diff --git a/Cargo.lock b/Cargo.lock index b6235c6c..4bbdb672 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,6 +378,7 @@ dependencies = [ "crossterm", "futures", "indexmap 2.0.0", + "libc", "natord", "notify", "parking_lot", diff --git a/app/src/executor.rs b/app/src/executor.rs index 7a350a00..1897bf4f 100644 --- a/app/src/executor.rs +++ b/app/src/executor.rs @@ -57,6 +57,7 @@ impl Executor { "escape" => cx.manager.active_mut().escape(), "quit" => cx.manager.quit(&cx.tasks), "close" => cx.manager.close(&cx.tasks), + "suspend" => cx.manager.suspend(), // Navigation "arrow" => { diff --git a/app/src/signals.rs b/app/src/signals.rs index 4dd921df..9a337130 100644 --- a/app/src/signals.rs +++ b/app/src/signals.rs @@ -50,19 +50,27 @@ impl Signals { #[cfg(not(target_os = "windows"))] fn spawn_system_task(&self) -> Result> { - use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM}; + use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM}; let tx = self.tx.clone(); - let mut signals = signal_hook_tokio::Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?; + let mut signals = signal_hook_tokio::Signals::new([ + // Terminating signals + SIGHUP, SIGTERM, SIGQUIT, SIGINT, // + // Job control signals + SIGCONT, + ])?; Ok(tokio::spawn(async move { while let Some(signal) = signals.next().await { match signal { - SIGHUP | SIGTERM | SIGINT | SIGQUIT => { + SIGHUP | SIGTERM | SIGQUIT | SIGINT => { if tx.send(Event::Quit).is_err() { break; } } + SIGCONT => { + tx.send(Event::Stop(false, None)).ok(); + } _ => {} } } diff --git a/config/preset/keymap.toml b/config/preset/keymap.toml index 399fca0b..e1736b17 100644 --- a/config/preset/keymap.toml +++ b/config/preset/keymap.toml @@ -1,9 +1,10 @@ [manager] keymap = [ - { on = [ "" ], exec = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, - { on = [ "q" ], exec = "quit", desc = "Exit the process" }, - { on = [ "" ], exec = "close", desc = "Close the current tab, or quit if it is last tab" }, + { on = [ "" ], exec = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, + { on = [ "q" ], exec = "quit", desc = "Exit the process" }, + { on = [ "" ], exec = "close", desc = "Close the current tab, or quit if it is last tab" }, + { on = [ "" ], exec = "suspend", desc = "Suspend the process" }, # Navigation { on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" }, diff --git a/core/Cargo.toml b/core/Cargo.toml index 0656a129..a29d996a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -14,6 +14,7 @@ async-channel = "^1" crossterm = "^0" futures = "^0" indexmap = "^2" +libc = "^0" natord = "^1" notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] } parking_lot = "^0" diff --git a/core/src/manager/manager.rs b/core/src/manager/manager.rs index a4730b9a..518d3892 100644 --- a/core/src/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -121,6 +121,14 @@ impl Manager { self.quit(tasks) } + pub fn suspend(&mut self) -> bool { + tokio::spawn(async move { + emit!(Stop(true)).await; + unsafe { libc::raise(libc::SIGTSTP) }; + }); + false + } + pub fn open(&mut self, interactive: bool) -> bool { let mut files: Vec<_> = self .selected() diff --git a/cspell.json b/cspell.json index c26e3940..d6760f99 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs"],"version":"0.2","flagWords":[]} +{"language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT"],"version":"0.2","flagWords":[]}