Git Product home page Git Product logo

rustyline's Introduction

RustyLine

Build Status dependency status Docs

Readline implementation in Rust that is based on Antirez' Linenoise

Supported Platforms

  • Unix (tested on FreeBSD, Linux and macOS)
  • Windows
    • cmd.exe
    • Powershell

Note:

  • Powershell ISE is not supported, check issue #56
  • Mintty (Cygwin/MinGW) is not supported
  • Highlighting / Colors are not supported on Windows < Windows 10 except with ConEmu and ColorMode::Forced.

Example

use rustyline::error::ReadlineError;
use rustyline::{DefaultEditor, Result};

fn main() -> Result<()> {
    // `()` can be used when no completer is required
    let mut rl = DefaultEditor::new()?;
    #[cfg(feature = "with-file-history")]
    if rl.load_history("history.txt").is_err() {
        println!("No previous history.");
    }
    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(line.as_str());
                println!("Line: {}", line);
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
    #[cfg(feature = "with-file-history")]
    rl.save_history("history.txt");
    Ok(())
}

crates.io

You can use this package in your project by adding the following to your Cargo.toml:

[dependencies]
rustyline = "14.0.0"

Features

  • Unicode (UTF-8) (linenoise supports only ASCII)
  • Word completion (linenoise supports only line completion)
  • Filename completion
  • History search (Searching for Commands in the History)
  • Kill ring (Killing Commands)
  • Multi line support (line wrapping)
  • Word commands
  • Hints

Actions

For all modes:

Keystroke Action
Home Move cursor to the beginning of line
End Move cursor to end of line
Left Move cursor one character left
Right Move cursor one character right
Ctrl-C Interrupt/Cancel edition
Ctrl-D, Del (if line is not empty) Delete character under cursor
Ctrl-D (if line is empty) End of File
Ctrl-J, Ctrl-M, Enter Finish the line entry
Ctrl-R Reverse Search history (Ctrl-S forward, Ctrl-G cancel)
Ctrl-T Transpose previous character with current character
Ctrl-U Delete from start of line to cursor
Ctrl-V Insert any special character without performing its associated action (#65)
Ctrl-W Delete word leading up to cursor (using white space as a word boundary)
Ctrl-Y Paste from Yank buffer
Ctrl-Z Suspend (Unix only)
Ctrl-_ Undo

Emacs mode (default mode)

Keystroke Action
Ctrl-A, Home Move cursor to the beginning of line
Ctrl-B, Left Move cursor one character left
Ctrl-E, End Move cursor to end of line
Ctrl-F, Right Move cursor one character right
Ctrl-H, Backspace Delete character before cursor
Ctrl-I, Tab Next completion
Ctrl-K Delete from cursor to end of line
Ctrl-L Clear screen
Ctrl-N, Down Next match from history
Ctrl-P, Up Previous match from history
Ctrl-X Ctrl-U Undo
Ctrl-Y Paste from Yank buffer (Meta-Y to paste next yank instead)
Meta-< Move to first entry in history
Meta-> Move to last entry in history
Meta-B, Alt-Left Move cursor to previous word
Meta-C Capitalize the current word
Meta-D Delete forwards one word
Meta-F, Alt-Right Move cursor to next word
Meta-L Lower-case the next word
Meta-T Transpose words
Meta-U Upper-case the next word
Meta-Y See Ctrl-Y
Meta-Backspace Kill from the start of the current word, or, if between words, to the start of the previous word
Meta-0, 1, ..., - Specify the digit to the argument. starts a negative argument.

Readline Emacs Editing Mode Cheat Sheet

vi command mode

Keystroke Action
$, End Move cursor to end of line
. Redo the last text modification
; Redo the last character finding command
, Redo the last character finding command in opposite direction
0, Home Move cursor to the beginning of line
^ Move to the first non-blank character of line
a Insert after cursor
A Insert at the end of line
b Move one word or token left
B Move one non-blank word left
c Change text of a movement command
C Change text to the end of line (equivalent to c$)
d Delete text of a movement command
D, Ctrl-K Delete to the end of the line
e Move to the end of the current word
E Move to the end of the current non-blank word
f Move right to the next occurrence of char
F Move left to the previous occurrence of char
h, Ctrl-H, Backspace Move one character left
l, Space Move one character right
Ctrl-L Clear screen
i Insert before cursor
I Insert at the beginning of line
+, j, Ctrl-N Move forward one command in history
-, k, Ctrl-P Move backward one command in history
p Insert the yanked text at the cursor (paste)
P Insert the yanked text before the cursor
r Replaces a single character under the cursor (without leaving command mode)
s Delete a single character under the cursor and enter input mode
S Change current line (equivalent to 0c$)
t Move right to the next occurrence of char, then one char backward
T Move left to the previous occurrence of char, then one char forward
u Undo
w Move one word or token right
W Move one non-blank word right
x Delete a single character under the cursor
X Delete a character before the cursor
y Yank a movement into buffer (copy)

vi insert mode

Keystroke Action
Ctrl-H, Backspace Delete character before cursor
Ctrl-I, Tab Next completion
Esc Switch to command mode

Readline vi Editing Mode Cheat Sheet

Terminal codes (ANSI/VT100)

Wine

$ cargo run --example example --target 'x86_64-pc-windows-gnu'
...
Error: Io(Error { repr: Os { code: 6, message: "Invalid handle." } })
$ wineconsole --backend=curses target/x86_64-pc-windows-gnu/debug/examples/example.exe
...

Terminal checks

$ # current settings of all terminal attributes:
$ stty -a
$ # key bindings:
$ bind -p
$ # print out a terminfo description:
$ infocmp

Similar projects

Library Lang OS Term Unicode History Completion Keymap Kill Ring Undo Colors Hint/Auto suggest
go-prompt Go Ux/win ANSI Yes Yes any Emacs/prog No No Yes Yes
Haskeline Haskell Ux/Win Any Yes Yes any Emacs/vi/conf Yes Yes ? ?
isocline C Ux/Win ANSI Yes Yes any Emacs No Yes Yes Yes
linefeed Rust Ux/Win Any Yes any Emacs/conf Yes No ? No
linenoise C Ux ANSI No Yes only line Emacs No No Ux Yes
Liner Rust Ux ANSI No inc search only word Emacs/vi/prog No Yes Ux History based
prompt_toolkit Python Ux/Win ANSI Yes Yes any Emacs/vi/conf Yes Yes Ux/Win Yes
reedline Rust Ux/Win ANSI Yes Yes any Emacs/vi/bind No Yes Ux/Win Yes
replxx C/C++ Ux/Win ANSI Yes Yes only line Emacs Yes No Ux/Win Yes
Rustyline Rust Ux/Win ANSI Yes Yes any Emacs/vi/bind Yes Yes Ux/Win 10+ Yes
termwiz Rust Ux/Win Any ? Yes any Emacs No No Ux/Win No

Multi line support

This is a very simple feature that simply causes lines that are longer than the current terminal width to be displayed on the next visual line instead of horizontally scrolling as more characters are typed. Currently, this feature is always enabled and there is no configuration option to disable it.

This feature does not allow the end user to hit a special key sequence and enter a mode where hitting the return key will cause a literal newline to be added to the input buffer.

The way to achieve multi-line editing is to implement the Validator trait.

rustyline's People

Contributors

basile-henry avatar birkenfeld avatar dependabot[bot] avatar driftluo avatar eminence avatar figsoda avatar flakebi avatar gwenn avatar hayd avatar homburg avatar kkawakam avatar kpp avatar leodog896 avatar lopopolo avatar marcbowes avatar miraclx avatar radicalzephyr avatar rgardner avatar rtzoeller avatar ryan1729 avatar saghm avatar sigmasd avatar striezel avatar sujiacong avatar tage64 avatar tailhook avatar thomcc avatar timclicks avatar totem3 avatar utkarshgupta137 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rustyline's Issues

Add an Iterator

We could do:

for cmd in editor {
    match ...
}

It would end on EOF or

Multi-line prompt appears to function incorrectly

I'm attempting to create a multi-line prompt by using a newline character in the argument to Editor::readline, e.g. readline("foo\n> ")

I expected this to produce

foo
>

but it is instead producing

foo
   >

Is this a problem with rustyline, or am I doing something incorrectly?

Clean up error handling

  • readline method should return custom error type that will be created when #1 is fixed
  • compose error handling into a easily readable format

Reference

Do a release

Last one was in August, there are some neat unreleased features!

Keybindings not working on rxvt terminal

Hi everyone,

I just built an example project with rustyline 1.0.0 and code as in the documentation:

extern crate rustyline;

fn main() {
    let mut rl = rustyline::Editor::<()>::new();

    let readline = rl.readline(">> ");

    match readline {
        Ok(line) => println!("Line: {:?}",line),
        Err(_)   => println!("No input"),
    }
}

I am running this example in a unicode-rxvt terminal ($TERM=rxvt), and the usual keybindings M-b, C-a and even Enter only generate their literal codes:

% cargo run
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/readline`
>> españa^[b^A^M
>> españa
Line: "españa"

I can submit the line with C-j though.

I am running rxvt-unicode-9.22 and rust-1.13.0.

Any help will be greatly appreciated. Thanks!

bind history-search-backward?

GNU readline support bind a keypress via INPUTRC like this:

bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

It would be great if rustyline support this.

Another option (for this specific function), rustyline can let users to customize the some KeyPress event, like this one, and provides low level APIs to manipulate prompted commands via history entries etc.

Thanks for this awesome project!

Add a way to enable command repeat

Like in gdb. Imagine you enter step. If after that you press enter with an empty command line, it will repeat step. It's really handy for debuggers for example. It would not be used in all cli interfaces, though.

Add a way to retrieve the current completer

I was messing with rustyline, it's completion API and trying do implement multiline editing at the same time, but then I encountered a problem: I need to have the input from the previous lines to have a proper context for my completion system.

Sorry if it's unclear, here's a quick example:

input> if [ x -eq 1 ];
  ...> th<tab>

In this case, my completer need to know that there's an if before to be able to complete the then.

My idea was to store the previous lines as context inside the Completer, but currently there is no way of retrieving the completer in use.

A see two ways of doing this: either make the completer field public or add the get_completer and get_completer_mut methods.

For now, I can do it by replacing the current completer with the added context, but I think that would be better by mutating the completer directly.

If there's a better way, please tell me, I'm open to discussion ;-)

Update README to 0.2.0

Great library thanks. You may want to update the README.md to 0.2.0:

[dependencies]
rustyline = "0.2.0"

Optimize cursor movement

If possible, avoid a full refresh of the line but move only the cursor when user press Ctrl-A, Ctrl-E, ...

0.2.0 broken on latest nightly

Could you push another release to crates.io? On the latest Rust nightly, 0.2.0 fails to build, but the latest revision seems to compile fine.

Thanks a bunch!

Incorrect prompt width when control chars are used

extern crate unicode_width;

fn main () {
    let s = "\x1b[1;32m>>\x1b[0m ";
    println!("{}", unicode_width::UnicodeWidthStr::width(s)); // 12
    let s = ">> ";
    println!("{}", unicode_width::UnicodeWidthStr::width(s)); // should be 3
}

Compile against Rust Stable

Currently we take advantage of some non-stabilized rust APIs but eventually we will want to be able to compile against Rust stable. The below links are tracking issues that need to be closed out before we can compile against rust stable.

Update June 6 2016: #38 introduced workaround changes that allowed rustyline to be compiled against rust stable (1.9.0). These changes should eventually replaced by Read::chars and encode_utf8 after they become stabilized in the standard library.

TO-DO

multiline support

The README mentions multiline support, but I can't find a way to enable it. Is this feature implemented?

Powershell ISE

Error: Io(Error { repr: Os { code: 6, message: "The handle is invalid." } })

Prompts with linebreaks clear too many lines

For example, running the below code results in SUCCESS never being printed.

extern crate rustyline;

use rustyline::Editor;
use rustyline::error;

fn main() {
    let mut editor = Editor::<()>::new();
    loop {
        match editor.readline("1\n>> ") {
            Ok(_) => println!("SUCCESS"),
            Err(error::ReadlineError::Eof) => break,
            Err(_) => continue,
        }
    }
}

actual:

1
>> foo
1
>>

expected:

1
>> foo
SUCCESS
1
>>

vi mode

Have you consider implement vi mode ?

however great project thanks.

Add support for matching delimiter blinking

I would like rustyline to blink the matching delimiter once I type it. Is there any reason you see why this shouldn't work in the library? Otherwise, I can put together a pull request.

I would think to start with () but I don't see an immediate reason to not add {} []. Perhaps it should be configurable for the user?

Add Simple Test Case

Currently there are no test cases for rustyline.

As an initial test case, a UTF-8 string should be written to STDIN file descriptor and see if the correct string is returned by rustyline.

Editor taking a trait object reference to Editor is awkward

I saw that windows support is (partially) available for rustyline now so I was considering removing my linenoise-rust dependency and use this instead as the completion support was to primitive for my needs.

Looking at the API however I am going to run into problems with Completer being a borrowed trait object as the current implementation mandates a borrow and prevents Editor from being Sync. This could be solved by instead parameterising Editor by the Completer.

I'd be happy to implement this and submit a PR if you think it is a good idea.

Suspend (Ctrl-Z) and Quit (Ctrl-\) not handled

Since rustyline removes the ISIG flag from the terminal, pressing Ctrl-Z or Ctrl-\ will insert a character instead of suspending/quitting the process. Especially suspend is quite essential for any CLI program.

Please consider using the default signal handling, or implementing some kind of handler for Ctrl-Z and Ctrl-\ that generates the signals.

Build with --target=x86_64-unknown-linux-musl fails

cargo build --target=x86_64-unknown-linux-musl fails with:

$ cargo build --target=x86_64-unknown-linux-musl
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling rustyline v0.2.3 (file:///home/bjb/code/rustyline)
src/lib.rs:247:48: 247:58 error: mismatched types [E0308]
src/lib.rs:247         match libc::ioctl(libc::STDOUT_FILENO, TIOCGWINSZ, &mut size) {
                                                              ^~~~~~~~~~
src/lib.rs:247:48: 247:58 help: run `rustc --explain E0308` to see a detailed explanation
src/lib.rs:247:48: 247:58 note: expected type `i32`
src/lib.rs:247:48: 247:58 note:    found type `u64`
error: aborting due to previous error
error: Could not compile `rustyline`.

I have a simple fix, will do a pull request shortly.

Can't add history line with preceding spaces

Entries with whitespace at the beginning of the string are excluded from the history object by history.rs:34. Perhaps the line could be replaced with if line.trim().is_empty() { so that only lines entirely made of whitespace are excluded?

Completing paths with spaces on windows

Completing paths which include spaces does not work currently, as the space is part of the DEFAULT_BREAK_CHARS array and so extract_word does not extract the whole path.

A workaround is to remove it from the list and making sure that you only pass the path without any prefix to the FilenameCompleter.

A proper fix would probably be doing what windows does: Adding quotes around the path if it contains a space.

Moving the cursor wipes out next lines

The library calls refresh in the cursor movement functions causing future lines to be wiped out. This is causing issues for a game I embedded the line editor in, because the bottom portion of the screen gets wiped if the user moves the cursor while entering a command.

Shrink repository

There seems to be something wrong:

$ git clone https://github.com/kkawakam/rustyline
Cloning into 'kkawakam-rustyline'...
remote: Counting objects: 125450, done.
remote: Total 125450 (delta 0), reused 0 (delta 0), pack-reused 125450
Receiving objects: 100% (125450/125450), 39.23 MiB | 4.30 MiB/s, done.
Resolving deltas: 100% (120354/120354), done.
$ cd rustyline
$ du -h -d 1
 43M	./.git
4.0K	./examples
144K	./src
 43M	.

It seems that some html/javascript files haven been added/commited.
Using the script described here

All sizes are in kB. The pack column is the size of the object, compressed, inside the pack file.
-e    size  pack                                      SHA                                              location
1158  102   ac022cdad0792d6b5a92443591a4a13447dd2f61  src/libc/lib.rs.html
889   156   18fb8e7d017939a7866d770f2f128dcf06f982cb  search-index.js
561   25    05cc9269d38aa0db6623f9f10e622ec3afad2870  nix/sys/ioctl/libc/index.html
364   57    67285d0679fe8741691acfff97c6223f7baadd64  search-index.js
337   10    35865ffd48354a252b1b9623af51e7b912934f4a  bitflags/__core/prelude/v1/trait.PartialEq.html
268   25    10323005747653adee46df009b7abf73c9d728ef  bitflags/__core/prelude/v1/struct.Vec.html
261   13    94a89fd9eac872d1468b183ad64168d6df682e7e  nix/sys/ioctl/libc/index.html
250   21    03df2507089f9edf622152bab56a4355d54d143d  bitflags/__core/prelude/v1/trait.Iterator.html
235   29    e44dca71087bbbaeca108a13aa1160a1fd80baf2  bitflags/__core/prelude/v1/struct.String.html
233   25    3216db156c7d32d82655051fce4b1039c79a029e  src/nix/errno.rs.html

Would you mind trying to cleanup this stuff ?
Thanks.

Support IME?

I like this great project, but it seemed IME is not supported for now (at least in Windows).

Debugging output for unknown escape sequences

The writeln() in escape_sequence should probably be removed in released versions.

Thanks for your work on rustyline btw! Apart from the other issue I raised it works beautifully for me as a simple REPL line editor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.