zellij-org / zellij

A terminal workspace with batteries included
https://zellij.dev
MIT License
20.47k stars 637 forks source link

Allow zellij run CLI command to block until command has completed #3018

Closed blefevre closed 4 months ago

blefevre commented 8 months ago

The zellij run command should have the ability to block until the command being run has exited.

This would allow zellij to be invoked in scripts or shortcuts to perform actions and then have control returned to the caller.

For example, my use case is using Helix keybinds to invoke the Yazi file browser to select a file to which will then be opened in Helix. However currently I am unable to block until I've selected a file as the zellij command immediately exits.

skariel commented 6 months ago

+1. I need this feature to send text to the repl from Helix. See here how it's done for tmux. The idea is to focu on a pane, send text, send the enter key, and focus back on Helix

rockboynton commented 4 months ago

I have this working with Yazi and Helix specifically:

# config.toml
[keys.normal."'"]
y = ":sh zellij run --floating -n 'yazi picker' -- /home/rboynton/.config/fish/scripts/open_in_helix_from_yazi.fish"
# open_in_helix_from_yazi.fish
set -l tmpfile /tmp/yazi-choice.txt
rm -f $tmpfile
yazi --chooser-file=$tmpfile
zellij action toggle-floating-panes
zellij action write 27 # send escape-key
zellij action write-chars ":open $(cat /tmp/yazi-choice.txt)"
zellij action write 13 # send enter-key
zellij action toggle-floating-panes
zellij action close-pane
sxyazi commented 4 months ago

Cool, thank you for sharing it! @rockboynton

Would you like to submit a PR and add it to the Tips page of the Yazi document? This way more people can see it.

Edit: Added to https://yazi-rs.github.io/docs/tips/#helix-with-zellij, fell free to use it ;)

https://github.com/zellij-org/zellij/assets/17523360/4b47ec6b-0282-44ab-814d-d25c0e8d6cf5


BTW I saw this comment from https://www.reddit.com/r/HelixEditor/comments/1chvan1/how_are_people_using_their_cli_file_explorers, hope I'm not too late here ;)

postsolar commented 4 months ago

In the meantime, one workaround to achieve blocking calls to zellij run would be to use FIFOs (aka named pipes). It's a bit hacky but still simple enough. Here's an example with fish:

set id (uuidgen)
mkfifo /tmp/$id
zellij run -fc -- fish -c "fzf | tee /tmp/$id"
cat < /tmp/$id > /dev/null
rm -rf /tmp/$id

This will run fzf and block until the command is done executing.

Or, even shorter with process signals:

zellij run -fc -- fish -c "fzf; kill -s CONT $fish_pid"
kill -s STOP $fish_pid
CraigglesO commented 4 months ago

Hopefully this isn't hijacking but I'd like to propose that if this kind of enhancement is deemed worthwhile, to allow options for both block AND orphan. Orphan option meaning I can run a command that runs separate to the pane and/or tab so that I can immediately close it.

rockboynton commented 4 months ago

Cool, thank you for sharing it! @rockboynton

Would you like to submit a PR and add it to the Tips page of the Yazi document? This way more people can see it.

BTW I saw this comment from https://www.reddit.com/r/HelixEditor/comments/1chvan1/how_are_people_using_their_cli_file_explorers, hope I'm not too late here ;)

@sxyazi Done! https://github.com/yazi-rs/yazi-rs.github.io/pull/61

blixenkrone commented 4 months ago

Thanks @rockboynton and @postsolar!

Here's (single file) using zsh:

# open_in_helix_from_yazi.zsh
file=$(yazi --chooser-file=/dev/stdout | cat)
zellij action toggle-floating-panes
zellij action write 27 # send escape-key
zellij action write-chars ":open $(command printf '%q' "$file")"
zellij action write 13 # send enter-key
zellij action toggle-floating-panes
zellij action close-pane
postsolar commented 4 months ago

@blixenkrone you can open multiple files at once if you change it to

files=(${(fqq)"$( yazi --chooser-file=/dev/stdout | cat )"})
zellij action toggle-floating-panes
zellij action write 27 # send escape-key
zellij action write-chars ":open $files"
zellij action write 13 # send enter-key
zellij action toggle-floating-panes
zellij action close-pane

This handles their quoting too.

peteringram0 commented 4 months ago

@blixenkrone you can open multiple files at once if you change it to

files=(${(fqq)"$( yazi --chooser-file=/dev/stdout | cat )"})
zellij action toggle-floating-panes
zellij action write 27 # send escape-key
zellij action write-chars ":open $files"
zellij action write 13 # send enter-key
zellij action toggle-floating-panes
zellij action close-pane

This handles their quoting too.

With this version i get the error "wrong argument count".

postsolar commented 4 months ago

With this version i get the error "wrong argument count".

You're probably executing the script with bash, not zsh, perhaps due to not adding the shebang? Try adding #! /usr/bin/env zsh as the very first line. Or run the bash version from yazi docs

blixenkrone commented 4 months ago

@postsolar Yeah thanks, I figured that too, but I typically dont want to open more than one file at a time, hence why I made single file only. Yours does work fine as well. Cheers mate.

imsnif commented 4 months ago

Thanks for suggesting this feature.

A few things:

  1. This is possible with plugins using the new pipe interface. The flow would be "pipe to a plugin from the CLI which will be launched if not running, the plugin could either do whatever it wants on its own or launch a command passed to it, then unblock the CLI once the command is done".
  2. Zellij also has in a built-in filepicker that does exactly this. Maybe it's not as nice as the dedicated Yazi, but it can at least serve as an example of how this can be achieved.

While I totally empathize with people wanting this to be part of core, the philosophy of this project is to offload as much as possible to plugins in order to help us maintainers keep up. If someone makes a generic plugin that blocks until a command is done, I'd be happy to link to it and refer to it when this comes up.

ADDENDUM: if someone is interested in implementing this plugin and wants support, they are welcome to join our Discord - there are lots of plugin authors there who'd be happy to help.

xtrasmal commented 4 months ago

The bash script assumes that the escape key puts the mode back to normal. In my case, the escape key is mapped to capslock and within Helix, my escape key toggles between NORMAL and INSERT mode. So consider making it explicit by mapping the keys in the Helix config like this:

# ~/.config/helix/config.toml
[keys.normal]
C-y = [
  "normal_mode",
  ":sh zellij run -f -- bash ~/picker.sh"
]

and do not write the escape key in the sh script.