85 lines
2.8 KiB
Rust
85 lines
2.8 KiB
Rust
use std::{env, path::PathBuf};
|
|
|
|
use vamp::{session::EditorSession, tui};
|
|
|
|
const HELP: &str = "vamp — modal editor with isolated Ruby plugins
|
|
|
|
Usage: vamp [--config PATH | --no-config] [FILE]
|
|
|
|
Default keys (configurable with config.bind):
|
|
Normal: i/a insert, I/A insert at first nonblank/end, o/O new line
|
|
h/j/k/l move, 0/$ line ends, x delete, J join lines
|
|
u undo, U redo, : command
|
|
Insert: Esc returns to normal
|
|
Commands: :w [PATH], :q, :q!, :wq [PATH], :plugins, :PLUGIN [ARGS]
|
|
|
|
Ruby config: $XDG_CONFIG_HOME/vamp/config.rb or ~/.config/vamp/config.rb
|
|
Set VAMP_RUBY to choose the Ruby executable.";
|
|
|
|
struct Options {
|
|
file: Option<PathBuf>,
|
|
config: Option<PathBuf>,
|
|
}
|
|
|
|
fn options() -> Result<Option<Options>, String> {
|
|
let mut args = env::args_os().skip(1);
|
|
let mut file = None;
|
|
let mut config = None;
|
|
let mut config_selected = false;
|
|
let mut positional = false;
|
|
while let Some(arg) = args.next() {
|
|
if !positional && (arg == "--help" || arg == "-h") {
|
|
println!("{HELP}");
|
|
return Ok(None);
|
|
} else if !positional && arg == "--" {
|
|
positional = true;
|
|
} else if !positional && arg == "--config" {
|
|
if config_selected {
|
|
return Err("use only one of --config and --no-config".into());
|
|
}
|
|
config = Some(PathBuf::from(
|
|
args.next().ok_or("--config requires a path")?,
|
|
));
|
|
config_selected = true;
|
|
} else if !positional && arg == "--no-config" {
|
|
if config_selected {
|
|
return Err("use only one of --config and --no-config".into());
|
|
}
|
|
config_selected = true;
|
|
} else if !positional && arg.to_string_lossy().starts_with('-') {
|
|
return Err(format!("unknown option: {}", arg.to_string_lossy()));
|
|
} else if file.replace(PathBuf::from(arg)).is_some() {
|
|
return Err("only one file can be opened".into());
|
|
}
|
|
}
|
|
if !config_selected {
|
|
let home = env::var_os("XDG_CONFIG_HOME")
|
|
.map(PathBuf::from)
|
|
.or_else(|| env::var_os("HOME").map(|home| PathBuf::from(home).join(".config")));
|
|
config = home
|
|
.map(|home| home.join("vamp/config.rb"))
|
|
.filter(|path| path.exists());
|
|
}
|
|
Ok(Some(Options { file, config }))
|
|
}
|
|
|
|
fn run() -> Result<(), String> {
|
|
let Some(options) = options()? else {
|
|
return Ok(());
|
|
};
|
|
let mut session = EditorSession::open(
|
|
options.file,
|
|
tui::CAPABILITIES.iter().map(|s| (*s).to_owned()).collect(),
|
|
options.config.as_deref(),
|
|
)
|
|
.map_err(|error| format!("cannot open file: {error}"))?;
|
|
tui::run(&mut session).map_err(|error| format!("terminal error: {error}"))
|
|
}
|
|
|
|
fn main() {
|
|
if let Err(error) = run() {
|
|
eprintln!("vamp: {error}");
|
|
std::process::exit(1);
|
|
}
|
|
}
|