mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-25 05:30:22 +00:00
other: clarify config file creation logic/code (#1518)
This commit is contained in:
parent
38c6e70c1e
commit
2c0fb2a723
3 changed files with 60 additions and 28 deletions
|
@ -12,8 +12,8 @@ If no config file argument is given, it will automatically look for a config fil
|
|||
| Linux | `~/.config/bottom/bottom.toml` <br/> `$XDG_CONFIG_HOME/bottom/bottom.toml` |
|
||||
| Windows | `C:\Users\<USER>\AppData\Roaming\bottom\bottom.toml` |
|
||||
|
||||
Like if a path is passed with `-C`/`--config`, if a file doesn't exist at the path, bottom will automatically create a
|
||||
new, default config file at that location.
|
||||
If the config file doesn't exist at the path, bottom will automatically try to create a new config file at the location
|
||||
with default values.
|
||||
|
||||
## JSON Schema
|
||||
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -27,7 +27,6 @@ use std::{
|
|||
boxed::Box,
|
||||
io::{stderr, stdout, Write},
|
||||
panic::{self, PanicInfo},
|
||||
path::Path,
|
||||
sync::{
|
||||
mpsc::{self, Receiver, Sender},
|
||||
Arc, Condvar, Mutex,
|
||||
|
@ -36,7 +35,6 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use app::{layout_manager::UsedWidgets, App, AppConfigFields, DataFilters};
|
||||
use crossterm::{
|
||||
event::{
|
||||
|
@ -49,7 +47,7 @@ use crossterm::{
|
|||
};
|
||||
use data_conversion::*;
|
||||
use event::{handle_key_event_or_break, handle_mouse_event, BottomEvent, CollectionThreadEvent};
|
||||
use options::{args, get_config_path, get_or_create_config, init_app};
|
||||
use options::{args, get_or_create_config, init_app};
|
||||
use tui::{backend::CrosstermBackend, Terminal};
|
||||
#[allow(unused_imports)]
|
||||
use utils::logging::*;
|
||||
|
@ -330,18 +328,8 @@ fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
// Read from config file.
|
||||
let config = {
|
||||
let config_path = get_config_path(args.general.config_location.as_deref());
|
||||
get_or_create_config(config_path.as_deref()).with_context(|| {
|
||||
format!(
|
||||
"Unable to parse or create the config file at: {}",
|
||||
config_path
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| Path::new("<failed locating>"))
|
||||
.display()
|
||||
)
|
||||
})?
|
||||
};
|
||||
|
||||
let config = get_or_create_config(args.general.config_location.as_deref())?;
|
||||
|
||||
// Create the "app" and initialize a bunch of stuff.
|
||||
let (mut app, widget_layout, styling) = init_app(args, config)?;
|
||||
|
|
|
@ -68,7 +68,7 @@ macro_rules! is_flag_enabled {
|
|||
///
|
||||
/// For more details on this, see [dirs](https://docs.rs/dirs/latest/dirs/fn.config_dir.html)'
|
||||
/// documentation.
|
||||
pub fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> {
|
||||
fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> {
|
||||
const DEFAULT_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";
|
||||
|
||||
if let Some(conf_loc) = override_config_path {
|
||||
|
@ -92,29 +92,73 @@ pub fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get the config at `config_path`. If there is no config file at the specified
|
||||
/// path, it will try to create a new file with the default settings, and return
|
||||
/// the default config. If bottom fails to write a new config, it will silently
|
||||
/// just return the default config.
|
||||
pub fn get_or_create_config(config_path: Option<&Path>) -> OptionResult<Config> {
|
||||
match &config_path {
|
||||
Some(path) => {
|
||||
if let Ok(config_string) = fs::read_to_string(path) {
|
||||
Ok(toml_edit::de::from_str(&config_string)?)
|
||||
} else {
|
||||
fn create_config_at_path(path: &Path) -> anyhow::Result<Config> {
|
||||
if let Some(parent_path) = path.parent() {
|
||||
fs::create_dir_all(parent_path)?;
|
||||
}
|
||||
|
||||
fs::File::create(path)?.write_all(CONFIG_TEXT.as_bytes())?;
|
||||
let mut file = fs::File::create(path)?;
|
||||
file.write_all(CONFIG_TEXT.as_bytes())?;
|
||||
|
||||
Ok(Config::default())
|
||||
}
|
||||
|
||||
/// Get the config at `config_path`. If there is no config file at the specified
|
||||
/// path, it will try to create a new file with the default settings, and return
|
||||
/// the default config.
|
||||
///
|
||||
/// We're going to use the following behaviour on when we'll return an error rather
|
||||
/// than just "silently" continuing on:
|
||||
/// - If the user passed in a path explicitly, then we will be loud and error out.
|
||||
/// - If the user does NOT pass in a path explicitly, then just show a warning,
|
||||
/// but continue. This is in case they do not want to write a default config file at
|
||||
/// the XDG locations, for example.
|
||||
pub fn get_or_create_config(config_path: Option<&Path>) -> anyhow::Result<Config> {
|
||||
let adjusted_config_path = get_config_path(config_path);
|
||||
|
||||
match &adjusted_config_path {
|
||||
Some(path) => {
|
||||
if let Ok(config_string) = fs::read_to_string(path) {
|
||||
Ok(toml_edit::de::from_str(&config_string)?)
|
||||
} else {
|
||||
match create_config_at_path(path) {
|
||||
Ok(cfg) => Ok(cfg),
|
||||
Err(err) => {
|
||||
if config_path.is_some() {
|
||||
Err(err.context(format!(
|
||||
"bottom could not create a new config file at '{}'.",
|
||||
path.display()
|
||||
)))
|
||||
} else {
|
||||
indoc::eprintdoc!(
|
||||
"Note: bottom couldn't create a default config file at '{}', and the \
|
||||
application has fallen back to the default configuration.
|
||||
|
||||
Caused by:
|
||||
{err}
|
||||
",
|
||||
path.display()
|
||||
);
|
||||
|
||||
Ok(Config::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// If we somehow don't have any config path, then just assume the default config
|
||||
// but don't write to any file.
|
||||
//
|
||||
// TODO: Maybe make this "show" an error, but don't crash.
|
||||
// TODO: For now, just print a message to stderr indicating this. In the future,
|
||||
// probably show in-app (too).
|
||||
|
||||
eprintln!(
|
||||
"Note: bottom couldn't find a location to create or read a config file, so \
|
||||
the application has fallen back to the default configuration. \
|
||||
This could be for a variety of reasons, such as issues with file permissions."
|
||||
);
|
||||
|
||||
Ok(Config::default())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue