ratatui / ratatui-website

Ratatui Documentation
http://ratatui.rs/
MIT License
96 stars 64 forks source link

Add section on how to spawn vim from a ratatui application #406

Open kdheepak opened 7 months ago

kdheepak commented 7 months ago

Example of how to do this with an async event loop:

https://github.com/ratatui-org/templates/blob/b75771463c00088b75e90986979c60720d024bbf/component/template/src/tui.rs#L171-L198

Valentin271 commented 7 months ago

I believe this should be about the same for any other TUI: lazygit, yazi, even bash.

Also one important thing to note, this is about spawning a program and gaining back control. Which is different (and somewhat harder) than spawning a program on end.

Otherwise +1 for this.

kdheepak commented 6 months ago

Related: https://github.com/kdheepak/taskwarrior-tui/issues/46

deepanchal commented 2 months ago

I got it to launch vim on newly generated test app (cargo generate ratatui-org/templates) with component template with the following changes

diff --git a/src/action.rs b/src/action.rs
index f422a62..ee157c2 100644
--- a/src/action.rs
+++ b/src/action.rs
@@ -17,4 +17,5 @@ pub enum Action {
   Refresh,
   Error(String),
   Help,
+  EditFile,
 }
diff --git a/src/app.rs b/src/app.rs
index e528d05..c378c00 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -126,6 +126,17 @@ impl App {
               }
             })?;
           },
+          Action::EditFile => {
+            tui.exit()?;
+            let status = std::process::Command::new("vim").arg("/tmp/a.txt").status()?;
+            if status.success() {
+              log::info!("Successfully launched vim");
+            } else {
+              log::error!("Failed to launch vim");
+            }
+            tui = tui::Tui::new()?.tick_rate(self.tick_rate).frame_rate(self.frame_rate);
+            tui.enter()?;
+          },
           _ => {},
         }
         for component in self.components.iter_mut() {
diff --git a/src/components/home.rs b/src/components/home.rs
index a1e9cc6..f1fd170 100644
--- a/src/components/home.rs
+++ b/src/components/home.rs
@@ -35,6 +35,13 @@ impl Component for Home {
     Ok(())
   }

+  fn handle_key_events(&mut self, key: KeyEvent) -> Result<Option<Action>> {
+    match key.code {
+      KeyCode::Char('v') => Ok(Some(Action::EditFile)),
+      _ => Ok(None),
+    }
+  }
+
   fn update(&mut self, action: Action) -> Result<Option<Action>> {
     match action {
       Action::Tick => {
@@ -45,7 +52,7 @@ impl Component for Home {
   }

   fn draw(&mut self, f: &mut Frame<'_>, area: Rect) -> Result<()> {
-    f.render_widget(Paragraph::new("hello world"), area);
+    f.render_widget(Paragraph::new("Hello! Press 'v' to launch vim"), area);
     Ok(())
   }
 }
deepanchal commented 2 months ago

I would like to contribute by adding this example (how-to-spawn-vim) to the repo. I will open a PR soon

deepanchal commented 2 months ago

I have created a PR with basic example on how to spawn vim here https://github.com/ratatui-org/ratatui-website/pull/651

LucasPickering commented 1 week ago

I wrote a crate called editor-command that would be tangentially helpful here. It doesn't do anything related to opening vim specifically, but it makes it easier to let the user customize the editor they want to open via the common VISUAL and EDITOR env variables, as well as configurable other sources.

Not shooting for self-promotion here, I just thought this might be helpful for readers of this page if you want to include it :)

deepanchal commented 1 week ago

@LucasPickering Thanks for suggestion :) I am already mentioning a similar looking crate called edit in the tips section at the end of spawn vim docs in my PR. Could you please verify if both libraries are trying to achieve the same functionality? After briefly looking through both libraries code, I think that editor-command crate gives you a low level control by returning Command while edit crate provides a high level interface to open editor and get edited content back.

Here are the changes I was planning on adding to the PR

diff --git a/src/content/docs/recipes/apps/spawn-vim.md b/src/content/docs/recipes/apps/spawn-vim.md
index eb86861..e2c82aa 100644
--- a/src/content/docs/recipes/apps/spawn-vim.md
+++ b/src/content/docs/recipes/apps/spawn-vim.md
@@ -105,7 +105,9 @@ command in the `Action::EditFile` arm.

 If you prefer to launch the user-specified `$EDITOR` and retrieve the buffer (edited content) back
 into your application, you can use the [`edit`](https://crates.io/crates/edit) crate. This can be
-particularly useful if you need to capture the changes made by the user in the editor.
+particularly useful if you need to capture the changes made by the user in the editor. There's also
+[`editor-command`](https://docs.rs/editor-command/latest/editor_command) crate if you want more
+control over launching / overriding editors based on `VISUAL` or `EDITOR` environment variables.

 Alternatively, you may use the [`edtui`](https://github.com/preiter93/edtui) crate from ratatui's
 ecosystem, which provides text editor widget inspired by vim.

If these changes look good to you, I will add these changes to the PR :)

LucasPickering commented 1 week ago

@deepanchal Yes, it looks like both libraries hand the same end goal. I searched for a library like edit before creating editor-command but didn't find it. Some key differences I noticed between the two:

In general I think it's fair to say editor-command gives lower level control at the cost of some convenience. You change looks good to me!

deepanchal commented 1 week ago

Changes are live :tada: https://ratatui.rs/recipes/apps/spawn-vim