2 releases
0.1.1 | Sep 5, 2024 |
---|---|
0.1.0 | Aug 16, 2024 |
#21 in #open-file
142 downloads per month
Used in 2 crates
(via slumber_tui)
16KB
199 lines
editor-command
Load a user's preferred file editing command from the VISUAL
or EDITOR
environment variables.
use editor_command::EditorCommand;
use std::process::Command;
std::env::set_var("VISUAL", "vim");
let mut command: Command = EditorCommand::edit_file("file.txt").unwrap();
command.spawn();
lib.rs
:
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
- Pass one or more paths to be opened by the editor
- Flexible builder pattern
Examples
The simplest usage looks like this:
use editor_command::EditorBuilder;
use std::process::Command;
std::env::set_var("VISUAL", "vim");
let command: Command = EditorBuilder::edit_file("file.txt").unwrap();
assert_eq!(command.get_program(), "vim");
Here's an example of using the builder pattern to provide both an override and a fallback command to [EditorBuilder]:
use editor_command::EditorBuilder;
use std::process::Command;
// In your app, this could be an optional field from a config object
let override_command = Some("code --wait");
let command: Command = 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.
.source(override_command)
.environment()
// If both VISUAL and EDITOR are undefined, we'll fall back to this
.source(Some("vi"))
.build()
.unwrap();
assert_eq!(format!("{command:?}"), "\"code\" \"--wait\"");
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
[EditorBuilder] 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 command: tokio::process::Command =
EditorBuilder::edit_file("file.yaml").unwrap().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 [shellish_parse] (with default [ParseOptions]). Refer to those docs for exact details on the syntax.
Lifetimes
[EditorBuilder] accepts a lifetime parameter, which is bound to the string
data it contains (both command strings and paths). This is to prevent
unnecessary cloning when building commands/paths from &str
s. If you need
the instance of [EditorBuilder] to be 'static
, e.g. so it can be returned
from a function, you can simply use EditorBuilder<'static>
. Internally,
all strings are stored as [Cow]s, so clones will be made as necessary.
use editor_command::EditorBuilder;
/// This is a contrived example of returning a command with owned data
fn get_editor_builder<'a>(command: &'a str) -> EditorBuilder<'static> {
// The lifetime bounds enforce the .to_owned() call
EditorBuilder::new().source(Some(command.to_owned()))
}
let command = get_editor_builder("vim").build().unwrap();
assert_eq!(command.get_program(), "vim");
Resources
For more information on the VISUAL
and EDITOR
environment variables,
check out this thread.
Dependencies
~36KB