Rustyline

Yesterday, I talked about GNU Readline. Today, I wanted something similar in Rust. I found several crates on crates.io, but all seem to have been yanked in favor of rustyline. Rustyline seems really well done and very flexible. In particular, it can be configured with either Emacs or Vi keybindings.

  use rustyline::{Config, Editor, EditMode};

  fn main() {
      // let config = Config::builder().edit_mode(EditMode::Emacs).build();
      let config = Config::builder().edit_mode(EditMode::Vi).build();

      let mut rl: Editor<()> = Editor::with_config(config);

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

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

But I want to write programs that automatically configure themselves according to the user's environment. There are a number of ways to do that. Here are three:

  1. Korn shell checks the environment variables VISUAL, then EDITOR. If either of these variables contain an edit mode it knows, it uses it.

  2. GNU Readline checks the environment variable INPUTRC for the name of a file, then checks the file ~/.inputrc, then /etc/inputrc. If any of these files exist, it reads them for lots of configuration information including edit mode.

  3. BSD Editline checks the environment variable EDITRC for the name of a file, then checks the file ./.editrc, then ~/.editrc. If any of these files exist, it reads them for lots of configuration information including edit mode.

I decided to do all three! Introducing rustylinerc!

Using this crate, I can write that first program as

use rustyline::{Config, Editor};

fn main() {
    let edit_mode = rustylinerc::determine_edit_mode();
    dbg!(&edit_mode);

    let config = Config::builder().edit_mode(edit_mode).build();
    dbg!(&config);

    let mut rl: Editor<()> = Editor::with_config(config);

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

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

And now if the user displays a preference for vi or Emacs, they will get that preference.