diff --git a/Cargo.lock b/Cargo.lock
index 3013130..f9705cd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -625,6 +625,12 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+[[package]]
+name = "futures-timer"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
+
[[package]]
name = "futures-util"
version = "0.3.31"
@@ -676,6 +682,12 @@ version = "0.29.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677"
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
[[package]]
name = "hashbrown"
version = "0.15.0"
@@ -731,6 +743,16 @@ dependencies = [
"cc",
]
+[[package]]
+name = "indexmap"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
[[package]]
name = "indoc"
version = "2.0.5"
@@ -1071,6 +1093,15 @@ dependencies = [
"zerocopy",
]
+[[package]]
+name = "proc-macro-crate"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
+dependencies = [
+ "toml_edit",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.89"
@@ -1140,6 +1171,15 @@ dependencies = [
"unicode-width 0.2.0",
]
+[[package]]
+name = "ratatui-macros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fef540f80dbe8a0773266fa6077788ceb65ef624cdbf36e131aaf90b4a52df4"
+dependencies = [
+ "ratatui",
+]
+
[[package]]
name = "redox_syscall"
version = "0.5.7"
@@ -1200,18 +1240,63 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+[[package]]
+name = "relative-path"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
+
[[package]]
name = "roxmltree"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
+[[package]]
+name = "rstest"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035"
+dependencies = [
+ "futures",
+ "futures-timer",
+ "rstest_macros",
+ "rustc_version",
+]
+
+[[package]]
+name = "rstest_macros"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a"
+dependencies = [
+ "cfg-if",
+ "glob",
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "regex 1.11.1",
+ "relative-path",
+ "rustc_version",
+ "syn",
+ "unicode-ident",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
version = "0.38.37"
@@ -1243,6 +1328,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
[[package]]
name = "serde"
version = "1.0.214"
@@ -1309,6 +1400,7 @@ dependencies = [
"ironcalc",
"ratatui",
"thiserror",
+ "tui-prompts",
"tui-textarea",
]
@@ -1468,6 +1560,35 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+
+[[package]]
+name = "toml_edit"
+version = "0.22.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "tui-prompts"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb6e0d8a972545cc209b933a1c06dab8932674b54ae19947834ec854fec2364f"
+dependencies = [
+ "itertools 0.13.0",
+ "ratatui",
+ "ratatui-macros",
+ "rstest",
+]
+
[[package]]
name = "tui-textarea"
version = "0.7.0"
@@ -1718,6 +1839,15 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+[[package]]
+name = "winnow"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "zerocopy"
version = "0.7.35"
diff --git a/Cargo.toml b/Cargo.toml
index d0d485d..1cda053 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,3 +15,4 @@ futures = "0.3.31"
ratatui = "0.29.0"
thiserror = "1.0.65"
tui-textarea = "0.7.0"
+tui-prompts = "0.5.0"
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
index 9e7bfca..c882acb 100644
--- a/src/ui/mod.rs
+++ b/src/ui/mod.rs
@@ -14,6 +14,7 @@ use ratatui::{
widgets::{Block, Cell, Paragraph, Row, Table, TableState, Widget},
Frame,
};
+use tui_prompts::{State, Status, TextPrompt, TextState};
use tui_textarea::{CursorMove, TextArea};
#[derive(Default, Debug, PartialEq)]
@@ -21,13 +22,15 @@ pub enum Modality {
#[default]
Navigate,
CellEdit,
+ Command,
// TODO(zaphar): Command Mode?
}
#[derive(Default, Debug)]
-pub struct AppState {
+pub struct AppState<'ws> {
pub modality: Modality,
pub table_state: TableState,
+ pub command_state: TextState<'ws>,
}
// TODO(jwall): This should probably move to a different module.
@@ -56,7 +59,7 @@ impl Default for Address {
pub struct Workspace<'ws> {
name: PathBuf,
book: Book,
- state: AppState,
+ state: AppState<'ws>,
text_area: TextArea<'ws>,
dirty: bool,
show_help: bool,
@@ -128,6 +131,7 @@ impl<'ws> Workspace<'ws> {
let result = match self.state.modality {
Modality::Navigate => self.handle_navigation_input(key)?,
Modality::CellEdit => self.handle_edit_input(key)?,
+ Modality::Command => self.handle_command_input(key)?,
};
return Ok(result);
}
@@ -151,18 +155,34 @@ impl<'ws> Workspace<'ws> {
"* ESC: Exit edit mode".into(),
"Otherwise edit as normal".into(),
]),
+ Modality::Command => Text::from(vec![
+ "Command Mode:".into(),
+ "* ESC: Exit command mode".into(),
+ ]),
})
.block(info_block)
}
+ fn handle_command_input(&mut self, key: event::KeyEvent) -> Result