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:
parent
f4fc9eb35a
commit
e4dc43e87c
9 changed files with 66 additions and 34 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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)),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
26
src/event.rs
26
src/event.rs
|
@ -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
|
||||||
|
|
42
src/input.rs
42
src/input.rs
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
///
|
///
|
||||||
|
|
13
src/util.rs
13
src/util.rs
|
@ -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(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue