mirror of https://github.com/Hilbis/Hilbish
Compare commits
6 Commits
062f40e9e5
...
284248fc08
Author | SHA1 | Date |
---|---|---|
TorchedSammy | 284248fc08 | |
TorchedSammy | 7bde025c8e | |
TorchedSammy | e8d0ea12cc | |
TorchedSammy | c175bb4d8a | |
TorchedSammy | b3981b5a4e | |
TorchedSammy | 065d752b82 |
51
api.go
51
api.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
|
|
||||||
"github.com/yuin/gopher-lua"
|
"github.com/yuin/gopher-lua"
|
||||||
|
"github.com/maxlandon/readline"
|
||||||
"mvdan.cc/sh/v3/interp"
|
"mvdan.cc/sh/v3/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ var exports = map[string]lua.LGFunction {
|
||||||
"multiprompt": hlmlprompt,
|
"multiprompt": hlmlprompt,
|
||||||
"prependPath": hlprependPath,
|
"prependPath": hlprependPath,
|
||||||
"prompt": hlprompt,
|
"prompt": hlprompt,
|
||||||
|
"inputMode": hlinputMode,
|
||||||
"interval": hlinterval,
|
"interval": hlinterval,
|
||||||
"read": hlread,
|
"read": hlread,
|
||||||
"run": hlrun,
|
"run": hlrun,
|
||||||
|
@ -34,9 +36,11 @@ var exports = map[string]lua.LGFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
var greeting string
|
var greeting string
|
||||||
|
var hshMod *lua.LTable
|
||||||
|
|
||||||
func hilbishLoader(L *lua.LState) int {
|
func hilbishLoader(L *lua.LState) int {
|
||||||
mod := L.SetFuncs(L.NewTable(), exports)
|
mod := L.SetFuncs(L.NewTable(), exports)
|
||||||
|
hshMod = mod
|
||||||
|
|
||||||
host, _ := os.Hostname()
|
host, _ := os.Hostname()
|
||||||
username := curuser.Username
|
username := curuser.Username
|
||||||
|
@ -57,6 +61,7 @@ The nice lil shell for {blue}Lua{reset} fanatics!
|
||||||
util.SetField(L, mod, "interactive", lua.LBool(interactive), "If this is an interactive shell")
|
util.SetField(L, mod, "interactive", lua.LBool(interactive), "If this is an interactive shell")
|
||||||
util.SetField(L, mod, "login", lua.LBool(interactive), "Whether this is a login shell")
|
util.SetField(L, mod, "login", lua.LBool(interactive), "Whether this is a login shell")
|
||||||
util.SetField(L, mod, "greeting", lua.LString(greeting), "Hilbish's welcome message for interactive shells. It has Lunacolors formatting.")
|
util.SetField(L, mod, "greeting", lua.LString(greeting), "Hilbish's welcome message for interactive shells. It has Lunacolors formatting.")
|
||||||
|
util.SetField(l, mod, "vimMode", lua.LNil, "Current Vim mode of Hilbish (nil if not in Vim mode)")
|
||||||
util.Document(L, mod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
|
util.Document(L, mod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
|
||||||
|
|
||||||
// hilbish.userDir table
|
// hilbish.userDir table
|
||||||
|
@ -83,6 +88,15 @@ The nice lil shell for {blue}Lua{reset} fanatics!
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setVimMode(mode string) {
|
||||||
|
hooks.Em.Emit("hilbish.vimMode", mode)
|
||||||
|
util.SetField(l, hshMod, "vimMode", lua.LString(mode), "Current Vim mode of Hilbish (nil if not in Vim mode)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetVimMode() {
|
||||||
|
util.SetField(l, hshMod, "vimMode", lua.LNil, "Current Vim mode of Hilbish (nil if not in Vim mode)")
|
||||||
|
}
|
||||||
|
|
||||||
// run(cmd)
|
// run(cmd)
|
||||||
// Runs `cmd` in Hilbish's sh interpreter.
|
// Runs `cmd` in Hilbish's sh interpreter.
|
||||||
// --- @param cmd string
|
// --- @param cmd string
|
||||||
|
@ -150,6 +164,9 @@ These will be formatted and replaced with the appropriate values.
|
||||||
*/
|
*/
|
||||||
func hlprompt(L *lua.LState) int {
|
func hlprompt(L *lua.LState) int {
|
||||||
prompt = L.CheckString(1)
|
prompt = L.CheckString(1)
|
||||||
|
if lr != nil {
|
||||||
|
lr.SetPrompt(fmtPrompt())
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -212,6 +229,7 @@ func appendPath(dir string) {
|
||||||
func hlexec(L *lua.LState) int {
|
func hlexec(L *lua.LState) int {
|
||||||
cmd := L.CheckString(1)
|
cmd := L.CheckString(1)
|
||||||
cmdArgs, _ := splitInput(cmd)
|
cmdArgs, _ := splitInput(cmd)
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
cmdPath, err := exec.LookPath(cmdArgs[0])
|
cmdPath, err := exec.LookPath(cmdArgs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -221,9 +239,17 @@ func hlexec(L *lua.LState) int {
|
||||||
|
|
||||||
// syscall.Exec requires an absolute path to a binary
|
// syscall.Exec requires an absolute path to a binary
|
||||||
// path, args, string slice of environments
|
// path, args, string slice of environments
|
||||||
// TODO: alternative for windows
|
|
||||||
syscall.Exec(cmdPath, cmdArgs, os.Environ())
|
syscall.Exec(cmdPath, cmdArgs, os.Environ())
|
||||||
return 0 // random thought: does this ever return?
|
} else {
|
||||||
|
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Run()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// goro(fn)
|
// goro(fn)
|
||||||
|
@ -309,6 +335,8 @@ func hlinterval(L *lua.LState) int {
|
||||||
// replacing <cmd> with the name of the command (for example `command.git`).
|
// replacing <cmd> with the name of the command (for example `command.git`).
|
||||||
// `cb` must be a function that returns a table of the entries to complete.
|
// `cb` must be a function that returns a table of the entries to complete.
|
||||||
// Nested tables will be used as sub-completions.
|
// Nested tables will be used as sub-completions.
|
||||||
|
// --- @param scope string
|
||||||
|
// --- @param cb function
|
||||||
func hlcomplete(L *lua.LState) int {
|
func hlcomplete(L *lua.LState) int {
|
||||||
scope := L.CheckString(1)
|
scope := L.CheckString(1)
|
||||||
cb := L.CheckFunction(2)
|
cb := L.CheckFunction(2)
|
||||||
|
@ -320,6 +348,7 @@ func hlcomplete(L *lua.LState) int {
|
||||||
|
|
||||||
// prependPath(dir)
|
// prependPath(dir)
|
||||||
// Prepends `dir` to $PATH
|
// Prepends `dir` to $PATH
|
||||||
|
// --- @param dir string
|
||||||
func hlprependPath(L *lua.LState) int {
|
func hlprependPath(L *lua.LState) int {
|
||||||
dir := L.CheckString(1)
|
dir := L.CheckString(1)
|
||||||
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
|
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
|
||||||
|
@ -335,6 +364,7 @@ func hlprependPath(L *lua.LState) int {
|
||||||
|
|
||||||
// which(binName)
|
// which(binName)
|
||||||
// Searches for an executable called `binName` in the directories of $PATH
|
// Searches for an executable called `binName` in the directories of $PATH
|
||||||
|
// --- @param binName string
|
||||||
func hlwhich(L *lua.LState) int {
|
func hlwhich(L *lua.LState) int {
|
||||||
binName := L.CheckString(1)
|
binName := L.CheckString(1)
|
||||||
path, err := exec.LookPath(binName)
|
path, err := exec.LookPath(binName)
|
||||||
|
@ -346,3 +376,20 @@ func hlwhich(L *lua.LState) int {
|
||||||
l.Push(lua.LString(path))
|
l.Push(lua.LString(path))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inputMode(mode)
|
||||||
|
// Sets the input mode for Hilbish's line reader. Accepts either emacs for vim
|
||||||
|
// --- @param mode string
|
||||||
|
func hlinputMode(L *lua.LState) int {
|
||||||
|
mode := L.CheckString(1)
|
||||||
|
switch mode {
|
||||||
|
case "emacs":
|
||||||
|
unsetVimMode()
|
||||||
|
lr.rl.InputMode = readline.Emacs
|
||||||
|
case "vim":
|
||||||
|
setVimMode("insert")
|
||||||
|
lr.rl.InputMode = readline.Vim
|
||||||
|
default: L.RaiseError("inputMode: expected vim or emacs, received " + mode)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ exec(cmd) > Replaces running hilbish with `cmd`
|
||||||
|
|
||||||
goro(fn) > Puts `fn` in a goroutine
|
goro(fn) > Puts `fn` in a goroutine
|
||||||
|
|
||||||
|
inputMode(mode) > Sets the input mode for Hilbish's line reader. Accepts either emacs for vim
|
||||||
|
|
||||||
interval(cb, time) > Runs the `cb` function every `time` milliseconds
|
interval(cb, time) > Runs the `cb` function every `time` milliseconds
|
||||||
|
|
||||||
multiprompt(str) > Changes the continued line prompt to `str`
|
multiprompt(str) > Changes the continued line prompt to `str`
|
||||||
|
|
|
@ -16,7 +16,9 @@ function hilbish.appendPath(dir) end
|
||||||
--- replacing <cmd> with the name of the command (for example `command.git`).
|
--- replacing <cmd> with the name of the command (for example `command.git`).
|
||||||
--- `cb` must be a function that returns a table of the entries to complete.
|
--- `cb` must be a function that returns a table of the entries to complete.
|
||||||
--- Nested tables will be used as sub-completions.
|
--- Nested tables will be used as sub-completions.
|
||||||
function hilbish.complete() end
|
--- @param scope string
|
||||||
|
--- @param cb function
|
||||||
|
function hilbish.complete(scope, cb) end
|
||||||
|
|
||||||
--- Returns the current directory of the shell
|
--- Returns the current directory of the shell
|
||||||
function hilbish.cwd() end
|
function hilbish.cwd() end
|
||||||
|
@ -29,6 +31,10 @@ function hilbish.exec(cmd) end
|
||||||
--- @param fn function
|
--- @param fn function
|
||||||
function hilbish.goroutine(fn) end
|
function hilbish.goroutine(fn) end
|
||||||
|
|
||||||
|
--- Sets the input mode for Hilbish's line reader. Accepts either emacs for vim
|
||||||
|
--- @param mode string
|
||||||
|
function hilbish.inputMode(mode) end
|
||||||
|
|
||||||
--- Runs the `cb` function every `time` milliseconds
|
--- Runs the `cb` function every `time` milliseconds
|
||||||
--- @param cb function
|
--- @param cb function
|
||||||
--- @param time number
|
--- @param time number
|
||||||
|
@ -39,7 +45,8 @@ function hilbish.interval(cb, time) end
|
||||||
function hilbish.mlprompt(str) end
|
function hilbish.mlprompt(str) end
|
||||||
|
|
||||||
--- Prepends `dir` to $PATH
|
--- Prepends `dir` to $PATH
|
||||||
function hilbish.prependPath() end
|
--- @param dir string
|
||||||
|
function hilbish.prependPath(dir) end
|
||||||
|
|
||||||
--- Changes the shell prompt to `str`
|
--- Changes the shell prompt to `str`
|
||||||
--- There are a few verbs that can be used in the prompt text.
|
--- There are a few verbs that can be used in the prompt text.
|
||||||
|
@ -66,6 +73,7 @@ function hilbish.run(cmd) end
|
||||||
function hilbish.timeout(cb, time) end
|
function hilbish.timeout(cb, time) end
|
||||||
|
|
||||||
--- Searches for an executable called `binName` in the directories of $PATH
|
--- Searches for an executable called `binName` in the directories of $PATH
|
||||||
function hilbish.which() end
|
--- @param binName string
|
||||||
|
function hilbish.which(binName) end
|
||||||
|
|
||||||
return hilbish
|
return hilbish
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -15,6 +15,6 @@ require (
|
||||||
|
|
||||||
replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20211022004519-f67a49cb50f5
|
replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20211022004519-f67a49cb50f5
|
||||||
|
|
||||||
replace github.com/maxlandon/readline => github.com/Rosettea/readline-1 v0.1.0-beta.0.20220228022904-61f5e4493011
|
replace github.com/maxlandon/readline => github.com/Rosettea/readline-1 v0.0.0-20220302012429-9ce5d23760f7
|
||||||
|
|
||||||
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
|
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,3 +1,5 @@
|
||||||
|
github.com/Rosettea/readline-1 v0.0.0-20220302012429-9ce5d23760f7 h1:LoY+kBKqMQqBcilRpVvifBTVve84asa3btpx3D/+IvM=
|
||||||
|
github.com/Rosettea/readline-1 v0.0.0-20220302012429-9ce5d23760f7/go.mod h1:QiUAvbhg8PzCA4hlafCUl0bKD/0VmcocM4AjqtszAJs=
|
||||||
github.com/Rosettea/readline-1 v0.1.0-beta.0.20211207003625-341c7985ad7d h1:KBttN41h/tPahmpaZavviwQ8q4rCkt5CD0HdVmfgPVA=
|
github.com/Rosettea/readline-1 v0.1.0-beta.0.20211207003625-341c7985ad7d h1:KBttN41h/tPahmpaZavviwQ8q4rCkt5CD0HdVmfgPVA=
|
||||||
github.com/Rosettea/readline-1 v0.1.0-beta.0.20211207003625-341c7985ad7d/go.mod h1:QiUAvbhg8PzCA4hlafCUl0bKD/0VmcocM4AjqtszAJs=
|
github.com/Rosettea/readline-1 v0.1.0-beta.0.20211207003625-341c7985ad7d/go.mod h1:QiUAvbhg8PzCA4hlafCUl0bKD/0VmcocM4AjqtszAJs=
|
||||||
github.com/Rosettea/readline-1 v0.1.0-beta.0.20220228022904-61f5e4493011 h1:+a61iNamZiO3Xru+l/1qtpKqqltVfWEm2r/rxH9hXxY=
|
github.com/Rosettea/readline-1 v0.1.0-beta.0.20220228022904-61f5e4493011 h1:+a61iNamZiO3Xru+l/1qtpKqqltVfWEm2r/rxH9hXxY=
|
||||||
|
|
19
rl.go
19
rl.go
|
@ -18,7 +18,18 @@ type lineReader struct {
|
||||||
// other gophers might hate this naming but this is local, shut up
|
// other gophers might hate this naming but this is local, shut up
|
||||||
func newLineReader(prompt string) *lineReader {
|
func newLineReader(prompt string) *lineReader {
|
||||||
rl := readline.NewInstance()
|
rl := readline.NewInstance()
|
||||||
rl.Multiline = true
|
rl.ShowVimMode = false
|
||||||
|
rl.ViModeCallback = func(mode readline.ViMode) {
|
||||||
|
modeStr := ""
|
||||||
|
switch mode {
|
||||||
|
case readline.VimKeys: modeStr = "normal"
|
||||||
|
case readline.VimInsert: modeStr = "insert"
|
||||||
|
case readline.VimDelete: modeStr = "delete"
|
||||||
|
case readline.VimReplaceOnce:
|
||||||
|
case readline.VimReplaceMany: modeStr = "replace"
|
||||||
|
}
|
||||||
|
setVimMode(modeStr)
|
||||||
|
}
|
||||||
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
|
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
|
||||||
ctx := string(line)
|
ctx := string(line)
|
||||||
var completions []string
|
var completions []string
|
||||||
|
@ -196,6 +207,7 @@ func (lr *lineReader) Read() (string, error) {
|
||||||
s, err := lr.rl.Readline()
|
s, err := lr.rl.Readline()
|
||||||
// this is so dumb
|
// this is so dumb
|
||||||
if err == readline.EOF {
|
if err == readline.EOF {
|
||||||
|
fmt.Println("")
|
||||||
return "", io.EOF
|
return "", io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,10 +221,13 @@ func (lr *lineReader) SetPrompt(prompt string) {
|
||||||
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt) - 1:][0]
|
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt) - 1:][0]
|
||||||
} else {
|
} else {
|
||||||
// print cursor up ansi code
|
// print cursor up ansi code
|
||||||
fmt.Printf("\033[1A")
|
//fmt.Printf("\033[1A")
|
||||||
lr.rl.SetPrompt("")
|
lr.rl.SetPrompt("")
|
||||||
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt) - 1:][0]
|
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt) - 1:][0]
|
||||||
}
|
}
|
||||||
|
if !running {
|
||||||
|
lr.rl.RefreshPromptInPlace("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lr *lineReader) AddHistory(cmd string) {
|
func (lr *lineReader) AddHistory(cmd string) {
|
||||||
|
|
Loading…
Reference in New Issue