Skip to content

Commit

Permalink
feat(cli): add an "agama config edit" command
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Jun 20, 2024
1 parent 2a1b453 commit 6d40cdc
Showing 1 changed file with 62 additions and 1 deletion.
63 changes: 62 additions & 1 deletion rust/agama-cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
use std::io::{self, Read};
use std::{
io::{self, Read},
path::PathBuf,
process::Command,
};

use crate::show_progress;
use agama_lib::{
auth::AuthToken, connection, install_settings::InstallSettings, Store as SettingsStore,
};
use anyhow::anyhow;
use clap::Subcommand;
use std::io::Write;
use tempfile::Builder;

const DEFAULT_EDITOR: &str = "/usr/bin/vim";

#[derive(Subcommand, Debug)]
pub enum ConfigCommands {
Expand All @@ -17,6 +27,13 @@ pub enum ConfigCommands {

/// Reads and loads a profile from the standard input.
Load,

/// Edits and updates Agama's configuration on an external editor.
Edit {
/// Editor command (including additional arguments if needed)
#[arg(short, long)]
editor: Option<String>,
},
}

pub async fn run(subcommand: ConfigCommands) -> anyhow::Result<()> {
Expand All @@ -42,5 +59,49 @@ pub async fn run(subcommand: ConfigCommands) -> anyhow::Result<()> {
let result: InstallSettings = serde_json::from_str(&contents)?;
Ok(store.store(&result).await?)
}
ConfigCommands::Edit { editor } => {
let model = store.load().await?;
let editor = editor
.or_else(|| std::env::var("EDITOR").ok())
.unwrap_or(DEFAULT_EDITOR.to_string());
let result = edit(&model, &editor)?;
tokio::spawn(async move {
show_progress().await.unwrap();
});
store.store(&result).await?;
Ok(())
}
}
}

/// Edit command.
///
/// Loads the configuration on an editor. If the editor returns a successful error code, it updates
/// the configuration.
///
/// * `model`: current installation settings.
fn edit(model: &InstallSettings, editor: &str) -> anyhow::Result<InstallSettings> {
let content = serde_json::to_string_pretty(model)?;
let mut file = Builder::new().suffix(".json").tempfile()?;
let path = PathBuf::from(file.path());
write!(file, "{}", content)?;

let mut command = editor_command(&editor);
let status = command.arg(path.as_os_str()).status()?;
if status.success() {
return Ok(InstallSettings::from_file(path)?);
}

Err(anyhow!(
"Ignoring the changes becase the editor was closed with an error code."
))
}

fn editor_command(command: &str) -> Command {
let mut parts = command.split_whitespace();
let program = parts.next().unwrap_or(DEFAULT_EDITOR);

let mut command = Command::new(program);
command.args(parts.collect::<Vec<&str>>());
command
}

0 comments on commit 6d40cdc

Please sign in to comment.