Closed stratosgear closed 1 year ago
Hey! Thanks for taking the time in opening this issue, this has been a pain point for quite a while. We have been thinking how to best alleviate this. An extra config option seems like a sensible addition.
Currently we would start a command as follows:
Run:
cmd: <path>,
args: [ARGS],
direction: <direction>,
I can see the value in adding something along the lines of:
Run:
cmd: <path>,
args: [ARGS],
direction: <direction>,
pane: keep_open
With it defaulting to true. If you set it to false You can run the command Without opening an extra pane.
I am not sure about the naming, though I think that this would be very valuable.
What do you think @stratosgear ?
IMO it can also be cool to re-run the command when focused on the pane and pressing ENTER.
Pressing enter, as suggested by @imsnif deviates too much from a "normal" terminal window. I would prefer if the process into that pane behaved like any other terminal window.
Since I also think that the pane window should always remain open (I am sure the error output of a failed process, might contain valuable info that you do not want lost), a config param of keep_open
should default to True, and for the minority (?) of people that want to have the pane autoclose they could use a keep_open: false
?
Maybe @imsnif suggestion could be implemented with an auto_reload: true
that would reload on Enter? But that would have to be specifically activated, so you know that you have such a "feature" active on that pane.
And that's all I have to say about that.... :)
@stratosgear - I totally get what you're saying. It's also important to me not to deviate too much from the way a normal terminal window behaves.
In this case however, the command has exited. Since we don't defer back to a shell in this case like a normal terminal window (since that's not something the user asked us to do), there isn't really any equivalent. The command is done and isn't accepting input any longer. I propose this feature only be available in this case, not when the command is still running. How would you feel about that?
Normal terminal windows usually have a keep-open
flag that keeps the window open
after a command finishes.
For example on alacritty that would be --hold
, thats why I think the default behaviour of closing
the pane when a program exits would be desirable. But I am OK if we decide differently in the end.
I didn't know about the keep-open
flag. Thanks!
I guess this would depend on the use-cases we're talking about and what we think the main one would be. For me the use-case of defaulting to keep-open
and being able to re-run with ENTER
is something I'd like to do with eg. cargo test
(when I don't want it to run on every file change in a loop).
What use-cases do you imagine defaulting to keep-open
being false, @a-kenji?
Also, @stratosgear - what use-cases would you not like the ENTER
to re-run functionality to overwrite?
As I mentioned my use case is that these panes are running a startup script that starts my development server in debug mode.
With tmux (where each pane was a standalone, self sufficient terminal), two things would usually happen:
Up arrow
and Enter
to restart my process. CTRL+C
. Then, once again: Up arrow
and Enter
to restart my process. In that case an auto-closing (or autorefreshing) pane would not be an issue, since there is no content that I would need to see between the restarts.So I guess I need both cases, somehow active.
And to be honest, I still have troubles groking why the panes cannot be normal terminals. Maybe I am too much invested in the mentality of tmux, where each pane is a "standalone" terminal that has a very stable deeply ingrained mentality of how it works.
Maybe the processes I have to start inside the panes, have to be just bash shells? But then I need to start a bash shell, with an initial startup command, like bash start_server.sh
Is this even doable?
So when my process finishes I drop back to the bash shell that started my process...? Does that make sense?
For what it's worth, I run kitty
as my terminal.
And contrary to what @a-kenji mentions above, I have never seen a "normal" terminal window quit, once a process that is started from within, terminates. They usually drop back to the shell afterwards, no...? Maybe they can be configured that way, but that's not a default setting.
Maybe I misunderstood, and he is talking about something else?
Some background (in a simplified manner):
Any terminal window (including a Zellij pane) is talking to another program that's running on the other side of the pty. Normally this is the shell. When you run something from within the shell, the shell itself defers to that process and forwards its stdout to the terminal and the terminal's stdin to said process. Eg. your script. When the script exits, you drop back into the shell.
Zellij and tmux panes work in the same way. They run a shell by default and when you run processes in that shell, they talk to those processes (this whole system is transparent to the multiplexer of course).
When you tell tmux to run a command in a pane, what it does (presumably by what you describe, I have not looked at the code) is forward your command to a pane running your default shell just as if you typed it in.
Zellij can do this, but IMO this is a bit hacky and we can definitely do better here. I feel it can be very powerful to give users the power to decide what they'd like to do inside a new pane. They can run a command regardless of which shell runs there, and have the pane interact directly with the command. Imagine running your dev script in a pane normally, being able to interact with it just as you did, and when it exits, you will see something like this:
┌ <your script name> ─────────────────────────────────────────┐
│ Your script output which you can scroll through and resize │
│ as you would any other pane │
│ │
│ │
│ │
│ │
│ │
└ EXIT STATUS: 2 (error), <ENTER> to rerun ───────────────────┘
To me this sounds like it not only gives you both cases, but saves you having to press the Up arrow
(you just have to press ENTER instead) and gives you a clearer visual indication that the script has terminated. But maybe I'm missing something about your use case... what do you think?
Hehe, I thought creating something as nice as your ASCII drawing from above shows, would be much more work than implementing something that (maybe naively) I thought would be much easier to do.
So if you think that creating something as interactive as the above, is feasible, then by all means. I would definitely agree that if you can do better (and I believe that you can) with these panes, is a much better goal!
From your description I also assume that a CTRL+C
will also result in this message from above, right?
From your description I also assume that a
CTRL+C
will also result in this message from above, right?
Yes, exactly (well, assuming the process responds to ctrl-c by exiting, but yeah :) ).
I'm happy you like the approach. It isn't that much work to implement, and is a direction I personally want to take Zellij anyway. While on the whole this isn't more work than creating a tmux-like solution, the incremental implementation that I'd recommend taking here might mean that there will be a gap where we'll be a little less good than tmux before we add everything else. So I hope you'll bear with us. :)
I'm going to put a Help Wanted
tag on this issue if anyone wants to pick it up. Otherwise I'll try to get to it sometime in the near future. Here's a rough plan for implementing this:
remain_open: bool
flag to the Layout. These panes should only close if the user explicitly closes them, rather than if their process exits.Option<u8>
on the TerminalPane
(a different solution can be found for plugins, but we can ignore them for now).TerminalPane
as an Option<String>
BoundariesFrame
to display the exit status if the pane exited (as well as the message in my ASCII drawing above) - bonus points if you'd like to change its color depending on the exit status (red for error, normal otherwise)ENTER
key, it should send a message to the Pty
thread to run the command in a new async task.I'd be more than happy to provide help and guidance if anyone wants/needs it.
What use-cases do you imagine defaulting to keep-open being false, @a-kenji?
For example opening a command like htop, looking quickly at the output it provides
and then closing the pane while closing the command itself. So you have a shortcut to launch the command, then can type q
and it will close the pane again.
And contrary to what @a-kenji mentions above, I have never seen a "normal" terminal window quit, once a process that is started from within, terminates. They usually drop back to the shell afterwards, no...? Maybe they can be configured that way, but that's not a default setting.
Yes, I think you misunderstood me, even kitty has the kitty --hold
flag.
And yes that is exactly how every single terminal I have come across behaves, also kitty.
For example the default configuration of kitty starts kitty with shell .
which is equivalent to $SHELL, so basically when just running kitty it would be equivalent to running
kitty -e $SHELL
.
And if you exit the shell the terminal usually does terminate.
Try it out yourself. Run kitty -e $SHELL
, then close the shell.
The terminal will close.
So when running kitty -e ls
the child process returns immediately
and the terminal closes again. When running kitty --hold -e ls
it waits
for you to put anything in there.
Add the remain_open: bool flag to the Layout. These panes should only close if the user explicitly closes them, rather than if their process exits.
I think that could maybe be a good way? But I think to address the original issue we would want to add a keep_open
or hold
flag to the cmd
configuration.
Those would be 2 separate contexts then.
I think that could maybe be a good way? But I think to address the original issue we would want to add a
keep_open
orhold
flag to thecmd
configuration. Those would be 2 separate contexts then.
Hum... why do you feel it would be better to add it to the command context and not on the pane itself?
Sorry for the additional confusion...
Add the remain_open: bool flag to the Layout. These panes should only close if the user explicitly closes them, rather than if their process exits.
How would you know that the user explicitly closed them? Does an explicit CTRL+C
differ from a failed process...? Or you mean to implement a specific zelliz command (shortcut?) that closes the pane for you, so it knows it was triggered by you...?
And thanks to @a-kenji for helping me better understand how terminals work:
Seeing the difference between kitty -e ls
and kitty --hold -e ls
was enlightening (hint, the first one opens a terminal with the ls
output and immediately closes, the second waits for a key press before closing)
How would you know that the user explicitly closed them? Does an explicit
CTRL+C
differ from a failed process...? Or you mean to implement a specific zelliz command (shortcut?) that closes the pane for you, so it knows it was triggered by you...?
Ctrl+C
is sent to the process itself (either that or directly send it SIGTERM, not sure about the implementation yet) and then the process closes itself. This will not close the pane in such a case.
Closing the pane through Zellij (eg. by doing ctrl+p
+ x
) will close the pane itself (and also kill the process) as happens now.
@stratosgear I am glad my description could help!
Hum... why do you feel it would be better to add it to the command context and not on the pane itself?
@imsnif, Because it is closely related to the command. Also I think these are 2 separate issues/features. That would both be good.
Have a --hold
flag for simple commands that return, that you can look over quickly
and want to be able to close again quickly, that is set to false by default.
It would behave like the --hold
in terminals, that would make it consistent with features
people might expect to be able to do.
So for example currently you can (assuming fish shell):
tabs:
- direction: Vertical
parts:
- direction: Vertical
run:
command:
cmd: "fish"
args: ["-C", "ls"]
- direction: Vertical
run:
command:
cmd: "htop"
Which would instruct fish to run ls and then you are still in a running fish shell and to run htop - quitting htop, or fish here would result in the pane to be closed.
A possible bash example:
- direction: Vertical
run:
command:
cmd: "bash"
args: ["-c", "ls; exec bash"]
With something like --hold
:
One could quickly open an ls.
- direction: Vertical
run:
command:
cmd: "ls"
hold: true
In which the pane would wait for input, after the child has already exited,
in order to kill the pane. That way a simple one off command could be
easily shown. Maybe even a quick grep
or rg
that can quickly be closed
again after one has found what they were looking for.
Currently without the hold
command, the pane in which ls would be executed
would be closed instantly.
A new pane type that makes it easier to rerun commands that are meant to be rerun:
Basically your proposal, I think it is pretty cool and we could even make it possible to
add an icon to the pane frame in order to re-run the last command once for convencience.
Also if we have the rerun pane, it could be really nice to for example have 3 panes of
cargo make run
& cargo make test
& cargo clippy
and synchronize all 3 and just run
them with an Enter.
I think these 2 concepts are kind of separate from each other, that is why I propose a hold
option for the command
type in the layout apart from the rerun pane.
@stratosgear On second thought, is that what you were trying to do?
I guess so!
My original assumption was that all panes opened would remain open (like having one of your "holds" default to on
) as this has been my previous experience from tmux (opening a pane meant opening a forever open terminal, unless you exited
or CTRL+d
)
So, you are describing a superset of what I wanted, therefore I think you are moving in the right direction... :)
For people that stumble on this issue. I have found a workaround for far:
run:
command:
cmd: zsh
args:
- "-c"
- "sleep 2 && task && zsh -i"
There currently the caveats:
Hello,
this feature is now implemented in zellij 0.32.0 and up as "command panes". Check out the blog post for the new release, which also includes a demo: https://zellij.dev/news/config-command-layouts/
In continuation of #551, where an arbitrary process could be started in each pane...
It seems that if the process ends, or I kill it, the pane closes.
My actual usecase, is to run some debug services in these panes, and as I continue developing I often do code changes and then need to restart them (CTRL+C then up arrow to rerun my latest command to bring them up again).
In the current implementation as soon as I stop the process the pane goes away, destroying my carefully layed out layout...
Can this be configurable? In tmux this is working much more intuitively.