forked from x-motemen/gore
/
complete.go
91 lines (75 loc) · 2.3 KB
/
complete.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
package main
import (
"strings"
"github.com/motemen/gore/gocode"
)
func (s *Session) completeWord(line string, pos int) (string, []string, string) {
if strings.HasPrefix(line, ":") {
// complete commands
if !strings.Contains(line[0:pos], " ") {
pre, post := line[0:pos], line[pos:]
result := []string{}
for _, command := range commands {
name := ":" + command.name
if strings.HasPrefix(name, pre) {
// having complete means that this command takes an argument (for now)
if !strings.HasPrefix(post, " ") && command.arg != "" {
name = name + " "
}
result = append(result, name)
}
}
return "", result, post
}
// complete command arguments
for _, command := range commands {
if command.complete == nil {
continue
}
cmdPrefix := ":" + command.name + " "
if strings.HasPrefix(line, cmdPrefix) && pos >= len(cmdPrefix) {
return cmdPrefix, command.complete(s, line[len(cmdPrefix):pos]), ""
}
}
return "", nil, ""
}
if gocode.Available() == false {
return "", nil, ""
}
// code completion
pos, cands, err := s.completeCode(line, pos, true)
if err != nil {
errorf("completeCode: %s", err)
return "", nil, ""
}
return line[0:pos], cands, ""
}
// completeCode does code completion within the session using gocode (https://github.com/nsf/gocode).
// in and pos specifies the current input and the cursor position (0 <= pos <= len(in)) respectively.
// If exprMode is set to true, the completion is done as an expression (e.g. appends "(" to functions).
// Return value keep specifies how many characters of in should be kept and candidates are what follow in[0:keep].
func (s *Session) completeCode(in string, pos int, exprMode bool) (keep int, candidates []string, err error) {
s.clearQuickFix()
source, err := s.source(false)
if err != nil {
return
}
// Kind of dirty hack :/
p := strings.LastIndex(source, "}")
editingSource := source[0:p] + in + source[p:]
cursor := len(source[0:p]) + pos
result, err := gocode.Query([]byte(editingSource), cursor)
if err != nil {
return
}
keep = pos - result.Cursor
candidates = make([]string, 0, len(result.Candidates))
for _, e := range result.Candidates {
cand := e.Name
if exprMode && e.Class == "func" {
cand = cand + "("
}
candidates = append(candidates, cand)
}
return
}