mirror of https://github.com/Hilbis/Hilbish
Compare commits
6 Commits
b210378380
...
db437905e0
Author | SHA1 | Date |
---|---|---|
TorchedSammy | db437905e0 | |
TorchedSammy | c890b86e08 | |
TorchedSammy | a8406657f9 | |
TorchedSammy | 4178b78341 | |
TorchedSammy | c4eb3ad368 | |
TorchedSammy | 0642ddda36 |
|
@ -24,7 +24,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) {
|
||||||
fileCompletions, filePref := matchPath(query)
|
fileCompletions, filePref := matchPath(query)
|
||||||
if len(fileCompletions) != 0 {
|
if len(fileCompletions) != 0 {
|
||||||
for _, f := range fileCompletions {
|
for _, f := range fileCompletions {
|
||||||
fullPath, _ := filepath.Abs(expandHome(query + strings.TrimPrefix(f, filePref)))
|
fullPath, _ := filepath.Abs(util.ExpandHome(query + strings.TrimPrefix(f, filePref)))
|
||||||
if err := findExecutable(fullPath, false, true); err != nil {
|
if err := findExecutable(fullPath, false, true); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func matchPath(query string) ([]string, string) {
|
||||||
var entries []string
|
var entries []string
|
||||||
var baseName string
|
var baseName string
|
||||||
|
|
||||||
path, _ := filepath.Abs(expandHome(filepath.Dir(query)))
|
path, _ := filepath.Abs(util.ExpandHome(filepath.Dir(query)))
|
||||||
if string(query) == "" {
|
if string(query) == "" {
|
||||||
// filepath base below would give us "."
|
// filepath base below would give us "."
|
||||||
// which would cause a match of only dotfiles
|
// which would cause a match of only dotfiles
|
||||||
|
|
106
exec.go
106
exec.go
|
@ -25,8 +25,63 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNotExec = errors.New("not executable")
|
var errNotExec = errors.New("not executable")
|
||||||
|
var errNotFound = errors.New("not found")
|
||||||
var runnerMode rt.Value = rt.StringValue("hybrid")
|
var runnerMode rt.Value = rt.StringValue("hybrid")
|
||||||
|
|
||||||
|
type execError struct{
|
||||||
|
typ string
|
||||||
|
cmd string
|
||||||
|
code int
|
||||||
|
colon bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e execError) Error() string {
|
||||||
|
return fmt.Sprintf("%s: %s", e.cmd, e.typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e execError) sprint() error {
|
||||||
|
sep := " "
|
||||||
|
if e.colon {
|
||||||
|
sep = ": "
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("hilbish: %s%s%s", e.cmd, sep, e.err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func isExecError(err error) (execError, bool) {
|
||||||
|
if exErr, ok := err.(execError); ok {
|
||||||
|
return exErr, true
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.Split(err.Error(), ": ")
|
||||||
|
knownTypes := []string{
|
||||||
|
"not-found",
|
||||||
|
"not-executable",
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) > 1 && contains(knownTypes, fields[1]) {
|
||||||
|
var colon bool
|
||||||
|
var e error
|
||||||
|
switch fields[1] {
|
||||||
|
case "not-found":
|
||||||
|
e = errNotFound
|
||||||
|
case "not-executable":
|
||||||
|
colon = true
|
||||||
|
e = errNotExec
|
||||||
|
}
|
||||||
|
|
||||||
|
return execError{
|
||||||
|
cmd: fields[0],
|
||||||
|
typ: fields[1],
|
||||||
|
colon: colon,
|
||||||
|
err: e,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return execError{}, false
|
||||||
|
}
|
||||||
|
|
||||||
func runInput(input string, priv bool) {
|
func runInput(input string, priv bool) {
|
||||||
running = true
|
running = true
|
||||||
cmdString := aliases.Resolve(input)
|
cmdString := aliases.Resolve(input)
|
||||||
|
@ -43,10 +98,6 @@ func runInput(input string, priv bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
input, exitCode, err = handleSh(input)
|
input, exitCode, err = handleSh(input)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
}
|
|
||||||
cmdFinish(exitCode, input, priv)
|
|
||||||
case "hybridRev":
|
case "hybridRev":
|
||||||
_, _, err = handleSh(input)
|
_, _, err = handleSh(input)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -54,27 +105,15 @@ func runInput(input string, priv bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
input, exitCode, err = handleLua(cmdString)
|
input, exitCode, err = handleLua(cmdString)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
}
|
|
||||||
cmdFinish(exitCode, input, priv)
|
|
||||||
case "lua":
|
case "lua":
|
||||||
input, exitCode, err = handleLua(cmdString)
|
input, exitCode, err = handleLua(cmdString)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
}
|
|
||||||
cmdFinish(exitCode, input, priv)
|
|
||||||
case "sh":
|
case "sh":
|
||||||
input, exitCode, err = handleSh(input)
|
input, exitCode, err = handleSh(input)
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
}
|
|
||||||
cmdFinish(exitCode, input, priv)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// can only be a string or function so
|
// can only be a string or function so
|
||||||
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false)
|
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false)
|
||||||
err := rt.Call(l.MainThread(), runnerMode, []rt.Value{rt.StringValue(cmdString)}, term)
|
err = rt.Call(l.MainThread(), runnerMode, []rt.Value{rt.StringValue(cmdString)}, term)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
cmdFinish(124, input, priv)
|
cmdFinish(124, input, priv)
|
||||||
|
@ -85,7 +124,6 @@ func runInput(input string, priv bool) {
|
||||||
luaexitcode := term.Get(1)
|
luaexitcode := term.Get(1)
|
||||||
runErr := term.Get(2)
|
runErr := term.Get(2)
|
||||||
|
|
||||||
var exitCode uint8
|
|
||||||
if code, ok := luaexitcode.TryInt(); ok {
|
if code, ok := luaexitcode.TryInt(); ok {
|
||||||
exitCode = uint8(code)
|
exitCode = uint8(code)
|
||||||
}
|
}
|
||||||
|
@ -94,12 +132,20 @@ func runInput(input string, priv bool) {
|
||||||
input = inp
|
input = inp
|
||||||
}
|
}
|
||||||
|
|
||||||
if runErr != rt.NilValue {
|
if errStr, ok := runErr.TryString(); ok {
|
||||||
fmt.Fprintln(os.Stderr, runErr)
|
err = fmt.Errorf("%s", errStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if exErr, ok := isExecError(err); ok {
|
||||||
|
hooks.Em.Emit("command." + exErr.typ, exErr.cmd)
|
||||||
|
err = exErr.sprint()
|
||||||
|
}
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
}
|
}
|
||||||
cmdFinish(exitCode, input, priv)
|
cmdFinish(exitCode, input, priv)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func handleLua(cmdString string) (string, uint8, error) {
|
func handleLua(cmdString string) (string, uint8, error) {
|
||||||
// First try to load input, essentially compiling to bytecode
|
// First try to load input, essentially compiling to bytecode
|
||||||
|
@ -255,12 +301,20 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
|
|
||||||
err := lookpath(args[0])
|
err := lookpath(args[0])
|
||||||
if err == errNotExec {
|
if err == errNotExec {
|
||||||
hooks.Em.Emit("command.no-perm", args[0])
|
return execError{
|
||||||
hooks.Em.Emit("command.not-executable", args[0])
|
typ: "not-executable",
|
||||||
return interp.NewExitStatus(126)
|
cmd: args[0],
|
||||||
|
code: 126,
|
||||||
|
colon: true,
|
||||||
|
err: errNotExec,
|
||||||
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
hooks.Em.Emit("command.not-found", args[0])
|
return execError{
|
||||||
return interp.NewExitStatus(127)
|
typ: "not-found",
|
||||||
|
cmd: args[0],
|
||||||
|
code: 127,
|
||||||
|
err: errNotFound,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
killTimeout := 2 * time.Second
|
killTimeout := 2 * time.Second
|
||||||
|
|
|
@ -30,7 +30,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
|
|
||||||
util.Document(mod, `The fs module provides easy and simple access to
|
util.Document(mod, `The fs module provides easy and simple access to
|
||||||
filesystem functions and other things, and acts an
|
filesystem functions and other things, and acts an
|
||||||
addition to the Lua standard library's I/O and fs functions.`)
|
addition to the Lua standard library's I/O and filesystem functions.`)
|
||||||
|
|
||||||
return rt.TableValue(mod), nil
|
return rt.TableValue(mod), nil
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,9 @@ func fcd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
path = util.ExpandHome(strings.TrimSpace(path))
|
||||||
|
|
||||||
err = os.Chdir(strings.TrimSpace(path))
|
err = os.Chdir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.CheckNArgs(2); err != nil {
|
if err := c.CheckNArgs(2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dirname, err := c.StringArg(0)
|
path, err := c.StringArg(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,7 @@ func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
path := strings.TrimSpace(dirname)
|
path = util.ExpandHome(strings.TrimSpace(path))
|
||||||
|
|
||||||
if recursive {
|
if recursive {
|
||||||
err = os.MkdirAll(path, 0744)
|
err = os.MkdirAll(path, 0744)
|
||||||
|
@ -96,6 +97,7 @@ func fstat(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
path = util.ExpandHome(path)
|
||||||
|
|
||||||
pathinfo, err := os.Stat(path)
|
pathinfo, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -122,6 +124,7 @@ func freaddir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
dir = util.ExpandHome(dir)
|
||||||
names := rt.NewTable()
|
names := rt.NewTable()
|
||||||
|
|
||||||
dirEntries, err := os.ReadDir(dir)
|
dirEntries, err := os.ReadDir(dir)
|
||||||
|
@ -143,6 +146,7 @@ func fabs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
path = util.ExpandHome(path)
|
||||||
|
|
||||||
abspath, err := filepath.Abs(path)
|
abspath, err := filepath.Abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
4
lua.go
4
lua.go
|
@ -51,14 +51,14 @@ func luaInit() {
|
||||||
// Add more paths that Lua can require from
|
// Add more paths that Lua can require from
|
||||||
err := util.DoString(l, "package.path = package.path .. " + requirePaths)
|
err := util.DoString(l, "package.path = package.path .. " + requirePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Could not add preload paths! Libraries will be missing. This shouldn't happen.")
|
fmt.Fprintln(os.Stderr, "Could not add Hilbish require paths! Libraries will be missing. This shouldn't happen.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = util.DoFile(l, "nature/init.lua")
|
err = util.DoFile(l, "nature/init.lua")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = util.DoFile(l, preloadPath)
|
err = util.DoFile(l, preloadPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Missing preload file, builtins may be missing.")
|
fmt.Fprintln(os.Stderr, "Missing nature module, some functionality and builtins will be missing.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
main.go
9
main.go
|
@ -56,13 +56,13 @@ func main() {
|
||||||
defaultConfDir = filepath.Join(confDir, "hilbish")
|
defaultConfDir = filepath.Join(confDir, "hilbish")
|
||||||
} else {
|
} else {
|
||||||
// else do ~ substitution
|
// else do ~ substitution
|
||||||
defaultConfDir = filepath.Join(expandHome(defaultConfDir), "hilbish")
|
defaultConfDir = filepath.Join(util.ExpandHome(defaultConfDir), "hilbish")
|
||||||
}
|
}
|
||||||
defaultConfPath = filepath.Join(defaultConfDir, "init.lua")
|
defaultConfPath = filepath.Join(defaultConfDir, "init.lua")
|
||||||
if defaultHistDir == "" {
|
if defaultHistDir == "" {
|
||||||
defaultHistDir = filepath.Join(userDataDir, "hilbish")
|
defaultHistDir = filepath.Join(userDataDir, "hilbish")
|
||||||
} else {
|
} else {
|
||||||
defaultHistDir = filepath.Join(expandHome(defaultHistDir), "hilbish")
|
defaultHistDir = filepath.Join(util.ExpandHome(defaultHistDir), "hilbish")
|
||||||
}
|
}
|
||||||
defaultHistPath = filepath.Join(defaultHistDir, ".hilbish-history")
|
defaultHistPath = filepath.Join(defaultHistDir, ".hilbish-history")
|
||||||
helpflag := getopt.BoolLong("help", 'h', "Prints Hilbish flags")
|
helpflag := getopt.BoolLong("help", 'h', "Prints Hilbish flags")
|
||||||
|
@ -273,11 +273,6 @@ func handleHistory(cmd string) {
|
||||||
// TODO: load history again (history shared between sessions like this ye)
|
// TODO: load history again (history shared between sessions like this ye)
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandHome(path string) string {
|
|
||||||
homedir := curuser.HomeDir
|
|
||||||
return strings.Replace(path, "~", homedir, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeDupes(slice []string) []string {
|
func removeDupes(slice []string) []string {
|
||||||
all := make(map[string]bool)
|
all := make(map[string]bool)
|
||||||
newSlice := []string{}
|
newSlice := []string{}
|
||||||
|
|
|
@ -31,5 +31,5 @@ commander.register('cd', function (args)
|
||||||
fs.cd(hilbish.home)
|
fs.cd(hilbish.home)
|
||||||
bait.throw('cd', hilbish.home)
|
bait.throw('cd', hilbish.home)
|
||||||
|
|
||||||
dirs.addRecent(hilbish.home)
|
dirs.push(hilbish.home)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
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)
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ local _ = require 'succulent' -- Function additions
|
||||||
package.path = package.path .. ';' .. hilbish.dataDir .. '/?/init.lua'
|
package.path = package.path .. ';' .. hilbish.dataDir .. '/?/init.lua'
|
||||||
.. ';' .. hilbish.dataDir .. '/?/?.lua'
|
.. ';' .. hilbish.dataDir .. '/?/?.lua'
|
||||||
|
|
||||||
require 'nature.hooks'
|
|
||||||
require 'nature.commands'
|
require 'nature.commands'
|
||||||
require 'nature.completions'
|
require 'nature.completions'
|
||||||
|
require 'nature.opts'
|
||||||
|
|
||||||
local shlvl = tonumber(os.getenv 'SHLVL')
|
local shlvl = tonumber(os.getenv 'SHLVL')
|
||||||
if shlvl ~= nil then
|
if shlvl ~= nil then
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
local fs = require 'fs'
|
||||||
|
|
||||||
|
function cdHandle(inp)
|
||||||
|
local input, exit, err = hilbish.runner.lua(inp)
|
||||||
|
|
||||||
|
if not err then
|
||||||
|
return input, exit, err
|
||||||
|
end
|
||||||
|
|
||||||
|
input, exit, err = hilbish.runner.sh(inp)
|
||||||
|
|
||||||
|
if exit ~= 0 and hilbish.opts.autocd then
|
||||||
|
local ok, stat = pcall(fs.stat, input)
|
||||||
|
if ok and stat.isDir then
|
||||||
|
-- discard here to not append the cd, which will be in history
|
||||||
|
_, exit, err = hilbish.runner.sh('cd ' .. input)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return input, exit, err
|
||||||
|
end
|
||||||
|
|
||||||
|
hilbish.runner.setMode(cdHandle)
|
|
@ -0,0 +1,28 @@
|
||||||
|
local opts = {}
|
||||||
|
hilbish.opts = {}
|
||||||
|
|
||||||
|
setmetatable(hilbish.opts, {
|
||||||
|
__newindex = function(_, k, v)
|
||||||
|
if opts[k] == nil then
|
||||||
|
error(string.format('opt %s does not exist', k))
|
||||||
|
end
|
||||||
|
|
||||||
|
opts[k] = v
|
||||||
|
end,
|
||||||
|
__index = function(_, k)
|
||||||
|
return opts[k]
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
local function setupOpt(name, default)
|
||||||
|
opts[name] = default
|
||||||
|
require('nature.opts.' .. name)
|
||||||
|
end
|
||||||
|
|
||||||
|
local defaultOpts = {
|
||||||
|
autocd = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for optsName, default in pairs(defaultOpts) do
|
||||||
|
setupOpt(optsName, default)
|
||||||
|
end
|
|
@ -3,7 +3,9 @@ package util
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
@ -150,3 +152,10 @@ func ForEach(tbl *rt.Table, cb func(key rt.Value, val rt.Value)) {
|
||||||
cb(key, val)
|
cb(key, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExpandHome(path string) string {
|
||||||
|
curuser, _ := user.Current()
|
||||||
|
homedir := curuser.HomeDir
|
||||||
|
|
||||||
|
return strings.Replace(path, "~", homedir, 1)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue