chzyer / readline Goto Github PK
View Code? Open in Web Editor NEWReadline is a pure go(golang) implementation for GNU-Readline kind library
License: MIT License
Readline is a pure go(golang) implementation for GNU-Readline kind library
License: MIT License
I'd like to use readline as a front end for a microcontroller attached over serial, to provide command history and searching. The basic idea is: enter a line, the line is sent out, gets echoed and processed by the microcontroller, and so on.
It works fine for normal use. The line is cleared when I hit return, and the echoed results show up in its place - just as intended. One special detail is that the returned line may contain more information than what was entered, appended to the end (i.e. results of a command are shown on the same line).
When I hit up/down arrow, I can access command history, and everything still works splendidly.
But when I hit ctrl-r, the text bck-i-search:
is printed and the cursor then moves up. This then destroys what was reported in the last output line.
Furthermore, when hitting a key repeatedly, if there is no matching history entry, the cursor will continue to be moved up, with below it the text failing bck-i-search: ...
. Hitting x repeatedly will gradually clear the entire screen while moving the cursor up.
Am I using this package wrong? Is there a way to work around this? Have I hit a bug in readline?
Attached the entire code I'm using. I can test further and provide more information - please just let me know. I'm using the latest version of readline from GitHub as of Oct 16th.
Cheers,
-jcw
PS. I'm on macOS 10.12, the above happens with both Terminal and iTerm2.
package main
import (
"os"
"bytes"
"github.com/chzyer/readline"
"github.com/pkg/term"
)
func main() {
tty, _ := term.Open("/dev/cu.usbmodemD5D4C5E3",
term.Speed(115200), term.RawMode)
rl, _ := readline.NewEx(&readline.Config{
UniqueEditLine: true,
})
defer rl.Close()
go func() {
for {
line := make([]byte, 100)
n, _ := tty.Read(line)
line = bytes.Replace(line[:n], []byte("\n"), []byte("\r\n"), -1)
os.Stdout.Write(line)
}
}()
for {
line, err := rl.Readline()
if err != nil {
break
}
tty.Write([]byte(line + "\r"))
}
}
Hi I noticed a malfunction when having PcItems with same prefix
Using this completer:
var completer = readline.NewPrefixCompleter(
readline.PcItem("simple",
readline.PcItem("rule",
readline.PcItem("-name"),
readline.PcItem("-name2"),
readline.PcItem("-name23"),
),
),
)
A will get following completion tree
.simple
......rule
............-name (as it is common prefix for all)
..................-name-name (this is not so good)
..................-name2
..................-name23
I would look at it on my own but I'm not sure where to look.
it works fine for
var completer = readline.NewPrefixCompleter(
readline.PcItem("simple",
readline.PcItem("rule",
readline.PcItem("-abc"),
readline.PcItem("-def"),
readline.PcItem("-qwe"),
),
),
)
prefix of agrs is not common
I want the prompt displays the path. Example:
# show
show# ip
show ip# list
How to do it?
I would like to create a program in the same spirit as fzf
I would like to use stdin myself in myprogram
cat /etc/var/nginx.log | myprogram
And be able to use readline inside my program.
Here's how fzf does it :
Do you think it is possible ?
When using iTerm2, the arrow keys are generating escape O sequences which are being printed out to screen instead of scrolling back in history of moving between characters. Is there any intention of supporting the escape O sequences in addition to the escape [ sequences?
For reference, the iTerm FAQ talks about the escape sequences under "Why my arrow/HOME/END keys are not working?"
You simple example wrapped into a binary panics on windows, when pressing the tab key.
This happens on windows 7 and windows 8.1.
package main
import "github.com/chzyer/readline"
func main() {
rl, err := readline.New("> ")
if err != nil {
panic(err)
}
defer rl.Close()
for {
line, err := rl.Readline()
if err != nil { // io.EOF
break
}
println(line)
}
}
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x20 pc=0x43d363]
goroutine 8 [running]:
github.com/chzyer/readline.(*opCompleter).OnComplete(0xc082050000)
c:/test/go/src/github.com/chzyer/readline/complete.go:76 +0x2e3
github.com/chzyer/readline.(*Operation).ioloop(0xc082008280)
c:/test/go/src/github.com/chzyer/readline/operation.go:118 +0x877
created by github.com/chzyer/readline.NewOperation
c:/test/go/src/github.com/chzyer/readline/operation.go:64 +0x491
goroutine 1 [chan receive]:
github.com/chzyer/readline.(*Operation).Runes(0xc082008280, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/test/go/src/github.com/chzyer/readline/operation.go:258 +0xbe
github.com/chzyer/readline.(*Operation).String(0xc082008280, 0x0, 0x0, 0x0, 0x0)
c:/test/go/src/github.com/chzyer/readline/operation.go:248 +0x56
github.com/chzyer/readline.(*Instance).Readline(0xc08200a410, 0x0, 0x0, 0x0, 0x0)
c:/test/go/src/github.com/chzyer/readline/readline.go:76 +0x57
main.main()
c:/test/go/src/rltest/main.go:13 +0xaf
goroutine 5 [chan receive]:
github.com/chzyer/readline.(*ANSIWriter).ioloop(0xc0820041c0)
c:/test/go/src/github.com/chzyer/readline/ansi_windows.go:101 +0x139
created by github.com/chzyer/readline.NewANSIWriter
c:/test/go/src/github.com/chzyer/readline/ansi_windows.go:64 +0xd7
goroutine 6 [chan receive]:
github.com/chzyer/readline.(*ANSIWriter).ioloop(0xc082004240)
c:/test/go/src/github.com/chzyer/readline/ansi_windows.go:101 +0x139
created by github.com/chzyer/readline.NewANSIWriter
c:/test/go/src/github.com/chzyer/readline/ansi_windows.go:64 +0xd7
goroutine 7 [syscall, locked to thread]:
github.com/chzyer/readline.func·021(0xc0820069a0, 0x4, 0x4, 0x0, 0x0)
c:/test/go/src/github.com/chzyer/readline/windows_api.go:120 +0x40b
github.com/chzyer/readline.(*RawReader).Read(0xc08200a3d0, 0xc08205b000, 0x1000, 0x1000, 0x4, 0x0, 0x0)
c:/test/go/src/github.com/chzyer/readline/rawreader_windows.go:46 +0x131
bufio.(*Reader).fill(0xc082042480)
c:/go/src/bufio/bufio.go:97 +0x1d5
bufio.(*Reader).ReadRune(0xc082042480, 0xc082042300, 0xc082049f14, 0x0, 0x0)
c:/go/src/bufio/bufio.go:227 +0xde
github.com/chzyer/readline.(*Terminal).ioloop(0xc082008230)
c:/test/go/src/github.com/chzyer/readline/terminal.go:95 +0x1c3
created by github.com/chzyer/readline.NewTerminal
c:/test/go/src/github.com/chzyer/readline/terminal.go:39 +0x279
exit status 2
Hello,
I have the following scenario in a program I'm writing.
Connection to one or more servers in their own go routines, with a sync.WaitGroup that will terminate the program if all servers are disconnected. Signal monitoring, which also monitors a boolean quit channel, so if a quit command is entered in the terminal window, the program will quit. Checks on the readline instance to determine if an interrupt of any kind is received, which will also quit the program. Entering the quot command in the terminal, or CTRL+C for interrupts shuts the program down cleanly, but trying to kill the program by sending it a signal will not terminate the program until enter is pressed, or likely, some other signal interrupt received.
Briefly, here is how I believe this could be reproduced.
My question is this. Is the Close() function call supposed to block like this? Or, could I read input in another way that would return an error immediately after the readline instance is closed, and not block on the readline instance Close() method? I could then completely end the program without the need for an extra step of entering a blank newline or otherwise.
Blake
When autocompleting or after completing command (after hitting enter), the next line after command line is indented. It starts on the same position as the old one ends, ilustration:
» say
hello bye
or
» test test
2016/07/21 09:55:19 you said: "test test"
Tested on two Linux machines, one of them was Debian 5.4.0-6 (Linux version 4.6.0-1-amd64) with pure installation of Go:
sudo apt install golang
export GOPATH=$HOME/go
go get github.com/chzyer/readline
go run go/src/github.com/chzyer/readline/example/readline-demo/readline-demo.go
This bug is probably caused by some changes in external packages, because when I was using older version of all packages (e.q. one month), all works as expected.
I'm running the simplest example under screen and the terminal is getting cleared at startup. It shouldn't be clearing the screen.
If I capture a screen log I get the following
$ hexdump -C screenlog.14 00000000 67 6f 20 72 75 6e 20 74 65 73 74 2e 67 6f 20 0d |go run test.go .| 00000010 0a 1b 5b 4a 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |..[J.[2K...[2K..| 00000020 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000030 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000040 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000050 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000060 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000070 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000080 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000090 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 000000a0 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 000000b0 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 000000c0 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 000000d0 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 000000e0 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 000000f0 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000100 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000110 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000120 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000130 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000140 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000150 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000160 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000170 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000180 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000190 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 000001a0 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 000001b0 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 000001c0 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 000001d0 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 000001e0 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 000001f0 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000200 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000210 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000220 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000230 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000240 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b |...[2K...[2K...[| 00000250 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 |2K...[2K...[2K..| 00000260 1b 5b 32 4b 0d 08 1b 5b 32 4b 0d 08 1b 5b 32 4b |.[2K...[2K...[2K| 00000270 0d 08 3e 20 |..> |
take the simplest example code from the main github page
package main import "github.com/chzyer/readline" func main() { rl, err := readline.New("> ") if err != nil { panic(err) } defer rl.Close() for { line, err := rl.Readline() if err != nil { // io.EOF break } println(line) } }
Hello @chzyer, thanks for this nifty library.
I hit a little problem when using it though: I want a user to enter a password (in plaintext) and check it's strength using the zxcvbn library. Depending on the strength I would color the Password:
prompt in a friendlier color. For this I modified the Autorefresh
example of yours, so that the refresh would fetch the current input, check the strength and do a fitting SetPrompt()
.
However, when using rl.Operation.Runes()
directly all sort of weird behaviour appears.
This appears due to the fact that it does not only fetch the current runes, but also does some IO. For testing I exposed the buf *RuneBuffer
in readline.Operation
to the outside and used it's Runes()
method directly.
Despite being an awful hack, it seems to work - am I doing something awfully wrong, or would the addition of another method that just fetches the current buffer contents appropiate?
Here's my current (working) attempt:
https://gist.github.com/sahib/2ee21e8d636c98876a83
Thanks.
Hello,
I'm working on a tool that emulate an terminal online.
I have a simple dynamic function that list directory dynamically.
Example:
If user write "ls" without anything.
It will print (with autocompleter) the current directory in help.
But if the user writes : ls ..
The action blocks.
I have notice that the problem comes with the line 160 in the file complete_helper.go :
return doInternal(lineCompleter, tmpLine, len(tmpLine), origLine)
When I comment this line, it prints well the directory with new scope "..".
Why this return is here ?
My function =
func (k *Kernel) ListLocalFiles() func(string) []string {
return func(line string) []string {
names := make([]string, 0)
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
return names
}
arr := strings.Fields(line)
if len(arr) > 1 {
dir = arr[1]
}
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
names = append(names, f.Name())
}
return names
}
}
In a simple app, using Alt tab seems to send the alt
signal to readline, which switches to "Esc" mode.. but hitting Alt+Tab
to switch, prevents the key release event to go through. So when we come back to the app, hitting d
for example, calls DeleteWord
or something.
Is there any way we could make sure to depress the alt, or release it after a given amount of time, or anything that wouldn't put the readline lib into an "always alt+" mode ?
Found with the following:
AddHistory("foo\nbar")
)See: https://circleci.com/gh/cockroachdb/cockroach/22259
This prevents us at CockroachDB from upgrading to the latest readline.
The problem is that the global var Stdin
is set to a CancelableStdin
object but this object is never closed, so there is a goroutine remaining when the program using readline
terminates. This makes leak checkers unhappy.
The better solution would be to create an API for readline to "initialize" and "finalize" the entire library. The CancelableStdin object would be created in "initialize" and closed in "finalize". This way, if a program (like cockroach
) merely imports the readline
package but does not actually use it, there will be no goroutine created.
Is it possible to do case-insensitive completion?
At CockroachDB we are now using expect to test the SQL shell and this shows all the characters sent by the program to the terminal. In our expect traces we see things like this:
send: sending "select 1;\r" to { exp6 }
expect: does ":26257> \u0008" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> se
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se" (spawn_id exp6) match glob pattern "1 row"? no root@:26257> selec
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se\u001b[J\u001b[2K\rroot@:26257> sel\u001b[J\u001b[2K\rroot@:26257> sele\u001b[J\u001b[2K\rroot@:26257> selec" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> select 1;
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se\u001b[J\u001b[2K\rroot@:26257> sel\u001b[J\u001b[2K\rroot@:26257> sele\u001b[J\u001b[2K\rroot@:26257> selec\u001b[J\u001b[2K\rroot@:26257> select\u001b[J\u001b[2K\rroot@:26257> select \u001b[J\u001b[2K\rroot@:26257> select 1\u001b[J\u001b[2K\rro
ot@:26257> select 1;" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> select 1;
What is happening here, is that after every character typed by the user (received by readline from the terminal), readline issues \033[J\033[2K\r
to the terminal then redraws (re-outputs) the prompt and all the characters typed so far.
This is sub-optimal: a redraw should only be necessary when characters previously present in the readline buffer are modified (e.g. when using left-arrow, up-arrow etc). During normal input of non-special characters, this redraw is unnecessary.
Also on slow terminals (like over slow ssh connections) this redraw becomes clearly noticeable to the user for very long inputs.
RemoteSvr.Read
need a to return EOF error in that case.
We're gearing up to use this library for Terraform and we target Solaris and have users using that OS. This library unfortunately doesn't compile there due to missing the State
struct there.
We've built around it with build tags for now to simply not support our interactive console feature there but it'd be fantastic if this was supported.
It's the cockroach project that uses your readline library, but when I tried to back search (using Ctrl+R), it just crashes, the backtrace is as follows:
Please help fix this. Thanks!
# Welcome to the cockroach SQL interface.
# All statements must be terminated by a semicolon.
# To exit: CTRL + D.
root@:15432> panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0xb8 pc=0x42e0c96]
goroutine 12 [running]:
github.com/chzyer/readline.(*opSearch).SearchRefresh(0xc8202925b0, 0xd)
/Users/q/go/src/github.com/chzyer/readline/search.go:127 +0xc6
github.com/chzyer/readline.(*opSearch).SearchMode(0xc8202925b0, 0x0)
/Users/q/go/src/github.com/chzyer/readline/search.go:100 +0x78
github.com/chzyer/readline.(*Operation).ioloop(0xc820261440)
/Users/q/go/src/github.com/chzyer/readline/operation.go:140 +0x2112
created by github.com/chzyer/readline.NewOperation
/Users/q/go/src/github.com/chzyer/readline/operation.go:70 +0x428
goroutine 1 [select]:
github.com/chzyer/readline.(*Operation).Runes(0xc820261440, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/q/go/src/github.com/chzyer/readline/operation.go:316 +0x2d5
github.com/chzyer/readline.(*Operation).String(0xc820261440, 0x0, 0x0, 0x0, 0x0)
/Users/q/go/src/github.com/chzyer/readline/operation.go:300 +0x40
github.com/chzyer/readline.(*Instance).Readline(0xc82027ed80, 0x0, 0x0, 0x0, 0x0)
/Users/q/go/src/github.com/chzyer/readline/readline.go:184 +0x3d
github.com/chzyer/readline.Line(0xc82028d700, 0xd, 0x0, 0x0, 0x0, 0x0)
/Users/q/go/src/github.com/chzyer/readline/std.go:44 +0xf6
github.com/cockroachdb/cockroach/cli.runInteractive(0xc8202943c0, 0xc820205e60, 0x28, 0x0, 0x0)
/Users/q/go/src/github.com/cockroachdb/cockroach/cli/sql.go:173 +0x450
github.com/cockroachdb/cockroach/cli.runTerm(0x5c13320, 0xc82028d600, 0x0, 0x1, 0x0, 0x0)
/Users/q/go/src/github.com/cockroachdb/cockroach/cli/sql.go:271 +0x151
github.com/spf13/cobra.(*Command).execute(0x5c13320, 0xc82028d5a0, 0x1, 0x1, 0x0, 0x0)
/Users/q/go/src/github.com/spf13/cobra/command.go:565 +0x63b
github.com/spf13/cobra.(*Command).ExecuteC(0x5c10320, 0x5c13320, 0x0, 0x0)
/Users/q/go/src/github.com/spf13/cobra/command.go:656 +0x56b
github.com/spf13/cobra.(*Command).Execute(0x5c10320, 0x0, 0x0)
/Users/q/go/src/github.com/spf13/cobra/command.go:615 +0x2d
github.com/cockroachdb/cockroach/cli.Run(0xc82000a190, 0x2, 0x2, 0x0, 0x0)
/Users/q/go/src/github.com/cockroachdb/cockroach/cli/cli.go:85 +0x7c
main.main()
/Users/q/go/src/github.com/cockroachdb/cockroach/main.go:37 +0xe6
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/Cellar/go/1.5.3/libexec/src/runtime/asm_amd64.s:1721 +0x1
goroutine 7 [chan receive]:
github.com/cockroachdb/cockroach/util/log.(*loggingT).flushDaemon(0x5c23740)
/Users/q/go/src/github.com/cockroachdb/cockroach/util/log/clog.go:1030 +0x64
created by github.com/cockroachdb/cockroach/util/log.init.1
/Users/q/go/src/github.com/cockroachdb/cockroach/util/log/clog.go:610 +0xbc
goroutine 9 [syscall]:
os/signal.loop()
/usr/local/Cellar/go/1.5.3/libexec/src/os/signal/signal_unix.go:22 +0x18
created by os/signal.init.1
/usr/local/Cellar/go/1.5.3/libexec/src/os/signal/signal_unix.go:28 +0x37
goroutine 10 [chan receive]:
database/sql.(*DB).connectionOpener(0xc8202943c0)
/usr/local/Cellar/go/1.5.3/libexec/src/database/sql/sql.go:634 +0x45
created by database/sql.Open
/usr/local/Cellar/go/1.5.3/libexec/src/database/sql/sql.go:481 +0x336
goroutine 11 [syscall]:
syscall.Syscall(0x3, 0x0, 0xc8202ac000, 0x1000, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/syscall/asm_darwin_amd64.s:16 +0x5
syscall.read(0x0, 0xc8202ac000, 0x1000, 0x1000, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/syscall/zsyscall_darwin_amd64.go:972 +0x5f
syscall.Read(0x0, 0xc8202ac000, 0x1000, 0x1000, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/syscall/syscall_unix.go:160 +0x4d
os.(*File).read(0xc82002c008, 0xc8202ac000, 0x1000, 0x1000, 0xc8202612b8, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/os/file_unix.go:211 +0x75
os.(*File).Read(0xc82002c008, 0xc8202ac000, 0x1000, 0x1000, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/os/file.go:95 +0x8a
bufio.(*Reader).fill(0xc82002be70)
/usr/local/Cellar/go/1.5.3/libexec/src/bufio/bufio.go:97 +0x1e9
bufio.(*Reader).ReadRune(0xc82002be70, 0xc820261260, 0xc82002bddc, 0x0, 0x0)
/usr/local/Cellar/go/1.5.3/libexec/src/bufio/bufio.go:260 +0xc8
github.com/chzyer/readline.(*Terminal).ioloop(0xc8202904b0)
/Users/q/go/src/github.com/chzyer/readline/terminal.go:111 +0x24b
created by github.com/chzyer/readline.NewTerminal
/Users/q/go/src/github.com/chzyer/readline/terminal.go:34 +0x189
Hi, when pressing ctrl+L to clear the screen, it instead inserts a new line and misplace the pompt (see here).
That is after pressing ctrl+L 3 times. This is on Linux in termite, but also happens in terminator and xterm.
The current line is splitted into multiple lines based on terminal width. Splitting is actually precalculated inside functions SplitByMultiLine and SplitByLine. Then, when printing a line, '\n' are sent to terminal after each precalculated line (lines that are a product of splitting). All of this rely on the fact that most terminals will do the same on window width change. They will wrap all lines from history and current editing line around new width boundary. Line printing, cleaining, and on width change logic relys on this idea of splitting.
First thing
I believe there is a problem when you have a line that needs to be splitted in more than two lines. The code doesn't perform well in some cases. For example, when you need to split a very long line into 5 new ones. This would be a dirty fix for such scenario:
func SplitByMultiLine(start, oldWidth, newWidth int, rs []rune) []string {
var ret []string
buf := bytes.NewBuffer(nil)
currentWidth := start
for _, r := range rs {
w := runes.Width(r)
currentWidth += w
buf.WriteRune(r)
if currentWidth%newWidth == 0 {
ret = append(ret, buf.String())
buf.Reset()
if currentWidth == oldWidth {
currentWidth = 0
}
continue
}
if currentWidth >= oldWidth {
ret = append(ret, buf.String())
buf.Reset()
currentWidth = 0
}
}
if buf.Len() > 0 {
ret = append(ret, buf.String())
}
return ret
}
Second thing
Adding NL after each split, gives terminal application 'a permission' to send some parts of original line beyond top of window screen, which taints scroll buffer. Every line that ends with '\n' becomes a part of history. So basically, complete line splitting logic that is used in printing and cleaning inside runebuf, that is relying on prediction of how many new lines will show on screen after line wrapping (done by terminal application automatically), can affect scrollbuffer badly. Once that a line (born after splitting) goes into scroll buffer, it might be gone from the screen as well. That breaks line cleaning logic from runebuf that sends "\033[2K\r\033[A" for every line, and moving cursor beyond top of the screen just doesn't work. Expecting that every splitted line will be always on screen is just not a good prediction. I suggest to replace the whole logic behind it. Adding NL artifically is just bad for scroll buffer and it breaks behaviour of terminal application in some cases.
Found in https://teamcity.cockroachdb.com/viewLog.html?buildId=20052#334279584_2_20052_problem:
github.com/chzyer/readline.(*RuneBuffer).PromptLen()
/go/src/github.com/chzyer/readline/runebuf.go:78 +0x5c
vs.
github.com/cockroachdb/cockroach/cli.runInteractive() // where SetPrompt() is called
/go/src/github.com/cockroachdb/cockroach/cli/sql.go:283 +0x2b9
The SetPrompt method should protect the prompt variable with a mutex.
I'm currently working on a CLI client for a chat application and I really like how this library manipulates the log output. There is currently besides this library no Go library available that refreshes the stdout without including all kinds of lay-outing I do not need.
But I have a question: Is it possible to prevent Readline() from printing to the terminal output?
Currently my output looks like this
(INSERT) > test
2016/02/14 15:59:07 > Rivalo > test
Where (INSERT) >
is the prompt for reading the line, and the next line simply returns the sent message inside the chat channel.
I want to prevent the User's message from displaying twice but keep the consistency with the messages from others, which means that after a \n
readline() shouldn't print its just received line to the stdout.
Is there currently an option or workaround for this I'm overlooking in the documentation?
(Please, in future, add comments above exported functions, it makes the godoc documentation easier to read)
Hello,
I'm using readline
in a terminal emulation setting - in this context, it would be nice to capture ctrl-c and send a remote reset instead of quitting the application (ctrl-d can be used for that). Is this possible? Can a custome Listener be used for this?
With many thanks for creating such a nice utility,
-jcw
hi, I'm using readline to accomplish goshell. And I expect tab key as normal input in any editor, how can I do that?
This library is missing many common vi mode commands that are implemented in readline/libedit.
Here are the ones that stood out most to me as I tried using a simple command prompt:
c<motion>
, d<motion>
(change, delete)x
(delete character)r
(replace character)Currently stdin an isatty are not configureable which makes using this package with x/crypto/ssh impossible.
I'm going to use your package in my project, but it would be really nice if it also had stable versions tagged so I could use it through gopkg.in! :)
Any plans to support the M-C-j functionality as described here: https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC22
I have a problem where occasionally readline will deadlock. I'm using readline in a couple of different simple CLI tools. There's nothing too unusual or fancy about the usage. I can't share the code, but maybe the information I've got would be useful.
The most recent time the problem happened, my program got stuck calling (*Instance).ReadLine()
. Nothing I typed caused that ReadLine call to return.
Here are a couple of the goroutines from the stack trace that I obtained with SIGQUIT:
goroutine 1 [select]:
xxx/vendor/github.com/chzyer/readline.(*Operation).Runes(0xc820317560, 0x0, 0x0, 0x0, 0x0, 0x0)
/gopath/src/xxx/vendor/github.com/chzyer/readline/operation.go:340 +0x369
xxx/vendor/github.com/chzyer/readline.(*Operation).String(0xc820317560, 0x0, 0x0, 0x0, 0x0)
/gopath/src/xxx/vendor/github.com/chzyer/readline/operation.go:327 +0x40
xxx/vendor/github.com/chzyer/readline.(*Instance).Readline(0xc820309400, 0x0, 0x0, 0x0, 0x0)
/gopath/src/xxx/vendor/github.com/chzyer/readline/readline.go:216 +0x3d
main.main()
/gopath/src/xxx/tool/tool.go:113 +0x1740 // this is where my code calls (*Instance).ReadLine()
goroutine 45 [select]:
xxx/vendor/github.com/chzyer/readline.(*Terminal).ioloop(0xc820304f40)
/gopath/src/xxx/vendor/github.com/chzyer/readline/terminal.go:108 +0x441
created by xxx/vendor/github.com/chzyer/readline.NewTerminal
/gopath/src/xxx/vendor/github.com/chzyer/readline/terminal.go:33 +0x186
goroutine 47 [chan receive]:
xxx/vendor/github.com/chzyer/readline.DefaultOnWidthChanged.func1.1(0xc8203175c0)
/gopath/src/xxx/vendor/github.com/chzyer/readline/utils_unix.go:72 +0x43
created by xxx/vendor/github.com/chzyer/readline.DefaultOnWidthChanged.func1
/gopath/src/xxx/vendor/github.com/chzyer/readline/utils_unix.go:78 +0x13f
goroutine 48 [chan receive]:
xxx/vendor/github.com/chzyer/readline.(*Operation).ioloop(0xc820317560)
/gopath/src/xxx/vendor/github.com/chzyer/readline/operation.go:98 +0x5b
created by xxx/vendor/github.com/chzyer/readline.NewOperation
/gopath/src/xxx/vendor/github.com/chzyer/readline/operation.go:82 +0x4a6
It would be nice to be compatible with liner, at least for the basic usages.
One idea is, to create a subpackage:
github.com/chzyer/readline/liner
which translates the liner interface to readline.
In this case, only the import path needs to be changed and it's very easy to compare the libraries.
What do you think?
Instance doesn't appear to be closing properly. When I attempt to close the instance it returns "errno 0" and doesn't release the terminal. Attached is a simple application which demonstrates the issue:
package main
import (
"fmt"
"github.com/chzyer/readline"
)
func main() {
rl, err := readline.NewEx(&readline.Config{
Prompt: "rl# ",
})
if err != nil {
fmt.Printf("Failed to create readline: %v\n", err)
return
}
fmt.Printf("enter 2 lines of stuff\n")
for i := 0; i < 2; i++ {
line, err := rl.Readline()
if err != nil {
fmt.Printf("ERR: %v\n", err)
return
}
fmt.Fprintf(rl.Stderr(), "you said: %v\n", line)
}
if err := rl.Close(); err != nil {
fmt.Printf("Failed to close readline instance: %v\n", err);
}
var input string
if _, err := fmt.Scanf("Input stuff: %s", &input); err != nil {
fmt.Printf("simple input: %v\n", input)
}
}
After attempting to close (I can attempt to close a few times, 2nd one seems to not return an error) the readline Instance is still consuming input. If I am not using it correctly, let me know.
Sometimes when I use history using up/down arrows the output get broken.
Command is printed out but not to current line.
It will get printed to a new line and I will get another line for input. Hard to explain hard to reproduce.
Example will be the best:
For expected history
command one
command two
command three
command four
Initial state (enter command is propmt message, _ is current cursos):
enter command: _
after playing with history I got output like this
enter command: command three _
(after pressing up arrow)
enter command:
command two
_
(then I press up arrow again [enter key is not pressed] and output is like this)
enter command:
command two
enter command: command one _
I hope it is a bit clear with this example. I'm not really sure where to look at
There is a specific case when you delete the first character in select mode, library panics out:
`> panic: runtime error: integer divide by zero
[signal 0x8 code=0x7 addr=0x5958e pc=0x5958e]
goroutine 6 [running]:
panic(0x1306a0, 0xc82000a0b0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:481 +0x3e6
gopkg.in/readline%2ev1.(_opCompleter).doSelect(0xc820084080)
/go/src/gopkg.in/readline.v1/complete.go:49 +0xee
gopkg.in/readline%2ev1.(_opCompleter).OnComplete(0xc820084080)
/go/src/gopkg.in/readline.v1/complete.go:72 +0x1e6
gopkg.in/readline%2ev1.(*Operation).ioloop(0xc820060300)
/go/src/gopkg.in/readline.v1/operation.go:172 +0x1439
created by gopkg.in/readline%2ev1.NewOperation
/go/src/gopkg.in/readline.v1/operation.go:67 +0x42a`
Here is a gist of what I'm using to test this:
https://gist.github.com/antekresic/283106411e826f53799fa4565e90f094
Steps to reproduce: press 's', Tab, Tab, Backspace
Issue seems to be caused by entering OnComplete for an empty input rune buffer. My fix suggestion is to add a check for the empty buffer here:
https://github.com/chzyer/readline/blob/master/complete.go#L69
Let me know if you want a PR.
Thanks!
Can i set autocomplete items in runtime?
Hello - I'm having a hard time figuring out how to cleanly restore the tty state to cooked mode when my application exits. I can use a defer.Close()
in the goroutine where rl.ReadLine()
is running, but the problem is that sometimes my application must quit programmatically (or panics). In these cases, the program exists and leaves the terminal in a very confusing raw/noecho mode.
The only workaround I can think of is to open a pipe to a child process, which then waits for its input to close before it runs stty sane
(but this won't be portable to Windows, as far as I know). And it feels like a hack...
Is there a standard idiom for this? Or some example code, perhaps?
As documented in the Changelog this features was supposed to be implemented in #12 but I don't see any code handling HOME and END (only DEL in this PR).
Does HOME and END works for anyone?
For example, b
, e
, 0
, and $
are all supported motions, but cb
, ce
, c0
, c$
, db
, de
, d0
, and d$
don't work.
Pretty simple. If I type Ctrl+Z at a Readline() on Windows, the line I was working on disappears along with the prompt and no keyboard input has any effect anymore aside from Ctrl+C, which kills the program and barfs whatever I typed in after hitting Ctrl+Z to the command prompt.
Is there a timeline or ETA for Windows support?
This is not an issue with readline itself, but impacts uses of it via gopkg. See niemeyer/gopkg#9 for details.
Basically, gopkg only works correctly with single-package repositories. Because gopokg.in/chzyer/readline.v1
imports github.com/chzyer/readline/runes
, both repositories will be pulled in, but the latter be at HEAD on master.
I don't have a solution to this unfortunately, I just noticed it when pulling in readline via otto.
when i try to install readline package by go get
, there is an error print: unrecognized import path "golang.org/x/crypto/ssh/terminal"
Examples (|
is the cursor):
> asdfa|sdfasdf asdfasdf # press e
> asdfasdfasdf |asdfasdf # what happens
> asdfasdfasd|f asdfasdf # what should happen
> asdfasdfasd|f asdfasdf # press e
> asdfasdfasdf |asdfasdf # what happens
> asdfasdfasdf asdfasd|f # what should happen
Is there a plan for implementing yank? Not necessarily the whole kill ring, just a way of yanking back your previous kill.
See cockroachdb/cockroach#9607 for details.
I want to create a cli app which can print next page by press space key. Just like less or more command. But when i try to call ReadRune
from readline, the program stucked. Can you fix this program? Or Can you create more example about how to use readline?
here is my code
package main
import (
"strings"
"github.com/chzyer/readline"
"io"
"fmt"
)
func main() {
cfg := &readline.Config{
Prompt: " \033[31m$\033[0m ",
HistoryFile: "/tmp/readline.tmp",
InterruptPrompt: "\nInterrupt, Press Ctrl+D to exit",
EOFPrompt: "exit",
}
l, err := readline.NewEx(cfg)
if err != nil {
panic(err)
}
for {
line, err := l.Readline()
if err == io.EOF {
break
}
line = strings.TrimSpace(line)
// 退出指令
lineLower := strings.ToLower(line)
if lineLower == "exit" || lineLower == "quit" || lineLower == "bye" {
l.Stdout().Write([]byte("exit...\n"))
break;
}
handleLine(l, line)
}
}
func handleLine(l *readline.Instance, line string) {
p := 1
printPage(l.Stdout(), p)
fmt.Fprintln(l.Stdout(), "hello, this is readline demo page 1, press space to view next page, ESC to quit.")
for {
ru := l.Terminal.ReadRune()
if ru == 27 {
fmt.Fprintln(l.Stdout(), "ESC pressed quiting...")
break;
}else if ru == 32 {
fmt.Fprintln(l.Stdout(), "space pressed. print next page.")
p += 1
printPage(l.Stdout(), p)
}
}
}
func printPage(writer io.Writer, page int) {
fmt.Fprintln(writer, "this is page:%d", page)
}
If the suggested completions are long enough to take up more than one terminal line, pressing tab to move the highlight causes more lines to be printed. Here some example code:
package main
import "github.com/chzyer/readline"
var completer = readline.NewPrefixCompleter(
readline.PcItem("all_these_options"),
readline.PcItem("take_up_more_than"),
readline.PcItem("one_terminal_line"),
readline.PcItem("so_the_highlights"),
readline.PcItem("do_not_work_right"))
func main() {
rl, err := readline.NewEx(&readline.Config{
Prompt: "> ",
AutoComplete: completer,
})
if err != nil {
panic(err)
}
defer rl.Close()
for {
line, err := rl.Readline()
if err != nil {
break
}
println(line)
}
}
If I run this snippet and press Tab
five times, this is what I see:
It looks like only the current line is being redrawn, and since there are two lines drawn it keeps moving down each time. The re-draw process should redraw all the lines, not just the last.
With shorter option texts, this doesn't happen.
This definitely happens in a windows 7 command prompt, I haven't tried it out on any other terminals yet.
build example in windows, run: fatal error: all goroutines are asleep - deadlock!
OS: win7 64
Go: 1.5.2
in CockroachDB if a user enters "SELECT" ... it would be nice to be able to do Ctrl+R then "sel..." in lowercase and see the SELECT come back from history.
Currently the history search is case sensitive so this does not work.
Ideally the behavior would be configurable.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.