Skip to content
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

feat: Add spawn vim docs #651

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

deepanchal
Copy link

@deepanchal deepanchal commented Jul 1, 2024

Description

This PR adds how-to-spawn-vim documentation under Recipes > Applications > Spawn External Editor (Vim)

I am now using hello-world-template as base for my example to keep things simple (31fc71c) and I have added logic to spawn vim in a separate commit (8380d5b).

I am not familiar with astro but I tried to use other examples as reference to write this documentation. Please let me know if I missed anything. Thanks!!

Related Issue

Ref #406

Images

localhost_4321_recipes_apps_spawn-vim_

@joshka
Copy link
Member

joshka commented Jul 1, 2024

This seems overly specific to the component template and has a lot of code just to show off the vim part. I have a few concerns with this:

If you were able to simplify this to an app that just showed off the problem and solution, this would be much clearer.
The problem are:

  • applications read events, either synchronously, in another thread, or in an async task via the event stream
  • applications manage the terminal state, such as raw mode, alternate screen, mouse capture etc.

The solution really needs to show off how to:

  • before spawning processes suspend / stop any event reading
  • restore the terminal state up that whatever your sub process needs to work properly
  • reset these after the sub process finishes
  • any abstractions like the component template on top of the plain crossterm stuff should probably be omitted (or perhaps noted for follow up with a some small snippets)

This likely should also have a bit of discussion about termion at the end that shows how to access the backend to do this (requires an unstable flag to get at the backend_mut function and call the suspend functions)

This is just my opinion - I know you've been working on this with @kdheepak who knows a lot more about this template than I do, so I'd let him chime in about whether this is worth keeping in this form or simplifying.

@deepanchal
Copy link
Author

Thanks for the feedback!
As I was writing this, I also noticed that there's quite a lot of boilerplate coming from component template. I was in the process of removing excess code from this template. I totally agree with your key points on clear problem and solution. I will address those points and make it more cleaner. Also, I am not familiar with writing documentation so I am sure that the wording in the documentation can be improved. I will try to improve docs as well. I will wait for @kdheepak's opinion before I make any big changes in the PR.

@kdheepak
Copy link
Contributor

kdheepak commented Jul 1, 2024

I agree with your comments. It should be a lot simpler to discuss just the aspect of starting an external process like vim.

One thing I wanted to note is that when I've attempted to do do this without the pattern used in the component template, it resulted in issues where ANSI RGB values would be printed into the TUI on returning back from vim.

See for example this commit from @orhun where he made a change to ensure it worked correctly: orhun/rattler-build@84ea16a

I first saw this issue in kdheepak/taskwarrior-tui#46
The reason this occurred is because when vim wants to find out the background color of the terminal, and the response to that request is written to stdin.

When this issue occurs, the response is written to stdin which is read by crossterm as if a user is typing it and that is sent to the keyevents and that ends up getting processed by the TUI.

I know that the combination of using select! + cancellation_token + tokio the way it is used in the component template does not cause this issue. But I haven't tested other ways to narrow down exactly what causes it and what doesn't cause it.

This issue is particularly annoying because it is not always reproducible. I never noticed it on iTerm until I decreased the tick time when using tokio. I noticed it happened more when I was using a background thread to send events to the main thread and was not able to solve it when using a AtomicBool as a Mutex lock to pause the background thread.

Currently, I don't know why the other methods didn't work, and I definitely didn't comprehensively test everything. I was changing multiple things at the same time when I was testing this in taskwarrior-tui and landed on a solution with tokio, select! and cancellation_tokens that worked.

I would like to ensure that this RGB issue doesn't occur with whatever recipe is posted on ratatui.rs because if it does we'll get a lot of questions about what is going on for users that copy paste the code.

@kdheepak
Copy link
Contributor

kdheepak commented Jul 1, 2024

Thanks for sharing a PR and describing your steps to solve this problem here and on discourse! Even just this information will be useful for those that try to do the same thing and come across this!

@deepanchal deepanchal force-pushed the feat/how-to-spawn-vim-example branch from 212c8ca to 883d87b Compare July 1, 2024 16:15
@deepanchal
Copy link
Author

@joshka @kdheepak
I have force pushed to this branch with a much simpler example using hello-world template and updated the docs accordingly. I just had a few questions

If any of you can review these new changes whenever you get a chance, that will be helpful! Thanks!!

Copy link
Member

@joshka joshka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal of the recipes section is less step by step tutorial and more an explanation of a snippet of code. What about dropping this down to just two code blocks, one showing the the main, handle_events and run_editor code in a single block, with the main and handle events methods collapsed, and when showing the full file, fully collapsed?, E.g. use the following and add a direct link to the code file in the repo.

```rust collapsed title="main.rs (click to expand)"

The main thing this article really needs to do is say something like (feel free to rephrase):

Before you run another app from your app, your app is in control of the input and output. Your app needs to doing that while the other app is running otherwise ...

It likely also needs to draw comparisons about synchronous, threaded, and async event handling.

Comment on lines 61 to 69
stdout().execute(LeaveAlternateScreen)?;
disable_raw_mode()?;
// Launch vim and wait for status
// You may change this to other editors like nvim, nano, etc.
Command::new("vim").arg("/tmp/a.txt").status()?;
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
// Clear the terminal and force a full redraw on the next draw call.
terminal.clear()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really the crux of the entire article, and it deserves it's own code block, everything else is boilerplate that could be in any app. I'd suggest pulling this out into a function and showing it with some narrative.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this part is important, but it is the obvious part imo, and pausing the key event handler before spawning vim and restarting the key event handler after resuming from vim exiting is imo the part that will trip most people.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In these examples we don't have a background key handler, so what I expect will happen is that someone will copy this code into their app and it won't work as expected.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for the delay in addressing this PR over the past two weeks. I agree with @kdheepak's concern about users with advanced setups experiencing issues when copying the snippet. Here are two possible solutions:

  1. Add a note to the documentation illustrating how to spawn an external process (e.g., Vim) using a component template. I have created a proof of concept here: feat: Add ExecuteCommand action in component template templates#62
  2. Enhance our snippet for spawning Vim by utilizing a similar but simplified version of the tui module component template.

src/content/docs/recipes/apps/index.md Outdated Show resolved Hide resolved
code/how-to-spawn-vim/src/main.rs Show resolved Hide resolved
@deepanchal deepanchal force-pushed the feat/how-to-spawn-vim-example branch from 5db9906 to 7be0016 Compare July 13, 2024 19:44
@deepanchal
Copy link
Author

I have updated the PR to focus more on the logic for spawning Vim. I have also updated the image of generated docs on PR description. Please let me know if this is acceptable :)
Thanks!

Copy link
Sponsor Member

@orhun orhun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall, but I feel like it is missing some parts.

Mainly, the edge case of ANSI code being printed should be mentioned somewhere. We can also give some example TUI apps which implements this.

Also, if the user only wants to launch vim to edit something, using e.g. edtui might also come in handy.

Lastly, clippy is complaining :)

events. The `handle_events` function listens for key events and returns an `Action` based on the key
pressed.

## Spawning vim
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
## Spawning vim
## Spawning Vim


## Spawning vim

Now, lets define the function `run_editor` function attached to `Action::EditFile` action.
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Now, lets define the function `run_editor` function attached to `Action::EditFile` action.
Now, let's define the function `run_editor` function attached to `Action::EditFile` action.

[full code](https://github.com/ratatui-org/ratatui-website/tree/main/code/how-to-spawn-vim/src/main.rs).
Next, we spawn a child process with `Command::new("vim").arg("/tmp/a.txt").status()` which launches
`vim` to edit the given file. At this point, we have given up control of our TUI app to vim. Our TUI
app will now wait for the exit status of the child process (i.e., Vim). Once the user exits Vim, our
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like Vim is mentioned too many times here :D

Suggested change
app will now wait for the exit status of the child process (i.e., Vim). Once the user exits Vim, our
app will now wait for the exit status of the child process. Once the user exits Vim, our

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants