Expand description
Get an executable Command to open a particular file in the user’s configured editor.
§Features
- Load editor command from the
VISUAL
orEDITOR
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:
- Build an Editor (optionally using an EditorBuilder), which represents a user’s desired editor
- Use Editor::open to build a Command that will open a particular file
§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. - Editor
Builder - 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§
- Editor
Builder Error - Any error that can occur while loading the editor command.