mirror of https://github.com/Hilbis/Hilbish
Compare commits
No commits in common. "123f8992b1b258bd649ea351ecb25ea9afc43dff" and "35e648b7bc3269c3c52d804a4ce4627e58d03abd" have entirely different histories.
123f8992b1
...
35e648b7bc
1
go.mod
1
go.mod
|
@ -4,7 +4,6 @@ go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650
|
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650
|
||||||
github.com/Rosettea/readline v0.0.0-20211122152601-6d95ce44b7ed
|
|
||||||
github.com/bobappleyard/readline v0.0.0-20150707195538-7e300e02d38e
|
github.com/bobappleyard/readline v0.0.0-20150707195538-7e300e02d38e
|
||||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9
|
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,7 +1,5 @@
|
||||||
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650 h1:nzFJUdJU8UJ1DA8mSQp4eoBtQyOJyecekVWusjfQsqE=
|
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650 h1:nzFJUdJU8UJ1DA8mSQp4eoBtQyOJyecekVWusjfQsqE=
|
||||||
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650/go.mod h1:/FFZ4cgR6TXXYaskRUxyLIYdfG0PS4BPtWjWRQms754=
|
github.com/Rosettea/Hilbiline v0.0.0-20210603231612-80054dac3650/go.mod h1:/FFZ4cgR6TXXYaskRUxyLIYdfG0PS4BPtWjWRQms754=
|
||||||
github.com/Rosettea/readline v0.0.0-20211122152601-6d95ce44b7ed h1:sGsGPG+b5h9OR1GjM0PiM4iemB9hmi0o8cg2YRSRKko=
|
|
||||||
github.com/Rosettea/readline v0.0.0-20211122152601-6d95ce44b7ed/go.mod h1:OH+WJSCks0t2ISvaCFUT4ZxNGr4Etq4ju9JE/UxH/5o=
|
|
||||||
github.com/Rosettea/sh/v3 v3.3.0 h1:0/xmOfzpy46gB1I2oPj8QwdYvyJzpdF5STcgNPRQHcI=
|
github.com/Rosettea/sh/v3 v3.3.0 h1:0/xmOfzpy46gB1I2oPj8QwdYvyJzpdF5STcgNPRQHcI=
|
||||||
github.com/Rosettea/sh/v3 v3.3.0/go.mod h1:dh3avhLDhJJ/MJKzbak6FYn+DJKUWk7Fb6Dh5mGdv6Y=
|
github.com/Rosettea/sh/v3 v3.3.0/go.mod h1:dh3avhLDhJJ/MJKzbak6FYn+DJKUWk7Fb6Dh5mGdv6Y=
|
||||||
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20211022004519-f67a49cb50f5 h1:ygwVRX8gf5MHA0VzSgOdscCEoAJLjM8joEotfQPgAd0=
|
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20211022004519-f67a49cb50f5 h1:ygwVRX8gf5MHA0VzSgOdscCEoAJLjM8joEotfQPgAd0=
|
||||||
|
|
16
lua.go
16
lua.go
|
@ -58,8 +58,6 @@ func LuaInit() {
|
||||||
hooks = bait.New()
|
hooks = bait.New()
|
||||||
l.PreloadModule("bait", hooks.Loader)
|
l.PreloadModule("bait", hooks.Loader)
|
||||||
|
|
||||||
l.SetGlobal("complete", l.NewFunction(hshcomplete))
|
|
||||||
|
|
||||||
// Add more paths that Lua can require from
|
// Add more paths that Lua can require from
|
||||||
l.DoString("package.path = package.path .. " + requirePaths)
|
l.DoString("package.path = package.path .. " + requirePaths)
|
||||||
|
|
||||||
|
@ -212,17 +210,3 @@ func hshinterval(L *lua.LState) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete(scope, cb)
|
|
||||||
// Registers a completion handler for `scope`.
|
|
||||||
// A `scope` is currently only expected to be `command.<cmd>`,
|
|
||||||
// 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.
|
|
||||||
// Nested tables will be used as sub-completions.
|
|
||||||
func hshcomplete(L *lua.LState) int {
|
|
||||||
scope := L.CheckString(1)
|
|
||||||
cb := L.CheckFunction(2)
|
|
||||||
|
|
||||||
luaCompletions[scope] = cb
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
19
main.go
19
main.go
|
@ -5,19 +5,18 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
|
|
||||||
"github.com/pborman/getopt"
|
"github.com/pborman/getopt"
|
||||||
"github.com/yuin/gopher-lua"
|
"github.com/yuin/gopher-lua"
|
||||||
"golang.org/x/term"
|
|
||||||
"layeh.com/gopher-luar"
|
"layeh.com/gopher-luar"
|
||||||
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -26,7 +25,6 @@ var (
|
||||||
|
|
||||||
commands = map[string]*lua.LFunction{}
|
commands = map[string]*lua.LFunction{}
|
||||||
aliases = map[string]string{}
|
aliases = map[string]string{}
|
||||||
luaCompletions = map[string]*lua.LFunction{}
|
|
||||||
|
|
||||||
homedir string
|
homedir string
|
||||||
confDir string
|
confDir string
|
||||||
|
@ -260,22 +258,15 @@ func fmtPrompt() string {
|
||||||
// do i even have to say
|
// do i even have to say
|
||||||
func HandleSignals() {
|
func HandleSignals() {
|
||||||
c := make(chan os.Signal)
|
c := make(chan os.Signal)
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGWINCH)
|
signal.Notify(c, os.Interrupt)
|
||||||
|
|
||||||
for s := range c {
|
for range c {
|
||||||
switch s {
|
|
||||||
case os.Interrupt:
|
|
||||||
if !running {
|
if !running {
|
||||||
if !interactive {
|
if !interactive {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
lr.ClearInput()
|
lr.ClearInput()
|
||||||
}
|
}
|
||||||
case syscall.SIGWINCH:
|
|
||||||
if !running {
|
|
||||||
lr.Resize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
144
rl.go
144
rl.go
|
@ -1,4 +1,3 @@
|
||||||
//go:build !hilbiline
|
|
||||||
// +build !hilbiline
|
// +build !hilbiline
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -7,149 +6,15 @@ package main
|
||||||
// making them interchangable during build time
|
// making them interchangable during build time
|
||||||
// this is normal readline
|
// this is normal readline
|
||||||
|
|
||||||
import (
|
import "github.com/bobappleyard/readline"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/Rosettea/readline"
|
|
||||||
"github.com/yuin/gopher-lua"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LineReader struct {
|
type LineReader struct {
|
||||||
Prompt string
|
Prompt string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// other gophers might hate this naming but this is local, shut up
|
||||||
func NewLineReader(prompt string) *LineReader {
|
func NewLineReader(prompt string) *LineReader {
|
||||||
readline.Completer = func(query string, ctx string) []string {
|
readline.Completer = readline.FilenameCompleter
|
||||||
var completions []string
|
|
||||||
// trim whitespace from ctx
|
|
||||||
ctx = strings.TrimLeft(ctx, " ")
|
|
||||||
fields := strings.Split(ctx, " ")
|
|
||||||
|
|
||||||
if len(fields) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fields) == 1 {
|
|
||||||
prefixes := []string{"./", "../"}
|
|
||||||
for _, prefix := range prefixes {
|
|
||||||
if strings.HasPrefix(query, prefix) {
|
|
||||||
if matches, err := filepath.Glob(query + "*"); err == nil {
|
|
||||||
for _, match := range matches {
|
|
||||||
if info, err := os.Stat(match); err == nil && info.Mode().Perm() & 0100 == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := filepath.Base(match)
|
|
||||||
completions = append(completions, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(completions) == 1 {
|
|
||||||
// we have add the base dir of query since the completion entries are basename
|
|
||||||
// why? so readline will display just that
|
|
||||||
// and we want to complete the full path when its the only completion entry
|
|
||||||
// query will be incomplete so adding it will be broken
|
|
||||||
// also Dir doesn't have a trailing slash so we need to filepath join
|
|
||||||
// to account to windows
|
|
||||||
// AND ANOTHER THING is it returns . if the arg is ./ and Join will
|
|
||||||
// ignore that so we have to check and just add the prefix instead
|
|
||||||
if prefix != "./" {
|
|
||||||
completions[0] = filepath.Join(filepath.Dir(query), completions[0])
|
|
||||||
} else {
|
|
||||||
completions[0] = prefix + completions[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
|
|
||||||
// print dir to stderr for debugging
|
|
||||||
// search for an executable which matches our query string
|
|
||||||
if matches, err := filepath.Glob(filepath.Join(dir, query + "*")); err == nil {
|
|
||||||
// get basename from matches
|
|
||||||
for _, match := range matches {
|
|
||||||
// check if we have execute permissions for our match
|
|
||||||
if info, err := os.Stat(match); err == nil && info.Mode().Perm() & 0100 == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// get basename from match
|
|
||||||
name := filepath.Base(match)
|
|
||||||
// print name to stderr for debugging
|
|
||||||
// add basename to completions
|
|
||||||
completions = append(completions, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add lua registered commands to completions
|
|
||||||
for cmdName := range commands {
|
|
||||||
if strings.HasPrefix(cmdName, query) {
|
|
||||||
completions = append(completions, cmdName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if completecb, ok := luaCompletions["command." + fields[0]]; ok {
|
|
||||||
err := l.CallByParam(lua.P{
|
|
||||||
Fn: completecb,
|
|
||||||
NRet: 1,
|
|
||||||
Protect: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
luacompleteTable := l.Get(-1)
|
|
||||||
l.Pop(1)
|
|
||||||
|
|
||||||
if cmpTbl, ok := luacompleteTable.(*lua.LTable); ok {
|
|
||||||
cmpTbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
|
||||||
// print key and value to stderr for debugging
|
|
||||||
// if key is a number (index), we just check and complete that
|
|
||||||
if key.Type() == lua.LTNumber {
|
|
||||||
// if we have only 2 fields then this is fine
|
|
||||||
if len(fields) == 2 {
|
|
||||||
if strings.HasPrefix(value.String(), fields[1]) {
|
|
||||||
completions = append(completions, value.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if key.Type() == lua.LTString {
|
|
||||||
if len(fields) == 2 {
|
|
||||||
if strings.HasPrefix(key.String(), fields[1]) {
|
|
||||||
completions = append(completions, key.String())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if we have more than 2 fields, we need to check if the key matches
|
|
||||||
// the current field and if it does, we need to check if the value is a string
|
|
||||||
// or table (nested sub completions)
|
|
||||||
if key.String() == fields[1] {
|
|
||||||
// if value is a table, we need to iterate over it
|
|
||||||
// and add each value to completions
|
|
||||||
valueTbl := value.(*lua.LTable)
|
|
||||||
valueTbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
|
||||||
val := value.String()
|
|
||||||
if val == "<file>" {
|
|
||||||
// complete files
|
|
||||||
completions = append(completions, readline.FilenameCompleter(query, ctx)...)
|
|
||||||
} else {
|
|
||||||
if strings.HasPrefix(val, query) {
|
|
||||||
completions = append(completions, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(completions) == 0 {
|
|
||||||
completions = readline.FilenameCompleter(query, ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completions
|
|
||||||
}
|
|
||||||
readline.LoadHistory(defaultHistPath)
|
readline.LoadHistory(defaultHistPath)
|
||||||
|
|
||||||
return &LineReader{
|
return &LineReader{
|
||||||
|
@ -176,6 +41,3 @@ func (lr *LineReader) ClearInput() {
|
||||||
readline.RefreshLine()
|
readline.RefreshLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lr *LineReader) Resize() {
|
|
||||||
readline.Resize()
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,7 +37,3 @@ func (lr *LineReader) ClearInput() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lr *LineReader) Resize() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
2
vars.go
2
vars.go
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
// String vars that are free to be changed at compile time
|
// String vars that are free to be changed at compile time
|
||||||
var (
|
var (
|
||||||
version = "v0.7.0"
|
version = "v0.6.1"
|
||||||
defaultConfDir = "" // ~ will be substituted for home, path for user's default config
|
defaultConfDir = "" // ~ will be substituted for home, path for user's default config
|
||||||
defaultHistDir = ""
|
defaultHistDir = ""
|
||||||
commonRequirePaths = "';./libs/?/init.lua;./?/init.lua;./?/?.lua'"
|
commonRequirePaths = "';./libs/?/init.lua;./?/init.lua;./?/?.lua'"
|
||||||
|
|
Loading…
Reference in New Issue