From 2ab87956435b32144b39c8c17b96f9aa2c00dd5c Mon Sep 17 00:00:00 2001 From: sawka Date: Thu, 10 Nov 2022 15:28:39 -0800 Subject: [PATCH] comp checkpoint --- pkg/cmdrunner/cmdrunner.go | 31 +----------------- pkg/comp/comp.go | 66 ++++++++++++++++++++++++++++++++++---- pkg/utilfn/utilfn.go | 38 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 37 deletions(-) diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index f788e918f..ac9041b33 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -1081,7 +1081,7 @@ func makeInsertUpdateFromComps(pos int64, prefix string, comps []string, hasMore if hasMore { return nil } - lcp := longestPrefix(prefix, comps) + lcp := utilfn.LongestPrefix(prefix, comps) if lcp == prefix || len(lcp) < len(prefix) || !strings.HasPrefix(lcp, prefix) { return nil } @@ -1090,35 +1090,6 @@ func makeInsertUpdateFromComps(pos int64, prefix string, comps []string, hasMore return sstore.ModelUpdate{CmdLine: clu} } -func longestPrefix(root string, comps []string) string { - if len(comps) == 0 { - return root - } - if len(comps) == 1 { - comp := comps[0] - if len(comp) >= len(root) && strings.HasPrefix(comp, root) { - if strings.HasSuffix(comp, "/") { - return comps[0] - } - return comps[0] + " " - } - } - lcp := comps[0] - for i := 1; i < len(comps); i++ { - s := comps[i] - for j := 0; j < len(lcp); j++ { - if j >= len(s) || lcp[j] != s[j] { - lcp = lcp[0:j] - break - } - } - } - if len(lcp) < len(root) || !strings.HasPrefix(lcp, root) { - return root - } - return lcp -} - func simpleCompMeta(ctx context.Context, prefix string, compCtx comp.CompContext, args []interface{}) (*comp.CompReturn, error) { compsCmd, _ := comp.DoSimpleComp(ctx, "command", prefix, compCtx, nil) compsMeta, _ := simpleCompCommandMeta(ctx, prefix, compCtx, nil) diff --git a/pkg/comp/comp.go b/pkg/comp/comp.go index cc6fffeae..0e29d0e5a 100644 --- a/pkg/comp/comp.go +++ b/pkg/comp/comp.go @@ -43,9 +43,9 @@ type CompContext struct { ForDisplay bool } -type SimpleCompPoint struct { - Word string - Pos int +type StrWithPos struct { + Str string + Pos int } type fullCompPrefix struct { @@ -130,7 +130,10 @@ func compQuoteString(s string, quoteType string, close bool) string { return rtn } if quoteType == QuoteTypeSQ { - rtn := utilfn.ShellQuote(s, true, MaxCompQuoteLen) + rtn := utilfn.ShellQuote(s, false, MaxCompQuoteLen) + if len(rtn) > 0 && rtn[0] != '\'' { + rtn = "'" + rtn + "'" + } if !close { rtn = rtn[0 : len(rtn)-1] } @@ -185,18 +188,46 @@ func (p *CompPoint) getCompPrefix() string { return shexec.SimpleExpandPartialWord(shexec.SimpleExpandContext{}, partialWordStr, false) } -func (p *CompPoint) extendWord(newWord string, newWordComplete bool) (string, int) { +func (p *CompPoint) extendWord(newWord string, newWordComplete bool) StrWithPos { pword := p.Words[p.CompWord] wordStr := p.wordAsStr(pword) quotePref := getQuoteTypePref(wordStr) needsClose := newWordComplete && (len(wordStr) == p.CompWordPos) wordSuffix := wordStr[p.CompWordPos:] newQuotedStr := compQuoteString(newWord, quotePref, needsClose) - if needsClose && wordSuffix == "" { + if needsClose && wordSuffix == "" && !strings.HasSuffix(newWord, "/") { newQuotedStr = newQuotedStr + " " } newPos := len(newQuotedStr) - return newQuotedStr + wordSuffix, newPos + return StrWithPos{Str: newQuotedStr + wordSuffix, Pos: newPos} +} + +func (p *CompPoint) FullyExtend(crtn *CompReturn) StrWithPos { + if crtn == nil || crtn.HasMore { + return StrWithPos{Str: p.getOrigStr(), Pos: p.getOrigPos()} + } + compStrs := crtn.getCompStrs() + compPrefix := p.getCompPrefix() + lcp := utilfn.LongestPrefix(compPrefix, compStrs) + if lcp == compPrefix || len(lcp) < len(compPrefix) || !strings.HasPrefix(lcp, compPrefix) { + return StrWithPos{Str: p.getOrigStr(), Pos: p.getOrigPos()} + } + newStr := p.extendWord(lcp, utilfn.ContainsStr(compStrs, lcp)) + var buf bytes.Buffer + buf.WriteString(p.Prefix) + for idx, w := range p.Words { + if idx == p.CompWord { + buf.WriteString(w.Prefix) + buf.WriteString(newStr.Str) + } else { + buf.WriteString(w.Prefix) + buf.WriteString(p.wordAsStr(w)) + } + } + buf.WriteString(p.Suffix) + compWord := p.Words[p.CompWord] + newPos := len(p.Prefix) + compWord.Offset + len(compWord.Prefix) + newStr.Pos + return StrWithPos{Str: buf.String(), Pos: newPos} } func (p *CompPoint) dump() { @@ -223,6 +254,10 @@ func (p *CompPoint) dump() { var SimpleCompGenFns map[string]SimpleCompGenFnType +func (sp StrWithPos) String() string { + return strWithCursor(sp.Str, sp.Pos) +} + func strWithCursor(str string, pos int) string { if pos < 0 { return "[*]_" + str @@ -384,3 +419,20 @@ func CombineCompReturn(c1 *CompReturn, c2 *CompReturn) *CompReturn { SortCompReturnEntries(&rtn) return &rtn } + +func (c *CompReturn) getCompStrs() []string { + rtn := make([]string, len(c.Entries)) + for idx, entry := range c.Entries { + rtn[idx] = entry.Word + } + return rtn +} + +func (p CompPoint) getOrigPos() int { + pword := p.Words[p.CompWord] + return len(p.Prefix) + pword.Offset + len(pword.Prefix) + p.CompWordPos +} + +func (p CompPoint) getOrigStr() string { + return p.Prefix + p.StmtStr + p.Suffix +} diff --git a/pkg/utilfn/utilfn.go b/pkg/utilfn/utilfn.go index a7fc04de2..b8e4a7c79 100644 --- a/pkg/utilfn/utilfn.go +++ b/pkg/utilfn/utilfn.go @@ -74,3 +74,41 @@ func ShellQuote(val string, forceQuote bool, maxLen int) string { return rtn } } + +func LongestPrefix(root string, strs []string) string { + if len(strs) == 0 { + return root + } + if len(strs) == 1 { + comp := strs[0] + if len(comp) >= len(root) && strings.HasPrefix(comp, root) { + if strings.HasSuffix(comp, "/") { + return strs[0] + } + return strs[0] + } + } + lcp := strs[0] + for i := 1; i < len(strs); i++ { + s := strs[i] + for j := 0; j < len(lcp); j++ { + if j >= len(s) || lcp[j] != s[j] { + lcp = lcp[0:j] + break + } + } + } + if len(lcp) < len(root) || !strings.HasPrefix(lcp, root) { + return root + } + return lcp +} + +func ContainsStr(strs []string, test string) bool { + for _, s := range strs { + if s == test { + return true + } + } + return false +}