2018-10-11 22:50:37 +02:00
|
|
|
use std::env;
|
2018-10-07 23:22:42 +02:00
|
|
|
use std::ffi::OsString;
|
|
|
|
use std::fs;
|
2020-03-24 03:08:19 +01:00
|
|
|
use std::io::{self, Write};
|
2018-10-17 23:02:53 +02:00
|
|
|
use std::path::PathBuf;
|
2018-10-07 23:22:42 +02:00
|
|
|
|
2020-03-21 16:48:27 +01:00
|
|
|
use crate::directories::PROJECT_DIRS;
|
2018-10-07 23:22:42 +02:00
|
|
|
|
2021-10-06 20:32:47 +02:00
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
|
|
const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "/etc";
|
|
|
|
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "C:\\ProgramData";
|
|
|
|
|
|
|
|
pub fn system_config_file() -> PathBuf {
|
|
|
|
let folder = option_env!("BAT_SYSTEM_CONFIG_PREFIX").unwrap_or(DEFAULT_SYSTEM_CONFIG_PREFIX);
|
|
|
|
let mut path = PathBuf::from(folder);
|
|
|
|
|
|
|
|
path.push("bat");
|
|
|
|
path.push("config");
|
|
|
|
|
|
|
|
path
|
|
|
|
}
|
|
|
|
|
2018-10-17 23:02:53 +02:00
|
|
|
pub fn config_file() -> PathBuf {
|
2018-11-01 16:48:56 +01:00
|
|
|
env::var("BAT_CONFIG_PATH")
|
|
|
|
.ok()
|
|
|
|
.map(PathBuf::from)
|
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<()> {
|
2020-03-24 03:08:19 +01:00
|
|
|
let config_file = config_file();
|
2021-02-27 12:21:06 +01:00
|
|
|
if config_file.is_file() {
|
2020-04-11 19:40:04 +02:00
|
|
|
println!(
|
|
|
|
"A config file already exists at: {}",
|
|
|
|
config_file.to_string_lossy()
|
|
|
|
);
|
2020-03-24 03:08:19 +01:00
|
|
|
|
2020-03-26 03:03:10 +01:00
|
|
|
print!("Overwrite? (y/N): ");
|
|
|
|
io::stdout().flush()?;
|
2020-03-24 03:08:19 +01:00
|
|
|
let mut decision = String::new();
|
2020-03-26 03:03:10 +01:00
|
|
|
io::stdin().read_line(&mut decision)?;
|
2020-03-24 03:08:19 +01:00
|
|
|
|
|
|
|
if !decision.trim().eq_ignore_ascii_case("Y") {
|
2020-03-26 03:03:10 +01:00
|
|
|
return Ok(());
|
2020-03-24 03:08:19 +01:00
|
|
|
}
|
|
|
|
} 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 => {
|
2020-04-24 08:46:01 +02:00
|
|
|
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-03-24 03:08:19 +01: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
|
2020-04-21 17:45:14 +02:00
|
|
|
# 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
|
|
|
|
2020-04-21 17:45:14 +02: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"
|
2020-03-24 03:08:19 +01:00
|
|
|
|
2020-04-21 17:45:14 +02:00
|
|
|
# Enable this to use italic text on the terminal. This is not supported on all
|
|
|
|
# terminal emulators (like tmux, by default):
|
2020-03-24 03:08:19 +01:00
|
|
|
#--italic-text=always
|
|
|
|
|
|
|
|
# Uncomment the following line to disable automatic paging:
|
|
|
|
#--paging=never
|
|
|
|
|
2020-04-21 17:45:14 +02:00
|
|
|
# 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.
|
2020-07-08 15:13:57 +02:00
|
|
|
#--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse"
|
2020-03-24 03:08:19 +01:00
|
|
|
|
2020-04-21 17:45:14 +02:00
|
|
|
# Syntax mappings: map a certain filename pattern to a language.
|
2021-09-07 06:00:44 +02:00
|
|
|
# Example 1: use the C++ syntax for Arduino .ino files
|
2020-04-21 17:45:14 +02:00
|
|
|
# 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-24 03:08:19 +01:00
|
|
|
|
2021-02-27 12:21:06 +01:00
|
|
|
fs::write(&config_file, default_config).map_err(|e| {
|
|
|
|
format!(
|
|
|
|
"Failed to create config file at '{}': {}",
|
|
|
|
config_file.to_string_lossy(),
|
|
|
|
e
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
|
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
|
|
|
|
2020-04-24 08:46:01 +02:00
|
|
|
Ok(())
|
2020-03-24 03:08:19 +01:00
|
|
|
}
|
|
|
|
|
2018-10-11 22:50:37 +02:00
|
|
|
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
|
2021-10-06 20:32:47 +02:00
|
|
|
let mut config = String::new();
|
|
|
|
|
|
|
|
if let Ok(c) = fs::read_to_string(system_config_file()) {
|
|
|
|
config.push_str(&c);
|
|
|
|
config.push('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Ok(c) = fs::read_to_string(config_file()) {
|
|
|
|
config.push_str(&c);
|
|
|
|
}
|
|
|
|
|
|
|
|
get_args_from_str(&config)
|
2018-10-07 23:22:42 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 01:30:11 +02:00
|
|
|
pub fn get_args_from_env_opts_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
|
2018-10-11 23:01:19 +02:00
|
|
|
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
|
2018-10-07 23:22:42 +02:00
|
|
|
.split('\n')
|
|
|
|
.map(|line| line.trim())
|
|
|
|
.filter(|line| !line.is_empty())
|
2019-03-08 11:46:49 +01:00
|
|
|
.filter(|line| !line.starts_with('#'))
|
2021-12-08 08:29:10 +01:00
|
|
|
.map(shell_words::split)
|
2018-10-11 22:50:37 +02:00
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
|
|
|
|
Ok(args_per_line
|
|
|
|
.iter()
|
|
|
|
.flatten()
|
2018-10-07 23:22:42 +02:00
|
|
|
.map(|line| line.into())
|
2018-10-11 22:50:37 +02:00
|
|
|
.collect())
|
2018-10-07 23:22:42 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 01:30:11 +02:00
|
|
|
pub fn get_args_from_env_vars() -> Vec<OsString> {
|
|
|
|
[
|
|
|
|
("--tabs", "BAT_TABS"),
|
|
|
|
("--theme", "BAT_THEME"),
|
|
|
|
("--pager", "BAT_PAGER"),
|
2023-08-05 21:18:38 +02:00
|
|
|
("--paging", "BAT_PAGING"),
|
2022-10-26 01:30:11 +02:00
|
|
|
("--style", "BAT_STYLE"),
|
|
|
|
]
|
|
|
|
.iter()
|
2022-10-26 04:18:03 +02:00
|
|
|
.filter_map(|(flag, key)| env::var(key).ok().map(|var| [flag.to_string(), var]))
|
2022-10-26 01:30:11 +02:00
|
|
|
.flatten()
|
2022-10-26 04:18:03 +02:00
|
|
|
.map(|a| a.into())
|
2022-10-26 01:30:11 +02:00
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2018-10-07 23:22:42 +02:00
|
|
|
#[test]
|
|
|
|
fn empty() {
|
2018-10-11 22:50:37 +02:00
|
|
|
let args = get_args_from_str("").unwrap();
|
2018-10-07 23:22:42 +02:00
|
|
|
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());
|
2018-10-07 23:22:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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() {
|
2018-10-07 23:22:42 +02:00
|
|
|
let config = "
|
|
|
|
-p
|
|
|
|
--style numbers,changes
|
|
|
|
|
|
|
|
--color=always
|
|
|
|
";
|
|
|
|
assert_eq!(
|
2018-10-11 21:39:36 +02:00
|
|
|
vec!["-p", "--style", "numbers,changes", "--color=always"],
|
2018-10-11 22:50:37 +02:00
|
|
|
get_args_from_str(config).unwrap()
|
2018-10-07 23:22:42 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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!(
|
2018-10-11 21:39:36 +02:00
|
|
|
vec!["-p", "--style", "numbers,changes", "--color=always"],
|
2018-10-11 22:50:37 +02:00
|
|
|
get_args_from_str(config).unwrap()
|
2018-10-07 23:22:42 +02:00
|
|
|
);
|
|
|
|
}
|