summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-01-16 14:45:14 -0500
committerFreya Murphy <freya@freyacat.org>2025-01-16 14:45:14 -0500
commit60985236c7070425c28aa0c5ce675306d06ab123 (patch)
tree7448aef5dadf19d4504151ebc370f9e20757ef10 /src/main.rs
downloadiris-60985236c7070425c28aa0c5ce675306d06ab123.tar.gz
iris-60985236c7070425c28aa0c5ce675306d06ab123.tar.bz2
iris-60985236c7070425c28aa0c5ce675306d06ab123.zip
initialHEADmain
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..86cd716
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,193 @@
+//! # Iris
+//! A locking plugin manager for vim
+
+use iris::{Config, Result};
+use log::info;
+use std::{env, process::exit};
+
+const USAGE: &str = "\
+Usage: iris [OPTION]... COMMAND [FILE}";
+
+const HELP: &str = "\
+A locking plugin manager for vim
+
+Commands:
+ switch checkout plugins using their current refs and generate autoload
+ file
+ lock update plugin refs to point to the latest commit
+
+Options:
+ -v, --verbose enable verbose output
+ -q, --quiet disable output
+ -h, --help print the help message
+ -V, --version print the program version
+";
+
+/// print the program version
+fn version() -> ! {
+ println!("iris {}", env!("CARGO_PKG_VERSION"));
+ exit(0);
+}
+
+/// print the program's usage
+fn usage() -> ! {
+ eprintln!("{USAGE}");
+ exit(1);
+}
+
+/// print the program's help message
+fn help() -> ! {
+ println!("{USAGE}\n{HELP}");
+ exit(0);
+}
+
+struct Options {
+ /// the command to run
+ command: String,
+ /// the file to load instead of defaults
+ file: Option<String>,
+ /// print verbose output
+ verbose: bool,
+ /// silence output
+ quiet: bool,
+}
+
+// parse options
+fn opts() -> Options {
+ let mut args = env::args().into_iter().peekable();
+ let mut quiet = false;
+ let mut verbose = false;
+
+ // skip program name
+ _ = args.next();
+
+ // options
+ while let Some(arg) = args.peek() {
+ // arg is not an option
+ if !arg.starts_with("-") {
+ break;
+ };
+ // grab next
+ let arg = args.next().expect("no arg?!");
+
+ match arg.as_str() {
+ // stop parsing options
+ "--" => break,
+ // quiet
+ "-q" | "--quiet" => {
+ quiet = true;
+ }
+ // verbose
+ "-v" | "--verbose" => {
+ verbose = true;
+ }
+ // version
+ "-V" | "--version" => version(),
+ // help
+ "-h" | "--help" => help(),
+ // invalid
+ _ => {
+ eprintln!("invalid options: '{arg}'");
+ exit(1);
+ }
+ };
+ }
+
+ // command
+ let Some(command) = args.next() else {
+ usage();
+ };
+
+ // file
+ let file = args.next();
+
+ // force end of arguments
+ if args.next().is_some() {
+ usage();
+ };
+
+ Options {
+ command,
+ file,
+ quiet,
+ verbose,
+ }
+}
+
+fn log(opts: &Options) {
+ if !opts.quiet {
+ let level = if opts.verbose {
+ log::LevelFilter::Trace
+ } else {
+ log::LevelFilter::Info
+ };
+
+ env_logger::Builder::from_default_env()
+ .filter_level(level)
+ .format_timestamp(None)
+ .format_module_path(false)
+ .format_source_path(false)
+ .init();
+ }
+}
+
+fn switch(opts: &Options) -> Result<()> {
+ let cfg = match &opts.file {
+ Some(path) => Config::read_from_file(path),
+ None => Config::read_from_lock_file()
+ .or_else(|_| Config::read_from_plugin_file()),
+ }?;
+
+ for plugin in &cfg.plugins {
+ plugin.switch()?;
+ info!("switched {}", plugin.id);
+ }
+
+ cfg.write_autoload_file()?;
+
+ Ok(())
+}
+
+fn lock(opts: &Options) -> Result<()> {
+ let mut cfg = match &opts.file {
+ Some(path) => Config::read_from_file(path),
+ None => Config::read_from_plugin_file(),
+ }?;
+
+ for plugin in &mut cfg.plugins {
+ plugin.lock()?;
+ info!("locked {}", plugin.id);
+ }
+
+ // save lock file
+ cfg.write_to_lock_file()?;
+
+ Ok(())
+}
+
+fn inner() -> Result<()> {
+ // parse opts
+ let opts = opts();
+
+ // initalize logger (if not quiet)
+ log(&opts);
+
+ // handle command
+ match opts.command.as_str() {
+ "switch" => switch(&opts)?,
+ "lock" => lock(&opts)?,
+ cmd => {
+ eprintln!("unknown command: '{cmd}'");
+ exit(1);
+ }
+ };
+
+ Ok(())
+}
+
+fn main() {
+ if let Err(err) = inner() {
+ log::error!("{err}");
+ exit(1);
+ }
+}