From 404e813cf7169bfa733ff723cae2dae06a2576be Mon Sep 17 00:00:00 2001 From: Elliot Date: Fri, 10 Dec 2021 11:51:05 +0800 Subject: [PATCH 1/3] feat(tui): add app state --- quake_tui/src/app.rs | 20 ++++++++++++++++++++ quake_tui/src/lib.rs | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/quake_tui/src/app.rs b/quake_tui/src/app.rs index f49dfbd0..bbf13b44 100644 --- a/quake_tui/src/app.rs +++ b/quake_tui/src/app.rs @@ -2,12 +2,21 @@ pub struct App { pub mode: Mode, pub command: String, pub main_widget: MainWidget, + pub state: AppState, } impl App { pub fn new() -> App { App::default() } + + pub fn running(&self) -> bool { + self.state.running + } + + pub fn shutdown(&mut self) { + self.state.running = false; + } } impl Default for App { @@ -16,6 +25,7 @@ impl Default for App { mode: Mode::Normal, command: "".to_string(), main_widget: MainWidget::Home, + state: AppState::default(), } } } @@ -29,3 +39,13 @@ pub enum MainWidget { Home, Dirs, } + +pub struct AppState { + running: bool, +} + +impl Default for AppState { + fn default() -> AppState { + AppState { running: true } + } +} diff --git a/quake_tui/src/lib.rs b/quake_tui/src/lib.rs index e10167dd..cb5c8b6c 100644 --- a/quake_tui/src/lib.rs +++ b/quake_tui/src/lib.rs @@ -40,7 +40,7 @@ pub fn tui_main_loop() -> Result<(), Box> { fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<()> { // TODO: refactor - loop { + while app.running() { terminal.draw(|f| { draw(f, &mut app); })?; @@ -56,7 +56,7 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( KeyCode::Enter => { let command: String = app.command.drain(..).collect(); match command.as_str() { - "quit" => return Ok(()), + "quit" => app.shutdown(), "listAll" => app.main_widget = MainWidget::Dirs, _ => {} } @@ -75,4 +75,6 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( } } } + + Ok(()) } From a4753a8e37c6066d35238c686d43f1586f6b42ad Mon Sep 17 00:00:00 2001 From: Elliot Date: Fri, 10 Dec 2021 11:59:07 +0800 Subject: [PATCH 2/3] refactor(tui): rename main widget virant --- quake_tui/src/app.rs | 2 +- quake_tui/src/lib.rs | 2 +- quake_tui/src/ui.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/quake_tui/src/app.rs b/quake_tui/src/app.rs index bbf13b44..14726195 100644 --- a/quake_tui/src/app.rs +++ b/quake_tui/src/app.rs @@ -37,7 +37,7 @@ pub enum Mode { pub enum MainWidget { Home, - Dirs, + EntryTypes, } pub struct AppState { diff --git a/quake_tui/src/lib.rs b/quake_tui/src/lib.rs index cb5c8b6c..ca5d0f65 100644 --- a/quake_tui/src/lib.rs +++ b/quake_tui/src/lib.rs @@ -57,7 +57,7 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( let command: String = app.command.drain(..).collect(); match command.as_str() { "quit" => app.shutdown(), - "listAll" => app.main_widget = MainWidget::Dirs, + "listAll" => app.main_widget = MainWidget::EntryTypes, _ => {} } } diff --git a/quake_tui/src/ui.rs b/quake_tui/src/ui.rs index fe8ca0dc..08ecceb5 100644 --- a/quake_tui/src/ui.rs +++ b/quake_tui/src/ui.rs @@ -69,7 +69,7 @@ where area, ) } - MainWidget::Dirs => { + MainWidget::EntryTypes => { let entry_types: Vec = list_entry_types().unwrap_or_default(); let entry_types_list = List::new(entry_types) .block(Block::default().borders(Borders::ALL).title("List")) From 907152b7fba69b82e9e4d55f8134ff4bbb95461e Mon Sep 17 00:00:00 2001 From: Elliot Date: Fri, 10 Dec 2021 14:13:55 +0800 Subject: [PATCH 3/3] refactor(tui): extract main render logic to `MainWidget` --- quake_tui/src/app.rs | 73 ++++++++++++++++++++++++++++++++++++++++ quake_tui/src/ui.rs | 79 +++----------------------------------------- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/quake_tui/src/app.rs b/quake_tui/src/app.rs index 14726195..b8971aa2 100644 --- a/quake_tui/src/app.rs +++ b/quake_tui/src/app.rs @@ -1,3 +1,15 @@ +use quake_core::entry::EntryDefines; +use quake_core::QuakeConfig; +use serde_yaml; +use std::error::Error; +use std::fs; +use std::path::Path; +use tui::buffer::Buffer; +use tui::layout::{Alignment, Corner, Rect}; +use tui::style::{Color, Modifier, Style}; +use tui::text::{Span, Spans}; +use tui::widgets::{Block, Borders, List, ListItem, Paragraph, Widget}; + pub struct App { pub mode: Mode, pub command: String, @@ -35,11 +47,72 @@ pub enum Mode { Normal, } +#[derive(Clone, Debug)] pub enum MainWidget { Home, EntryTypes, } +impl Widget for MainWidget { + fn render(self, area: Rect, buf: &mut Buffer) { + match self { + MainWidget::Home => { + let help_messages = vec![ + Spans::from(vec![ + Span::raw("Press "), + Span::styled(":", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" into command mode, "), + Span::styled("Esc", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" back to normal mode."), + ]), + Spans::from(vec![ + Span::raw("Command "), + Span::styled("listAll", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" list all workspace."), + ]), + Spans::from(vec![ + Span::raw("Command "), + Span::styled("quit", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" quit quake app."), + ]), + ]; + let p = Paragraph::new(help_messages) + .block(Block::default().title("Main").borders(Borders::ALL)) + .alignment(Alignment::Center); + p.render(area, buf); + } + MainWidget::EntryTypes => { + let entry_types: Vec = list_entry_types().unwrap_or_default(); + let entry_types_list = List::new(entry_types) + .block(Block::default().borders(Borders::ALL).title("List")) + .start_corner(Corner::TopLeft); + + entry_types_list.render(area, buf); + } + } + } +} + +fn list_entry_types() -> Result>, Box> { + let config: QuakeConfig = serde_yaml::from_str(fs::read_to_string(".quake.yaml")?.as_str())?; + let entry_defines_path = Path::new(&config.workspace).join("entries-define.yaml"); + let entry_defines: EntryDefines = + serde_yaml::from_str(&fs::read_to_string(entry_defines_path)?)?; + + Ok(entry_defines + .entries + .iter() + .map(|define| { + let entry_type = Spans::from(vec![Span::styled( + define.entry_type.clone(), + Style::default().fg(Color::Yellow), + )]); + + ListItem::new(vec![entry_type]) + }) + .collect()) +} + pub struct AppState { running: bool, } diff --git a/quake_tui/src/ui.rs b/quake_tui/src/ui.rs index 08ecceb5..8ec940fd 100644 --- a/quake_tui/src/ui.rs +++ b/quake_tui/src/ui.rs @@ -1,15 +1,8 @@ -use crate::app::{App, MainWidget, Mode}; -use quake_core::entry::EntryDefines; -use quake_core::QuakeConfig; -use serde_yaml; -use std::error::Error; -use std::fs; -use std::path::Path; +use crate::app::{App, Mode}; use tui::backend::Backend; -use tui::layout::{Alignment, Constraint, Corner, Direction, Layout, Rect}; -use tui::style::{Color, Modifier, Style}; -use tui::text::{Span, Spans}; -use tui::widgets::{Block, Borders, List, ListItem, Paragraph}; +use tui::layout::{Constraint, Direction, Layout}; +use tui::style::{Color, Style}; +use tui::widgets::{Block, Borders, Paragraph}; use tui::Frame; use unicode_width::UnicodeWidthStr; @@ -34,67 +27,5 @@ pub fn draw(f: &mut Frame, app: &mut App) { ), } - draw_main(app, f, chunks[1]); -} - -fn draw_main(app: &App, frame: &mut Frame, area: Rect) -where - B: Backend, -{ - match app.main_widget { - MainWidget::Home => { - let help_messages = vec![ - Spans::from(vec![ - Span::raw("Press "), - Span::styled(":", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(" into command mode, "), - Span::styled("Esc", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(" back to normal mode."), - ]), - Spans::from(vec![ - Span::raw("Command "), - Span::styled("listAll", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(" list all workspace."), - ]), - Spans::from(vec![ - Span::raw("Command "), - Span::styled("quit", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(" quit quake app."), - ]), - ]; - frame.render_widget( - Paragraph::new(help_messages) - .block(Block::default().title("Main").borders(Borders::ALL)) - .alignment(Alignment::Center), - area, - ) - } - MainWidget::EntryTypes => { - let entry_types: Vec = list_entry_types().unwrap_or_default(); - let entry_types_list = List::new(entry_types) - .block(Block::default().borders(Borders::ALL).title("List")) - .start_corner(Corner::TopLeft); - frame.render_widget(entry_types_list, area); - } - } -} - -fn list_entry_types() -> Result>, Box> { - let config: QuakeConfig = serde_yaml::from_str(fs::read_to_string(".quake.yaml")?.as_str())?; - let entry_defines_path = Path::new(&config.workspace).join("entries-define.yaml"); - let entry_defines: EntryDefines = - serde_yaml::from_str(&fs::read_to_string(entry_defines_path)?)?; - - Ok(entry_defines - .entries - .iter() - .map(|define| { - let entry_type = Spans::from(vec![Span::styled( - define.entry_type.clone(), - Style::default().fg(Color::Yellow), - )]); - - ListItem::new(vec![entry_type]) - }) - .collect()) + f.render_widget(app.main_widget.clone(), chunks[1]); }