1use std::path::PathBuf;
4
5use clap::Parser;
6use knf_dotted::PathLeaf;
7
8use crate::format::Format;
9
10#[derive(Parser, Debug)]
11#[command(
12 name = "knf",
13 version,
14 about = "Merge layered configuration files and print the result",
15 long_about = "\
16Merge layered configuration files and print the result.
17
18Files are layers, merged left to right in argument order. JSON and TOML may be
19mixed freely. Exactly one document goes to stdout.
20
21 knf base.toml prod.toml
22 knf base.json - --input-format json # stdin as a layer
23 knf defaults.json --set server.port=8080 -f toml
24
25Objects merge key by key. Arrays, scalars and null all replace wholesale —
26null is an ordinary value that overwrites, not a delete instruction."
27)]
28pub struct Cli {
29 #[arg(value_name = "FILE")]
31 pub files: Vec<PathBuf>,
32
33 #[arg(
35 long,
36 value_name = "FORMAT",
37 long_help = "\
38Treat every input as this format, overriding extension inference.
39
40Required for `-`, which has no extension. Note that it applies to all inputs,
41not only stdin, so it cannot be used to mix a stdin layer of one format with
42files of another."
43 )]
44 pub input_format: Option<Format>,
45
46 #[arg(
48 long = "set",
49 value_name = "KEY.PATH=VALUE",
50 long_help = "\
51Inline terminal layer, applied after all files. Repeatable; multiple --set apply
52left to right.
53
54The value is parsed as JSON, falling back to a string when that fails:
55
56 port=8080 -> 8080 (number)
57 debug=true -> true (bool)
58 name=foo -> \"foo\" (not valid JSON, so a string)
59 proxy=null -> null (an error under -f toml, like any other null)
60 tags=[\"a\",\"b\"] -> array
61 tags=[a,b] -> \"[a,b]\" (not valid JSON, so a string)
62
63Sharp edge: version=1.0 is the number 1.0, not the string \"1.0\". Force a string
64by quoting into JSON: --set version='\"1.0\"'.
65
66Dotted paths nest, so keys containing a literal dot are not addressable from
67--set; use a file."
68 )]
69 pub set: Vec<PathLeaf<String>>,
70
71 #[arg(short = 'f', long, value_name = "FORMAT")]
73 pub format: Option<Format>,
74
75 #[arg(long)]
77 pub strict: bool,
78
79 #[arg(long)]
81 pub compact: bool,
82}