diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e378376..6515d25 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/.github/workflows/release.yml b/.github/workflows/release.yml index 9f9163d..4d9afba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,7 @@ jobs: - uses: actions/checkout@v3 with: submodules: true + fetch-depth: 0 - name: Download Task run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d' - uses: wangyoucao577/go-release-action@v1.25 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml new file mode 100644 index 0000000..547673b --- /dev/null +++ b/.github/workflows/website.yml @@ -0,0 +1,31 @@ +name: Build website + +on: + push: + branches: + - master + - docs-refactor + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: Setup Hugo + uses: peaceiris/actions-hugo@v2 + with: + hugo-version: 'latest' + extended: true + + - name: Build + run: 'cd website && hugo --minify' + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./website/public diff --git a/.gitignore b/.gitignore index 338ef97..b2be7c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ *.exe hilbish +!docs/api/hilbish docgen +!cmd/docgen .vim petals/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c621d1..e856546 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,16 @@ # 🎀 Changelog ## Unreleased -**NOTE:** Hilbish now uses [Task] insead of Make for builds. -Windows support is also now at a lower tier; The only thing guaranteed is -Hilbish *compiling* on Windows. +**NOTES FOR USERS/PACKAGERS UPDATING:** +- Hilbish now uses [Task] insead of Make for builds. +- The doc format has been changed from plain text to markdown. +**YOU MUST reinstall Hilbish to remove the duplicate, old docs.** +- Hilbish will by default install to **`/usr/local`** instead of just `/usr/` +when building via Task. This is mainly to avoid conflict of distro packages +and local installs, and is the correct place when building from git either way. +To keep Hilbish in `/usr`, you must have `PREFIX="/usr/"` when running `task build` or `task install` +- Windows is no longer supported. It will build and run, but **will** have problems. +If you want to help fix the situation, start a discussion or open an issue and contribute. [Task]: https://taskfile.dev/#/ @@ -103,6 +110,7 @@ of a dot. (ie. `job.stop()` -> `job:stop()`) - All `fs` module functions which take paths now implicitly expand ~ to home. - **Breaking Change:** `hilbish.greeting` has been moved to an opt (`hilbish.opts.greeting`) and is always printed by default. To disable it, set the opt to false. +- **Breaking Change:** `command.no-perm` hook has been replaced with `command.not-executable` - History is now fetched from Lua, which means users can override `hilbish.history` methods to make it act how they want. - `guide` has been removed. See the [website](https://rosettea.github.io/Hilbish/) @@ -161,6 +169,8 @@ will result in the files being completed. - Cut off item names in grid menu if its longer than cell width - Fix completion search menu disappearing - Completion paths having duplicated characters if it's escaped +- Get custom completion command properly to call from Lua +- Put proper command on the line when using up and down arrow keys to go through command history ## [2.0.0-rc1] - 2022-09-14 This is a pre-release version of Hilbish for testing. To see the changelog, diff --git a/README.md b/README.md index 5ca8232..b4f85f7 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ If you're new to nix you should probably read up on how to do that [here](https: ## Manual Build ### Prerequisites - [Go 1.17+](https://go.dev) -- [Task](https://taskfile.dev/#/) +- [Task](https://taskfile.dev/installation/) (**Go on the hyperlink here to see Task's install method for your OS.**) ### Build First, clone Hilbish. The recursive is required, as some Lua libraries diff --git a/Taskfile.yaml b/Taskfile.yaml index 0170885..6bf17e0 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -3,12 +3,12 @@ version: '3' vars: - PREFIX: '{{default "/usr" .PREFIX}}' + PREFIX: '{{default "/usr/local" .PREFIX}}' bindir__: '{{.PREFIX}}/bin' BINDIR: '{{default .bindir__ .BINDIR}}' libdir__: '{{.PREFIX}}/share/hilbish' LIBDIR: '{{default .libdir__ .LIBDIR}}' - goflags__: '-ldflags "-s -w"' + goflags__: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}}"' GOFLAGS: '{{default .goflags__ .GOFLAGS}}' tasks: @@ -16,7 +16,7 @@ tasks: cmds: - CGO_ENABLED=0 go build {{.GOFLAGS}} vars: - GOFLAGS: '-ldflags "-s -w -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"' + GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"' build: cmds: diff --git a/aliases.go b/aliases.go index 3007cc3..741a6a3 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 3e5f892..09df7c0 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 39a2a76..cf70840 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 c2a107c..7c3f563 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 0000000..5c8b722 --- /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 0000000..fdf22b0 --- /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 0000000..e3e5320 --- /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 0000000..6ad11de --- /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 0000000..5cdcb4d --- /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 0000000..1ff766c --- /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 0000000..bcfd2f9 --- /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 0000000..bb0f257 --- /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 0000000..f297ab2 --- /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 0000000..b180dd4 --- /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 0000000..aa2198e --- /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 0000000..68ffdc6 --- /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 0000000..60bedb5 --- /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 0000000..0b95057 --- /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 0000000..99d4b49 --- /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 2b6f7ae..0000000 --- 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 8b4b329..0000000 --- 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 8372afd..0000000 --- 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 20a9bd7..0000000 --- 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 7683bbb..0000000 --- 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 868f458..4331dd9 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 a957e00..65f9f83 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 14e7be4..eb5743a 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 ca34425..7a6930d 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/exec.go b/exec.go index caf7d1b..d668192 100644 --- a/exec.go +++ b/exec.go @@ -141,9 +141,9 @@ func runInput(input string, priv bool) { if err != nil { if exErr, ok := isExecError(err); ok { hooks.Emit("command." + exErr.typ, exErr.cmd) - err = exErr.sprint() + } else { + fmt.Fprintln(os.Stderr, err) } - fmt.Fprintln(os.Stderr, err) } cmdFinish(exitCode, input, priv) } diff --git a/go.mod b/go.mod index 825dae0..52b274a 100644 --- a/go.mod +++ b/go.mod @@ -29,4 +29,4 @@ replace github.com/maxlandon/readline => ./readline replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10 -replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3 +replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345 diff --git a/go.sum b/go.sum index c313c19..74a351b 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac h1:dtXrgjch8PQyf7C9 github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3 h1:I/wWr40FFLFF9pbT3wLb1FAEZhKb/hUWE+nJ5uHBK2g= github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= +github.com/Rosettea/golua v0.0.0-20220621002945-b05143999437 h1:6lWu4YVLeKuZ8jR9xwHONhkHBsrIbw5dpfG1gtOVw0A= +github.com/Rosettea/golua v0.0.0-20220621002945-b05143999437/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= +github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345 h1:QNYjYDogUSiNUkffbhFSrSCtpZhofeiVYGFN2FI4wSs= +github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE= github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e h1:P2XupP8SaylWaudD1DqbWtZ3mIa8OsE9635LmR+Q+lg= github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e/go.mod h1:R09vh/04ILvP2Gj8/Z9Jd0Dh0ZIvaucowMEs6abQpWs= github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b h1:s5eDMhBk6H1BgipgLub/gv9qeyBaTuiHM0k3h2/9TSE= diff --git a/golibs/bait/bait.go b/golibs/bait/bait.go index 70e122c..8a6bf8c 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 24f1c03..93785e2 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 5b12e73..94b8110 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 df1755c..4ae8f88 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 709cc1f..b9400cd 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 a290cd8..bc16dfe 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/completions.lua b/nature/completions.lua index d20cc59..f8127a1 100644 --- a/nature/completions.lua +++ b/nature/completions.lua @@ -24,7 +24,7 @@ function hilbish.completion.handler(line, pos) return {compGroup}, pfx else local ok, compGroups, pfx = pcall(hilbish.completion.call, - 'command.' .. #fields[1], query, ctx, fields) + 'command.' .. fields[1], query, ctx, fields) if ok then return compGroups, pfx end diff --git a/nature/init.lua b/nature/init.lua index aa85a2e..ecd1054 100644 --- a/nature/init.lua +++ b/nature/init.lua @@ -69,3 +69,11 @@ end bait.catch('error', function(event, handler, err) bait.release(event, handler) end) + +bait.catch('command.not-found', function(cmd) + print(string.format('hilbish: %s not found', cmd)) +end) + +bait.catch('command.not-executable', function(cmd) + print(string.format('hilbish: %s: not executable', cmd)) +end) diff --git a/nature/runner.lua b/nature/runner.lua index e155f63..9b62ad1 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 0000000..a214ea9 --- /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/readline/history.go b/readline/history.go index 41200c6..f772813 100644 --- a/readline/history.go +++ b/readline/history.go @@ -123,23 +123,20 @@ func (rl *Instance) walkHistory(i int) { // When we are exiting the current line buffer to move around // the history, we make buffer the current line - if rl.histPos == 0 && (rl.histPos+i) == 1 { + if rl.histOffset == 0 && rl.histOffset + i == 1 { rl.lineBuf = string(rl.line) } - switch rl.histPos + i { - case 0, history.Len() + 1: - rl.histPos = 0 + rl.histOffset += i + if rl.histOffset == 0 { rl.line = []rune(rl.lineBuf) rl.pos = len(rl.lineBuf) - return - case -1: - rl.histPos = 0 - rl.lineBuf = string(rl.line) - default: + } else if rl.histOffset <= -1 { + rl.histOffset = 0 + } else { dedup = true old = string(rl.line) - new, err = history.GetLine(history.Len() - rl.histPos - 1) + new, err = history.GetLine(history.Len() - rl.histOffset) if err != nil { rl.resetHelpers() print("\r\n" + err.Error() + "\r\n") @@ -148,7 +145,6 @@ func (rl *Instance) walkHistory(i int) { } rl.clearLine() - rl.histPos += i rl.line = []rune(new) rl.pos = len(rl.line) if rl.pos > 0 { diff --git a/readline/instance.go b/readline/instance.go index fcd8379..039f040 100644 --- a/readline/instance.go +++ b/readline/instance.go @@ -134,6 +134,7 @@ type Instance struct { // history operating params lineBuf string histPos int + histOffset int histNavIdx int // Used for quick history navigation. // diff --git a/readline/readline.go b/readline/readline.go index 7397faf..f1d6c96 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -49,7 +49,7 @@ func (rl *Instance) Readline() (string, error) { // History Init // We need this set to the last command, so that we can access it quickly - rl.histPos = 0 + rl.histOffset = 0 rl.viUndoHistory = []undoItem{{line: "", pos: 0}} // Multisplit @@ -546,6 +546,10 @@ func (rl *Instance) Readline() (string, error) { // entry readline is currently configured for and then update the line entries // accordingly. func (rl *Instance) editorInput(r []rune) { + if len(r) == 0 { + return + } + switch rl.modeViMode { case VimKeys: rl.vi(r[0]) diff --git a/rl.go b/rl.go index f6cb6cd..6356f64 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 c26ed03..e212604 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 74d13c4..be8f270 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 64caff8..92947e1 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 0000000..b3581e2 --- /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/vars_linux.go b/vars_linux.go index 815ba6a..e1160ba 100644 --- a/vars_linux.go +++ b/vars_linux.go @@ -14,7 +14,7 @@ var ( .. hilbish.userDir.config .. '/hilbish/?/init.lua;' .. hilbish.userDir.config .. '/hilbish/?/?.lua;' .. hilbish.userDir.config .. '/hilbish/?.lua'` - dataDir = "/usr/share/hilbish" + dataDir = "/usr/local/share/hilbish" preloadPath = dataDir + "/nature/init.lua" sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config defaultConfDir = "" diff --git a/website/.hugo_build.lock b/website/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/website/archetypes/default.md b/website/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/website/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/website/config.toml b/website/config.toml new file mode 100644 index 0000000..ff6b801 --- /dev/null +++ b/website/config.toml @@ -0,0 +1,25 @@ +baseURL = 'https://rosettea.github.io/Hilbish/' +languageCode = 'en-us' +title = 'Hilbish' +theme = 'hsh' +enableGitInfo = true + +[menu] +[[menu.nav]] + identifier = 'home' + name = 'Home' + pageref = '/' + weight = 1 +[[menu.nav]] + identifier = 'install' + name = 'Install' + pageref = '/install' + weight = 2 +[[menu.nav]] + identifier = 'docs' + name = 'Docs' + pageref = '/docs' + weight = 3 + +[markup.goldmark.renderer] +unsafe = true diff --git a/website/content/_index.md b/website/content/_index.md new file mode 100644 index 0000000..2b1087b --- /dev/null +++ b/website/content/_index.md @@ -0,0 +1,134 @@ +--- +description: 'Something Unique. Hilbish is the new interactive shell for Lua fans. Extensible, scriptable, configurable: All in Lua.' +--- + +[//]: <> + + +
+

Something Unique.

+

+ Hilbish is the new interactive shell for Lua fans.
+ Extensible, scriptable, configurable: All in Lua. +

+ Install + Github +
+ +
+ +
+
+
+
+
+ + + +
+
+
Simple and Easy Scripting
+
+

+ Hilbish is configured and scripted in the Lua programming language. + This removes all the old, ugly things about Shell script and introduces + everything good about Lua, including other languages (Moonscript & Fennel). +

+
+
+
+
+
+
+
+
+
+ + + +
+
+
History and Completion Menus
+
+

+ Hilbish provides the user with proper menus for completions, + history searching. Want to see your previous commands? Hit Ctrl-R. +

+
+
+
+
+
+
+
+
+
+ + + +
+
+
Tons of Features, and More to Come
+
+

+ Hilbish offers a bunch of features to make your interactive + shell experience rich. Things like syntax highlighting and hinting + available via the Lua API. +

+

* Command hints shown in photo are not default.

+
+
+
+
+
+ + +
+ +
+ +

Why not just Lua?

+

+ Hilbish is your interactive shell as well as a just a Lua interpreter + and enhanced REPL.
+

+
    +
  • Batteries included Lua runtime that's also your user shell!
  • +
  • Hilbish is easily cross platform. It has OS agnostic interfaces for easy cross platform Lua code.
  • +
+ +
+ +

Try It Today!

+

+ Hilbish is known to run on the 3 major platforms (Windows, MacOS, Linux) + but likely builds on other Unixes! +
+ Windows doesn't work as well as it should, so if you're a Windows user, + say something! +

+

diff --git a/website/content/docs/_index.md b/website/content/docs/_index.md new file mode 100644 index 0000000..4f30ab3 --- /dev/null +++ b/website/content/docs/_index.md @@ -0,0 +1,19 @@ +--- +title: Introduction +layout: doc +weight: -1 +menu: docs +--- + +Here lies the documentation for Hilbish, the hyper extensible Lua shell. +Hilbish provides you with a few quality of life features and useful +functions to ensure you can make the shell fully yours. + +These features include: +- Completion and history search menus +- Hinting and syntax highlighting (scripted by user) + +# Installation +Steps on installing Hilbish will be at the Install page in the navigation bar +at the top. This also included getting development builds from the GitHub +repository. diff --git a/website/content/docs/api b/website/content/docs/api new file mode 120000 index 0000000..1c5c360 --- /dev/null +++ b/website/content/docs/api @@ -0,0 +1 @@ +../../../docs/api/ \ No newline at end of file diff --git a/website/content/docs/faq.md b/website/content/docs/faq.md new file mode 100644 index 0000000..d5cd1a2 --- /dev/null +++ b/website/content/docs/faq.md @@ -0,0 +1,25 @@ +--- +title: Frequently Asked Questions +layout: doc +weight: -20 +menu: docs +--- + +# Is Hilbish POSIX compliant? +No, it is not. POSIX compliance is a non-goal. Perhaps in the future, +someone would be able to write a native plugin to support shell scripting +(which would be against it's main goal, but ....) + +# Windows Support? +It compiles for Windows (CI ensures it does), but otherwise it is not +directly supported. If you'd like to improve this situation, +checkout [the discussion](https://github.com/Rosettea/Hilbish/discussions/165). + +# Where is the API documentation? +The builtin `doc` command supplies all documentation of Hilbish provided +APIs. This will be on the website in the near future. + +# Why? +Hilbish emerged from the desire of a Lua configured shell. +It was the initial reason that it was created, but now it's more: +to be hyper extensible, simpler and more user friendly. diff --git a/website/content/docs/features/_index.md b/website/content/docs/features/_index.md new file mode 100644 index 0000000..0e14346 --- /dev/null +++ b/website/content/docs/features/_index.md @@ -0,0 +1,11 @@ +--- +title: Features +layout: doc +weight: -40 +menu: docs +--- + +Hilbish has a wide range of features to enhance the user's experience and +is always adding new ones. If there is something missing here or something +you would like to see, please [start a discussion](https://github.com/Rosettea/Hilbish/discussions) +or comment on any existing ones which match your request. diff --git a/website/content/docs/features/runner-mode.md b/website/content/docs/features/runner-mode.md new file mode 100644 index 0000000..87ecc8b --- /dev/null +++ b/website/content/docs/features/runner-mode.md @@ -0,0 +1,17 @@ +--- +title: Runner Mode +description: Customize the interactive script/command runner. +layout: doc +menu: + docs: + parent: "Features" +--- + +Hilbish allows you to change how interactive text can be interpreted. +This is mainly due to the fact that the default method Hilbish uses +is that it runs Lua first and then falls back to shell script. + +In some cases, someone might want to switch to just shell script to avoid +it while interactive but still have a Lua config, or go full Lua to use +Hilbish as a REPL. This also allows users to add alternative languages, +instead of either like Fennel. diff --git a/website/content/docs/getting-started.md b/website/content/docs/getting-started.md new file mode 100644 index 0000000..f0fe56d --- /dev/null +++ b/website/content/docs/getting-started.md @@ -0,0 +1,59 @@ +--- +title: Getting Started +layout: doc +weight: -10 +menu: docs +--- + +To start Hilbish, open a terminal. If Hilbish has been installed and is not the +default shell, you can simply run `hilbish` to start it. This will launch +a normal interactive session. +To exit, you can either run the `exit` command or hit Ctrl+D. + +# Setting as Default +## Login shell +There are a few ways to make Hilbish your default shell. A simple way is +to make it your user/login shell. + +{{< warning `It is not recommended to set Hilbish as your login shell. That is expected to be a +POSIX compliant shell, which Hilbish is not. At most, there will just be a +few variables missing in your environment` >}} + +To do that, simply run `chsh -s /usr/bin/hilbish`. +Some distros (namely Fedora) might have `lchsh` instead, which is used like `lchsh `. +When prompted, you can put the path for Hilbish. + +## Default with terminal +The simpler way is to set the default shell for your terminal. The way of +doing this depends on how your terminal settings are configured. + +## Run after login shell +Some shells (like zsh) have an rc file, like `.zlogin`, which is ran when the shell session +is a login shell. In that file, you can run Hilbish. Example: + +``` +exec hilbish -S -l +``` + +This will replace the shell with Hilbish, set $SHELL to Hilbish and launch it as a login shell. + +# Configuration +Once installation and setup has been done, you can then configure Hilbish. +It is configured and scripted via Lua, so the config file is a Lua file. +You can use any pure Lua library to do whatever you want. + +Hilbish's sample configuration is usually located in `hilbish.dataDir .. '/.hilbishrc.lua'`. +You can print that path via Lua to see what it is: `print(hilbish.dataDir .. '/.hilbishrc.lua')`. +As an example, it will usually will result in `/usr/share/hilbish/.hilbishrc.lua` on Linux. + +To edit your user configuration, you can copy that file to `hilbish.userDir.config .. '/hilbish/init.lua'`, +which follows XDG on Linux and MacOS, and is located in %APPDATA% on Windows. + +As the directory is usually `~/.config` on Linux, you can run this command to copy it: +`cp /usr/share/hilbish/.hilbishrc.lua ~/.config/hilbish/init.lua` + +Now you can get to editing it. Since it's just a Lua file, having basic +knowledge of Lua would help. All of Lua's standard libraries and functions +from Lua 5.4 are available. Hilbish has some custom and modules that are +available. To see them, you can run the `doc` command. This also works as +general documentation for other things. diff --git a/website/content/install.md b/website/content/install.md new file mode 100644 index 0000000..731b8c0 --- /dev/null +++ b/website/content/install.md @@ -0,0 +1,38 @@ +--- +title: Install +description: Steps on how to install Hilbish on all the OSes and distros supported. +layout: page +--- + +## Official Binaries +The best way to get Hilbish is to get a build directly from GitHub. +At any time, there are 2 versions of Hilbish recommended for download: +the latest stable release, and development builds from the master branch. + +You can download both at any time, but note that the development builds may +have breaking changes. + +For the latest **stable release**, check here: https://github.com/Rosettea/Hilbish/releases/latest +For a **development build**: https://nightly.link/Rosettea/Hilbish/workflows/build/master + +## Package Repositories +### Arch Linux (AUR) +Hilbish is on the AUR. Setup an AUR helper, and install. +Example with yay: + +``` +yay -S hilbish +``` + +Or, from master branch: +``` +yay -S hilbish-git +``` + +### Alpine Linux +Hilbish is currentlty in the testing/edge repository for Alpine. +Follow the steps [here](https://wiki.alpinelinux.org/wiki/Enable_Community_Repository) +(Using testing repositories) and install: +``` +apk add hilbish +``` diff --git a/website/static/hilbish-flower.png b/website/static/hilbish-flower.png new file mode 100644 index 0000000..b4fb0f7 Binary files /dev/null and b/website/static/hilbish-flower.png differ diff --git a/website/themes/hsh/LICENSE b/website/themes/hsh/LICENSE new file mode 100644 index 0000000..da3c8c1 --- /dev/null +++ b/website/themes/hsh/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Rosettea + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/website/themes/hsh/archetypes/default.md b/website/themes/hsh/archetypes/default.md new file mode 100644 index 0000000..ac36e06 --- /dev/null +++ b/website/themes/hsh/archetypes/default.md @@ -0,0 +1,2 @@ ++++ ++++ diff --git a/website/themes/hsh/layouts/404.html b/website/themes/hsh/layouts/404.html new file mode 100644 index 0000000..06b3561 --- /dev/null +++ b/website/themes/hsh/layouts/404.html @@ -0,0 +1,7 @@ +{{ define "main"}} +
+
+

Go Home

+
+
+{{ end }} diff --git a/website/themes/hsh/layouts/_default/_markup/render-heading.html b/website/themes/hsh/layouts/_default/_markup/render-heading.html new file mode 100644 index 0000000..6ea5346 --- /dev/null +++ b/website/themes/hsh/layouts/_default/_markup/render-heading.html @@ -0,0 +1,6 @@ + + {{ .Text | safeHTML }} + +{{ if eq .Text ""}} +
+{{ end }} diff --git a/website/themes/hsh/layouts/_default/_markup/render-link.html b/website/themes/hsh/layouts/_default/_markup/render-link.html new file mode 100644 index 0000000..9c2a95e --- /dev/null +++ b/website/themes/hsh/layouts/_default/_markup/render-link.html @@ -0,0 +1,4 @@ + + {{ .Text | safeHTML }} + + diff --git a/website/themes/hsh/layouts/_default/baseof.html b/website/themes/hsh/layouts/_default/baseof.html new file mode 100644 index 0000000..dad9ef8 --- /dev/null +++ b/website/themes/hsh/layouts/_default/baseof.html @@ -0,0 +1,21 @@ + + + {{- partial "head.html" . -}} + + + + + + + + + + + + + + {{- partial "header.html" . -}} + {{- block "main" . }}{{- end }} + {{- partial "footer.html" . -}} + + diff --git a/website/themes/hsh/layouts/_default/doc.html b/website/themes/hsh/layouts/_default/doc.html new file mode 100644 index 0000000..8fc5958 --- /dev/null +++ b/website/themes/hsh/layouts/_default/doc.html @@ -0,0 +1,53 @@ +{{ define "main" }} +
+
+
+ +
+
+
+
+

{{ .Title }}

+

+ {{ $date := .Date.UTC.Format "Jan 2, 2006" }} + {{ $lastmod := .Lastmod.UTC.Format "Jan 2, 2006" }} + {{ if and (ne $lastmod $date) (gt .Lastmod .Date) }} + Last updated {{ $lastmod }}
+ {{ end }} + + {{ if .Description }} + {{ .Description }}
+ {{ end}} +

+ {{.Content}} +
+ + +
+
+{{ end }} + diff --git a/website/themes/hsh/layouts/_default/list.html b/website/themes/hsh/layouts/_default/list.html new file mode 100644 index 0000000..e69de29 diff --git a/website/themes/hsh/layouts/_default/page.html b/website/themes/hsh/layouts/_default/page.html new file mode 100644 index 0000000..69aaf99 --- /dev/null +++ b/website/themes/hsh/layouts/_default/page.html @@ -0,0 +1,7 @@ +{{ define "main" }} +
+
+ {{.Content}} +
+
+{{ end }} diff --git a/website/themes/hsh/layouts/_default/single.html b/website/themes/hsh/layouts/_default/single.html new file mode 100644 index 0000000..0ac0e37 --- /dev/null +++ b/website/themes/hsh/layouts/_default/single.html @@ -0,0 +1,8 @@ +{{ define "main" }} +
+
+

{{ .Title }}

+ {{.Content}} +
+
+{{ end }} diff --git a/website/themes/hsh/layouts/index.html b/website/themes/hsh/layouts/index.html new file mode 100644 index 0000000..a9f64d2 --- /dev/null +++ b/website/themes/hsh/layouts/index.html @@ -0,0 +1,6 @@ +{{ define "main" }} +
+ {{.Content}} +
+{{ end }} + diff --git a/website/themes/hsh/layouts/partials/footer.html b/website/themes/hsh/layouts/partials/footer.html new file mode 100644 index 0000000..15aa193 --- /dev/null +++ b/website/themes/hsh/layouts/partials/footer.html @@ -0,0 +1,32 @@ + diff --git a/website/themes/hsh/layouts/partials/head.html b/website/themes/hsh/layouts/partials/head.html new file mode 100644 index 0000000..3556074 --- /dev/null +++ b/website/themes/hsh/layouts/partials/head.html @@ -0,0 +1,26 @@ + + {{ $title := print .Title " — " .Site.Title }} + {{ if .IsHome }}{{ $title = .Site.Title }}{{ end }} + {{ $title }} + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/themes/hsh/layouts/partials/header.html b/website/themes/hsh/layouts/partials/header.html new file mode 100644 index 0000000..281b602 --- /dev/null +++ b/website/themes/hsh/layouts/partials/header.html @@ -0,0 +1,25 @@ +
+ +
diff --git a/website/themes/hsh/layouts/shortcodes/warning.html b/website/themes/hsh/layouts/shortcodes/warning.html new file mode 100644 index 0000000..b217b57 --- /dev/null +++ b/website/themes/hsh/layouts/shortcodes/warning.html @@ -0,0 +1,6 @@ + diff --git a/website/themes/hsh/theme.toml b/website/themes/hsh/theme.toml new file mode 100644 index 0000000..a567739 --- /dev/null +++ b/website/themes/hsh/theme.toml @@ -0,0 +1,21 @@ +# theme.toml template for a Hugo theme +# See https://github.com/gohugoio/hugoThemes#themetoml for an example + +name = "Hsh" +license = "MIT" +licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE" +description = "" +homepage = "http://example.com/" +tags = [] +features = [] +min_version = "0.41.0" + +[author] + name = "" + homepage = "" + +# If porting an existing theme +[original] + name = "" + homepage = "" + repo = ""