forked from madlambda/nash
/
completer.go
98 lines (73 loc) · 2.09 KB
/
completer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main
import (
"fmt"
"os"
"strconv"
"github.com/NeowayLabs/nash"
"github.com/NeowayLabs/nash/sh"
"github.com/chzyer/readline"
)
var runes = readline.Runes{}
type Completer struct {
op *readline.Operation
term *readline.Terminal
sh *nash.Shell
}
func NewCompleter(op *readline.Operation, term *readline.Terminal, sh *nash.Shell) *Completer {
return &Completer{op, term, sh}
}
func (c *Completer) Do(line []rune, pos int) ([][]rune, int) {
var (
newLine [][]rune
offset int
lineArg = sh.NewStrObj(string(line))
posArg = sh.NewStrObj(strconv.Itoa(pos))
)
defer c.op.Refresh()
defer c.term.PauseRead(false)
nashFunc, ok := c.sh.GetFn("nash_complete")
if !ok {
// no complete available
return [][]rune{[]rune{'\t'}}, offset
}
err := nashFunc.SetArgs([]sh.Obj{lineArg, posArg})
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to autocomplete: %s\n", err.Error())
return newLine, offset
}
nashFunc.SetStdin(c.sh.Stdin())
nashFunc.SetStdout(c.sh.Stdout())
nashFunc.SetStderr(c.sh.Stderr())
if err = nashFunc.Start(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to autocomplete: %s\n", err.Error())
return newLine, offset
}
if err = nashFunc.Wait(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to autocomplete: %s\n", err.Error())
return newLine, offset
}
ret := nashFunc.Results()
if ret == nil || ret.Type() != sh.ListType {
fmt.Fprintf(os.Stderr, "ignoring autocomplete value: %v\n", ret)
return newLine, offset
}
retlist := ret.(*sh.ListObj)
if len(retlist.List()) != 2 {
return newLine, pos
}
newline := retlist.List()[0]
newpos := retlist.List()[1]
if newline.Type() != sh.StringType || newpos.Type() != sh.StringType {
fmt.Fprintf(os.Stderr, "ignoring autocomplete value: (%s) (%s)\n", newline, newpos)
return newLine, offset
}
objline := newline.(*sh.StrObj)
objpos := newpos.(*sh.StrObj)
newoffset, err := strconv.Atoi(objpos.Str())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to autocomplete: %s\n", err.Error())
return newLine, offset
}
newLine = append(newLine, []rune(objline.Str()))
return newLine, newoffset
}