summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiklas Claesson <nicke.claesson@gmail.com>2017-05-29 02:42:36 +0200
committerJoe Wilm <jwilm@users.noreply.github.com>2017-05-28 17:42:36 -0700
commit81116fb8a4f91f28b5751827e7bcda22f6fcbaf0 (patch)
treeb9b446b5f8ed18c31189eb45f24f02ffe767657f /src
parent13eac6b673a089afe6f15adb73d6812916c73f73 (diff)
Add config file as cli option (#576)
* Parse cli arguments before configuration file Parsing the cli arguments before the configuration file allows `--help` and `--version` to be used even if the configuration file is broken. * Add configuration file to command line arguments This commit adds a new command line flag `--config-file` to override the default configuration file location. If the specified file is unavailable, Alacritty will quit instead of generating a fallback. If the specified file is invalid, i.e. /dev/null, the compiled in defaults will be loaded instead.
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs17
-rw-r--r--src/config.rs52
-rw-r--r--src/main.rs49
3 files changed, 74 insertions, 44 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 4a455cf4..e7783807 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -15,7 +15,8 @@ extern crate log;
use clap::{Arg, App};
use index::{Line, Column};
use config::{Dimensions, Shell};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
+use std::borrow::Cow;
const DEFAULT_TITLE: &'static str = "Alacritty";
@@ -28,6 +29,7 @@ pub struct Options {
pub log_level: log::LogLevelFilter,
pub command: Option<Shell<'static>>,
pub working_dir: Option<PathBuf>,
+ pub config: Option<PathBuf>,
}
impl Default for Options {
@@ -40,6 +42,7 @@ impl Default for Options {
log_level: log::LogLevelFilter::Warn,
command: None,
working_dir: None,
+ config: None,
}
}
}
@@ -82,6 +85,10 @@ impl Options {
.long("working-directory")
.takes_value(true)
.help("Start the shell in the specified working directory"))
+ .arg(Arg::with_name("config-file")
+ .long("config-file")
+ .takes_value(true)
+ .help("Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.yml]"))
.arg(Arg::with_name("command")
.short("e")
.multiple(true)
@@ -128,6 +135,10 @@ impl Options {
options.working_dir = Some(PathBuf::from(dir.to_string()));
}
+ if let Some(path) = matches.value_of("config-file") {
+ options.config = Some(PathBuf::from(path.to_string()));
+ }
+
if let Some(mut args) = matches.values_of("command") {
// The following unwrap is guaranteed to succeed.
// If 'command' exists it must also have a first item since
@@ -147,4 +158,8 @@ impl Options {
pub fn command(&self) -> Option<&Shell> {
self.command.as_ref()
}
+
+ pub fn config_path(&self) -> Option<Cow<Path>> {
+ self.config.as_ref().map(|p| Cow::Borrowed(p.as_path()))
+ }
}
diff --git a/src/config.rs b/src/config.rs
index ada6f8d1..5142b9b0 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -721,6 +721,9 @@ pub enum Error {
/// Config file not found
NotFound,
+ /// Config file empty
+ Empty,
+
/// Couldn't read $HOME environment variable
ReadingEnvHome(env::VarError),
@@ -923,6 +926,7 @@ impl ::std::error::Error for Error {
fn cause(&self) -> Option<&::std::error::Error> {
match *self {
Error::NotFound => None,
+ Error::Empty => None,
Error::ReadingEnvHome(ref err) => Some(err),
Error::Io(ref err) => Some(err),
Error::Yaml(ref err) => Some(err),
@@ -932,6 +936,7 @@ impl ::std::error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::NotFound => "could not locate config file",
+ Error::Empty => "empty config file",
Error::ReadingEnvHome(ref err) => err.description(),
Error::Io(ref err) => err.description(),
Error::Yaml(ref err) => err.description(),
@@ -943,6 +948,7 @@ impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error::NotFound => write!(f, "{}", ::std::error::Error::description(self)),
+ Error::Empty => write!(f, "{}", ::std::error::Error::description(self)),
Error::ReadingEnvHome(ref err) => {
write!(f, "could not read $HOME environment variable: {}", err)
},
@@ -978,19 +984,16 @@ impl From<serde_yaml::Error> for Error {
pub type Result<T> = ::std::result::Result<T, Error>;
impl Config {
- /// Attempt to load the config file
- ///
- /// The config file is loaded from the first file it finds in this list of paths
+ /// Get the location of the first found default config file paths
+ /// according to the following order:
///
/// 1. $XDG_CONFIG_HOME/alacritty/alacritty.yml
/// 2. $XDG_CONFIG_HOME/alacritty.yml
/// 3. $HOME/.config/alacritty/alacritty.yml
/// 4. $HOME/.alacritty.yml
- pub fn load() -> Result<Config> {
- let home = env::var("HOME")?;
-
+ pub fn installed_config() -> Option<Cow<'static, Path>> {
// Try using XDG location by default
- let path = ::xdg::BaseDirectories::with_prefix("alacritty")
+ ::xdg::BaseDirectories::with_prefix("alacritty")
.ok()
.and_then(|xdg| xdg.find_config_file("alacritty.yml"))
.or_else(|| {
@@ -999,27 +1002,29 @@ impl Config {
})
})
.or_else(|| {
- // Fallback path: $HOME/.config/alacritty/alacritty.yml
- let fallback = PathBuf::from(&home).join(".config/alacritty/alacritty.yml");
- match fallback.exists() {
- true => Some(fallback),
- false => None
+ if let Ok(home) = env::var("HOME") {
+ // Fallback path: $HOME/.config/alacritty/alacritty.yml
+ let fallback = PathBuf::from(&home).join(".config/alacritty/alacritty.yml");
+ if fallback.exists() {
+ return Some(fallback);
+ }
+ // Fallback path: $HOME/.alacritty.yml
+ let fallback = PathBuf::from(&home).join(".alacritty.yml");
+ if fallback.exists() {
+ return Some(fallback);
+ }
}
+ None
})
- .unwrap_or_else(|| {
- // Fallback path: $HOME/.alacritty.yml
- PathBuf::from(&home).join(".alacritty.yml")
- });
-
- Config::load_from(path)
+ .map(|path| path.into())
}
- pub fn write_defaults() -> io::Result<PathBuf> {
+ pub fn write_defaults() -> io::Result<Cow<'static, Path>> {
let path = ::xdg::BaseDirectories::with_prefix("alacritty")
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, ::std::error::Error::description(&err)))
.and_then(|p| p.place_config_file("alacritty.yml"))?;
File::create(&path)?.write_all(DEFAULT_ALACRITTY_CONFIG.as_bytes())?;
- Ok(path)
+ Ok(path.into())
}
/// Get list of colors
@@ -1116,7 +1121,7 @@ impl Config {
self.hide_cursor_when_typing
}
- fn load_from<P: Into<PathBuf>>(path: P) -> Result<Config> {
+ pub fn load_from<P: Into<PathBuf>>(path: P) -> Result<Config> {
let path = path.into();
let raw = Config::read_file(path.as_path())?;
let mut config: Config = serde_yaml::from_str(&raw)?;
@@ -1129,6 +1134,9 @@ impl Config {
let mut f = fs::File::open(path)?;
let mut contents = String::new();
f.read_to_string(&mut contents)?;
+ if contents.len() == 0 {
+ return Err(Error::Empty);
+ }
Ok(contents)
}
@@ -1427,7 +1435,7 @@ impl Monitor {
// Reload file
path.map(|path| {
if path == config_path {
- match Config::load() {
+ match Config::load_from(path) {
Ok(config) => {
let _ = config_tx.send(config);
handler.on_config_reload();
diff --git a/src/main.rs b/src/main.rs
index b7db4dec..f4ee72b6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,28 +37,9 @@ use alacritty::tty::{self, process_should_exit};
use alacritty::util::fmt::Red;
fn main() {
-
- // Load configuration
- let config = Config::load().unwrap_or_else(|err| {
- match err {
- // Use default config when not found
- config::Error::NotFound => {
- match Config::write_defaults() {
- Ok(path) => err_println!("Config file not found; write defaults config to {:?}", path),
- Err(err) => err_println!("Write defaults config failure: {}", err)
- }
-
- Config::load().unwrap()
- },
-
- // If there's a problem with the config file, print an error
- // and exit.
- _ => die!("{}", err),
- }
- });
-
- // Load command line options
+ // Load command line options and config
let options = cli::Options::load();
+ let config = load_config(&options);
// Run alacritty
if let Err(err) = run(config, options) {
@@ -68,6 +49,32 @@ fn main() {
info!("Goodbye.");
}
+/// Load configuration
+///
+/// If a configuration file is given as a command line argument we don't
+/// generate a default file. If an empty configuration file is given, i.e.
+/// /dev/null, we load the compiled-in defaults.
+fn load_config(options: &cli::Options) -> Config {
+ let config_path = options.config_path()
+ .or_else(|| Config::installed_config())
+ .unwrap_or_else(|| {
+ Config::write_defaults()
+ .unwrap_or_else(|err| die!("Write defaults config failure: {}", err))
+ });
+
+ Config::load_from(&*config_path).unwrap_or_else(|err| {
+ match err {
+ config::Error::NotFound => {
+ die!("Config file not found at: {}", config_path.display());
+ },
+ config::Error::Empty => {
+ err_println!("Empty config; Loading defaults");
+ Config::default()
+ },
+ _ => die!("{}", err),
+ }
+ })
+}
/// Run Alacritty
///