on master help sign in
add a CLI flag for specifying config file location (#2666)
5d33dbaMichael Davis
book/src/configuration.md+3
@@ -25,6 +25,9 @@ select = "underline"
25hidden = false
25hidden = false
26```
26```
27
27
28+You may also specify a file to use for configuration with the `-c` or
29+`--config` CLI argument: `hx -c path/to/custom-config.toml`.
30+
28## Editor
31## Editor
29
32
30### `[editor]` Section
33### `[editor]` Section
contrib/completion/hx.bash+1−1
@@ -16,7 +16,7 @@ _hx() {
16 COMPREPLY=($(compgen -W "$languages" -- $2))
16 COMPREPLY=($(compgen -W "$languages" -- $2))
17 ;;
17 ;;
18 *)
18 *)
19− COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit" -- $2))
19+ COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config" -- $2))
20 ;;
20 ;;
21 esac
21 esac
22} && complete -F _hx hx
22} && complete -F _hx hx
contrib/completion/hx.fish+1
@@ -11,3 +11,4 @@ complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity"
11complete -c hx -s V -l version -d "Prints version information"
11complete -c hx -s V -l version -d "Prints version information"
12complete -c hx -l vsplit -d "Splits all given files vertically into different windows"
12complete -c hx -l vsplit -d "Splits all given files vertically into different windows"
13complete -c hx -l hsplit -d "Splits all given files horizontally into different windows"
13complete -c hx -l hsplit -d "Splits all given files horizontally into different windows"
14+complete -c hx -s c -l config -d "Specifies a file to use for completion"
contrib/completion/hx.zsh+2
@@ -16,6 +16,8 @@ _hx() {
16 "--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \
16 "--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \
17 "--vsplit[Splits all given files vertically into different windows]" \
17 "--vsplit[Splits all given files vertically into different windows]" \
18 "--hsplit[Splits all given files horizontally into different windows]" \
18 "--hsplit[Splits all given files horizontally into different windows]" \
19+ "-c[Specifies a file to use for configuration]" \
20+ "--config[Specifies a file to use for configuration]" \
19 "*:file:_files"
21 "*:file:_files"
20
22
21 case "$state" in
23 case "$state" in
helix-loader/src/lib.rs+31−11
@@ -2,11 +2,28 @@ pub mod config;
2pub mod grammar;
2pub mod grammar;
3
3
4use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
4use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
5+use std::path::PathBuf;
5
6
6−pub static RUNTIME_DIR: once_cell::sync::Lazy<std::path::PathBuf> =
7+pub static RUNTIME_DIR: once_cell::sync::Lazy<PathBuf> = once_cell::sync::Lazy::new(runtime_dir);
7− once_cell::sync::Lazy::new(runtime_dir);
8
8
9+static CONFIG_FILE: once_cell::sync::OnceCell<PathBuf> = once_cell::sync::OnceCell::new();
10+
11+pub fn initialize_config_file(specified_file: Option<PathBuf>) {
12+ let config_file = specified_file.unwrap_or_else(|| {
13+ let config_dir = config_dir();
14+
15+ if !config_dir.exists() {
16+ std::fs::create_dir_all(&config_dir).ok();
17+ }
18+
19+ config_dir.join("config.toml")
20+ });
21+
22+ // We should only initialize this value once.
23+ CONFIG_FILE.set(config_file).ok();
24+}
25+
9−pub fn runtime_dir() -> std::path::PathBuf {
26+pub fn runtime_dir() -> PathBuf {
10 if let Ok(dir) = std::env::var("HELIX_RUNTIME") {
27 if let Ok(dir) = std::env::var("HELIX_RUNTIME") {
11 return dir.into();
28 return dir.into();
12 }
29 }
@@ -31,7 +48,7 @@ pub fn runtime_dir() -> std::path::PathBuf {
31 .unwrap()
48 .unwrap()
32}
49}
33
50
34−pub fn config_dir() -> std::path::PathBuf {
51+pub fn config_dir() -> PathBuf {
35 // TODO: allow env var override
52 // TODO: allow env var override
36 let strategy = choose_base_strategy().expect("Unable to find the config directory!");
53 let strategy = choose_base_strategy().expect("Unable to find the config directory!");
37 let mut path = strategy.config_dir();
54 let mut path = strategy.config_dir();
@@ -39,7 +56,7 @@ pub fn config_dir() -> std::path::PathBuf {
39 path
56 path
40}
57}
41
58
42−pub fn local_config_dirs() -> Vec<std::path::PathBuf> {
59+pub fn local_config_dirs() -> Vec<PathBuf> {
43 let directories = find_root_impl(None, &[".helix".to_string()])
60 let directories = find_root_impl(None, &[".helix".to_string()])
44 .into_iter()
61 .into_iter()
45 .map(|path| path.join(".helix"))
62 .map(|path| path.join(".helix"))
@@ -48,7 +65,7 @@ pub fn local_config_dirs() -> Vec<std::path::PathBuf> {
48 directories
65 directories
49}
66}
50
67
51−pub fn cache_dir() -> std::path::PathBuf {
68+pub fn cache_dir() -> PathBuf {
52 // TODO: allow env var override
69 // TODO: allow env var override
53 let strategy = choose_base_strategy().expect("Unable to find the config directory!");
70 let strategy = choose_base_strategy().expect("Unable to find the config directory!");
54 let mut path = strategy.cache_dir();
71 let mut path = strategy.cache_dir();
@@ -56,19 +73,22 @@ pub fn cache_dir() -> std::path::PathBuf {
56 path
73 path
57}
74}
58
75
59−pub fn config_file() -> std::path::PathBuf {
76+pub fn config_file() -> PathBuf {
77+ CONFIG_FILE
78+ .get()
79+ .map(|path| path.to_path_buf())
60− config_dir().join("config.toml")
80+ .unwrap_or_else(|| config_dir().join("config.toml"))
61}
81}
62
82
63−pub fn lang_config_file() -> std::path::PathBuf {
83+pub fn lang_config_file() -> PathBuf {
64 config_dir().join("languages.toml")
84 config_dir().join("languages.toml")
65}
85}
66
86
67−pub fn log_file() -> std::path::PathBuf {
87+pub fn log_file() -> PathBuf {
68 cache_dir().join("helix.log")
88 cache_dir().join("helix.log")
69}
89}
70
90
71−pub fn find_root_impl(root: Option<&str>, root_markers: &[String]) -> Vec<std::path::PathBuf> {
91+pub fn find_root_impl(root: Option<&str>, root_markers: &[String]) -> Vec<PathBuf> {
72 let current_dir = std::env::current_dir().expect("unable to determine current directory");
92 let current_dir = std::env::current_dir().expect("unable to determine current directory");
73 let mut directories = Vec::new();
93 let mut directories = Vec::new();
74
94
helix-term/src/application.rs+1−2
@@ -89,9 +89,8 @@ impl Application {
89
89
90 use helix_view::editor::Action;
90 use helix_view::editor::Action;
91
91
92− let config_dir = helix_loader::config_dir();
93 let theme_loader = std::sync::Arc::new(theme::Loader::new(
92 let theme_loader = std::sync::Arc::new(theme::Loader::new(
94− &config_dir,
93+ &helix_loader::config_dir(),
95 &helix_loader::runtime_dir(),
94 &helix_loader::runtime_dir(),
96 ));
95 ));
97
96
helix-term/src/args.rs+5
@@ -14,6 +14,7 @@ pub struct Args {
14 pub build_grammars: bool,
14 pub build_grammars: bool,
15 pub split: Option<Layout>,
15 pub split: Option<Layout>,
16 pub verbosity: u64,
16 pub verbosity: u64,
17+ pub config_file: Option<PathBuf>,
17 pub files: Vec<(PathBuf, Position)>,
18 pub files: Vec<(PathBuf, Position)>,
18}
19}
19
20
@@ -43,6 +44,10 @@ impl Args {
43 anyhow::bail!("--grammar must be followed by either 'fetch' or 'build'")
44 anyhow::bail!("--grammar must be followed by either 'fetch' or 'build'")
44 }
45 }
45 },
46 },
47+ "-c" | "--config" => match argv.next().as_deref() {
48+ Some(path) => args.config_file = Some(path.into()),
49+ None => anyhow::bail!("--config must specify a path to read"),
50+ },
46 arg if arg.starts_with("--") => {
51 arg if arg.starts_with("--") => {
47 anyhow::bail!("unexpected double dash argument: {}", arg)
52 anyhow::bail!("unexpected double dash argument: {}", arg)
48 }
53 }
helix-term/src/main.rs+4−2
@@ -64,6 +64,7 @@ FLAGS:
64 --health [LANG] Checks for potential errors in editor setup
64 --health [LANG] Checks for potential errors in editor setup
65 If given, checks for config errors in language LANG
65 If given, checks for config errors in language LANG
66 -g, --grammar {{fetch|build}} Fetches or builds tree-sitter grammars listed in languages.toml
66 -g, --grammar {{fetch|build}} Fetches or builds tree-sitter grammars listed in languages.toml
67+ -c, --config <file> Specifies a file to use for configuration
67 -v Increases logging verbosity each use for up to 3 times
68 -v Increases logging verbosity each use for up to 3 times
68 (default file: {})
69 (default file: {})
69 -V, --version Prints version information
70 -V, --version Prints version information
@@ -119,14 +120,15 @@ FLAGS:
119 std::fs::create_dir_all(&config_dir).ok();
120 std::fs::create_dir_all(&config_dir).ok();
120 }
121 }
121
122
123+ helix_loader::initialize_config_file(args.config_file.clone());
124+
122− let config = match std::fs::read_to_string(config_dir.join("config.toml")) {
125+ let config = match std::fs::read_to_string(helix_loader::config_file()) {
123 Ok(config) => toml::from_str(&config)
126 Ok(config) => toml::from_str(&config)
124 .map(helix_term::keymap::merge_keys)
127 .map(helix_term::keymap::merge_keys)
125 .unwrap_or_else(|err| {
128 .unwrap_or_else(|err| {
126 eprintln!("Bad config: {}", err);
129 eprintln!("Bad config: {}", err);
127 eprintln!("Press <ENTER> to continue with default config");
130 eprintln!("Press <ENTER> to continue with default config");
128 use std::io::Read;
131 use std::io::Read;
129− // This waits for an enter press.
130 let _ = std::io::stdin().read(&mut []);
132 let _ = std::io::stdin().read(&mut []);
131 Config::default()
133 Config::default()
132 }),
134 }),