diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d524457..2171249 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,10 +9,19 @@ jobs: gen: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 - uses: actions/setup-go@v5 - - name: Run docgen + - name: Download Task + run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d' + - name: Build + run: ./bin/task + - name: Run docgen (go-written) run: go run cmd/docgen/docgen.go + - name: Run docgen (lua-written) + run: ./hilbish cmd/docgen/docgen.lua - name: Commit new docs uses: stefanzweifel/git-auto-commit-action@v4 with: diff --git a/cmd/docgen/docgen.go b/cmd/docgen/docgen.go index bf8fd1b..4743dea 100644 --- a/cmd/docgen/docgen.go +++ b/cmd/docgen/docgen.go @@ -299,7 +299,25 @@ start: func main() { fset := token.NewFileSet() os.Mkdir("docs", 0777) + os.RemoveAll("docs/api") os.Mkdir("docs/api", 0777) + + f, err := os.Create("docs/api/_index.md") + if err != nil { + panic(err) + } + f.WriteString(`--- +title: API +layout: doc +weight: -100 +menu: docs +--- + +Welcome to the API documentation for Hilbish. This documents Lua functions +provided by Hilbish. +`) + f.Close() + os.Mkdir("emmyLuaDocs", 0777) dirs := []string{"./"} diff --git a/cmd/docgen/docgen.lua b/cmd/docgen/docgen.lua index 207357a..e1e57d6 100644 --- a/cmd/docgen/docgen.lua +++ b/cmd/docgen/docgen.lua @@ -1,7 +1,9 @@ local fs = require 'fs' local emmyPattern = '^%-%-%- (.+)' -local modpattern = '^%-+ @module (%w+)' +local emmyPattern2 = '^%-%- (.+)' +local modpattern = '^%-+ @module (.+)' local pieces = {} +local descriptions = {} local files = fs.readdir 'nature' for _, fname in ipairs(files) do @@ -15,16 +17,24 @@ for _, fname in ipairs(files) do print(fname, mod) pieces[mod] = {} + descriptions[mod] = {} local docPiece = {} local lines = {} local lineno = 0 + local doingDescription = true + for line in f:lines() do lineno = lineno + 1 lines[lineno] = line if line == header then goto continue2 end - if not line:match(emmyPattern) then + if line:match(emmyPattern) or line:match(emmyPattern2) then + if doingDescription then + table.insert(descriptions[mod], line:match(emmyPattern) or line:match(emmyPattern2)) + end + else + doingDescription = false if line:match '^function' then local pattern = (string.format('^function %s%%.', mod) .. '(%w+)') local funcName = line:match(pattern) @@ -49,10 +59,14 @@ for _, fname in ipairs(files) do if emmy then if emmy == 'param' then + print('bruh', emmythings[1], emmythings[2]) table.insert(dps.params, 1, { name = emmythings[1], - type = emmythings[2] + type = emmythings[2], + -- the +1 accounts for space. + description = table.concat(emmythings, ' '):sub(emmythings[1]:len() + 1 + emmythings[2]:len() + 1) }) + print(table.concat(emmythings, '/')) end else table.insert(dps.description, 1, docline) @@ -81,30 +95,79 @@ description: %s layout: doc menu: docs: - parent: "Nature" + parent: "%s" --- ]] for iface, dps in pairs(pieces) do local mod = iface:match '(%w+)%.' or 'nature' - local path = string.format('docs/%s/%s.md', mod, iface) + local docParent = 'Nature' + + path = string.format('docs/%s/%s.md', mod, iface) + if mod ~= 'nature' then + docParent = "API" + path = string.format('docs/api/%s/%s.md', mod, iface) + end + fs.mkdir(fs.dir(path), true) - local f = io.open(path, 'w') - f:write(string.format(header, 'Module', iface, 'No description.')) + + local exists = pcall(fs.stat, path) + local newOrNotNature = exists and mod ~= 'nature' + + local f = io.open(path, newOrNotNature and 'r+' or 'w+') + local tocPos + if not newOrNotNature then + f:write(string.format(header, 'Module', iface, (descriptions[iface] and #descriptions[iface] > 0) and descriptions[iface][1] or 'No description.', docParent)) + if descriptions[iface] and #descriptions[iface] > 0 then + table.remove(descriptions[iface], 1) + f:write(string.format('\n## Introduction\n%s\n\n', table.concat(descriptions[iface], '\n'))) + f:write('## Functions\n') + f:write([[||| +|----|----| +]]) + tocPos = f:seek() + end + end print(f) - print(mod, path) + print('mod and path:', mod, path) + + local tocSearch = false + for line in f:lines() do + if line:match '^## Functions' then + tocSearch = true + end + if tocSearch and line == '' then + tocSearch = false + tocPos = f:seek() - 1 + end + end for func, docs in pairs(dps) do - f:write(string.format('
\n
', func)) local sig = string.format('%s.%s(', iface, func) + local params = '' for idx, param in ipairs(docs.params) do - sig = sig .. ((param.name:gsub('%?$', ''))) - if idx ~= #docs.params then sig = sig .. ', ' end + sig = sig .. param.name:gsub('%?$', '') + params = params .. param.name:gsub('%?$', '') + if idx ~= #docs.params then + sig = sig .. ', ' + params = params .. ', ' + end end sig = sig .. ')' - f:write(string.format([[ + + if tocPos then + f:seek('set', tocPos) + local contents = f:read '*a' + f:seek('set', tocPos) + local tocLine = string.format('|%s|%s|\n', func, string.format('%s(%s)', func, params), docs.description[1]) + f:write(tocLine .. contents) + f:seek 'end' + end + + f:write(string.format('
\n
\n', func)) + f:write(string.format([[

%s @@ -120,7 +183,8 @@ for iface, dps in pairs(pieces) do f:write 'This function has no parameters. \n' end for _, param in ipairs(docs.params) do - f:write(string.format('`%s` **`%s`**\n', param.name:gsub('%?$', ''), param.type)) + f:write(string.format('`%s` **`%s`** \n', param.name:gsub('%?$', ''), param.type)) + f:write(string.format('%s\n\n', param.description)) end --[[ local params = table.filter(docs, function(t) diff --git a/docs/getting-started.md b/docs/getting-started.md index de7607e..b5c3148 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -53,8 +53,39 @@ 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. +Now we can get to customization! + +If we closely examine a small snippet of the default config: +```lua +-- Default Hilbish config +-- .. with some omitted code .. -- + +local function doPrompt(fail) + hilbish.prompt(lunacolors.format( + '{blue}%u {cyan}%d ' .. (fail and '{red}' or '{green}') .. '∆ ' + )) +end + +doPrompt() + +bait.catch('command.exit', function(code) + doPrompt(code ~= 0) +end) +``` + +We see a whopping **three** Hilbish libraries being used in this part of code. +First is of course, named after the shell itself, [`hilbish`](../api/hilbish). This is kind of a +"catch-all" namespace for functions that directly related to shell functionality/settings. + +And as we can see, the [hilbish.prompt](../api/hilbish/#prompt) function is used +to change our prompt. Change our prompt to what, exactly? + +The doc for the function states that the verbs `%u` and `%d`are used for username and current directory +of the shell, respectively. + +We wrap this in the [`lunacolors.format`](../lunacolors) function, to give +our prompt some nice color. + +But you might have also noticed that this is in the `doPrompt` function, which is called once, +and then used again in a [bait](../api/bait) hook. Specifically, the `command.exit` hook, +which is called after a command exits, so when it finishes running. diff --git a/docs/nature/dirs.md b/docs/nature/dirs.md index 3c707e6..e49247c 100644 --- a/docs/nature/dirs.md +++ b/docs/nature/dirs.md @@ -1,14 +1,27 @@ --- title: Module dirs -description: No description. +description: internal directory management layout: doc menu: docs: parent: "Nature" --- + +## Introduction +The dirs module defines a small set of functions to store and manage +directories. + +## Functions +||| +|----|----| +|recent(idx)|Get entry from recent directories list based on index.| +|pop(num)|Remove the specified amount of dirs from the recent directories list.| +|peak(num)|Look at `num` amount of recent directories, starting from the latest.| +|push(dir)|Add `dir` to the recent directories list.| +|setOld(d)|Sets the old directory string.|
-
+
-
+

-dirs.push() +dirs.push(dir)

-Add `d` to the recent directories list. +Add `dir` to the recent directories list. #### Parameters -This function has no parameters. +`dir` **`string`** + +

-
+
-
+
-
+ diff --git a/docs/nature/doc.md b/docs/nature/doc.md new file mode 100644 index 0000000..6a2ca48 --- /dev/null +++ b/docs/nature/doc.md @@ -0,0 +1,76 @@ +--- +title: Module doc +description: command-line doc rendering +layout: doc +menu: + docs: + parent: "Nature" +--- + + +## Introduction +The doc module contains a small set of functions +used by the Greenhouse pager to render parts of the documentation pages. +This is only documented for the sake of it. It's only intended use +is by the Greenhouse pager. + +## Functions +||| +|----|----| +|renderCodeBlock(text)|Assembles and renders a code block. This returns| +|highlight(text)|Performs basic Lua code highlighting.| +|renderInfoBlock(type, text)|Renders an info block. An info block is a block of text with| +
+
+

+doc.renderInfoBlock(type, text) + + + +

+ +Renders an info block. An info block is a block of text with +an icon and styled text block. +#### Parameters +`type` **`string`** + Type of info block. The only one specially styled is the `warning`. + +`text` **`string`** + + +
+ +
+
+

+doc.highlight(text) + + + +

+ +Performs basic Lua code highlighting. +#### Parameters +`text` **`string`** + Code/text to do highlighting on. + +
+ +
+
+

+doc.renderCodeBlock(text) + + + +

+ +Assembles and renders a code block. This returns +the supplied text based on the number of command line columns, +and styles it to resemble a code block. +#### Parameters +`text` **`string`** + + +
+ diff --git a/lua.go b/lua.go index 00398ea..859a39d 100644 --- a/lua.go +++ b/lua.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "path/filepath" "hilbish/util" "hilbish/golibs/bait" @@ -63,7 +64,7 @@ func luaInit() { err1 := util.DoFile(l, "nature/init.lua") if err1 != nil { - err2 := util.DoFile(l, preloadPath) + err2 := util.DoFile(l, filepath.Join(dataDir, "nature", "init.lua")) if err2 != nil { fmt.Fprintln(os.Stderr, "Missing nature module, some functionality and builtins will be missing.") fmt.Fprintln(os.Stderr, "local error:", err1) diff --git a/main.go b/main.go index c26a55e..77b1847 100644 --- a/main.go +++ b/main.go @@ -40,11 +40,24 @@ var ( ) func main() { + if runtime.GOOS == "linux" { + // dataDir should only be empty on linux to allow XDG_DATA_DIRS searching. + // but since it might be set on some distros (nixos) we should still check if its really is empty. + if dataDir == "" { + searchableDirs := getenv("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/") + dataDir = "." + for _, path := range strings.Split(searchableDirs, ":") { + _, err := os.Stat(filepath.Join(path, "hilbish", ".hilbishrc.lua")) + if err == nil { + dataDir = filepath.Join(path, "hilbish") + break + } + } + } + } + curuser, _ = user.Current() - homedir := curuser.HomeDir confDir, _ = os.UserConfigDir() - preloadPath = strings.Replace(preloadPath, "~", homedir, 1) - sampleConfPath = strings.Replace(sampleConfPath, "~", homedir, 1) // i honestly dont know what directories to use for this switch runtime.GOOS { @@ -138,10 +151,11 @@ func main() { confpath := ".hilbishrc.lua" if err != nil { // If it wasnt found, go to the real sample conf - _, err = os.ReadFile(sampleConfPath) - confpath = sampleConfPath + sampleConfigPath := filepath.Join(dataDir, ".hilbishrc.lua") + _, err = os.ReadFile(sampleConfigPath) + confpath = sampleConfigPath if err != nil { - fmt.Println("could not find .hilbishrc.lua or", sampleConfPath) + fmt.Println("could not find .hilbishrc.lua or", sampleConfigPath) return } } diff --git a/nature/dirs.lua b/nature/dirs.lua index 2efad63..0576f8a 100644 --- a/nature/dirs.lua +++ b/nature/dirs.lua @@ -1,11 +1,13 @@ -- @module dirs +-- internal directory management +-- The dirs module defines a small set of functions to store and manage +-- directories. local bait = require 'bait' local fs = require 'fs' local dirs = {} ---- Last (current working) directory. Separate from recentDirs mainly for ---- easier use. +--- Last (current working) directory. Separate from recentDirs mainly for easier use. dirs.old = '' --- Table of recent directories. For use, look at public functions. dirs.recentDirs = {} @@ -36,13 +38,15 @@ function dirRecents(num, remove) end --- Look at `num` amount of recent directories, starting from the latest. +--- This returns a table of recent directories, up to the `num` amount. -- @param num? number function dirs.peak(num) return dirRecents(num) end ---- Add `d` to the recent directories list. -function dirs.push(d) +--- Add `dir` to the recent directories list. +--- @param dir string +function dirs.push(dir) dirs.recentDirs[dirs.recentSize + 1] = nil if dirs.recentDirs[#dirs.recentDirs - 1] ~= d then ok, d = pcall(fs.abs, d) diff --git a/nature/doc.lua b/nature/doc.lua index f0b7e11..a21312a 100644 --- a/nature/doc.lua +++ b/nature/doc.lua @@ -1,13 +1,25 @@ +-- @module doc +-- command-line doc rendering +-- The doc module contains a small set of functions +-- used by the Greenhouse pager to render parts of the documentation pages. +-- This is only documented for the sake of it. It's only intended use +-- is by the Greenhouse pager. local lunacolors = require 'lunacolors' -local M = {} +local doc = {} -function M.highlight(text) +--- Performs basic Lua code highlighting. +--- @param text string Code/text to do highlighting on. +function doc.highlight(text) return text:gsub('\'.-\'', lunacolors.yellow) --:gsub('%-%- .-', lunacolors.black) end -function M.renderCodeBlock(text) +--- Assembles and renders a code block. This returns +--- the supplied text based on the number of command line columns, +--- and styles it to resemble a code block. +--- @param text string +function doc.renderCodeBlock(text) local longest = 0 local lines = string.split(text:gsub('\t', ' '), '\n') @@ -17,14 +29,18 @@ function M.renderCodeBlock(text) end for i, line in ipairs(lines) do - lines[i] = lunacolors.format('{greyBg}' .. ' ' .. M.highlight(line:sub(0, longest)) + lines[i] = lunacolors.format('{greyBg}' .. ' ' .. doc.highlight(line:sub(0, longest)) .. string.rep(' ', longest - line:len()) .. ' ') end return '\n' .. lunacolors.format('{greyBg}' .. table.concat(lines, '\n')) .. '\n' end -function M.renderInfoBlock(type, text) +--- Renders an info block. An info block is a block of text with +--- an icon and styled text block. +--- @param type string Type of info block. The only one specially styled is the `warning`. +--- @param text string +function doc.renderInfoBlock(type, text) local longest = 0 local lines = string.split(text:gsub('\t', ' '), '\n') @@ -34,7 +50,7 @@ function M.renderInfoBlock(type, text) end for i, line in ipairs(lines) do - lines[i] = ' ' .. M.highlight(line:sub(0, longest)) + lines[i] = ' ' .. doc.highlight(line:sub(0, longest)) .. string.rep(' ', longest - line:len()) .. ' ' end @@ -44,4 +60,4 @@ function M.renderInfoBlock(type, text) end return '\n' .. heading .. '\n' .. lunacolors.format('{greyBg}' .. table.concat(lines, '\n')) .. '\n' end -return M +return doc diff --git a/nature/greenhouse/init.lua b/nature/greenhouse/init.lua index fe4c31c..2badfae 100644 --- a/nature/greenhouse/init.lua +++ b/nature/greenhouse/init.lua @@ -1,4 +1,5 @@ --- Greenhouse is a simple text scrolling handler for terminal programs. +-- @module greenhouse +-- Greenhouse is a simple text scrolling handler (pager) for terminal programs. -- The idea is that it can be set a region to do its scrolling and paging -- job and then the user can draw whatever outside it. -- This reduces code duplication for the message viewer diff --git a/nature/greenhouse/page.lua b/nature/greenhouse/page.lua index 51d1440..185ef61 100644 --- a/nature/greenhouse/page.lua +++ b/nature/greenhouse/page.lua @@ -1,3 +1,4 @@ +-- @module greenhouse.page local Object = require 'nature.object' local Page = Object:extend() @@ -10,6 +11,7 @@ function Page:new(title, text) self.children = {} end + function Page:setText(text) self.lines = string.split(text, '\n') end diff --git a/nature/hummingbird.lua b/nature/hummingbird.lua index 581e92c..88cb88f 100644 --- a/nature/hummingbird.lua +++ b/nature/hummingbird.lua @@ -1,3 +1,14 @@ +-- @module hilbish.messages +-- simplistic message passing +-- The messages interface defines a way for Hilbish-integrated commands, +-- user config and other tasks to send notifications to alert the user.z +-- The `hilbish.message` type is a table with the following keys: +-- `title` (string): A title for the message notification. +-- `text` (string): The contents of the message. +-- `channel` (string): States the origin of the message, `hilbish.*` is reserved for Hilbish tasks. +-- `summary` (string): A short summary of the `text`. +-- `icon` (string): Unicode (preferably standard emoji) icon for the message notification +-- `read` (boolean): Whether the full message has been read or not. local bait = require 'bait' local commander = require 'commander' local lunacolors = require 'lunacolors' @@ -44,24 +55,30 @@ function hilbish.messages.send(message) bait.throw('hilbish.notification', message) end +--- Marks a message at `idx` as read. +--- @param idx number function hilbish.messages.read(idx) local msg = M._messages[idx] - if msg then + if msg then M._messages[idx].read = true unread = unread - 1 end end -function hilbish.messages.readAll(idx) +--- Marks all messages as read. +function hilbish.messages.readAll() for _, msg in ipairs(hilbish.messages.all()) do hilbish.messages.read(msg.index) end end +--- Returns the amount of unread messages. function hilbish.messages.unreadCount() return unread end +--- Deletes the message at `idx`. +--- @param idx number function hilbish.messages.delete(idx) local msg = M._messages[idx] if not msg then @@ -71,12 +88,14 @@ function hilbish.messages.delete(idx) M._messages[idx] = nil end +--- Deletes all messages. function hilbish.messages.clear() for _, msg in ipairs(hilbish.messages.all()) do hilbish.messages.delete(msg.index) end end +--- Returns all messages. function hilbish.messages.all() return M._messages end diff --git a/nature/opts/motd.lua b/nature/opts/motd.lua index ca08142..064ef93 100644 --- a/nature/opts/motd.lua +++ b/nature/opts/motd.lua @@ -2,9 +2,7 @@ local bait = require 'bait' local lunacolors = require 'lunacolors' hilbish.motd = [[ -Wait ... {magenta}2.3{reset} is basically the same as {red}2.2?{reset} -Erm.. {blue}Ctrl-C works for Commanders,{reset} {cyan}and the sh runner has some fixes.{reset} -Just trust me bro, this is an important bug fix release. {red}- 🌺 sammyette{reset} +{magenta}Hilbish{reset} blooms in the {blue}midnight.{reset} ]] bait.catch('hilbish.init', function() diff --git a/nature/runner.lua b/nature/runner.lua index 6bb0b22..f854638 100644 --- a/nature/runner.lua +++ b/nature/runner.lua @@ -1,6 +1,5 @@ ---- hilbish.runner +-- @module hilbish.runner local snail = require 'snail' - local currentRunner = 'hybrid' local runners = {} @@ -8,7 +7,7 @@ local runners = {} hilbish = hilbish --- Get a runner by name. ---- @param name string +--- @param name string Name of the runner to retrieve. --- @return table function hilbish.runner.get(name) local r = runners[name] @@ -20,10 +19,10 @@ function hilbish.runner.get(name) return r end ---- Adds a runner to the table of available runners. If runner is a table, ---- it must have the run function in it. ---- @param name string ---- @param runner function | table +--- Adds a runner to the table of available runners. +--- If runner is a table, it must have the run function in it. +--- @param name string Name of the runner +--- @param runner function|table function hilbish.runner.add(name, runner) if type(name) ~= 'string' then error 'expected runner name to be a table' @@ -44,7 +43,9 @@ function hilbish.runner.add(name, runner) hilbish.runner.set(name, runner) end ---- Sets a runner by name. The runner table must have the run function in it. +--- *Sets* a runner by name. The difference between this function and +--- add, is set will *not* check if the named runner exists. +--- The runner table must have the run function in it. --- @param name string --- @param runner table function hilbish.runner.set(name, runner) @@ -55,11 +56,11 @@ function hilbish.runner.set(name, runner) runners[name] = runner end ---- Executes cmd with a runner. If runnerName isn't passed, it uses ---- the user's current runner. +--- Executes `cmd` with a runner. +--- If `runnerName` is not specified, it uses the default Hilbish runner. --- @param cmd string --- @param runnerName string? ---- @return string, number, string +--- @return table function hilbish.runner.exec(cmd, runnerName) if not runnerName then runnerName = currentRunner end @@ -68,7 +69,7 @@ function hilbish.runner.exec(cmd, runnerName) return r.run(cmd) end ---- Sets the current interactive/command line runner mode. +--- Sets Hilbish's runner mode by name. --- @param name string function hilbish.runner.setCurrent(name) local r = hilbish.runner.get(name) diff --git a/vars_darwin.go b/vars_darwin.go index 43215d5..be7a4c1 100644 --- a/vars_darwin.go +++ b/vars_darwin.go @@ -15,7 +15,5 @@ var ( .. hilbish.userDir.config .. '/hilbish/?/?.lua;' .. hilbish.userDir.config .. '/hilbish/?.lua'` dataDir = "/usr/local/share/hilbish" - preloadPath = dataDir + "/nature/init.lua" - sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config defaultConfDir = getenv("XDG_CONFIG_HOME", "~/.config") ) diff --git a/vars_unix.go b/vars_unix.go index f90fa55..6bf47f5 100644 --- a/vars_unix.go +++ b/vars_unix.go @@ -14,8 +14,6 @@ var ( .. hilbish.userDir.config .. '/hilbish/?/init.lua;' .. hilbish.userDir.config .. '/hilbish/?/?.lua;' .. hilbish.userDir.config .. '/hilbish/?.lua'` - dataDir = "/usr/local/share/hilbish" - preloadPath = dataDir + "/nature/init.lua" - sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config + dataDir = "" defaultConfDir = "" ) diff --git a/vars_windows.go b/vars_windows.go index f724fc2..4c46539 100644 --- a/vars_windows.go +++ b/vars_windows.go @@ -10,8 +10,6 @@ var ( .. hilbish.userDir.config .. '\\Hilbish\\libs\\?\\init.lua;' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?\\?.lua;' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?.lua;'` - dataDir = util.ExpandHome("~\\Appdata\\Roaming\\Hilbish") // ~ and \ gonna cry? - preloadPath = dataDir + "\\nature\\init.lua" - sampleConfPath = dataDir + "\\.hilbishrc.lua" // Path to default/sample config + dataDir = util.ExpandHome("~\\Appdata\\Roaming\\Hilbish") // ~ and \, gonna cry? defaultConfDir = "" )