mirror of https://github.com/Hilbis/Hilbish
chore: update branch
commit
477fcaf980
|
@ -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:
|
||||
|
|
|
@ -9,8 +9,6 @@ local function doPrompt(fail)
|
|||
))
|
||||
end
|
||||
|
||||
print(lunacolors.format(hilbish.greeting))
|
||||
|
||||
doPrompt()
|
||||
|
||||
bait.catch('command.exit', function(code)
|
||||
|
|
28
CHANGELOG.md
28
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.
|
||||
|
@ -73,11 +86,16 @@ 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.
|
||||
|
||||
- **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
|
||||
|
|
30
Makefile
30
Makefile
|
@ -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
|
21
README.md
21
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.
|
||||
|
|
|
@ -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
|
6
api.go
6
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.")
|
||||
|
|
32
complete.go
32
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)
|
||||
}
|
||||
if !strings.HasPrefix(oldQuery, "\"") {
|
||||
entry = escapeFilename(entry)
|
||||
}
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
|
|
6
exec.go
6
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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
56
history.go
56
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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
8
lua.go
8
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 {
|
||||
|
|
8
main.go
8
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{}
|
||||
|
|
|
@ -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)
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
|
@ -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]...)
|
||||
|
|
26
rl.go
26
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
|
||||
}
|
||||
|
|
|
@ -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 = ""
|
||||
|
|
Loading…
Reference in New Issue