[Rust] TUI: ratatui
ratatui๋ ํฐ๋ฏธ๋ UI ํ๋ ์์ํฌ๋ค.
GUI ์์ด ํฐ๋ฏธ๋ ํ๊ฒฝ์์ ์ด๋ฐ์ ๋ฐ ๋ณต์กํ ์ ์ด๊ธฐ๋ฅ์ ๋ค๋ฃจ๊ณ ์ถ์๋ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ค์น
์๋ ๋ํ๋์๋ฅผ 2๊ฐ ์ถ๊ฐํด์ค๋ค.
[dependencies]
crossterm = "0.27.0"
ratatui = "0.26.0"

Hello World ์์ฑํด๋ณด๊ธฐ
๊ธฐ๋ณธ ์ฝ๋ ์์ด ์กฐ๊ธ ๋๋ค. ๋ถ์์ ์์์ ๋ณต๋ถํ๊ณ ์คํ๋ถํฐ ํด๋ณด์.
use crossterm::{
event::{self, KeyCode, KeyEventKind},
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
ExecutableCommand,
};
use ratatui::{
prelude::{CrosstermBackend, Stylize, Terminal},
widgets::Paragraph,
};
use std::io::{stdout, Result};
fn main() -> Result<()> {
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?;
loop {
terminal.draw(|frame| {
let area = frame.size();
frame.render_widget(
Paragraph::new("Hello Ratatui! (press 'q' to quit)")
.white()
.on_blue(),
area,
);
})?;
if event::poll(std::time::Duration::from_millis(16))? {
if let event::Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
break;
}
}
}
}
stdout().execute(LeaveAlternateScreen)?;
disable_raw_mode()?;
Ok(())
}
๊ทธ๋ผ ๋น๋ ํ ์คํ์ด ๋ ๊ฒ์ด๊ณ , ์ ์ฉ ํ๋ฉด์ด ๋ฐ ๊ฒ์ด๋ค.

๊ทธ๋ฆฌ๊ณ q๋ฅผ ๋๋ฅด๋ฉด ์ข ๋ฃ๋๋ค.

์ฝ๋ ์ดํด๋ณด๊ธฐ
๋ญ๊ฐ ๋ณต์กํด๋ณด์ด๊ธด ํ๋๋ฐ, ํ๋์ฉ ๋ฏ์ด๋ณด๋ฉด ๊ทธ๋ ๊ฒ ์ด๋ ต์ง๋ ์๋ค.

-
๋จผ์ Alternate ์คํฌ๋ฆฐ ๋ชจ๋๋ก ์ง์ ํ๋ค. ์ด๋์ผ ์ ์ถ๋ ฅ์ ๋ฐฉํดํ์ง ์๊ณ ๊ทธ๋ํฝ์ค๋ฐ ๋ ๋๋ง์ ์ ํ ์ ์๋ค.
-
raw mode๋ฅผ ์ผ์ ํฐ๋ฏธ๋์ ์ ์ถ๋ ฅ์ ์ ํํ๋ค. ๊ทธ๋์ผ ์ด ์ฑ์์๋ง ํฐ๋ฏธ๋์ ๋ง์๋๋ก ํต์ ํ ์ ์๋ค.
-
๊ทธ๋ฆฌ๊ณ ํฐ๋ฏธ๋ ๋ฐฑ์๋๋ฅผ ์์ฑํ๋ค. ์ด์ ๋ถํฐ ์ด๊ฑธ๋ก ํต์ ๋ฅผ ํ ์ ์๊ฒ ๋๋ค.
-
ํ์ฌ ํฐ๋ฏธ๋์ ์ฒญ์ํ๋ค.
๊ทธ๋ฌ๋ฉด ๊ทธ ๋ค์์๋ ๋ฃจํ์ ์ง์ ํด์ ๋ ๋๋ง ํ๋ก์ธ์ค๋ฅผ ์งํํ๊ฒ ๋๋ค.

-
๋งค ๋ ๋๋ง๋ง๋ค draw๋ก ๋ชจ์์ ๊ทธ๋ฆฐ๋ค. ์ฌ๊ธฐ์๋ ์์ธํ ๋ค๋ฃจ์ง ์์ง๋ง, ์ขํ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ธํ๊ฒ ์ ์ดํ ์๋ ์๋ค.
์ฐธ์กฐ https://ratatui.rs/concepts/layout/ -
๊ทธ๋ฆฌ๊ณ ํค ์ด๋ฒคํธ๊ฐ ์ค๋, ๊ทธ๊ฒ q์ด๋ฉด ๋ฃจํ๋ฅผ ์ข ๋ฃํด์ ํ๋ก๊ทธ๋จ์ ๋๊ฐ๋๋ก ํด๋๋ค.
์ฐธ์กฐ https://ratatui.rs/concepts/event-handling/
๋ ์์ธํ ๊ฒ์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ๋ค.
https://ratatui.rs/introduction/