From 4cb5566a9c2d68006ffa97e2f8082ae3ef6c8de4 Mon Sep 17 00:00:00 2001 From: Valentin Ignatev Date: Thu, 10 Oct 2019 00:37:48 +0300 Subject: [PATCH] Add --hold CLI flag This implements --hold flag which keeps Alacritty open after its child process exits. Fixes #1165. --- CHANGELOG.md | 1 + alacritty/src/cli.rs | 204 ++++++++++++++------------- alacritty/src/main.rs | 3 +- alacritty_terminal/src/config/mod.rs | 4 + alacritty_terminal/src/event_loop.rs | 13 +- extra/alacritty.man | 3 + extra/completions/_alacritty | 1 + extra/completions/alacritty.bash | 2 +- extra/completions/alacritty.fish | 3 + 9 files changed, 130 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b48a10bc..e7a28413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bindings for ScrollToTop and ScrollToBottom actions - `ReceiveChar` key binding action to insert the key's text character - Live reload font size from config +- New CLI flag `--hold` for keeping Alacritty opened after its child process exits ### Changed diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index aabcdee3..99387a61 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -35,6 +35,7 @@ pub struct Options { pub embed: Option, pub log_level: LevelFilter, pub command: Option>, + pub hold: bool, pub working_dir: Option, pub config: Option, pub persistent_logging: bool, @@ -53,6 +54,7 @@ impl Default for Options { embed: None, log_level: LevelFilter::Warn, command: None, + hold: false, working_dir: None, config: None, persistent_logging: false, @@ -71,104 +73,106 @@ impl Options { let mut options = Options::default(); - let matches = - App::new(crate_name!()) - .version(version.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("embed").long("embed").takes_value(true).help( + let matches = App::new(crate_name!()) + .version(version.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("embed").long("embed").takes_value(true).help( "Defines the X11 window ID (as a decimal integer) to embed Alacritty within", - )) - .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(); + ), + ) + .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)"), + ) + .arg(Arg::with_name("hold").long("hold").help("Remain open after child process exits")) + .get_matches(); if matches.is_present("ref-test") { options.ref_test = true; @@ -238,6 +242,10 @@ impl Options { options.command = Some(Shell::new_with_args(command, args)); } + if matches.is_present("hold") { + options.hold = true; + } + options } @@ -254,6 +262,8 @@ impl Options { ); config.shell = self.command.or(config.shell); + config.hold = self.hold; + 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); diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index cbd00443..65e13a62 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -178,8 +178,7 @@ fn run(window_event_loop: GlutinEventLoop, config: Config) -> Result<(), // renderer and input processing. Note that access to the terminal state is // synchronized since the I/O loop updates the state, and the display // consumes it periodically. - let event_loop = - EventLoop::new(Arc::clone(&terminal), event_proxy.clone(), pty, config.debug.ref_test); + let event_loop = EventLoop::new(Arc::clone(&terminal), event_proxy.clone(), pty, &config); // The event loop channel allows write requests from the event processor // to be sent to the pty loop and ultimately written to the pty. diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs index f810b519..26432415 100644 --- a/alacritty_terminal/src/config/mod.rs +++ b/alacritty_terminal/src/config/mod.rs @@ -130,6 +130,10 @@ pub struct Config { #[serde(flatten)] pub ui_config: T, + /// Remain open after child process exits + #[serde(skip)] + pub hold: bool, + // TODO: DEPRECATED #[serde(default, deserialize_with = "failure_default")] pub render_timer: Option, diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index ed78d79e..3e762840 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -13,6 +13,7 @@ use mio::{self, Events, PollOpt, Ready}; use mio_extras::channel::{self, Receiver, Sender}; use crate::ansi; +use crate::config::Config; use crate::event::{self, Event, EventListener}; use crate::sync::FairMutex; use crate::term::Term; @@ -43,6 +44,7 @@ pub struct EventLoop { tx: Sender, terminal: Arc>>, event_proxy: U, + hold: bool, ref_test: bool, } @@ -143,11 +145,11 @@ where U: EventListener + Send + 'static, { /// Create a new event loop - pub fn new( + pub fn new( terminal: Arc>>, event_proxy: U, pty: T, - ref_test: bool, + config: &Config, ) -> EventLoop { let (tx, rx) = channel::channel(); EventLoop { @@ -157,7 +159,8 @@ where rx, terminal, event_proxy, - ref_test, + hold: config.hold, + ref_test: config.debug.ref_test, } } @@ -327,7 +330,9 @@ where #[cfg(unix)] token if token == self.pty.child_event_token() => { if let Some(tty::ChildEvent::Exited) = self.pty.next_child_event() { - self.terminal.lock().exit(); + if !self.hold { + self.terminal.lock().exit(); + } self.event_proxy.send_event(Event::Wakeup); break 'event_loop; } diff --git a/extra/alacritty.man b/extra/alacritty.man index fafb10c3..5f3bf3cb 100644 --- a/extra/alacritty.man +++ b/extra/alacritty.man @@ -14,6 +14,9 @@ However, it does allow configuration of many aspects of the terminal. \fB\-h\fR, \fB\-\-help\fR Prints help information .TP +\fB\-\-hold\fR +Remain open after child process exits +.TP \fB\-\-live\-config\-reload\fR Enable automatic config reloading .TP diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty index c2fb29c2..f074042f 100644 --- a/extra/completions/_alacritty +++ b/extra/completions/_alacritty @@ -11,6 +11,7 @@ _arguments \ "--print-events[print all events to stdout]" \ '(-v)'{-q,-qq}"[reduce the level of verbosity (min is -qq)]" \ "--ref-test[generate ref test]" \ + "--hold[remain open after child process exits]" \ '(-q)'{-v,-vv,-vvv}"[increase the level of verbosity (max is -vvv)]" \ "$ign(-)"{-V,--version}"[print version information]" \ "--class=[define the window class]:class" \ diff --git a/extra/completions/alacritty.bash b/extra/completions/alacritty.bash index d87dd215..d2abda7e 100644 --- a/extra/completions/alacritty.bash +++ b/extra/completions/alacritty.bash @@ -11,7 +11,7 @@ _alacritty() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" prevprev="${COMP_WORDS[COMP_CWORD-2]}" - opts="-h --help -V --version --live-config-reload --no-live-config-reload --persistent-logging --print-events -q -qq -v -vv -vvv --ref-test -e --command --config-file -d --dimensions --position -t --title --embed --class --working-directory" + opts="-h --help -V --version --live-config-reload --no-live-config-reload --persistent-logging --print-events -q -qq -v -vv -vvv --ref-test --hold -e --command --config-file -d --dimensions --position -t --title --embed --class --working-directory" # If `--command` or `-e` is used, stop completing for i in "${!COMP_WORDS[@]}"; do diff --git a/extra/completions/alacritty.fish b/extra/completions/alacritty.fish index 3daa3447..4fb662d3 100644 --- a/extra/completions/alacritty.fish +++ b/extra/completions/alacritty.fish @@ -37,6 +37,9 @@ complete -c alacritty \ -a '(__fish_complete_directories (commandline -ct))' \ -l "working-directory" \ -d "Start shell in specified directory" +complete -c alacritty \ + -l "hold" \ + -d "Remain open after child process exits" # Output complete \