feat: implement command mode

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2024-05-09 00:15:42 +02:00
parent 445a628ff5
commit ed5a5db7c5
8 changed files with 405 additions and 57 deletions

View File

@@ -0,0 +1,53 @@
use ratatui::widgets::{Paragraph, StatefulWidget, Widget};
use crate::{
commands::IntoCommand,
models::{EditMsg, Msg},
};
use super::dialog::BufferState;
pub struct CommandBarState {
contents: BufferState,
}
impl Default for CommandBarState {
fn default() -> Self {
Self {
contents: BufferState::Focused {
content: ropey::Rope::default(),
position: 0,
},
}
}
}
#[derive(Default)]
pub struct CommandBar {}
impl CommandBarState {
pub fn update(&mut self, msg: &Msg) -> anyhow::Result<impl IntoCommand> {
if let Msg::Edit(e) = msg {
self.contents.update(e)?;
if let EditMsg::InsertNewLine = e {
return Ok(Msg::SubmitCommand.into_command());
}
}
Ok(().into_command())
}
}
impl StatefulWidget for CommandBar {
type State = CommandBarState;
fn render(
self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
state: &mut Self::State,
) {
Paragraph::new(format!(":{}", state.contents.string())).render(area, buf);
}
}

View File

@@ -1,5 +1,3 @@
use std::{ops::Deref, rc::Rc};
use ratatui::{prelude::*, widgets::*};
use crate::models::{EditMsg, Msg};
@@ -25,13 +23,13 @@ impl Default for BufferState {
}
impl BufferState {
fn update(&mut self, msg: &EditMsg) -> anyhow::Result<()> {
pub fn update(&mut self, msg: &EditMsg) -> anyhow::Result<()> {
if let BufferState::Focused { content, position } = self {
let pos = *position;
match msg {
EditMsg::Delete => {
if pos > 0 && content.len_chars() > pos {
if pos > 0 && pos <= content.len_chars() {
content.remove((pos - 1)..pos);
*position = position.saturating_sub(1);
}
@@ -41,8 +39,8 @@ impl BufferState {
content.remove((pos)..pos + 1);
}
}
EditMsg::InsertNewLine => todo!(),
EditMsg::InsertTab => todo!(),
EditMsg::InsertNewLine => {}
EditMsg::InsertTab => {}
EditMsg::InsertChar(c) => {
content.try_insert_char(pos, *c)?;
*position = position.saturating_add(1);
@@ -51,7 +49,7 @@ impl BufferState {
*position = position.saturating_sub(1);
}
EditMsg::MoveRight => {
if pos + 1 < content.len_chars() {
if pos < content.len_chars() {
*position = pos.saturating_add(1);
}
}
@@ -60,10 +58,17 @@ impl BufferState {
Ok(())
}
pub fn string(&self) -> String {
match self {
BufferState::Focused { content, .. } => content.to_string(),
BufferState::Static { content, .. } => content.to_owned(),
}
}
}
pub struct InputBuffer {
state: BufferState,
pub state: BufferState,
}
impl InputBuffer {
@@ -111,7 +116,8 @@ impl InputBuffer {
pub fn update(&mut self, msg: &Msg) -> anyhow::Result<()> {
match msg {
Msg::EnterInsertMode => self.to_focused(),
Msg::EnterCommandMode => self.to_static(),
Msg::EnterCommandMode => self.to_focused(),
Msg::EnterViewMode => self.to_static(),
Msg::Edit(c) => {
self.state.update(c)?;
}
@@ -120,13 +126,12 @@ impl InputBuffer {
Ok(())
}
}
impl Widget for InputBuffer {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
pub fn string(&self) -> String {
match &self.state {
BufferState::Focused { ref content, .. } => content.to_string(),
BufferState::Static { content, .. } => content.to_owned(),
}
}
}
@@ -155,10 +160,13 @@ impl<'a> StatefulWidget for InputField<'a> {
let block = Block::bordered().title(self.title);
match &state.state {
BufferState::Focused { content, .. } => {
BufferState::Focused { content, position } => {
Paragraph::new(content.to_string().as_str())
.block(block)
.render(area, buf);
buf.get_mut(area.x + 1 + *position as u16, area.y + 1)
.set_style(Style::new().bg(Color::Magenta).fg(Color::Black));
}
BufferState::Static { content, .. } => {
Paragraph::new(content.as_str())