You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.3 KiB
143 lines
4.3 KiB
10 years ago
|
package linenoise
|
||
|
|
||
|
// -windows
|
||
|
|
||
|
// #include <stdlib.h>
|
||
|
// #include "linenoise.h"
|
||
|
// #include "linenoiseCompletionCallbackHook.h"
|
||
|
import "C"
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
// KillSignalError is returned returned by Line() when a user quits from prompt.
|
||
|
// This occurs when the user enters ctrl+C or ctrl+D.
|
||
|
var KillSignalError = errors.New("prompt was quited with a killsignal")
|
||
|
|
||
|
func init() {
|
||
|
C.linenoiseSetupCompletionCallbackHook()
|
||
|
}
|
||
|
|
||
|
// Line displays given string and returns line from user input.
|
||
|
func Line(prompt string) (string, error) { // char *linenoise(const char *prompt);
|
||
|
promptCString := C.CString(prompt)
|
||
|
resultCString := C.linenoise(promptCString)
|
||
|
C.free(unsafe.Pointer(promptCString))
|
||
|
defer C.free(unsafe.Pointer(resultCString))
|
||
|
|
||
|
if resultCString == nil {
|
||
|
return "", KillSignalError
|
||
|
}
|
||
|
|
||
|
result := C.GoString(resultCString)
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
// AddHistory adds a line to history. Returns non-nil error on fail.
|
||
|
func AddHistory(line string) error { // int linenoiseHistoryAdd(const char *line);
|
||
|
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
|
||
|
}
|
||
|
|
||
|
// SetHistoryCapacity changes the maximum length of history. Returns non-nil error on fail.
|
||
|
func SetHistoryCapacity(capacity int) error { // int linenoiseHistorySetMaxLen(int len);
|
||
|
res := C.linenoiseHistorySetMaxLen(C.int(capacity))
|
||
|
if res != 1 {
|
||
|
return errors.New("Could not set history max len.")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// SaveHistory saves from file with given filename. Returns non-nil error on fail.
|
||
|
func SaveHistory(filename string) error { // int linenoiseHistorySave(char *filename);
|
||
|
filenameCString := C.CString(filename)
|
||
|
res := C.linenoiseHistorySave(filenameCString)
|
||
|
C.free(unsafe.Pointer(filenameCString))
|
||
|
if res != 0 {
|
||
|
return errors.New("Could not save history to file.")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// LoadHistory loads from file with given filename. Returns non-nil error on fail.
|
||
|
func LoadHistory(filename string) error { // int linenoiseHistoryLoad(char *filename);
|
||
|
filenameCString := C.CString(filename)
|
||
|
res := C.linenoiseHistoryLoad(filenameCString)
|
||
|
C.free(unsafe.Pointer(filenameCString))
|
||
|
if res != 0 {
|
||
|
return errors.New("Could not load history from file.")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Clear clears the screen.
|
||
|
func Clear() { // void linenoiseClearScreen(void);
|
||
|
C.linenoiseClearScreen()
|
||
|
}
|
||
|
|
||
|
// SetMultiline sets linenoise to multiline or single line.
|
||
|
// In multiline mode the user input will be wrapped to a new line when the length exceeds the amount of available rows in the terminal.
|
||
|
func SetMultiline(ml bool) { // void linenoiseSetMultiLine(int ml);
|
||
|
if ml {
|
||
|
C.linenoiseSetMultiLine(1)
|
||
|
} else {
|
||
|
C.linenoiseSetMultiLine(0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 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)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PrintKeyCodes puts linenoise in key codes debugging mode.
|
||
|
// Press keys and key combinations to see key codes. Type 'quit' at any time to exit.
|
||
|
// PrintKeyCodes blocks until user enters 'quit'.
|
||
|
func PrintKeyCodes() { // void linenoisePrintKeyCodes(void);
|
||
|
C.linenoisePrintKeyCodes()
|
||
|
}
|