Skip to content

Commit 71d3253

Browse files
authored
Replace console module with liner (#53)
* replace readline with liner * implement auto complete of keywords * add header
1 parent 0fba127 commit 71d3253

File tree

7 files changed

+495
-23
lines changed

7 files changed

+495
-23
lines changed

cmd/sqlcmd/main.go

+4-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
"github.com/alecthomas/kong"
1111
"github.com/denisenkom/go-mssqldb/azuread"
12-
"github.com/gohxs/readline"
12+
"github.com/microsoft/go-sqlcmd/pkg/console"
1313
"github.com/microsoft/go-sqlcmd/pkg/sqlcmd"
1414
)
1515

@@ -194,18 +194,12 @@ func run(vars *sqlcmd.Variables, args *SQLCmdArguments) (int, error) {
194194
}
195195

196196
iactive := args.InputFile == nil && args.Query == ""
197-
var console sqlcmd.Console = nil
198-
var line *readline.Instance
197+
var line sqlcmd.Console = nil
199198
if iactive {
200-
line, err = readline.New(">")
201-
if err != nil {
202-
return 1, err
203-
}
204-
console = line
205-
defer line.Close()
199+
line = console.NewConsole("")
206200
}
207201

208-
s := sqlcmd.New(console, wd, vars)
202+
s := sqlcmd.New(line, wd, vars)
209203
setConnect(&s.Connect, args, vars)
210204
if args.BatchTerminator != "GO" {
211205
err = s.Cmd.SetBatchTerminator(args.BatchTerminator)

go.mod

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ go 1.16
44

55
require (
66
github.com/alecthomas/kong v0.2.18-0.20210621093454-54558f65e86f
7-
github.com/chzyer/logex v1.1.10 // indirect
8-
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 // indirect
97
github.com/denisenkom/go-mssqldb v0.12.0
10-
github.com/gohxs/readline v0.0.0-20171011095936-a780388e6e7c
118
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188
129
github.com/google/uuid v1.2.0
10+
github.com/peterh/liner v1.2.2
1311
github.com/stretchr/testify v1.7.0
1412
)
1513

go.sum

+6-7
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,21 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI4
66
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
77
github.com/alecthomas/kong v0.2.18-0.20210621093454-54558f65e86f h1:VgRM6/wqZIB1D9W3XMllm/wplTmPgI5yvCHUXEsmKps=
88
github.com/alecthomas/kong v0.2.18-0.20210621093454-54558f65e86f/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
9-
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
10-
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
11-
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ=
12-
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
139
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1410
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1511
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1612
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
17-
github.com/gohxs/readline v0.0.0-20171011095936-a780388e6e7c h1:yE35fKFwcelIte3q5q1/cPiY7pI7vvf5/j/0ddxNCKs=
18-
github.com/gohxs/readline v0.0.0-20171011095936-a780388e6e7c/go.mod h1:9S/fKAutQ6wVHqm1jnp9D9sc5hu689s9AaTWFS92LaU=
1913
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
2014
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
2115
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4=
2216
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
2317
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
2418
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
19+
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
20+
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
2521
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
22+
github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw=
23+
github.com/peterh/liner v1.2.2/go.mod h1:xFwJyiKIXJZUKItq5dGHZSTBRAuG/CpeNpWLyiNRNwI=
2624
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
2725
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
2826
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -44,8 +42,9 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
4442
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
4543
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4644
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
47-
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
4845
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
46+
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
47+
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
4948
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
5049
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
5150
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=

pkg/console/complete.go

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package console
5+
6+
import "strings"
7+
8+
// CompleteLine returns a set of candidate TSQL keywords to complete the current input line
9+
func CompleteLine(line string) []string {
10+
idx := strings.LastIndexAny(line, " ;") + 1
11+
// we don't try to complete without a starting letter
12+
if idx == len(line) {
13+
return []string{}
14+
}
15+
prefix := strings.ToUpper(string(line[idx:]))
16+
left := 0
17+
right := len(keywords) - 1
18+
for left <= right {
19+
mid := (left + right) / 2
20+
comp := 0
21+
if len(keywords[mid]) >= len(prefix) {
22+
comp = strings.Compare(prefix, string(keywords[mid][:len(prefix)]))
23+
} else {
24+
comp = strings.Compare(prefix, keywords[mid])
25+
}
26+
if comp < 0 {
27+
right = mid - 1
28+
} else if comp > 0 {
29+
left = mid + 1
30+
} else {
31+
// look up and down the list from mid and return the slice of matching words
32+
first := mid - 1
33+
last := mid + 1
34+
for first >= 0 && strings.HasPrefix(keywords[first], prefix) {
35+
first--
36+
}
37+
for last < len(keywords) && strings.HasPrefix(keywords[last], prefix) {
38+
last++
39+
}
40+
lines := make([]string, last-first-1)
41+
for i, w := range keywords[first+1 : last] {
42+
lines[i] = mergeLine(line, w, idx)
43+
}
44+
return lines
45+
}
46+
}
47+
return []string{}
48+
}
49+
50+
// mergeline appends keyword to line starting at index idx
51+
// It matches the case of the current character in the line
52+
func mergeLine(line string, keyword string, idx int) string {
53+
upcase := line[idx] >= 'A' && line[idx] <= 'Z'
54+
b := strings.Builder{}
55+
b.Write([]byte(line[:idx]))
56+
if !upcase {
57+
b.WriteString(strings.ToLower(keyword))
58+
} else {
59+
b.WriteString(keyword)
60+
}
61+
return b.String()
62+
}
63+
64+
var keywords = []string{
65+
"ADD",
66+
"ALL",
67+
"ALTER",
68+
"AND",
69+
"ANY",
70+
"AS",
71+
"ASC",
72+
"AUTHORIZATION",
73+
"BACKUP",
74+
"BEGIN",
75+
"BETWEEN",
76+
"BREAK",
77+
"BROWSE",
78+
"BULK",
79+
"BY",
80+
"CASCADE",
81+
"CASE",
82+
"CHECK",
83+
"CHECKPOINT",
84+
"CLOSE",
85+
"CLUSTERED",
86+
"COALESCE",
87+
"COLLATE",
88+
"COLUMN",
89+
"COMMIT",
90+
"COMPUTE",
91+
"CONSTRAINT",
92+
"CONTAINS",
93+
"CONTAINSTABLE",
94+
"CONTINUE",
95+
"CONVERT",
96+
"CREATE",
97+
"CROSS",
98+
"CURRENT",
99+
"CURRENT_DATE",
100+
"CURRENT_TIME",
101+
"CURRENT_TIMESTAMP",
102+
"CURRENT_USER",
103+
"CURSOR",
104+
"DATABASE",
105+
"DBCC",
106+
"DEALLOCATE",
107+
"DECLARE",
108+
"DEFAULT",
109+
"DELETE",
110+
"DENY",
111+
"DESC",
112+
"DISTINCT",
113+
"DISTRIBUTED",
114+
"DOUBLE",
115+
"DROP",
116+
"ELSE",
117+
"END",
118+
"ERRLVL",
119+
"ESCAPE",
120+
"EXCEPT",
121+
"EXEC",
122+
"EXECUTE",
123+
"EXISTS",
124+
"EXIT",
125+
"EXTERNAL",
126+
"FETCH",
127+
"FILE",
128+
"FILLFACTOR",
129+
"FOR",
130+
"FOREIGN",
131+
"FREETEXT",
132+
"FREETEXTTABLE",
133+
"FROM",
134+
"FULL",
135+
"FUNCTION",
136+
"GOTO",
137+
"GRANT",
138+
"GROUP",
139+
"HAVING",
140+
"HOLDLOCK",
141+
"IDENTITY",
142+
"IDENTITY_INSERT",
143+
"IDENTITYCOL",
144+
"IF",
145+
"IN",
146+
"INDEX",
147+
"INNER",
148+
"INSERT",
149+
"INTERSECT",
150+
"INTO",
151+
"IS",
152+
"JOIN",
153+
"KEY",
154+
"KILL",
155+
"LEFT",
156+
"LIKE",
157+
"LINENO",
158+
"MERGE",
159+
"NATIONAL",
160+
"NOCHECK",
161+
"NONCLUSTERED",
162+
"NOT",
163+
"NULL",
164+
"NULLIF",
165+
"OF",
166+
"OFF",
167+
"OFFSETS",
168+
"ON",
169+
"OPEN",
170+
"OPENDATASOURCE",
171+
"OPENQUERY",
172+
"OPENROWSET",
173+
"OPENXML",
174+
"OPTION",
175+
"OR",
176+
"ORDER",
177+
"OUTER",
178+
"OVER",
179+
"PERCENT",
180+
"PIVOT",
181+
"PLAN",
182+
"PRIMARY",
183+
"PRINT",
184+
"PROC",
185+
"PROCEDURE",
186+
"PUBLIC",
187+
"RAISERROR",
188+
"READ",
189+
"READTEXT",
190+
"RECONFIGURE",
191+
"REFERENCES",
192+
"REPLICATION",
193+
"RESTORE",
194+
"RESTRICT",
195+
"RETURN",
196+
"REVERT",
197+
"REVOKE",
198+
"RIGHT",
199+
"ROLLBACK",
200+
"ROWCOUNT",
201+
"ROWGUIDCOL",
202+
"RULE",
203+
"SAVE",
204+
"SCHEMA",
205+
"SELECT",
206+
"SEMANTICKEYPHRASETABLE",
207+
"SEMANTICSIMILARITYDETAILSTABLE",
208+
"SEMANTICSIMILARITYTABLE",
209+
"SESSION_USER",
210+
"SET",
211+
"SETUSER",
212+
"SHUTDOWN",
213+
"SOME",
214+
"STATISTICS",
215+
"SYSTEM_USER",
216+
"TABLE",
217+
"TABLESAMPLE",
218+
"TEXTSIZE",
219+
"THEN",
220+
"TO",
221+
"TOP",
222+
"TRAN",
223+
"TRANSACTION",
224+
"TRIGGER",
225+
"TRUNCATE",
226+
"TRY_CONVERT",
227+
"TSEQUAL",
228+
"UNION",
229+
"UNIQUE",
230+
"UNPIVOT",
231+
"UPDATE",
232+
"UPDATETEXT",
233+
"USE",
234+
"USER",
235+
"VALUES",
236+
"VARYING",
237+
"VIEW",
238+
"WAITFOR",
239+
"WHEN",
240+
"WHERE",
241+
"WHERECURRENT",
242+
"WHILE",
243+
"WITH",
244+
"WRITETEXT",
245+
}

0 commit comments

Comments
 (0)