Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Improve README
Erik Kundt committed 1 year ago
commit 369616abd150e7d70017c93cbd7bc4110a8d1516
parent b0e32a7d4e8246900ff5c4c0f87554d1d4312568
3 files changed +94 -44
modified README.md
@@ -1,8 +1,16 @@
# radicle-tui

-
_Radicle terminal user interfaces_
+
![alt text](demo.gif "Demo")

-
## Installation
+
`radicle-tui` provides various terminal user interfaces for interacting with the [Radicle](https://radicle.xyz) code forge and exposes the application framework they were built with.
+

+
## Binaries
+

+
This crate provides a single binary called `rad-tui`, which contains all user interfaces. Specific interfaces can be run by the appropriate command, e.g. `rad-tui patch select` shows a patch selector.
+

+
The interfaces are designed to be modular and to integrate well with the existing Radicle CLI. Right now, they are meant to be called from other programs that will collect and process their output.
+

+
### Installation

**Requirements**

@@ -10,87 +18,128 @@ _Radicle terminal user interfaces_
- Git 2.34 or later
- OpenSSH 9.1 or later with `ssh-agent`

-
### 📦 From source
+
#### From source

> Requires the Rust toolchain.

You can install the binary from source, by running the following
commands from inside this repository:

-
    cargo install --path . --force --locked
+
```
+
cargo install --path . --force --locked
+
```

Or directly from our seed node:

-
    cargo install --force --locked --git https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git
+
```
+
cargo install --force --locked --git https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git
+
```

This will install `rad-tui`. You can execute it by running `rad-tui`. All available commands can be shown by running `rad-tui --help`.

-
## Interfaces
-

-
The Radicle terminal interfaces are designed to be modular and to integrate well with the existing Radicle CLI. Right now, they are meant to be called from other programs that will collect and process their output.
-

### Usage

-
#### Patches
-

-
Select a patch and an operation:
-

-
    $ rad-tui patch select
-
    { "operation": "show", "ids": ["546443226b300484a97a2b2d7c7000af6e8169ba"], args:[] }
-

+
Select a patch, an issue or a notification and an operation:

+
```
+
$ rad-tui <patch | issue | inbox> select
+
```
Same as above:

-
    $ rad-tui patch select --mode operation
-
    { "operation": "show", "ids": ["546443226b300484a97a2b2d7c7000af6e8169ba"], args:[] }
+
```
+
$ rad-tui <patch | issue | inbox> select --mode operation
+
```

-
Select a patch only and return its id:
+
Select a patch, an issue or a notification only and return its id:

-
    $ rad-tui patch select --mode id
-
    { "operation": "null", "ids": ["546443226b300484a97a2b2d7c7000af6e8169ba"], args:[] }
+
```
+
$ rad-tui <patch | issue | inbox> select --mode id
+
```

-
#### Issues
+
### Output

-
Select an issue and an operation:
+
All interfaces return a JSON object that reflects the choices made by the user, e.g.: 

-
    $ rad-tui issue select
-
    { "operation": "show", "ids": ["12f019e3f9f52d88b470a3d7fb922452ebaca39e"], args:[] }
+
```
+
{ "operation": "show", "ids": ["546443226b300484a97a2b2d7c7000af6e8169ba"], args:[] }
+
```

+
## Framework

-
Same as above:
-

-
    $ rad-tui issue select --mode operation
-
    { "operation": "show", "ids": ["12f019e3f9f52d88b470a3d7fb922452ebaca39e"], args:[] }
+
The library portion of this crate is a framework that is the foundation for the interfaces mentioned above. The framework is built on top of [ratatui](https://ratatui.rs) and was inspired by the Flux application pattern. It took some ideas from [cursive](https://github.com/gyscos/cursive) and [rust-chat-server](https://github.com/Yengas/rust-chat-server).

+
### Example

-
Select an issue only and return its id:
+
```rust
+
use anyhow::Result;
+
use termion::event::Key;

-
    $ rad-tui issue select --mode id
-
    { "operation": "null", "ids": ["12f019e3f9f52d88b470a3d7fb922452ebaca39e"], args:[] }
+
use radicle_tui as tui;

+
use tui::store;
+
use tui::ui::widget::text::{Paragraph, ParagraphProps};
+
use tui::ui::widget::{Properties, Widget};
+
use tui::{Channel, Exit};

-
#### Inbox
+
#[derive(Clone, Debug)]
+
struct State {
+
    welcome: String,
+
}

-
Select a notification and an operation:
+
enum Message {
+
    Quit,
+
    ReverseWelcome,
+
}

-
    $ rad-tui inbox select
-
    { "operation": "show", "ids": ["1"], args:[] }
+
impl store::State<()> for State {
+
    type Message = Message;

+
    fn update(&mut self, message: Self::Message) -> Option<tui::Exit<()>> {
+
        match message {
+
            Message::Quit => Some(Exit { value: None }),
+
            Message::ReverseWelcome => {
+
                self.welcome = self.welcome.chars().rev().collect::<String>();
+
                None
+
            }
+
        }
+
    }

-
Same as above:
+
    fn tick(&self) {}
+
}

-
    $ rad-tui inbox select --mode operation
-
    { "operation": "show", "ids": ["1"], args:[] }
+
#[tokio::main]
+
pub async fn main() -> Result<()> {
+
    let channel = Channel::default();
+
    let state = State {
+
        welcome: "Hello TUI".to_string(),
+
    };

+
    let welcome = Paragraph::new(&state, channel.tx.clone())
+
        .on_update(|state| {
+
            ParagraphProps::default()
+
                .text(&state.welcome.clone().into())
+
                .to_boxed()
+
        })
+
        .on_event(|paragraph, key| {
+
            paragraph
+
                .downcast_mut::<Paragraph<'_, State, Message>>()
+
                .and_then(|paragraph| match key {
+
                    Key::Char('r') => paragraph.send(Message::ReverseWelcome).ok(),
+
                    Key::Char('q') => paragraph.send(Message::Quit).ok(),
+
                    _ => None,
+
                });
+
        })
+
        .to_boxed();

-
Select a notification only and return its id:
+
    tui::run(channel, state, welcome).await?;

-
    $ rad-tui inbox select --mode id
-
    { "operation": "null", "ids": ["1"], args:[] }
+
    Ok(())
+
}
+
```


## License

-
Radicle is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
+
`radicle-tui` is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.
added demo.gif
modified src/terminal.rs
@@ -95,7 +95,8 @@ impl<W: Write> ratatui::backend::Backend for TermionBackendExt<W> {
pub fn setup(height: usize) -> anyhow::Result<Terminal<Backend>> {
    let stdout = io::stdout().into_raw_mode()?;
    let options = TerminalOptions {
-
        viewport: Viewport::Inline(height as u16),
+
        // viewport: Viewport::Inline(height as u16),
+
        viewport: Viewport::Fullscreen,
    };

    Ok(Terminal::with_options(