Skip to content

Commit

Permalink
Add ctrl-z to suspend
Browse files Browse the repository at this point in the history
  • Loading branch information
pickfire committed Jul 20, 2021
1 parent 722cfed commit 95d8871
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 16 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion helix-lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ lsp-types = { version = "0.89", features = ["proposed"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
tokio = { version = "1.8", features = ["full"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
tokio-stream = "0.1.7"
6 changes: 5 additions & 1 deletion helix-term/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ helix-lsp = { version = "0.3", path = "../helix-lsp" }
anyhow = "1"
once_cell = "1.8"

tokio = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
num_cpus = "1"
tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] }
crossterm = { version = "0.20", features = ["event-stream"] }
signal-hook = "0.3"

futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }

Expand All @@ -54,3 +55,6 @@ toml = "0.5"

serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }

[target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100
signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] }
77 changes: 65 additions & 12 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ use crossterm::{
event::{Event, EventStream},
execute, terminal,
};
#[cfg(not(windows))]
use signal_hook::{consts::signal, low_level};
#[cfg(not(windows))]
use signal_hook_tokio::Signals;

pub struct Application {
compositor: Compositor,
Expand All @@ -36,6 +40,8 @@ pub struct Application {
#[allow(dead_code)]
syn_loader: Arc<syntax::Loader>,

#[cfg(not(windows))]
signals: Signals,
jobs: Jobs,
lsp_progress: LspProgressMap,
}
Expand Down Expand Up @@ -99,6 +105,9 @@ impl Application {

editor.set_theme(theme);

#[cfg(not(windows))]
let signals = Signals::new(&[signal::SIGTSTP, signal::SIGCONT])?;

let app = Self {
compositor,
editor,
Expand All @@ -108,6 +117,8 @@ impl Application {
theme_loader,
syn_loader,

#[cfg(not(windows))]
signals,
jobs: Jobs::new(),
lsp_progress: LspProgressMap::new(),
};
Expand Down Expand Up @@ -144,22 +155,60 @@ impl Application {

use futures_util::StreamExt;

#[cfg(not(windows))]
tokio::select! {
biased;

event = reader.next() => {
self.handle_terminal_events(event)
}
Some(signal) = self.signals.next() => {
use helix_view::graphics::Rect;
match signal {
signal::SIGTSTP => {
self.restore_term().unwrap();
low_level::emulate_default_handler(signal::SIGTSTP).unwrap();
} signal::SIGCONT => {
self.claim_term().await.unwrap();
// redraw the terminal
let Rect { width, height, .. } = self.compositor.size();
self.compositor.resize(width, height);
self.render();
}
_ => unreachable!(),
}
}
Some((id, call)) = self.editor.language_servers.incoming.next() => {
self.handle_language_server_message(call, id).await;
// limit render calls for fast language server messages
let last = self.editor.language_servers.incoming.is_empty();
if last || last_render.elapsed() > deadline {
self.render();
last_render = Instant::now();
}
} } Some(callback) = self.jobs.futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.render();
}
Some(callback) = self.jobs.wait_futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.render();
}
Some(callback) = self.jobs.futures.next() => {
}
#[cfg(windows)]
tokio::select! {
biased;

event = reader.next() => {
self.handle_terminal_events(event)
}
Some((id, call)) = self.editor.language_servers.incoming.next() => {
self.handle_language_server_message(call, id).await;
// limit render calls for fast language server messages
let last = self.editor.language_servers.incoming.is_empty();
if last || last_render.elapsed() > deadline {
self.render();
last_render = Instant::now();
} } Some(callback) = self.jobs.futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.render();
}
Expand Down Expand Up @@ -440,12 +489,23 @@ impl Application {
}
}

pub async fn run(&mut self) -> Result<(), Error> {
async fn claim_term(&mut self) -> Result<(), Error> {
terminal::enable_raw_mode()?;
self.editor.close_language_servers(None).await?;
Ok(())
}

fn restore_term(&mut self) -> Result<(), Error> {
let mut stdout = stdout();
// reset cursor shape
write!(stdout, "\x1B[2 q")?;
execute!(stdout, terminal::LeaveAlternateScreen)?;
terminal::disable_raw_mode()?;
Ok(())
}

execute!(stdout, terminal::EnterAlternateScreen)?;
pub async fn run(&mut self) -> Result<(), Error> {
self.claim_term().await?;

// Exit the alternate screen and disable raw mode before panicking
let hook = std::panic::take_hook();
Expand All @@ -460,14 +520,7 @@ impl Application {

self.event_loop().await;

self.editor.close_language_servers(None).await?;

// reset cursor shape
write!(stdout, "\x1B[2 q")?;

execute!(stdout, terminal::LeaveAlternateScreen)?;

terminal::disable_raw_mode()?;
self.restore_term()?;

Ok(())
}
Expand Down
9 changes: 8 additions & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use std::{

use once_cell::sync::{Lazy, OnceCell};
use serde::de::{self, Deserialize, Deserializer};
use signal_hook::{consts::signal, low_level};

pub struct Context<'a> {
pub selected_register: helix_view::RegisterSelection,
Expand Down Expand Up @@ -279,7 +280,8 @@ impl Command {
view_mode,
left_bracket_mode,
right_bracket_mode,
match_mode
match_mode,
suspend
);
}

Expand Down Expand Up @@ -3671,6 +3673,11 @@ fn surround_delete(cx: &mut Context) {
})
}

fn suspend(_cx: &mut Context) {
#[cfg(not(windows))]
low_level::raise(signal::SIGTSTP).unwrap();
}

/// Do nothing, just for modeinfo.
fn noop(_cx: &mut Context) -> bool {
false
Expand Down
1 change: 1 addition & 0 deletions helix-term/src/keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ impl Default for Keymaps {
key!('z') => Command::view_mode,

key!('"') => Command::select_register,
ctrl!('z') => Command::suspend,
);
// TODO: decide whether we want normal mode to also be select mode (kakoune-like), or whether
// we keep this separate select mode. More keys can fit into normal mode then, but it's weird
Expand Down
2 changes: 1 addition & 1 deletion helix-view/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ crossterm = { version = "0.20", optional = true }
once_cell = "1.8"
url = "2"

tokio = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }

slotmap = "1"
Expand Down

0 comments on commit 95d8871

Please sign in to comment.