Skip to content

Commit b66aa93

Browse files
authored
cmd: Use readline library. (#98)
Using this library we have history out of the box.
1 parent 761ba5e commit b66aa93

File tree

1 file changed

+39
-48
lines changed

1 file changed

+39
-48
lines changed

Diff for: cmd/gitql/shell.go

+39-48
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package main
22

33
import (
4-
"bufio"
5-
"bytes"
64
"fmt"
7-
"os"
85
"strings"
6+
7+
"github.com/chzyer/readline"
8+
)
9+
10+
const (
11+
initPrompt = "!> "
12+
multilinePrompt = "!>>> "
913
)
1014

1115
type CmdShell struct {
@@ -21,69 +25,56 @@ func (c *CmdShell) Execute(args []string) error {
2125
return err
2226
}
2327

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(`
2538
gitQL SHELL
2639
-----------
2740
You must end your queries with ';'
2841
29-
`)
30-
31-
s := bufio.NewScanner(os.Stdin)
32-
33-
s.Split(scanQueries)
42+
`))
3443

44+
var cmds []string
3545
for {
36-
fmt.Print("!> ")
37-
38-
if !s.Scan() {
46+
line, err := rl.Readline()
47+
if err != nil {
3948
break
4049
}
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+
}
4159

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)
4664

47-
fmt.Printf("\n--> Executing query: %s\n\n", query)
65+
rl.Terminal.Print(fmt.Sprintf("\n--> Executing query: %s\n\n", query))
4866

4967
schema, rowIter, err := c.executeQuery(query)
5068
if err != nil {
51-
c.printError(err)
69+
rl.Terminal.Print(fmt.Sprintf("ERROR: %v\n\n", err))
5270
continue
5371
}
5472

5573
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
5776
}
5877
}
5978

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()
8980
}

0 commit comments

Comments
 (0)