| |
- 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.
|