2
3
spegling av https://github.com/sammy-ette/Hilbish synced 2025-08-10 02:52:03 +00:00

Jämför commits

...

17 Incheckningar

Upphovsman SHA1 Meddelande Datum
sammyette
df70082a81
feat: add doc command (closes #76)
the `doc` command is a way to see hilbish documentation from
in the shell. for usage, just run the command
2021-10-16 15:42:55 -04:00
sammyette
4dd6db54fe
fix: stop using setField wrapper 2021-10-16 15:40:16 -04:00
sammyette
afd999a7b0
docs: add docs for functions 2021-10-16 15:38:49 -04:00
sammyette
54635072f6
fix(docgen): use better perm mask for output files and folder 2021-10-16 15:38:17 -04:00
sammyette
bd3e9fdca6
docs: make linebreaks to descriptions for better alignment 2021-10-16 15:36:30 -04:00
sammyette
784e611272
chore: remove unused setField func 2021-10-16 15:33:57 -04:00
sammyette
77b3dac1b1
build: add docs folder to makefile 2021-10-16 15:33:22 -04:00
sammyette
3b97b22f10
feat: add hilbish.dataDir var 2021-10-16 13:51:09 -04:00
sammyette
20acfad2c2
fix(fs)!: handle mkdir error, change error return for cd
breaking change: cd now returns a message instead of a code to indicate the error.
any error in mkdir is now handled
2021-10-16 13:49:01 -04:00
sammyette
539a39f83a
feat: add fs.readdir function
it takes 1 argument: the directory to read.
2021-10-16 13:47:39 -04:00
sammyette
452335d84a
fix: change luaErr to return string instead of code 2021-10-16 13:47:09 -04:00
sammyette
3cafbe8c4f
docs: document hilbish module functions, xdg vars, and add descriptions for modules 2021-10-16 12:41:10 -04:00
sammyette
a2f54b627b
feat: output docs to a docs folder, allow multiline docs 2021-10-16 12:38:46 -04:00
sammyette
71b72bbdd4
chore: move comments below package declaration 2021-10-16 11:31:01 -04:00
sammyette
1689d80721
feat: add docgen program, document almost all hilbish functions 2021-10-16 10:21:05 -04:00
sammyette
ecbcf9a968
feat: add docgen program 2021-10-15 23:58:56 -04:00
sammyette
f9133584d4
chore: add dataDir var 2021-10-14 19:46:25 -04:00
19 ändrade filer med 313 tillägg och 47 borttagningar

1
.gitignore vendored
Visa fil

@ -1,5 +1,6 @@
*.exe
hilbish
docgen
.vim
petals/

Visa fil

@ -15,7 +15,7 @@ hilbiline:
install:
@install -v -d "$(DESTDIR)$(BINDIR)/" && install -m 0755 -v hilbish "$(DESTDIR)$(BINDIR)/hilbish"
@mkdir -p "$(DESTDIR)$(LIBDIR)"
@cp libs preload.lua .hilbishrc.lua "$(DESTDIR)$(LIBDIR)" -r
@cp libs docs preload.lua .hilbishrc.lua "$(DESTDIR)$(LIBDIR)" -r
@grep "$(DESTDIR)$(BINDIR)/hilbish" -qxF /etc/shells || echo "$(DESTDIR)$(BINDIR)/hilbish" >> /etc/shells
@echo "Hilbish Installed"

79
cmd/docgen/docgen.go Normal file
Visa fil

@ -0,0 +1,79 @@
package main
import (
"fmt"
"path/filepath"
"go/ast"
"go/doc"
"go/parser"
"go/token"
"strings"
"os"
)
// feel free to clean this up
// it works, dont really care about the code
func main() {
fset := token.NewFileSet()
dirs := []string{"./"}
filepath.Walk("golibs/", func (path string, info os.FileInfo, err error) error {
if !info.IsDir() {
return nil
}
dirs = append(dirs, "./" + path)
return nil
})
pkgs := make(map[string]*ast.Package)
for _, path := range dirs {
d, err := parser.ParseDir(fset, path, nil, parser.ParseComments)
if err != nil {
fmt.Println(err)
return
}
for k, v := range d {
pkgs[k] = v
}
}
prefix := map[string]string{
"main": "hsh",
"hilbish": "hl",
"fs": "f",
"commander": "c",
"bait": "b",
}
docs := make(map[string][]string)
for l, f := range pkgs {
p := doc.New(f, "./", doc.AllDecls)
for _, t := range p.Funcs {
mod := l
if strings.HasPrefix(t.Name, "hl") { mod = "hilbish" }
if !strings.HasPrefix(t.Name, prefix[mod]) || t.Name == "Loader" { continue }
parts := strings.Split(t.Doc, "\n")
funcsig := parts[0]
doc := parts[1:]
docs[mod] = append(docs[mod], funcsig + " > " + strings.Join(doc, "\n"))
}
for _, t := range p.Types {
for _, m := range t.Methods {
if !strings.HasPrefix(m.Name, prefix[l]) || m.Name == "Loader" { continue }
parts := strings.Split(m.Doc, "\n")
funcsig := parts[0]
doc := parts[1:]
docs[l] = append(docs[l], funcsig + " > " + strings.Join(doc, "\n"))
}
}
}
for mod, v := range docs {
if mod == "main" { mod = "global" }
os.Mkdir("docs", 0777)
f, _ := os.Create("docs/" + mod + ".txt")
f.WriteString(strings.Join(v, "\n") + "\n")
}
}

4
docs/bait.txt Normal file
Visa fil

@ -0,0 +1,4 @@
catch(name, cb) > Catches a hook with `name`. Runs the `cb` when it is thrown
throw(name, ...args) > Throws a hook with `name` with the provided `args`

4
docs/commander.txt Normal file
Visa fil

@ -0,0 +1,4 @@
deregister(name) > Deregisters any command registered with `name`
register(name, cb) > Register a command with `name` that runs `cb` when ran

8
docs/fs.txt Normal file
Visa fil

@ -0,0 +1,8 @@
cd(dir) > Changes directory to `dir`
mkdir(name, recursive) > Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
readdir(dir) > Returns a table of files in `dir`
stat(path) > Returns info about `path`

21
docs/global.txt Normal file
Visa fil

@ -0,0 +1,21 @@
alias(cmd, orig) > Sets an alias of `orig` to `cmd`
appendPath(dir) > Appends `dir` to $PATH
exec(cmd) > Replaces running hilbish with `cmd`
goro(fn) > Puts `fn` in a goroutine
interval(cb, time) > Runs the `cb` function every `time` milliseconds
multiprompt(str) > Changes the continued line prompt to `str`
prompt(str) > Changes the shell prompt to `str`
There are a few verbs that can be used in the prompt text.
These will be formatted and replaced with the appropriate values.
`%d` - Current working directory
`%u` - Name of current user
`%h` - Hostname of device
timeout(cb, time) > Runs the `cb` function after `time` in milliseconds

6
docs/hilbish.txt Normal file
Visa fil

@ -0,0 +1,6 @@
cwd() > Returns the current directory of the shell
flag(f) > Checks if the `f` flag has been passed to Hilbish.
run(cmd) > Runs `cmd` in Hilbish's sh interpreter

Visa fil

@ -1,6 +1,8 @@
package bait
import (
"hilbish/util"
"github.com/chuckpreslar/emission"
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
@ -18,18 +20,28 @@ func New() Bait {
func (b *Bait) Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), map[string]lua.LGFunction{})
L.SetField(mod, "throw", luar.New(L, b.throw))
L.SetField(mod, "catch", luar.New(L, b.catch))
L.SetField(mod, "throw", luar.New(L, b.bthrow))
L.SetField(mod, "catch", luar.New(L, b.bcatch))
util.Document(L, mod, `Bait is the event emitter for Hilbish. Why name it bait?
Because it throws hooks that you can catch
(emits events that you can listen to) and because why not,
fun naming is fun. This is what you will use if you want to
listen in on hooks to know when certain things have happened,
like when you've changed directory, a command has failed, etc.`)
L.Push(mod)
return 1
}
func (b *Bait) throw(name string, args ...interface{}) {
// throw(name, ...args)
// Throws a hook with `name` with the provided `args`
func (b *Bait) bthrow(name string, args ...interface{}) {
b.Em.Emit(name, args...)
}
func (b *Bait) catch(name string, catcher func(...interface{})) {
// catch(name, cb)
// Catches a hook with `name`. Runs the `cb` when it is thrown
func (b *Bait) bcatch(name string, catcher func(...interface{})) {
b.Em.On(name, catcher)
}

Visa fil

@ -1,6 +1,8 @@
package commander
import (
"hilbish/util"
"github.com/chuckpreslar/emission"
"github.com/yuin/gopher-lua"
)
@ -17,17 +19,19 @@ func New() Commander {
func (c *Commander) Loader(L *lua.LState) int {
var exports = map[string]lua.LGFunction{
"register": c.register,
"deregister": c.deregister,
"register": c.cregister,
"deregister": c.cderegister,
}
mod := L.SetFuncs(L.NewTable(), exports)
util.Document(L, mod, "Commander is Hilbish's custom command library, a way to write commands with the shell in Lua.")
L.Push(mod)
return 1
}
func (c *Commander) register(L *lua.LState) int {
// register(name, cb)
// Register a command with `name` that runs `cb` when ran
func (c *Commander) cregister(L *lua.LState) int {
cmdName := L.CheckString(1)
cmd := L.CheckFunction(2)
@ -36,7 +40,9 @@ func (c *Commander) register(L *lua.LState) int {
return 0
}
func (c *Commander) deregister(L *lua.LState) int {
// deregister(name)
// Deregisters any command registered with `name`
func (c *Commander) cderegister(L *lua.LState) int {
cmdName := L.CheckString(1)
c.Events.Emit("commandDeregister", cmdName)

Visa fil

@ -1,10 +1,12 @@
// The fs module provides easy and simple access to filesystem functions and other
// things, and acts an addition to the Lua standard library's I/O and fs functions.
package fs
import (
"fmt"
"os"
"strings"
"hilbish/util"
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
)
@ -12,62 +14,91 @@ import (
func Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), exports)
util.Document(L, mod, `The fs module provides easy and simple access to
filesystem functions and other things, and acts an
addition to the Lua standard library's I/O and fs functions.`)
L.Push(mod)
return 1
}
func LuaErr(L *lua.LState, code int) {
// TODO: Error with a table, with path and error code
L.Error(lua.LNumber(code), 2)
func luaErr(L *lua.LState, msg string) {
L.Error(lua.LString(msg), 2)
}
var exports = map[string]lua.LGFunction{
"cd": cd,
"mkdir": mkdir,
"stat": stat,
"cd": fcd,
"mkdir": fmkdir,
"stat": fstat,
"readdir": freaddir,
}
func cd(L *lua.LState) int {
// cd(dir)
// Changes directory to `dir`
func fcd(L *lua.LState) int {
path := L.CheckString(1)
err := os.Chdir(strings.TrimSpace(path))
if err != nil {
switch e := err.(*os.PathError).Err.Error(); e {
case "no such file or directory":
LuaErr(L, 1)
case "not a directory":
LuaErr(L, 2)
default:
fmt.Printf("Found unhandled error case: %s\n", e)
fmt.Printf("Report this at https://github.com/Rosettea/Hilbish/issues with the title being: \"fs: unhandled error case %s\", and show what caused it.\n", e)
LuaErr(L, 213)
}
e := err.(*os.PathError).Err.Error()
luaErr(L, e)
}
return 0
}
func mkdir(L *lua.LState) int {
// mkdir(name, recursive)
// Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
func fmkdir(L *lua.LState) int {
dirname := L.CheckString(1)
recursive := L.ToBool(2)
path := strings.TrimSpace(dirname)
var err error
// TODO: handle error here
if recursive {
os.MkdirAll(path, 0744)
err = os.MkdirAll(path, 0744)
} else {
os.Mkdir(path, 0744)
err = os.Mkdir(path, 0744)
}
if err != nil {
luaErr(L, err.Error())
}
return 0
}
func stat(L *lua.LState) int {
// stat(path)
// Returns info about `path`
func fstat(L *lua.LState) int {
path := L.CheckString(1)
// TODO: handle error here
pathinfo, _ := os.Stat(path)
pathinfo, err := os.Stat(path)
if err != nil {
luaErr(L, err.Error())
return 0
}
L.Push(luar.New(L, pathinfo))
return 1
}
// readdir(dir)
// Returns a table of files in `dir`
func freaddir(L *lua.LState) int {
dir := L.CheckString(1)
names := []string{}
dirEntries, err := os.ReadDir(dir)
if err != nil {
luaErr(L, err.Error())
return 0
}
for _, entry := range dirEntries {
names = append(names, entry.Name())
}
L.Push(luar.New(L, names))
return 1
}

Visa fil

@ -8,15 +8,17 @@ import (
"runtime"
"strings"
"hilbish/util"
"github.com/pborman/getopt"
"github.com/yuin/gopher-lua"
"mvdan.cc/sh/v3/interp"
)
var exports = map[string]lua.LGFunction {
"run": run,
"flag": flag,
"cwd": cwd,
"run": hlrun,
"flag": hlflag,
"cwd": hlcwd,
}
func HilbishLoader(L *lua.LState) int {
@ -39,13 +41,15 @@ func HilbishLoader(L *lua.LState) int {
L.SetField(xdg, "data", lua.LString(getenv("XDG_DATA_HOME", homedir + "/.local/share/")))
L.SetField(mod, "xdg", xdg)
util.Document(L, mod, "A miscellaneous sort of \"core\" API for things that relate to the shell itself and others.")
L.Push(mod)
return 1
}
// Runs a command
func run(L *lua.LState) int {
// run(cmd)
// Runs `cmd` in Hilbish's sh interpreter
func hlrun(L *lua.LState) int {
var exitcode uint8 = 0
cmd := L.CheckString(1)
err := execCommand(cmd)
@ -60,7 +64,9 @@ func run(L *lua.LState) int {
return 1
}
func flag(L *lua.LState) int {
// flag(f)
// Checks if the `f` flag has been passed to Hilbish.
func hlflag(L *lua.LState) int {
flagchar := L.CheckString(1)
L.Push(lua.LBool(getopt.Lookup([]rune(flagchar)[0]).Seen()))
@ -68,7 +74,9 @@ func flag(L *lua.LState) int {
return 1
}
func cwd(L *lua.LState) int {
// cwd()
// Returns the current directory of the shell
func hlcwd(L *lua.LState) int {
cwd, _ := os.Getwd()
L.Push(lua.LString(cwd))

21
lua.go
Visa fil

@ -95,18 +95,29 @@ func RunLogin() {
}
}
/* prompt(str)
Changes the shell prompt to `str`
There are a few verbs that can be used in the prompt text.
These will be formatted and replaced with the appropriate values.
`%d` - Current working directory
`%u` - Name of current user
`%h` - Hostname of device */
func hshprompt(L *lua.LState) int {
prompt = L.CheckString(1)
return 0
}
// multiprompt(str)
// Changes the continued line prompt to `str`
func hshmlprompt(L *lua.LState) int {
multilinePrompt = L.CheckString(1)
return 0
}
// alias(cmd, orig)
// Sets an alias of `orig` to `cmd`
func hshalias(L *lua.LState) int {
alias := L.CheckString(1)
source := L.CheckString(2)
@ -116,6 +127,8 @@ func hshalias(L *lua.LState) int {
return 1
}
// appendPath(dir)
// Appends `dir` to $PATH
func hshappendPath(L *lua.LState) int {
dir := L.CheckString(1)
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
@ -129,6 +142,8 @@ func hshappendPath(L *lua.LState) int {
return 0
}
// exec(cmd)
// Replaces running hilbish with `cmd`
func hshexec(L *lua.LState) int {
cmd := L.CheckString(1)
cmdArgs, _ := splitInput(cmd)
@ -146,16 +161,22 @@ func hshexec(L *lua.LState) int {
return 0 // random thought: does this ever return?
}
// goro(fn)
// Puts `fn` in a goroutine
func hshgoroutine(gofunc func()) {
go gofunc()
}
// timeout(cb, time)
// Runs the `cb` function after `time` in milliseconds
func hshtimeout(timeoutfunc func(), ms int) {
timeout := time.Duration(ms) * time.Millisecond
time.Sleep(timeout)
timeoutfunc()
}
// interval(cb, time)
// Runs the `cb` function every `time` milliseconds
func hshinterval(L *lua.LState) int {
intervalfunc := L.CheckFunction(1)
ms := L.CheckInt(2)

Visa fil

@ -44,6 +44,57 @@ commander.register('exit', function()
os.exit(0)
end)
commander.register('doc', function(args)
local moddocPath = hilbish.dataDir .. '/docs/'
local globalDesc = [[
These are the global Hilbish functions that are always available and not part of a module.]]
if #args > 0 then
local mod = ''
for i = 1, #args do
mod = mod .. tostring(args[i]) .. ' '
end
mod = mod:gsub('^%s*(.-)%s*$', '%1')
local f = io.open(moddocPath .. mod .. '.txt', 'rb')
if not f then
print('Could not find docs for module named ' .. mod .. '.')
return 1
end
local desc = (mod == 'global' and globalDesc or getmetatable(require(mod)).__doc)
local funcdocs = f:read '*a'
local backtickOccurence = 0
print(desc .. '\n\n' .. lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function()
backtickOccurence = backtickOccurence + 1
if backtickOccurence % 2 == 0 then
return '{reset}'
else
return '{invert}'
end
end)))
f:close()
return
end
local modules = fs.readdir(moddocPath)
io.write [[
Welcome to Hilbish's doc tool! Here you can find documentation for builtin
functions and other things.
Usage: doc <module>
Available modules: ]]
local mods = ''
for i = 1, #modules do
mods = mods .. tostring(modules[i]):gsub('.txt', '') .. ', '
end
print(mods)
return
end)
do
local virt_G = { }

3
rl.go
Visa fil

@ -1,9 +1,10 @@
// +build !hilbiline
package main
// Here we define a generic interface for readline and hilbiline,
// making them interchangable during build time
// this is normal readline
package main
import "github.com/bobappleyard/readline"

Visa fil

@ -1,9 +1,10 @@
// +build hilbiline
package main
// Here we define a generic interface for readline and hilbiline,
// making them interchangable during build time
// this is hilbiline's, as is obvious by the filename
package main
import "github.com/Rosettea/Hilbiline"

10
util/util.go Normal file
Visa fil

@ -0,0 +1,10 @@
package util
import "github.com/yuin/gopher-lua"
func Document(L *lua.LState, module lua.LValue, doc string) {
mt := L.NewTable()
L.SetField(mt, "__doc", lua.LString(doc))
L.SetMetatable(module, mt)
}

Visa fil

@ -13,6 +13,7 @@ var (
.. hilbish.xdg.config .. '/hilbish/?/init.lua'
.. hilbish.xdg.config .. '/hilbish/?/?.lua'
.. hilbish.xdg.config .. '/hilbish/?.lua'`
preloadPath = "/usr/share/hilbish/preload.lua"
sampleConfPath = "/usr/share/hilbish/.hilbishrc.lua" // Path to default/sample config
dataDir = "/usr/share/hilbish"
preloadPath = dataDir + "/preload.lua"
sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config
)

Visa fil

@ -7,6 +7,7 @@ var (
requirePaths = `';./libs/?/init.lua;./?/init.lua;./?/?.lua'
.. hilbish.home .. '\\Appdata\\Roaming\\Hilbish\\libs\\?\\init.lua;'
.. hilbish.home .. '\\Appdata\\Roaming\\Hilbish\\libs\\?\\?.lua;'`
preloadPath = "~\\Appdata\\Roaming\\Hilbish\\preload.lua" // ~ and \ gonna cry?
sampleConfPath = "~\\Appdata\\Roaming\\Hilbish\\hilbishrc.lua" // Path to default/sample config
dataDir = "~\\Appdata\\Roaming\\Hilbish" // ~ and \ gonna cry?
preloadPath = dataDir + "\\preload.lua"
sampleConfPath = dataDir + "\\hilbishrc.lua" // Path to default/sample config
)