mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
Support completion of commands
This commit is contained in:
parent
f52e1760b0
commit
8794232b26
|
@ -6,6 +6,7 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/elves/elvish/eval"
|
||||
"github.com/elves/elvish/parse"
|
||||
)
|
||||
|
||||
|
@ -58,8 +59,8 @@ func (c *completion) next(cycle bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func findCandidates(p string, all []string) (cands []*candidate) {
|
||||
// Prefix match
|
||||
// Find candidates by matching against a prefix.
|
||||
func prefixMatchCandidates(p string, all []string) (cands []*candidate) {
|
||||
for _, s := range all {
|
||||
if len(s) >= len(p) && s[:len(p)] == p {
|
||||
cand := newCandidate()
|
||||
|
@ -117,6 +118,8 @@ func peekCurrentCompound(ctx *parse.Context, dot int) (string, int, error) {
|
|||
}
|
||||
|
||||
switch ctx.Typ {
|
||||
case parse.CommandContext:
|
||||
return peekIncompleteCompound(ctx.Form.Command)
|
||||
case parse.ArgContext:
|
||||
compounds := ctx.Form.Args.Nodes
|
||||
lastCompound := compounds[len(compounds)-1]
|
||||
|
@ -134,6 +137,13 @@ func peekCurrentCompound(ctx *parse.Context, dot int) (string, int, error) {
|
|||
}
|
||||
}
|
||||
|
||||
var builtins []string
|
||||
|
||||
func init() {
|
||||
builtins = append(builtins, eval.BuiltinFnNames...)
|
||||
builtins = append(builtins, eval.BuiltinSpecialNames...)
|
||||
}
|
||||
|
||||
func startCompletion(ed *Editor, k Key) *leReturn {
|
||||
c := &completion{}
|
||||
ctx, err := parse.Complete("<completion>", ed.line[:ed.dot])
|
||||
|
@ -152,8 +162,13 @@ func startCompletion(ed *Editor, k Key) *leReturn {
|
|||
|
||||
switch ctx.Typ {
|
||||
case parse.CommandContext:
|
||||
// BUG(xiaq): When completing, CommandContext is not supported
|
||||
ed.pushTip("command context not yet supported :(")
|
||||
// BUG(xiaq): When completing commands, only builtins are searched
|
||||
findAll = func() ([]string, error) {
|
||||
return builtins, nil
|
||||
}
|
||||
makeCandidates = func(all []string) (cands []*candidate) {
|
||||
return prefixMatchCandidates(compound, all)
|
||||
}
|
||||
case parse.NewArgContext, parse.ArgContext:
|
||||
// BUG(xiaq): When completing, [New]ArgContext is treated like RedirFilenameContext
|
||||
fallthrough
|
||||
|
|
|
@ -353,36 +353,38 @@ func (w *writer) refresh(bs *editorState) error {
|
|||
}
|
||||
|
||||
comp := bs.completion
|
||||
var suppress = false
|
||||
hasComp := comp != nil && comp.current != -1
|
||||
|
||||
nowAt := func(i int) {
|
||||
if hasComp && comp.start == i {
|
||||
// Put the current completion candidate.
|
||||
for _, part := range comp.candidates[comp.current].parts {
|
||||
attr := attrForType[comp.typ]
|
||||
if part.completed {
|
||||
attr += attrForCompleted
|
||||
}
|
||||
b.writes(part.text, attr)
|
||||
}
|
||||
}
|
||||
if bs.dot == i {
|
||||
b.dot = b.cursor()
|
||||
}
|
||||
}
|
||||
nowAt(0)
|
||||
tokens:
|
||||
for _, token := range bs.tokens {
|
||||
for _, r := range token.Val {
|
||||
if suppress && i < comp.end {
|
||||
if hasComp && comp.start <= i && i < comp.end {
|
||||
// Silence the part that is being completed
|
||||
} else {
|
||||
b.write(r, attrForType[token.Typ])
|
||||
}
|
||||
i += utf8.RuneLen(r)
|
||||
if comp != nil && comp.current != -1 && i == comp.start {
|
||||
// Put the current candidate and instruct text up to comp.end
|
||||
// to be suppressed. The cursor should be placed correctly
|
||||
// (i.e. right after the candidate)
|
||||
for _, part := range comp.candidates[comp.current].parts {
|
||||
attr := attrForType[comp.typ]
|
||||
if part.completed {
|
||||
attr += attrForCompleted
|
||||
}
|
||||
b.writes(part.text, attr)
|
||||
}
|
||||
suppress = true
|
||||
}
|
||||
|
||||
nowAt(i)
|
||||
if bs.mode == modeHistory && i == len(bs.history.prefix) {
|
||||
break tokens
|
||||
}
|
||||
if bs.dot == i {
|
||||
b.dot = b.cursor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
)
|
||||
|
||||
var builtinFns []*builtinFn
|
||||
var BuiltinFnNames []string
|
||||
|
||||
func init() {
|
||||
// Needed to work around init loop.
|
||||
|
@ -51,6 +52,9 @@ func init() {
|
|||
|
||||
&builtinFn{"=", eq},
|
||||
}
|
||||
for _, b := range builtinFns {
|
||||
BuiltinFnNames = append(BuiltinFnNames, b.Name)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -19,6 +19,7 @@ type builtinSpecial struct {
|
|||
}
|
||||
|
||||
var builtinSpecials map[string]builtinSpecial
|
||||
var BuiltinSpecialNames []string
|
||||
|
||||
func init() {
|
||||
// Needed to avoid initialization loop
|
||||
|
@ -34,6 +35,9 @@ func init() {
|
|||
|
||||
"static-typeof": builtinSpecial{compileStaticTypeof},
|
||||
}
|
||||
for k, _ := range builtinSpecials {
|
||||
BuiltinSpecialNames = append(BuiltinSpecialNames, k)
|
||||
}
|
||||
}
|
||||
|
||||
func mayAssign(tvar, tval Type) bool {
|
||||
|
|
Loading…
Reference in New Issue
Block a user