//! 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>, &'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> { 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>, &'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> { todo!("insert-column not yet implemented") } pub fn try_consume_edit<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option> { todo!("edit not yet implemented") } pub fn try_consume_help<'cmd, 'i: 'cmd>(mut input: StrCursor<'i>) -> Option> { todo!("help not yet implemented") }