bat/src/bin/bat/config.rs

169 lines
4.4 KiB
Rust
Raw Normal View History

2018-10-11 22:50:37 +02:00
use std::env;
use std::ffi::OsString;
use std::fs;
use std::io::{self, Write};
2018-10-17 23:02:53 +02:00
use std::path::PathBuf;
use crate::directories::PROJECT_DIRS;
2018-10-17 23:02:53 +02:00
pub fn config_file() -> PathBuf {
env::var("BAT_CONFIG_PATH")
.ok()
.map(PathBuf::from)
.filter(|config_path| config_path.is_file())
2019-03-08 11:46:49 +01:00
.unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
2018-10-17 23:02:53 +02:00
}
2020-04-22 21:45:47 +02:00
pub fn generate_config_file() -> bat::error::Result<()> {
let config_file = config_file();
if config_file.exists() {
2020-04-11 19:40:04 +02:00
println!(
"A config file already exists at: {}",
config_file.to_string_lossy()
);
2020-03-26 03:03:10 +01:00
print!("Overwrite? (y/N): ");
io::stdout().flush()?;
let mut decision = String::new();
2020-03-26 03:03:10 +01:00
io::stdin().read_line(&mut decision)?;
if !decision.trim().eq_ignore_ascii_case("Y") {
2020-03-26 03:03:10 +01:00
return Ok(());
}
} else {
2020-03-26 03:03:10 +01:00
let config_dir = config_file.parent();
match config_dir {
Some(path) => fs::create_dir_all(path)?,
2020-04-11 19:40:04 +02:00
None => {
return Err(format!(
2020-04-11 19:40:04 +02:00
"Unable to write config file to: {}",
config_file.to_string_lossy()
2020-04-24 16:09:56 +02:00
)
.into());
2020-04-11 19:40:04 +02:00
}
}
}
2020-10-11 21:57:12 +02:00
let default_config = r#"# This is `bat`s configuration file. Each line either contains a comment or
# a command-line option that you want to pass to `bat` by default. You can
# run `bat --help` to get a list of all possible configuration options.
2020-03-26 03:03:10 +01:00
# Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes`
# for a list of all available themes
2020-03-26 03:03:10 +01:00
#--theme="TwoDark"
# Enable this to use italic text on the terminal. This is not supported on all
# terminal emulators (like tmux, by default):
#--italic-text=always
# Uncomment the following line to disable automatic paging:
#--paging=never
# Uncomment the following line if you are using less version >= 551 and want to
# enable mouse scrolling support in `bat` when running inside tmux. This might
# disable text selection, unless you press shift.
#--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse"
# Syntax mappings: map a certain filename pattern to a language.
# Example 1: use the C++ syntax for .ino files
# Example 2: Use ".gitignore"-style highlighting for ".ignore" files
#--map-syntax "*.ino:C++"
2020-03-26 03:03:10 +01:00
#--map-syntax ".ignore:Git Ignore"
"#;
2020-03-26 03:03:10 +01:00
fs::write(&config_file, default_config)?;
2020-04-11 19:40:04 +02:00
println!(
"Success! Config file written to {}",
config_file.to_string_lossy()
);
2020-03-26 03:03:10 +01:00
Ok(())
}
2018-10-11 22:50:37 +02:00
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
2019-10-20 22:01:20 +02:00
Ok(fs::read_to_string(config_file())
.ok()
.map(|content| get_args_from_str(&content))
.transpose()?
.unwrap_or_else(|| vec![]))
}
2018-10-11 23:01:19 +02:00
pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
}
2019-03-08 11:46:49 +01:00
fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseError> {
2018-10-11 22:50:37 +02:00
let args_per_line = content
.split('\n')
.map(|line| line.trim())
.filter(|line| !line.is_empty())
2019-03-08 11:46:49 +01:00
.filter(|line| !line.starts_with('#'))
2018-10-11 22:50:37 +02:00
.map(|line| shell_words::split(line))
.collect::<Result<Vec<_>, _>>()?;
Ok(args_per_line
.iter()
.flatten()
.map(|line| line.into())
2018-10-11 22:50:37 +02:00
.collect())
}
#[test]
fn empty() {
2018-10-11 22:50:37 +02:00
let args = get_args_from_str("").unwrap();
assert!(args.is_empty());
}
#[test]
fn single() {
2018-10-11 22:50:37 +02:00
assert_eq!(vec!["--plain"], get_args_from_str("--plain").unwrap());
}
#[test]
fn multiple() {
2018-10-11 21:39:44 +02:00
assert_eq!(
vec!["--plain", "--language=cpp"],
2018-10-11 22:50:37 +02:00
get_args_from_str("--plain --language=cpp").unwrap()
2018-10-11 21:39:44 +02:00
);
}
#[test]
fn quotes() {
assert_eq!(
vec!["--theme", "Sublime Snazzy"],
2018-10-11 22:50:37 +02:00
get_args_from_str("--theme \"Sublime Snazzy\"").unwrap()
2018-10-11 21:39:44 +02:00
);
}
#[test]
fn multi_line() {
let config = "
-p
--style numbers,changes
--color=always
";
assert_eq!(
vec!["-p", "--style", "numbers,changes", "--color=always"],
2018-10-11 22:50:37 +02:00
get_args_from_str(config).unwrap()
);
}
#[test]
fn comments() {
let config = "
# plain style
-p
# show line numbers and Git modifications
--style numbers,changes
# Always show ANSI colors
--color=always
";
assert_eq!(
vec!["-p", "--style", "numbers,changes", "--color=always"],
2018-10-11 22:50:37 +02:00
get_args_from_str(config).unwrap()
);
}