diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 08c69ef..371d284 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,8 +26,10 @@ jobs: uses: actions/setup-go@v2 with: go-version: '1.17.7' + - name: Download Task + run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d' - name: Build - run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} make + run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task - uses: actions/upload-artifact@v2 if: matrix.goos == 'windows' with: diff --git a/.hilbishrc.lua b/.hilbishrc.lua index 4a06b26..5d6382b 100644 --- a/.hilbishrc.lua +++ b/.hilbishrc.lua @@ -9,8 +9,6 @@ local function doPrompt(fail) )) end -print(lunacolors.format(hilbish.greeting)) - doPrompt() bait.catch('command.exit', function(code) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd733c6..522c8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # 🎀 Changelog ## Unreleased +**NOTE:** Hilbish now uses [Task] insead of Make for builds. + +[Task]: https://taskfile.dev/#/ + ### Added - Inline hints, akin to fish and the others. To make a handler for hint text, you can set the `hilbish.hinter` function. @@ -52,11 +56,20 @@ having and using multiple runners. - `fs.basename(path)` gets the basename of path - `fs.dir(path)` gets the directory part of path - `fs.glob(pattern)` globs files and directories based on patterns + - `fs.join(dirs...)` joins directories by OS dir separator - .. and 2 properties - `fs.pathSep` is the separator for filesystem paths and directories - `fs.pathListSep` is the separator for $PATH env entries - Lua modules located in `hilbish.userDir.data .. '/hilbish/start'` (like `~/.local/share/hilbish/start/foo/init.lua`) will be ran on startup +- `hilbish.init` hook, thrown after Hilbish has initialized Lua side +- Message of the day on startup (`hilbish.motd`), mainly intended as quick +small news pieces for releases. It is printed by default. To disable it, +set `hilbish.opts.motd` to false. +- `history` opt has been added and is true by default. Setting it to false +disables commands being added to history. +- `hilbish.rawInput` hook for input from the readline library +- Completion of files in quotes ### Changed - **Breaking Change:** Upgraded to Lua 5.4. @@ -72,12 +85,17 @@ It can (at the moment) have 4 variables: User input has been added to the return to account for runners wanting to prompt for continued input, and to add it properly to history. `continue` got added so that it would be easier for runners to get continued input -without having to actually handle it at all. - +without having to actually handle it at all. - **Breaking Change:** Job objects and timers are now Lua userdata instead of a table, so their functions require you to call them with a colon instead of a dot. (ie. `job.stop()` -> `job:stop()`) - All `fs` module functions which take paths now implicitly expand ~ to home. +- **Breaking Change:** `hilbish.greeting` has been moved to an opt (`hilbish.opts.greeting`) and is +always printed by default. To disable it, set the opt to false. +- History is now fetched from Lua, which means users can override `hilbish.history` +methods to make it act how they want. +- `guide` has been removed. See the [website](https://rosettea.github.io/Hilbish/) +for general tips and documentation ### Fixed - If in Vim replace mode, input at the end of the line inserts instead of @@ -112,6 +130,14 @@ for explanation. Lua `job.stop` function. - Jobs are always started in sh exec handler now instead of only successful start. - SIGTERM is handled properly now, which means stopping jobs and timers. +- Fix panic on trailing newline on pasted multiline text. +- Completions will no longer be refreshed if the prompt refreshes while the +menu is open. +- Print error on search fail instead of panicking +- Windows related fixes: + - `hilbish.dataDir` now has tilde (`~`) expanded. + - Arrow keys now work on Windows terminals. + - Escape codes now work. ## [1.2.0] - 2022-03-17 ### Added diff --git a/Makefile b/Makefile deleted file mode 100644 index 40945d3..0000000 --- a/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -PREFIX ?= /usr -BINDIR ?= $(PREFIX)/bin -LIBDIR ?= $(PREFIX)/share/hilbish - -MY_GOFLAGS = -ldflags "-s -w" - -all: dev - -dev: MY_GOFLAGS = -ldflags "-s -w -X main.gitCommit=$(shell git rev-parse --short HEAD) -X main.gitBranch=$(shell git rev-parse --abbrev-ref HEAD)" -dev: build - -build: - go build $(MY_GOFLAGS) - -install: - install -v -d "$(DESTDIR)$(BINDIR)/" && install -m 0755 -v hilbish "$(DESTDIR)$(BINDIR)/hilbish" - mkdir -p "$(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: - rm -vrf \ - "$(DESTDIR)$(BINDIR)/hilbish" \ - "$(DESTDIR)$(LIBDIR)" - sed -i '/hilbish/d' /etc/shells - -clean: - go clean - -.PHONY: all dev build install uninstall clean diff --git a/README.md b/README.md index bb2ca29..86879d1 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ If you're new to nix you should probably read up on how to do that [here](https: ## Manual Build ### Prerequisites - [Go 1.17+](https://go.dev) +- [Task](https://taskfile.dev/#/) ### Build First, clone Hilbish. The recursive is required, as some Lua libraries @@ -78,30 +79,16 @@ go get -d ./... To build, run: ``` -make dev +task ``` Or, if you want a stable branch, run these commands: ``` git checkout $(git describe --tags `git rev-list --tags --max-count=1`) -make build +task build ``` -After you did all that, run `sudo make install` to install Hilbish globally. - -# Getting Started -At startup, you should see a message which says to run a `guide` command. -This guide is a *very* simple and basic step through text of what Hilbish is -and where to find documentation. - -Documentation is primarily viewed via the in shell `doc` command. -Autogenerated function docs and general docs about other things are included -there, so be sure to read it. - -Using Hilbish is the same as using any other Linux shell, with an addition -that you can also run Lua. Hilbish can also act as an enhanced Lua REPL -via `hilbish.runnerMode 'lua'`. To switch back to normal, use -`hilbish.runnerMode 'hybrid'`. +After you did all that, run `sudo task install` to install Hilbish globally. # Contributing Any kind of contributions are welcome! Hilbish is very easy to contribute to. diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 0000000..067f2ba --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,36 @@ +# https://taskfile.dev + +version: '3' + +vars: + PREFIX: '{{default "/usr" .PREFIX}}' + bindir__: '{{.PREFIX}}/bin' + BINDIR: '{{default .bindir__ .BINDIR}}' + libdir__: '{{.PREFIX}}/share/hilbish' + LIBDIR: '{{default .libdir__ .LIBDIR}}' + GOFLAGS: '-ldflags "-s -w"' + +tasks: + default: + cmds: + - go build {{.GOFLAGS}} + vars: + GOFLAGS: '-ldflags "-s -w -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"' + + build: + cmds: + - go build {{.GOFLAGS}} + + install: + cmds: + - install -v -d "{{.DESTDIR}}{{.BINDIR}}/" && install -m 0755 -v hilbish "{{.DESTDIR}}{{.BINDIR}}/hilbish" + - mkdir -p "{{.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: + cmds: + - rm -vrf + "{{.DESTDIR}}{{.BINDIR}}/hilbish" + "{{.DESTDIR}}{{.LIBDIR}}" + - sed -i '/hilbish/d' /etc/shells diff --git a/api.go b/api.go index 073aa94..67b2a1c 100644 --- a/api.go +++ b/api.go @@ -44,7 +44,6 @@ var exports = map[string]util.LuaExport{ "which": {hlwhich, 1, false}, } -var greeting string var hshMod *rt.Table var hilbishLoader = packagelib.Loader{ Load: hilbishLoad, @@ -103,10 +102,6 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) { username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows } - greeting = `Welcome to {magenta}Hilbish{reset}, {cyan}` + username + `{reset}. -The nice lil shell for {blue}Lua{reset} fanatics! -Check out the {blue}{bold}guide{reset} command to get started. -` util.SetFieldProtected(fakeMod, mod, "ver", rt.StringValue(getVersion()), "Hilbish version") util.SetFieldProtected(fakeMod, mod, "user", rt.StringValue(username), "Username of user") util.SetFieldProtected(fakeMod, mod, "host", rt.StringValue(host), "Host name of the machine") @@ -114,7 +109,6 @@ Check out the {blue}{bold}guide{reset} command to get started. util.SetFieldProtected(fakeMod, mod, "dataDir", rt.StringValue(dataDir), "Directory for Hilbish's data files") util.SetFieldProtected(fakeMod, mod, "interactive", rt.BoolValue(interactive), "If this is an interactive shell") util.SetFieldProtected(fakeMod, mod, "login", rt.BoolValue(login), "Whether this is a login shell") - util.SetFieldProtected(fakeMod, mod, "greeting", rt.StringValue(greeting), "Hilbish's welcome message for interactive shells. It has Lunacolors formatting.") util.SetFieldProtected(fakeMod, mod, "vimMode", rt.NilValue, "Current Vim mode of Hilbish (nil if not in Vim mode)") util.SetFieldProtected(fakeMod, mod, "exitCode", rt.IntValue(0), "Exit code of last exected command") util.Document(fakeMod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.") diff --git a/complete.go b/complete.go index 01a8137..3a2899d 100644 --- a/complete.go +++ b/complete.go @@ -11,8 +11,34 @@ import ( rt "github.com/arnodel/golua/runtime" ) +func splitQuote(str string) []string { + split := []string{} + sb := &strings.Builder{} + quoted := false + + for _, r := range str { + if r == '"' { + quoted = !quoted + sb.WriteRune(r) + } else if !quoted && r == ' ' { + split = append(split, sb.String()) + sb.Reset() + } else { + sb.WriteRune(r) + } + } + + if sb.Len() > 0 { + split = append(split, sb.String()) + } + + return split +} + func fileComplete(query, ctx string, fields []string) ([]string, string) { - return matchPath(query) + q := splitQuote(ctx) + + return matchPath(q[len(q) - 1]) } func binaryComplete(query, ctx string, fields []string) ([]string, string) { @@ -68,6 +94,8 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) { } func matchPath(query string) ([]string, string) { + oldQuery := query + query = strings.TrimPrefix(query, "\"") var entries []string var baseName string @@ -87,7 +115,9 @@ func matchPath(query string) ([]string, string) { if file.IsDir() { entry = entry + string(os.PathSeparator) } - entry = escapeFilename(entry) + if !strings.HasPrefix(oldQuery, "\"") { + entry = escapeFilename(entry) + } entries = append(entries, entry) } } diff --git a/docs/fs.txt b/docs/fs.txt index c3d173e..8372afd 100644 --- a/docs/fs.txt +++ b/docs/fs.txt @@ -11,6 +11,9 @@ filepath.Dir glob(pattern) > Glob all files and directories that match the pattern. For the rules, see Go's filepath.Glob +join(paths...) > Takes paths and joins them together with the OS's +directory separator (forward or backward slash). + mkdir(name, recursive) > Makes a directory called `name`. If `recursive` is true, it will create its parent directories. readdir(dir) > Returns a table of files in `dir` diff --git a/emmyLuaDocs/fs.lua b/emmyLuaDocs/fs.lua index 5fbfb2b..14e7be4 100644 --- a/emmyLuaDocs/fs.lua +++ b/emmyLuaDocs/fs.lua @@ -22,6 +22,10 @@ function fs.dir() end --- For the rules, see Go's filepath.Glob function fs.glob() end +--- Takes paths and joins them together with the OS's +--- directory separator (forward or backward slash). +function fs.join() end + --- Makes a directory called `name`. If `recursive` is true, it will create its parent directories. --- @param name string --- @param recursive boolean diff --git a/exec.go b/exec.go index cc5016a..e1862ed 100644 --- a/exec.go +++ b/exec.go @@ -540,13 +540,9 @@ func splitInput(input string) ([]string, string) { } func cmdFinish(code uint8, cmdstr string, private bool) { - // if input has space at the beginning, dont put in history - if interactive && !private { - handleHistory(cmdstr) - } util.SetField(l, hshMod, "exitCode", rt.IntValue(int64(code)), "Exit code of last exected command") // using AsValue (to convert to lua type) on an interface which is an int // results in it being unknown in lua .... ???? // so we allow the hook handler to take lua runtime Values - hooks.Em.Emit("command.exit", rt.IntValue(int64(code)), cmdstr) + hooks.Em.Emit("command.exit", rt.IntValue(int64(code)), cmdstr, private) } diff --git a/golibs/fs/fs.go b/golibs/fs/fs.go index 88a04c5..5b12e73 100644 --- a/golibs/fs/fs.go +++ b/golibs/fs/fs.go @@ -1,6 +1,7 @@ package fs import ( + "fmt" "path/filepath" "strconv" "os" @@ -27,6 +28,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) { "basename": util.LuaExport{fbasename, 1, false}, "dir": util.LuaExport{fdir, 1, false}, "glob": util.LuaExport{fglob, 1, false}, + "join": util.LuaExport{fjoin, 0, true}, } mod := rt.NewTable() util.SetExports(rtm, mod, exports) @@ -216,3 +218,21 @@ func fglob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext(t.Runtime, rt.TableValue(luaMatches)), nil } + +// join(paths...) +// Takes paths and joins them together with the OS's +// directory separator (forward or backward slash). +func fjoin(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { + strs := make([]string, len(c.Etc())) + for i, v := range c.Etc() { + if v.Type() != rt.StringType { + // +2; go indexes of 0 and first arg from above + return nil, fmt.Errorf("bad argument #%d to run (expected string, got %s)", i + 1, v.TypeName()) + } + strs[i] = v.AsString() + } + + res := filepath.Join(strs...) + + return c.PushingNext(t.Runtime, rt.StringValue(res)), nil +} diff --git a/history.go b/history.go index b666515..a8eb089 100644 --- a/history.go +++ b/history.go @@ -4,21 +4,69 @@ import ( "errors" "io/fs" "os" + "path/filepath" "strings" + + rt "github.com/arnodel/golua/runtime" ) +type luaHistory struct {} + +func (h *luaHistory) Write(line string) (int, error) { + histWrite := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("add")) + ln, err := rt.Call1(l.MainThread(), histWrite, rt.StringValue(line)) + + var num int64 + if ln.Type() == rt.IntType { + num = ln.AsInt() + } + + return int(num), err +} + +func (h *luaHistory) GetLine(idx int) (string, error) { + histGet := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("get")) + lcmd, err := rt.Call1(l.MainThread(), histGet, rt.IntValue(int64(idx))) + + var cmd string + if lcmd.Type() == rt.StringType { + cmd = lcmd.AsString() + } + + return cmd, err +} + +func (h *luaHistory) Len() int { + histSize := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("size")) + ln, _ := rt.Call1(l.MainThread(), histSize) + + var num int64 + if ln.Type() == rt.IntType { + num = ln.AsInt() + } + + return int(num) +} + +func (h *luaHistory) Dump() interface{} { + // hilbish.history interface already has all function, this isnt used in readline + return nil +} + type fileHistory struct { items []string f *os.File } -func newFileHistory() *fileHistory { - err := os.MkdirAll(defaultHistDir, 0755) +func newFileHistory(path string) *fileHistory { + dir := filepath.Dir(path) + + err := os.MkdirAll(dir, 0755) if err != nil { panic(err) } - data, err := os.ReadFile(defaultHistPath) + data, err := os.ReadFile(path) if err != nil { if !errors.Is(err, fs.ErrNotExist) { panic(err) @@ -33,7 +81,7 @@ func newFileHistory() *fileHistory { } itms = append(itms, l) } - f, err := os.OpenFile(defaultHistPath, os.O_APPEND | os.O_WRONLY | os.O_CREATE, 0755) + f, err := os.OpenFile(path, os.O_APPEND | os.O_WRONLY | os.O_CREATE, 0755) if err != nil { panic(err) } diff --git a/init_windows.go b/init_windows.go index ee17a6b..825069d 100644 --- a/init_windows.go +++ b/init_windows.go @@ -5,7 +5,13 @@ package main import "golang.org/x/sys/windows" func init() { - var mode uint32 - windows.GetConsoleMode(windows.Stdout, &mode) - windows.SetConsoleMode(windows.Stdout, mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + // vt output (escape codes) + var outMode uint32 + windows.GetConsoleMode(windows.Stdout, &outMode) + windows.SetConsoleMode(windows.Stdout, outMode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + + // vt input + var inMode uint32 + windows.GetConsoleMode(windows.Stdin, &inMode) + windows.SetConsoleMode(windows.Stdin, inMode | windows.ENABLE_VIRTUAL_TERMINAL_INPUT) } diff --git a/lua.go b/lua.go index 8f3c0fb..92ece05 100644 --- a/lua.go +++ b/lua.go @@ -12,12 +12,16 @@ import ( rt "github.com/arnodel/golua/runtime" "github.com/arnodel/golua/lib" + "github.com/arnodel/golua/lib/debuglib" ) var minimalconf = `hilbish.prompt '& '` func luaInit() { l = rt.New(os.Stdout) + l.PushContext(rt.RuntimeContextDef{ + MessageHandler: debuglib.Traceback, + }) lib.LoadAll(l) lib.LoadLibs(l, hilbishLoader) @@ -48,6 +52,10 @@ func luaInit() { } }) + lr.rl.RawInputCallback = func(r []rune) { + hooks.Em.Emit("hilbish.rawInput", string(r)) + } + // Add more paths that Lua can require from err := util.DoString(l, "package.path = package.path .. " + requirePaths) if err != nil { diff --git a/main.go b/main.go index 9421bfc..e53055d 100644 --- a/main.go +++ b/main.go @@ -116,8 +116,8 @@ func main() { } go handleSignals() - luaInit() lr = newLineReader("", false) + luaInit() // If user's config doesn't exixt, if _, err := os.Stat(defaultConfPath); os.IsNotExist(err) && *configflag == defaultConfPath { // Read default from current directory @@ -138,6 +138,7 @@ func main() { } else { runConfig(*configflag) } + hooks.Em.Emit("hilbish.init") if fileInfo, _ := os.Stdin.Stat(); (fileInfo.Mode() & os.ModeCharDevice) == 0 { scanner := bufio.NewScanner(bufio.NewReader(os.Stdin)) @@ -268,11 +269,6 @@ func fmtPrompt(prompt string) string { return nprompt } -func handleHistory(cmd string) { - lr.AddHistory(cmd) - // TODO: load history again (history shared between sessions like this ye) -} - func removeDupes(slice []string) []string { all := make(map[string]bool) newSlice := []string{} diff --git a/nature/commands/guide.lua b/nature/commands/guide.lua deleted file mode 100644 index 1c1e346..0000000 --- a/nature/commands/guide.lua +++ /dev/null @@ -1,54 +0,0 @@ -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 index 8ecbf86..13b33be 100644 --- a/nature/commands/init.lua +++ b/nature/commands/init.lua @@ -3,7 +3,6 @@ require 'nature.commands.cd' require 'nature.commands.cdr' require 'nature.commands.doc' require 'nature.commands.exit' -require 'nature.commands.guide' require 'nature.commands.disown' require 'nature.commands.fg' require 'nature.commands.bg' diff --git a/nature/opts/greeting.lua b/nature/opts/greeting.lua new file mode 100644 index 0000000..ed408d7 --- /dev/null +++ b/nature/opts/greeting.lua @@ -0,0 +1,8 @@ +local bait = require 'bait' +local lunacolors = require 'lunacolors' + +bait.catch('hilbish.init', function() + if hilbish.interactive and type(hilbish.opts.greeting) == 'string' then + print(lunacolors.format(hilbish.opts.greeting)) + end +end) diff --git a/nature/opts/history.lua b/nature/opts/history.lua new file mode 100644 index 0000000..f7ab1d7 --- /dev/null +++ b/nature/opts/history.lua @@ -0,0 +1,5 @@ +local bait = require 'bait' + +bait.catch('command.exit', function(_, cmd, priv) + if not priv and hilbish.opts.history then hilbish.history.add(cmd) end +end) diff --git a/nature/opts/init.lua b/nature/opts/init.lua index 59d3cbd..ae95ee1 100644 --- a/nature/opts/init.lua +++ b/nature/opts/init.lua @@ -20,7 +20,12 @@ local function setupOpt(name, default) end local defaultOpts = { - autocd = false + autocd = false, + history = true, + greeting = string.format([[Welcome to {magenta}Hilbish{reset}, {cyan}%s{reset}. +The nice lil shell for {blue}Lua{reset} fanatics! +]], hilbish.user), + motd = true } for optsName, default in pairs(defaultOpts) do diff --git a/nature/opts/motd.lua b/nature/opts/motd.lua new file mode 100644 index 0000000..b22f5a2 --- /dev/null +++ b/nature/opts/motd.lua @@ -0,0 +1,13 @@ +local bait = require 'bait' +local lunacolors = require 'lunacolors' + +hilbish.motd = [[ +Hilbish 2.0 is a {red}major{reset} update! If your config doesn't work +anymore, that will definitely be why! A MOTD, very message, much day. +]] + +bait.catch('hilbish.init', function() + if hilbish.opts.motd then + print(lunacolors.format(hilbish.motd)) + end +end) diff --git a/readline/instance.go b/readline/instance.go index f04811e..fcd8379 100644 --- a/readline/instance.go +++ b/readline/instance.go @@ -198,6 +198,8 @@ type Instance struct { ViModeCallback func(ViMode) ViActionCallback func(ViAction, []string) + + RawInputCallback func([]rune) // called on all input } // NewInstance is used to create a readline instance and initialise it with sane defaults. diff --git a/readline/readline.go b/readline/readline.go index c00fda9..731e297 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -94,6 +94,9 @@ func (rl *Instance) Readline() (string, error) { rl.skipStdinRead = false r := []rune(string(b)) + if rl.RawInputCallback != nil { + rl.RawInputCallback(r[:i]) + } if isMultiline(r[:i]) || len(rl.multiline) > 0 { rl.multiline = append(rl.multiline, b[:i]...) diff --git a/rl.go b/rl.go index 88adc65..6350aa2 100644 --- a/rl.go +++ b/rl.go @@ -13,18 +13,22 @@ import ( type lineReader struct { rl *readline.Instance + fileHist *fileHistory } -var fileHist *fileHistory var hinter *rt.Closure var highlighter *rt.Closure func newLineReader(prompt string, noHist bool) *lineReader { rl := readline.NewInstance() + lr := &lineReader{ + rl: rl, + } + // we don't mind hilbish.read rl instances having completion, // but it cant have shared history if !noHist { - fileHist = newFileHistory() - rl.SetHistoryCtrlR("History", fileHist) + lr.fileHist = newFileHistory(defaultHistPath) + rl.SetHistoryCtrlR("History", &luaHistory{}) rl.HistoryAutoWrite = false } rl.ShowVimMode = false @@ -171,9 +175,7 @@ func newLineReader(prompt string, noHist bool) *lineReader { return pfx, compGroups } - return &lineReader{ - rl, - } + return lr } func (lr *lineReader) Read() (string, error) { @@ -212,7 +214,7 @@ func (lr *lineReader) SetRightPrompt(p string) { } func (lr *lineReader) AddHistory(cmd string) { - fileHist.Write(cmd) + lr.fileHist.Write(cmd) } func (lr *lineReader) ClearInput() { @@ -253,7 +255,7 @@ func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) } func (lr *lineReader) luaSize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - return c.PushingNext1(t.Runtime, rt.IntValue(int64(fileHist.Len()))), nil + return c.PushingNext1(t.Runtime, rt.IntValue(int64(lr.fileHist.Len()))), nil } func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { @@ -265,17 +267,17 @@ func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) return nil, err } - cmd, _ := fileHist.GetLine(int(idx)) + cmd, _ := lr.fileHist.GetLine(int(idx)) return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil } func (lr *lineReader) luaAllHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { tbl := rt.NewTable() - size := fileHist.Len() + size := lr.fileHist.Len() for i := 1; i < size; i++ { - cmd, _ := fileHist.GetLine(i) + cmd, _ := lr.fileHist.GetLine(i) tbl.Set(rt.IntValue(int64(i)), rt.StringValue(cmd)) } @@ -283,6 +285,6 @@ func (lr *lineReader) luaAllHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) } func (lr *lineReader) luaClearHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - fileHist.clear() + lr.fileHist.clear() return c.Next(), nil } diff --git a/vars_windows.go b/vars_windows.go index a257baf..403941f 100644 --- a/vars_windows.go +++ b/vars_windows.go @@ -2,13 +2,15 @@ package main +import "hilbish/util" + // String vars that are free to be changed at compile time var ( requirePaths = commonRequirePaths + `.. ';' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?\\init.lua;' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?\\?.lua;' .. hilbish.userDir.config .. '\\Hilbish\\libs\\?.lua;'` - dataDir = "~\\Appdata\\Roaming\\Hilbish" // ~ and \ gonna cry? + dataDir = util.ExpandHome("~\\Appdata\\Roaming\\Hilbish") // ~ and \ gonna cry? preloadPath = dataDir + "\\nature\\init.lua" sampleConfPath = dataDir + "\\hilbishrc.lua" // Path to default/sample config defaultConfDir = ""