Merge pull request #26 from zaphar/help

Help documentation improvements
This commit is contained in:
Jeremy Wall 2025-02-18 20:03:12 -05:00 committed by GitHub
commit b5e0362a4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 462 additions and 180 deletions

289
Cargo.lock generated
View File

@ -58,6 +58,19 @@ dependencies = [
"libc",
]
[[package]]
name = "ansi-to-tui"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67555e1f1ece39d737e28c8a017721287753af3f93225e4a445b29ccb0f5912c"
dependencies = [
"nom",
"ratatui",
"simdutf8",
"smallvec",
"thiserror",
]
[[package]]
name = "anstream"
version = "0.6.17"
@ -143,12 +156,27 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitcode"
version = "0.6.3"
@ -173,6 +201,12 @@ dependencies = [
"syn",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
@ -415,7 +449,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags",
"bitflags 2.6.0",
"crossterm_winapi",
"futures-core",
"mio",
@ -544,6 +578,12 @@ dependencies = [
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "digest"
version = "0.10.7"
@ -713,6 +753,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width 0.1.14",
]
[[package]]
name = "getrandom"
version = "0.2.15"
@ -925,6 +974,12 @@ version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
@ -968,6 +1023,12 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
@ -990,6 +1051,16 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@ -1020,6 +1091,28 @@ version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "onig"
version = "6.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
dependencies = [
"bitflags 1.3.2",
"libc",
"once_cell",
"onig_sys",
]
[[package]]
name = "onig_sys"
version = "69.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -1137,6 +1230,19 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "plist"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
dependencies = [
"base64",
"indexmap",
"quick-xml",
"serde",
"time",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -1152,6 +1258,16 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
@ -1170,6 +1286,34 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "pulldown-cmark"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
dependencies = [
"bitflags 2.6.0",
"getopts",
"memchr",
"pulldown-cmark-escape",
"unicase",
]
[[package]]
name = "pulldown-cmark-escape"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
[[package]]
name = "quick-xml"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.37"
@ -1215,7 +1359,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
"bitflags",
"bitflags 2.6.0",
"cassowary",
"compact_str",
"crossterm",
@ -1245,7 +1389,7 @@ version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
"bitflags 2.6.0",
]
[[package]]
@ -1340,7 +1484,7 @@ version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags",
"bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
@ -1359,6 +1503,15 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -1440,6 +1593,7 @@ dependencies = [
"serde_json",
"slice-utils",
"thiserror",
"tui-markdown",
"tui-popup",
"tui-prompts",
"tui-textarea",
@ -1481,6 +1635,12 @@ dependencies = [
"libc",
]
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "0.3.11"
@ -1558,6 +1718,28 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "syntect"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
dependencies = [
"bincode",
"bitflags 1.3.2",
"flate2",
"fnv",
"once_cell",
"onig",
"plist",
"regex-syntax",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"walkdir",
"yaml-rust",
]
[[package]]
name = "thiserror"
version = "1.0.65"
@ -1585,10 +1767,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
@ -1597,6 +1781,16 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
@ -1614,6 +1808,53 @@ dependencies = [
"winnow",
]
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
]
[[package]]
name = "tui-markdown"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf7ca4141b6846fae9ca363e7cf00277978d999bf85bfd40b4f569305994c6b"
dependencies = [
"ansi-to-tui",
"itertools 0.13.0",
"pretty_assertions",
"pulldown-cmark",
"ratatui",
"rstest",
"syntect",
"tracing",
]
[[package]]
name = "tui-popup"
version = "0.6.0"
@ -1655,6 +1896,12 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicase"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"
version = "1.0.13"
@ -1702,6 +1949,16 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -1779,6 +2036,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@ -1885,6 +2151,21 @@ dependencies = [
"memchr",
]
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "zerocopy"
version = "0.7.35"

View File

@ -21,3 +21,4 @@ slice-utils = { git = "https://dev.zaphar.net/zaphar/slice-cursor-rs.git" }
tui-popup = "0.6.0"
serde_json = "1.0.133"
colorsys = "0.6.7"
tui-markdown = { version = "0.3.1", features = [] }

20
docs/command.md Normal file
View File

@ -0,0 +1,20 @@
# Command Mode
You enter command mode by typing `:` while in navigation mode. You can then
type a command and hit `Enter` to execute it or `Esc` to cancel.
The currently supported commands are:
* `write [path]` save the current spreadsheet. If the path is provided it will save it to that path. If omitted it will save to the path you are currently editing. `w` is a shorthand alias for this command.
* `insert-rows [number]` Inserts a row into the sheet at your current row. If the number is provided then inserts that many rows. If omitted then just inserts one.
* `insert-cols [number]` Just line `insert-rows` but for columns.
* `rename-sheet [idx] <name>` rename a sheet. If the idx is provide then renames that sheet. If omitted then it renames the current sheet.
* `new-sheet [name]` Creates a new sheet. If the name is provided then uses that. If omitted then uses a default sheet name.
* `select-sheet <name>` Select a sheet by name.
* `edit <path>` Edit a new spreadsheet at the current path. `e` is a shorthand alias for this command.
* `quit` Quits the application. `q` is a shorthand alias for this command.
<aside>Note that in the case of `quit` and `edit` that we do not currently
prompt you if the current spreadsheet has not been saved yet. So your changes
will be discarded if you have not saved first.</aside>

31
docs/edit.md Normal file
View File

@ -0,0 +1,31 @@
# Edit Mode
You enter Edit mode by hitting `e` or `i` while in navigation mode. Type
what you want into the cell.
Starting with:
* `=` will treat what you type as a formula.
* `$` will treat it as us currency.
Typing a number will treat the contents as a number. While typing non-numeric
text will treat it as text content.
<aside>We do not yet support modifying the type of a cell after the fact. We
may add this in the future.</aside>
For the most part this should work the same way you expect a spreadsheet to
work.
* `Enter` will update the cell contents.
* `Esc` will cancel editing the cell and leave it unedited.
* `Ctrl-p` will paste the range selection if it exists into the cell.
`Ctrl-r` will enter range select mode when editing a formula. You can navigate
around the sheet and hit space to select that cell in the sheet to set the
start of the range. Navigate some more and hit space to set the end of the
range.
You can find the functions we support documented here:
[ironcalc docs](https://docs.ironcalc.com/functions/lookup-and-reference.html)

View File

@ -33,123 +33,9 @@ The sheetui user interface is loosely inspired by vim. It is a modal interface
that is entirely keyboard driven. At nearly any time you can type `Alt-h` to
get some context sensitive help.
### Navigation Mode
### Modal Docs
The interface will start out in navigation mode. You can navigate around the
table and between the sheets using the following keybinds:
**Cell Navigation**
* `h`, ⬆️, and `TAB` will move one cell to the left.
* `l` and, ➡️ will move one cell to the right.
* `j`, ⬇️, and `Enter` will move one cell down.
* `k` ⬆️, will move one cell up.
* `d` will delete the contents of the selected cell leaving style untouched
* `D` will delete the contents of the selected cell including any style
* `gg` will go to the top row in the current column
**Sheet Navigation**
* `Ctrl-n` moves to the next sheet
* `Ctrl-p` moves to the prev sheet
Sheet navigation moving will loop around when you reach the ends.
**Numeric prefixes**
You can prefix each of the keybinds above with a numeric prefix to do them that
many times. So typing `123h` will move to the left 123 times. Hitting `Esc`
will clear the numeric prefix if you want to cancel it.
**Modifying the Sheet or Cells**
* `e` or `i` will enter CellEdit mode for the current cell.
* `Ctrl-h` will shorten the width of the column you are on.
* `Ctrl-l` will lengthen the width of the column you are on.
**Other Keybindings**
* `Ctrl-r` will enter range selection mode.
* `v` will enter range selection mode with the start of the range already selected.
* `Ctrl-s` will save the sheet.
* `Ctrl-c`, `y` Copy the cell or range contents.
* `Ctrl-v`, `p` Paste into the sheet.
* `Ctrl-Shift-C` Copy the cell or range formatted content.
* `q` will exit the application.
* `:` will enter CommandMode.
Range selections made from navigation mode will be available to paste into a Cell Edit.
<aside>Note that for `q` this will not currently prompt you if the sheet is not
saved.</aside>
### CellEdit Mode
You enter CellEdit mode by hitting `e` or `i` while in navigation mode. Type
what you want into the cell.
Starting with:
* `=` will treat what you type as a formula.
* `$` will treat it as us currency.
Typing a number will treat the contents as a number. While typing non-numeric
text will treat it as text content.
<aside>We do not yet support modifying the type of a cell after the fact. We
may add this in the future.</aside>
For the most part this should work the same way you expect a spreadsheet to
work.
* `Enter` will update the cell contents.
* `Esc` will cancel editing the cell and leave it unedited.
* `Ctrl-p` will paste the range selection if it exists into the cell.
`Ctrl-r` will enter range select mode when editing a formula. You can navigate
around the sheet and hit space to select that cell in the sheet to set the
start of the range. Navigate some more and hit space to set the end of the
range.
You can find the functions we support documented here:
[ironcalc docs](https://docs.ironcalc.com/functions/lookup-and-reference.html)
### Command Mode
You enter command mode by typing `:` while in navigation mode. You can then
type a command and hit `Enter` to execute it or `Esc` to cancel.
The currently supported commands are:
* `write [path]` save the current spreadsheet. If the path is provided it will save it to that path. If omitted it will save to the path you are currently editing. `w` is a shorthand alias for this command.
* `insert-rows [number]` Inserts a row into the sheet at your current row. If the number is provided then inserts that many rows. If omitted then just inserts one.
* `insert-cols [number]` Just line `insert-rows` but for columns.
* `rename-sheet [idx] <name>` rename a sheet. If the idx is provide then renames that sheet. If omitted then it renames the current sheet.
* `new-sheet [name]` Creates a new sheet. If the name is provided then uses that. If omitted then uses a default sheet name.
* `select-sheet <name>` Select a sheet by name.
* `edit <path>` Edit a new spreadsheet at the current path. `e` is a shorthand alias for this command.
* `quit` Quits the application. `q` is a shorthand alias for this command.
<aside>Note that in the case of `quit` and `edit` that we do not currently
prompt you if the current spreadsheet has not been saved yet. So your changes
will be discarded if you have not saved first.</aside>
### Range Select Mode
Range Select mode copies a range reference for use later or delete a range's contents. You can enter range
select mode from CellEdit mode with `CTRL-r`.
* `h`, `j`, `k`, `l` will navigate around the sheet.
* `Ctrl-n`, `Ctrl-p` will navigate between sheets.
* `Ctrl-c`, `y` Copy the cell or range contents.
* `Ctrl-Shift-C`, 'Y' Copy the cell or range formatted content.
* `The spacebar will select the start and end of the range respectively.
* `d` will delete the contents of the range leaving any style untouched
* `D` will delete the contents of the range including any style
When you have selected the end of the range you will exit range select mode and
the range reference will be placed into the cell contents you are editing.
<aside>We only support continuous ranges for the moment. Planned for
discontinuous ranges still needs the interaction interface to be
determined.</aside>
* [Navigation](./navigation.md)
* [Edit](./edit.md)
* [Visual](./visual.md)
* [Command](./command.md)

23
docs/intro.md Normal file
View File

@ -0,0 +1,23 @@
# Intro
## Supported formats
Currently we only support the [ironcalc](https://docs.ironcalc.com/) xlsx
features for spreadsheet. I plan to handle csv import and export at some point.
I also might support other export formats as well but for the moment just csv
and it's variants such as tsv are in the roadmap.
## User Interface
The sheetui user interface is loosely inspired by vim. It is a modal interface
that is entirely keyboard driven. At nearly any time you can type `Alt-h` to
get some context sensitive help.
## Modal Docs
To get help on each modality in command mode `:` type
* `help navigate`
* `help edit`
* `help command`
* `help visual`

50
docs/navigation.md Normal file
View File

@ -0,0 +1,50 @@
# Navigation Mode
The interface will start out in navigation mode. You can navigate around the
table and between the sheets using the following keybinds:
## Cell Navigation
* `h`, ⬆️, and `TAB` will move one cell to the left.
* `l` and, ➡️ will move one cell to the right.
* `j`, ⬇️, and `Enter` will move one cell down.
* `k` ⬆️, will move one cell up.
* `d` will delete the contents of the selected cell leaving style untouched
* `D` will delete the contents of the selected cell including any style
* `gg` will go to the top row in the current column
## Sheet Navigation
* `Ctrl-n` moves to the next sheet
* `Ctrl-p` moves to the prev sheet
Sheet navigation moving will loop around when you reach the ends.
## Numeric prefixes
You can prefix each of the keybinds above with a numeric prefix to do them that
many times. So typing `123h` will move to the left 123 times. Hitting `Esc`
will clear the numeric prefix if you want to cancel it.
**Modifying the Sheet or Cells**
* `e` or `i` will enter CellEdit mode for the current cell.
* `Ctrl-h` will shorten the width of the column you are on.
* `Ctrl-l` will lengthen the width of the column you are on.
## Other Keybindings
* `Ctrl-r` will enter range selection mode.
* `v` will enter range selection mode with the start of the range already selected.
* `Ctrl-s` will save the sheet.
* `Ctrl-c`, `y` Copy the cell or range contents.
* `Ctrl-v`, `p` Paste into the sheet.
* `Ctrl-Shift-C` Copy the cell or range formatted content.
* `q` will exit the application.
* `:` will enter CommandMode.
Range selections made from navigation mode will be available to paste into a Cell Edit.
<aside>Note that for `q` this will not currently prompt you if the sheet is not
saved.</aside>

19
docs/visual.md Normal file
View File

@ -0,0 +1,19 @@
# Range Select Mode
Range Select mode copies a range reference for use later or delete a range's contents. You can enter range
select mode from CellEdit mode with `CTRL-r`.
* `h`, `j`, `k`, `l` will navigate around the sheet.
* `Ctrl-n`, `Ctrl-p` will navigate between sheets.
* `Ctrl-c`, `y` Copy the cell or range contents.
* `Ctrl-Shift-C`, 'Y' Copy the cell or range formatted content.
* `The spacebar will select the start and end of the range respectively.
* `d` will delete the contents of the range leaving any style untouched
* `D` will delete the contents of the range including any style
When you have selected the end of the range you will exit range select mode and
the range reference will be placed into the cell contents you are editing.
<aside>We only support continuous ranges for the moment. Planned for
discontinuous ranges still needs the interaction interface to be
determined.</aside>

2
result
View File

@ -1 +1 @@
/nix/store/k826wsv9zc73jamdff1yl1rky2bw9lc6-sheetui-0.1.0
/nix/store/mvnsm5ndvx4psah2d3y6yd2vwkypy9m7-sheetui-0.1.0

12
src/ui/help/mod.rs Normal file
View File

@ -0,0 +1,12 @@
use ratatui::text::Text;
use tui_markdown;
pub fn render_topic(topic: &str) -> Text<'static> {
match topic {
"navigate" => tui_markdown::from_str(include_str!("../../../docs/navigation.md")),
"edit" => tui_markdown::from_str(include_str!("../../../docs/edit.md")),
"command" => tui_markdown::from_str(include_str!("../../../docs/command.md")),
"visual" => tui_markdown::from_str(include_str!("../../../docs/visual.md")),
_ => tui_markdown::from_str(include_str!("../../../docs/intro.md")),
}
}

View File

@ -7,14 +7,12 @@ use anyhow::{anyhow, Result};
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
use ironcalc::base::{expressions::types::Area, Model};
use ratatui::{
buffer::Buffer,
layout::{Constraint, Flex, Layout},
style::{Modifier, Style},
widgets::Block,
buffer::Buffer, layout::{Constraint, Flex, Layout}, style::{Modifier, Style}, text::{Line, Text}, widgets::Block
};
use tui_prompts::{State, Status, TextPrompt, TextState};
use tui_textarea::{CursorMove, TextArea};
mod help;
mod cmd;
pub mod render;
#[cfg(test)]
@ -81,7 +79,7 @@ pub struct AppState<'ws> {
pub char_queue: Vec<char>,
pub range_select: RangeSelection,
dirty: bool,
popup: Vec<String>,
popup: Text<'ws>,
clipboard: Option<ClipboardContents>,
}
@ -296,55 +294,16 @@ impl<'ws> Workspace<'ws> {
Ok(None)
}
fn render_help_text(&self) -> Vec<String> {
fn render_help_text(&self) -> Text<'static> {
// TODO(zaphar): We should be sourcing these from our actual help documentation.
// Ideally we would also render the markdown content properly.
// https://github.com/zaphar/sheetsui/issues/22
match self.state.modality() {
Modality::Navigate => vec![
"Navigate Mode:".to_string(),
"* e,i: Enter edit mode for current cell".to_string(),
"* ENTER/RETURN: Go down one cell".to_string(),
"* TAB: Go over one cell".to_string(),
"* h,j,k,l: vim style navigation".to_string(),
"* d: clear cell contents leaving style untouched".to_string(),
"* D: clear cell contents including style".to_string(),
"* CTRl-r: Add a row".to_string(),
"* CTRl-c: Add a column".to_string(),
"* CTRl-l: Grow column width by 1".to_string(),
"* CTRl-h: Shrink column width by 1".to_string(),
"* CTRl-n: Next sheet. Starts over at beginning if at end.".to_string(),
"* CTRl-p: Previous sheet. Starts over at end if at beginning.".to_string(),
"* ALT-h: Previous sheet. Starts over at end if at beginning.".to_string(),
"* q exit".to_string(),
"* Ctrl-S Save sheet".to_string(),
],
Modality::CellEdit => vec![
"Edit Mode:".to_string(),
"* ENTER/RETURN: Exit edit mode and save changes".to_string(),
"* Ctrl-r: Enter Range Selection mode".to_string(),
"* v: Enter Range Selection mode with the start of the range already selected"
.to_string(),
"* ESC: Exit edit mode and discard changes".to_string(),
"Otherwise edit as normal".to_string(),
],
Modality::Command => vec![
"Command Mode:".to_string(),
"* ESC: Exit command mode".to_string(),
"* CTRL-?: Exit command mode".to_string(),
"* ENTER/RETURN: run command and exit command mode".to_string(),
],
Modality::RangeSelect => vec![
"Range Selection Mode:".to_string(),
"* ESC: Exit command mode".to_string(),
"* h,j,k,l: vim style navigation".to_string(),
"* d: delete the contents of the range leaving style untouched".to_string(),
"* D: clear cell contents including style".to_string(),
"* Spacebar: Select start and end of range".to_string(),
"* CTRl-n: Next sheet. Starts over at beginning if at end.".to_string(),
"* CTRl-p: Previous sheet. Starts over at end if at beginning.".to_string(),
],
_ => vec!["General help".to_string()],
Modality::Navigate => help::render_topic("navigate"),
Modality::CellEdit => help::render_topic("edit"),
Modality::Command => help::render_topic("command"),
Modality::RangeSelect => help::render_topic("visual"),
_ => help::render_topic(""),
}
}
@ -424,8 +383,8 @@ impl<'ws> Workspace<'ws> {
self.load_into(path)?;
Ok(None)
}
Ok(Some(Cmd::Help(_maybe_topic))) => {
self.enter_dialog_mode(vec!["TODO help topic".to_owned()]);
Ok(Some(Cmd::Help(maybe_topic))) => {
self.enter_dialog_mode(help::render_topic(maybe_topic.unwrap_or("")));
Ok(None)
}
Ok(Some(Cmd::Write(maybe_path))) => {
@ -515,11 +474,11 @@ impl<'ws> Workspace<'ws> {
Ok(None)
}
Ok(None) => {
self.enter_dialog_mode(vec![format!("Unrecognized commmand {}", cmd_text)]);
self.enter_dialog_mode(vec![Line::from(format!("Unrecognized commmand {}", cmd_text))]);
Ok(None)
}
Err(msg) => {
self.enter_dialog_mode(vec![msg.to_owned()]);
self.enter_dialog_mode(vec![Line::from(msg.to_owned())]);
Ok(None)
}
}
@ -931,8 +890,8 @@ impl<'ws> Workspace<'ws> {
self.state.command_state.focus();
}
fn enter_dialog_mode(&mut self, msg: Vec<String>) {
self.state.popup = msg;
fn enter_dialog_mode<T: Into<Text<'ws>>>(&mut self, msg: T) {
self.state.popup = msg.into();
self.state.modality_stack.push(Modality::Dialog);
}