Skip to content

Commit a0e1ed9

Browse files
authored
Merge pull request #14 from bodo-run/copilot/fix-13
Fix CLI/config field naming consistency by ensuring kebab-case naming across all field types
2 parents 992098c + 37cb4cc commit a0e1ed9

13 files changed

+369
-193
lines changed

advanced-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
special-secret: "from_config"

examples/advanced/advanced-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
# You can place this file in the current directory (or a parent directory)
33
# so it can be auto-discovered, or specify it via --config-file, etc.
44

5-
server_port: 9000
6-
database_url: "postgres://user:pass@localhost/mydb"
5+
port: 9000
6+
database-url: "postgres://user:pass@localhost/mydb"
77
debug: true
88

99
# Lists for demonstration
10-
extend_list:
10+
extend-list:
1111
- "foo"
1212
- "bar"
13-
overwrite_list:
13+
overwrite-list:
1414
- "config_item_1"
1515
- "config_item_2"
1616

1717
# These are config-only; no CLI arguments can override them
18-
special_secret: "this-came-from-the-config"
19-
extra_settings:
20-
nesting_level: 3
21-
allow_guest: false
18+
special-secret: "this-came-from-the-config"
19+
extra-settings:
20+
nesting-level: 3
21+
allow-guest: false

examples/advanced/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use serde::{Deserialize, Serialize};
33

44
#[derive(Debug, Default, Deserialize, Serialize)]
55
pub struct ExtraSettings {
6+
#[serde(rename = "nesting-level")]
67
pub nesting_level: i64,
8+
#[serde(rename = "allow-guest")]
79
pub allow_guest: Option<bool>,
810
}
911

@@ -32,7 +34,7 @@ struct AdvancedConfig {
3234
pub server_port: u16,
3335

3436
// just specifying --debug will set it to true
35-
#[config_arg()]
37+
#[config_arg(default_value = "false")]
3638
pub debug: bool,
3739

3840
// some config files expand environment variables

examples/basic/app-config.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
# Sample configuration file for the "basic" example.
22
port: 9090
3-
database_url: "postgres://localhost:5432/mydb"
4-
ignored_files:
5-
- "*.log"
6-
- "target/"
7-
- "node_modules/"
3+
database-url: "postgres://localhost:5432/mydb"

examples/basic/simple-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
port: 3000

examples/basic/snake-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
database_url: "postgres://localhost:5432/mydb"

examples/basic/test-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
database-url: "postgres://localhost:5432/mydb"

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,15 @@ fn generate_config_field(field: &FieldInfo) -> TokenStream2 {
318318
let ident = &field.ident;
319319
let ty = &field.ty;
320320

321-
// Only use rename if explicitly specified
321+
// Use kebab-case naming for config fields to match CLI conventions
322322
let rename_attr = if let Some(name) = &field.arg_attrs.name {
323323
let name_lit = LitStr::new(name, Span::call_site());
324324
quote!(#[serde(rename = #name_lit)])
325325
} else {
326-
quote!()
326+
// Convert to kebab-case to match CLI field naming
327+
let kebab_name = ident.to_string().to_kebab_case();
328+
let name_lit = LitStr::new(&kebab_name, Span::call_site());
329+
quote!(#[serde(rename = #name_lit)])
327330
};
328331

329332
// Wrap non-Option types as Option<T> to detect presence in config
@@ -488,7 +491,7 @@ fn unify_field(field: &FieldInfo) -> TokenStream2 {
488491
}
489492
}
490493
}
491-
},
494+
}
492495
MultiValueBehavior::Overwrite => {
493496
// For overwrite: CLI > config > default
494497
if let Some(dv) = &field.arg_attrs.default_value {

tests/advanced.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use tempfile::TempDir;
66
#[test]
77
fn extend_list_merging() -> Result<(), Box<dyn std::error::Error>> {
88
let dir = TempDir::new()?;
9-
std::fs::write(dir.path().join("advanced-config.yaml"),
10-
"extend_list: [\"config_item\"]\noverwrite_list: [\"config_item\"]\nspecial_secret: \"secret\"\nextra_settings: { nesting_level: 3, allow_guest: false }")?;
9+
std::fs::write(dir.path().join("advanced-config.yaml"),
10+
"extend-list: [\"config_item\"]\noverwrite-list: [\"config_item\"]\nspecial-secret: \"secret\"\nextra-settings:\n nesting-level: 3\n allow-guest: false")?;
1111

1212
Command::cargo_bin("advanced")?
1313
.current_dir(dir.path())
@@ -27,8 +27,8 @@ fn extend_list_merging() -> Result<(), Box<dyn std::error::Error>> {
2727
#[test]
2828
fn overwrite_list_cli() -> Result<(), Box<dyn std::error::Error>> {
2929
let dir = TempDir::new()?;
30-
std::fs::write(dir.path().join("advanced-config.yaml"),
31-
"overwrite_list: [\"config_item\"]\nspecial_secret: \"secret\"\nextra_settings: { nesting_level: 3, allow_guest: false }")?;
30+
std::fs::write(dir.path().join("advanced-config.yaml"),
31+
"overwrite-list: [\"config_item\"]\nspecial-secret: \"secret\"\nextra-settings:\n nesting-level: 3\n allow-guest: false")?;
3232

3333
Command::cargo_bin("advanced")?
3434
.current_dir(dir.path())
@@ -49,7 +49,7 @@ fn config_only_field_from_file() -> Result<(), Box<dyn std::error::Error>> {
4949
let dir = TempDir::new()?;
5050
std::fs::write(
5151
dir.path().join("advanced-config.yaml"),
52-
"special_secret: \"from_config\"\nextra_settings: { nesting_level: 3, allow_guest: false }",
52+
"special-secret: \"from_config\"",
5353
)?;
5454

5555
Command::cargo_bin("advanced")?
@@ -80,7 +80,7 @@ fn test_positional_args() -> Result<(), Box<dyn std::error::Error>> {
8080
let dir = TempDir::new()?;
8181
std::fs::write(
8282
dir.path().join("advanced-config.yaml"),
83-
"database_url: \"sqlite://test.db\"\n",
83+
"database-url: \"sqlite://test.db\"\n",
8484
)?;
8585

8686
Command::cargo_bin("advanced")?

tests/basic.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ fn no_config_uses_defaults() -> Result<(), Box<dyn std::error::Error>> {
5757
fn config_overrides_default_github_issue_8() -> Result<(), Box<dyn std::error::Error>> {
5858
// This test specifically validates the fix for GitHub issue #8
5959
// Config file values should override default_value attributes
60-
60+
6161
let dir = Path::new("examples/basic");
62-
62+
6363
// The config file has port: 9090
6464
// The struct has #[config_arg(default_value = "8080")]
6565
// Expected: config value (9090) should override default (8080)
66-
66+
6767
Command::cargo_bin("basic")?
6868
.current_dir(dir)
6969
.arg("--config-file")

0 commit comments

Comments
 (0)