use liner instead of linenoise

This commit is contained in:
siddontang 2015-08-02 09:23:51 +08:00
parent fdcaa0c4cc
commit 29df518dfd
10 changed files with 47 additions and 1314 deletions

View File

@ -14,10 +14,10 @@ export GO_BUILD_TAGS
all: build all: build
build: build:
$(GO) install -tags 'linenoise $(GO_BUILD_TAGS)' ./... $(GO) install -tags '$(GO_BUILD_TAGS)' ./...
build_lmdb: build_lmdb:
$(GO) install -tags 'linenoise $(GO_BUILD_TAGS) lmdb' ./... $(GO) install -tags '$(GO_BUILD_TAGS) lmdb' ./...
test: test:
$(GO) test --race -tags '$(GO_BUILD_TAGS)' ./... $(GO) test --race -tags '$(GO_BUILD_TAGS)' ./...

View File

@ -1,16 +0,0 @@
package main
// CompletionHandler provides possible completions for given input
type CompletionHandler func(input string) []string
// DefaultCompletionHandler simply returns an empty slice.
var DefaultCompletionHandler = func(input string) []string {
return make([]string, 0)
}
var complHandler = DefaultCompletionHandler
// SetCompletionHandler sets the CompletionHandler to be used for completion
func SetCompletionHandler(c CompletionHandler) {
complHandler = c
}

View File

@ -1,22 +0,0 @@
Copyright (c) 2013, Geert-Johan Riemer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
// +build linenoise
package main
//#include <stdlib.h>
//#include "linenoise.h"
//#include "linenoiseCompletionCallbackHook.h"
import "C"
import (
"errors"
"unsafe"
)
func init() {
C.linenoiseSetupCompletionCallbackHook()
}
func line(prompt string) (string, error) {
promptCString := C.CString(prompt)
resultCString := C.linenoise(promptCString)
C.free(unsafe.Pointer(promptCString))
defer C.free(unsafe.Pointer(resultCString))
if resultCString == nil {
return "", errors.New("exiting due to signal")
}
result := C.GoString(resultCString)
return result, nil
}
func addHistory(line string) error {
lineCString := C.CString(line)
res := C.linenoiseHistoryAdd(lineCString)
C.free(unsafe.Pointer(lineCString))
if res != 1 {
return errors.New("Could not add line to history.")
}
return nil
}
func setHistoryCapacity(capacity int) error {
res := C.linenoiseHistorySetMaxLen(C.int(capacity))
if res != 1 {
return errors.New("Could not set history max len.")
}
return nil
}
// typedef struct linenoiseCompletions {
// size_t len;
// char **cvec;
// } linenoiseCompletions;
// typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
// void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
// void linenoiseAddCompletion(linenoiseCompletions *, char *);
//export linenoiseGoCompletionCallbackHook
func linenoiseGoCompletionCallbackHook(input *C.char, completions *C.linenoiseCompletions) {
completionsSlice := complHandler(C.GoString(input))
completionsLen := len(completionsSlice)
completions.len = C.size_t(completionsLen)
if completionsLen > 0 {
cvec := C.malloc(C.size_t(int(unsafe.Sizeof(*(**C.char)(nil))) * completionsLen))
cvecSlice := (*(*[999999]*C.char)(cvec))[:completionsLen]
for i, str := range completionsSlice {
cvecSlice[i] = C.CString(str)
}
completions.cvec = (**C.char)(cvec)
}
}

View File

@ -1,68 +0,0 @@
// +build linenoise
/* linenoise.h -- guerrilla line editing library against the idea that a
* line editing lib needs to be 20,000 lines of C code.
*
* See linenoise.c for more information.
*
* ------------------------------------------------------------------------
*
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINENOISE_H
#define __LINENOISE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct linenoiseCompletions {
size_t len;
char **cvec;
} linenoiseCompletions;
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
char *linenoise(const char *prompt);
int linenoiseHistoryAdd(const char *line);
int linenoiseHistorySetMaxLen(int len);
int linenoiseHistorySave(const char *filename);
int linenoiseHistoryLoad(const char *filename);
void linenoiseClearScreen(void);
void linenoiseSetMultiLine(int ml);
void linenoisePrintKeyCodes(void);
#ifdef __cplusplus
}
#endif
#endif /* __LINENOISE_H */

View File

@ -1,9 +0,0 @@
// +build linenoise
#include "linenoiseCompletionCallbackHook.h"
extern void linenoiseGoCompletionCallbackHook(const char *, linenoiseCompletions *);
void linenoiseSetupCompletionCallbackHook() {
linenoiseSetCompletionCallback(linenoiseGoCompletionCallbackHook);
}

View File

@ -1,6 +0,0 @@
// +build linenoise
#include <stdlib.h>
#include "linenoise.h"
void linenoiseSetupCompletionCallbackHook();

View File

@ -1,14 +1,14 @@
// +build linenoise
package main package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"os"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/peterh/liner"
"github.com/siddontang/goredis" "github.com/siddontang/goredis"
) )
@ -17,9 +17,24 @@ var port = flag.Int("p", 6380, "ledisdb server port (default 6380)")
var socket = flag.String("s", "", "ledisdb server socket, overwrite ip and port") var socket = flag.String("s", "", "ledisdb server socket, overwrite ip and port")
var dbn = flag.Int("n", 0, "ledisdb database number(default 0)") var dbn = flag.Int("n", 0, "ledisdb database number(default 0)")
var (
line *liner.State
historyPath = "/tmp/ledis-cli"
)
func main() { func main() {
flag.Parse() flag.Parse()
line = liner.NewLiner()
defer line.Close()
line.SetCtrlCAborts(true)
setCompletionHandler()
loadHisotry()
defer saveHisotry()
var addr string var addr string
if len(*socket) > 0 { if len(*socket) > 0 {
addr = *socket addr = *socket
@ -31,9 +46,6 @@ func main() {
c.SetMaxIdleConns(1) c.SetMaxIdleConns(1)
sendSelect(c, *dbn) sendSelect(c, *dbn)
SetCompletionHandler(completionHandler)
setHistoryCapacity(100)
reg, _ := regexp.Compile(`'.*?'|".*?"|\S+`) reg, _ := regexp.Compile(`'.*?'|".*?"|\S+`)
prompt := "" prompt := ""
@ -45,7 +57,7 @@ func main() {
prompt = fmt.Sprintf("%s> ", addr) prompt = fmt.Sprintf("%s> ", addr)
} }
cmd, err := line(prompt) cmd, err := line.Prompt(prompt)
if err != nil { if err != nil {
fmt.Printf("%s\n", err.Error()) fmt.Printf("%s\n", err.Error())
return return
@ -55,7 +67,7 @@ func main() {
if len(cmds) == 0 { if len(cmds) == 0 {
continue continue
} else { } else {
addHistory(cmd) line.AppendHistory(cmd)
args := make([]interface{}, len(cmds[1:])) args := make([]interface{}, len(cmds[1:]))
@ -167,12 +179,29 @@ func sendSelect(client *goredis.Client, index int) {
} }
} }
func completionHandler(in string) []string { func setCompletionHandler() {
var keyWords []string line.SetCompleter(func(line string) (c []string) {
for _, i := range helpCommands { for _, i := range helpCommands {
if strings.HasPrefix(i[0], strings.ToUpper(in)) { if strings.HasPrefix(i[0], strings.ToLower(line)) {
keyWords = append(keyWords, i[0]) c = append(c, i[0])
} }
} }
return keyWords return
})
}
func loadHisotry() {
if f, err := os.Open(historyPath); err == nil {
line.ReadHistory(f)
f.Close()
}
}
func saveHisotry() {
if f, err := os.Create(historyPath); err != nil {
fmt.Printf("Error writing history file: ", err)
} else {
line.WriteHistory(f)
f.Close()
}
} }

View File

@ -1,7 +0,0 @@
// +build !linenoise
package main
func main() {
println("Please use linenoise to build again, or use redis-cli instead")
}