Skip to content

Commit

Permalink
Add async template (ratatui-org#23)
Browse files Browse the repository at this point in the history
* new: Initial commit 🎉

* Update README.md

* feat: tokio sleep ✨

* feat: remove async for increment and decrement ✨

* feat: decrease complexity of app struct ✨

* feat: remove ActionHandler ✨

* docs: Update README.md 📚

* feat: More simplifications ✨

* feat: Add Error event ✨

* feat: Add trace_dbg macro ✨

* Create Makefile.toml

* Create rustfmt.toml

* Create cd.yml

* Create .gitkeep

* Update README.md

* feat: keypress should not delay tick ✨

* feat: Remove async trait ✨

* docs: Update README.md 📚

* feat: More simplifications ✨

* feat: Add time delay ✨

* feat: Tick after every increment or decrement ✨

* feat: Use ActionHandler ✨

* feat: Change time sleep to 5 seconds ✨

* feat: Change tick rate to 50 ✨

* feat: Separate render loop ✨

* feat: Decrease logging of Tick ✨

* feat: Replace RwLock with action channel implementation ✨

* chore: reformat ♻️

* feat: Add ExitProcessing ✨

* feat: Add event handler tokio task ✨

* feat: Remove action handler and make more tokio tasks ✨

* feat: Cleaner exit ✨

* feat: Better variable names ✨

* feat: Refactor tx and rx for Action ✨

* feat: Add build.rs with shadow ✨

* feat: Update version string ✨

* feat: Reorganize utils ✨

* feat: Use libc exit codes ✨

* feat: Use precommit config ✨

* style: Make clippy happy 💎

* refactor: move version to main.rs 📦

* feat: Drop shadow ✨

* feat: Update build.rs ✨

* feat: Update main.rs ✨

* feat: Add cliff.toml ✨

* feat: Simplify ✨

* feat: Remove current_exe_path ✨

* feat: Rename tui.rs to terminal.rs ✨

* feat: Rename TuiHandler to TerminalHandler ✨

* feat: Rename task to handle ✨

* feat: Reorder import ✨

* docs: Update README.md 📚

* feat: Add signal handler to suspend and resume ✨

* feat: Reduce CPU utilization to 5% ✨

* feat: Rename TuiMsg to Message ✨

* chore: rename variables ♻️

* feat: Separate app tick rate and render tick rate ✨

* chore: rename variables ♻️

* docs: Update README.md 📚

* chore: Rename variables ♻️

* fix: bug in tick rate interval in event 🐛

* feat: Add docs ✨

* docs: Update index.qmd 📚

* docs: Update part1.qmd 📚

* docs: Update tutorial 📚

* docs: Update part2.qmd 📚

* docs: Update part3.qmd 📚

* docs: Update parts 📚

* docs: Update tutorial 📚

* feat: Use terminal.rs and event.rs ✨

* docs: Update tutorial 📚

* feat: Use tokio::sync::Notify instead of oneshot::Sender<()> ✨

* feat: Fix cargo clippy ✨

* feat: Use tokio_util::sync::CancellationToken instead of tokio::sync::Notify ✨

* feat: Use Message::Suspend ✨

* feat: Use action::Action ✨

* feat: Move should_quit and should_suspend to root app ✨

* feat: Use TuiTask and EventTask ✨

* feat: Make methods on app private ✨

* feat: Add TuiTask methods ✨

* feat: Refactor TerminalHandlerTask and EventHandlerTask to separate files ✨

* feat: Use tx.clone().unwrap() in home ✨

* docs: Update tutorial 📚

* feat: Simplify app.run ✨

* feat: Simplify event and terminal ✨

* docs: Update tutorial 📚

* feat: Make get_data_dir and get_config_dir return Result<PathBuf> instead ✨

* feat: Fix naming ✨

* feat: Implement Deref for Tui ✨

* docs: Update tutorial 📚

* docs: Add faq 📚

* docs: Update faq 📚

* chore: Update files ♻️

* fix: event documentation 🐛

* feat: Remove on_*_event functions ✨

* feat: Add serde ✨

* chore: Update files ♻️

* feat: Rename from ratatui-template to ratatui-async-template ✨

* fix: link 🐛

* docs: Update documentation 📚

* docs: Update documentation 📚

* docs: Update documentation 📚

* docs: Update documentation 📚

* docs: Use mdbook instead 📚

* docs: Add catppuccin 📚

* docs: Add linkcheck 📚

* docs: Fix CI 📚

* docs: Disable playground 📚

* docs: Update github workflow 📚

* docs: Update documentation 📚

* docs: Update documentation 📚

* docs: Make CI mdbook plugins install faster 📚

* docs: Use cache 📚

* docs: Better permissions on github 📚

* chore: Add workflow dispatch ♻️

* chore: Remove catppuccin mdbook plugin install from ci ♻️

* chore: Add bin to cargo cache ♻️

* Update docs.yml

* chore: Update cache ♻️

* chore: Update docs.yml ♻️

* chore: Update docs.yml ♻️

* chore: Update docs.yml ♻️

* chore: Update docs.yml ♻️

* docs: add site-url for mdbook 📚

* docs: fix content on ci 📚

* docs: Fix sentence 📚

* docs: fix 01-structure 📚

* docs: Fix 01-structure 📚

* docs: Add KeyEventPress example 📚

* chore: Cache binaries for mdbook on CI ♻️

* Update 01-structure.md

* docs: update structure

* docs: Update main.rs book section

* docs: Update action.rs

* docs: Update index.qmd

* docs: Rename files

* feat: Remove copy trait ✨

* feat: Add rust toolchain ✨

* feat: Use if let ✨

* Update 04-structure.md

* feat: Use color eyre ✨

* fix: Remove is_markdown_file function 🐛

* docs: Update about string 📚

* feat: Use a simpler structure

* chore: Remove cliff.toml ♻️

* feat: Don't use RUST_LOG environment variable ✨

* feat: better error handling ✨

* docs: Update screenshot in README.md

* docs: Update README text 📚

* docs: Remove tui-logger 📚

* feat: Add default keymap ✨

* chore: Change components/mod.rs to components.rs ♻️

* feat: Add FpsCounter component ✨

* feat: Better logging ✨

* feat: better error reporting ✨

* feat: Use tick rate and frame rate ✨

* feat: Add register action handler ✨

* fix: Change F1 to f1 to key event to string 🐛

* feat: Add test for key event to string ✨

* docs: Fix include 📚

* feat: Add cargo generate template ✨

* docs: Update README.md 📚

* docs: Update README.md and index.md 📚

* chore: Update ci.yml ♻️

* feat: Update template for ratatui-counter ✨

* docs: Update documentation 📚

* feat: Remove Cargo files from root ✨

* docs: Better documentation for configuration 📚

* feat: Add .envrc ✨

* feat: Add .envrc ✨

* docs: Update instructions for running demo 📚

* feat: Better configuration handling ✨

* feat: Better configuration handling in counter ✨

* docs: Update README.md 📚

* Update README.md

* feat: Update styling ✨

* feat: Show current key presses ✨

* feat: Make cli.rs use short and long args ✨

* docs: Update README.md

* docs: Update README.md 📚

* feat: Update version string ✨

* feat: Add authors to the template ✨

* feat: Add ci and cd to template ✨

* feat: Better authors and package name ✨

* feat: Ignore log files ✨

* feat: Add more crossterm feature support ✨

* feat: Make tui build constructors ✨

* feat: Move mode to separate file ✨

* docs: Update README.md

* docs: Update README.md 📚

* docs: Update README.md 📚

* docs: Update README.md 📚

* docs: Update documentation 📚

* feat: Change default render rate to 4fps ✨

* docs: Update README.md

* feat: Use rhai script for cargo generate ✨

* feat: Add source for rhai script ✨

* feat: Change spelling ✨

* feat: Better prompt message ✨

* docs: Update README.md 📚

* docs: Add docstring in template 📚

* feat: Add Fps component to template ✨

* feat: Add optional rustfmt.toml ✨

* docs: Update README.md 📚

* docs: Update README.md 📚

* docs: Update README.md with better headings 📚

* docs: Update README.md for more clarity 📚

* docs: Update README.md by moving gifs around 📚

* docs: Update README.md intro gif 📚

* docs: Update README.md

* docs: Update README.md

* fix: Persist git info 🐛

* feat: Use strum ✨ (ratatui-org#20)

* chore: Rename to async template ♻️ (ratatui-org#21)

* Update docs to make it relevant to both templates

---------

Co-authored-by: Dheepak Krishnamurthy <me@kdheepak.com>
  • Loading branch information
2 people authored and orhun committed Dec 15, 2023
1 parent b51eab3 commit ebdb96f
Show file tree
Hide file tree
Showing 70 changed files with 7,076 additions and 15 deletions.
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,6 @@ This repository contains templates for bootstrapping a Rust
[`Ratatui`](https://github.com/ratatui-org/ratatui) &
[`crossterm`](https://github.com/crossterm-rs/crossterm).

## Project structure

```text
src/
├── app.rs -> holds the state and application logic
├── event.rs -> handles the terminal events (key press, mouse click, resize, etc.)
├── handler.rs -> handles the key press events and updates the application
├── lib.rs -> module definitions
├── main.rs -> entry-point
├── tui.rs -> initializes/exits the terminal interface
└── ui.rs -> renders the widgets / UI
```

## Creating a project

1. Install [`cargo-generate`](https://github.com/cargo-generate/cargo-generate#installation)
Expand All @@ -29,9 +16,26 @@ src/
2. Create a new app based on this repository:

```shell
cargo generate ratatui-org/ratatui-template simple
cargo generate ratatui-org/ratatui-template
```

3. Choose either the [Simple](#simple-template) or [Async](./async/README.md) template.

## Simple template

The simple template will create the following project structure:

```text
src/
├── app.rs -> holds the state and application logic
├── event.rs -> handles the terminal events (key press, mouse click, resize, etc.)
├── handler.rs -> handles the key press events and updates the application
├── lib.rs -> module definitions
├── main.rs -> entry-point
├── tui.rs -> initializes/exits the terminal interface
└── ui.rs -> renders the widgets / UI
```

## See also

- [Rust Munich Meetup #8 - Designing TUI Applications in Rust](https://www.youtube.com/watch?v=ogdJnOLo238)
Expand Down
31 changes: 31 additions & 0 deletions async/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Build Template
on:
push:
branches:
- main
pull_request:

jobs:
build:
runs-on: ubuntu-latest
env:
PROJECT_NAME: ratatui-github-example
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run cargo generate
uses: cargo-generate/cargo-generate-action@v0.18.3
with:
name: ${{ env.PROJECT_NAME }}
subfolder: template
template_values_file: .github/workflows/template.toml
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cargo check
# we need to move the generated project to a temp folder, away from the template project
# otherwise `cargo` runs would fail
# see https://github.com/rust-lang/cargo/issues/9922
run: |
mv $PROJECT_NAME ${{ runner.temp }}/
cd ${{ runner.temp }}/$PROJECT_NAME
cargo check --tests
50 changes: 50 additions & 0 deletions async/.github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: docs

on:
push:
branches:
- main
pull_request:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v2

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: "latest"

- uses: baptiste0928/cargo-install@v2
with:
crate: mdbook-admonish
version: "1.9.0"

- uses: baptiste0928/cargo-install@v2
with:
crate: mdbook-svgbob2
version: "0.3.0"

- uses: baptiste0928/cargo-install@v2
with:
crate: mdbook-linkcheck
version: "0.7.7"

- name: Build with mdbook
run: mdbook build book

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book/html
force_orphan: true
7 changes: 7 additions & 0 deletions async/.github/workflows/template.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[values]
gh-username = "kdheepak"
project-description = "Example of ratatui template"
msrv = "stable"
use_gitserver = false
crossterm_io = "stderr"
use_rustfmt = false
18 changes: 18 additions & 0 deletions async/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust

### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/
/target
.data

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# End of https://www.toptal.com/developers/gitignore/api/rust
44 changes: 44 additions & 0 deletions async/.justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
default:
@just --list

fmt:
cargo fmt
prettier --write .
just --fmt --unstable

update:
cargo upgrade --incompatible
cargo update

check:
pre-commit run --all-files
cargo check
cargo clippy

build:
cargo build --all-targets

test:
cargo test run --workspace --all-targets

changelog:
git cliff -o CHANGELOG.md
prettier --write CHANGELOG.md

binary-name := "ratatui-hello-world"

generate-hello-world:
cargo generate --path . --name {{binary-name}} -d project-description="Hello World project using ratatui-template" -d gh-username=kdheepak -d msrv="stable"

generate:
@just clean
@just generate-hello-world

clean:
rm -rf {{binary-name}}

generate-and-run:
@just generate
cd {{binary-name}} && cargo run
@just clean

32 changes: 32 additions & 0 deletions async/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
default_stages: [commit]
default_install_hook_types: [pre-commit, commit-msg]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- id: check-vcs-permalinks
- id: check-xml
- id: check-yaml
- id: destroyed-symlinks
- id: detect-private-key
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: pretty-format-json
- id: trailing-whitespace
- repo: https://github.com/rhysd/actionlint
rev: v1.6.24
hooks:
- id: actionlint

ci:
autofix_prs: false
autoupdate_commit_msg: "chore: pre-commit autoupdate"
skip: [actionlint]
19 changes: 19 additions & 0 deletions async/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2023 Dheepak Krishnamurthy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
131 changes: 131 additions & 0 deletions async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# async-template

![async template demo](https://user-images.githubusercontent.com/1813121/277114001-0d25a09c-f24e-4ffc-8763-cd258828cec0.gif)

## Usage

You can start by using `cargo-generate`:

```shell
cargo install cargo-generate
cargo generate ratatui-org/templates async --name ratatui-hello-world
cd ratatui-hello-world
```

## Features

- Uses [tokio](https://tokio.rs/) for async events
- Start and stop key events to shell out to another TUI like vim
- Supports suspend signal hooks
- Logs using [tracing](https://github.com/tokio-rs/tracing)
- [better-panic](https://github.com/mitsuhiko/better-panic)
- [color-eyre](https://github.com/eyre/color-eyre)
- [human-panic](https://github.com/rust-cli/human-panic)
- Clap for command line argument parsing
- `Component` trait with
[`Home`](https://github.com/ratatui-org/async-template/blob/main/template/src/components/home.rs)
and
[`Fps`](https://github.com/ratatui-org/async-template/blob/main/template/src/components/fps.rs)
components as examples

## Advanced Usage

You can also use a
[`template.toml`](https://github.com/ratatui-org/async-template/blob/main/.github/workflows/template.toml)
file to skip the prompts:

```bash
$ cargo generate --git https://github.com/ratatui-org/async-template --template-values-file .github/workflows/template.toml --name ratatui-hello-world
# OR generate from local clone
$ cargo generate --path . --template-values-file .github/workflows/template.toml --name ratatui-hello-world
```

## Running your App

```bash
cargo run # Press `q` to exit
```

## Show help

```bash
$ cargo run -- --help
Hello World project using ratatui-template

Usage: ratatui-hello-world [OPTIONS]

Options:
-t, --tick-rate <FLOAT> Tick rate, i.e. number of ticks per second [default: 1]
-f, --frame-rate <FLOAT> Frame rate, i.e. number of frames per second [default: 60]
-h, --help Print help
-V, --version Print version
```

## Show `version`

Without direnv variables:

```bash
$ cargo run -- --version
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target/debug/ratatui-hello-world --version`
ratatui-hello-world v0.1.0-47-eb0a31a

Authors: Dheepak Krishnamurthy

Config directory: /Users/kd/Library/Application Support/com.kdheepak.ratatui-hello-world
Data directory: /Users/kd/Library/Application Support/com.kdheepak.ratatui-hello-world
```

With direnv variables:

```bash
$ direnv allow
direnv: loading ~/gitrepos/async-template/ratatui-hello-world/.envrc
direnv: export +RATATUI_HELLO_WORLD_CONFIG +RATATUI_HELLO_WORLD_DATA +RATATUI_HELLO_WORLD_LOG_LEVEL

$ # OR

$ export RATATUI_HELLO_WORLD_CONFIG=`pwd`/.config
$ export RATATUI_HELLO_WORLD_DATA=`pwd`/.data
$ export RATATUI_HELLO_WORLD_LOG_LEVEL=debug

$ cargo run -- --version
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
Running `target/debug/ratatui-hello-world --version`
ratatui-hello-world v0.1.0-47-eb0a31a

Authors: Dheepak Krishnamurthy

Config directory: /Users/kd/gitrepos/async-template/ratatui-hello-world/.config
Data directory: /Users/kd/gitrepos/async-template/ratatui-hello-world/.data
```

## Documentation

Read documentation on design decisions in the template here:
<https://ratatui-org.github.io/async-template/>

## Counter + Text Input Demo

This repo contains a `ratatui-counter` folder that is a working demo as an example. If you wish to
run a demo without using `cargo generate`, you can run the counter + text input demo by following
the instructions below:

```bash
git clone https://github.com/ratatui-org/async-template
cd async-template
cd ratatui-counter # counter + text input demo

export RATATUI_COUNTER_CONFIG=`pwd`/.config
export RATATUI_COUNTER_DATA=`pwd`/.data
export RATATUI_COUNTER_LOG_LEVEL=debug
# OR
direnv allow

cargo run
```

You should see a demo like this:

![counter demo](https://github.com/ratatui-org/async-template/assets/1813121/057a0fe9-9f6d-4f8c-963c-ca2725721bdd)
1 change: 1 addition & 0 deletions async/book/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
Loading

0 comments on commit ebdb96f

Please sign in to comment.