codeberg-cli 0.5.5

CLI Tool for codeberg similar to gh and glab
Documentation
use config::ValueKind;
use itertools::Itertools;
use miette::IntoDiagnostic;

use crate::{
    actions::GlobalArgs,
    render::json::JsonToStdout,
    types::{config::BergConfig, output::OutputMode},
};

use clap::Parser;

/// Display short overview of which config values are used
#[derive(Parser, Debug)]
pub struct ConfigInfoArgs {}

impl ConfigInfoArgs {
    pub fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
        // use the raw config since it contains the origin of field
        let raw_config = BergConfig::raw()?;
        let config = BergConfig::new()?;

        match global_args.output_mode {
            OutputMode::Pretty => present_config_info(config, raw_config)?,
            OutputMode::Json => config.print_json()?,
        };

        Ok(())
    }
}

fn present_config_info(config: BergConfig, raw_config: config::Config) -> miette::Result<()> {
    let table = config
        .make_table()
        .set_header(vec!["Field", "Source", "Value"])
        .add_rows(
            raw_config
                .cache
                .into_table()
                .into_diagnostic()?
                .into_iter()
                .sorted_by_key(|(k, _)| k.to_string())
                .map(|(k, v)| {
                    // this is a bit difficult since the lib doesn't make the field public
                    let origin = {
                        let dbg = format!("{v:?}");
                        dbg.find("origin: ").map_or_else(
                            || String::from("Default"),
                            |idx| {
                                let origin = dbg
                                    .chars()
                                    .skip(idx)
                                    .skip("origin: ".len())
                                    .take_while(|&c| c != ',')
                                    .collect::<String>();

                                match origin.as_str() {
                                    "None" => String::from("Default"),
                                    s if s.starts_with("Some(") => {
                                        s.replace("Some(", "").replace(')', "")
                                    }
                                    s => s.to_string(),
                                }
                            },
                        )
                    };
                    let v = {
                        let is_string = matches!(v.kind, ValueKind::String(_));
                        if is_string {
                            format!("{:?}", v.to_string())
                        } else {
                            v.to_string()
                        }
                    };
                    vec![k, origin, v]
                }),
        );

    println!("{table}", table = table.show());

    Ok(())
}