Skip to content

Commit

Permalink
add first ratatui frame with dummy prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
soywod committed Sep 17, 2024
1 parent eb6e974 commit f3d035c
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 2 deletions.
111 changes: 111 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ once_cell = "1.16"
petgraph = "0.6"
pimalaya-tui = { version = "=0.1.0", default-features = false, features = ["email", "path", "cli", "config", "tracing"] }
process-lib = { version = "=0.4.2", features = ["derive"] }
ratatui = "=0.28.1"
secret-lib = { version = "=0.4.6", default-features = false, features = ["command", "derive"], optional = true }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
117 changes: 115 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,116 @@
fn main() {
println!("Hello, world!");
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event, KeyCode, KeyModifiers},
layout::{Constraint, Layout, Position},
style::Stylize,
text::Text,
DefaultTerminal, Frame,
};

fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let app_result = App::new().run(terminal);
ratatui::restore();
app_result
}

struct App {
input: String,
character_index: usize,
}

impl App {
const fn new() -> Self {
Self {
input: String::new(),
character_index: 0,
}
}

fn move_cursor_left(&mut self) {
let cursor_moved_left = self.character_index.saturating_sub(1);
self.character_index = self.clamp_cursor(cursor_moved_left);
}

fn move_cursor_right(&mut self) {
let cursor_moved_right = self.character_index.saturating_add(1);
self.character_index = self.clamp_cursor(cursor_moved_right);
}

fn enter_char(&mut self, new_char: char) {
let index = self.byte_index();
self.input.insert(index, new_char);
self.move_cursor_right();
}

fn byte_index(&self) -> usize {
self.input
.char_indices()
.map(|(i, _)| i)
.nth(self.character_index)
.unwrap_or(self.input.len())
}

fn delete_char(&mut self) {
let is_not_cursor_leftmost = self.character_index != 0;
if is_not_cursor_leftmost {
let current_index = self.character_index;
let from_left_to_current_index = current_index - 1;

let before_char_to_delete = self.input.chars().take(from_left_to_current_index);
let after_char_to_delete = self.input.chars().skip(current_index);
self.input = before_char_to_delete.chain(after_char_to_delete).collect();
self.move_cursor_left();
}
}

fn clamp_cursor(&self, new_cursor_pos: usize) -> usize {
new_cursor_pos.clamp(0, self.input.chars().count())
}

fn reset_cursor(&mut self) {
self.character_index = 0;
}

fn submit_message(&mut self) {
self.input.clear();
self.reset_cursor();
}

fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(|frame| self.draw(frame))?;

if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Enter => self.submit_message(),
KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => {
return Ok(());
}
KeyCode::Char(c) => self.enter_char(c),
KeyCode::Backspace => self.delete_char(),
KeyCode::Left => self.move_cursor_left(),
KeyCode::Right => self.move_cursor_right(),
_ => {}
}
}
}
}

fn draw(&self, frame: &mut Frame) {
let prompt = "himalaya > ";

let layout =
Layout::horizontal([Constraint::Length(prompt.len() as u16), Constraint::Fill(1)]);
let [prompt_area, input_area] = layout.areas(frame.area());

frame.render_widget(Text::raw(prompt).blue(), prompt_area);
frame.render_widget(&self.input, input_area);

frame.set_cursor_position(Position::new(
input_area.x + self.character_index as u16,
input_area.y,
))
}
}

0 comments on commit f3d035c

Please sign in to comment.