config: --init-config CLI redesign + documentation rewrite (CLI half of #13) - #15
Merged
Merged
Conversation
…ig CLI Adds explicit destination semantics to --init-config so that root-run invocations don't silently route to /root/.config based on the calling user's $HOME. Implements the destination-token spec from sanohiro#13: the first comma-token of --init-config=... is interpreted as a target ("system", "user", or an absolute or ~/-prefixed path); remaining tokens are preset names. When the first token is none of those, the destination defaults to "user", so the legacy form --init-config=vim,jp keeps writing to ~/.config/bcon/config.toml. Library changes (src/config/mod.rs): - New `WriteTarget {User, System, Path(PathBuf)}` enum (pub). - New `parse_init_config_arg(arg: &str) -> (WriteTarget, Vec<String>)` free function (pub). - New `expand_tilde(s: &str) -> PathBuf` private helper. - `Config::write_config_with_preset` now takes `(target: &WriteTarget, presets: &[&str])`. Target is no longer threaded through the preset list; display name is `presets.join` without the previous "system" filter. - `Config::get_config_path_for_preset` renamed to `Config::path_for_target(target: &WriteTarget)`. - `Config::write_default_config()` updated for the new signature. Binary changes (src/main.rs): - --init-config parser routed through `parse_init_config_arg`. - --help EXAMPLES and the post-init-config usage hint enumerate the four target-token forms (system / user / absolute / tilde) in the order matching the spec; preset-only and no-token rows are omitted from the example listing as they do not exercise the target path. Tests (src/config/mod.rs): - test_parse_init_config_arg_cases: target detection over user, system, absolute path, ~/-prefixed path, and preset-only (legacy) input. - test_expand_tilde_basics: passthrough for absolute paths and ~/ prepending (guarded when home_dir is None). cargo test --bin bcon config::tests: 11/11 passing.
…et token Updates user-facing documentation to describe the layered config discovery model from sanohiro#14 and the new --init-config target/preset split. docs/configuration.md and configuration.ja.md: - "Config File Locations" rewritten as a layered XDG merge (built-in defaults <- /etc/bcon/config.toml <- ~/.config/bcon/config.toml) with helix/mpv-style semantics (table-recursive, array-replace). - New "Generating a Config File: --init-config" section with two subsections: Destinations - 4-row table for system / user / absolute path / tilde-prefixed path (path rows note BCON_CONFIG for loading the resulting file). Examples - typical invocations whose generated file is picked up by the standard layered load. - New "Single-file bypass: BCON_CONFIG" section, placed after --init-config, with two use cases: loading an ad-hoc config generated by a path target, and BCON_CONFIG=/dev/null bcon for clean-defaults A/B-comparison. - "system" removed from the preset list since it is now a target, not a preset. - "Example Config" renamed to "Configuration File Example" so the upstream-content section name no longer collides with the new --init-config "Examples" subsection. CLAUDE.md: - Configuration section expanded to mention the layered merge, BCON_CONFIG, and the explicit target form of --init-config. docs/installation.md and installation.ja.md are intentionally unchanged: their existing --init-config=system,vim,jp invocations remain valid under the new parser (the comma-list first-token scheme).
…patibility The implementation has exactly three layers today (builtin defaults + /etc/bcon/config.toml + ~/.config/bcon/config.toml), but calling out the literal number in user-facing docs and identifiers locks us in: future expansion to XDG_CONFIG_DIRS, conf.d-style splits, or vendor overlays would make "three" a lie. The more abstract "multi-layer" / "multiple layers" wording communicates the model without committing to a fixed count. - docs/configuration.md: "in three layers (XDG-style merge)" -> "across multiple layers (XDG-style merge)". - docs/configuration.ja.md: 「3 レイヤー」-> 「複数のレイヤー」. - src/config/mod.rs: load_layered_from_paths doc comment changed from "up to three layers" to "multiple layers"; the unit test renamed test_load_three_layer_merge -> test_load_multi_layer_merge (its body comment updated to match). cargo test --bin bcon config::tests: 11/11 passing. No new clippy lints introduced.
Owner
|
Thanks — the root-shadow trap is properly eliminated now. Docs rewrite is thorough too. This closes the #13 proposal cleanly. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CLI redesign + documentation rewrite — the second half of the two-PR
split agreed in #13. Pairs with #14.
--init-configpreviously decided between/etc/bcon/and~/.config/bcon/via
dirs::config_dir()of the calling user. Undersudo, this silentlywrites to
/root/.config/bcon/config.tomlrather than/etc/bcon/...—the production trap described in #13 (sec. 2 "init-config silently routes
to the caller's home"). This PR replaces the implicit destination with an
explicit target token, and rewrites
docs/configuration.{md,ja.md}tocover the layered model and the new CLI surface.
CLI: target token
The first comma-separated argument of
--init-config=...is interpretedas a
WriteTargetwhen it isuser,system, or starts with/or~/.Otherwise the entire list is treated as preset names — preserving every
pre-existing destination (legacy
--init-config=vim,jpstill writes to~/.config/bcon/config.toml).bcon --init-config=system/etc/bcon/config.tomlbcon --init-config=user~/.config/bcon/config.tomlbcon --init-config=/tmp/x.toml/tmp/x.toml(load viaBCON_CONFIG)bcon --init-config=~/foo.toml$HOME/foo.toml(tilde-expanded; load viaBCON_CONFIG)sudo bcon --init-config=systemnow writes to/etc/bcon/config.tomldeterministically, regardless of the caller's
$HOME.Library API
pub enum WriteTarget { User, System, Path(PathBuf) }pub fn parse_init_config_arg(arg: &str) -> (WriteTarget, Vec<String>)Config::write_config_with_preset(target: &WriteTarget, presets: &[&str])—target no longer threaded through the preset list
Config::path_for_target(&WriteTarget)(renamed fromget_config_path_for_preset)expand_tildehelperWriteTargetandparse_init_config_argarepubso distributors usingConfig::default_template()(introduced in #14) can pick a destinationwithout re-implementing the CLI parser.
Documentation
docs/configuration.{md,ja.md}rewritten end-to-end to cover:/etc/bcon/...→~/.config/bcon/..., with helix/mpv-style merge semantics)--init-configtarget-token syntax, presented as aDestinationstable (4 forms) and a separate
Examplessubsection (typicalinvocations that complete with the standard layered load)
BCON_CONFIGenv-var bypass (introduced in config: layered XDG-style config discovery (engine + distributors API) #14), documented withtwo use cases: loading an ad-hoc config generated by a path-target
--init-config, andBCON_CONFIG=/dev/null bconfor clean-defaultsA/B-comparison
Example Config→Configuration File Example) sothe upstream-content section name no longer collides with the new
### ExamplessubsectionCLAUDE.md's Configuration section gains a short pointer to the newbehavior.
Wording in
src/config/mod.rs(introduced via #14) is forward-compat'd:the
load_layered_from_pathsdoc comment ("up to three layers") and thetest name (
test_load_three_layer_merge) are renamed to "multi-layer"versions so future overlays (per-host, per-project, etc.) don't make the
prose stale.
Backward compatibility
--init-config(no argument): user destination, unchanged.--init-config=vim,jp): the detection ruleshort-circuits to
WriteTarget::Userwhen the first token is not arecognized target, so the destination stays at
~/.config/bcon/config.toml.--forcesemantics unchanged.get_config_path_for_preset→path_for_target)and one signature change (
write_config_with_presettakes&WriteTarget).Test plan
cargo test --bin bcon config::tests: 11/11 passing (9 inheritedfrom #14, 2 new).
test_parse_init_config_arg_casesuser,system, absolute path,~/)test_expand_tilde_basicsFull
cargo test: 53 passed; 0 failed; 1 ignored (seatd,env-dependent).
cargo build --release: clean, no new warnings.Manual verification
End-to-end verified on a separate Arch VM (PR2 binary deployed alongside
the AUR-installed v1.3.4 as
/usr/local/bin/bcon-pr2, original configfiles preserved by mv-aside):
sudo bcon --init-config=systemwrites to/etc/bcon/config.tomlwithroot:rootownership; no/root/.config/bcon/config.tomlis created— the production trap from Proposal: Layered XDG-style config discovery (/etc/ + ~/.config/ merge) #13 (sec. 2) is eliminated.
bcon --init-config=user,vim,jpwrites to$XDG_CONFIG_HOME/bcon/config.toml.bcon --init-config=/tmp/x.toml,vimwrites to the requested absolutepath.
bcon --init-config=~/foo.toml,vimtilde-expands inside the binary(the shell does not expand
~in=...context, so the literal~/foo.tomlreachesparse_init_config_argandexpand_tilderesolvesit to
/home/<user>/foo.toml).Refs
Refs #13 (CLI half). Pairs with #14.