git-subtree-dir: third_party/src/github.com/GeertJohan/go.linenoise git-subtree-split: 5d5d5277d975f40b12167b478c0d79df00bda5a8master
commit
0a65e23e3a
@ -0,0 +1,2 @@ |
|||||||
|
*sublime* |
||||||
|
/examplenoise/examplenoise |
@ -0,0 +1,22 @@ |
|||||||
|
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. |
@ -0,0 +1,14 @@ |
|||||||
|
## go.linenoise |
||||||
|
|
||||||
|
go.linenoise is a [go](http://golang.org) package wrapping the [linenoise](https://github.com/antirez/linenoise) C library. |
||||||
|
|
||||||
|
This package does not compile on windows. |
||||||
|
|
||||||
|
### Documentation |
||||||
|
Documentation can be found at [godoc.org/github.com/GeertJohan/go.linenoise](http://godoc.org/github.com/GeertJohan/go.linenoise). |
||||||
|
An example is located in the folder [examplenoise](examplenoise). |
||||||
|
|
||||||
|
### License |
||||||
|
All code in this repository is licensed under a BSD license. |
||||||
|
This project wraps [linenoise](https://github.com/antirez/linenoise) which is written by Salvatore Sanfilippo and Pieter Noordhuis. The license for linenoise is included in the files `linenoise.c` and `linenoise.h`. |
||||||
|
For all other files please read the [LICENSE](LICENSE) file. |
@ -0,0 +1,11 @@ |
|||||||
|
// Package linenoise wraps the linenoise library (https://github.com/antirez/linenoise).
|
||||||
|
//
|
||||||
|
// The package is imported with "go." prefix
|
||||||
|
// import "github.com/GeertJohan/go.linenoise"
|
||||||
|
//
|
||||||
|
// Simple readline usage:
|
||||||
|
// linenoise.Line("prompt> ")
|
||||||
|
//
|
||||||
|
// Adding lines to history, you could simply do this for every line you read.
|
||||||
|
// linenoise.AddHistory("This will be displayed in prompt when arrow-up is pressed")
|
||||||
|
package linenoise |
@ -0,0 +1,112 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"github.com/GeertJohan/go.linenoise" |
||||||
|
"os" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
func main() { |
||||||
|
fmt.Println("Welcome to go.linenoise example.") |
||||||
|
writeHelp() |
||||||
|
for { |
||||||
|
str, err := linenoise.Line("prompt> ") |
||||||
|
if err != nil { |
||||||
|
if err == linenoise.KillSignalError { |
||||||
|
quit() |
||||||
|
} |
||||||
|
fmt.Println("Unexpected error: %s", err) |
||||||
|
quit() |
||||||
|
} |
||||||
|
fields := strings.Fields(str) |
||||||
|
|
||||||
|
// check if there is any valid input at all
|
||||||
|
if len(fields) == 0 { |
||||||
|
writeUnrecognized() |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
// switch on the command
|
||||||
|
switch fields[0] { |
||||||
|
case "help": |
||||||
|
writeHelp() |
||||||
|
case "echo": |
||||||
|
fmt.Printf("echo: %s\n\n", str[5:]) |
||||||
|
case "clear": |
||||||
|
linenoise.Clear() |
||||||
|
case "multiline": |
||||||
|
fmt.Println("Setting linenoise to multiline") |
||||||
|
linenoise.SetMultiline(true) |
||||||
|
case "singleline": |
||||||
|
fmt.Println("Setting linenoise to singleline") |
||||||
|
linenoise.SetMultiline(false) |
||||||
|
case "complete": |
||||||
|
fmt.Println("Setting arguments as completion values for linenoise.") |
||||||
|
fmt.Printf("%d arguments: %s\n", len(fields)-1, fields[1:]) |
||||||
|
completionHandler := func(in string) []string { |
||||||
|
return fields[1:] |
||||||
|
} |
||||||
|
linenoise.SetCompletionHandler(completionHandler) |
||||||
|
case "printKeyCodes": |
||||||
|
linenoise.PrintKeyCodes() |
||||||
|
case "addHistory": |
||||||
|
if len(str) < 12 { |
||||||
|
fmt.Println("No argument given.") |
||||||
|
} |
||||||
|
err := linenoise.AddHistory(str[11:]) |
||||||
|
if err != nil { |
||||||
|
fmt.Printf("Error: %s\n", err) |
||||||
|
} |
||||||
|
case "save": |
||||||
|
if len(fields) != 2 { |
||||||
|
fmt.Println("Error. Expecting 'save <filename>'.") |
||||||
|
continue |
||||||
|
} |
||||||
|
err := linenoise.SaveHistory(fields[1]) |
||||||
|
if err != nil { |
||||||
|
fmt.Printf("Error on save: %s\n", err) |
||||||
|
} |
||||||
|
case "load": |
||||||
|
if len(fields) != 2 { |
||||||
|
fmt.Println("Error. Expecting 'load <filename>'.") |
||||||
|
continue |
||||||
|
} |
||||||
|
err := linenoise.LoadHistory(fields[1]) |
||||||
|
if err != nil { |
||||||
|
fmt.Printf("Error on load: %s\n", err) |
||||||
|
} |
||||||
|
case "quit": |
||||||
|
quit() |
||||||
|
default: |
||||||
|
writeUnrecognized() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func quit() { |
||||||
|
fmt.Println("Thanks for running the go.linenoise example.") |
||||||
|
fmt.Println("") |
||||||
|
os.Exit(0) |
||||||
|
} |
||||||
|
|
||||||
|
func writeHelp() { |
||||||
|
fmt.Println("help write this message") |
||||||
|
fmt.Println("echo ... echo the arguments") |
||||||
|
fmt.Println("clear clear the screen") |
||||||
|
fmt.Println("multiline set linenoise to multiline") |
||||||
|
fmt.Println("singleline set linenoise to singleline") |
||||||
|
fmt.Println("complete ... set arguments as completion values") |
||||||
|
fmt.Println("addHistory ... add arguments to linenoise history") |
||||||
|
fmt.Println("save <filename> save the history to file") |
||||||
|
fmt.Println("load <filename> load the history from file") |
||||||
|
fmt.Println("quit stop the program") |
||||||
|
fmt.Println("") |
||||||
|
fmt.Println("Use the arrow up and down keys to walk through history.") |
||||||
|
fmt.Println("Note that you have to use addHistory to create history entries. Commands are not added to history in this example.") |
||||||
|
fmt.Println("") |
||||||
|
} |
||||||
|
|
||||||
|
func writeUnrecognized() { |
||||||
|
fmt.Println("Unrecognized command. Use 'help'.") |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,142 @@ |
|||||||
|
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() |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
/* 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-2014, Salvatore Sanfilippo <antirez at gmail dot com> |
||||||
|
* Copyright (c) 2010-2013, 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 */ |
@ -0,0 +1,8 @@ |
|||||||
|
|
||||||
|
#include "linenoiseCompletionCallbackHook.h" |
||||||
|
|
||||||
|
extern void linenoiseGoCompletionCallbackHook(const char *, linenoiseCompletions *); |
||||||
|
|
||||||
|
void linenoiseSetupCompletionCallbackHook() { |
||||||
|
linenoiseSetCompletionCallback(linenoiseGoCompletionCallbackHook); |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
|
||||||
|
#include <stdlib.h> |
||||||
|
#include "linenoise.h" |
||||||
|
|
||||||
|
void linenoiseSetupCompletionCallbackHook(); |
@ -0,0 +1,8 @@ |
|||||||
|
package linenoise |
||||||
|
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include "linenoise.h"
|
||||||
|
import "C" |
||||||
|
|
||||||
|
// this will break a go build on windows and display the string on console
|
||||||
|
"go.linenoise does not support windows." |
Loading…
Reference in new issue