Skip to content

Commit

Permalink
better handling of tmux
Browse files Browse the repository at this point in the history
  • Loading branch information
LoricAndre committed Nov 27, 2024
1 parent be8c1da commit ba129cb
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 36 deletions.
77 changes: 68 additions & 9 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 skim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ beef = "0.5.2" # compact cow
defer-drop = "1.3.0"
indexmap = "2.6.0"
rand = "0.8.5"
tmux_interface = "0.3.2"
which = "7.0.0"

[features]
default = ["cli"]
Expand Down
29 changes: 16 additions & 13 deletions skim/src/tmux.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::{
borrow::Cow,
io::{BufRead as _, BufReader, BufWriter, IsTerminal as _, Write as _},
process::Command,
process::{Command, Stdio},
sync::Arc,
thread,
};

use rand::{distributions::Alphanumeric, Rng};
use tuikit::key::Key;
use which::which;

use crate::{event::Event, SkimItem, SkimOptions, SkimOutput};

Expand Down Expand Up @@ -160,19 +161,19 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
// Run downstream sk in tmux
let raw_tmux_opts = &opts.tmux.clone().unwrap();
let tmux_opts = TmuxOptions::from(raw_tmux_opts);
let mut tmux_cmd = Command::new("/bin/tmux");
let mut tmux_cmd = Command::new(which("tmux").unwrap_or_else(|e| panic!("Failed to find tmux in path: {}", e)));

tmux_cmd
.arg("display-popup")
.args(["-E", "-E"])
.arg("-E")
.args(["-d", std::env::current_dir().unwrap().to_str().unwrap()])
.args(["-h", tmux_opts.height])
.args(["-w", tmux_opts.width])
.args(["-x", tmux_opts.x])
.args(["-y", tmux_opts.y]);

for (name, value) in std::env::vars() {
if name.starts_with("SKIM") {
if name.starts_with("SKIM") || name == "PATH" {
debug!("adding {} = {} to the command's env", name, value);
tmux_cmd.args(["-e", &format!("{}={}", name, value)]);
}
Expand All @@ -182,28 +183,30 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {

debug!("tmux command: {:?}", tmux_cmd);

let out = tmux_cmd
.output()
let status = tmux_cmd
.stdout(Stdio::null())
.stderr(Stdio::null())
.stdin(Stdio::null())
.status()
.unwrap_or_else(|e| panic!("Tmux invocation failed with {}", e));

debug!("Tmux returned {:?}", out);

if let Some(h) = stdin_handle {
h.join().unwrap_or(());
}

let output_ending = if opts.print0 { "\0" } else { "\n" };
let stdout_bytes = std::fs::read_to_string(tmp_stdout).unwrap_or_default();
let mut stdout_bytes = std::fs::read_to_string(tmp_stdout).unwrap_or_default();
stdout_bytes.pop();
let mut stdout = stdout_bytes.split(output_ending);
// let _ = std::fs::remove_dir_all(temp_dir);
let _ = std::fs::remove_dir_all(temp_dir);

let query_str = if opts.print_query && out.status.success() {
let query_str = if opts.print_query && status.success() {
stdout.next().expect("Not enough lines to unpack in downstream result")
} else {
""
};

let command_str = if opts.print_cmd && out.status.success() {
let command_str = if opts.print_cmd && status.success() {
stdout.next().expect("Not enough lines to unpack in downstream result")
} else {
""
Expand All @@ -215,7 +218,7 @@ pub fn run_with(opts: &SkimOptions) -> Option<SkimOutput> {
output_lines.push(Arc::new(SkimTmuxOutput { line: line.to_string() }));
}

let is_abort = !out.status.success();
let is_abort = !status.success();
let final_event = match is_abort {
true => Event::EvActAbort,
false => Event::EvActAccept(None), // if --expect or --bind accept(key) are used,
Expand Down
6 changes: 2 additions & 4 deletions test/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ TEST_CLASS=test_skim.TestSkim

cd $(dirname "$0")
tests=$(sed -n 's/^\s\+def \(test_\w\+\)(self.*):\s*$/\1/p' test_skim.py | \
sk --multi)
sk --multi --bind 'ctrl-a:select-all' | xargs -I% echo "$TEST_CLASS.%")

cargo build --release

for test in $tests; do
python3 -m unittest $TEST_CLASS.$test
done
python3 -m unittest $tests
22 changes: 13 additions & 9 deletions test/test_skim.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,26 +1233,30 @@ def setup_tmux_mock(self):
self.tmux.send_keys(
f'mkdir -p {bin_test_dir}; export PATH="{bin_test_dir}:$PATH"; cp {mock_bin} {bin_test_dir}/tmux; chmod +x {bin_test_dir}/*', Key('Enter'))

def test_tmux_stdin(self):
def test_tmux_vanilla(self):
args = '--tmux'
self.setup_tmux_mock()
self.tmux.send_keys(
f"""echo -e 'a\\nb\\nc' | {self.sk(args)}""", Key('Enter'))
self.tmux.send_keys(self.sk(args), Key('Enter'))
with open('/tmp/sk-test-mock/stdout', 'r') as f:
tmux_cmd = f.readlines()[-1].strip()

self.assertTrue(tmux_cmd.startswith("popup"))
self.assertRegex(tmux_cmd, "< *[^ ]*/sk-tmux-")
self.assertTrue(tmux_cmd.startswith("display-popup"))
self.assertIn(" -E ", tmux_cmd)
self.assertIn(f"{BASE}/target/release/sk", tmux_cmd)
self.assertNotRegex(tmux_cmd, "< *[^ ]*/sk-tmux-")

def test_tmux_vanilla(self):
def test_tmux_stdin(self):
args = '--tmux'
self.setup_tmux_mock()
self.tmux.send_keys(self.sk(args), Key('Enter'))
self.tmux.send_keys(
f"""echo -e 'a\\nb\\nc' | {self.sk(args)}""", Key('Enter'))
self.tmux.until(lambda _: os.path.exists('/tmp/sk-test-mock/stdout'))
with open('/tmp/sk-test-mock/stdout', 'r') as f:
tmux_cmd = f.readlines()[-1].strip()

self.assertTrue(tmux_cmd.startswith("popup"))
self.assertNotRegex(tmux_cmd, "< *[^ ]*/sk-tmux-")
print(tmux_cmd)
self.assertTrue(tmux_cmd.startswith("display-popup"))
self.assertRegex(tmux_cmd, "< *[^ ]*/sk-tmux-")

def test_reload_no_arg(self):
args = "--bind 'ctrl-a:reload'"
Expand Down

0 comments on commit ba129cb

Please sign in to comment.