Crate editor_command

Crate editor_command 

Source
Expand description

Get an executable Command to open a particular file in the user’s configured editor.

§Features

  • Load editor command from the VISUAL or EDITOR environment variables
  • Specify high-priority override and low-priority default commands to use
  • Open files to a particular line/column
  • Flexible builder pattern

§Examples

editor-command uses a two-stage abstraction:

§Simplest Usage

use editor_command::Editor;
use std::process::Command;

std::env::set_var("VISUAL", "vim");
// Building an editor is fallible because the user's configured command may
// be invalid (e.g. it could have unclosed quotes)
let editor = Editor::new().unwrap();
// Once we have an editor, building a Command is infallible
let command: Command = editor.open("file.txt");

assert_eq!(command.get_program(), "vim");
assert_eq!(command.get_args().collect::<Vec<_>>(), &["file.txt"]);

// You can spawn the editor with:
// command.status().unwrap();

§Open to Line/Column

You can open a file to particular line/column using Editor::open_at:

use editor_command::Editor;
use std::process::Command;

std::env::set_var("VISUAL", "vim");
let editor = Editor::new().unwrap();
let command: Command = editor.open_at("file.txt", 10, 5);

assert_eq!(command.get_program(), "vim");
assert_eq!(
    command.get_args().collect::<Vec<_>>(),
    &["file.txt", "+call cursor(10, 5)"],
);

See Editor::open_at for info on how it supports line/column for various editors, and how to support it for arbitrary user-provided commands.

§Overrides and Fallbacks

Here’s an example of using EditorBuilder to provide both an override and a fallback command:

use editor_command::EditorBuilder;
use std::process::Command;

std::env::set_var("VISUAL", "vim"); // This gets overridden
let editor = EditorBuilder::new()
    // In this case, the override is always populated so it will always win.
    // In reality it would be an optional user-provided field.
    .string(Some("code --wait"))
    .environment()
    // If both VISUAL and EDITOR are undefined, we'll fall back to this
    .string(Some("vi"))
    .build()
    .unwrap();
let command = editor.open("file.txt");

assert_eq!(command.get_program(), "code");
assert_eq!(command.get_args().collect::<Vec<_>>(), &["--wait", "file.txt"]);

This pattern is useful for apps that have a way to configure an app-specific editor. For example, git has the core.editor config field.

§Tokio

Editor returns a std Command, which will execute synchronously. If you want to run your editor subprocess asynchronously via tokio, use the From<std::process::Command> impl on tokio::process::Command. For example:

let editor = Editor::new().unwrap();
let command: tokio::process::Command = editor.open("file.yaml").into();

§Syntax

The syntax of the command is meant to resemble command syntax for common shells. The first word is the program name, and subsequent tokens (separated by spaces) are arguments to that program. Single and double quotes can be used to join multiple tokens together into a single argument.

Command parsing is handled by the crate shell-words. Refer to those docs for exact details on the syntax.

§Resources

For more information on the VISUAL and EDITOR environment variables, check out this thread.

Structs§

Editor
An editor is a builder for Commands. An Editor instance represent’s a user’s desired editor, and can be used repeatedly to open files.
EditorBuilder
A builder for customizing an Editor. In simple cases you can just use Editor::new and don’t have to interact with this struct. See crate-level documentation for more details and examples.

Enums§

EditorBuilderError
Any error that can occur while loading the editor command.