diff --git a/crates/aiken/src/cmd/completion/mod.rs b/crates/aiken/src/cmd/completion/mod.rs index 8c13de58..56ec04be 100644 --- a/crates/aiken/src/cmd/completion/mod.rs +++ b/crates/aiken/src/cmd/completion/mod.rs @@ -1,4 +1,4 @@ -pub mod completion; +pub mod shell; use clap::Subcommand; use clap_complete::Shell; @@ -6,15 +6,15 @@ use clap_complete::Shell; /// Commands for working with transactions #[derive(Subcommand)] pub enum Cmd { - Bash(completion::Args), - Zsh(completion::Args), - Fish(completion::Args), + Bash(shell::Args), + Zsh(shell::Args), + Fish(shell::Args), } pub fn exec(cmd: Cmd) -> miette::Result<()> { match cmd { - Cmd::Bash(args) => completion::exec(args, Shell::Bash), - Cmd::Zsh(args) => completion::exec(args, Shell::Zsh), - Cmd::Fish(args) => completion::exec(args, Shell::Fish), + Cmd::Bash(args) => shell::exec(args, Shell::Bash), + Cmd::Zsh(args) => shell::exec(args, Shell::Zsh), + Cmd::Fish(args) => shell::exec(args, Shell::Fish), } } diff --git a/crates/aiken/src/cmd/completion/completion.rs b/crates/aiken/src/cmd/completion/shell.rs similarity index 97% rename from crates/aiken/src/cmd/completion/completion.rs rename to crates/aiken/src/cmd/completion/shell.rs index 03fd21c5..df405bb5 100644 --- a/crates/aiken/src/cmd/completion/completion.rs +++ b/crates/aiken/src/cmd/completion/shell.rs @@ -6,42 +6,52 @@ use clap_complete::{generate, Shell}; use std::fs::OpenOptions; /// Generates shell completion scripts - #[derive(clap::Args)] pub struct Args { + /// Install the completion scripts #[arg(short, long, default_value_t = false)] install: bool, } fn generate_wrapper(shell: Shell, buf: &mut dyn Write) { let cli = Command::new("aiken").disable_version_flag(true); + let mut main = MainCmd::augment_subcommands(cli); + generate(shell, &mut main, "aiken".to_string(), buf); } fn zsh() -> miette::Result<()> { //if oh-my-zsh let prefix_dir = "zsh-completions/site-functions"; + let home = std::env::var("HOME").expect("Environment variable 'HOME' not set but needed."); + let xdg_dirs = xdg::BaseDirectories::with_prefix(prefix_dir) .expect("Could not find completion directory {prefix_dir} in xdg directories."); + let data_home = xdg_dirs.get_data_home(); + let mut completion_file: File; let oh_my_zsh_path = Path::new(&home).join(".oh-my-zsh"); if oh_my_zsh_path.exists() { let completions_path = oh_my_zsh_path.join("completions"); + let aiken_completion_path = completions_path.join("_aiken"); + if !completions_path.exists() { std::fs::create_dir(completions_path.as_path()).expect( "Cannot create directory: {completions_path.into_os_string().into_string()}", ); } + completion_file = File::create(aiken_completion_path) .expect("Cannot open file at: {aiken_completion_path.into_os_string().into_string()}"); generate_wrapper(Shell::Zsh, &mut completion_file); + return Ok(()); } @@ -49,15 +59,19 @@ fn zsh() -> miette::Result<()> { let completion_path = xdg_dirs .place_data_file("_aiken") .expect("cannot create directory"); + completion_file = File::create(completion_path) .expect("Cannot open file at: {completion_path.into_os_string().into_string()}"); + generate_wrapper(Shell::Zsh, &mut completion_file); + return Ok(()); } let completion_path = xdg_dirs .place_data_file("_aiken") .expect("cannot create directory"); + completion_file = File::create(completion_path) .expect("Cannot open file at: {completion_path.into_os_string().into_string()}"); @@ -66,38 +80,51 @@ fn zsh() -> miette::Result<()> { .append(true) .open(format!("{}/.zshrc", home)) .expect(".zshrc file not found"); + if let Some(home) = data_home.to_str() { let fpath: String = format!(r#"fpath=($fpath "{}")"#, home); + if let Err(e) = writeln!(zshrc, "{}", fpath) { eprintln!("Couldn't write to file: {}", e); } } generate_wrapper(Shell::Zsh, &mut completion_file); + Ok(()) } fn fish() -> miette::Result<()> { // NOTE: Installing completion on ~/.confi/fish/completions let prefix_dir = "fish/completions"; + let xdg_dirs = xdg::BaseDirectories::with_prefix(prefix_dir) .expect("Could not find completion directory {prefix_dir} in xdg directories."); + let completion_path = xdg_dirs .place_config_file("aiken.fish") .expect("Cannot create path"); + let mut completion_file = File::create(completion_path) .expect("Cannot open file at: {completion_path.into_os_string().into_string()}"); + generate_wrapper(Shell::Fish, &mut completion_file); + Ok(()) } fn bash() -> miette::Result<()> { let prefix_dir = "bash-completion/completions"; + let aiken_bash = "aiken.completion.bash"; + let xdg_dirs = xdg::BaseDirectories::with_prefix(prefix_dir) .expect("Could not find completion directory {prefix_dir} in xdg directories."); + let home = std::env::var("HOME").expect("Environment variable 'HOME' not set but needed."); + let config_home = xdg_dirs.get_config_home(); + let completion_path = xdg_dirs .place_config_file(aiken_bash) .expect("Cannot create completion file {aiken_bash} under xdg directories"); @@ -107,15 +134,20 @@ fn bash() -> miette::Result<()> { .append(true) .open(format!("{}/.bashrc", home)) .expect(".bashrc file not found in {home} directory"); + if let Some(config) = config_home.to_str() { let path: String = format!("source {config}"); + if let Err(e) = writeln!(bashrc, "{}", path) { eprintln!("Couldn't write to file: {}", e); } } + let mut completion_file = File::create(completion_path) .expect("Cannot open file at: {completion_path.into_os_string().into_string()}"); + generate_wrapper(Shell::Bash, &mut completion_file); + Ok(()) } @@ -130,7 +162,7 @@ fn completions_to_file(shell: Shell) -> miette::Result<()> { Shell::Zsh => { zsh()?; } - _ => eprintln!("Shell not supported"), + s => eprintln!("{s} not supported"), } Ok(()) @@ -142,5 +174,6 @@ pub fn exec(cmd_args: Args, shell: Shell) -> miette::Result<()> { } else { generate_wrapper(shell, &mut std::io::stdout()); } + Ok(()) }