1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2024-11-25 14:05:41 -05:00

Add key/mouse action for spawning new Alacritty instances

This commit is contained in:
Carlos Tuñón 2019-01-05 15:47:12 -05:00 committed by Christian Duerr
parent f4fc9eb35a
commit e4dc43e87c
9 changed files with 66 additions and 34 deletions

View file

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Crashes on Windows are now also reported with a popup in addition to stderr - Crashes on Windows are now also reported with a popup in addition to stderr
- Windows: New configuration field `enable_experimental_conpty_backend` which enables support - Windows: New configuration field `enable_experimental_conpty_backend` which enables support
for the Pseudoconsole API (ConPTY) added in Windows 10 October 2018 (1809) update for the Pseudoconsole API (ConPTY) added in Windows 10 October 2018 (1809) update
- New mouse and key action `SpawnNewInstance` for launching another instance of Alacritty
### Changed ### Changed

View file

@ -319,7 +319,7 @@ live_config_reload: true
# arguments (`command`). # arguments (`command`).
# #
# Example: # Example:
# `- { key: V, mods: Command, action: Paste }` # `- { key: V, mods: Control|Shift, action: Paste }`
# #
# Available fields: # Available fields:
# - key # - key
@ -374,6 +374,7 @@ live_config_reload: true
# - Hide # - Hide
# - Quit # - Quit
# - ClearLogNotice # - ClearLogNotice
# - SpawnNewInstance
# #
# Values for `command`: # Values for `command`:
# The `command` field must be a map containing a `program` string and # The `command` field must be a map containing a `program` string and
@ -392,8 +393,6 @@ key_bindings:
- { key: C, mods: Control|Shift, action: Copy } - { key: C, mods: Control|Shift, action: Copy }
- { key: Paste, action: Paste } - { key: Paste, action: Paste }
- { key: Copy, action: Copy } - { key: Copy, action: Copy }
- { key: Q, mods: Command, action: Quit }
- { key: W, mods: Command, action: Quit }
- { key: Insert, mods: Shift, action: PasteSelection } - { key: Insert, mods: Shift, action: PasteSelection }
- { key: Key0, mods: Control, action: ResetFontSize } - { key: Key0, mods: Control, action: ResetFontSize }
- { key: Equals, mods: Control, action: IncreaseFontSize } - { key: Equals, mods: Control, action: IncreaseFontSize }

View file

@ -326,7 +326,7 @@ live_config_reload: true
# arguments (`command`). # arguments (`command`).
# #
# Example: # Example:
# `- { key: V, mods: Command, action: Paste }` # `- { key: V, mods: Control|Shift, action: Paste }`
# #
# Available fields: # Available fields:
# - key # - key
@ -381,6 +381,7 @@ live_config_reload: true
# - Hide # - Hide
# - Quit # - Quit
# - ClearLogNotice # - ClearLogNotice
# - SpawnNewInstance
# #
# Values for `command`: # Values for `command`:
# The `command` field must be a map containing a `program` string and # The `command` field must be a map containing a `program` string and

View file

@ -303,7 +303,7 @@ enable_experimental_conpty_backend: false
# arguments (`command`). # arguments (`command`).
# #
# Example: # Example:
# `- { key: V, mods: Command, action: Paste }` # `- { key: V, mods: Control|Shift, action: Paste }`
# #
# Available fields: # Available fields:
# - key # - key
@ -358,6 +358,7 @@ enable_experimental_conpty_backend: false
# - Hide # - Hide
# - Quit # - Quit
# - ClearLogNotice # - ClearLogNotice
# - SpawnNewInstance
# #
# Values for `command`: # Values for `command`:
# The `command` field must be a map containing a `program` string and # The `command` field must be a map containing a `program` string and
@ -374,8 +375,6 @@ enable_experimental_conpty_backend: false
key_bindings: key_bindings:
- { key: V, mods: Control|Shift, action: Paste } - { key: V, mods: Control|Shift, action: Paste }
- { key: C, mods: Control|Shift, action: Copy } - { key: C, mods: Control|Shift, action: Copy }
- { key: Q, mods: Command, action: Quit }
- { key: W, mods: Command, action: Quit }
- { key: Insert, mods: Shift, action: PasteSelection } - { key: Insert, mods: Shift, action: PasteSelection }
- { key: Key0, mods: Control, action: ResetFontSize } - { key: Key0, mods: Control, action: ResetFontSize }
- { key: Equals, mods: Control, action: IncreaseFontSize } - { key: Equals, mods: Control, action: IncreaseFontSize }

View file

@ -771,7 +771,7 @@ impl<'a> de::Deserialize<'a> for ActionWrapper {
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Paste, Copy, PasteSelection, IncreaseFontSize, DecreaseFontSize, \ f.write_str("Paste, Copy, PasteSelection, IncreaseFontSize, DecreaseFontSize, \
ResetFontSize, ScrollPageUp, ScrollPageDown, ScrollToTop, \ ResetFontSize, ScrollPageUp, ScrollPageDown, ScrollToTop, \
ScrollToBottom, ClearHistory, Hide, ClearLogNotice or Quit") ScrollToBottom, ClearHistory, Hide, ClearLogNotice, SpawnNewInstance or Quit")
} }
fn visit_str<E>(self, value: &str) -> ::std::result::Result<ActionWrapper, E> fn visit_str<E>(self, value: &str) -> ::std::result::Result<ActionWrapper, E>
@ -792,6 +792,7 @@ impl<'a> de::Deserialize<'a> for ActionWrapper {
"Hide" => Action::Hide, "Hide" => Action::Hide,
"Quit" => Action::Quit, "Quit" => Action::Quit,
"ClearLogNotice" => Action::ClearLogNotice, "ClearLogNotice" => Action::ClearLogNotice,
"SpawnNewInstance" => Action::SpawnNewInstance,
_ => return Err(E::invalid_value(Unexpected::Str(value), &self)), _ => return Err(E::invalid_value(Unexpected::Str(value), &self)),
})) }))
} }

View file

@ -1,15 +1,21 @@
//! Process window events //! Process window events
#[cfg(unix)]
use std::fs;
use std::borrow::Cow; use std::borrow::Cow;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::sync::mpsc; use std::sync::mpsc;
use std::time::{Instant}; use std::time::{Instant};
use std::env;
use serde_json as json; use serde_json as json;
use parking_lot::MutexGuard; use parking_lot::MutexGuard;
use glutin::{self, ModifiersState, Event, ElementState}; use glutin::{self, ModifiersState, Event, ElementState};
use copypasta::{Clipboard, Load, Store, Buffer as ClipboardBuffer}; use copypasta::{Clipboard, Load, Store, Buffer as ClipboardBuffer};
use glutin::dpi::PhysicalSize;
#[cfg(unix)]
use crate::tty;
use crate::ansi::{Handler, ClearMode}; use crate::ansi::{Handler, ClearMode};
use crate::grid::Scroll; use crate::grid::Scroll;
use crate::config::{self, Config}; use crate::config::{self, Config};
@ -21,10 +27,9 @@ use crate::selection::Selection;
use crate::sync::FairMutex; use crate::sync::FairMutex;
use crate::term::{Term, SizeInfo, TermMode, Search}; use crate::term::{Term, SizeInfo, TermMode, Search};
use crate::term::cell::Cell; use crate::term::cell::Cell;
use crate::util::limit; use crate::util::{limit, start_daemon};
use crate::util::fmt::Red; use crate::util::fmt::Red;
use crate::window::Window; use crate::window::Window;
use glutin::dpi::PhysicalSize;
/// Byte sequences are sent to a `Notify` in response to some events /// Byte sequences are sent to a `Notify` in response to some events
pub trait Notify { pub trait Notify {
@ -177,6 +182,23 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
fn clear_log(&mut self) { fn clear_log(&mut self) {
self.terminal.clear_log(); self.terminal.clear_log();
} }
fn spawn_new_instance(&mut self) {
let alacritty = env::args().next().unwrap();
#[cfg(unix)]
let args = [
"--working-directory".into(),
fs::read_link(format!("/proc/{}/cwd", unsafe { tty::PID }))
.expect("shell working directory"),
];
#[cfg(not(unix))]
let args: [&str; 0] = [];
match start_daemon(&alacritty, &args) {
Ok(_) => debug!("Started new Alacritty process: {} {:?}", alacritty, args),
Err(_) => warn!("Unable to start new Alacritty process: {} {:?}", alacritty, args),
}
}
} }
/// The ActionContext can't really have direct access to the Window /// The ActionContext can't really have direct access to the Window

View file

@ -75,6 +75,7 @@ pub trait ActionContext {
fn hide_window(&mut self); fn hide_window(&mut self);
fn url(&self, _: Point<usize>) -> Option<String>; fn url(&self, _: Point<usize>) -> Option<String>;
fn clear_log(&mut self); fn clear_log(&mut self);
fn spawn_new_instance(&mut self);
} }
/// Describes a state and action to take in that state /// Describes a state and action to take in that state
@ -202,6 +203,9 @@ pub enum Action {
/// Clears warning and error notices. /// Clears warning and error notices.
ClearLogNotice, ClearLogNotice,
/// Spawn a new instance of Alacritty.
SpawnNewInstance,
} }
impl Action { impl Action {
@ -279,7 +283,10 @@ impl Action {
}, },
Action::ClearLogNotice => { Action::ClearLogNotice => {
ctx.clear_log(); ctx.clear_log();
} },
Action::SpawnNewInstance => {
ctx.spawn_new_instance();
},
} }
} }
@ -793,9 +800,17 @@ mod tests {
} }
impl <'a>super::ActionContext for ActionContext<'a> { impl <'a>super::ActionContext for ActionContext<'a> {
fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, _val: B) { fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, _val: B) {}
// STUBBED fn update_selection(&mut self, _point: Point, _side: Side) {}
} fn simple_selection(&mut self, _point: Point, _side: Side) {}
fn copy_selection(&self, _buffer: ClipboardBuffer) {}
fn clear_selection(&mut self) {}
fn change_font_size(&mut self, _delta: f32) {}
fn reset_font_size(&mut self) {}
fn clear_history(&mut self) {}
fn clear_log(&mut self) {}
fn hide_window(&mut self) {}
fn spawn_new_instance(&mut self) {}
fn terminal_mode(&self) -> TermMode { fn terminal_mode(&self) -> TermMode {
*self.terminal.mode() *self.terminal.mode()
@ -805,14 +820,6 @@ mod tests {
*self.size_info *self.size_info
} }
fn copy_selection(&self, _buffer: ClipboardBuffer) {
// STUBBED
}
fn clear_selection(&mut self) {}
fn update_selection(&mut self, _point: Point, _side: Side) {}
fn simple_selection(&mut self, _point: Point, _side: Side) {}
fn semantic_selection(&mut self, _point: Point) { fn semantic_selection(&mut self, _point: Point) {
// set something that we can check for here // set something that we can check for here
self.last_action = MultiClick::DoubleClick; self.last_action = MultiClick::DoubleClick;
@ -851,21 +858,14 @@ mod tests {
fn received_count(&mut self) -> &mut usize { fn received_count(&mut self) -> &mut usize {
&mut self.received_count &mut self.received_count
} }
fn suppress_chars(&mut self) -> &mut bool { fn suppress_chars(&mut self) -> &mut bool {
&mut self.suppress_chars &mut self.suppress_chars
} }
fn last_modifiers(&mut self) -> &mut ModifiersState { fn last_modifiers(&mut self) -> &mut ModifiersState {
&mut self.last_modifiers &mut self.last_modifiers
} }
fn change_font_size(&mut self, _delta: f32) {
}
fn reset_font_size(&mut self) {
}
fn clear_history(&mut self) {
}
fn hide_window(&mut self) {
}
fn clear_log(&mut self) {}
} }
macro_rules! test_clickstate { macro_rules! test_clickstate {

View file

@ -38,7 +38,7 @@ use std::os::unix::io::AsRawFd;
/// Process ID of child process /// Process ID of child process
/// ///
/// Necessary to put this in static storage for `sigchld` to have access /// Necessary to put this in static storage for `sigchld` to have access
static mut PID: pid_t = 0; pub static mut PID: pid_t = 0;
/// Exit flag /// Exit flag
/// ///

View file

@ -14,6 +14,7 @@
#[cfg(not(windows))] #[cfg(not(windows))]
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
use std::process::Command; use std::process::Command;
use std::ffi::OsStr;
use std::{cmp, io}; use std::{cmp, io};
/// Threading utilities /// Threading utilities
@ -77,7 +78,11 @@ pub mod fmt {
} }
#[cfg(not(windows))] #[cfg(not(windows))]
pub fn start_daemon(program: &str, args: &[String]) -> io::Result<()> { pub fn start_daemon<I, S>(program: &str, args: I) -> io::Result<()>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
Command::new(program) Command::new(program)
.args(args) .args(args)
.before_exec(|| unsafe { .before_exec(|| unsafe {
@ -90,7 +95,11 @@ pub fn start_daemon(program: &str, args: &[String]) -> io::Result<()> {
} }
#[cfg(windows)] #[cfg(windows)]
pub fn start_daemon(program: &str, args: &[String]) -> io::Result<()> { pub fn start_daemon<I, S>(program: &str, args: I) -> io::Result<()>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
Command::new(program).args(args).spawn().map(|_| ()) Command::new(program).args(args).spawn().map(|_| ())
} }