mirror of
https://github.com/orhun/systeroid
synced 2024-10-02 21:53:31 +00:00
feat(tui): make input prompt functional
This commit is contained in:
parent
cb9d072a3e
commit
4df05f94fe
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -527,6 +527,7 @@ dependencies = [
|
|||
"termion",
|
||||
"thiserror",
|
||||
"tui",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
termion = "1.5.6"
|
||||
unicode-width = "0.1.9"
|
||||
thiserror = "1.0.30"
|
||||
|
||||
[dependencies.systeroid-core]
|
||||
|
|
|
@ -5,11 +5,16 @@ use crate::command::Command;
|
|||
pub struct App {
|
||||
/// Whether if the application is running.
|
||||
pub running: bool,
|
||||
/// Input buffer.
|
||||
pub input: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
Self { running: true }
|
||||
Self {
|
||||
running: true,
|
||||
input: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +22,23 @@ impl App {
|
|||
/// Runs the given command and updates the application.
|
||||
pub fn run_command(&mut self, command: Command) {
|
||||
match command {
|
||||
Command::UpdateInput(v) => match self.input.as_mut() {
|
||||
Some(input) => {
|
||||
input.push(v);
|
||||
}
|
||||
None => {
|
||||
self.input = Some(String::new());
|
||||
}
|
||||
},
|
||||
Command::ClearInput(cancel) => {
|
||||
if cancel {
|
||||
self.input = None
|
||||
} else if let Some(input) = self.input.as_mut() {
|
||||
if input.pop().is_none() {
|
||||
self.input = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::Exit => {
|
||||
self.running = false;
|
||||
}
|
||||
|
|
|
@ -3,17 +3,32 @@ use termion::event::Key;
|
|||
/// Possible application commands.
|
||||
#[derive(Debug)]
|
||||
pub enum Command {
|
||||
/// Update the input buffer.
|
||||
UpdateInput(char),
|
||||
/// Clear the input buffer.
|
||||
ClearInput(bool),
|
||||
/// Exit the application.
|
||||
Exit,
|
||||
/// Do nothing.
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<Key> for Command {
|
||||
fn from(key: Key) -> Self {
|
||||
match key {
|
||||
Key::Esc => Command::Exit,
|
||||
_ => Command::None,
|
||||
impl Command {
|
||||
/// Parses a command from the given key.
|
||||
pub fn parse(key: Key, input_mode: bool) -> Self {
|
||||
if input_mode {
|
||||
match key {
|
||||
Key::Char(c) => Command::UpdateInput(c),
|
||||
Key::Backspace => Command::ClearInput(false),
|
||||
Key::Esc => Command::ClearInput(true),
|
||||
_ => Command::None,
|
||||
}
|
||||
} else {
|
||||
match key {
|
||||
Key::Char(':') => Command::UpdateInput(' '),
|
||||
Key::Esc => Command::Exit,
|
||||
_ => Command::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ pub fn run<Output: Write>(output: Output) -> Result<()> {
|
|||
let event_handler = EventHandler::new(250);
|
||||
let mut app = App::default();
|
||||
while app.running {
|
||||
terminal.draw(|frame| ui::render(frame))?;
|
||||
terminal.draw(|frame| ui::render(frame, &mut app))?;
|
||||
match event_handler.next()? {
|
||||
Event::KeyPress(key) => {
|
||||
let command = Command::from(key);
|
||||
let command = Command::parse(key, app.input.is_some());
|
||||
app.run_command(command);
|
||||
}
|
||||
Event::Tick => {}
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
use crate::app::App;
|
||||
use tui::backend::Backend;
|
||||
use tui::layout::{Constraint, Direction, Layout};
|
||||
use tui::style::{Color, Style};
|
||||
use tui::widgets::{Block, BorderType, Borders, Paragraph};
|
||||
use tui::Frame;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Renders the user interface.
|
||||
pub fn render<B: Backend>(frame: &mut Frame<'_, B>) {
|
||||
pub fn render<B: Backend>(frame: &mut Frame<'_, B>, app: &mut App) {
|
||||
let rect = frame.size();
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Min(rect.height - 3), Constraint::Min(3)].as_ref())
|
||||
.split(rect);
|
||||
|
||||
if let Some(input) = &app.input {
|
||||
frame.set_cursor(input.width() as u16 + 2, rect.height - 2);
|
||||
}
|
||||
frame.render_widget(
|
||||
Paragraph::new(env!("CARGO_PKG_NAME")).block(
|
||||
Paragraph::new(match &app.input {
|
||||
Some(input) => format!(":{}", input),
|
||||
None => String::new(),
|
||||
})
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::all())
|
||||
.border_style(Style::default().fg(Color::White))
|
||||
|
|
Loading…
Reference in a new issue