mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
Rename config show command to settings
This commit is contained in:
parent
9da45b319e
commit
74b2c5c889
9 changed files with 90 additions and 133 deletions
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "fabro config show, preflight subcommand, and storage-dir"
|
||||
title: "fabro settings, preflight subcommand, and storage-dir"
|
||||
date: "2026-03-27"
|
||||
---
|
||||
|
||||
## `fabro config show`
|
||||
## `fabro settings`
|
||||
|
||||
A new `fabro config show` command displays the fully resolved configuration for a workflow, showing how CLI flags, environment variables, project config, and workflow defaults are layered together. This makes it easy to debug configuration issues without guessing which layer is winning.
|
||||
A new `fabro settings` command displays the fully resolved configuration for a workflow, showing how CLI flags, environment variables, project config, and workflow defaults are layered together. This makes it easy to debug configuration issues without guessing which layer is winning.
|
||||
|
||||
```bash
|
||||
fabro config show my-workflow
|
||||
fabro settings my-workflow
|
||||
```
|
||||
|
||||
## `fabro preflight`
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ CLI flags always override `user.toml` values, which override hardcoded defaults.
|
|||
|
||||
---
|
||||
|
||||
## `fabro config show`
|
||||
## `fabro settings`
|
||||
|
||||
Print the merged resolved configuration as YAML.
|
||||
|
||||
```bash
|
||||
fabro config show
|
||||
fabro config show demo
|
||||
fabro config show run.toml
|
||||
fabro settings
|
||||
fabro settings demo
|
||||
fabro settings run.toml
|
||||
```
|
||||
|
||||
With no argument, Fabro prints the merged ambient defaults from `~/.fabro/user.toml` and the nearest `fabro.toml`.
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ pub(crate) struct DfArgs {
|
|||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct ConfigShowArgs {
|
||||
pub(crate) struct SettingsArgs {
|
||||
/// Optional workflow name, .fabro path, or .toml run config to overlay
|
||||
pub(crate) workflow: Option<PathBuf>,
|
||||
}
|
||||
|
|
@ -794,7 +794,7 @@ pub(crate) enum Commands {
|
|||
/// Manage secrets in ~/.fabro/.env
|
||||
Secret(SecretNamespace),
|
||||
/// Inspect merged configuration
|
||||
Config(ConfigNamespace),
|
||||
Settings(SettingsArgs),
|
||||
/// Workflow operations
|
||||
Workflow(WorkflowNamespace),
|
||||
/// Open the Discord community in the browser
|
||||
|
|
@ -871,9 +871,7 @@ impl Commands {
|
|||
SecretCommand::Rm(_) => "secret rm",
|
||||
SecretCommand::Set(_) => "secret set",
|
||||
},
|
||||
Self::Config(ns) => match &ns.command {
|
||||
ConfigCommand::Show(_) => "config show",
|
||||
},
|
||||
Self::Settings(_) => "settings",
|
||||
Self::Workflow(ns) => match &ns.command {
|
||||
WorkflowCommand::List(_) => "workflow list",
|
||||
WorkflowCommand::Create(_) => "workflow create",
|
||||
|
|
@ -962,18 +960,6 @@ pub(crate) enum SecretCommand {
|
|||
Set(SecretSetArgs),
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct ConfigNamespace {
|
||||
#[command(subcommand)]
|
||||
pub(crate) command: ConfigCommand,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub(crate) enum ConfigCommand {
|
||||
/// Print the merged FabroSettings as YAML
|
||||
Show(ConfigShowArgs),
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct SystemNamespace {
|
||||
#[command(subcommand)]
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::args::{ConfigCommand, ConfigNamespace, ConfigShowArgs, GlobalArgs};
|
||||
use crate::args::{GlobalArgs, SettingsArgs};
|
||||
use crate::user_config;
|
||||
use fabro_config::{ConfigLayer, FabroSettings};
|
||||
|
||||
pub(crate) fn dispatch(ns: ConfigNamespace, globals: &GlobalArgs) -> anyhow::Result<()> {
|
||||
match ns.command {
|
||||
ConfigCommand::Show(args) => show_command(&args, globals),
|
||||
}
|
||||
}
|
||||
|
||||
fn merged_config(workflow: Option<&Path>, globals: &GlobalArgs) -> anyhow::Result<FabroSettings> {
|
||||
let cwd = std::env::current_dir()?;
|
||||
let base = match workflow {
|
||||
|
|
@ -22,7 +16,7 @@ fn merged_config(workflow: Option<&Path>, globals: &GlobalArgs) -> anyhow::Resul
|
|||
base.combine(cli).resolve()
|
||||
}
|
||||
|
||||
pub(crate) fn show_command(args: &ConfigShowArgs, globals: &GlobalArgs) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: &SettingsArgs, globals: &GlobalArgs) -> anyhow::Result<()> {
|
||||
let config = merged_config(args.workflow.as_deref(), globals)?;
|
||||
let mut yaml = serde_yaml::to_string(&config)?;
|
||||
if !yaml.ends_with('\n') {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ async fn main_inner() -> (String, Result<()>) {
|
|||
}
|
||||
Commands::Pr(ns) => commands::pr::dispatch(ns, &globals).await?,
|
||||
Commands::Secret(ns) => commands::secret::dispatch(ns)?,
|
||||
Commands::Config(ns) => commands::config::dispatch(ns, &globals)?,
|
||||
Commands::Settings(args) => commands::config::execute(&args, &globals)?,
|
||||
Commands::Workflow(ns) => commands::workflow::dispatch(ns)?,
|
||||
Commands::Skill(ns) => commands::skill::dispatch(ns)?,
|
||||
Commands::Upgrade(args) => {
|
||||
|
|
@ -245,10 +245,7 @@ async fn main_inner() -> (String, Result<()>) {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use args::{
|
||||
ConfigCommand, ConfigNamespace, ProviderCommand, ProviderNamespace, StoreCommand,
|
||||
StoreNamespace,
|
||||
};
|
||||
use args::{ProviderCommand, ProviderNamespace, StoreCommand, StoreNamespace};
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
|
|
@ -456,13 +453,11 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn parse_config_show_command() {
|
||||
let cli = Cli::try_parse_from(["fabro", "config", "show"]).expect("should parse");
|
||||
assert_eq!(cli.command.name(), "config show");
|
||||
fn parse_settings_command() {
|
||||
let cli = Cli::try_parse_from(["fabro", "settings"]).expect("should parse");
|
||||
assert_eq!(cli.command.name(), "settings");
|
||||
match *cli.command {
|
||||
Commands::Config(ConfigNamespace {
|
||||
command: ConfigCommand::Show(args),
|
||||
}) => {
|
||||
Commands::Settings(args) => {
|
||||
assert!(args.workflow.is_none());
|
||||
}
|
||||
_ => panic!("unexpected command variant"),
|
||||
|
|
@ -470,12 +465,10 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn parse_config_show_with_workflow() {
|
||||
let cli = Cli::try_parse_from(["fabro", "config", "show", "demo"]).expect("should parse");
|
||||
fn parse_settings_with_workflow() {
|
||||
let cli = Cli::try_parse_from(["fabro", "settings", "demo"]).expect("should parse");
|
||||
match *cli.command {
|
||||
Commands::Config(ConfigNamespace {
|
||||
command: ConfigCommand::Show(args),
|
||||
}) => {
|
||||
Commands::Settings(args) => {
|
||||
assert_eq!(args.workflow, Some(std::path::PathBuf::from("demo")));
|
||||
}
|
||||
_ => panic!("unexpected command variant"),
|
||||
|
|
@ -484,23 +477,21 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn parse_quiet_flag() {
|
||||
let cli =
|
||||
Cli::try_parse_from(["fabro", "--quiet", "config", "show"]).expect("should parse");
|
||||
let cli = Cli::try_parse_from(["fabro", "--quiet", "settings"]).expect("should parse");
|
||||
assert!(cli.globals.quiet);
|
||||
assert!(!cli.globals.verbose);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_verbose_flag() {
|
||||
let cli =
|
||||
Cli::try_parse_from(["fabro", "--verbose", "config", "show"]).expect("should parse");
|
||||
let cli = Cli::try_parse_from(["fabro", "--verbose", "settings"]).expect("should parse");
|
||||
assert!(!cli.globals.quiet);
|
||||
assert!(cli.globals.verbose);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quiet_and_verbose_conflict() {
|
||||
let result = Cli::try_parse_from(["fabro", "--quiet", "--verbose", "config", "show"]);
|
||||
let result = Cli::try_parse_from(["fabro", "--quiet", "--verbose", "settings"]);
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"should fail when both --quiet and --verbose"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use predicates::prelude::*;
|
|||
#[test]
|
||||
fn help() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.config();
|
||||
let mut cmd = context.settings();
|
||||
cmd.arg("--help");
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: true
|
||||
|
|
@ -18,35 +18,7 @@ fn help() {
|
|||
----- stdout -----
|
||||
Inspect merged configuration
|
||||
|
||||
Usage: fabro config [OPTIONS] <COMMAND>
|
||||
|
||||
Commands:
|
||||
show Print the merged FabroSettings as YAML
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
--debug Enable DEBUG-level logging (default is INFO) [env: FABRO_DEBUG=]
|
||||
--no-upgrade-check Disable automatic upgrade check [env: FABRO_NO_UPGRADE_CHECK=true]
|
||||
--quiet Suppress non-essential output [env: FABRO_QUIET=]
|
||||
--verbose Enable verbose output [env: FABRO_VERBOSE=]
|
||||
--storage-dir <STORAGE_DIR> Storage directory (default: ~/.fabro) [env: FABRO_STORAGE_DIR=[STORAGE_DIR]]
|
||||
-h, --help Print help
|
||||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn show_help() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.config();
|
||||
cmd.args(["show", "--help"]);
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Print the merged FabroSettings as YAML
|
||||
|
||||
Usage: fabro config show [OPTIONS] [WORKFLOW]
|
||||
Usage: fabro settings [OPTIONS] [WORKFLOW]
|
||||
|
||||
Arguments:
|
||||
[WORKFLOW] Optional workflow name, .fabro path, or .toml run config to overlay
|
||||
|
|
@ -62,17 +34,35 @@ fn show_help() {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_config_show_command_is_rejected() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.command();
|
||||
cmd.args(["config", "show"]);
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
----- stderr -----
|
||||
error: unrecognized subcommand 'config'
|
||||
|
||||
Usage: fabro [OPTIONS] <COMMAND>
|
||||
|
||||
For more information, try '--help'.
|
||||
");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn parse_config_show(stdout: &[u8]) -> FabroSettings {
|
||||
fn parse_settings(stdout: &[u8]) -> FabroSettings {
|
||||
serde_yaml::from_slice(stdout).expect("stdout should be valid YAML FabroSettings")
|
||||
}
|
||||
|
||||
/// Set up home config and project config for config show tests.
|
||||
/// Set up home config and project config for settings command tests.
|
||||
/// Uses `context.home_dir` for the home directory. Returns project tempdir.
|
||||
fn setup_config_show_fixture(context: &fabro_test::TestContext) -> tempfile::TempDir {
|
||||
fn setup_settings_fixture(context: &fabro_test::TestContext) -> tempfile::TempDir {
|
||||
context.write_home(
|
||||
".fabro/user.toml",
|
||||
r#"
|
||||
|
|
@ -262,21 +252,20 @@ commands = ["workflow-setup"]
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn config_show_merges_cli_and_project_defaults() {
|
||||
fn settings_merges_cli_and_project_defaults() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
|
||||
let output = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show"])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
|
||||
let cfg = parse_config_show(&output);
|
||||
let cfg = parse_settings(&output);
|
||||
let llm = cfg.llm.as_ref().expect("llm config");
|
||||
assert_eq!(llm.model.as_deref(), Some("project-model"));
|
||||
assert_eq!(llm.provider.as_deref(), Some("openai"));
|
||||
|
|
@ -299,21 +288,21 @@ fn config_show_merges_cli_and_project_defaults() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_workflow_name_applies_run_overlay_and_deep_merges() {
|
||||
fn settings_workflow_name_applies_run_overlay_and_deep_merges() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
|
||||
let output = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show", "demo"])
|
||||
.args(["demo"])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
|
||||
let cfg = parse_config_show(&output);
|
||||
let cfg = parse_settings(&output);
|
||||
let llm = cfg.llm.as_ref().expect("llm config");
|
||||
assert_eq!(cfg.goal.as_deref(), Some("demo goal"));
|
||||
assert_eq!(llm.model.as_deref(), Some("run-model"));
|
||||
|
|
@ -375,7 +364,7 @@ fn config_show_workflow_name_applies_run_overlay_and_deep_merges() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_explicit_workflow_path_uses_workflow_project_layers() {
|
||||
fn settings_explicit_workflow_path_uses_workflow_project_layers() {
|
||||
let context = test_context!();
|
||||
let (project, _storage_dir) = setup_external_workflow_fixture(&context);
|
||||
let cwd = tempfile::tempdir().unwrap();
|
||||
|
|
@ -383,17 +372,17 @@ fn config_show_explicit_workflow_path_uses_workflow_project_layers() {
|
|||
|
||||
// Remove FABRO_STORAGE_DIR so the CLI uses storage_dir from user.toml
|
||||
let output = context
|
||||
.command()
|
||||
.settings()
|
||||
.env_remove("FABRO_STORAGE_DIR")
|
||||
.current_dir(cwd.path())
|
||||
.args(["config", "show", workflow.to_str().unwrap()])
|
||||
.args([workflow.to_str().unwrap()])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
|
||||
let cfg = parse_config_show(&output);
|
||||
let cfg = parse_settings(&output);
|
||||
assert_eq!(cfg.auto_approve, Some(true));
|
||||
assert_eq!(
|
||||
cfg.setup.as_ref().expect("setup config").commands,
|
||||
|
|
@ -474,40 +463,39 @@ fn create_explicit_workflow_path_uses_project_config_relative_to_workflow() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_fabro_path_matches_ambient_defaults() {
|
||||
fn settings_fabro_path_matches_ambient_defaults() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
|
||||
let ambient = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show"])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
let graph = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show", "standalone.fabro"])
|
||||
.args(["standalone.fabro"])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
|
||||
assert_eq!(parse_config_show(&graph), parse_config_show(&ambient));
|
||||
assert_eq!(parse_settings(&graph), parse_settings(&ambient));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_missing_run_config_errors() {
|
||||
fn settings_missing_run_config_errors() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
|
||||
let mut cmd = context.command();
|
||||
let mut cmd = context.settings();
|
||||
cmd.current_dir(project.path());
|
||||
cmd.args(["config", "show", "missing.toml"]);
|
||||
cmd.args(["missing.toml"]);
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
|
|
@ -518,7 +506,7 @@ fn config_show_missing_run_config_errors() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_legacy_cli_config_warns_and_ignores_it() {
|
||||
fn settings_legacy_cli_config_warns_and_ignores_it() {
|
||||
let context = test_context!();
|
||||
let project = tempfile::tempdir().unwrap();
|
||||
|
||||
|
|
@ -533,23 +521,22 @@ model = "legacy-model"
|
|||
);
|
||||
|
||||
let assert = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show"])
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(predicate::str::contains("ignoring legacy config file"))
|
||||
.stderr(predicate::str::contains("Rename it to"));
|
||||
|
||||
let cfg = parse_config_show(&assert.get_output().stdout);
|
||||
let cfg = parse_settings(&assert.get_output().stdout);
|
||||
assert_eq!(cfg.verbose, None);
|
||||
assert_eq!(cfg.llm, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_show_user_config_wins_over_legacy_cli_config() {
|
||||
fn settings_user_config_wins_over_legacy_cli_config() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
context.write_home(
|
||||
".fabro/cli.toml",
|
||||
r#"
|
||||
|
|
@ -562,14 +549,13 @@ shared = "legacy"
|
|||
);
|
||||
|
||||
let assert = context
|
||||
.command()
|
||||
.settings()
|
||||
.current_dir(project.path())
|
||||
.args(["config", "show"])
|
||||
.assert()
|
||||
.success()
|
||||
.stderr(predicate::str::contains("ignoring legacy config file"));
|
||||
|
||||
let cfg = parse_config_show(&assert.get_output().stdout);
|
||||
let cfg = parse_settings(&assert.get_output().stdout);
|
||||
let llm = cfg.llm.as_ref().expect("llm config");
|
||||
assert_eq!(llm.model.as_deref(), Some("project-model"));
|
||||
assert_eq!(
|
||||
|
|
@ -582,9 +568,9 @@ shared = "legacy"
|
|||
|
||||
#[test]
|
||||
#[cfg(feature = "server")]
|
||||
fn config_show_server_url_overrides_cli_defaults() {
|
||||
fn settings_server_url_overrides_cli_defaults() {
|
||||
let context = test_context!();
|
||||
let project = setup_config_show_fixture(&context);
|
||||
let project = setup_settings_fixture(&context);
|
||||
let user_toml_path = context.home_dir.join(".fabro/user.toml");
|
||||
let existing = std::fs::read_to_string(&user_toml_path).unwrap();
|
||||
context.write_home(
|
||||
|
|
@ -597,14 +583,14 @@ fn config_show_server_url_overrides_cli_defaults() {
|
|||
let output = context
|
||||
.command()
|
||||
.current_dir(project.path())
|
||||
.args(["--server-url", "https://cli.example.com", "config", "show"])
|
||||
.args(["--server-url", "https://cli.example.com", "settings"])
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
|
||||
let cfg = parse_config_show(&output);
|
||||
let cfg = parse_settings(&output);
|
||||
assert_eq!(cfg.mode, Some(ExecutionMode::Server));
|
||||
assert_eq!(
|
||||
cfg.server
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ use fabro_test::{fabro_snapshot, test_context};
|
|||
#[test]
|
||||
fn help() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.command();
|
||||
cmd.args(["config", "show", "--help"]);
|
||||
let mut cmd = context.settings();
|
||||
cmd.arg("--help");
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Print the merged FabroSettings as YAML
|
||||
Inspect merged configuration
|
||||
|
||||
Usage: fabro config show [OPTIONS] [WORKFLOW]
|
||||
Usage: fabro settings [OPTIONS] [WORKFLOW]
|
||||
|
||||
Arguments:
|
||||
[WORKFLOW] Optional workflow name, .fabro path, or .toml run config to overlay
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ fn help() {
|
|||
install Set up the Fabro environment (LLMs, certs, GitHub)
|
||||
pr Pull request operations
|
||||
secret Manage secrets in ~/.fabro/.env
|
||||
config Inspect merged configuration
|
||||
settings Inspect merged configuration
|
||||
workflow Workflow operations
|
||||
discord Open the Discord community in the browser
|
||||
docs Open the docs website in the browser
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ impl TestContext {
|
|||
cmd
|
||||
}
|
||||
|
||||
/// Build a `config` subcommand.
|
||||
pub fn config(&self) -> Command {
|
||||
/// Build a `settings` subcommand.
|
||||
pub fn settings(&self) -> Command {
|
||||
let mut cmd = self.command();
|
||||
cmd.arg("config");
|
||||
cmd.arg("settings");
|
||||
cmd
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue