diff --git a/README.md b/README.md index 40992112..e7da4179 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,17 @@ Any of the following applies: $ # Add the resulting `target/release/sk` executable to your PATH ``` +You will then have access to: + +- The man page, which you can either write to the correct path or run `man --local-file <(sk --man)` +- The shell completions (and optional keybinds), using `source <(sk --shell \ \[--shell-bindings])`, see below for details + # Usage Skim can be used either as a general filter (similar to `grep`) or as an interactive interface for running commands. -## As Vim plugin +## As Vim plugin (on neovim, checkout [fzf-lua](https://github.com/ibhagwan/fzf-lua) with the skim profile) Via vim-plug (recommended): diff --git a/man/man1/sk.1 b/man/man1/sk.1 index 02d6de10..dafa838f 100644 --- a/man/man1/sk.1 +++ b/man/man1/sk.1 @@ -8,7 +8,7 @@ sk \- Fuzzy Finder in rust! .ie \n(.g .ds Aq \(aq .el .ds Aq ' .SH SYNOPSIS -\fBsk\fR [\fB\-\-tac\fR] [\fB\-\-min\-query\-length\fR] [\fB\-\-no\-sort\fR] [\fB\-t\fR|\fB\-\-tiebreak\fR] [\fB\-n\fR|\fB\-\-nth\fR] [\fB\-\-with\-nth\fR] [\fB\-d\fR|\fB\-\-delimiter\fR] [\fB\-e\fR|\fB\-\-exact\fR] [\fB\-\-regex\fR] [\fB\-\-algo\fR] [\fB\-\-case\fR] [\fB\-\-split\-match\fR] [\fB\-b\fR|\fB\-\-bind\fR] [\fB\-m\fR|\fB\-\-multi\fR] [\fB\-\-no\-multi\fR] [\fB\-\-no\-mouse\fR] [\fB\-c\fR|\fB\-\-cmd\fR] [\fB\-i\fR|\fB\-\-interactive\fR] [\fB\-I \fR] [\fB\-\-color\fR] [\fB\-\-no\-hscroll\fR] [\fB\-\-keep\-right\fR] [\fB\-\-skip\-to\-pattern\fR] [\fB\-\-no\-clear\-if\-empty\fR] [\fB\-\-no\-clear\-start\fR] [\fB\-\-no\-clear\fR] [\fB\-\-show\-cmd\-error\fR] [\fB\-\-cycle\fR] [\fB\-\-disabled\fR] [\fB\-\-layout\fR] [\fB\-\-reverse\fR] [\fB\-\-height\fR] [\fB\-\-no\-height\fR] [\fB\-\-min\-height\fR] [\fB\-\-margin\fR] [\fB\-p\fR|\fB\-\-prompt\fR] [\fB\-\-cmd\-prompt\fR] [\fB\-\-selector\fR] [\fB\-\-multi\-selector\fR] [\fB\-\-ansi\fR] [\fB\-\-tabstop\fR] [\fB\-\-info\fR] [\fB\-\-no\-info\fR] [\fB\-\-inline\-info\fR] [\fB\-\-header\fR] [\fB\-\-header\-lines\fR] [\fB\-\-border\fR] [\fB\-\-wrap\fR] [\fB\-\-history\fR] [\fB\-\-history\-size\fR] [\fB\-\-cmd\-history\fR] [\fB\-\-cmd\-history\-size\fR] [\fB\-\-preview\fR] [\fB\-\-preview\-window\fR] [\fB\-q\fR|\fB\-\-query\fR] [\fB\-\-cmd\-query\fR] [\fB\-\-read0\fR] [\fB\-\-print0\fR] [\fB\-\-print\-query\fR] [\fB\-\-print\-cmd\fR] [\fB\-\-print\-score\fR] [\fB\-\-print\-header\fR] [\fB\-\-no\-strip\-ansi\fR] [\fB\-1\fR|\fB\-\-select\-1\fR] [\fB\-0\fR|\fB\-\-exit\-0\fR] [\fB\-\-sync\fR] [\fB\-\-pre\-select\-n\fR] [\fB\-\-pre\-select\-pat\fR] [\fB\-\-pre\-select\-items\fR] [\fB\-\-pre\-select\-file\fR] [\fB\-f\fR|\fB\-\-filter\fR] [\fB\-\-shell\fR] [\fB\-\-shell\-bindings\fR] [\fB\-\-man\fR] [\fB\-\-listen\fR] [\fB\-\-tmux\fR] [\fB\-\-log\-file\fR] [\fB\-\-expect\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] +\fBsk\fR [\fB\-\-tac\fR] [\fB\-\-min\-query\-length\fR] [\fB\-\-no\-sort\fR] [\fB\-t\fR|\fB\-\-tiebreak\fR] [\fB\-n\fR|\fB\-\-nth\fR] [\fB\-\-with\-nth\fR] [\fB\-d\fR|\fB\-\-delimiter\fR] [\fB\-e\fR|\fB\-\-exact\fR] [\fB\-\-regex\fR] [\fB\-\-algo\fR] [\fB\-\-case\fR] [\fB\-\-split\-match\fR] [\fB\-b\fR|\fB\-\-bind\fR] [\fB\-m\fR|\fB\-\-multi\fR] [\fB\-\-no\-multi\fR] [\fB\-\-no\-mouse\fR] [\fB\-c\fR|\fB\-\-cmd\fR] [\fB\-i\fR|\fB\-\-interactive\fR] [\fB\-I \fR] [\fB\-\-color\fR] [\fB\-\-no\-hscroll\fR] [\fB\-\-keep\-right\fR] [\fB\-\-skip\-to\-pattern\fR] [\fB\-\-no\-clear\-if\-empty\fR] [\fB\-\-no\-clear\-start\fR] [\fB\-\-no\-clear\fR] [\fB\-\-show\-cmd\-error\fR] [\fB\-\-cycle\fR] [\fB\-\-disabled\fR] [\fB\-\-layout\fR] [\fB\-\-reverse\fR] [\fB\-\-height\fR] [\fB\-\-no\-height\fR] [\fB\-\-min\-height\fR] [\fB\-\-margin\fR] [\fB\-p\fR|\fB\-\-prompt\fR] [\fB\-\-cmd\-prompt\fR] [\fB\-\-selector\fR] [\fB\-\-multi\-selector\fR] [\fB\-\-ansi\fR] [\fB\-\-tabstop\fR] [\fB\-\-info\fR] [\fB\-\-no\-info\fR] [\fB\-\-inline\-info\fR] [\fB\-\-header\fR] [\fB\-\-header\-lines\fR] [\fB\-\-border\fR] [\fB\-\-wrap\fR] [\fB\-\-history\fR] [\fB\-\-history\-size\fR] [\fB\-\-cmd\-history\fR] [\fB\-\-cmd\-history\-size\fR] [\fB\-\-preview\fR] [\fB\-\-preview\-window\fR] [\fB\-q\fR|\fB\-\-query\fR] [\fB\-\-cmd\-query\fR] [\fB\-\-read0\fR] [\fB\-\-print0\fR] [\fB\-\-print\-query\fR] [\fB\-\-print\-cmd\fR] [\fB\-\-print\-score\fR] [\fB\-\-print\-header\fR] [\fB\-\-no\-strip\-ansi\fR] [\fB\-1\fR|\fB\-\-select\-1\fR] [\fB\-0\fR|\fB\-\-exit\-0\fR] [\fB\-\-sync\fR] [\fB\-\-pre\-select\-n\fR] [\fB\-\-pre\-select\-pat\fR] [\fB\-\-pre\-select\-items\fR] [\fB\-\-pre\-select\-file\fR] [\fB\-f\fR|\fB\-\-filter\fR] [\fB\-\-shell\fR] [\fB\-\-shell\-bindings\fR] [\fB\-\-man\fR] [\fB\-\-listen\fR] [\fB\-\-remote\fR] [\fB\-\-tmux\fR] [\fB\-\-log\-file\fR] [\fB\-\-expect\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] .ie \n(.g .ds Aq \(aq .el .ds Aq ' .SH OPTIONS @@ -516,7 +516,12 @@ Generate man page and output it to stdout \fB\-\-listen\fR [\fI...\fR] Run an IPC socket with optional name (defaults to sk) -The socket expects Actions in Ron format (similar to Rust code), see ./src/tui/event.rs for all possible Actions To write to it, you can use socat, for example with \-\-listen sk: echo \*(AqToggleIn\*(Aq | socat \-u STDIN ABSTRACT\-CONNECT:sk +The socket expects Actions in Ron format (similar to Rust code), see ./src/tui/event.rs for all possible Actions To write to it, see the \-\-remote option or the man page +.TP +\fB\-\-remote\fR [\fI...\fR] +Send commands to an IPC socket with optional name (defaults to sk) + +The commands are read from stdin, one per line, in the same format as the actions in the bind flag. They can also be chained using + as a separator. All other arguments will be ignored .TP \fB\-\-log\-file\fR \fI\fR Pipe log output to a file @@ -938,6 +943,26 @@ Example: `\-\-color \*(Aq16,normal\-fg:0+bold,matched\-fg:#ffffff+u,cursor\-bg:# white) underlined foreground for matched parts and a #deadbe (pale rose, apparently) cursor background. .br +.SH LISTEN/REMOTE + +.br +skim can be controlled from other processes, using the `\-\-listen` (and optionally `\-\-remote`) flags. +.br + +.br +To achieve this, run the server instance using `sk \-\-listen optional_address` (the address defaults to `sk`). +.br +It will then start listening on a named socket for instructions. +.br + +.br +To send instructions, you can use `sk \-\-remote optional_address` or any other tool that allows us to interact with such sockets, +.br +such as `socat` on linux: `echo \*(AqToggleIn\*(Aq | socat \-u STDIN ABSTRACT\-CONNECT:optional_address`. Instructions correspond to skim\*(Aqs Actions and need to be sent in Ron format. +.br +When using `sk \-\-remote`, pipe in action chains (see the KEYBINDS section), for instance `echo \*(Aqup+select\-row\*(Aq | sk \-\-remote optional_address` +.br + .SH "EXIT CODES" .br diff --git a/shell/completion.bash b/shell/completion.bash index f000ddc3..6f1a54f5 100644 --- a/shell/completion.bash +++ b/shell/completion.bash @@ -23,7 +23,7 @@ _sk() { case "${cmd}" in sk) - opts="-t -n -d -e -b -m -c -i -I -p -q -1 -0 -f -x -h -V --tac --min-query-length --no-sort --tiebreak --nth --with-nth --delimiter --exact --regex --algo --case --split-match --bind --multi --no-multi --no-mouse --cmd --interactive --color --no-hscroll --keep-right --skip-to-pattern --no-clear-if-empty --no-clear-start --no-clear --show-cmd-error --cycle --disabled --layout --reverse --height --no-height --min-height --margin --prompt --cmd-prompt --selector --multi-selector --ansi --tabstop --info --no-info --inline-info --header --header-lines --border --wrap --history --history-size --cmd-history --cmd-history-size --preview --preview-window --query --cmd-query --read0 --print0 --print-query --print-cmd --print-score --print-header --no-strip-ansi --select-1 --exit-0 --sync --pre-select-n --pre-select-pat --pre-select-items --pre-select-file --filter --shell --shell-bindings --man --listen --tmux --log-file --extended --literal --hscroll-off --filepath-word --jump-labels --no-bold --phony --expect --help --version" + opts="-t -n -d -e -b -m -c -i -I -p -q -1 -0 -f -x -h -V --tac --min-query-length --no-sort --tiebreak --nth --with-nth --delimiter --exact --regex --algo --case --split-match --bind --multi --no-multi --no-mouse --cmd --interactive --color --no-hscroll --keep-right --skip-to-pattern --no-clear-if-empty --no-clear-start --no-clear --show-cmd-error --cycle --disabled --layout --reverse --height --no-height --min-height --margin --prompt --cmd-prompt --selector --multi-selector --ansi --tabstop --info --no-info --inline-info --header --header-lines --border --wrap --history --history-size --cmd-history --cmd-history-size --preview --preview-window --query --cmd-query --read0 --print0 --print-query --print-cmd --print-score --print-header --no-strip-ansi --select-1 --exit-0 --sync --pre-select-n --pre-select-pat --pre-select-items --pre-select-file --filter --shell --shell-bindings --man --listen --remote --tmux --log-file --extended --literal --hscroll-off --filepath-word --jump-labels --no-bold --phony --expect --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -221,6 +221,10 @@ _sk() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --remote) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --tmux) COMPREPLY=($(compgen -f "${cur}")) return 0 diff --git a/shell/completion.fish b/shell/completion.fish index 45f82896..e935b7b6 100644 --- a/shell/completion.fish +++ b/shell/completion.fish @@ -61,6 +61,7 @@ nushell\t'Nushell (nu)' power-shell\t'PowerShell' zsh\t'Zsh'" complete -c sk -l listen -d 'Run an IPC socket with optional name (defaults to sk)' -r +complete -c sk -l remote -d 'Send commands to an IPC socket with optional name (defaults to sk)' -r complete -c sk -l tmux -d 'Run in a tmux popup' -r complete -c sk -l log-file -d 'Pipe log output to a file' -r complete -c sk -l hscroll-off -d 'Reserved for later use' -r diff --git a/shell/completion.nu b/shell/completion.nu index ccb076df..0ad83d46 100644 --- a/shell/completion.nu +++ b/shell/completion.nu @@ -101,6 +101,7 @@ module completions { --shell-bindings # Generate shell key bindings - only for bash, zsh and fish --man # Generate man page and output it to stdout --listen: string # Run an IPC socket with optional name (defaults to sk) + --remote: string # Send commands to an IPC socket with optional name (defaults to sk) --tmux: string # Run in a tmux popup --log-file: string # Pipe log output to a file --extended(-x) # Reserved for later use diff --git a/shell/completion.zsh b/shell/completion.zsh index f484f758..8e21a1ba 100644 --- a/shell/completion.zsh +++ b/shell/completion.zsh @@ -75,6 +75,7 @@ nushell\:"Nushell (nu)" power-shell\:"PowerShell" zsh\:"Zsh"))' \ '--listen=[Run an IPC socket with optional name (defaults to sk)]::LISTEN:_default' \ +'--remote=[Send commands to an IPC socket with optional name (defaults to sk)]::REMOTE:_default' \ '--tmux=[Run in a tmux popup]::TMUX:_default' \ '--log-file=[Pipe log output to a file]:LOG_FILE:_default' \ '--hscroll-off=[Reserved for later use]:HSCROLL_OFF:_default' \ diff --git a/src/bin/main.rs b/src/bin/main.rs index 7cc22bed..dcb15fed 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -13,7 +13,11 @@ use clap::{Error, Parser}; use color_eyre::Result; use color_eyre::eyre::eyre; use derive_builder::Builder; +use interprocess::bound_util::RefWrite; +use interprocess::local_socket::ToNsName as _; +use interprocess::local_socket::traits::Stream as _; use log::trace; +use skim::binds::parse_action_chain; use skim::item::RankBuilder; use skim::reader::CommandCollector; use skim::tui::event::Action; @@ -105,6 +109,30 @@ fn main() -> Result<()> { return Ok(()); } + if let Some(remote) = opts.remote { + let ns_name = remote + .to_ns_name::() + .unwrap(); + let stream = interprocess::local_socket::Stream::connect(ns_name)?; + let mut action_chain = String::new(); + loop { + action_chain.clear(); + let len = std::io::stdin().read_line(&mut action_chain)?; + log::debug!("Got line {} from stdin", action_chain.trim()); + if len == 0 { + break; + } + let actions = parse_action_chain(&action_chain.trim())?; + for act in actions { + stream + .as_write() + .write_all(&format!("{}\n", ron::ser::to_string(&act)?).as_bytes())?; + log::debug!("Sent action {act:?} to listener"); + } + } + return Ok(()); + } + match sk_main(opts) { Ok(exit_code) => std::process::exit(exit_code), Err(err) => { diff --git a/src/binds.rs b/src/binds.rs index 3b466830..990dad57 100644 --- a/src/binds.rs +++ b/src/binds.rs @@ -202,7 +202,8 @@ where /// Parses an action chain, separated by '+'s into the corresponding actions pub fn parse_action_chain(action_chain: &str) -> Result> { let mut actions: Vec = vec![]; - let mut split = action_chain.split("+"); + let lchain = action_chain.to_ascii_lowercase(); + let mut split = lchain.split("+"); loop { let Some(mut s) = split.next().map(String::from) else { break; diff --git a/src/manpage.rs b/src/manpage.rs index 33a3b5a1..35c6a745 100644 --- a/src/manpage.rs +++ b/src/manpage.rs @@ -177,6 +177,17 @@ const ACTIONS_SS: &str = " * yank: ctrl-y "; +const REMOTE_SECTION: &str = " +skim can be controlled from other processes, using the `--listen` (and optionally `--remote`) flags. + +To achieve this, run the server instance using `sk --listen optional_address` (the address defaults to `sk`). +It will then start listening on a named socket for instructions. + +To send instructions, you can use `sk --remote optional_address` or any other tool that allows us to interact with such sockets, +such as `socat` on linux: `echo 'ToggleIn' | socat -u STDIN ABSTRACT-CONNECT:optional_address`. Instructions correspond to skim's Actions and need to be sent in Ron format. +When using `sk --remote`, pipe in action chains (see the KEYBINDS section), for instance `echo 'up+select-row' | sk --remote optional_address` +"; + fn parse_str(src: &str) -> Vec { let mut res = Vec::new(); for line in src.lines() { @@ -313,6 +324,8 @@ It will expand to the corresponding fields, separated by the `--delimiter|-d` op section(&mut custom, "THEME", THEME_SECTION); + section(&mut custom, "LISTEN/REMOTE", REMOTE_SECTION); + section(&mut custom, "EXIT CODES", EXIT_CODES_SECTION); custom.to_writer(w)?; diff --git a/src/options.rs b/src/options.rs index c28fe101..65784005 100644 --- a/src/options.rs +++ b/src/options.rs @@ -656,11 +656,18 @@ pub struct SkimOptions { /// Run an IPC socket with optional name (defaults to `sk`) /// /// The socket expects Actions in Ron format (similar to Rust code), see `./src/tui/event.rs` for all possible Actions - /// To write to it, you can use socat, for example with `--listen sk`: - /// `echo 'ToggleIn' | socat -u STDIN ABSTRACT-CONNECT:sk` + /// To write to it, see the `--remote` option or the man page #[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting", default_missing_value = "sk", num_args=0..))] pub listen: Option, + /// Send commands to an IPC socket with optional name (defaults to `sk`) + /// + /// The commands are read from stdin, one per line, in the same format as the actions in the + /// bind flag. They can also be chained using `+` as a separator. + /// All other arguments will be ignored + #[cfg_attr(feature = "cli", arg(long, help_heading = "Scripting", default_missing_value = "sk", num_args=0..))] + pub remote: Option, + /// Run in a tmux popup /// /// Format: `sk --tmux [,SIZE[%]][,SIZE[%]]` @@ -754,6 +761,7 @@ impl Default for SkimOptions { no_strip_ansi: false, wrap_items: false, listen: None, + remote: None, print_header: false, disabled: false, tac: Default::default(), diff --git a/tests/listen.rs b/tests/listen.rs index bf2faac1..00434027 100644 --- a/tests/listen.rs +++ b/tests/listen.rs @@ -3,24 +3,31 @@ mod common; use common::tmux::Keys::*; -use interprocess::{ - bound_util::RefWrite, - local_socket::{GenericNamespaced, Stream, ToNsName, traits::Stream as _}, -}; use rand::{Rng as _, distr::Alphabetic}; -use std::io::{Result, Write as _}; +use std::{ + io::{Result, Write as _}, + process::{Child, Command, Stdio}, +}; use common::tmux::TmuxController; -fn connect(name: &str) -> Result { - let ns_name = name.to_ns_name::().unwrap(); - Stream::connect(ns_name) +use crate::common::tmux::SK; + +fn connect(name: &str) -> Result { + Command::new("/bin/sh") + .arg("-c") + .arg(&format!("{SK} --remote {name}")) + .stdin(Stdio::piped()) + .spawn() } -fn send(stream: &Stream, msg: &str) -> Result<()> { - stream.as_write().write_all(format!("{msg}\n").as_bytes()) +fn send(child: &mut Child, msg: &str) -> Result<()> { + let mut b = msg.bytes().collect::>(); + b.push(b'\n'); + child.stdin.as_mut().map(|s| s.write_all(&b)); + Ok(()) } -fn setup(name: &str, extra_args: &[&str]) -> Result<(TmuxController, Stream)> { +fn setup(name: &str, extra_args: &[&str]) -> Result<(TmuxController, Child)> { let mut tmux = TmuxController::new_named(name)?; let socket_name = format!( "sk-test-{name}{}", @@ -41,10 +48,10 @@ fn setup(name: &str, extra_args: &[&str]) -> Result<(TmuxController, Stream)> { #[test] fn listen_up() -> std::io::Result<()> { - let (tmux, stream) = setup("up", &[])?; + let (tmux, mut stream) = setup("up", &[])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); - send(&stream,"Up(2)")? ; + send(&mut stream,"up(2)")? ; @capture[2]trim().starts_with("a"); @capture[4]starts_with("> c"); ); @@ -53,13 +60,13 @@ fn listen_up() -> std::io::Result<()> { #[test] fn listen_down() -> std::io::Result<()> { - let (tmux, stream) = setup("down", &[])?; + let (tmux, mut stream) = setup("down", &[])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); @keys Up, Up; @capture[2]trim().starts_with("a"); @capture[4]starts_with("> c"); - send(&stream, "Down(2)")?; + send(&mut stream, "down(2)")?; @capture[2]starts_with("> a"); ); Ok(()) @@ -67,9 +74,9 @@ fn listen_down() -> std::io::Result<()> { #[test] fn listen_abort() -> std::io::Result<()> { - let (tmux, stream) = setup("abort", &[])?; + let (tmux, mut stream) = setup("abort", &[])?; sk_test!(@expand tmux; - send(&stream, "Abort")?; + send(&mut stream, "abort")?; @capture[0]trim().contains("$"); ); Ok(()) @@ -78,10 +85,10 @@ fn listen_abort() -> std::io::Result<()> { // Test Accept action - adapted to use "a" instead of "apple" #[test] fn listen_accept() -> std::io::Result<()> { - let (tmux, stream) = setup("accept", &[])?; + let (tmux, mut stream) = setup("accept", &[])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); - send(&stream, "Accept(None)")?; + send(&mut stream, "accept")?; @output[0]eq("a"); ); Ok(()) @@ -90,9 +97,9 @@ fn listen_accept() -> std::io::Result<()> { // Test Accept with key - adapted to use "a" instead of "apple" #[test] fn listen_accept_key() -> std::io::Result<()> { - let (tmux, stream) = setup("accept_key", &[])?; + let (tmux, mut stream) = setup("accept_key", &[])?; sk_test!(@expand tmux; - send(&stream, "Accept(Some(\"ctrl-a\"))")?; + send(&mut stream, "accept(ctrl-a)")?; @output[0]eq("ctrl-a"); @output[1]eq("a"); ); @@ -101,9 +108,9 @@ fn listen_accept_key() -> std::io::Result<()> { #[test] fn listen_add_char() -> std::io::Result<()> { - let (tmux, stream) = setup("add_char", &[])?; + let (tmux, mut stream) = setup("add_char", &[])?; sk_test!(@expand tmux; - send(&stream, "AddChar('a')")?; + send(&mut stream, "add-char(a)")?; @capture[0]trim().eq("> a"); ); Ok(()) @@ -111,11 +118,11 @@ fn listen_add_char() -> std::io::Result<()> { #[test] fn listen_backward_char() -> std::io::Result<()> { - let (tmux, stream) = setup("backward_char", &[])?; + let (tmux, mut stream) = setup("backward_char", &[])?; sk_test!(@expand tmux; @keys Str("hello"); @capture[0]starts_with("> hello"); - send(&stream, "BackwardChar")?; + send(&mut stream, "backward-char")?; @keys Key('|'); @capture[0]trim().eq("> hell|o"); ); @@ -124,11 +131,11 @@ fn listen_backward_char() -> std::io::Result<()> { #[test] fn listen_backward_delete_char() -> std::io::Result<()> { - let (tmux, stream) = setup("backward_delete_char", &[])?; + let (tmux, mut stream) = setup("backward_delete_char", &[])?; sk_test!(@expand tmux; @keys Str("test"); @capture[0]trim().eq("> test"); - send(&stream, "BackwardDeleteChar")?; + send(&mut stream, "backward-delete-char")?; @capture[0]trim().eq("> tes"); ); Ok(()) @@ -136,11 +143,11 @@ fn listen_backward_delete_char() -> std::io::Result<()> { #[test] fn listen_backward_delete_char_eof() -> std::io::Result<()> { - let (tmux, stream) = setup("backward_delete_char_eof", &[])?; + let (tmux, mut stream) = setup("backward_delete_char_eof", &[])?; sk_test!(@expand tmux; @keys Str("x"); @capture[0]trim().eq("> x"); - send(&stream, "BackwardDeleteCharEof")?; + send(&mut stream, "backward-delete-char/eof")?; @capture[0]trim().eq(">"); ); Ok(()) @@ -148,11 +155,11 @@ fn listen_backward_delete_char_eof() -> std::io::Result<()> { #[test] fn listen_backward_kill_word() -> std::io::Result<()> { - let (tmux, stream) = setup("backward_kill_word", &[])?; + let (tmux, mut stream) = setup("backward_kill_word", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "BackwardKillWord")?; + send(&mut stream, "backward-kill-word")?; @capture[0]trim().eq("> hello"); ); Ok(()) @@ -160,11 +167,11 @@ fn listen_backward_kill_word() -> std::io::Result<()> { #[test] fn listen_backward_word() -> std::io::Result<()> { - let (tmux, stream) = setup("backward_word", &[])?; + let (tmux, mut stream) = setup("backward_word", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]starts_with("> hello world"); - send(&stream, "BackwardWord")?; + send(&mut stream, "backward-word")?; @keys Key('|'); @capture[0]trim().eq("> hello |world"); ); @@ -173,12 +180,12 @@ fn listen_backward_word() -> std::io::Result<()> { #[test] fn listen_end_of_line() -> std::io::Result<()> { - let (tmux, stream) = setup("end_of_line", &[])?; + let (tmux, mut stream) = setup("end_of_line", &[])?; sk_test!(@expand tmux; @keys Str("hello"); @capture[0]trim().eq("> hello"); - send(&stream, "BeginningOfLine")?; - send(&stream, "EndOfLine")?; + send(&mut stream, "beginning-of-line")?; + send(&mut stream, "end-of-line")?; @keys Key('X'); @capture[0]trim().eq("> helloX"); ); @@ -187,11 +194,11 @@ fn listen_end_of_line() -> std::io::Result<()> { #[test] fn listen_first() -> std::io::Result<()> { - let (tmux, stream) = setup("first", &[])?; + let (tmux, mut stream) = setup("first", &[])?; sk_test!(@expand tmux; @keys Up, Up; @capture[4]starts_with("> c"); - send(&stream, "First")?; + send(&mut stream, "first")?; @capture[2]starts_with("> a"); ); Ok(()) @@ -199,12 +206,12 @@ fn listen_first() -> std::io::Result<()> { #[test] fn listen_forward_char() -> std::io::Result<()> { - let (tmux, stream) = setup("forward_char", &[])?; + let (tmux, mut stream) = setup("forward_char", &[])?; sk_test!(@expand tmux; @keys Str("hello"); @capture[0]trim().eq("> hello"); - send(&stream, "BeginningOfLine")?; - send(&stream, "ForwardChar")?; + send(&mut stream, "beginning-of-line")?; + send(&mut stream, "forward-char")?; @keys Key('X'); @capture[0]trim().eq("> hXello"); ); @@ -213,12 +220,12 @@ fn listen_forward_char() -> std::io::Result<()> { #[test] fn listen_forward_word() -> std::io::Result<()> { - let (tmux, stream) = setup("forward_word", &[])?; + let (tmux, mut stream) = setup("forward_word", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "BeginningOfLine")?; - send(&stream, "ForwardWord")?; + send(&mut stream, "beginning-of-line")?; + send(&mut stream, "forward-word")?; @keys Key('X'); @capture[0]trim().eq("> helloX world"); ); @@ -227,12 +234,12 @@ fn listen_forward_word() -> std::io::Result<()> { #[test] fn listen_kill_line() -> std::io::Result<()> { - let (tmux, stream) = setup("kill_line", &[])?; + let (tmux, mut stream) = setup("kill_line", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "BackwardWord")?; - send(&stream, "KillLine")?; + send(&mut stream, "backward-word")?; + send(&mut stream, "kill-line")?; @capture[0]trim().eq("> hello"); ); Ok(()) @@ -240,12 +247,12 @@ fn listen_kill_line() -> std::io::Result<()> { #[test] fn listen_kill_word() -> std::io::Result<()> { - let (tmux, stream) = setup("kill_word", &[])?; + let (tmux, mut stream) = setup("kill_word", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "BeginningOfLine")?; - send(&stream, "KillWord")?; + send(&mut stream, "beginning-of-line")?; + send(&mut stream, "kill-word")?; @capture[0]trim().eq("> world"); ); Ok(()) @@ -253,11 +260,11 @@ fn listen_kill_word() -> std::io::Result<()> { #[test] fn listen_last() -> std::io::Result<()> { - let (tmux, stream) = setup("last", &[])?; + let (tmux, mut stream) = setup("last", &[])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); @capture[5]trim().eq("d"); - send(&stream, "Last")?; + send(&mut stream, "last")?; @capture[5]starts_with("> d"); ); Ok(()) @@ -266,10 +273,10 @@ fn listen_last() -> std::io::Result<()> { // Test Reload action with command #[test] fn listen_reload_cmd() -> std::io::Result<()> { - let (tmux, stream) = setup("reload_cmd", &[])?; + let (tmux, mut stream) = setup("reload_cmd", &[])?; sk_test!(@expand tmux; @capture[1]trim().contains("4/4"); - send(&stream, "Reload(Some(\"printf 'x\\\\ny\\\\nz'\"))")?; + send(&mut stream, "reload(printf 'x\\ny\\nz'))")?; @capture[2]starts_with("> x"); ); Ok(()) @@ -277,9 +284,9 @@ fn listen_reload_cmd() -> std::io::Result<()> { #[test] fn listen_select_all() -> std::io::Result<()> { - let (tmux, stream) = setup("select_all", &["-m"])?; + let (tmux, mut stream) = setup("select_all", &["-m"])?; sk_test!(@expand tmux; - send(&stream, "SelectAll")?; + send(&mut stream, "select-all")?; @capture[2]trim().eq(">>a"); @capture[3]trim().eq(">b"); @capture[4]trim().eq(">c"); @@ -289,10 +296,10 @@ fn listen_select_all() -> std::io::Result<()> { #[test] fn listen_select_row() -> std::io::Result<()> { - let (tmux, stream) = setup("select_row", &["-m"])?; + let (tmux, mut stream) = setup("select_row", &["-m"])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); - send(&stream, "SelectRow(2)")?; + send(&mut stream, "select-row(2)")?; @capture[2]trim().eq("> a"); @capture[4]trim().eq(">c"); ); @@ -301,9 +308,9 @@ fn listen_select_row() -> std::io::Result<()> { #[test] fn listen_select() -> std::io::Result<()> { - let (tmux, stream) = setup("select", &["-m"])?; + let (tmux, mut stream) = setup("select", &["-m"])?; sk_test!(@expand tmux; - send(&stream, "Select")?; + send(&mut stream, "select")?; @capture[2]starts_with(">>"); ); Ok(()) @@ -311,11 +318,11 @@ fn listen_select() -> std::io::Result<()> { #[test] fn listen_toggle() -> std::io::Result<()> { - let (tmux, stream) = setup("toggle", &["-m"])?; + let (tmux, mut stream) = setup("toggle", &["-m"])?; sk_test!(@expand tmux; - send(&stream, "Toggle")?; + send(&mut stream, "toggle")?; @capture[2]starts_with(">>a"); - send(&stream, "Toggle")?; + send(&mut stream, "toggle")?; @capture[2]starts_with("> a"); ); Ok(()) @@ -323,9 +330,9 @@ fn listen_toggle() -> std::io::Result<()> { #[test] fn listen_toggle_all() -> std::io::Result<()> { - let (tmux, stream) = setup("toggle_all", &["-m"])?; + let (tmux, mut stream) = setup("toggle_all", &["-m"])?; sk_test!(@expand tmux; - send(&stream, "ToggleAll")?; + send(&mut stream, "toggle-all")?; @capture[2]starts_with(">>a"); @capture[3]trim().eq(">b"); @capture[4]trim().eq(">c"); @@ -335,12 +342,12 @@ fn listen_toggle_all() -> std::io::Result<()> { #[test] fn listen_toggle_in() -> std::io::Result<()> { - let (tmux, stream) = setup("toggle_in", &["-m"])?; + let (tmux, mut stream) = setup("toggle_in", &["-m"])?; sk_test!(@expand tmux; @keys Up; @capture[2]trim().starts_with("a"); @capture[3]starts_with("> b"); - send(&stream, "ToggleIn")?; + send(&mut stream, "toggle-in")?; @capture[2]starts_with("> a"); @capture[3]trim().starts_with(">b"); ); @@ -349,11 +356,11 @@ fn listen_toggle_in() -> std::io::Result<()> { #[test] fn listen_toggle_out() -> std::io::Result<()> { - let (tmux, stream) = setup("toggle_out", &["-m"])?; + let (tmux, mut stream) = setup("toggle_out", &["-m"])?; sk_test!(@expand tmux; @capture[2]starts_with("> a"); @capture[3]trim().starts_with("b"); - send(&stream, "ToggleOut")?; + send(&mut stream, "toggle-out")?; @capture[2]trim().starts_with(">a"); @capture[3]starts_with("> b"); ); @@ -363,11 +370,11 @@ fn listen_toggle_out() -> std::io::Result<()> { // Test Top action (alias for First) #[test] fn listen_top() -> std::io::Result<()> { - let (tmux, stream) = setup("top", &[])?; + let (tmux, mut stream) = setup("top", &[])?; sk_test!(@expand tmux; @keys Up, Up; @capture[4]starts_with("> c"); - send(&stream, "Top")?; + send(&mut stream, "top")?; @capture[2]starts_with("> a"); ); Ok(()) @@ -375,11 +382,11 @@ fn listen_top() -> std::io::Result<()> { #[test] fn listen_unix_line_discard() -> std::io::Result<()> { - let (tmux, stream) = setup("unix_line_discard", &[])?; + let (tmux, mut stream) = setup("unix_line_discard", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "UnixLineDiscard")?; + send(&mut stream, "unix-line-discard")?; @capture[0]trim().eq(">"); ); Ok(()) @@ -387,11 +394,11 @@ fn listen_unix_line_discard() -> std::io::Result<()> { #[test] fn listen_unix_word_rubout() -> std::io::Result<()> { - let (tmux, stream) = setup("unix_word_rubout", &[])?; + let (tmux, mut stream) = setup("unix_word_rubout", &[])?; sk_test!(@expand tmux; @keys Str("hello world"); @capture[0]trim().eq("> hello world"); - send(&stream, "UnixWordRubout")?; + send(&mut stream, "unix-word-rubout")?; @capture[0]trim().eq("> hello"); ); Ok(()) @@ -399,13 +406,13 @@ fn listen_unix_word_rubout() -> std::io::Result<()> { #[test] fn listen_yank() -> std::io::Result<()> { - let (tmux, stream) = setup("yank", &[])?; + let (tmux, mut stream) = setup("yank", &[])?; sk_test!(@expand tmux; @keys Str("hello"); @capture[0]trim().eq("> hello"); - send(&stream, "BackwardKillWord")?; + send(&mut stream, "backward-kill-word")?; @capture[0]trim().eq(">"); - send(&stream, "Yank")?; + send(&mut stream, "yank")?; @capture[0]trim().eq("> hello"); ); Ok(())