diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e378376d..6515d25b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,13 +2,14 @@ name: Generate docs on: push: - branches: [master] + branches: + - master jobs: gen: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/setup-go@v2 - name: Run docgen run: go run cmd/docgen/docgen.go diff --git a/.gitignore b/.gitignore index 338ef97f..b2be7c46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ *.exe hilbish +!docs/api/hilbish docgen +!cmd/docgen .vim petals/ diff --git a/aliases.go b/aliases.go index 3007cc3d..741a6a30 100644 --- a/aliases.go +++ b/aliases.go @@ -9,40 +9,40 @@ import ( rt "github.com/arnodel/golua/runtime" ) -var aliases *aliasHandler +var aliases *aliasModule -type aliasHandler struct { +type aliasModule struct { aliases map[string]string mu *sync.RWMutex } // initialize aliases map -func newAliases() *aliasHandler { - return &aliasHandler{ +func newAliases() *aliasModule { + return &aliasModule{ aliases: make(map[string]string), mu: &sync.RWMutex{}, } } -func (a *aliasHandler) Add(alias, cmd string) { +func (a *aliasModule) Add(alias, cmd string) { a.mu.Lock() defer a.mu.Unlock() a.aliases[alias] = cmd } -func (a *aliasHandler) All() map[string]string { +func (a *aliasModule) All() map[string]string { return a.aliases } -func (a *aliasHandler) Delete(alias string) { +func (a *aliasModule) Delete(alias string) { a.mu.Lock() defer a.mu.Unlock() delete(a.aliases, alias) } -func (a *aliasHandler) Resolve(cmdstr string) string { +func (a *aliasModule) Resolve(cmdstr string) string { a.mu.RLock() defer a.mu.RUnlock() @@ -66,7 +66,10 @@ func (a *aliasHandler) Resolve(cmdstr string) string { // lua section -func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table { +// #interface aliases +// command aliasing +// The alias interface deals with all command aliases in Hilbish. +func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table { // create a lua module with our functions hshaliasesLua := map[string]util.LuaExport{ "add": util.LuaExport{hlalias, 2, false}, @@ -81,7 +84,17 @@ func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table { return mod } -func (a *aliasHandler) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { +// #interface aliases +// add(alias, cmd) +// This is an alias (ha) for the `hilbish.alias` function. +// --- @param alias string +// --- @param cmd string +func _hlalias() {} + +// #interface aliases +// list() +// Get a table of all aliases. +func (a *aliasModule) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { aliasesList := rt.NewTable() for k, v := range a.All() { aliasesList.Set(rt.StringValue(k), rt.StringValue(v)) @@ -90,7 +103,11 @@ func (a *aliasHandler) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.TableValue(aliasesList)), nil } -func (a *aliasHandler) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { +// #interface aliases +// delete(name) +// Removes an alias. +// --- @param name string +func (a *aliasModule) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err } @@ -103,7 +120,11 @@ func (a *aliasHandler) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } -func (a *aliasHandler) luaResolve(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { +// #interface aliases +// resolve(alias) +// Tries to resolve an alias to its command. +// --- @param alias string +func (a *aliasModule) luaResolve(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err } diff --git a/api.go b/api.go index 3e5f8927..09df7c0e 100644 --- a/api.go +++ b/api.go @@ -1,6 +1,14 @@ -// Here is the core api for the hilbi shell itself -// Basically, stuff about the shell itself and other functions -// go here. +// the core Hilbish API +// The Hilbish module includes the core API, containing +// interfaces and functions which directly relate to shell functionality. +// #field ver The version of Hilbish +// #field user Username of the user +// #field host Hostname of the machine +// #field dataDir Directory for Hilbish data files, including the docs and default modules +// #field interactive Is Hilbish in an interactive shell? +// #field login Is Hilbish the login shell? +// #field vimMode Current Vim input mode of Hilbish (will be nil if not in Vim input mode) +// #field exitCode xit code of the last executed command package main import ( @@ -19,7 +27,6 @@ import ( rt "github.com/arnodel/golua/runtime" "github.com/arnodel/golua/lib/packagelib" "github.com/maxlandon/readline" - "github.com/blackfireio/osinfo" "mvdan.cc/sh/v3/interp" ) @@ -114,20 +121,12 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) { util.Document(fakeMod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.") // hilbish.userDir table - hshuser := rt.NewTable() - - util.SetField(rtm, hshuser, "config", rt.StringValue(confDir), "User's config directory") - util.SetField(rtm, hshuser, "data", rt.StringValue(userDataDir), "XDG data directory") + hshuser := userDirLoader(rtm) util.Document(hshuser, "User directories to store configs and/or modules.") mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser)) // hilbish.os table - hshos := rt.NewTable() - info, _ := osinfo.GetOSInfo() - - util.SetField(rtm, hshos, "family", rt.StringValue(info.Family), "Family name of the current OS") - util.SetField(rtm, hshos, "name", rt.StringValue(info.Name), "Pretty name of the current OS") - util.SetField(rtm, hshos, "version", rt.StringValue(info.Version), "Version of the current OS") + hshos := hshosLoader(rtm) util.Document(hshos, "OS info interface") mod.Set(rt.StringValue("os"), rt.TableValue(hshos)) @@ -159,10 +158,10 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) { mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule)) // hilbish.timers table - timers = newTimerHandler() - timerModule := timers.loader(rtm) - util.Document(timerModule, "Timer interface, for control of all intervals and timeouts.") - mod.Set(rt.StringValue("timers"), rt.TableValue(timerModule)) + timers = newTimersModule() + timersModule := timers.loader(rtm) + util.Document(timersModule, "Timer interface, for control of all intervals and timeouts.") + mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule)) editorModule := editorLoader(rtm) util.Document(editorModule, "") @@ -250,11 +249,12 @@ func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { } -// read(prompt?) -> input? +// read(prompt) -> input // Read input from the user, using Hilbish's line editor/input reader. // This is a separate instance from the one Hilbish actually uses. // Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen) -// --- @param prompt string +// --- @param prompt string|nil +// --- @returns string|nil func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { luaprompt := c.Arg(0) if typ := luaprompt.Type(); typ != rt.StringType && typ != rt.NilType { @@ -281,7 +281,7 @@ func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { } /* -prompt(str, typ?) +prompt(str, typ) 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. @@ -289,7 +289,7 @@ These will be formatted and replaced with the appropriate values. `%u` - Name of current user `%h` - Hostname of device --- @param str string ---- @param typ string Type of prompt, being left or right. Left by default. +--- @param typ string|nil Type of prompt, being left or right. Left by default. */ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { err := c.Check1Arg() diff --git a/cmd/docgen/docgen.go b/cmd/docgen/docgen.go index 39a2a760..cf708404 100644 --- a/cmd/docgen/docgen.go +++ b/cmd/docgen/docgen.go @@ -9,26 +9,191 @@ import ( "go/token" "strings" "os" + "sync" ) -type EmmyPiece struct { - FuncName string - Docs []string +var header = `--- +title: %s %s +description: %s +layout: doc +menu: + docs: + parent: "API" +--- + +` + +type emmyPiece struct { + DocPiece *docPiece + Annotations []string Params []string // we only need to know param name to put in function + FuncName string } -type DocPiece struct { + +type module struct { + Docs []docPiece + Fields []docPiece + Properties []docPiece + ShortDescription string + Description string + ParentModule string + HasInterfaces bool +} + +type docPiece struct { Doc []string FuncSig string FuncName string + Interfacing string + ParentModule string + GoFuncName string + IsInterface bool + IsMember bool + Fields []docPiece + Properties []docPiece +} + +type tag struct { + id string + fields []string +} + +var docs = make(map[string]module) +var interfaceDocs = make(map[string]module) +var emmyDocs = make(map[string][]emmyPiece) +var prefix = map[string]string{ + "main": "hl", + "hilbish": "hl", + "fs": "f", + "commander": "c", + "bait": "b", + "terminal": "term", +} + +func getTagsAndDocs(docs string) (map[string][]tag, []string) { + pts := strings.Split(docs, "\n") + parts := []string{} + tags := make(map[string][]tag) + + for _, part := range pts { + if strings.HasPrefix(part, "#") { + tagParts := strings.Split(strings.TrimPrefix(part, "#"), " ") + if tags[tagParts[0]] == nil { + var id string + if len(tagParts) > 1 { + id = tagParts[1] + } + tags[tagParts[0]] = []tag{ + {id: id}, + } + if len(tagParts) >= 2 { + tags[tagParts[0]][0].fields = tagParts[2:] + } + } else { + fleds := []string{} + if len(tagParts) >= 2 { + fleds = tagParts[2:] + } + tags[tagParts[0]] = append(tags[tagParts[0]], tag{ + id: tagParts[1], + fields: fleds, + }) + } + } else { + parts = append(parts, part) + } + } + + return tags, parts +} + +func docPieceTag(tagName string, tags map[string][]tag) []docPiece { + dps := []docPiece{} + for _, tag := range tags[tagName] { + dps = append(dps, docPiece{ + FuncName: tag.id, + Doc: tag.fields, + }) + } + + return dps +} + +func setupDoc(mod string, fun *doc.Func) *docPiece { + docs := strings.TrimSpace(fun.Doc) + inInterface := strings.HasPrefix(docs, "#interface") + if (!strings.HasPrefix(fun.Name, prefix[mod]) && !inInterface) || (strings.ToLower(fun.Name) == "loader" && !inInterface) { + return nil + } + + tags, parts := getTagsAndDocs(docs) + + var interfaces string + funcsig := parts[0] + doc := parts[1:] + funcName := strings.TrimPrefix(fun.Name, prefix[mod]) + funcdoc := []string{} + + if inInterface { + interfaces = tags["interface"][0].id + funcName = interfaces + "." + strings.Split(funcsig, "(")[0] + } + em := emmyPiece{FuncName: funcName} + + fields := docPieceTag("field", tags) + properties := docPieceTag("property", tags) + + for _, d := range doc { + if strings.HasPrefix(d, "---") { + emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---")) + emmyLinePieces := strings.Split(emmyLine, " ") + emmyType := emmyLinePieces[0] + if emmyType == "@param" { + em.Params = append(em.Params, emmyLinePieces[1]) + } + if emmyType == "@vararg" { + em.Params = append(em.Params, "...") // add vararg + } + em.Annotations = append(em.Annotations, d) + } else { + funcdoc = append(funcdoc, d) + } + } + + var isMember bool + if tags["member"] != nil { + isMember = true + } + var parentMod string + if inInterface { + parentMod = mod + } + dps := &docPiece{ + Doc: funcdoc, + FuncSig: funcsig, + FuncName: funcName, + Interfacing: interfaces, + GoFuncName: strings.ToLower(fun.Name), + IsInterface: inInterface, + IsMember: isMember, + ParentModule: parentMod, + Fields: fields, + Properties: properties, + } + if strings.HasSuffix(dps.GoFuncName, strings.ToLower("loader")) { + dps.Doc = parts + } + em.DocPiece = dps + + emmyDocs[mod] = append(emmyDocs[mod], em) + return dps } -// feel free to clean this up -// it works, dont really care about the code func main() { fset := token.NewFileSet() os.Mkdir("docs", 0777) + os.Mkdir("docs/api", 0777) os.Mkdir("emmyLuaDocs", 0777) - dirs := []string{"./"} filepath.Walk("golibs/", func (path string, info os.FileInfo, err error) error { @@ -51,120 +216,172 @@ func main() { } } - prefix := map[string]string{ - "hilbish": "hl", - "fs": "f", - "commander": "c", - "bait": "b", - "terminal": "term", - } - docs := make(map[string][]DocPiece) - emmyDocs := make(map[string][]EmmyPiece) - + interfaceModules := make(map[string]*module) for l, f := range pkgs { p := doc.New(f, "./", doc.AllDecls) + pieces := []docPiece{} + mod := l + if mod == "main" { + mod = "hilbish" + } + var hasInterfaces bool 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(strings.TrimSpace(t.Doc), "\n") - funcsig := parts[0] - doc := parts[1:] - funcdoc := []string{} - em := EmmyPiece{FuncName: strings.TrimPrefix(t.Name, prefix[mod])} - for _, d := range doc { - if strings.HasPrefix(d, "---") { - emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---")) - emmyLinePieces := strings.Split(emmyLine, " ") - emmyType := emmyLinePieces[0] - if emmyType == "@param" { - em.Params = append(em.Params, emmyLinePieces[1]) - } - if emmyType == "@vararg" { - em.Params = append(em.Params, "...") // add vararg - } - em.Docs = append(em.Docs, d) - } else { - funcdoc = append(funcdoc, d) - } + piece := setupDoc(mod, t) + if piece == nil { + continue } - - dps := DocPiece{ - Doc: funcdoc, - FuncSig: funcsig, - FuncName: strings.TrimPrefix(t.Name, prefix[mod]), + + pieces = append(pieces, *piece) + if piece.IsInterface { + hasInterfaces = true } - - docs[mod] = append(docs[mod], dps) - emmyDocs[mod] = append(emmyDocs[mod], em) } for _, t := range p.Types { for _, m := range t.Methods { - if !strings.HasPrefix(m.Name, prefix[l]) || m.Name == "Loader" { continue } - parts := strings.Split(strings.TrimSpace(m.Doc), "\n") - funcsig := parts[0] - doc := parts[1:] - funcdoc := []string{} - em := EmmyPiece{FuncName: strings.TrimPrefix(m.Name, prefix[l])} - for _, d := range doc { - if strings.HasPrefix(d, "---") { - emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---")) - emmyLinePieces := strings.Split(emmyLine, " ") - emmyType := emmyLinePieces[0] - if emmyType == "@param" { - em.Params = append(em.Params, emmyLinePieces[1]) - } - if emmyType == "@vararg" { - em.Params = append(em.Params, "...") // add vararg - } - em.Docs = append(em.Docs, d) - } else { - funcdoc = append(funcdoc, d) - } - } - dps := DocPiece{ - Doc: funcdoc, - FuncSig: funcsig, - FuncName: strings.TrimPrefix(m.Name, prefix[l]), + piece := setupDoc(mod, m) + if piece == nil { + continue } - docs[l] = append(docs[l], dps) - emmyDocs[l] = append(emmyDocs[l], em) + pieces = append(pieces, *piece) + if piece.IsInterface { + hasInterfaces = true + } } } + + tags, descParts := getTagsAndDocs(strings.TrimSpace(p.Doc)) + shortDesc := descParts[0] + desc := descParts[1:] + filteredPieces := []docPiece{} + for _, piece := range pieces { + if !piece.IsInterface { + filteredPieces = append(filteredPieces, piece) + continue + } + + modname := piece.ParentModule + "." + piece.Interfacing + if interfaceModules[modname] == nil { + interfaceModules[modname] = &module{ + ParentModule: piece.ParentModule, + } + } + + if strings.HasSuffix(piece.GoFuncName, strings.ToLower("loader")) { + shortDesc := piece.Doc[0] + desc := piece.Doc[1:] + interfaceModules[modname].ShortDescription = shortDesc + interfaceModules[modname].Description = strings.Join(desc, "\n") + interfaceModules[modname].Fields = piece.Fields + interfaceModules[modname].Properties = piece.Properties + continue + } + interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece) + } + + docs[mod] = module{ + Docs: filteredPieces, + ShortDescription: shortDesc, + Description: strings.Join(desc, "\n"), + HasInterfaces: hasInterfaces, + Properties: docPieceTag("property", tags), + Fields: docPieceTag("field", tags), + } } + for key, mod := range interfaceModules { + docs[key] = *mod + } + + var wg sync.WaitGroup + wg.Add(len(docs) * 2) + for mod, v := range docs { - if mod == "main" { continue } - f, _ := os.Create("docs/" + mod + ".txt") - for _, dps := range v { - f.WriteString(dps.FuncSig + " > ") - for _, doc := range dps.Doc { - if !strings.HasPrefix(doc, "---") { - f.WriteString(doc + "\n") - } - } - f.WriteString("\n") + docPath := "docs/api/" + mod + ".md" + if v.HasInterfaces { + os.Mkdir("docs/api/" + mod, 0777) + os.Remove(docPath) // remove old doc path if it exists + docPath = "docs/api/" + mod + "/_index.md" } - } - - for mod, v := range emmyDocs { - if mod == "main" { continue } - f, _ := os.Create("emmyLuaDocs/" + mod + ".lua") - f.WriteString("--- @meta\n\nlocal " + mod + " = {}\n\n") - for _, em := range v { - var funcdocs []string - for _, dps := range docs[mod] { - if dps.FuncName == em.FuncName { - funcdocs = dps.Doc - } - } - f.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n") - if len(em.Docs) != 0 { - f.WriteString(strings.Join(em.Docs, "\n") + "\n") - } - f.WriteString("function " + mod + "." + em.FuncName + "(" + strings.Join(em.Params, ", ") + ") end\n\n") + if v.ParentModule != "" { + docPath = "docs/api/" + v.ParentModule + "/" + mod + ".md" } - f.WriteString("return " + mod + "\n") + + go func(modname, docPath string, modu module) { + defer wg.Done() + modOrIface := "Module" + if modu.ParentModule != "" { + modOrIface = "Interface" + } + + f, _ := os.Create(docPath) + f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription)) + f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n", modu.Description)) + if len(modu.Fields) != 0 { + f.WriteString("## Interface fields\n") + for _, dps := range modu.Fields { + f.WriteString(fmt.Sprintf("- `%s`: ", dps.FuncName)) + f.WriteString(strings.Join(dps.Doc, " ")) + f.WriteString("\n") + } + f.WriteString("\n") + } + if len(modu.Properties) != 0 { + f.WriteString("## Object properties\n") + for _, dps := range modu.Properties { + f.WriteString(fmt.Sprintf("- `%s`: ", dps.FuncName)) + f.WriteString(strings.Join(dps.Doc, " ")) + f.WriteString("\n") + } + f.WriteString("\n") + } + if len(modu.Docs) != 0 { + f.WriteString("## Functions\n") + } + for _, dps := range modu.Docs { + f.WriteString(fmt.Sprintf("### %s\n", dps.FuncSig)) + for _, doc := range dps.Doc { + if !strings.HasPrefix(doc, "---") { + f.WriteString(doc + "\n") + } + } + f.WriteString("\n") + } + }(mod, docPath, v) + + go func(md, modname string, modu module) { + defer wg.Done() + + if modu.ParentModule != "" { + return + } + + ff, _ := os.Create("emmyLuaDocs/" + modname + ".lua") + ff.WriteString("--- @meta\n\nlocal " + modname + " = {}\n\n") + for _, em := range emmyDocs[modname] { + if strings.HasSuffix(em.DocPiece.GoFuncName, strings.ToLower("loader")) { + continue + } + + dps := em.DocPiece + funcdocs := dps.Doc + ff.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n") + if len(em.Annotations) != 0 { + ff.WriteString(strings.Join(em.Annotations, "\n") + "\n") + } + accessor := "." + if dps.IsMember { + accessor = ":" + } + signature := strings.Split(dps.FuncSig, " ->")[0] + var intrface string + if dps.IsInterface { + intrface = "." + dps.Interfacing + } + ff.WriteString("function " + modname + intrface + accessor + signature + " end\n\n") + } + ff.WriteString("return " + modname + "\n") + }(mod, mod, v) } + wg.Wait() } diff --git a/complete.go b/complete.go index c2a107c7..7c3f563f 100644 --- a/complete.go +++ b/complete.go @@ -172,6 +172,9 @@ func escapeFilename(fname string) string { return escapeReplaer.Replace(fname) } +// #interface completions +// tab completions +// The completions interface deals with tab completions. func completionLoader(rtm *rt.Runtime) *rt.Table { exports := map[string]util.LuaExport{ "files": {luaFileComplete, 3, false}, @@ -186,11 +189,19 @@ func completionLoader(rtm *rt.Runtime) *rt.Table { return mod } -// left as a shim, might doc in the same way as hilbish functions +// #interface completions +// handler(line, pos) +// The handler function is the callback for tab completion in Hilbish. +// You can check the completions doc for more info. func completionHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface completions +// call(name, query, ctx, fields) +// Calls a completer function. This is mainly used to call +// a command completer, which will have a `name` in the form +// of `command.name`, example: `command.git` func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.CheckNArgs(4); err != nil { return nil, err @@ -230,6 +241,9 @@ func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, completerReturn), nil } +// #interface completions +// files(query, ctx, fields) +// Returns file completion candidates based on the provided query. func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { query, ctx, fds, err := getCompleteParams(t, c) if err != nil { @@ -246,6 +260,9 @@ func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil } +// #interface completions +// bins(query, ctx, fields) +// Returns binary/executale completion candidates based on the provided query. func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { query, ctx, fds, err := getCompleteParams(t, c) if err != nil { diff --git a/docs/api/_index.md b/docs/api/_index.md new file mode 100644 index 00000000..5c8b7221 --- /dev/null +++ b/docs/api/_index.md @@ -0,0 +1,7 @@ +--- +title: API +layout: doc +weight: -50 +menu: docs +--- + diff --git a/docs/api/bait.md b/docs/api/bait.md new file mode 100644 index 00000000..fdf22b03 --- /dev/null +++ b/docs/api/bait.md @@ -0,0 +1,34 @@ +--- +title: Module bait +description: the event emitter +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +Bait is the event emitter for Hilbish. Why name it bait? Why not. +It throws hooks that you can catch. 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. To find all available hooks thrown by Hilbish, see doc hooks. + +## Functions +### catch(name, cb) +Catches a hook with `name`. Runs the `cb` when it is thrown + +### catchOnce(name, cb) +Same as catch, but only runs the `cb` once and then removes the hook + +### hooks(name) -> {cb, cb...} +Returns a table with hooks on the event with `name`. + +### release(name, catcher) +Removes the `catcher` for the event with `name` +For this to work, `catcher` has to be the same function used to catch +an event, like one saved to a variable. + +### throw(name, ...args) +Throws a hook with `name` with the provided `args` + diff --git a/docs/api/commander.md b/docs/api/commander.md new file mode 100644 index 00000000..e3e5320c --- /dev/null +++ b/docs/api/commander.md @@ -0,0 +1,19 @@ +--- +title: Module commander +description: library for custom commands +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +Commander is a library for writing custom commands in Lua. + +## Functions +### deregister(name) +Deregisters any command registered with `name` + +### register(name, cb) +Register a command with `name` that runs `cb` when ran + diff --git a/docs/api/fs.md b/docs/api/fs.md new file mode 100644 index 00000000..6ad11de8 --- /dev/null +++ b/docs/api/fs.md @@ -0,0 +1,46 @@ +--- +title: Module fs +description: filesystem interaction and functionality library +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +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 filesystem functions. + +## Functions +### abs(path) +Gives an absolute version of `path`. + +### basename(path) +Gives the basename of `path`. For the rules, +see Go's filepath.Base + +### cd(dir) +Changes directory to `dir` + +### dir(path) +Returns the directory part of `path`. For the rules, see Go's +filepath.Dir + +### glob(pattern) +Glob all files and directories that match the pattern. +For the rules, see Go's filepath.Glob + +### join(paths...) +Takes paths and joins them together with the OS's +directory separator (forward or backward slash). + +### 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` + diff --git a/docs/api/hilbish/_index.md b/docs/api/hilbish/_index.md new file mode 100644 index 00000000..5cdcb4df --- /dev/null +++ b/docs/api/hilbish/_index.md @@ -0,0 +1,104 @@ +--- +title: Module hilbish +description: the core Hilbish API +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The Hilbish module includes the core API, containing +interfaces and functions which directly relate to shell functionality. + +## Interface fields +- `ver`: The version of Hilbish +- `user`: Username of the user +- `host`: Hostname of the machine +- `dataDir`: Directory for Hilbish data files, including the docs and default modules +- `interactive`: Is Hilbish in an interactive shell? +- `login`: Is Hilbish the login shell? +- `vimMode`: Current Vim input mode of Hilbish (will be nil if not in Vim input mode) +- `exitCode`: xit code of the last executed command + +## Functions +### alias(cmd, orig) +Sets an alias of `cmd` to `orig` + +### appendPath(dir) +Appends `dir` to $PATH + +### complete(scope, cb) +Registers a completion handler for `scope`. +A `scope` is currently only expected to be `command.`, +replacing with the name of the command (for example `command.git`). +`cb` must be a function that returns a table of "completion groups." +Check `doc completions` for more information. + +### cwd() +Returns the current directory of the shell + +### exec(cmd) +Replaces running hilbish with `cmd` + +### goro(fn) +Puts `fn` in a goroutine + +### highlighter(line) +Line highlighter handler. This is mainly for syntax highlighting, but in +reality could set the input of the prompt to *display* anything. The +callback is passed the current line and is expected to return a line that +will be used as the input display. + +### hinter(line, pos) +The command line hint handler. It gets called on every key insert to +determine what text to use as an inline hint. It is passed the current +line and cursor position. It is expected to return a string which is used +as the text for the hint. This is by default a shim. To set hints, +override this function with your custom handler. + +### inputMode(mode) +Sets the input mode for Hilbish's line reader. Accepts either emacs or vim + +### interval(cb, time) +Runs the `cb` function every `time` milliseconds. +Returns a `timer` object (see `doc timers`). + +### multiprompt(str) +Changes the continued line prompt to `str` + +### prependPath(dir) +Prepends `dir` to $PATH + +### prompt(str, typ) +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 + +### read(prompt) -> input +Read input from the user, using Hilbish's line editor/input reader. +This is a separate instance from the one Hilbish actually uses. +Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen) + +### run(cmd, returnOut) -> exitCode, stdout, stderr +Runs `cmd` in Hilbish's sh interpreter. +If returnOut is true, the outputs of `cmd` will be returned as the 2nd and +3rd values instead of being outputted to the terminal. + +### runnerMode(mode) +Sets the execution/runner mode for interactive Hilbish. This determines whether +Hilbish wll try to run input as Lua and/or sh or only do one of either. +Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua), +sh, and lua. It also accepts a function, to which if it is passed one +will call it to execute user input instead. + +### timeout(cb, time) +Runs the `cb` function after `time` in milliseconds +Returns a `timer` object (see `doc timers`). + +### which(name) +Checks if `name` is a valid command + diff --git a/docs/api/hilbish/hilbish.aliases.md b/docs/api/hilbish/hilbish.aliases.md new file mode 100644 index 00000000..1ff766c8 --- /dev/null +++ b/docs/api/hilbish/hilbish.aliases.md @@ -0,0 +1,25 @@ +--- +title: Interface hilbish.aliases +description: command aliasing +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The alias interface deals with all command aliases in Hilbish. + +## Functions +### add(alias, cmd) +This is an alias (ha) for the `hilbish.alias` function. + +### delete(name) +Removes an alias. + +### list() +Get a table of all aliases. + +### resolve(alias) +Tries to resolve an alias to its command. + diff --git a/docs/api/hilbish/hilbish.completions.md b/docs/api/hilbish/hilbish.completions.md new file mode 100644 index 00000000..bcfd2f90 --- /dev/null +++ b/docs/api/hilbish/hilbish.completions.md @@ -0,0 +1,28 @@ +--- +title: Interface hilbish.completions +description: tab completions +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The completions interface deals with tab completions. + +## Functions +### call(name, query, ctx, fields) +Calls a completer function. This is mainly used to call +a command completer, which will have a `name` in the form +of `command.name`, example: `command.git` + +### handler(line, pos) +The handler function is the callback for tab completion in Hilbish. +You can check the completions doc for more info. + +### bins(query, ctx, fields) +Returns binary/executale completion candidates based on the provided query. + +### files(query, ctx, fields) +Returns file completion candidates based on the provided query. + diff --git a/docs/api/hilbish/hilbish.editor.md b/docs/api/hilbish/hilbish.editor.md new file mode 100644 index 00000000..bb0f257d --- /dev/null +++ b/docs/api/hilbish/hilbish.editor.md @@ -0,0 +1,26 @@ +--- +title: Interface hilbish.editor +description: interactions for Hilbish's line reader +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The hilbish.editor interface provides functions to +directly interact with the line editor in use. + +## Functions +### getLine() +Returns the current input line. + +### getVimRegister(register) +Returns the text that is at the register. + +### insert(text) +Inserts text into the line. + +### setVimRegister(register, text) +Sets the vim register at `register` to hold the passed text. + diff --git a/docs/api/hilbish/hilbish.history.md b/docs/api/hilbish/hilbish.history.md new file mode 100644 index 00000000..f297ab20 --- /dev/null +++ b/docs/api/hilbish/hilbish.history.md @@ -0,0 +1,27 @@ +--- +title: Interface hilbish.history +description: command history +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The history interface deals with command history. +This includes the ability to override functions to change the main +method of saving history. + +## Functions +### add(cmd) +Adds a command to the history. + +### clear() +Deletes all commands from the history. + +### get(idx) +Retrieves a command from the history based on the `idx`. + +### size() +Returns the amount of commands in the history. + diff --git a/docs/api/hilbish/hilbish.jobs.md b/docs/api/hilbish/hilbish.jobs.md new file mode 100644 index 00000000..b180dd48 --- /dev/null +++ b/docs/api/hilbish/hilbish.jobs.md @@ -0,0 +1,54 @@ +--- +title: Interface hilbish.jobs +description: background job management +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction + +Manage interactive jobs in Hilbish via Lua. + +Jobs are the name of background tasks/commands. A job can be started via +interactive usage or with the functions defined below for use in external runners. + +## Object properties +- `cmd`: The user entered command string for the job. +- `running`: Whether the job is running or not. +- `id`: The ID of the job in the job table +- `pid`: The Process ID +- `exitCode`: The last exit code of the job. +- `stdout`: The standard output of the job. This just means the normal logs of the process. +- `stderr`: The standard error stream of the process. This (usually) includes error messages of the job. + +## Functions +### background() +Puts a job in the background. This acts the same as initially running a job. + +### foreground() +Puts a job in the foreground. This will cause it to run like it was +executed normally and wait for it to complete. + +### start() +Starts running the job. + +### stop() +Stops the job from running. + +### add(cmdstr, args, execPath) +Adds a new job to the job table. Note that this does not immediately run it. + +### all() +Returns a table of all job objects. + +### disown(id) +Disowns a job. This deletes it from the job table. + +### get(id) +Get a job object via its ID. + +### last() -> Job +Returns the last added job from the table. + diff --git a/docs/api/hilbish/hilbish.os.md b/docs/api/hilbish/hilbish.os.md new file mode 100644 index 00000000..aa2198ee --- /dev/null +++ b/docs/api/hilbish/hilbish.os.md @@ -0,0 +1,19 @@ +--- +title: Interface hilbish.os +description: OS Info +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The `os` interface provides simple text information properties about +the current OS on the systen. This mainly includes the name and +version. + +## Interface fields +- `family`: Family name of the current OS +- `name`: Pretty name of the current OS +- `version`: Version of the current OS + diff --git a/docs/api/hilbish/hilbish.runner.md b/docs/api/hilbish/hilbish.runner.md new file mode 100644 index 00000000..68ffdc6e --- /dev/null +++ b/docs/api/hilbish/hilbish.runner.md @@ -0,0 +1,31 @@ +--- +title: Interface hilbish.runner +description: interactive command runner customization +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The runner interface contains functions that allow the user to change +how Hilbish interprets interactive input. +Users can add and change the default runner for interactive input to any +language or script of their choosing. A good example is using it to +write command in Fennel. + +## Functions +### setMode(cb) +This is the same as the `hilbish.runnerMode` function. It takes a callback, +which will be used to execute all interactive input. +In normal cases, neither callbacks should be overrided by the user, +as the higher level functions listed below this will handle it. + +### lua(cmd) +Evaluates `cmd` as Lua input. This is the same as using `dofile` +or `load`, but is appropriated for the runner interface. + +### sh(cmd) +Runs a command in Hilbish's shell script interpreter. +This is the equivalent of using `source`. + diff --git a/docs/api/hilbish/hilbish.timers.md b/docs/api/hilbish/hilbish.timers.md new file mode 100644 index 00000000..60bedb58 --- /dev/null +++ b/docs/api/hilbish/hilbish.timers.md @@ -0,0 +1,33 @@ +--- +title: Interface hilbish.timers +description: timeout and interval API +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The timers interface si one to easily set timeouts and intervals +to run functions after a certain time or repeatedly without using +odd tricks. + +## Object properties +- `type`: What type of timer it is +- `running`: If the timer is running +- `duration`: The duration in milliseconds that the timer will run + +## Functions +### start() +Starts a timer. + +### stop() +Stops a timer. + +### create(type, time, callback) +Creates a timer that runs based on the specified `time` in milliseconds. +The `type` can either be interval (value of 0) or timeout (value of 1). + +### get(id) +Retrieves a timer via its ID. + diff --git a/docs/api/hilbish/hilbish.userDir.md b/docs/api/hilbish/hilbish.userDir.md new file mode 100644 index 00000000..0b950572 --- /dev/null +++ b/docs/api/hilbish/hilbish.userDir.md @@ -0,0 +1,18 @@ +--- +title: Interface hilbish.userDir +description: user-related directories +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +This interface just contains properties to know about certain user directories. +It is equivalent to XDG on Linux and gets the user's preferred directories +for configs and data. + +## Interface fields +- `config`: The user's config directory +- `data`: The user's directory for program data + diff --git a/docs/api/terminal.md b/docs/api/terminal.md new file mode 100644 index 00000000..99d4b493 --- /dev/null +++ b/docs/api/terminal.md @@ -0,0 +1,26 @@ +--- +title: Module terminal +description: low level terminal library +layout: doc +menu: + docs: + parent: "API" +--- + +## Introduction +The terminal library is a simple and lower level library for certain terminal interactions. + +## Functions +### restoreState() +Restores the last saved state of the terminal + +### saveState() +Saves the current state of the terminal + +### setRaw() +Puts the terminal in raw mode + +### size() +Gets the dimensions of the terminal. Returns a table with `width` and `height` +Note: this is not the size in relation to the dimensions of the display + diff --git a/docs/bait.txt b/docs/bait.txt deleted file mode 100644 index 2b6f7aec..00000000 --- a/docs/bait.txt +++ /dev/null @@ -1,12 +0,0 @@ -catch(name, cb) > Catches a hook with `name`. Runs the `cb` when it is thrown - -catchOnce(name, cb) > Same as catch, but only runs the `cb` once and then removes the hook - -hooks(name) -> {cb, cb...} > Returns a table with hooks on the event with `name`. - -release(name, catcher) > Removes the `catcher` for the event with `name` -For this to work, `catcher` has to be the same function used to catch -an event, like one saved to a variable. - -throw(name, ...args) > Throws a hook with `name` with the provided `args` - diff --git a/docs/commander.txt b/docs/commander.txt deleted file mode 100644 index 8b4b329b..00000000 --- a/docs/commander.txt +++ /dev/null @@ -1,4 +0,0 @@ -deregister(name) > Deregisters any command registered with `name` - -register(name, cb) > Register a command with `name` that runs `cb` when ran - diff --git a/docs/completions.txt b/docs/completions.md similarity index 100% rename from docs/completions.txt rename to docs/completions.md diff --git a/docs/fs.txt b/docs/fs.txt deleted file mode 100644 index 8372afde..00000000 --- a/docs/fs.txt +++ /dev/null @@ -1,22 +0,0 @@ -abs(path) > Gives an absolute version of `path`. - -basename(path) > Gives the basename of `path`. For the rules, -see Go's filepath.Base - -cd(dir) > Changes directory to `dir` - -dir(path) > Returns the directory part of `path`. For the rules, see Go's -filepath.Dir - -glob(pattern) > Glob all files and directories that match the pattern. -For the rules, see Go's filepath.Glob - -join(paths...) > Takes paths and joins them together with the OS's -directory separator (forward or backward slash). - -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` - diff --git a/docs/hilbish.txt b/docs/hilbish.txt deleted file mode 100644 index 20a9bd7f..00000000 --- a/docs/hilbish.txt +++ /dev/null @@ -1,62 +0,0 @@ -alias(cmd, orig) > Sets an alias of `cmd` to `orig` - -appendPath(dir) > Appends `dir` to $PATH - -complete(scope, cb) > Registers a completion handler for `scope`. -A `scope` is currently only expected to be `command.`, -replacing with the name of the command (for example `command.git`). -`cb` must be a function that returns a table of "completion groups." -Check `doc completions` for more information. - -cwd() > Returns the current directory of the shell - -exec(cmd) > Replaces running hilbish with `cmd` - -goro(fn) > Puts `fn` in a goroutine - -highlighter(line) > Line highlighter handler. This is mainly for syntax highlighting, but in -reality could set the input of the prompt to *display* anything. The -callback is passed the current line and is expected to return a line that -will be used as the input display. - -hinter(line, pos) > The command line hint handler. It gets called on every key insert to -determine what text to use as an inline hint. It is passed the current -line and cursor position. It is expected to return a string which is used -as the text for the hint. This is by default a shim. To set hints, -override this function with your custom handler. - -inputMode(mode) > Sets the input mode for Hilbish's line reader. Accepts either emacs or vim - -interval(cb, time) > Runs the `cb` function every `time` milliseconds. -Returns a `timer` object (see `doc timers`). - -multiprompt(str) > Changes the continued line prompt to `str` - -prependPath(dir) > Prepends `dir` to $PATH - -prompt(str, typ?) > 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 - -read(prompt?) -> input? > Read input from the user, using Hilbish's line editor/input reader. -This is a separate instance from the one Hilbish actually uses. -Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen) - -run(cmd, returnOut) -> exitCode, stdout, stderr > Runs `cmd` in Hilbish's sh interpreter. -If returnOut is true, the outputs of `cmd` will be returned as the 2nd and -3rd values instead of being outputted to the terminal. - -runnerMode(mode) > Sets the execution/runner mode for interactive Hilbish. This determines whether -Hilbish wll try to run input as Lua and/or sh or only do one of either. -Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua), -sh, and lua. It also accepts a function, to which if it is passed one -will call it to execute user input instead. - -timeout(cb, time) > Runs the `cb` function after `time` in milliseconds -Returns a `timer` object (see `doc timers`). - -which(name) > Checks if `name` is a valid command - diff --git a/docs/hooks/command.txt b/docs/hooks/command.md similarity index 100% rename from docs/hooks/command.txt rename to docs/hooks/command.md diff --git a/docs/hooks/hilbish.txt b/docs/hooks/hilbish.md similarity index 100% rename from docs/hooks/hilbish.txt rename to docs/hooks/hilbish.md diff --git a/docs/hooks/index.txt b/docs/hooks/index.md similarity index 100% rename from docs/hooks/index.txt rename to docs/hooks/index.md diff --git a/docs/hooks/job.txt b/docs/hooks/job.md similarity index 100% rename from docs/hooks/job.txt rename to docs/hooks/job.md diff --git a/docs/hooks/signal.txt b/docs/hooks/signal.md similarity index 100% rename from docs/hooks/signal.txt rename to docs/hooks/signal.md diff --git a/docs/jobs.txt b/docs/jobs.md similarity index 100% rename from docs/jobs.txt rename to docs/jobs.md diff --git a/docs/lunacolors.txt b/docs/lunacolors.md similarity index 100% rename from docs/lunacolors.txt rename to docs/lunacolors.md diff --git a/docs/nature/index.txt b/docs/nature/index.md similarity index 100% rename from docs/nature/index.txt rename to docs/nature/index.md diff --git a/docs/runner-mode.txt b/docs/runner-mode.md similarity index 100% rename from docs/runner-mode.txt rename to docs/runner-mode.md diff --git a/docs/terminal.txt b/docs/terminal.txt deleted file mode 100644 index 7683bbbd..00000000 --- a/docs/terminal.txt +++ /dev/null @@ -1,9 +0,0 @@ -restoreState() > Restores the last saved state of the terminal - -saveState() > Saves the current state of the terminal - -setRaw() > Puts the terminal in raw mode - -size() > Gets the dimensions of the terminal. Returns a table with `width` and `height` -Note: this is not the size in relation to the dimensions of the display - diff --git a/docs/timers.txt b/docs/timers.md similarity index 100% rename from docs/timers.txt rename to docs/timers.md diff --git a/docs/vim-mode/actions.txt b/docs/vim-mode/actions.md similarity index 100% rename from docs/vim-mode/actions.txt rename to docs/vim-mode/actions.md diff --git a/docs/vim-mode/index.txt b/docs/vim-mode/index.md similarity index 100% rename from docs/vim-mode/index.txt rename to docs/vim-mode/index.md diff --git a/editor.go b/editor.go index 868f4589..4331dd9d 100644 --- a/editor.go +++ b/editor.go @@ -6,6 +6,10 @@ import ( rt "github.com/arnodel/golua/runtime" ) +// #interface editor +// interactions for Hilbish's line reader +// The hilbish.editor interface provides functions to +// directly interact with the line editor in use. func editorLoader(rtm *rt.Runtime) *rt.Table { exports := map[string]util.LuaExport{ "insert": {editorInsert, 1, false}, @@ -20,6 +24,9 @@ func editorLoader(rtm *rt.Runtime) *rt.Table { return mod } +// #interface editor +// insert(text) +// Inserts text into the line. func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -35,6 +42,9 @@ func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface editor +// setVimRegister(register, text) +// Sets the vim register at `register` to hold the passed text. func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -55,6 +65,9 @@ func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface editor +// getVimRegister(register) +// Returns the text that is at the register. func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -70,6 +83,9 @@ func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil } +// #interface editor +// getLine() +// Returns the current input line. func editorGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { buf := lr.rl.GetLine() diff --git a/emmyLuaDocs/bait.lua b/emmyLuaDocs/bait.lua index a957e00d..65f9f832 100644 --- a/emmyLuaDocs/bait.lua +++ b/emmyLuaDocs/bait.lua @@ -27,6 +27,6 @@ function bait.release(name, catcher) end --- Throws a hook with `name` with the provided `args` --- @param name string --- @vararg any -function bait.throw(name, ...) end +function bait.throw(name, ...args) end return bait diff --git a/emmyLuaDocs/fs.lua b/emmyLuaDocs/fs.lua index 14e7be44..eb5743a4 100644 --- a/emmyLuaDocs/fs.lua +++ b/emmyLuaDocs/fs.lua @@ -8,7 +8,7 @@ function fs.abs(path) end --- Gives the basename of `path`. For the rules, --- see Go's filepath.Base -function fs.basename() end +function fs.basename(path) end --- Changes directory to `dir` --- @param dir string @@ -16,15 +16,15 @@ function fs.cd(dir) end --- Returns the directory part of `path`. For the rules, see Go's --- filepath.Dir -function fs.dir() end +function fs.dir(path) end --- Glob all files and directories that match the pattern. --- For the rules, see Go's filepath.Glob -function fs.glob() end +function fs.glob(pattern) end --- Takes paths and joins them together with the OS's --- directory separator (forward or backward slash). -function fs.join() end +function fs.join(paths...) end --- Makes a directory called `name`. If `recursive` is true, it will create its parent directories. --- @param name string diff --git a/emmyLuaDocs/hilbish.lua b/emmyLuaDocs/hilbish.lua index ca344254..7a6930de 100644 --- a/emmyLuaDocs/hilbish.lua +++ b/emmyLuaDocs/hilbish.lua @@ -2,6 +2,38 @@ local hilbish = {} +--- This is an alias (ha) for the `hilbish.alias` function. +--- @param alias string +--- @param cmd string +function hilbish.aliases.add(alias, cmd) end + +--- This is the same as the `hilbish.runnerMode` function. It takes a callback, +--- which will be used to execute all interactive input. +--- In normal cases, neither callbacks should be overrided by the user, +--- as the higher level functions listed below this will handle it. +function hilbish.runner.setMode(cb) end + +--- Calls a completer function. This is mainly used to call +--- a command completer, which will have a `name` in the form +--- of `command.name`, example: `command.git` +function hilbish.completions.call(name, query, ctx, fields) end + +--- The handler function is the callback for tab completion in Hilbish. +--- You can check the completions doc for more info. +function hilbish.completions.handler(line, pos) end + +--- Returns the current input line. +function hilbish.editor.getLine() end + +--- Returns the text that is at the register. +function hilbish.editor.getVimRegister(register) end + +--- Inserts text into the line. +function hilbish.editor.insert(text) end + +--- Sets the vim register at `register` to hold the passed text. +function hilbish.editor.setVimRegister(register, text) end + --- Sets an alias of `cmd` to `orig` --- @param cmd string --- @param orig string @@ -73,20 +105,21 @@ function hilbish.prependPath(dir) end --- `%u` - Name of current user --- `%h` - Hostname of device --- @param str string ---- @param typ string Type of prompt, being left or right. Left by default. +--- @param typ string|nil Type of prompt, being left or right. Left by default. function hilbish.prompt(str, typ) end --- Read input from the user, using Hilbish's line editor/input reader. --- This is a separate instance from the one Hilbish actually uses. --- Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen) ---- @param prompt string +--- @param prompt string|nil +--- @returns string|nil function hilbish.read(prompt) end --- Runs `cmd` in Hilbish's sh interpreter. --- If returnOut is true, the outputs of `cmd` will be returned as the 2nd and --- 3rd values instead of being outputted to the terminal. --- @param cmd string -function hilbish.run(cmd) end +function hilbish.run(cmd, returnOut) end --- Sets the execution/runner mode for interactive Hilbish. This determines whether --- Hilbish wll try to run input as Lua and/or sh or only do one of either. @@ -105,6 +138,87 @@ function hilbish.timeout(cb, time) end --- Checks if `name` is a valid command --- @param binName string -function hilbish.which(binName) end +function hilbish.which(name) end + +--- Puts a job in the background. This acts the same as initially running a job. +function hilbish.jobs:background() end + +--- Returns binary/executale completion candidates based on the provided query. +function hilbish.completions.bins(query, ctx, fields) end + +--- Returns file completion candidates based on the provided query. +function hilbish.completions.files(query, ctx, fields) end + +--- Puts a job in the foreground. This will cause it to run like it was +--- executed normally and wait for it to complete. +function hilbish.jobs:foreground() end + +--- Evaluates `cmd` as Lua input. This is the same as using `dofile` +--- or `load`, but is appropriated for the runner interface. +function hilbish.runner.lua(cmd) end + +--- Starts running the job. +function hilbish.jobs:start() end + +--- Stops the job from running. +function hilbish.jobs.stop() end + +--- Runs a command in Hilbish's shell script interpreter. +--- This is the equivalent of using `source`. +function hilbish.runner.sh(cmd) end + +--- Starts a timer. +function hilbish.timers:start() end + +--- Stops a timer. +function hilbish.timers:stop() end + +--- Removes an alias. +--- @param name string +function hilbish.aliases.delete(name) end + +--- Get a table of all aliases. +function hilbish.aliases.list() end + +--- Tries to resolve an alias to its command. +--- @param alias string +function hilbish.aliases.resolve(alias) end + +--- Adds a new job to the job table. Note that this does not immediately run it. +function hilbish.jobs.add(cmdstr, args, execPath) end + +--- Returns a table of all job objects. +function hilbish.jobs.all() end + +--- Disowns a job. This deletes it from the job table. +function hilbish.jobs.disown(id) end + +--- Get a job object via its ID. +function hilbish.jobs.get(id) end + +--- Returns the last added job from the table. +function hilbish.jobs.last() end + +--- Adds a command to the history. +--- @param cmd string +function hilbish.history.add(cmd) end + +--- Deletes all commands from the history. +function hilbish.history.clear() end + +--- Retrieves a command from the history based on the `idx`. +--- @param idx number +function hilbish.history.get(idx) end + +--- Returns the amount of commands in the history. +--- @returns number +function hilbish.history.size() end + +--- Creates a timer that runs based on the specified `time` in milliseconds. +--- The `type` can either be interval (value of 0) or timeout (value of 1). +function hilbish.timers.create(type, time, callback) end + +--- Retrieves a timer via its ID. +function hilbish.timers.get(id) end return hilbish diff --git a/golibs/bait/bait.go b/golibs/bait/bait.go index 70e122cb..8a6bf8cd 100644 --- a/golibs/bait/bait.go +++ b/golibs/bait/bait.go @@ -1,3 +1,9 @@ +// the event emitter +// Bait is the event emitter for Hilbish. Why name it bait? Why not. +// It throws hooks that you can catch. 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. To find all available hooks thrown by Hilbish, see doc hooks. package bait import ( diff --git a/golibs/commander/commander.go b/golibs/commander/commander.go index 24f1c036..93785e29 100644 --- a/golibs/commander/commander.go +++ b/golibs/commander/commander.go @@ -1,3 +1,5 @@ +// library for custom commands +// Commander is a library for writing custom commands in Lua. package commander import ( diff --git a/golibs/fs/fs.go b/golibs/fs/fs.go index 5b12e739..94b81108 100644 --- a/golibs/fs/fs.go +++ b/golibs/fs/fs.go @@ -1,3 +1,7 @@ +// filesystem interaction and functionality library +// 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 filesystem functions. package fs import ( diff --git a/golibs/terminal/terminal.go b/golibs/terminal/terminal.go index df1755cb..4ae8f885 100644 --- a/golibs/terminal/terminal.go +++ b/golibs/terminal/terminal.go @@ -1,3 +1,5 @@ +// low level terminal library +// The terminal library is a simple and lower level library for certain terminal interactions. package terminal import ( diff --git a/job.go b/job.go index 709cc1f7..b9400cd3 100644 --- a/job.go +++ b/job.go @@ -110,6 +110,10 @@ func (j *job) getProc() *os.Process { return nil } +// #interface jobs +// #member +// start() +// Starts running the job. func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -130,6 +134,9 @@ func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface jobs +// stop() +// Stops the job from running. func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -148,6 +155,11 @@ func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface jobs +// #member +// foreground() +// Puts a job in the foreground. This will cause it to run like it was +// executed normally and wait for it to complete. func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -180,6 +192,10 @@ func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface jobs +// #member +// background() +// Puts a job in the background. This acts the same as initially running a job. func luaBackgroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -276,6 +292,20 @@ func (j *jobHandler) stopAll() { } } +// #interface jobs +// #property cmd The user entered command string for the job. +// #property running Whether the job is running or not. +// #property id The ID of the job in the job table +// #property pid The Process ID +// #property exitCode The last exit code of the job. +// #property stdout The standard output of the job. This just means the normal logs of the process. +// #property stderr The standard error stream of the process. This (usually) includes error messages of the job. +// background job management +/* +Manage interactive jobs in Hilbish via Lua. + +Jobs are the name of background tasks/commands. A job can be started via +interactive usage or with the functions defined below for use in external runners. */ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table { jobMethods := rt.NewTable() jFuncs := map[string]util.LuaExport{ @@ -353,6 +383,9 @@ func jobUserData(j *job) *rt.UserData { return rt.NewUserData(j, jobMeta.AsTable()) } +// #interface jobs +// get(id) +// Get a job object via its ID. func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { j.mu.RLock() defer j.mu.RUnlock() @@ -373,6 +406,9 @@ func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext(t.Runtime, rt.UserDataValue(job.ud)), nil } +// #interface jobs +// add(cmdstr, args, execPath) +// Adds a new job to the job table. Note that this does not immediately run it. func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.CheckNArgs(3); err != nil { return nil, err @@ -402,6 +438,9 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.UserDataValue(jb.ud)), nil } +// #interface jobs +// all() +// Returns a table of all job objects. func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { j.mu.RLock() defer j.mu.RUnlock() @@ -414,6 +453,9 @@ func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil } +// #interface jobs +// disown(id) +// Disowns a job. This deletes it from the job table. func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -431,6 +473,9 @@ func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface jobs +// last() -> Job +// Returns the last added job from the table. func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { j.mu.RLock() defer j.mu.RUnlock() diff --git a/nature/commands/doc.lua b/nature/commands/doc.lua index a290cd87..bc16dfeb 100644 --- a/nature/commands/doc.lua +++ b/nature/commands/doc.lua @@ -4,34 +4,34 @@ local lunacolors = require 'lunacolors' commander.register('doc', function(args) local moddocPath = hilbish.dataDir .. '/docs/' - local modDocFormat = [[ -%s -%s -# Functions + local apidocHeader = [[ +# %s +{grayBg} {white}{italic}%s {reset} + ]] if #args > 0 then local mod = args[1] - local f = io.open(moddocPath .. mod .. '.txt', 'rb') + local f = io.open(moddocPath .. mod .. '.md', 'rb') local funcdocs = nil if not f then -- assume subdir - -- dataDir/docs//.txt + -- dataDir/docs//.md moddocPath = moddocPath .. mod .. '/' local subdocName = args[2] if not subdocName then subdocName = 'index' end - f = io.open(moddocPath .. subdocName .. '.txt', 'rb') + f = io.open(moddocPath .. subdocName .. '.md', 'rb') if not f then print('No documentation found for ' .. mod .. '.') return end funcdocs = f:read '*a' - local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= 'index.txt' end) + local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= 'index.md' end) local subdocs = table.map(moddocs, function(fname) - return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.txt', ''))) + return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', ''))) end) if subdocName == 'index' then funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ') @@ -41,8 +41,24 @@ commander.register('doc', function(args) if not funcdocs then funcdocs = f:read '*a' end - local desc = '' - local ok = pcall(require, mod) + local valsStr = funcdocs:match '%-%-%-\n([^%-%-%-]+)\n' + local vals = {} + if valsStr then + local _, endpos = funcdocs:find('---\n' .. valsStr .. '\n---\n\n', 1, true) + funcdocs = funcdocs:sub(endpos + 1, #funcdocs) + + -- parse vals + local lines = string.split(valsStr, '\n') + for _, line in ipairs(lines) do + local key = line:match '(%w+): ' + local val = line:match '^%w+: (.-)$' + + vals[key] = val + end + end + if mod == 'api' then + funcdocs = string.format(apidocHeader, vals.name, vals.description) .. funcdocs + end local backtickOccurence = 0 local formattedFuncs = lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function() backtickOccurence = backtickOccurence + 1 @@ -51,34 +67,16 @@ commander.register('doc', function(args) else return '{underline}{green}' end + end):gsub('#+.-\n', function(t) + return '{bold}{magenta}' .. t .. '{reset}' end)) - - if ok then - local props = {} - local propstr = '' - local modDesc = '' - local modmt = getmetatable(require(mod)) - if modmt then - modDesc = modmt.__doc - if modmt.__docProp then - -- not all modules have docs for properties - props = table.map(modmt.__docProp, function(v, k) - return lunacolors.underline(lunacolors.blue(k)) .. ' > ' .. v - end) - end - if #props > 0 then - propstr = '\n# Properties\n' .. table.concat(props, '\n') .. '\n' - end - desc = string.format(modDocFormat, modDesc, propstr) - end - end - print(desc .. formattedFuncs) + print(formattedFuncs) f:close() return end local modules = table.map(fs.readdir(moddocPath), function(f) - return lunacolors.underline(lunacolors.blue(string.gsub(f, '.txt', ''))) + return lunacolors.underline(lunacolors.blue(string.gsub(f, '.md', ''))) end) io.write [[ diff --git a/nature/runner.lua b/nature/runner.lua index e155f63e..9b62ad1d 100644 --- a/nature/runner.lua +++ b/nature/runner.lua @@ -1,3 +1,4 @@ +--- hilbish.runner local currentRunner = 'hybrid' local runners = {} diff --git a/os.go b/os.go new file mode 100644 index 00000000..a214ea95 --- /dev/null +++ b/os.go @@ -0,0 +1,27 @@ +package main + +import ( + "hilbish/util" + + rt "github.com/arnodel/golua/runtime" + "github.com/blackfireio/osinfo" +) + +// #interface os +// OS Info +// The `os` interface provides simple text information properties about +// the current OS on the systen. This mainly includes the name and +// version. +// #field family Family name of the current OS +// #field name Pretty name of the current OS +// #field version Version of the current OS +func hshosLoader(rtm *rt.Runtime) *rt.Table { + info, _ := osinfo.GetOSInfo() + mod := rt.NewTable() + + util.SetField(rtm, mod, "family", rt.StringValue(info.Family), "Family name of the current OS") + util.SetField(rtm, mod, "name", rt.StringValue(info.Name), "Pretty name of the current OS") + util.SetField(rtm, mod, "version", rt.StringValue(info.Version), "Version of the current OS") + + return mod +} diff --git a/rl.go b/rl.go index f6cb6cde..6356f645 100644 --- a/rl.go +++ b/rl.go @@ -225,7 +225,11 @@ func (lr *lineReader) Resize() { return } -// lua module +// #interface history +// command history +// The history interface deals with command history. +// This includes the ability to override functions to change the main +// method of saving history. func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table { lrLua := map[string]util.LuaExport{ "add": {lr.luaAddHistory, 1, false}, @@ -241,6 +245,10 @@ func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table { return mod } +// #interface history +// add(cmd) +// Adds a command to the history. +// --- @param cmd string func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -254,10 +262,18 @@ func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) return c.Next(), nil } +// #interface history +// size() +// Returns the amount of commands in the history. +// --- @returns number func (lr *lineReader) luaSize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.IntValue(int64(lr.fileHist.Len()))), nil } +// #interface history +// get(idx) +// Retrieves a command from the history based on the `idx`. +// --- @param idx number func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -284,6 +300,9 @@ func (lr *lineReader) luaAllHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) return c.PushingNext1(t.Runtime, rt.TableValue(tbl)), nil } +// #interface history +// clear() +// Deletes all commands from the history. func (lr *lineReader) luaClearHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { lr.fileHist.clear() return c.Next(), nil diff --git a/runnermode.go b/runnermode.go index c26ed036..e212604a 100644 --- a/runnermode.go +++ b/runnermode.go @@ -6,6 +6,13 @@ import ( rt "github.com/arnodel/golua/runtime" ) +// #interface runner +// interactive command runner customization +// The runner interface contains functions that allow the user to change +// how Hilbish interprets interactive input. +// Users can add and change the default runner for interactive input to any +// language or script of their choosing. A good example is using it to +// write command in Fennel. func runnerModeLoader(rtm *rt.Runtime) *rt.Table { exports := map[string]util.LuaExport{ "sh": {shRunner, 1, false}, @@ -19,6 +26,18 @@ func runnerModeLoader(rtm *rt.Runtime) *rt.Table { return mod } +// #interface runner +// setMode(cb) +// This is the same as the `hilbish.runnerMode` function. It takes a callback, +// which will be used to execute all interactive input. +// In normal cases, neither callbacks should be overrided by the user, +// as the higher level functions listed below this will handle it. +func _runnerMode() {} + +// #interface runner +// sh(cmd) +// Runs a command in Hilbish's shell script interpreter. +// This is the equivalent of using `source`. func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -42,6 +61,10 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil } +// #interface runner +// lua(cmd) +// Evaluates `cmd` as Lua input. This is the same as using `dofile` +// or `load`, but is appropriated for the runner interface. func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err diff --git a/timer.go b/timer.go index 74d13c4c..be8f270b 100644 --- a/timer.go +++ b/timer.go @@ -21,7 +21,7 @@ type timer struct{ running bool dur time.Duration fun *rt.Closure - th *timerHandler + th *timersModule ticker *time.Ticker ud *rt.UserData channel chan struct{} @@ -73,6 +73,10 @@ func (t *timer) stop() error { return nil } +// #interface timers +// #member +// start() +// Starts a timer. func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err @@ -91,6 +95,10 @@ func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } +// #interface timers +// #member +// stop() +// Stops a timer. func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err diff --git a/timerhandler.go b/timerhandler.go index 64caff86..92947e1f 100644 --- a/timerhandler.go +++ b/timerhandler.go @@ -10,10 +10,10 @@ import ( rt "github.com/arnodel/golua/runtime" ) -var timers *timerHandler +var timers *timersModule var timerMetaKey = rt.StringValue("hshtimer") -type timerHandler struct { +type timersModule struct { mu *sync.RWMutex wg *sync.WaitGroup timers map[int]*timer @@ -21,8 +21,8 @@ type timerHandler struct { running int } -func newTimerHandler() *timerHandler { - return &timerHandler{ +func newTimersModule() *timersModule { + return &timersModule{ timers: make(map[int]*timer), latestID: 0, mu: &sync.RWMutex{}, @@ -30,11 +30,11 @@ func newTimerHandler() *timerHandler { } } -func (th *timerHandler) wait() { +func (th *timersModule) wait() { th.wg.Wait() } -func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure) *timer { +func (th *timersModule) create(typ timerType, dur time.Duration, fun *rt.Closure) *timer { th.mu.Lock() defer th.mu.Unlock() @@ -54,14 +54,18 @@ func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure return t } -func (th *timerHandler) get(id int) *timer { +func (th *timersModule) get(id int) *timer { th.mu.RLock() defer th.mu.RUnlock() return th.timers[id] } -func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { +// #interface timers +// create(type, time, callback) +// Creates a timer that runs based on the specified `time` in milliseconds. +// The `type` can either be interval (value of 0) or timeout (value of 1). +func (th *timersModule) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.CheckNArgs(3); err != nil { return nil, err } @@ -83,7 +87,10 @@ func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext1(t.Runtime, rt.UserDataValue(tmr.ud)), nil } -func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { +// #interface timers +// get(id) +// Retrieves a timer via its ID. +func (th *timersModule) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { if err := c.Check1Arg(); err != nil { return nil, err } @@ -100,7 +107,15 @@ func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.Next(), nil } -func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table { +// #interface timers +// #property type What type of timer it is +// #property running If the timer is running +// #property duration The duration in milliseconds that the timer will run +// timeout and interval API +// The timers interface si one to easily set timeouts and intervals +// to run functions after a certain time or repeatedly without using +// odd tricks. +func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table { timerMethods := rt.NewTable() timerFuncs := map[string]util.LuaExport{ "start": {timerStart, 1, false}, diff --git a/userdir.go b/userdir.go new file mode 100644 index 00000000..b3581e2c --- /dev/null +++ b/userdir.go @@ -0,0 +1,23 @@ +package main + +import ( + "hilbish/util" + + rt "github.com/arnodel/golua/runtime" +) + +// #interface userDir +// user-related directories +// This interface just contains properties to know about certain user directories. +// It is equivalent to XDG on Linux and gets the user's preferred directories +// for configs and data. +// #field config The user's config directory +// #field data The user's directory for program data +func userDirLoader(rtm *rt.Runtime) *rt.Table { + mod := rt.NewTable() + + util.SetField(rtm, mod, "config", rt.StringValue(confDir), "User's config directory") + util.SetField(rtm, mod, "data", rt.StringValue(userDataDir), "XDG data directory") + + return mod +} diff --git a/website/content/docs/api b/website/content/docs/api new file mode 120000 index 00000000..1c5c3605 --- /dev/null +++ b/website/content/docs/api @@ -0,0 +1 @@ +../../../docs/api/ \ No newline at end of file