mirror of
https://github.com/zaphar/sheetsui.git
synced 2025-07-23 05:19:48 -04:00
parent
d7301246d8
commit
e91c149619
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1399,6 +1399,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"ironcalc",
|
"ironcalc",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
|
"slice-cursor",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tui-prompts",
|
"tui-prompts",
|
||||||
"tui-textarea",
|
"tui-textarea",
|
||||||
@ -1455,6 +1456,11 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slice-cursor"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://dev.zaphar.net/zaphar/slice-cursor-rs.git#562a78eb3f06ac2a9729af7aa211a070f8ed9c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
|
@ -16,3 +16,4 @@ ratatui = "0.29.0"
|
|||||||
thiserror = "1.0.65"
|
thiserror = "1.0.65"
|
||||||
tui-textarea = "0.7.0"
|
tui-textarea = "0.7.0"
|
||||||
tui-prompts = "0.5.0"
|
tui-prompts = "0.5.0"
|
||||||
|
slice-cursor = { git = "https://dev.zaphar.net/zaphar/slice-cursor-rs.git" }
|
||||||
|
99
src/ui/cmd.rs
Normal file
99
src/ui/cmd.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//! Command mode command parsers.
|
||||||
|
use slice_cursor::{Cursor, Seekable, Span, SpanRange, StrCursor};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum Cmd<'a> {
|
||||||
|
Write(Option<&'a str>),
|
||||||
|
InsertRow(usize),
|
||||||
|
InsertColumns(usize),
|
||||||
|
Edit(&'a str),
|
||||||
|
Help(Option<&'a str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse<'cmd, 'i: 'cmd>(input: &'i str) -> Result<Option<Cmd<'cmd>>, &'static str> {
|
||||||
|
let cursor = StrCursor::new(input);
|
||||||
|
// try consume write command.
|
||||||
|
if let Some(cmd) = try_consume_write(cursor.clone()) {
|
||||||
|
return Ok(Some(cmd));
|
||||||
|
}
|
||||||
|
// try consume insert-row command.
|
||||||
|
if let Some(cmd) = try_consume_insert_row(cursor.clone())? {
|
||||||
|
return Ok(Some(cmd));
|
||||||
|
}
|
||||||
|
// try consume insert-col command.
|
||||||
|
if let Some(cmd) = try_consume_insert_column(cursor.clone()) {
|
||||||
|
return Ok(Some(cmd));
|
||||||
|
}
|
||||||
|
// try consume edit command.
|
||||||
|
if let Some(cmd) = try_consume_edit(cursor.clone()) {
|
||||||
|
return Ok(Some(cmd));
|
||||||
|
}
|
||||||
|
// try consume help command.
|
||||||
|
if let Some(cmd) = try_consume_help(cursor.clone()) {
|
||||||
|
return Ok(Some(cmd));
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
const WRITE: &'static str = "write";
|
||||||
|
|
||||||
|
pub fn try_consume_write<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option<Cmd<'cmd>> {
|
||||||
|
let prefix_len = WRITE.len();
|
||||||
|
let full_length = dbg!(input.span(..).len());
|
||||||
|
let arg = if full_length >= prefix_len && input.span(..prefix_len) == WRITE {
|
||||||
|
input.seek(prefix_len);
|
||||||
|
// Should we check for whitespace?
|
||||||
|
input.span(prefix_len..)
|
||||||
|
} else if full_length >= 2 && input.span(..2) == "w " {
|
||||||
|
input.span(2..)
|
||||||
|
// Should we check for whitespace?
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
.trim();
|
||||||
|
return Some(Cmd::Write(if arg.is_empty() { None } else { Some(arg) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
const IR: &'static str = "ir";
|
||||||
|
const INSERT_ROW: &'static str = "insert-row";
|
||||||
|
|
||||||
|
pub fn try_consume_insert_row<'cmd, 'i: 'cmd>(
|
||||||
|
mut input: StrCursor<'i>,
|
||||||
|
) -> Result<Option<Cmd<'cmd>>, &'static str> {
|
||||||
|
let prefix_len = INSERT_ROW.len();
|
||||||
|
let second_prefix_len = IR.len();
|
||||||
|
let full_length = input.span(..).len();
|
||||||
|
let arg =
|
||||||
|
if full_length >= prefix_len && input.span(..prefix_len) == INSERT_ROW {
|
||||||
|
input.seek(prefix_len);
|
||||||
|
// Should we check for whitespace?
|
||||||
|
input.span(prefix_len..)
|
||||||
|
} else if full_length >= second_prefix_len && input.span(..second_prefix_len) == IR {
|
||||||
|
input.span(second_prefix_len..)
|
||||||
|
// Should we check for whitespace?
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
.trim();
|
||||||
|
return Ok(Some(Cmd::InsertRow(if arg.is_empty() {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
if let Ok(count) = arg.parse() {
|
||||||
|
count
|
||||||
|
} else {
|
||||||
|
return Err("You must pass in a non negative number for the row count");
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_consume_insert_column<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option<Cmd<'cmd>> {
|
||||||
|
todo!("insert-column not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_consume_edit<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option<Cmd<'cmd>> {
|
||||||
|
todo!("edit not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_consume_help<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option<Cmd<'cmd>> {
|
||||||
|
todo!("help not yet implemented")
|
||||||
|
}
|
@ -12,6 +12,10 @@ use ratatui::{
|
|||||||
use tui_prompts::{State, Status, TextPrompt, TextState};
|
use tui_prompts::{State, Status, TextPrompt, TextState};
|
||||||
use tui_textarea::{CursorMove, TextArea};
|
use tui_textarea::{CursorMove, TextArea};
|
||||||
|
|
||||||
|
mod cmd;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq)]
|
#[derive(Default, Debug, PartialEq)]
|
||||||
pub enum Modality {
|
pub enum Modality {
|
||||||
#[default]
|
#[default]
|
||||||
@ -197,6 +201,14 @@ impl<'ws> Workspace<'ws> {
|
|||||||
if cmd.is_empty() {
|
if cmd.is_empty() {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
match cmd.as_str() {
|
||||||
|
"w" | "write" => {
|
||||||
|
self.save_file()?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// noop?
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
src/ui/test.rs
Normal file
45
src/ui/test.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use super::cmd::{parse, Cmd};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_write_cmd() {
|
||||||
|
let input = "write foo.xlsx";
|
||||||
|
let result = parse(input);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let output = result.unwrap();
|
||||||
|
assert!(output.is_some());
|
||||||
|
let cmd = output.unwrap();
|
||||||
|
assert_eq!(cmd, Cmd::Write(Some("foo.xlsx")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_short_write_cmd() {
|
||||||
|
let input = "w foo.xlsx";
|
||||||
|
let result = parse(input);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let output = result.unwrap();
|
||||||
|
assert!(output.is_some());
|
||||||
|
let cmd = output.unwrap();
|
||||||
|
assert_eq!(cmd, Cmd::Write(Some("foo.xlsx")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert_row_cmd() {
|
||||||
|
let input = "insert-row 1";
|
||||||
|
let result = parse(input);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let output = result.unwrap();
|
||||||
|
assert!(output.is_some());
|
||||||
|
let cmd = output.unwrap();
|
||||||
|
assert_eq!(cmd, Cmd::InsertRow(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert_row_cmd_short() {
|
||||||
|
let input = "ir 1";
|
||||||
|
let result = parse(input);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
let output = result.unwrap();
|
||||||
|
assert!(output.is_some());
|
||||||
|
let cmd = output.unwrap();
|
||||||
|
assert_eq!(cmd, Cmd::InsertRow(1));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user