mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-01 16:52:03 +00:00
234 lines
6.4 KiB
Lua
234 lines
6.4 KiB
Lua
-- @module hilbish
|
|
local bait = require 'bait'
|
|
local fs = require 'fs'
|
|
local readline = require 'readline'
|
|
local snail = require 'snail'
|
|
|
|
hilbish.snail = snail.new()
|
|
hilbish.snail:run 'true' -- to "initialize" snail
|
|
bait.catch('hilbish.cd', function(path)
|
|
hilbish.snail:dir(path)
|
|
end)
|
|
|
|
local function abbrevHome(path)
|
|
if path:sub(1, hilbish.home:len()) == hilbish.home then
|
|
return fs.join('~', path:sub(hilbish.home:len() + 1))
|
|
end
|
|
|
|
return path
|
|
end
|
|
|
|
local function expandHome(path)
|
|
if path:sub(1, 1) == '~' then
|
|
return fs.join(hilbish.home, path:sub(2))
|
|
end
|
|
|
|
return path
|
|
end
|
|
|
|
local function fmtPrompt(p)
|
|
return p:gsub('%%(%w)', function(c)
|
|
if c == 'd' then
|
|
return abbrevHome(hilbish.cwd())
|
|
elseif c == 'D' then
|
|
return fs.basename(abbrevHome(hilbish.cwd()))
|
|
elseif c == 'u' then
|
|
return hilbish.user
|
|
elseif c == 'h' then
|
|
return hilbish.host
|
|
end
|
|
end)
|
|
end
|
|
|
|
--- prompt(str, typ)
|
|
--- Changes the shell prompt to the provided string.
|
|
--- 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
|
|
--- `%D` - Basename of working directory ()
|
|
--- `%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.
|
|
--- #example
|
|
--- -- the default hilbish prompt without color
|
|
--- hilbish.prompt '%u %d ∆'
|
|
--- -- or something of old:
|
|
--- hilbish.prompt '%u@%h :%d $'
|
|
--- -- prompt: user@hostname: ~/directory $
|
|
--- #example
|
|
-- @param p string
|
|
-- @param typ string Type of prompt, either left or right
|
|
function hilbish.prompt(p, typ)
|
|
if type(p) ~= 'string' then
|
|
error('expected #1 to be string, got ' .. type(p))
|
|
end
|
|
|
|
if not typ or typ == 'left' then
|
|
hilbish.editor:prompt(fmtPrompt(p))
|
|
if not hilbish.running then
|
|
hilbish.editor:refreshPrompt()
|
|
end
|
|
elseif typ == 'right' then
|
|
hilbish.editor:rightPrompt(fmtPrompt(p))
|
|
if not hilbish.running then
|
|
hilbish.editor:refreshPrompt()
|
|
end
|
|
else
|
|
error('expected prompt type to be right or left, got ' .. tostring(typ))
|
|
end
|
|
end
|
|
|
|
local pathSep = ':'
|
|
if hilbish.os.family == 'windows' then
|
|
pathSep = ';'
|
|
end
|
|
|
|
local function appendPath(path)
|
|
os.setenv('PATH', os.getenv 'PATH' .. pathSep .. expandHome(path))
|
|
end
|
|
|
|
--- appendPath(path)
|
|
--- Appends the provided dir to the command path (`$PATH`)
|
|
--- @param path string|table Directory (or directories) to append to path
|
|
--- #example
|
|
--- hilbish.appendPath '~/go/bin'
|
|
--- -- Will add ~/go/bin to the command path.
|
|
---
|
|
--- -- Or do multiple:
|
|
--- hilbish.appendPath {
|
|
--- '~/go/bin',
|
|
--- '~/.local/bin'
|
|
--- }
|
|
--- #example
|
|
function hilbish.appendPath(path)
|
|
if type(path) == 'table' then
|
|
for _, p in ipairs(path) do
|
|
appendPath(p)
|
|
end
|
|
elseif type(path) == 'string' then
|
|
appendPath(path)
|
|
else
|
|
error('bad argument to appendPath (expected string or table, got ' .. type(path) .. ')')
|
|
end
|
|
end
|
|
|
|
local function prependPath(path)
|
|
print('prepending', path, expandHome(path))
|
|
os.setenv('PATH', expandHome(path) .. pathSep .. os.getenv 'PATH')
|
|
end
|
|
|
|
--- prependPath(path)
|
|
--- Prepends the provided dir to the command path (`$PATH`)
|
|
--- @param path string|table Directory (or directories) to append to path
|
|
--- #example
|
|
--- hilbish.prependPath '~/go/bin'
|
|
--- -- Will add ~/go/bin to the command path.
|
|
---
|
|
--- -- Or do multiple:
|
|
--- hilbish.prependPath {
|
|
--- '~/go/bin',
|
|
--- '~/.local/bin'
|
|
--- }
|
|
--- #example
|
|
function hilbish.prependPath(path)
|
|
if type(path) == 'table' then
|
|
for _, p in ipairs(path) do
|
|
prependPath(p)
|
|
end
|
|
elseif type(path) == 'string' then
|
|
prependPath(path)
|
|
else
|
|
error('bad argument to prependPath (expected string or table, got ' .. type(path) .. ')')
|
|
end
|
|
end
|
|
|
|
--- read(prompt) -> input (string)
|
|
--- 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.
|
|
-- @param prompt? string Text to print before input, can be empty.
|
|
-- @returns string|nil
|
|
function hilbish.read(prompt)
|
|
prompt = prompt or ''
|
|
if type(prompt) ~= 'string' then
|
|
error 'expected #1 to be a string'
|
|
end
|
|
|
|
local rl = readline.new()
|
|
rl:prompt(prompt)
|
|
|
|
return rl:read()
|
|
end
|
|
|
|
--- Runs `cmd` in Hilbish's shell script interpreter.
|
|
--- The `streams` parameter specifies the output and input streams the command should use.
|
|
--- For example, to write command output to a sink.
|
|
--- As a table, the caller can directly specify the standard output, error, and input
|
|
--- streams of the command with the table keys `out`, `err`, and `input` respectively.
|
|
--- As a boolean, it specifies whether the command should use standard output or return its output streams.
|
|
--- #example
|
|
--- -- This code is the same as `ls -l | wc -l`
|
|
--- local fs = require 'fs'
|
|
--- local pr, pw = fs.pipe()
|
|
--- hilbish.run('ls -l', {
|
|
--- stdout = pw,
|
|
--- stderr = pw,
|
|
--- })
|
|
--- pw:close()
|
|
--- hilbish.run('wc -l', {
|
|
--- stdin = pr
|
|
--- })
|
|
--- #example
|
|
-- @param cmd string
|
|
-- @param streams table|boolean
|
|
-- @returns number, string, string
|
|
function hilbish.run(cmd, streams)
|
|
local sinks = {}
|
|
|
|
if type(streams) == 'boolean' then
|
|
if not streams then
|
|
sinks = {
|
|
out = hilbish.sink.new(),
|
|
err = hilbish.sink.new(),
|
|
input = io.stdin
|
|
}
|
|
end
|
|
elseif type(streams) == 'table' then
|
|
sinks = streams
|
|
end
|
|
|
|
local out = hilbish.snail:run(cmd, {sinks = sinks})
|
|
local returns = {out.exitCode}
|
|
|
|
if type(streams) == 'boolean' and not streams then
|
|
table.insert(returns, sinks.out:readAll())
|
|
table.insert(returns, sinks.err:readAll())
|
|
end
|
|
|
|
return table.unpack(returns)
|
|
end
|
|
|
|
--- Sets the execution/runner mode for interactive Hilbish.
|
|
--- **NOTE: This function is deprecated and will be removed in 3.0**
|
|
--- Use `hilbish.runner.setCurrent` instead.
|
|
--- 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.
|
|
--- Read [about runner mode](../features/runner-mode) for more information.
|
|
-- @param mode string|function
|
|
function hilbish.runnerMode(mode)
|
|
if type(mode) == 'string' then
|
|
hilbish.runner.setCurrent(mode)
|
|
elseif type(mode) == 'function' then
|
|
hilbish.runner.set('_', {
|
|
run = mode
|
|
})
|
|
hilbish.runner.setCurrent '_'
|
|
else
|
|
error('expected runner mode type to be either string or function, got', type(mode))
|
|
end
|
|
end
|