-
-
Notifications
You must be signed in to change notification settings - Fork 681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: How to dump the terminal output #1353
Comments
Hey @cosminadrianpopescu - I'm happy to read you're excited about Zellij! I'd be happy to guide you through implementing this feature, but maybe as a first step - since you mention you're not very proficient with Rust - let's see if this is something that would make sense for you to implement? It could be a pretty big feature (though not super complex if you're willing to devote some time to it). We keep the viewport of each Each Would you like to take a look through that area of the code and let me know if it makes sense to you? If so I'd be happy to discuss steps on how to implement this. |
I would imagine is something on these lines? if let Ok(mut f) = File::create("/tmp/dump.screen") {
for line in &self.lines_above {
for char in &line.columns { // Here I'm sure there is a smarter way to get the columns as a string.
write!(f, "{}", char.character);
}
writeln!(f);
}
} What about the widht from |
Actually, I think I see the point of canonical. I think I was looking at it the other way around. But probably I need to wrap the writeline in an if depending on canonical, something like this: if line.is_canonical {
writeln!(f);
} |
Yes, that should do the trick - except we would of course need to adjust it a little to the codebase (eg. not use write! directly but rather use our os_input_output interface) - we can totally worry about those things later once we have a basic implementation. I'll guide you through it.
No need, you can safely ignore it and write the characters to disk. Handling the width will be the responsibility of whoever opens the file.
Yes! This is a good and simple solution. |
Here is a more robust way of the code above: if let Ok(mut f) = File::create("/tmp/log") {
for line in &self.lines_above {
let s: String = (&line.columns).into_iter().map(|x| x.character).collect();
write!(f, "{}", s);
if line.is_canonical {
writeln!(f);
}
}
} Let me know what you think. I would really be interested in developping this feature. With this feature added, I can completely forget about tmux. The search is the last piece missing and this would also allow me to stay inside of the tty, since after dumping the buffer I can easily also copy / paste from vim to the xclip without the help of the mouse (which is missing in the tty). |
I really never thought of it (searching and copy pasting from the buffer) in this way. I think your idea (of dumping the buffer in a file rather than trying to implement a selection and a search command and so on) is brilliant. |
I'm not 100% sure, but I think your first solution is a tiny bit more performant (less heap allocations), but it doesn't really matter in this case :) And thanks! My ideal solution would be to temporarily replace the current pane with your default editor to make it even more seamless, but that'll for sure come later in addition to this feature. Also, classic search is being worked on as well. So a solution for every taste! Anyway - this all sounds great, I'd be very happy if you implement this. How can I help? Shall we break it down to steps, do you have a different idea? |
That indeed would be a perfect solution.
Yes, also classic search is not bad (I've used it in tmux for years). But your solution (with dumping the screen in a file) is perfect. Anyways, my idea is that then I will set up a shortcut which will dump the screen and open the file automatically in a popup pane. So it would be as close as possible of your first idea, with 0 effort. What I'm thinking is that this code (let me know if it needs some more polishing, as I told you I'm not expert in rust) can be called by a new Action. And the next step is to properly implement a new Action (following as a model one of the existing actions). Does this sounds ok? Do you have any advice for me? And this code should reside in the |
I would encourage you to make this action as program agnostic as possible. |
I think you misunderstood. What this feature would implement would be only an Action like Then, all the rest is done via config, like for example: - action: [DumpScreen, Run: {cmd: nvim, args: [/tmp/log.sh, +normal G]}, SwitchToMode: Locked, ]
key: [Char: '/'] The opening of the editor and so on would not be part of the code. |
Hey @cosminadrianpopescu , I think your solution is pretty cool. Let's get it implemented!
It sounds good. Either one of the functions is fine (at first glance, I'll give it another go over once you make a PR ofc). A few notes on structure:
Then there's a bit of threading you need to do to create the action and pass it from Makes sense? I can expand on whichever part you want or explain things differently. *If it makes more sense to you, you can also call it |
Yes, I think I did misunderstand you. It sounded like there was much more hard coding going on in the beginning. What you propose is exactly what I had in mind. |
I was thinking that the file name can be set via config or hard coded. The folder it will be the system temp folder and the name something deterministic. The idea is that after the screen is dumped I want to have an action to be able to automatically open that file, and since the commands don't return an output to the next command in chain, I would have to manually open the file, if the name is not deterministic. What do you think? - action: [DumpScreen, Run: {cmd: nvim, args: [/tmp/log.sh, +normal G]}, SwitchToMode: Locked, ]
key: [Char: '/'] I will start develop and let you know when I have a PR. Also, I will add here any questions I might have. |
Or maybe the - action: [DumpScreen: /tmp/log.sh, Run: {cmd: nvim, args: [/tmp/log.sh, +normal G]}, SwitchToMode: Locked, ]
key: [Char: '/'] |
Hum... what happens though if you trigger the action on another pane before you closed the first one? I guess since this happens "in user space" this is up to you, but it would be nice to also have an option to dump it to a random temporary file. I'm not sure what the story right now is to have optional parameters to (don't let this stop you though @cosminadrianpopescu, you can start developing for your use case and we'll sort it out as we go) |
I began devleoping the feature. I have one question. I see that in order to define a new Action, I need to include in the 62 | impl Pane for PluginPane {
| ^^^^^^^^^^^^^^^^^^^^^^^^ missing `dump_screen` in implementation |
I'm not sure I follow. I would say that the parameter to the |
Another question is how do I run the test cases? |
Some quick answers because I'm on the road:
For running the tests you can take a look at contributing.md... The method
can be a noop for plugin pane for now, we'll clean it up later
…On Sun, May 1, 2022, 9:44 AM Cosmin Popescu ***@***.***> wrote:
Another question is how do I run the test cases?
—
Reply to this email directly, view it on GitHub
<#1353 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGCHTSC2OJRP5R523X6OJTVHYY5VANCNFSM5UPRLKAQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
That's fine, because that's what I implemented so far. Just a fn dump_screen(&mut self, _client_id: ClientId) -> String {
return "".to_owned();
} |
Do you have any idea what this message means:
Basically I did the work with a hard coded name and it works fine. Now I'm trying to add the Thank you. |
It's this line: https://github.com/zellij-org/zellij/blob/main/zellij-utils/src/input/plugins.rs#L21 |
Btw @cosminadrianpopescu - the more I think about it the more I feel it would be better to at least start with the file path parameter being mandatory. We don't have a good and easy way to display messages to the user yet, so if we create a random temp file name it'll be hard to let the user know about it. We might be escaping this problem for now by making it mandatory. wdyt? |
Does it work when starting zellij with: |
Optional parameters to I'm fine with going ahead an getting some sort of workable solution here. The initial reason I did not open a pr for this: I imagined this working together with a formatting system with some sort of interpolation. I really need to write the formatting issue up soon. |
No. |
This is what I tried to emulate. I wonder if being an |
Without |
I will have an initial PR as soon as I clear out some warnings (it should be preety soon). |
That is quite weird. And it also doesn't work when starting with just the default configuration? |
I've opened an initial PR. For the test cases, I'm trying to implement some, but I see that the function fn write_to_tty_stdin(&self, _fd: RawFd, _buf: &[u8]) -> Result<usize, nix::Error> {
unimplemented!()
} |
Hey @cosminadrianpopescu - very cool to see you open an initial PR so quickly! About testing: while Zellij has e2e tests, we only use them to kind of make sure "things are connected" and try not to add many tests there. The reason is that (like most e2e tests) they are quite fragile and tend towards flakiness. So we use them only when absolutely necessary. For this use case, I'd check out the tab integration tests here: https://github.com/zellij-org/zellij/blob/main/zellij-server/src/tab/unit/tab_integration_tests.rs In these tests we call the methods on tab directly and then snapshot the output. In this case snapshotting the output won't make a whole lot of sense, so instead what I'd go for is to create a mock method on I plan on taking a look at the draft PR tomorrow and maybe then I'll have more specific ideas once I see how you implemented this. |
A thousand pardons for not getting to this yet @cosminadrianpopescu ! 🙏 |
Don't worry. There is no rush. I am using the feature already. I will open another ticket for another idea, to discuss. I've seen the discussion page, so I'll put it there. |
* Initial commit for fixing #1353 * adding a new line between the lines_above and the viewport * changes following code review * implementing a test case for the dump screen * implemented test case for dump_screen * better regexp replace * fixes following code review * style(api): remove extraneous method in plugin pane * style(fmt): rustfmt * style(tests): fix method name Co-authored-by: Aram Drevekenin <aram@poor.dev>
@cosminadrianpopescu, But you can already dump the pane there with:
|
Hello,
I'm a long time tmux user, I'm in the process of switching to zellij (due to the floating panels) and I'm missing the search in buffer.
I've seen in a post on reddit that you intend to implement a command to dump the terminal output (with all the scroll) into a file. I think this is an amazing idea which would leave tmux so far behind.
I would be interested in this.
Can you please explain what it involves, from a development point of view? I'm a developer, I've developed in my life in many languages, but not in Rust. However, I would be willing to see what I can come up with.
The text was updated successfully, but these errors were encountered: