mirror of https://github.com/Hilbis/Hilbish
Compare commits
14 Commits
84ec3d085d
...
123f8992b1
Author | SHA1 | Date |
---|---|---|
TorchedSammy | 123f8992b1 | |
TorchedSammy | 77cc7fe24a | |
TorchedSammy | 5a258ce68e | |
TorchedSammy | 35e648b7bc | |
TorchedSammy | 06272778f8 | |
sammyette | 2f816c33cd | |
sammyette | 9b66547803 | |
sammyette | e06765abc3 | |
sammyette | 2073752e7e | |
sammyette | 174d67c9e1 | |
sammyette | c360ac7126 | |
sammyette | f46d4c7024 | |
sammyette | d3c50aa227 | |
sammyette | 1ee8827c9c |
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -2,8 +2,18 @@
|
||||||
|
|
||||||
This is the changelog for the Hilbish shell made in Go and Lua.
|
This is the changelog for the Hilbish shell made in Go and Lua.
|
||||||
|
|
||||||
|
## [0.6.1] - 2021-10-21
|
||||||
|
### Fixed
|
||||||
|
- Require paths now use the `dataDir` variable so there is no need to change it anymore unless you want to add more paths
|
||||||
|
- Remove double slash in XDG data require paths
|
||||||
|
- Ctrl+C is handled properly when not interactive and won't result in a panic anymore
|
||||||
|
- Commanders are handled by the sh interpreter library only now, so they work with sh syntax
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Error messages from `fs` functions now include the path provided
|
||||||
|
|
||||||
## [0.6.0] - 2021-10-17
|
## [0.6.0] - 2021-10-17
|
||||||
## Added
|
### Added
|
||||||
- Hilbish will expand `~` in the preloadPath and samplePathConf variables. These are for compile time.
|
- Hilbish will expand `~` in the preloadPath and samplePathConf variables. These are for compile time.
|
||||||
- On Windows, the hostname in `%u` has been removed.
|
- On Windows, the hostname in `%u` has been removed.
|
||||||
- Made it easier to compile on Windows by adding Windows-tailored vars and paths.
|
- Made it easier to compile on Windows by adding Windows-tailored vars and paths.
|
||||||
|
@ -24,13 +34,13 @@ This is the changelog for the Hilbish shell made in Go and Lua.
|
||||||
- The [Succulent](https://github.com/Rosettea/Succulent) library has been added. This includes more utility functions and expansions to the Lua standard library itself.
|
- The [Succulent](https://github.com/Rosettea/Succulent) library has been added. This includes more utility functions and expansions to the Lua standard library itself.
|
||||||
- The command string is now passed to the `command.exit` hook
|
- The command string is now passed to the `command.exit` hook
|
||||||
|
|
||||||
# Changed
|
### Changed
|
||||||
- Hilbish won't print an extra newline at exit with ctrl + d
|
- Hilbish won't print an extra newline at exit with ctrl + d
|
||||||
- `command.exit` with 0 exit code will now be thrown if input is nothing
|
- `command.exit` with 0 exit code will now be thrown if input is nothing
|
||||||
- **Breaking Change:** `fs.stat` has been made better. It returns a proper table instead of userdata, and has fields instead of functions
|
- **Breaking Change:** `fs.stat` has been made better. It returns a proper table instead of userdata, and has fields instead of functions
|
||||||
- It includes `name`, `mode` as a octal representation in a string, `isDir`, and `size`
|
- It includes `name`, `mode` as a octal representation in a string, `isDir`, and `size`
|
||||||
|
|
||||||
# Fixed
|
### Fixed
|
||||||
- `timeout()` is now blocking
|
- `timeout()` is now blocking
|
||||||
- Directories with spaces in them can now be `cd`'d to
|
- Directories with spaces in them can now be `cd`'d to
|
||||||
- An alias with the same name as the command will now not cause a freeze (#73)
|
- An alias with the same name as the command will now not cause a freeze (#73)
|
||||||
|
@ -40,15 +50,15 @@ This is the changelog for the Hilbish shell made in Go and Lua.
|
||||||
|
|
||||||
## [0.5.1] - 2021-06-16
|
## [0.5.1] - 2021-06-16
|
||||||
|
|
||||||
## Added
|
### Added
|
||||||
|
|
||||||
- Add `~/.config/hilbish` as a require path
|
- Add `~/.config/hilbish` as a require path
|
||||||
|
|
||||||
## Changed
|
### Changed
|
||||||
|
|
||||||
- `cd` hook is only thrown after directory has actually changed
|
- `cd` hook is only thrown after directory has actually changed
|
||||||
|
|
||||||
## Fixed
|
### Fixed
|
||||||
|
|
||||||
- Handle error in commander properly, preventing a panic from Lua
|
- Handle error in commander properly, preventing a panic from Lua
|
||||||
|
|
||||||
|
@ -56,7 +66,7 @@ This is the changelog for the Hilbish shell made in Go and Lua.
|
||||||
|
|
||||||
An absolutely massive release. Probably the biggest yet, includes a bunch of fixes and new features and convenient additions to the Lua API.
|
An absolutely massive release. Probably the biggest yet, includes a bunch of fixes and new features and convenient additions to the Lua API.
|
||||||
|
|
||||||
## Added
|
### Added
|
||||||
|
|
||||||
- `-n` flag, which checks Lua for syntax errors without running it
|
- `-n` flag, which checks Lua for syntax errors without running it
|
||||||
- `exec(command)` function, acts like the `exec` builtin in sh
|
- `exec(command)` function, acts like the `exec` builtin in sh
|
||||||
|
@ -83,7 +93,7 @@ When `false` is run, it will have the exit code of `1`, this is shorter/easier t
|
||||||
- `hilbish.home` is a crossplatform Lua alternative to get the home directory easily.
|
- `hilbish.home` is a crossplatform Lua alternative to get the home directory easily.
|
||||||
- `commander.deregister(cmdName)` de-registers any command defined with commander.
|
- `commander.deregister(cmdName)` de-registers any command defined with commander.
|
||||||
|
|
||||||
## Changed
|
### Changed
|
||||||
|
|
||||||
- **Breaking Change**: Move `_user` and `_ver` to a global `hilbish` table
|
- **Breaking Change**: Move `_user` and `_ver` to a global `hilbish` table
|
||||||
- Accessing username and Hilbish version is now done with `hilbish.user` and `hilbish.ver`
|
- Accessing username and Hilbish version is now done with `hilbish.user` and `hilbish.ver`
|
||||||
|
@ -100,7 +110,7 @@ When `false` is run, it will have the exit code of `1`, this is shorter/easier t
|
||||||
- Add input to history before alias expansion. Basically, this adds the actual alias to history instead of the aliased command.
|
- Add input to history before alias expansion. Basically, this adds the actual alias to history instead of the aliased command.
|
||||||
- Global preload path, require paths, default config directory and sample config directory can now be changed at compile time to help support other systems.
|
- Global preload path, require paths, default config directory and sample config directory can now be changed at compile time to help support other systems.
|
||||||
|
|
||||||
## Fixed
|
### Fixed
|
||||||
|
|
||||||
- `cd` now exits with code `1` instead of the error code if it occurs
|
- `cd` now exits with code `1` instead of the error code if it occurs
|
||||||
- Don't append directory to $PATH with `appendPath` if its already there
|
- Don't append directory to $PATH with `appendPath` if its already there
|
||||||
|
@ -111,7 +121,7 @@ When `false` is run, it will have the exit code of `1`, this is shorter/easier t
|
||||||
|
|
||||||
## [0.4.0] - 2021-05-01
|
## [0.4.0] - 2021-05-01
|
||||||
|
|
||||||
## Added
|
### Added
|
||||||
- Ctrl C in the prompt now cancels/clear input (I've needed this for so long also)
|
- Ctrl C in the prompt now cancels/clear input (I've needed this for so long also)
|
||||||
- Made Hilbish act like a login shell on login
|
- Made Hilbish act like a login shell on login
|
||||||
- If Hilbish is the login shell, or the `-l`/`--login` flags are used, Hilbish will use an additional `~/.hprofile.lua` file, you can use this to set environment variables once on login
|
- If Hilbish is the login shell, or the `-l`/`--login` flags are used, Hilbish will use an additional `~/.hprofile.lua` file, you can use this to set environment variables once on login
|
||||||
|
@ -125,7 +135,7 @@ When `false` is run, it will have the exit code of `1`, this is shorter/easier t
|
||||||
- `string.split(str, delimiter)`
|
- `string.split(str, delimiter)`
|
||||||
- Added a `_user` variable to easily get current user's name
|
- Added a `_user` variable to easily get current user's name
|
||||||
|
|
||||||
## Changed
|
### Changed
|
||||||
|
|
||||||
- **BREAKING Change**: [Lunacolors](https://github.com/Hilbis/Lunacolors) has replaced ansikit for formatting colors, which means the format function has been removed from ansikit and moved to Lunacolors.
|
- **BREAKING Change**: [Lunacolors](https://github.com/Hilbis/Lunacolors) has replaced ansikit for formatting colors, which means the format function has been removed from ansikit and moved to Lunacolors.
|
||||||
- Users must replace ansikit with `lunacolors` in their config files
|
- Users must replace ansikit with `lunacolors` in their config files
|
||||||
|
@ -239,6 +249,7 @@ This input for example will prompt for more input to complete:
|
||||||
|
|
||||||
First "stable" release of Hilbish.
|
First "stable" release of Hilbish.
|
||||||
|
|
||||||
|
[0.6.1]: https://github.com/Rosettea/Hilbish/compare/v0.6.0...v0.6.1
|
||||||
[0.6.0]: https://github.com/Rosettea/Hilbish/compare/v0.5.1...v0.6.0
|
[0.6.0]: https://github.com/Rosettea/Hilbish/compare/v0.5.1...v0.6.0
|
||||||
[0.5.1]: https://github.com/Rosettea/Hilbish/compare/v0.5.0...v0.5.1
|
[0.5.1]: https://github.com/Rosettea/Hilbish/compare/v0.5.0...v0.5.1
|
||||||
[0.5.0]: https://github.com/Rosettea/Hilbish/compare/v0.4.0...v0.5.0
|
[0.5.0]: https://github.com/Rosettea/Hilbish/compare/v0.4.0...v0.5.0
|
||||||
|
|
|
@ -10,8 +10,8 @@ a contribution. Be sure to read through it.
|
||||||
Use GitHub Issues to report any bugs or to request any features
|
Use GitHub Issues to report any bugs or to request any features
|
||||||
that may be useful to *anyone* else.
|
that may be useful to *anyone* else.
|
||||||
|
|
||||||
Check [currently open issues](https://github.com/Hilbis/Hilbish/issues)
|
Check [currently open issues](https://github.com/Rosettea/Hilbish/issues)
|
||||||
and [closed ones](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aclosed) to make sure someone else hasn't already made the issue.
|
and [closed ones](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aclosed) to make sure someone else hasn't already made the issue.
|
||||||
|
|
||||||
For bug reports, be sure to include:
|
For bug reports, be sure to include:
|
||||||
- Hilbish Version (`hilbish -v`)
|
- Hilbish Version (`hilbish -v`)
|
||||||
|
@ -40,8 +40,8 @@ your commits correctly.
|
||||||
4. Finally, make the pull request to the **dev** branch.
|
4. Finally, make the pull request to the **dev** branch.
|
||||||
|
|
||||||
## Finding Issues to Contribute to
|
## Finding Issues to Contribute to
|
||||||
You can check out the [help wanted](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+)
|
You can check out the [help wanted](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+)
|
||||||
labels to figure out what we need your help working on.
|
labels to figure out what we need your help working on.
|
||||||
|
|
||||||
The [up for grabs](https://github.com/Hilbis/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22+) labeled issues are low hanging fruit that should be
|
The [up for grabs](https://github.com/Rosettea/Hilbish/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22+) labeled issues are low hanging fruit that should be
|
||||||
easy for anyone. You can use this to get started on contributing!
|
easy for anyone. You can use this to get started on contributing!
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="./assets/hilbish-flower.png" width=128><br>
|
<img src="./assets/hilbish-flower.png" width=128><br>
|
||||||
<img src="./assets/hilbish-text.png" width=256>
|
<img src="./assets/hilbish-text.png" width=256><br><br>
|
||||||
<h1></h1>
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
🌺 The flower shell. A comfy and nice little shell for Lua users and fans!
|
🌺 The flower shell. A comfy and nice little shell for Lua users and fans!
|
||||||
</blockquote>
|
</blockquote><br>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/Rosettea/Hilbish?style=flat-square">
|
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/Rosettea/Hilbish?style=flat-square">
|
||||||
<img alt="GitHub commits since latest release (by date)" src="https://img.shields.io/github/commits-since/Rosettea/Hilbish/latest?style=flat-square">
|
<img alt="GitHub commits since latest release (by date)" src="https://img.shields.io/github/commits-since/Rosettea/Hilbish/latest?style=flat-square">
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ 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,5 +1,7 @@
|
||||||
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,6 +58,8 @@ 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)
|
||||||
|
|
||||||
|
@ -210,3 +212,17 @@ 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,18 +5,19 @@ 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"
|
||||||
"layeh.com/gopher-luar"
|
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
"layeh.com/gopher-luar"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,6 +26,7 @@ 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
|
||||||
|
@ -258,15 +260,22 @@ 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)
|
signal.Notify(c, os.Interrupt, syscall.SIGWINCH)
|
||||||
|
|
||||||
for range c {
|
for s := 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,3 +166,7 @@ bait.catch('command.not-found', function(cmd)
|
||||||
print(string.format('hilbish: %s not found', cmd))
|
print(string.format('hilbish: %s not found', cmd))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
bait.catch('command.no-perm', function(cmd)
|
||||||
|
print(string.format('hilbish: %s: no permission', cmd))
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
144
rl.go
144
rl.go
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !hilbiline
|
||||||
// +build !hilbiline
|
// +build !hilbiline
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@ -6,15 +7,149 @@ package main
|
||||||
// making them interchangable during build time
|
// making them interchangable during build time
|
||||||
// this is normal readline
|
// this is normal readline
|
||||||
|
|
||||||
import "github.com/bobappleyard/readline"
|
import (
|
||||||
|
"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 = readline.FilenameCompleter
|
readline.Completer = func(query string, ctx string) []string {
|
||||||
|
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{
|
||||||
|
@ -41,3 +176,6 @@ func (lr *LineReader) ClearInput() {
|
||||||
readline.RefreshLine()
|
readline.RefreshLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lr *LineReader) Resize() {
|
||||||
|
readline.Resize()
|
||||||
|
}
|
||||||
|
|
|
@ -37,3 +37,7 @@ func (lr *LineReader) ClearInput() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lr *LineReader) Resize() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
34
shell.go
34
shell.go
|
@ -4,10 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
// "github.com/bobappleyard/readline"
|
|
||||||
"github.com/yuin/gopher-lua"
|
"github.com/yuin/gopher-lua"
|
||||||
//"github.com/yuin/gopher-lua/parse"
|
//"github.com/yuin/gopher-lua/parse"
|
||||||
"mvdan.cc/sh/v3/interp"
|
"mvdan.cc/sh/v3/interp"
|
||||||
|
@ -95,7 +95,6 @@ func execCommand(cmd string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
exechandle := func(ctx context.Context, args []string) error {
|
exechandle := func(ctx context.Context, args []string) error {
|
||||||
hc := interp.HandlerCtx(ctx)
|
|
||||||
_, argstring := splitInput(strings.Join(args, " "))
|
_, argstring := splitInput(strings.Join(args, " "))
|
||||||
|
|
||||||
// If alias was found, use command alias
|
// If alias was found, use command alias
|
||||||
|
@ -142,7 +141,11 @@ func execCommand(cmd string) error {
|
||||||
return interp.NewExitStatus(exitcode)
|
return interp.NewExitStatus(exitcode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := interp.LookPathDir(hc.Dir, hc.Env, args[0]); err != nil {
|
err := lookpath(args[0])
|
||||||
|
if err == os.ErrPermission {
|
||||||
|
hooks.Em.Emit("command.no-perm", args[0])
|
||||||
|
return interp.NewExitStatus(126)
|
||||||
|
} else if err != nil {
|
||||||
hooks.Em.Emit("command.not-found", args[0])
|
hooks.Em.Emit("command.not-found", args[0])
|
||||||
return interp.NewExitStatus(127)
|
return interp.NewExitStatus(127)
|
||||||
}
|
}
|
||||||
|
@ -158,6 +161,31 @@ func execCommand(cmd string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// custom lookpath function so we know if a command is found *and* has execute permission
|
||||||
|
func lookpath(file string) error {
|
||||||
|
for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
|
||||||
|
path := filepath.Join(dir, file)
|
||||||
|
err := findExecutable(path)
|
||||||
|
if err == os.ErrPermission {
|
||||||
|
return err
|
||||||
|
} else if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
|
func findExecutable(name string) error {
|
||||||
|
f, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if m := f.Mode(); !m.IsDir() && m & 0111 != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return os.ErrPermission
|
||||||
|
}
|
||||||
|
|
||||||
func splitInput(input string) ([]string, string) {
|
func splitInput(input string) ([]string, string) {
|
||||||
// end my suffering
|
// end my suffering
|
||||||
// TODO: refactor this garbage
|
// TODO: refactor this garbage
|
||||||
|
|
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.6.0"
|
version = "v0.7.0"
|
||||||
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