From 9e596dc271d18b7f8be9b07c7bce2028357857d2 Mon Sep 17 00:00:00 2001 From: TorchedSammy <38820196+TorchedSammy@users.noreply.github.com> Date: Fri, 22 Apr 2022 23:56:57 -0400 Subject: [PATCH] refactor: (re)organize and change prelude path and structure prelude is no longer. it is now nature. organized the single file prelude into multiple source files and renamed it to nature. this is coming after thought that it can turn into a general hilbish lua core, with user facing modules as well. this introduces the `nature.dirs` module, to interact and get recently changed to directories and last/old cwd. --- Makefile | 2 +- lua.go | 2 +- nature/commands/cd.lua | 35 +++++ nature/commands/cdr.lua | 39 ++++++ nature/commands/doc.lua | 93 +++++++++++++ nature/commands/exit.lua | 7 + nature/commands/guide.lua | 54 ++++++++ nature/commands/init.lua | 6 + nature/dirs.lua | 75 +++++++++++ nature/hooks.lua | 11 ++ nature/init.lua | 44 +++++++ prelude/init.lua | 265 -------------------------------------- vars_darwin.go | 2 +- vars_linux.go | 2 +- vars_windows.go | 2 +- 15 files changed, 369 insertions(+), 270 deletions(-) create mode 100644 nature/commands/cd.lua create mode 100644 nature/commands/cdr.lua create mode 100644 nature/commands/doc.lua create mode 100644 nature/commands/exit.lua create mode 100644 nature/commands/guide.lua create mode 100644 nature/commands/init.lua create mode 100644 nature/dirs.lua create mode 100644 nature/hooks.lua create mode 100644 nature/init.lua delete mode 100644 prelude/init.lua diff --git a/Makefile b/Makefile index 660bc58..a0c6580 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ build: install: install -v -d "$(DESTDIR)$(BINDIR)/" && install -m 0755 -v hilbish "$(DESTDIR)$(BINDIR)/hilbish" mkdir -p "$(DESTDIR)$(LIBDIR)" - cp -r libs docs emmyLuaDocs prelude .hilbishrc.lua "$(DESTDIR)$(LIBDIR)" + cp -r libs docs emmyLuaDocs nature .hilbishrc.lua "$(DESTDIR)$(LIBDIR)" grep -qxF "$(DESTDIR)$(BINDIR)/hilbish" /etc/shells || echo "$(DESTDIR)$(BINDIR)/hilbish" >> /etc/shells uninstall: diff --git a/lua.go b/lua.go index 3b925c6..838ce8a 100644 --- a/lua.go +++ b/lua.go @@ -54,7 +54,7 @@ func luaInit() { fmt.Fprintln(os.Stderr, "Could not add preload paths! Libraries will be missing. This shouldn't happen.") } - err = util.DoFile(l, "prelude/init.lua") + err = util.DoFile(l, "nature/init.lua") if err != nil { err = util.DoFile(l, preloadPath) if err != nil { diff --git a/nature/commands/cd.lua b/nature/commands/cd.lua new file mode 100644 index 0000000..509e774 --- /dev/null +++ b/nature/commands/cd.lua @@ -0,0 +1,35 @@ +local bait = require 'bait' +local commander = require 'commander' +local fs = require 'fs' +local dirs = require 'nature.dirs' + +dirs.old = hilbish.cwd() +commander.register('cd', function (args) + if #args > 1 then + print("cd: too many arguments") + return 1 + elseif #args > 0 then + local path = args[1]:gsub('$%$','\0'):gsub('${([%w_]+)}', os.getenv) + :gsub('$([%w_]+)', os.getenv):gsub('%z','$'):gsub('^%s*(.-)%s*$', '%1') + + if path == '-' then + path = dirs.old + print(path) + end + dirs.setOld(hilbish.cwd()) + dirs.push(path) + + local ok, err = pcall(function() fs.cd(path) end) + if not ok then + print(err) + return 1 + end + bait.throw('cd', path) + + return + end + fs.cd(hilbish.home) + bait.throw('cd', hilbish.home) + + dirs.addRecent(hilbish.home) +end) diff --git a/nature/commands/cdr.lua b/nature/commands/cdr.lua new file mode 100644 index 0000000..0438e6f --- /dev/null +++ b/nature/commands/cdr.lua @@ -0,0 +1,39 @@ +local commander = require 'commander' +local fs = require 'fs' +local lunacolors = require 'lunacolors' +local dirs = require 'nature.dirs' + +commander.register('cdr', function(args) + if not args[1] then + print(lunacolors.format [[ +cdr: change directory to one which has been recently visied + +usage: cdr + +to get a list of recent directories, use {green}{underline}cdr list{reset}]]) + return + end + + if args[1] == 'list' then + local recentDirs = dirs.recentDirs + if #recentDirs == 0 then + print 'No directories have been visited.' + return 1 + end + print(table.concat(recentDirs, '\n')) + return + end + + local index = tonumber(args[1]) + if not index then + print(string.format('Received %s as index, which isn\'t a number.', index)) + return 1 + end + + if not dirs.recent(index) then + print(string.format('No recent directory found at index %s.', index)) + return 1 + end + + fs.cd(dirs.recent(index)) +end) diff --git a/nature/commands/doc.lua b/nature/commands/doc.lua new file mode 100644 index 0000000..34e81ae --- /dev/null +++ b/nature/commands/doc.lua @@ -0,0 +1,93 @@ +local commander = require 'commander' +local fs = require 'fs' +local lunacolors = require 'lunacolors' + +commander.register('doc', function(args) + local moddocPath = hilbish.dataDir .. '/docs/' + local modDocFormat = [[ +%s +%s +# Functions +]] + + if #args > 0 then + local mod = args[1] + + local f = io.open(moddocPath .. mod .. '.txt', 'rb') + local funcdocs = nil + if not f then + -- assume subdir + -- dataDir/docs//.txt + moddocPath = moddocPath .. mod .. '/' + local subdocName = args[2] + if not subdocName then + subdocName = 'index' + end + f = io.open(moddocPath .. subdocName .. '.txt', '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 subdocs = table.map(moddocs, function(fname) + return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.txt', ''))) + end) + if subdocName == 'index' then + funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ') + end + end + + if not funcdocs then + funcdocs = f:read '*a' + end + local desc = '' + local ok = pcall(require, mod) + local backtickOccurence = 0 + local formattedFuncs = lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function() + backtickOccurence = backtickOccurence + 1 + if backtickOccurence % 2 == 0 then + return '{reset}' + else + return '{underline}{green}' + end + end)) + + if ok then + local props = {} + local propstr = '' + local modDesc = '' + local modmt = getmetatable(require(mod)) + 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 + print(desc .. formattedFuncs) + f:close() + + return + end + local modules = table.map(fs.readdir(moddocPath), function(f) + return lunacolors.underline(lunacolors.blue(string.gsub(f, '.txt', ''))) + end) + + io.write [[ +Welcome to Hilbish's doc tool! Here you can find documentation for builtin +functions and other things. + +Usage: doc
[subdoc] +A section is a module or a literal section and a subdoc is a subsection for it. + +Available sections: ]] + io.flush() + + print(table.concat(modules, ', ')) +end) diff --git a/nature/commands/exit.lua b/nature/commands/exit.lua new file mode 100644 index 0000000..421730c --- /dev/null +++ b/nature/commands/exit.lua @@ -0,0 +1,7 @@ +local bait = require 'bait' +local commander = require 'commander' + +commander.register('exit', function() + bait.throw('hilbish.exit') + os.exit(0) +end) diff --git a/nature/commands/guide.lua b/nature/commands/guide.lua new file mode 100644 index 0000000..1c1e346 --- /dev/null +++ b/nature/commands/guide.lua @@ -0,0 +1,54 @@ +local ansikit = require 'ansikit' +local commander = require 'commander' + +local helpTexts = { +[[ +Hello there! Welcome to Hilbish, the comfy and nice little shell for +Lua users and fans. Hilbish is configured with Lua, and its +scripts are also in Lua. It also runs both Lua and shell script when +interactive (aka normal usage). +]], +[[ +What does that mean for you, the user? It means that if you prefer to +use Lua for scripting instead of shell script but still have ordinary +shell usage for interactive use. +]], +[[ +If this is your first time using Hilbish and Lua, check out the +Programming in Lua book here: https://www.lua.org/pil +After (or if you already know Lua) check out the doc command. +It is an in shell tool for documentation about Hilbish provided +functions and modules. +]], +[[ +If you've updated from a pre-1.0 version (0.7.1 as an example) +you'll want to move your config from ~/.hilbishrc.lua to +]] .. +hilbish.userDir.config .. '/hilbish/init.lua' .. +[[ + +and also change all global functions (prompt, alias) to be +in the hilbish module (hilbish.prompt, hilbish.alias as examples). + +And if this is your first time (most likely), you can copy a config +from ]] .. hilbish.dataDir, +[[ +Since 1.0 is a big release, you'll want to check the changelog +at https://github.com/Rosettea/Hilbish/releases/tag/v1.0.0 +to find more breaking changes. +]] +} +commander.register('guide', function() + ansikit.clear() + ansikit.cursorTo(0, 0) + for _, text in ipairs(helpTexts) do + print(text) + local out = hilbish.read('Hit enter to continue ') + ansikit.clear() + ansikit.cursorTo(0, 0) + if not out then + return + end + end + print 'Hope you enjoy using Hilbish!' +end) diff --git a/nature/commands/init.lua b/nature/commands/init.lua new file mode 100644 index 0000000..e824c7c --- /dev/null +++ b/nature/commands/init.lua @@ -0,0 +1,6 @@ +-- Add command builtins +require 'nature.commands.cd' +require 'nature.commands.cdr' +require 'nature.commands.doc' +require 'nature.commands.exit' +require 'nature.commands.guide' diff --git a/nature/dirs.lua b/nature/dirs.lua new file mode 100644 index 0000000..5b7ec86 --- /dev/null +++ b/nature/dirs.lua @@ -0,0 +1,75 @@ +local fs = require 'fs' + +local dirs = {} + +--- 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 = {} +--- Size of the recentDirs table. +dirs.recentSize = 10 + +--- Get (and remove) a `num` of entries from recent directories. +--- @param num number +--- @param remove boolean Whether to remove items +function dirRecents(num, remove) + num = num or 1 + local entries = {} + + if #dirs.recentDirs ~= 0 then + for i = 1, num do + local idx = remove and 1 or i + if not dirs.recentDirs[idx] then break end + table.insert(entries, dirs.recentDirs[idx]) + if remove then table.remove(dirs.recentDirs, 1) end + end + end + + if #entries == 1 then + return entries[1] + end + + return entries +end + +--- Look at `num` amount of recent directories, starting from the latest. +--- @param num? number +function dirs.peak(num) + return dirRecents(num) +end + +--- Add `d` to the recent directories. +function dirs.push(d) + dirs.recentDirs[dirs.recentSize + 1] = nil + if dirs.recentDirs[#dirs.recentDirs - 1] ~= d then + ok, d = pcall(fs.abs, d) + assert(ok, 'could not turn "' .. d .. '"into an absolute path') + + table.insert(dirs.recentDirs, 1, d) + end +end + +--- Remove `num` amount of dirs from the recent directories. +--- @param num number +function dirs.pop(num) + return dirRecents(num, true) +end + +--- Get entry from recent directories. +--- @param idx number +function dirs.recent(idx) + return dirs.recentDirs[idx] +end + +--- Sets the old directory. +--- @param d string +function dirs.setOld(d) + ok, d = pcall(fs.abs, d) + assert(ok, 'could not turn "' .. d .. '"into an absolute path') + + os.setenv('OLDPWD', d) + dirs.old = d +end + +return dirs diff --git a/nature/hooks.lua b/nature/hooks.lua new file mode 100644 index 0000000..a9bd0b1 --- /dev/null +++ b/nature/hooks.lua @@ -0,0 +1,11 @@ +local bait = require 'bait' + +-- Hook handles +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/init.lua b/nature/init.lua new file mode 100644 index 0000000..5e07298 --- /dev/null +++ b/nature/init.lua @@ -0,0 +1,44 @@ +-- Prelude initializes everything else for our shell +local _ = require 'succulent' -- Function additions + +package.path = package.path .. ';' .. hilbish.dataDir .. '/?/init.lua' +.. ';' .. hilbish.dataDir .. '/?/?.lua' + +require 'nature.hooks' +require 'nature.commands' + +local shlvl = tonumber(os.getenv 'SHLVL') +if shlvl ~= nil then + os.setenv('SHLVL', tostring(shlvl + 1)) +else + os.setenv('SHLVL', '0') +end + +do + local virt_G = { } + + setmetatable(_G, { + __index = function (_, key) + local got_virt = virt_G[key] + if got_virt ~= nil then + return got_virt + end + + virt_G[key] = os.getenv(key) + return virt_G[key] + end, + + __newindex = function (_, key, value) + if type(value) == 'string' then + os.setenv(key, value) + virt_G[key] = value + else + if type(virt_G[key]) == 'string' then + os.setenv(key, '') + end + virt_G[key] = value + end + end, + }) +end + diff --git a/prelude/init.lua b/prelude/init.lua deleted file mode 100644 index 21467b0..0000000 --- a/prelude/init.lua +++ /dev/null @@ -1,265 +0,0 @@ --- The preload file initializes everything else for our shell -local ansikit = require 'ansikit' -local bait = require 'bait' -local commander = require 'commander' -local fs = require 'fs' -local lunacolors = require 'lunacolors' -local _ = require 'succulent' -- Function additions -local oldDir = hilbish.cwd() - -local shlvl = tonumber(os.getenv 'SHLVL') -if shlvl ~= nil then os.setenv('SHLVL', tostring(shlvl + 1)) else os.setenv('SHLVL', '0') end - --- Builtins -local recentDirs = {} -commander.register('cd', function (args) - if #args > 0 then - local path = table.concat(args, ' '):gsub('$%$','\0'):gsub('${([%w_]+)}', os.getenv) - :gsub('$([%w_]+)', os.getenv):gsub('%z','$'):gsub('^%s*(.-)%s*$', '%1') - - if path == '-' then - path = oldDir - print(path) - end - oldDir = hilbish.cwd() - - local ok, err = pcall(function() fs.cd(path) end) - if not ok then - print(err:sub(17)) - return 1 - end - bait.throw('cd', path) - - -- add to table of recent dirs - recentDirs[11] = nil - if recentDirs[#recentDirs - 1] ~= path then - table.insert(recentDirs, 1, path) - end - - return - end - fs.cd(hilbish.home) - bait.throw('cd', hilbish.home) - - table.insert(recentDirs, 1, hilbish.home) - recentDirs[11] = nil -end) - -commander.register('exit', function() - bait.throw('hilbish.exit') - os.exit(0) -end) - -commander.register('doc', function(args) - local moddocPath = hilbish.dataDir .. '/docs/' - local modDocFormat = [[ -%s -%s -# Functions -]] - - if #args > 0 then - local mod = args[1] - - local f = io.open(moddocPath .. mod .. '.txt', 'rb') - local funcdocs = nil - if not f then - -- assume subdir - -- dataDir/docs//.txt - moddocPath = moddocPath .. mod .. '/' - local subdocName = args[2] - if not subdocName then - subdocName = 'index' - end - f = io.open(moddocPath .. subdocName .. '.txt', '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 subdocs = table.map(moddocs, function(fname) - return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.txt', ''))) - end) - if subdocName == 'index' then - funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ') - end - end - - if not funcdocs then - funcdocs = f:read '*a' - end - local desc = '' - local ok = pcall(require, mod) - local backtickOccurence = 0 - local formattedFuncs = lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function() - backtickOccurence = backtickOccurence + 1 - if backtickOccurence % 2 == 0 then - return '{reset}' - else - return '{underline}{green}' - end - end)) - - if ok then - local props = {} - local propstr = '' - local modDesc = '' - local modmt = getmetatable(require(mod)) - 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 - print(desc .. formattedFuncs) - f:close() - - return - end - local modules = table.map(fs.readdir(moddocPath), function(f) - return lunacolors.underline(lunacolors.blue(string.gsub(f, '.txt', ''))) - end) - - io.write [[ -Welcome to Hilbish's doc tool! Here you can find documentation for builtin -functions and other things. - -Usage: doc
[subdoc] -A section is a module or a literal section and a subdoc is a subsection for it. - -Available sections: ]] - io.flush() - - print(table.concat(modules, ', ')) -end) - -local helpTexts = { -[[ -Hello there! Welcome to Hilbish, the comfy and nice little shell for -Lua users and fans. Hilbish is configured with Lua, and its -scripts are also in Lua. It also runs both Lua and shell script when -interactive (aka normal usage). -]], -[[ -What does that mean for you, the user? It means that if you prefer to -use Lua for scripting instead of shell script but still have ordinary -shell usage for interactive use. -]], -[[ -If this is your first time using Hilbish and Lua, check out the -Programming in Lua book here: https://www.lua.org/pil -After (or if you already know Lua) check out the doc command. -It is an in shell tool for documentation about Hilbish provided -functions and modules. -]], -[[ -If you've updated from a pre-1.0 version (0.7.1 as an example) -you'll want to move your config from ~/.hilbishrc.lua to -]] .. -hilbish.userDir.config .. '/hilbish/init.lua' .. -[[ - -and also change all global functions (prompt, alias) to be -in the hilbish module (hilbish.prompt, hilbish.alias as examples). - -And if this is your first time (most likely), you can copy a config -from ]] .. hilbish.dataDir, -[[ -Since 1.0 is a big release, you'll want to check the changelog -at https://github.com/Rosettea/Hilbish/releases/tag/v1.0.0 -to find more breaking changes. -]] -} -commander.register('guide', function() - ansikit.clear() - ansikit.cursorTo(0, 0) - for _, text in ipairs(helpTexts) do - print(text) - local out = hilbish.read('Hit enter to continue ') - ansikit.clear() - ansikit.cursorTo(0, 0) - if not out then - return - end - end - print 'Hope you enjoy using Hilbish!' -end) - -do - local virt_G = { } - - setmetatable(_G, { - __index = function (_, key) - local got_virt = virt_G[key] - if got_virt ~= nil then - return got_virt - end - - virt_G[key] = os.getenv(key) - return virt_G[key] - end, - - __newindex = function (_, key, value) - if type(value) == 'string' then - os.setenv(key, value) - virt_G[key] = value - else - if type(virt_G[key]) == 'string' then - os.setenv(key, '') - end - virt_G[key] = value - end - end, - }) -end - -commander.register('cdr', function(args) - if not args[1] then - print(lunacolors.format [[ -cdr: change directory to one which has been recently visied - -usage: cdr - -to get a list of recent directories, use {green}{underline}cdr list{reset}]]) - return - end - - if args[1] == 'list' then - if #recentDirs == 0 then - print 'No directories have been visited.' - return 1 - end - print(table.concat(recentDirs, '\n')) - return - end - - local index = tonumber(args[1]) - if not index then - print(string.format('received %s as index, which isn\'t a number', index)) - return 1 - end - - if not recentDirs[index] then - print(string.format('no recent directory found at index %s', index)) - return 1 - end - - fs.cd(recentDirs[index]) -end) - --- Hook handles -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/vars_darwin.go b/vars_darwin.go index b780c23..8ec83ba 100644 --- a/vars_darwin.go +++ b/vars_darwin.go @@ -15,7 +15,7 @@ var ( .. hilbish.userDir.config .. '/hilbish/?/?.lua;' .. hilbish.userDir.config .. '/hilbish/?.lua'` dataDir = "/usr/local/share/hilbish" - preloadPath = dataDir + "/prelude/init.lua" + preloadPath = dataDir + "/nature/init.lua" sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config defaultConfDir = getenv("XDG_CONFIG_HOME", "~/.config") ) diff --git a/vars_linux.go b/vars_linux.go index 5ea3ac5..815ba6a 100644 --- a/vars_linux.go +++ b/vars_linux.go @@ -15,7 +15,7 @@ var ( .. hilbish.userDir.config .. '/hilbish/?/?.lua;' .. hilbish.userDir.config .. '/hilbish/?.lua'` dataDir = "/usr/share/hilbish" - preloadPath = dataDir + "/prelude/init.lua" + preloadPath = dataDir + "/nature/init.lua" sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config defaultConfDir = "" ) diff --git a/vars_windows.go b/vars_windows.go index 5e9878c..a257baf 100644 --- a/vars_windows.go +++ b/vars_windows.go @@ -9,7 +9,7 @@ var ( .. hilbish.userDir.config .. '\\Hilbish\\libs\\?\\?.lua;' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?.lua;'` dataDir = "~\\Appdata\\Roaming\\Hilbish" // ~ and \ gonna cry? - preloadPath = dataDir + "\\prelude\\init.lua" + preloadPath = dataDir + "\\nature\\init.lua" sampleConfPath = dataDir + "\\hilbishrc.lua" // Path to default/sample config defaultConfDir = "" )