aboutsummaryrefslogtreecommitdiff
path: root/alacritty
diff options
context:
space:
mode:
authorChristian Duerr <chrisduerr@users.noreply.github.com>2019-05-10 11:36:16 +0000
committerGitHub <noreply@github.com>2019-05-10 11:36:16 +0000
commit5d173f6df3b20308eb318cef4b58147b2197d5f9 (patch)
tree05638837bef25d65a818253814331a4f429f57ac /alacritty
parent7738c52ed4eb177ead9f43d14207ecb129cfe617 (diff)
downloadr-alacritty-5d173f6df3b20308eb318cef4b58147b2197d5f9.tar.gz
r-alacritty-5d173f6df3b20308eb318cef4b58147b2197d5f9.tar.bz2
r-alacritty-5d173f6df3b20308eb318cef4b58147b2197d5f9.zip
Refactor config parsing files
This is a large refactor of the config parsing structure, attempting to reduce the size of the file a bit by splitting it up into different modules with more specific purposes. This also fixes #2279.
Diffstat (limited to 'alacritty')
-rw-r--r--alacritty/Cargo.toml6
-rw-r--r--alacritty/build.rs3
-rw-r--r--alacritty/src/cli.rs417
-rw-r--r--alacritty/src/config.rs210
-rw-r--r--alacritty/src/logging.rs18
-rw-r--r--alacritty/src/main.rs52
6 files changed, 511 insertions, 195 deletions
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index 742492fe..7a3f5f89 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -15,11 +15,15 @@ log = "0.4"
time = "0.1.40"
env_logger = "0.6.0"
crossbeam-channel = "0.3.8"
+serde_yaml = "0.8"
[build-dependencies]
rustc_tools_util = "0.1"
-[target.'cfg(target_os = "macos")'.dependencies]
+[target.'cfg(not(windows))'.dependencies]
+xdg = "2"
+
+[target.'cfg(any(target_os = "macos", windows))'.dependencies]
dirs = "1.0.2"
[target.'cfg(windows)'.dependencies]
diff --git a/alacritty/build.rs b/alacritty/build.rs
index 2a1ce9e0..1ad0def4 100644
--- a/alacritty/build.rs
+++ b/alacritty/build.rs
@@ -13,7 +13,6 @@
// limitations under the License.
fn main() {
- let hash = rustc_tools_util::get_commit_hash()
- .expect("couldn't get commit hash");
+ let hash = rustc_tools_util::get_commit_hash().expect("couldn't get commit hash");
println!("cargo:rustc-env=GIT_HASH={}", hash);
}
diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs
index 90906218..3ecea644 100644
--- a/alacritty/src/cli.rs
+++ b/alacritty/src/cli.rs
@@ -12,184 +12,293 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use std::path::PathBuf;
+use std::borrow::Cow;
+use std::cmp::max;
+use std::path::{Path, PathBuf};
-use ::log;
use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
+use log::{self, LevelFilter};
-use alacritty_terminal::config::{Options, Delta, Dimensions, Shell};
+use alacritty_terminal::config::{Config, Delta, Dimensions, Shell};
use alacritty_terminal::index::{Column, Line};
use alacritty_terminal::window::DEFAULT_NAME;
-/// Build `Options` from command line arguments.
-pub fn options() -> Options {
- let mut options = Options::default();
-
- let version_string = format!("{} ({})",
- crate_version!(),
- env!("GIT_HASH"));
-
- let matches = App::new(crate_name!())
- .version(version_string.as_str())
- .author(crate_authors!("\n"))
- .about(crate_description!())
- .arg(Arg::with_name("ref-test").long("ref-test").help("Generates ref test"))
- .arg(
- Arg::with_name("live-config-reload")
- .long("live-config-reload")
- .help("Enable automatic config reloading"),
- )
- .arg(
- Arg::with_name("no-live-config-reload")
- .long("no-live-config-reload")
- .help("Disable automatic config reloading")
- .conflicts_with("live-config-reload"),
- )
- .arg(
- Arg::with_name("print-events")
- .long("print-events")
- .help("Print all events to stdout"),
- )
- .arg(
- Arg::with_name("persistent-logging")
- .long("persistent-logging")
- .help("Keep the log file after quitting Alacritty"),
- )
- .arg(
- Arg::with_name("dimensions")
- .long("dimensions")
- .short("d")
- .value_names(&["columns", "lines"])
- .help(
- "Defines the window dimensions. Falls back to size specified by window \
- manager if set to 0x0 [default: 0x0]",
- ),
- )
- .arg(
- Arg::with_name("position")
- .long("position")
- .allow_hyphen_values(true)
- .value_names(&["x-pos", "y-pos"])
- .help(
- "Defines the window position. Falls back to position specified by window \
- manager if unset [default: unset]",
- ),
- )
- .arg(
- Arg::with_name("title")
- .long("title")
- .short("t")
- .takes_value(true)
- .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME)),
- )
- .arg(
- Arg::with_name("class")
- .long("class")
- .takes_value(true)
- .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME)),
- )
- .arg(
- Arg::with_name("q")
- .short("q")
- .multiple(true)
- .conflicts_with("v")
- .help("Reduces the level of verbosity (the min level is -qq)"),
- )
- .arg(
- Arg::with_name("v")
- .short("v")
- .multiple(true)
- .conflicts_with("q")
- .help("Increases the level of verbosity (the max level is -vvv)"),
- )
- .arg(
- Arg::with_name("working-directory")
- .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")
- .long("command")
- .short("e")
- .multiple(true)
- .takes_value(true)
- .min_values(1)
- .allow_hyphen_values(true)
- .help("Command and args to execute (must be last argument)"),
- )
- .get_matches();
-
- if matches.is_present("ref-test") {
- options.ref_test = true;
- }
+/// Options specified on the command line
+pub struct Options {
+ pub live_config_reload: Option<bool>,
+ pub print_events: bool,
+ pub ref_test: bool,
+ pub dimensions: Option<Dimensions>,
+ pub position: Option<Delta<i32>>,
+ pub title: Option<String>,
+ pub class: Option<String>,
+ pub log_level: LevelFilter,
+ pub command: Option<Shell<'static>>,
+ pub working_dir: Option<PathBuf>,
+ pub config: Option<PathBuf>,
+ pub persistent_logging: bool,
+}
- if matches.is_present("print-events") {
- options.print_events = true;
+impl Default for Options {
+ fn default() -> Options {
+ Options {
+ live_config_reload: None,
+ print_events: false,
+ ref_test: false,
+ dimensions: None,
+ position: None,
+ title: None,
+ class: None,
+ log_level: LevelFilter::Warn,
+ command: None,
+ working_dir: None,
+ config: None,
+ persistent_logging: false,
+ }
}
+}
- if matches.is_present("live-config-reload") {
- options.live_config_reload = Some(true);
- } else if matches.is_present("no-live-config-reload") {
- options.live_config_reload = Some(false);
- }
+impl Options {
+ /// Build `Options` from command line arguments.
+ pub fn new() -> Self {
+ let mut options = Options::default();
- if matches.is_present("persistent-logging") {
- options.persistent_logging = true;
- }
+ let version_string = format!("{} ({})", crate_version!(), env!("GIT_HASH"));
- if let Some(mut dimensions) = matches.values_of("dimensions") {
- let width = dimensions.next().map(|w| w.parse().map(Column));
- let height = dimensions.next().map(|h| h.parse().map(Line));
- if let (Some(Ok(width)), Some(Ok(height))) = (width, height) {
- options.dimensions = Some(Dimensions::new(width, height));
+ let matches = App::new(crate_name!())
+ .version(version_string.as_str())
+ .author(crate_authors!("\n"))
+ .about(crate_description!())
+ .arg(Arg::with_name("ref-test").long("ref-test").help("Generates ref test"))
+ .arg(
+ Arg::with_name("live-config-reload")
+ .long("live-config-reload")
+ .help("Enable automatic config reloading"),
+ )
+ .arg(
+ Arg::with_name("no-live-config-reload")
+ .long("no-live-config-reload")
+ .help("Disable automatic config reloading")
+ .conflicts_with("live-config-reload"),
+ )
+ .arg(
+ Arg::with_name("print-events")
+ .long("print-events")
+ .help("Print all events to stdout"),
+ )
+ .arg(
+ Arg::with_name("persistent-logging")
+ .long("persistent-logging")
+ .help("Keep the log file after quitting Alacritty"),
+ )
+ .arg(
+ Arg::with_name("dimensions")
+ .long("dimensions")
+ .short("d")
+ .value_names(&["columns", "lines"])
+ .help(
+ "Defines the window dimensions. Falls back to size specified by window \
+ manager if set to 0x0 [default: 0x0]",
+ ),
+ )
+ .arg(
+ Arg::with_name("position")
+ .long("position")
+ .allow_hyphen_values(true)
+ .value_names(&["x-pos", "y-pos"])
+ .help(
+ "Defines the window position. Falls back to position specified by window \
+ manager if unset [default: unset]",
+ ),
+ )
+ .arg(
+ Arg::with_name("title")
+ .long("title")
+ .short("t")
+ .takes_value(true)
+ .help(&format!("Defines the window title [default: {}]", DEFAULT_NAME)),
+ )
+ .arg(
+ Arg::with_name("class")
+ .long("class")
+ .takes_value(true)
+ .help(&format!("Defines window class on Linux [default: {}]", DEFAULT_NAME)),
+ )
+ .arg(
+ Arg::with_name("q")
+ .short("q")
+ .multiple(true)
+ .conflicts_with("v")
+ .help("Reduces the level of verbosity (the min level is -qq)"),
+ )
+ .arg(
+ Arg::with_name("v")
+ .short("v")
+ .multiple(true)
+ .conflicts_with("q")
+ .help("Increases the level of verbosity (the max level is -vvv)"),
+ )
+ .arg(
+ Arg::with_name("working-directory")
+ .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")
+ .long("command")
+ .short("e")
+ .multiple(true)
+ .takes_value(true)
+ .min_values(1)
+ .allow_hyphen_values(true)
+ .help("Command and args to execute (must be last argument)"),
+ )
+ .get_matches();
+
+ if matches.is_present("ref-test") {
+ options.ref_test = true;
}
- }
- if let Some(mut position) = matches.values_of("position") {
- let x = position.next().map(str::parse);
- let y = position.next().map(str::parse);
- if let (Some(Ok(x)), Some(Ok(y))) = (x, y) {
- options.position = Some(Delta { x, y });
+ if matches.is_present("print-events") {
+ options.print_events = true;
+ }
+
+ if matches.is_present("live-config-reload") {
+ options.live_config_reload = Some(true);
+ } else if matches.is_present("no-live-config-reload") {
+ options.live_config_reload = Some(false);
}
- }
- options.class = matches.value_of("class").map(ToOwned::to_owned);
- options.title = matches.value_of("title").map(ToOwned::to_owned);
+ if matches.is_present("persistent-logging") {
+ options.persistent_logging = true;
+ }
+
+ if let Some(mut dimensions) = matches.values_of("dimensions") {
+ let width = dimensions.next().map(|w| w.parse().map(Column));
+ let height = dimensions.next().map(|h| h.parse().map(Line));
+ if let (Some(Ok(width)), Some(Ok(height))) = (width, height) {
+ options.dimensions = Some(Dimensions::new(width, height));
+ }
+ }
+
+ if let Some(mut position) = matches.values_of("position") {
+ let x = position.next().map(str::parse);
+ let y = position.next().map(str::parse);
+ if let (Some(Ok(x)), Some(Ok(y))) = (x, y) {
+ options.position = Some(Delta { x, y });
+ }
+ }
+
+ options.class = matches.value_of("class").map(ToOwned::to_owned);
+ options.title = matches.value_of("title").map(ToOwned::to_owned);
- match matches.occurrences_of("q") {
- 0 => {},
- 1 => options.log_level = log::LevelFilter::Error,
- 2 | _ => options.log_level = log::LevelFilter::Off,
+ match matches.occurrences_of("q") {
+ 0 => {},
+ 1 => options.log_level = LevelFilter::Error,
+ 2 | _ => options.log_level = LevelFilter::Off,
+ }
+
+ match matches.occurrences_of("v") {
+ 0 if !options.print_events => options.log_level = LevelFilter::Warn,
+ 0 | 1 => options.log_level = LevelFilter::Info,
+ 2 => options.log_level = LevelFilter::Debug,
+ 3 | _ => options.log_level = LevelFilter::Trace,
+ }
+
+ if let Some(dir) = matches.value_of("working-directory") {
+ 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
+ // Arg::min_values(1) is set.
+ let command = String::from(args.next().unwrap());
+ let args = args.map(String::from).collect();
+ options.command = Some(Shell::new_with_args(command, args));
+ }
+
+ options
}
- match matches.occurrences_of("v") {
- 0 if !options.print_events => {},
- 0 | 1 => options.log_level = log::LevelFilter::Info,
- 2 => options.log_level = log::LevelFilter::Debug,
- 3 | _ => options.log_level = log::LevelFilter::Trace,
+ pub fn config_path(&self) -> Option<Cow<'_, Path>> {
+ self.config.as_ref().map(|p| Cow::Borrowed(p.as_path()))
}
- if let Some(dir) = matches.value_of("working-directory") {
- options.working_dir = Some(PathBuf::from(dir.to_string()));
+ pub fn into_config(self, mut config: Config) -> Config {
+ config.set_live_config_reload(
+ self.live_config_reload.unwrap_or_else(|| config.live_config_reload()),
+ );
+ config.set_working_directory(
+ self.working_dir.or_else(|| config.working_directory().to_owned()),
+ );
+ config.shell = self.command.or(config.shell);
+
+ config.window.dimensions = self.dimensions.unwrap_or(config.window.dimensions);
+ config.window.position = self.position.or(config.window.position);
+ config.window.title = self.title.or(config.window.title);
+ config.window.class = self.class.or(config.window.class);
+
+ config.set_dynamic_title(config.dynamic_title() && config.window.title.is_none());
+
+ config.debug.print_events = self.print_events || config.debug.print_events;
+ config.debug.log_level = max(config.debug.log_level, self.log_level);
+ config.debug.ref_test = self.ref_test || config.debug.ref_test;
+
+ if config.debug.print_events {
+ config.debug.log_level = max(config.debug.log_level, LevelFilter::Info);
+ }
+
+ config
}
+}
+
+#[cfg(test)]
+mod test {
+ use alacritty_terminal::config::{Config, DEFAULT_ALACRITTY_CONFIG};
+
+ use crate::cli::Options;
+
+ #[test]
+ fn dynamic_title_ignoring_options_by_default() {
+ let config: Config =
+ ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config");
+ let old_dynamic_title = config.dynamic_title();
+
+ let config = Options::default().into_config(config);
- if let Some(path) = matches.value_of("config-file") {
- options.config = Some(PathBuf::from(path.to_string()));
+ assert_eq!(old_dynamic_title, config.dynamic_title());
}
- 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
- // Arg::min_values(1) is set.
- let command = String::from(args.next().unwrap());
- let args = args.map(String::from).collect();
- options.command = Some(Shell::new_with_args(command, args));
+ #[test]
+ fn dynamic_title_overridden_by_options() {
+ let config: Config =
+ ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config");
+
+ let mut options = Options::default();
+ options.title = Some("foo".to_owned());
+ let config = options.into_config(config);
+
+ assert!(!config.dynamic_title());
}
- options
+ #[test]
+ fn dynamic_title_overridden_by_config() {
+ let mut config: Config =
+ ::serde_yaml::from_str(DEFAULT_ALACRITTY_CONFIG).expect("deserialize config");
+
+ config.window.title = Some("foo".to_owned());
+ let config = Options::default().into_config(config);
+
+ assert!(!config.dynamic_title());
+ }
}
diff --git a/alacritty/src/config.rs b/alacritty/src/config.rs
new file mode 100644
index 00000000..ea487ecd
--- /dev/null
+++ b/alacritty/src/config.rs
@@ -0,0 +1,210 @@
+use std::borrow::Cow;
+use std::env;
+use std::fs::File;
+use std::io::{self, Read, Write};
+use std::path::{Path, PathBuf};
+
+#[cfg(windows)]
+use dirs;
+use log::{error, warn};
+use serde_yaml;
+#[cfg(not(windows))]
+use xdg;
+
+use alacritty_terminal::config::{Config, DEFAULT_ALACRITTY_CONFIG};
+
+pub const SOURCE_FILE_PATH: &str = file!();
+
+/// Result from config loading
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+/// Errors occurring during config loading
+#[derive(Debug)]
+pub enum Error {
+ /// Config file not found
+ NotFound,
+
+ /// Couldn't read $HOME environment variable
+ ReadingEnvHome(env::VarError),
+
+ /// io error reading file
+ Io(io::Error),
+
+ /// Not valid yaml or missing parameters
+ Yaml(serde_yaml::Error),
+}
+
+impl ::std::error::Error for Error {
+ fn cause(&self) -> Option<&dyn (::std::error::Error)> {
+ match *self {
+ Error::NotFound => None,
+ Error::ReadingEnvHome(ref err) => Some(err),
+ Error::Io(ref err) => Some(err),
+ Error::Yaml(ref err) => Some(err),
+ }
+ }
+
+ fn description(&self) -> &str {
+ match *self {
+ Error::NotFound => "Couldn't locate config file",
+ Error::ReadingEnvHome(ref err) => err.description(),
+ Error::Io(ref err) => err.description(),
+ Error::Yaml(ref err) => err.description(),
+ }
+ }
+}
+
+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::ReadingEnvHome(ref err) => {
+ write!(f, "Couldn't read $HOME environment variable: {}", err)
+ },
+ Error::Io(ref err) => write!(f, "Error reading config file: {}", err),
+ Error::Yaml(ref err) => write!(f, "Problem with config: {}", err),
+ }
+ }
+}
+
+impl From<env::VarError> for Error {
+ fn from(val: env::VarError) -> Error {
+ Error::ReadingEnvHome(val)
+ }
+}
+
+impl From<io::Error> for Error {
+ fn from(val: io::Error) -> Error {
+ if val.kind() == io::ErrorKind::NotFound {
+ Error::NotFound
+ } else {
+ Error::Io(val)
+ }
+ }
+}
+
+impl From<serde_yaml::Error> for Error {
+ fn from(val: serde_yaml::Error) -> Error {
+ Error::Yaml(val)
+ }
+}
+
+/// 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
+#[cfg(not(windows))]
+pub fn installed_config<'a>() -> Option<Cow<'a, Path>> {
+ // Try using XDG location by default
+ xdg::BaseDirectories::with_prefix("alacritty")
+ .ok()
+ .and_then(|xdg| xdg.find_config_file("alacritty.yml"))
+ .or_else(|| {
+ xdg::BaseDirectories::new()
+ .ok()
+ .and_then(|fallback| fallback.find_config_file("alacritty.yml"))
+ })
+ .or_else(|| {
+ 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
+ })
+ .map(Into::into)
+}
+
+#[cfg(windows)]
+pub fn installed_config<'a>() -> Option<Cow<'a, Path>> {
+ dirs::config_dir()
+ .map(|path| path.join("alacritty\\alacritty.yml"))
+ .filter(|new| new.exists())
+ .map(Cow::from)
+}
+
+#[cfg(not(windows))]
+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, err.to_string().as_str()))
+ .and_then(|p| p.place_config_file("alacritty.yml"))?;
+
+ File::create(&path)?.write_all(DEFAULT_ALACRITTY_CONFIG.as_bytes())?;
+
+ Ok(path.into())
+}
+
+#[cfg(windows)]
+pub fn write_defaults() -> io::Result<Cow<'static, Path>> {
+ let mut path = dirs::config_dir().ok_or_else(|| {
+ io::Error::new(io::ErrorKind::NotFound, "Couldn't find profile directory")
+ })?;
+
+ path = path.join("alacritty/alacritty.yml");
+
+ std::fs::create_dir_all(path.parent().unwrap())?;
+
+ File::create(&path)?.write_all(DEFAULT_ALACRITTY_CONFIG.as_bytes())?;
+
+ Ok(path.into())
+}
+
+pub fn load_from(path: PathBuf) -> Config {
+ let mut config = reload_from(&path).unwrap_or_else(|_| Config::default());
+ config.config_path = Some(path);
+ config
+}
+
+pub fn reload_from(path: &PathBuf) -> Result<Config> {
+ match read_config(path) {
+ Ok(config) => Ok(config),
+ Err(err) => {
+ error!("Unable to load config {:?}: {}", path, err);
+ Err(err)
+ },
+ }
+}
+
+fn read_config(path: &PathBuf) -> Result<Config> {
+ let mut contents = String::new();
+ File::open(path)?.read_to_string(&mut contents)?;
+
+ // Prevent parsing error with empty string
+ if contents.is_empty() {
+ return Ok(Config::default());
+ }
+
+ let config = serde_yaml::from_str(&contents)?;
+
+ print_deprecation_warnings(&config);
+
+ Ok(config)
+}
+
+fn print_deprecation_warnings(config: &Config) {
+ if config.window.start_maximized.is_some() {
+ warn!(
+ "Config window.start_maximized is deprecated; please use window.startup_mode instead"
+ );
+ }
+
+ if config.render_timer.is_some() {
+ warn!("Config render_timer is deprecated; please use debug.render_timer instead");
+ }
+
+ if config.persistent_logging.is_some() {
+ warn!(
+ "Config persistent_logging is deprecated; please use debug.persistent_logging instead"
+ );
+ }
+}
diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs
index 0b67440d..d4cb70c5 100644
--- a/alacritty/src/logging.rs
+++ b/alacritty/src/logging.rs
@@ -29,23 +29,26 @@ use crossbeam_channel::Sender;
use log::{self, Level};
use time;
-use alacritty_terminal::config::Options;
use alacritty_terminal::message_bar::Message;
use alacritty_terminal::term::color;
+use crate::cli::Options;
+
const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG";
pub fn initialize(
options: &Options,
message_tx: Sender<Message>,
) -> Result<Option<PathBuf>, log::SetLoggerError> {
+ log::set_max_level(options.log_level);
+
// Use env_logger if RUST_LOG environment variable is defined. Otherwise,
// use the alacritty-only logger.
if ::std::env::var("RUST_LOG").is_ok() {
::env_logger::try_init()?;
Ok(None)
} else {
- let logger = Logger::new(options.log_level, message_tx);
+ let logger = Logger::new(message_tx);
let path = logger.file_path();
log::set_boxed_logger(Box::new(logger))?;
Ok(path)
@@ -53,22 +56,17 @@ pub fn initialize(
}
pub struct Logger {
- level: log::LevelFilter,
logfile: Mutex<OnDemandLogFile>,
stdout: Mutex<LineWriter<Stdout>>,
message_tx: Sender<Message>,
}
impl Logger {
- // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734
- #[allow(clippy::new_ret_no_self)]
- fn new(level: log::LevelFilter, message_tx: Sender<Message>) -> Self {
- log::set_max_level(level);
-
+ fn new(message_tx: Sender<Message>) -> Self {
let logfile = Mutex::new(OnDemandLogFile::new());
let stdout = Mutex::new(LineWriter::new(io::stdout()));
- Logger { level, logfile, stdout, message_tx }
+ Logger { logfile, stdout, message_tx }
}
fn file_path(&self) -> Option<PathBuf> {
@@ -82,7 +80,7 @@ impl Logger {
impl log::Log for Logger {
fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
- metadata.level() <= self.level
+ metadata.level() <= log::max_level()
}
fn log(&self, record: &log::Record<'_>) {
diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs
index 24f2d6c9..54533d72 100644
--- a/alacritty/src/main.rs
+++ b/alacritty/src/main.rs
@@ -42,7 +42,7 @@ use std::env;
use std::os::unix::io::AsRawFd;
use alacritty_terminal::clipboard::Clipboard;
-use alacritty_terminal::config::{self, Config, Options, Monitor};
+use alacritty_terminal::config::{Config, Monitor};
use alacritty_terminal::display::Display;
use alacritty_terminal::event_loop::{self, EventLoop, Msg};
#[cfg(target_os = "macos")]
@@ -56,8 +56,11 @@ use alacritty_terminal::util::fmt::Red;
use alacritty_terminal::{die, event};
mod cli;
+mod config;
mod logging;
+use crate::cli::Options;
+
fn main() {
panic::attach_handler();
@@ -70,7 +73,7 @@ fn main() {
}
// Load command line options
- let options = cli::options();
+ let options = Options::new();
// Setup storage for message UI
let message_buffer = MessageBuffer::new();
@@ -83,15 +86,19 @@ fn main() {
// If the file is a command line argument, we won't write a generated default file
let config_path = options
.config_path()
- .or_else(Config::installed_config)
- .or_else(|| Config::write_defaults().ok())
+ .or_else(config::installed_config)
+ .or_else(|| config::write_defaults().ok())
.map(|path| path.to_path_buf());
let config = if let Some(path) = config_path {
- Config::load_from(path).update_dynamic_title(&options)
+ config::load_from(path)
} else {
error!("Unable to write the default config");
Config::default()
};
+ let config = options.into_config(config);
+
+ // Update the log level from config
+ log::set_max_level(config.debug.log_level);
// Switch to home directory
#[cfg(target_os = "macos")]
@@ -101,10 +108,10 @@ fn main() {
locale::set_locale_environment();
// Store if log file should be deleted before moving config
- let persistent_logging = options.persistent_logging || config.persistent_logging();
+ let persistent_logging = config.persistent_logging();
// Run alacritty
- if let Err(err) = run(config, &options, message_buffer) {
+ if let Err(err) = run(config, message_buffer) {
die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err));
}
@@ -120,13 +127,9 @@ fn main() {
///
/// Creates a window, the terminal state, pty, I/O event loop, input processor,
/// config change monitor, and runs the main display loop.
-fn run(
- mut config: Config,
- options: &Options,
- message_buffer: MessageBuffer,
-) -> Result<(), Box<dyn Error>> {
+fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Error>> {
info!("Welcome to Alacritty");
- if let Some(config_path) = config.path() {
+ if let Some(config_path) = &config.config_path {
info!("Configuration loaded from {:?}", config_path.display());
};
@@ -136,7 +139,7 @@ fn run(
// Create a display.
//
// The display manages a window and can draw the terminal
- let mut display = Display::new(&config, options)?;
+ let mut display = Display::new(&config)?;
info!("PTY Dimensions: {:?} x {:?}", display.size().lines(), display.size().cols());
@@ -162,7 +165,7 @@ fn run(
// The pty forks a process to run the shell on the slave side of the
// pseudoterminal. A file descriptor for the master side is retained for
// reading/writing to the shell.
- let pty = tty::new(&config, options, &display.size(), window_id);
+ let pty = tty::new(&config, &display.size(), window_id);
// Get a reference to something that we can resize
//
@@ -181,7 +184,7 @@ fn run(
// synchronized since the I/O loop updates the state, and the display
// consumes it periodically.
let event_loop =
- EventLoop::new(Arc::clone(&terminal), display.notifier(), pty, options.ref_test);
+ EventLoop::new(Arc::clone(&terminal), display.notifier(), pty, config.debug.ref_test);
// The event loop channel allows write requests from the event processor
// to be sent to the loop and ultimately written to the pty.
@@ -193,9 +196,7 @@ fn run(
let mut processor = event::Processor::new(
event_loop::Notifier(event_loop.channel()),
display.resize_channel(),
- options,
&config,
- options.ref_test,
display.size().to_owned(),
);
@@ -203,14 +204,10 @@ fn run(
//
// The monitor watches the config file for changes and reloads it. Pending
// config changes are processed in the main loop.
- let config_monitor = match (options.live_config_reload, config.live_config_reload()) {
- // Start monitor if CLI flag says yes
- (Some(true), _) |
- // Or if no CLI flag was passed and the config says yes
- (None, true) => config.path()
- .map(|path| config::Monitor::new(path, display.notifier())),
- // Otherwise, don't start the monitor
- _ => None,
+ let config_monitor = if config.live_config_reload() {
+ config.config_path.as_ref().map(|path| Monitor::new(path, display.notifier()))
+ } else {
+ None
};
// Kick off the I/O thread
@@ -228,8 +225,7 @@ fn run(
// Clear old config messages from bar
terminal_lock.message_buffer_mut().remove_topic(config::SOURCE_FILE_PATH);
- if let Ok(new_config) = Config::reload_from(path) {
- config = new_config.update_dynamic_title(options);
+ if let Ok(config) = config::reload_from(path) {
display.update_config(&config);
processor.update_config(&config);
terminal_lock.update_config(&config);