mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-11 05:22:02 +00:00
this is a pretty big commit which mainly contains a refactor and breaking change to how command completions are done. before that, a hilbish.completion interface has been added which for now just has 2 functions (`files` and `bins`) for completions of normal files and executables. hilbish.complete is now expected to return a table of "completions groups," which are as the name suggests a group for a completion. a completion group is a table which has the fields `type`, which can be either `list` or `grid`, and `items`, being an array (or string keyed table) of items if an item is string keyed the item itself is the key name and the value is a table with the first value in it being the description for the item. this description is only applied with the list type. this is probably the longest commit message ive written
109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"os"
|
|
)
|
|
|
|
func fileComplete(query, ctx string, fields []string) []string {
|
|
var completions []string
|
|
|
|
prefixes := []string{"./", "../", "/", "~/"}
|
|
for _, prefix := range prefixes {
|
|
if strings.HasPrefix(query, prefix) {
|
|
completions, _ = matchPath(strings.Replace(query, "~", curuser.HomeDir, 1), query)
|
|
}
|
|
}
|
|
|
|
if len(completions) == 0 && len(fields) > 1 {
|
|
completions, _ = matchPath("./" + query, query)
|
|
}
|
|
|
|
return completions
|
|
}
|
|
|
|
func binaryComplete(query, ctx string, fields []string) ([]string, string) {
|
|
var completions []string
|
|
|
|
prefixes := []string{"./", "../", "/", "~/"}
|
|
for _, prefix := range prefixes {
|
|
if strings.HasPrefix(query, prefix) {
|
|
fileCompletions := fileComplete(query, ctx, fields)
|
|
if len(fileCompletions) != 0 {
|
|
for _, f := range fileCompletions {
|
|
name := strings.Replace(query + f, "~", curuser.HomeDir, 1)
|
|
if info, err := os.Stat(name); err == nil && info.Mode().Perm() & 0100 == 0 {
|
|
continue
|
|
}
|
|
completions = append(completions, f)
|
|
}
|
|
}
|
|
return completions, ""
|
|
}
|
|
}
|
|
|
|
// filter out executables, but in path
|
|
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)
|
|
// 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)
|
|
}
|
|
}
|
|
|
|
return completions, query
|
|
}
|
|
|
|
func matchPath(path, pref string) ([]string, error) {
|
|
var entries []string
|
|
matches, err := filepath.Glob(path + "*")
|
|
if err == nil {
|
|
args := []string{
|
|
"\"", "\\\"",
|
|
"'", "\\'",
|
|
"`", "\\`",
|
|
" ", "\\ ",
|
|
"(", "\\(",
|
|
")", "\\)",
|
|
"[", "\\[",
|
|
"]", "\\]",
|
|
}
|
|
|
|
r := strings.NewReplacer(args...)
|
|
for _, match := range matches {
|
|
name := filepath.Base(match)
|
|
p := filepath.Base(pref)
|
|
if pref == "" {
|
|
p = ""
|
|
}
|
|
name = strings.TrimPrefix(name, p)
|
|
matchFull, _ := filepath.Abs(match)
|
|
if info, err := os.Stat(matchFull); err == nil && info.IsDir() {
|
|
name = name + string(os.PathSeparator)
|
|
}
|
|
name = r.Replace(name)
|
|
entries = append(entries, name)
|
|
}
|
|
}
|
|
|
|
return entries, err
|
|
}
|