Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tui refactor #16

Merged
merged 3 commits into from
Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 94 additions & 1 deletion quake_tui/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
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,
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 {
Expand All @@ -16,6 +37,7 @@ impl Default for App {
mode: Mode::Normal,
command: "".to_string(),
main_widget: MainWidget::Home,
state: AppState::default(),
}
}
}
Expand All @@ -25,7 +47,78 @@ pub enum Mode {
Normal,
}

#[derive(Clone, Debug)]
pub enum MainWidget {
Home,
Dirs,
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<ListItem> = 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<Vec<ListItem<'static>>, Box<dyn Error>> {
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,
}

impl Default for AppState {
fn default() -> AppState {
AppState { running: true }
}
}
8 changes: 5 additions & 3 deletions quake_tui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn tui_main_loop() -> Result<(), Box<dyn Error>> {

fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
// TODO: refactor
loop {
while app.running() {
terminal.draw(|f| {
draw(f, &mut app);
})?;
Expand All @@ -56,8 +56,8 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<(
KeyCode::Enter => {
let command: String = app.command.drain(..).collect();
match command.as_str() {
"quit" => return Ok(()),
"listAll" => app.main_widget = MainWidget::Dirs,
"quit" => app.shutdown(),
"listAll" => app.main_widget = MainWidget::EntryTypes,
_ => {}
}
}
Expand All @@ -75,4 +75,6 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<(
}
}
}

Ok(())
}
79 changes: 5 additions & 74 deletions quake_tui/src/ui.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -34,67 +27,5 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, app: &mut App) {
),
}

draw_main(app, f, chunks[1]);
}

fn draw_main<B>(app: &App, frame: &mut Frame<B>, 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::Dirs => {
let entry_types: Vec<ListItem> = 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<Vec<ListItem<'static>>, Box<dyn Error>> {
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]);
}