1
1
package main
2
2
3
3
import (
4
- "bufio"
5
- "bytes"
6
4
"fmt"
7
- "os"
8
5
"strings"
6
+
7
+ "github.com/chzyer/readline"
8
+ )
9
+
10
+ const (
11
+ initPrompt = "!> "
12
+ multilinePrompt = "!>>> "
9
13
)
10
14
11
15
type CmdShell struct {
@@ -21,69 +25,56 @@ func (c *CmdShell) Execute(args []string) error {
21
25
return err
22
26
}
23
27
24
- fmt .Print (`
28
+ rl , err := readline .NewEx (& readline.Config {
29
+ Prompt : initPrompt ,
30
+ HistoryFile : "/tmp/gitql-history" ,
31
+ DisableAutoSaveHistory : true ,
32
+ })
33
+ if err != nil {
34
+ return err
35
+ }
36
+
37
+ rl .Terminal .Print (fmt .Sprint (`
25
38
gitQL SHELL
26
39
-----------
27
40
You must end your queries with ';'
28
41
29
- ` )
30
-
31
- s := bufio .NewScanner (os .Stdin )
32
-
33
- s .Split (scanQueries )
42
+ ` ))
34
43
44
+ var cmds []string
35
45
for {
36
- fmt .Print ("!> " )
37
-
38
- if ! s .Scan () {
46
+ line , err := rl .Readline ()
47
+ if err != nil {
39
48
break
40
49
}
50
+ line = strings .TrimSpace (line )
51
+ if len (line ) == 0 {
52
+ continue
53
+ }
54
+ cmds = append (cmds , line )
55
+ if ! strings .HasSuffix (line , ";" ) {
56
+ rl .SetPrompt (multilinePrompt )
57
+ continue
58
+ }
41
59
42
- query := s . Text ( )
43
-
44
- query = strings . Replace ( query , " \n " , " " , - 1 )
45
- query = strings . TrimSpace (query )
60
+ query := strings . Join ( cmds , " " )
61
+ cmds = cmds [: 0 ]
62
+ rl . SetPrompt ( initPrompt )
63
+ rl . SaveHistory (query )
46
64
47
- fmt .Printf ("\n --> Executing query: %s\n \n " , query )
65
+ rl . Terminal . Print ( fmt .Sprintf ("\n --> Executing query: %s\n \n " , query ) )
48
66
49
67
schema , rowIter , err := c .executeQuery (query )
50
68
if err != nil {
51
- c . printError ( err )
69
+ rl . Terminal . Print ( fmt . Sprintf ( "ERROR: %v \n \n " , err ) )
52
70
continue
53
71
}
54
72
55
73
if err := c .printQuery (schema , rowIter , "pretty" ); err != nil {
56
- c .printError (err )
74
+ rl .Terminal .Print (fmt .Sprintf ("ERROR: %v\n \n " , err ))
75
+ continue
57
76
}
58
77
}
59
78
60
- return s .Err ()
61
- }
62
-
63
- func (c * CmdShell ) printError (err error ) {
64
- fmt .Printf ("ERROR: %v\n \n " , err )
65
- }
66
-
67
- func scanQueries (data []byte , atEOF bool ) (int , []byte , error ) {
68
- if atEOF && len (data ) == 0 {
69
- return 0 , nil , nil
70
- }
71
- if i := bytes .IndexByte (data , ';' ); i >= 0 {
72
- // We have a full newline-terminated line.
73
- return i + 1 , dropCR (data [0 :i ]), nil
74
- }
75
- // If we're at EOF, we have a final, non-terminated line. Return it.
76
- if atEOF {
77
- return len (data ), dropCR (data ), nil
78
- }
79
- // Request more data.
80
- return 0 , nil , nil
81
- }
82
-
83
- // dropCR drops a terminal \r from the data.
84
- func dropCR (data []byte ) []byte {
85
- if len (data ) > 0 && data [len (data )- 1 ] == '\r' {
86
- return data [0 : len (data )- 1 ]
87
- }
88
- return data
79
+ return rl .Close ()
89
80
}
0 commit comments