ledisdb/cmd/ledis-cli/linenoise.go

90 lines
2.3 KiB
Go
Raw Normal View History

2014-07-01 06:34:45 +04:00
package main
//#include <stdlib.h>
//#include "linenoise.h"
2014-07-22 15:54:17 +04:00
//#include "linenoiseCompletionCallbackHook.h"
2014-07-01 06:34:45 +04:00
import "C"
import (
"errors"
"unsafe"
)
2014-07-22 15:54:17 +04:00
func init() {
C.linenoiseSetupCompletionCallbackHook()
}
2014-07-01 06:34:45 +04:00
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("quited by a 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
}
2014-07-22 15:54:17 +04:00
// 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
}
// 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)
}
}