diff --git a/CLAUDE.md b/CLAUDE.md index 97aa82c..b6df388 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -171,9 +171,14 @@ builds the tree. Help renders through `gotermstyle/cobrahelp`. - **Every key the board takes is a row in `tui/action_table.go`, in every mode.** The key handler, the hints in the status bar and in each prompt, picker and overlay, and the `?` overlay all read it. So a - key added there shows in each, and a row's `applies` keeps it out of each where it does not act. A - mode with a text box binds only keys that type nothing, and `typesText` hands the rest to the box. - The hosted reader takes its own keys while it shows. + key added there shows in each, and a row's `Applies` keeps it out of each where it does not act. A + row is gotermboard's `KeyAction`. On the board, `j` `k` `g` `G`, `ctrl+d` `ctrl+u`, `J` `K`, `[` + `]`, Enter, space, `?` and `q` are gotermboard's `UniversalActions`, acting on `App` as a + `gotermboard.Host` in `tui/key_host.go`, and the board's own rows take a key ahead of them where + they apply. A mode with a text box binds only keys that type nothing, and `typesText` hands the + rest to the box. The hosted reader takes its own keys while it shows. +- **Enter and space open an item's detail, the page its reader shows.** Space opens it under the + row however tall. Enter opens it there where it fits the pane, and full screen where it does not. - **The board hosts gotermboard's `Reader` and not its `Model`.** Its own panes, glyphs and footer are drawn in `tui`, so `App` forwards keys, pastes and window sizes to the reader while one shows, and `Reader.ClosesWith` hands the screen back. diff --git a/go.mod b/go.mod index af66b1c..134036e 100644 --- a/go.mod +++ b/go.mod @@ -17,8 +17,8 @@ require ( github.com/datapointchris/goclikit v0.5.3 github.com/datapointchris/goclilogin v0.9.0 github.com/datapointchris/goselfupdate v0.11.0 - github.com/datapointchris/gotermboard v0.31.0 - github.com/datapointchris/gotermstyle v0.4.0 + github.com/datapointchris/gotermboard v0.43.0 + github.com/datapointchris/gotermstyle v0.5.0 github.com/datapointchris/tuidrive v0.1.0 github.com/go-viper/mapstructure/v2 v2.4.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index f1c2d87..1c5c90d 100644 --- a/go.sum +++ b/go.sum @@ -91,10 +91,10 @@ github.com/datapointchris/goclilogin v0.9.0 h1:xajsKfzuBvuREUZqw7B9Gv5PHxylSc8ss github.com/datapointchris/goclilogin v0.9.0/go.mod h1:oiMIbY0jwfqH5pX8G1T1iBPa+cG1m3JQhqpaP9JxJ+w= github.com/datapointchris/goselfupdate v0.11.0 h1:aUJ27Cm9ZNGMfC7+kKChBsnm8offBE99wwUa10lFo2w= github.com/datapointchris/goselfupdate v0.11.0/go.mod h1:YcgyvM+wH6nh9zo9xioUqTHeH5HTYeCHevv4U+G7INc= -github.com/datapointchris/gotermboard v0.31.0 h1:Ri8KUGjPXoS5xM+/PA4IPicwzzNKKxMVwa2jH0ZtFbc= -github.com/datapointchris/gotermboard v0.31.0/go.mod h1:gzSG1LtOC2McInuKV5mSFJOLZ3EnFIY/1chPyivuxe0= -github.com/datapointchris/gotermstyle v0.4.0 h1:kOovTrAVF4oI/P6ptNg5VTuU9woNpPyjrhcKd6ndJsI= -github.com/datapointchris/gotermstyle v0.4.0/go.mod h1:pcTXWC/xls5Riw0rFtTueCQGlnszB3sqlepRItgdgeg= +github.com/datapointchris/gotermboard v0.43.0 h1:WQ5xgmogGwu7V+0BaoJYrr+qATVTc46XAqkX/6rDpZ8= +github.com/datapointchris/gotermboard v0.43.0/go.mod h1:A/9phVumidQPEVvHBLHTIWGgMfwbyDT+1/0iOHtjmao= +github.com/datapointchris/gotermstyle v0.5.0 h1:xdpuNASa4vS0jSMpBDQOO0rRFGY7jaft5H3hTHOrREE= +github.com/datapointchris/gotermstyle v0.5.0/go.mod h1:pcTXWC/xls5Riw0rFtTueCQGlnszB3sqlepRItgdgeg= github.com/datapointchris/tuidrive v0.1.0 h1:s6esDWL9P8EkQYzdvrPwvBxYjPF98u0ukpnZbfBIGOc= github.com/datapointchris/tuidrive v0.1.0/go.mod h1:lbRNaZkLTfPvfVqkJlcCzfuItgbePNp1flvS70mf/gI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/real_binary_flows_test.go b/real_binary_flows_test.go index 1900075..6818e8e 100644 --- a/real_binary_flows_test.go +++ b/real_binary_flows_test.go @@ -41,7 +41,7 @@ func TestRealBinaryFlows(t *testing.T) { {name: "views", script: "views.keys"}, {name: "filter", script: "filter.keys"}, {name: "move", script: "move.keys"}, - {name: "note-in-place", script: "note-in-place.keys"}, + {name: "detail-in-place", script: "detail-in-place.keys"}, {name: "reader", script: "reader.keys"}, {name: "add-project-and-item", script: "add-project-and-item.keys"}, {name: "add-task", script: "add-task.keys"}, diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/item-added.txt b/testdata/TestRealBinaryFlows/add-project-and-item/item-added.txt index 2733c76..f904edc 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/item-added.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/item-added.txt @@ -1,7 +1,7 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Repaint the fence ┃ -│ Move the blog to plain files ○3 ✓1 │┃> ○ Scrape and prime the boards ┃ +│ Move the blog to plain files ○3 ✓1 │┃> ▸ ○ Scrape and prime the boards ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 39┃ │ Plan the Lisbon trip ○31 ✓0 │┃ ┃ │> Repaint the fence ○1 ✓0 │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item created [?]help LOCAL projects.db + Item created ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/item-in-two-projects.txt b/testdata/TestRealBinaryFlows/add-project-and-item/item-in-two-projects.txt index 941e430..c678023 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/item-in-two-projects.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/item-in-two-projects.txt @@ -1,9 +1,9 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Repaint the fence ┃ -│ Move the blog to plain files ○3 ✓1 │┃> ○ Scrape and prime the boards ┃ +│ Move the blog to plain files ○3 ✓1 │┃> ▸ ○ Scrape and prime the boards ┃ │ Replace the kitchen faucet ○4 ✓0 │┃ 39┃ -│ Plan the Lisbon trip ○31 ✓0 │┃ ○ Buy exterior paint ◈ ┃ +│ Plan the Lisbon trip ○31 ✓0 │┃ ▸ ○ Buy exterior paint ◈ ┃ │> Repaint the fence ○2 ✓0 │┃ also in Replace the kitchen faucet 40┃ │ │┃ ┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item created [?]help LOCAL projects.db + Item created ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.style b/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.style index 899521f..6d85653 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.style @@ -10,7 +10,7 @@ 15: 81-81 fg=4 16: 20-81 fg=4 17: 20-20 fg=4 -17: 25-50 fg=8 +17: 25-49 fg=8 17: 81-81 fg=4 18: 20-81 fg=4 19: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.txt b/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.txt index c897c13..fea2d4e 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/item-prompt.txt @@ -14,6 +14,6 @@ │ │ │ > Enter item title... │ │ │ - │ [Enter]confirm [Esc]cancel │ + │ enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-added.style b/testdata/TestRealBinaryFlows/add-project-and-item/project-added.style index 3ff413f..7d6f87a 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-added.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-added.style @@ -43,7 +43,9 @@ 8: 100-100 fg=8 9: 1-40 fg=4 9: 41-41 fg=8 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-added.txt b/testdata/TestRealBinaryFlows/add-project-and-item/project-added.txt index be470d5..d26b609 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-added.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-added.txt @@ -6,12 +6,12 @@ ┃ Plan the Lisbon trip ○31 ✓0 ┃│ ✓ Dump the database │ ┃ Repaint the fence ○0 ✓0 ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - Project created [?]help LOCAL projects.db + Project created ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.style b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.style index fd62690..2c64010 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.style @@ -23,7 +23,7 @@ 19: 81-81 fg=4 20: 20-81 fg=4 21: 20-20 fg=4 -21: 25-64 fg=8 +21: 25-63 fg=8 21: 81-81 fg=4 22: 20-81 fg=4 23: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.txt b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.txt index 757db62..91d7d0c 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker-toggled.txt @@ -18,6 +18,6 @@ │ │ │ Currently in 2 project(s). Must belong to at least 1. │ │ │ - │ [space]toggle [Enter]confirm [Esc]cancel │ + │ space toggle enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.style b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.style index 2b4e2e3..1f406f4 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.style @@ -23,7 +23,7 @@ 19: 81-81 fg=4 20: 20-81 fg=4 21: 20-20 fg=4 -21: 25-64 fg=8 +21: 25-63 fg=8 21: 81-81 fg=4 22: 20-81 fg=4 23: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.txt b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.txt index 551d6a1..ca1ac6f 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-picker.txt @@ -18,6 +18,6 @@ │ │ │ Currently in 1 project(s). Must belong to at least 1. │ │ │ - │ [space]toggle [Enter]confirm [Esc]cancel │ + │ space toggle enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.style b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.style index d439f37..d94571c 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.style @@ -9,7 +9,7 @@ 15: 81-81 fg=4 16: 20-81 fg=4 17: 20-20 fg=4 -17: 25-50 fg=8 +17: 25-49 fg=8 17: 81-81 fg=4 18: 20-81 fg=4 19: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.txt b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.txt index f0d786d..9bd1f40 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt-typed.txt @@ -14,6 +14,6 @@ │ │ │ > Repaint the fence │ │ │ - │ [Enter]confirm [Esc]cancel │ + │ enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.style b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.style index 340d264..40098bd 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.style +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.style @@ -10,7 +10,7 @@ 15: 81-81 fg=4 16: 20-81 fg=4 17: 20-20 fg=4 -17: 25-50 fg=8 +17: 25-49 fg=8 17: 81-81 fg=4 18: 20-81 fg=4 19: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.txt b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.txt index 2f05fd3..c43e395 100644 --- a/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.txt +++ b/testdata/TestRealBinaryFlows/add-project-and-item/project-prompt.txt @@ -14,6 +14,6 @@ │ │ │ > Enter project name... │ │ │ - │ [Enter]confirm [Esc]cancel │ + │ enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-task/added-from-the-list.style b/testdata/TestRealBinaryFlows/add-task/added-from-the-list.style index 661002b..fce6e97 100644 --- a/testdata/TestRealBinaryFlows/add-task/added-from-the-list.style +++ b/testdata/TestRealBinaryFlows/add-task/added-from-the-list.style @@ -45,7 +45,9 @@ 9: 100-100 fg=4 10: 1-40 fg=8 10: 41-41 fg=4 -10: 42-46 strike +10: 42-44 strike +10: 45-45 fg=8 strike +10: 46-46 strike 10: 47-47 fg=8 strike 10: 48-48 strike 10: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/add-task/added-from-the-list.txt b/testdata/TestRealBinaryFlows/add-task/added-from-the-list.txt index c92cf4b..8dccc18 100644 --- a/testdata/TestRealBinaryFlows/add-task/added-from-the-list.txt +++ b/testdata/TestRealBinaryFlows/add-task/added-from-the-list.txt @@ -7,12 +7,12 @@ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ │ │┃ ○ Check the image links ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove [Tab]view … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/add-task/prompt.style b/testdata/TestRealBinaryFlows/add-task/prompt.style index 9cc294b..4d5ccd8 100644 --- a/testdata/TestRealBinaryFlows/add-task/prompt.style +++ b/testdata/TestRealBinaryFlows/add-task/prompt.style @@ -10,7 +10,7 @@ 15: 81-81 fg=4 16: 20-81 fg=4 17: 20-20 fg=4 -17: 25-50 fg=8 +17: 25-49 fg=8 17: 81-81 fg=4 18: 20-81 fg=4 19: 20-81 fg=4 diff --git a/testdata/TestRealBinaryFlows/add-task/prompt.txt b/testdata/TestRealBinaryFlows/add-task/prompt.txt index 6e2bcee..94999e9 100644 --- a/testdata/TestRealBinaryFlows/add-task/prompt.txt +++ b/testdata/TestRealBinaryFlows/add-task/prompt.txt @@ -14,6 +14,6 @@ │ │ │ > New task... │ │ │ - │ [Enter]confirm [Esc]cancel │ + │ enter confirm esc cancel │ │ │ ╰────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/add-task/task-deleted.style b/testdata/TestRealBinaryFlows/add-task/task-deleted.style index 64b1808..dc4735a 100644 --- a/testdata/TestRealBinaryFlows/add-task/task-deleted.style +++ b/testdata/TestRealBinaryFlows/add-task/task-deleted.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/add-task/task-deleted.txt b/testdata/TestRealBinaryFlows/add-task/task-deleted.txt index 707abd1..6c6c52d 100644 --- a/testdata/TestRealBinaryFlows/add-task/task-deleted.txt +++ b/testdata/TestRealBinaryFlows/add-task/task-deleted.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ > ○ Download the images ┃ │ │┃ ○ Check the image links ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [a]dd [space]done [D]elete [Tab]view [/]filter [?]help LOCAL projects.db + a add space done D delete tab view / filter j/k move [/] jump … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/add-task/task-toggled.style b/testdata/TestRealBinaryFlows/add-task/task-toggled.style index 1838d09..406a24b 100644 --- a/testdata/TestRealBinaryFlows/add-task/task-toggled.style +++ b/testdata/TestRealBinaryFlows/add-task/task-toggled.style @@ -52,7 +52,9 @@ 9: 100-100 fg=4 10: 1-40 fg=8 10: 41-41 fg=4 -10: 42-46 strike +10: 42-44 strike +10: 45-45 fg=8 strike +10: 46-46 strike 10: 47-47 fg=8 strike 10: 48-48 strike 10: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/add-task/task-toggled.txt b/testdata/TestRealBinaryFlows/add-task/task-toggled.txt index daa04e6..07f1094 100644 --- a/testdata/TestRealBinaryFlows/add-task/task-toggled.txt +++ b/testdata/TestRealBinaryFlows/add-task/task-toggled.txt @@ -7,12 +7,12 @@ │ │┃ > ✓ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ │ │┃ ○ Check the image links ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [a]dd [space]done [D]elete [Tab]view [/]filter [?]help LOCAL projects.db + a add space done D delete tab view / filter j/k move [/] jump … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/api-mode/item-added.style b/testdata/TestRealBinaryFlows/api-mode/item-added.style index a54150e..30552eb 100644 --- a/testdata/TestRealBinaryFlows/api-mode/item-added.style +++ b/testdata/TestRealBinaryFlows/api-mode/item-added.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/api-mode/item-added.txt b/testdata/TestRealBinaryFlows/api-mode/item-added.txt index b51c119..d57354b 100644 --- a/testdata/TestRealBinaryFlows/api-mode/item-added.txt +++ b/testdata/TestRealBinaryFlows/api-mode/item-added.txt @@ -6,15 +6,15 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ -│ │┃ ○ Rotate the API keys ┃ +│ │┃ ▸ ○ Rotate the API keys ┃ │ │┃ 39┃ │ │┃ ┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item created [?]help API 127.0.0.1: + Item created ? keys API 127.0.0.1: diff --git a/testdata/TestRealBinaryFlows/api-mode/opened.style b/testdata/TestRealBinaryFlows/api-mode/opened.style index be69960..c61a32d 100644 --- a/testdata/TestRealBinaryFlows/api-mode/opened.style +++ b/testdata/TestRealBinaryFlows/api-mode/opened.style @@ -41,7 +41,9 @@ 8: 100-100 fg=8 9: 1-40 fg=4 9: 41-41 fg=8 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/api-mode/opened.txt b/testdata/TestRealBinaryFlows/api-mode/opened.txt index 0c35ffe..7612def 100644 --- a/testdata/TestRealBinaryFlows/api-mode/opened.txt +++ b/testdata/TestRealBinaryFlows/api-mode/opened.txt @@ -6,12 +6,12 @@ ┃ Plan the Lisbon trip ○31 ✓0 ┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]read [space]mark [a]dd [e]dit [M]ove [Tab]view [/]filter [?]help API 127.0.0.1: + enter read space mark a add e edit M move tab view / filter … ? keys API 127.0.0.1: diff --git a/testdata/TestRealBinaryFlows/browse/archived-filter.style b/testdata/TestRealBinaryFlows/browse/archived-filter.style index 5ed016d..bedc30c 100644 --- a/testdata/TestRealBinaryFlows/browse/archived-filter.style +++ b/testdata/TestRealBinaryFlows/browse/archived-filter.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/archived-filter.txt b/testdata/TestRealBinaryFlows/browse/archived-filter.txt index aa01995..f758e5a 100644 --- a/testdata/TestRealBinaryFlows/browse/archived-filter.txt +++ b/testdata/TestRealBinaryFlows/browse/archived-filter.txt @@ -6,15 +6,15 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃> ○ Set up redirects for the old URLs ┃ +│ │┃> ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ -│ │┃ ○ Compare hosting quotes ┃ +│ │┃ ▸ ○ Compare hosting quotes ┃ │ │┃ 5┃ │ │┃ ┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter 0 reset … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/blocked-filter.txt b/testdata/TestRealBinaryFlows/browse/blocked-filter.txt index 64c3541..a731b1f 100644 --- a/testdata/TestRealBinaryFlows/browse/blocked-filter.txt +++ b/testdata/TestRealBinaryFlows/browse/blocked-filter.txt @@ -1,10 +1,10 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Move the blog to plain files [BLOCKED] ┃ -│> Move the blog to plain files ○3 ✓1 │┃> ○ Set up redirects for the old URLs ┃ +│> Move the blog to plain files ○3 ✓1 │┃> ▸ ○ Set up redirects for the old URLs ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 3┃ │ Plan the Lisbon trip ○31 ✓0 │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter 0 reset … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.style b/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.style index 9b784d6..d89e4df 100644 --- a/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.style +++ b/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.style @@ -41,7 +41,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.txt b/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.txt index 8c67a69..4e2f625 100644 --- a/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.txt +++ b/testdata/TestRealBinaryFlows/browse/cursor-on-last-item.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃> ○ Point DNS at the new host ┃ +│ │┃> ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/cursor-on-task.style b/testdata/TestRealBinaryFlows/browse/cursor-on-task.style index 3c9b79a..b0461b9 100644 --- a/testdata/TestRealBinaryFlows/browse/cursor-on-task.style +++ b/testdata/TestRealBinaryFlows/browse/cursor-on-task.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/cursor-on-task.txt b/testdata/TestRealBinaryFlows/browse/cursor-on-task.txt index bb436f0..9b4de0a 100644 --- a/testdata/TestRealBinaryFlows/browse/cursor-on-task.txt +++ b/testdata/TestRealBinaryFlows/browse/cursor-on-task.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ > ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [a]dd [space]done [D]elete [Tab]view [/]filter [?]help LOCAL projects.db + a add space done D delete tab view / filter j/k move [/] jump … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/first-screen.style b/testdata/TestRealBinaryFlows/browse/first-screen.style index a174474..9aa3b0f 100644 --- a/testdata/TestRealBinaryFlows/browse/first-screen.style +++ b/testdata/TestRealBinaryFlows/browse/first-screen.style @@ -41,7 +41,9 @@ 8: 100-100 fg=8 9: 1-40 fg=4 9: 41-41 fg=8 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/first-screen.txt b/testdata/TestRealBinaryFlows/browse/first-screen.txt index 353d508..51243aa 100644 --- a/testdata/TestRealBinaryFlows/browse/first-screen.txt +++ b/testdata/TestRealBinaryFlows/browse/first-screen.txt @@ -6,12 +6,12 @@ ┃ Plan the Lisbon trip ○31 ✓0 ┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]read [space]mark [a]dd [e]dit [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + enter read space mark a add e edit M move tab view / filter … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/items-focused.style b/testdata/TestRealBinaryFlows/browse/items-focused.style index 097e7f9..e99a40d 100644 --- a/testdata/TestRealBinaryFlows/browse/items-focused.style +++ b/testdata/TestRealBinaryFlows/browse/items-focused.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/items-focused.txt b/testdata/TestRealBinaryFlows/browse/items-focused.txt index 4084d16..a8dbe3b 100644 --- a/testdata/TestRealBinaryFlows/browse/items-focused.txt +++ b/testdata/TestRealBinaryFlows/browse/items-focused.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove [Tab]view … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/last-project.txt b/testdata/TestRealBinaryFlows/browse/last-project.txt index 9958dde..00753ff 100644 --- a/testdata/TestRealBinaryFlows/browse/last-project.txt +++ b/testdata/TestRealBinaryFlows/browse/last-project.txt @@ -1,30 +1,30 @@ By project All items Dependencies ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓╭──────────────────────────────────────────────────────────╮ ┃ Projects ┃│ Plan the Lisbon trip │ -┃ Move the blog to plain files ○3 ✓1 ┃│> ○ Ask Sam for a plumber and a place to stay ◈ │ +┃ Move the blog to plain files ○3 ✓1 ┃│> ▸ ○ Ask Sam for a plumber and a place to stay ◈ │ ┃ Replace the kitchen faucet ○3 ✓0 ┃│ also in Replace the kitchen faucet 8│ -┃> Plan the Lisbon trip ○31 ✓0 ┃│ ○ Write up the trip on the new blog │ +┃> Plan the Lisbon trip ○31 ✓0 ┃│ ▸ ○ Write up the trip on the new blog │ ┃ ┃│ 9│ ┃ ┃│ └─ blocked by: Move the blog…: Point DNS at th… (4)│ -┃ ┃│ ○ Read every neighborhood guide and write down which…│ +┃ ┃│ ▸ ○ Read every neighborhood guide and write down which…│ ┃ ┃│ 10│ -┃ ┃│ ○ Day 1: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 1: walk the next neighborhood │ ┃ ┃│ 11│ -┃ ┃│ ○ Day 2: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 2: walk the next neighborhood │ ┃ ┃│ 12│ -┃ ┃│ ○ Day 3: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 3: walk the next neighborhood │ ┃ ┃│ 13│ -┃ ┃│ ○ Day 4: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 4: walk the next neighborhood │ ┃ ┃│ 14│ -┃ ┃│ ○ Day 5: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 5: walk the next neighborhood │ ┃ ┃│ 15│ -┃ ┃│ ○ Day 6: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 6: walk the next neighborhood │ ┃ ┃│ 16│ -┃ ┃│ ○ Day 7: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 7: walk the next neighborhood │ ┃ ┃│ 17│ -┃ ┃│ ○ Day 8: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 8: walk the next neighborhood │ ┃ ┃│ 18│ -┃ ┃│ ○ Day 9: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 9: walk the next neighborhood │ ┃ ┃│ 1/31 │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]read [space]mark [a]dd [e]dit [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + enter read space mark a add e edit M move tab view / filter … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/long-list-bottom.txt b/testdata/TestRealBinaryFlows/browse/long-list-bottom.txt index 5b37d55..5009c52 100644 --- a/testdata/TestRealBinaryFlows/browse/long-list-bottom.txt +++ b/testdata/TestRealBinaryFlows/browse/long-list-bottom.txt @@ -1,30 +1,30 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Plan the Lisbon trip ┃ -│ Move the blog to plain files ○3 ✓1 │┃ ○ Day 17: walk the next neighborhood ┃ +│ Move the blog to plain files ○3 ✓1 │┃ ▸ ○ Day 17: walk the next neighborhood ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 27┃ -│> Plan the Lisbon trip ○31 ✓0 │┃ ○ Day 18: walk the next neighborhood ┃ +│> Plan the Lisbon trip ○31 ✓0 │┃ ▸ ○ Day 18: walk the next neighborhood ┃ │ │┃ 28┃ -│ │┃ ○ Day 19: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 19: walk the next neighborhood ┃ │ │┃ 29┃ -│ │┃ ○ Day 20: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 20: walk the next neighborhood ┃ │ │┃ 30┃ -│ │┃ ○ Day 21: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 21: walk the next neighborhood ┃ │ │┃ 31┃ -│ │┃ ○ Day 22: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 22: walk the next neighborhood ┃ │ │┃ 32┃ -│ │┃ ○ Day 23: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 23: walk the next neighborhood ┃ │ │┃ 33┃ -│ │┃ ○ Day 24: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 24: walk the next neighborhood ┃ │ │┃ 34┃ -│ │┃ ○ Day 25: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 25: walk the next neighborhood ┃ │ │┃ 35┃ -│ │┃ ○ Day 26: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 26: walk the next neighborhood ┃ │ │┃ 36┃ -│ │┃ ○ Day 27: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 27: walk the next neighborhood ┃ │ │┃ 37┃ -│ │┃> ○ Day 28: walk the next neighborhood ┃ +│ │┃> ▸ ○ Day 28: walk the next neighborhood ┃ │ │┃ 38┃ │ │┃ 31/31 ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/long-list-half-page.txt b/testdata/TestRealBinaryFlows/browse/long-list-half-page.txt index 421d227..c48f15f 100644 --- a/testdata/TestRealBinaryFlows/browse/long-list-half-page.txt +++ b/testdata/TestRealBinaryFlows/browse/long-list-half-page.txt @@ -1,30 +1,30 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Plan the Lisbon trip ┃ -│ Move the blog to plain files ○3 ✓1 │┃ ○ Write up the trip on the new blog ┃ +│ Move the blog to plain files ○3 ✓1 │┃ ▸ ○ Write up the trip on the new blog ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ └─ blocked by: Move the blog…: Point DNS at th… (4)┃ -│> Plan the Lisbon trip ○31 ✓0 │┃ ○ Read every neighborhood guide and write down which…┃ +│> Plan the Lisbon trip ○31 ✓0 │┃ ▸ ○ Read every neighborhood guide and write down which…┃ │ │┃ 10┃ -│ │┃ ○ Day 1: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 1: walk the next neighborhood ┃ │ │┃ 11┃ -│ │┃ ○ Day 2: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 2: walk the next neighborhood ┃ │ │┃ 12┃ -│ │┃ ○ Day 3: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 3: walk the next neighborhood ┃ │ │┃ 13┃ -│ │┃ ○ Day 4: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 4: walk the next neighborhood ┃ │ │┃ 14┃ -│ │┃ ○ Day 5: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 5: walk the next neighborhood ┃ │ │┃ 15┃ -│ │┃ ○ Day 6: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 6: walk the next neighborhood ┃ │ │┃ 16┃ -│ │┃ ○ Day 7: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 7: walk the next neighborhood ┃ │ │┃ 17┃ -│ │┃ ○ Day 8: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 8: walk the next neighborhood ┃ │ │┃ 18┃ -│ │┃ ○ Day 9: walk the next neighborhood ┃ +│ │┃ ▸ ○ Day 9: walk the next neighborhood ┃ │ │┃ 19┃ -│ │┃> ○ Day 10: walk the next neighborhood ┃ +│ │┃> ▸ ○ Day 10: walk the next neighborhood ┃ │ │┃ 20┃ │ │┃ 13/31 ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/browse/two-projects-selected.style b/testdata/TestRealBinaryFlows/browse/two-projects-selected.style index de2ed17..8a6db89 100644 --- a/testdata/TestRealBinaryFlows/browse/two-projects-selected.style +++ b/testdata/TestRealBinaryFlows/browse/two-projects-selected.style @@ -47,7 +47,9 @@ 9: 100-100 fg=8 10: 1-40 fg=4 10: 41-41 fg=8 -10: 42-46 strike +10: 42-44 strike +10: 45-45 fg=8 strike +10: 46-46 strike 10: 47-47 fg=8 strike 10: 48-48 strike 10: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/browse/two-projects-selected.txt b/testdata/TestRealBinaryFlows/browse/two-projects-selected.txt index e4d8a73..f06cc20 100644 --- a/testdata/TestRealBinaryFlows/browse/two-projects-selected.txt +++ b/testdata/TestRealBinaryFlows/browse/two-projects-selected.txt @@ -7,24 +7,24 @@ ┃ ┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ ┃ ┃│ ▾ ── Replace the kitchen faucet ── ○3 ✓0 │ ┃ ┃│ ▸ ○ Buy the faucet ≡ │ ┃ ┃│ 6│ -┃ ┃│ ○ Shut off the water and swap it │ +┃ ┃│ ▸ ○ Shut off the water and swap it │ ┃ ┃│ 7│ ┃ ┃│ └─ blocked by: Buy the faucet (6) │ -┃ ┃│ ○ Ask Sam for a plumber and a place to stay ◈ │ +┃ ┃│ ▸ ○ Ask Sam for a plumber and a place to stay ◈ │ ┃ ┃│ also in Plan the Lisbon trip 8│ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]read [space]mark [a]dd [e]dit [M]ove [Esc]back [Tab]view … [?]help LOCAL projects.db + enter read space mark a add e edit M move esc back tab view … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/back-in-the-tree.txt b/testdata/TestRealBinaryFlows/dependency-tree/back-in-the-tree.txt index cb236af..a73ab6b 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/back-in-the-tree.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/back-in-the-tree.txt @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰────────────────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [l]drill [h]back [Enter]read [i]flip [.]finished [Esc]back … [?]help LOCAL projects.db + l drill h back enter read i flip . finished esc back tab view … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/flipped.txt b/testdata/TestRealBinaryFlows/dependency-tree/flipped.txt index 2e37ace..7ec039c 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/flipped.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/flipped.txt @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰────────────────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [l]drill [h]back [Enter]read [i]flip [.]finished [Esc]back … [?]help LOCAL projects.db + l drill h back enter read i flip . finished esc back tab view … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/focus-pane.txt b/testdata/TestRealBinaryFlows/dependency-tree/focus-pane.txt index cb236af..a73ab6b 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/focus-pane.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/focus-pane.txt @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰────────────────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [l]drill [h]back [Enter]read [i]flip [.]finished [Esc]back … [?]help LOCAL projects.db + l drill h back enter read i flip . finished esc back tab view … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/forest.txt b/testdata/TestRealBinaryFlows/dependency-tree/forest.txt index 4d987eb..874c596 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/forest.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/forest.txt @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰────────────────────────────────────────────────╯ - [l]drill [Enter]read [.]finished [Tab]view [/]filter [?]help LOCAL projects.db + l drill enter read . finished tab view / filter j/k move q quit ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.style b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.style index 2618826..5de1ba7 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.style +++ b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.style @@ -17,7 +17,7 @@ 17: 91-91 fg=4 18: 10-91 fg=4 19: 10-10 fg=4 -19: 15-36 fg=8 +19: 15-35 fg=8 19: 91-91 fg=4 20: 10-91 fg=4 21: 10-91 fg=4 diff --git a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.txt b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.txt index 6ce7ecd..a8bb3c4 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay-filtered.txt @@ -16,6 +16,6 @@ │ ── Replace the kitchen faucet ── │ │ > ○ Buy the faucet 6 │ │ │ - │ [Enter]keep [Esc]clear │ + │ enter keep esc clear │ │ │ ╰────────────────────────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.style b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.style index 9904ede..9e709fb 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.style +++ b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.style @@ -74,7 +74,7 @@ 26: 91-91 fg=4 27: 10-91 fg=4 28: 10-10 fg=4 -28: 15-47 fg=8 +28: 15-46 fg=8 28: 91-91 fg=4 29: 10-91 fg=4 30: 10-91 fg=4 diff --git a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.txt b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.txt index 314bc9d..276467d 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/link-overlay.txt @@ -25,6 +25,6 @@ │ ○ Day 8: walk the next neighborhood 18 │ │ ○ Day 9: walk the next neighborhood 19 │ │ │ - │ [Enter]link [/]filter [Esc]cancel │ + │ enter link / filter esc cancel │ │ │ ╰────────────────────────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/dependency-tree/linked.style b/testdata/TestRealBinaryFlows/dependency-tree/linked.style index 01e6234..ec1b513 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/linked.style +++ b/testdata/TestRealBinaryFlows/dependency-tree/linked.style @@ -47,7 +47,9 @@ 9: 100-100 fg=4 10: 1-40 fg=8 10: 41-41 fg=4 -10: 42-46 strike +10: 42-44 strike +10: 45-45 fg=8 strike +10: 46-46 strike 10: 47-47 fg=8 strike 10: 48-48 strike 10: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/dependency-tree/linked.txt b/testdata/TestRealBinaryFlows/dependency-tree/linked.txt index 6d1dfff..365fe02 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/linked.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/linked.txt @@ -7,12 +7,12 @@ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ │ │┃ └─ blocked by: Replace the k…: Buy the faucet (6) ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Dependency linked [?]help LOCAL projects.db + Dependency linked ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.style b/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.style index 80735ad..0856a59 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.style +++ b/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.style @@ -10,7 +10,7 @@ 15: 91-91 fg=4 16: 10-91 fg=4 17: 10-10 fg=4 -17: 15-39 fg=8 +17: 15-38 fg=8 17: 91-91 fg=4 18: 10-91 fg=4 19: 10-91 fg=4 diff --git a/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.txt b/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.txt index 129b2f0..abaed89 100644 --- a/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.txt +++ b/testdata/TestRealBinaryFlows/dependency-tree/unlink-overlay.txt @@ -14,6 +14,6 @@ │ │ │ > ○ Buy the faucet 6 │ │ │ - │ [Enter]unlink [Esc]cancel │ + │ enter unlink esc cancel │ │ │ ╰────────────────────────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/note-in-place/note-closed.style b/testdata/TestRealBinaryFlows/detail-in-place/detail-closed.style similarity index 96% rename from testdata/TestRealBinaryFlows/note-in-place/note-closed.style rename to testdata/TestRealBinaryFlows/detail-in-place/detail-closed.style index 097e7f9..e99a40d 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/note-closed.style +++ b/testdata/TestRealBinaryFlows/detail-in-place/detail-closed.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/note-in-place/note-closed.txt b/testdata/TestRealBinaryFlows/detail-in-place/detail-closed.txt similarity index 87% rename from testdata/TestRealBinaryFlows/note-in-place/note-closed.txt rename to testdata/TestRealBinaryFlows/detail-in-place/detail-closed.txt index 4084d16..a8dbe3b 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/note-closed.txt +++ b/testdata/TestRealBinaryFlows/detail-in-place/detail-closed.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove [Tab]view … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.style b/testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.style similarity index 96% rename from testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.style rename to testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.style index 097e7f9..e99a40d 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.style +++ b/testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.txt b/testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.txt similarity index 87% rename from testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.txt rename to testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.txt index 4084d16..a8dbe3b 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/chevron-only-where-it-opens.txt +++ b/testdata/TestRealBinaryFlows/detail-in-place/every-item-opens.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove [Tab]view … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/note-in-place/note-open.style b/testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.style similarity index 79% rename from testdata/TestRealBinaryFlows/note-in-place/note-open.style rename to testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.style index 8aa3f12..69be5af 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/note-open.style +++ b/testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.style @@ -21,83 +21,75 @@ 5: 1-1 fg=8 5: 32-33 fg=3 5: 35-40 fg=8 -5: 41-41 fg=4 -5: 99-99 fg=8 -5: 100-100 fg=4 +5: 41-100 fg=4 6: 1-1 fg=8 6: 26-28 fg=3 6: 30-40 fg=8 6: 41-41 fg=4 -6: 49-54 fg=12 bold reverse -6: 55-55 fg=12 reverse -6: 56-59 fg=12 bold reverse +6: 49-53 fg=12 bold 6: 100-100 fg=4 7: 1-40 fg=8 7: 41-100 fg=4 8: 1-40 fg=8 8: 41-41 fg=4 -8: 77-90 bold +8: 49-54 fg=12 bold reverse +8: 55-55 fg=12 reverse +8: 56-59 fg=12 bold reverse 8: 100-100 fg=4 9: 1-40 fg=8 -9: 41-41 fg=4 -9: 100-100 fg=4 +9: 41-100 fg=4 10: 1-40 fg=8 10: 41-41 fg=4 +10: 77-90 bold 10: 100-100 fg=4 11: 1-40 fg=8 11: 41-41 fg=4 11: 100-100 fg=4 12: 1-40 fg=8 12: 41-41 fg=4 -12: 94-96 italic 12: 100-100 fg=4 13: 1-40 fg=8 13: 41-41 fg=4 13: 100-100 fg=4 14: 1-40 fg=8 14: 41-41 fg=4 +14: 94-96 italic 14: 100-100 fg=4 15: 1-40 fg=8 -15: 41-100 fg=4 +15: 41-41 fg=4 +15: 100-100 fg=4 16: 1-40 fg=8 16: 41-41 fg=4 -16: 49-49 fg=12 -16: 51-55 fg=12 bold 16: 100-100 fg=4 17: 1-40 fg=8 17: 41-100 fg=4 18: 1-40 fg=8 18: 41-41 fg=4 -18: 49-50 fg=12 +18: 49-55 fg=12 bold 18: 100-100 fg=4 19: 1-40 fg=8 -19: 41-41 fg=4 -19: 100-100 fg=4 +19: 41-100 fg=4 20: 1-40 fg=8 20: 41-41 fg=4 -20: 49-50 fg=12 20: 100-100 fg=4 21: 1-40 fg=8 21: 41-41 fg=4 21: 100-100 fg=4 22: 1-40 fg=8 22: 41-41 fg=4 -22: 49-50 fg=12 22: 100-100 fg=4 23: 1-40 fg=8 23: 41-41 fg=4 -23: 52-79 fg=11 23: 100-100 fg=4 24: 1-40 fg=8 24: 41-41 fg=4 -24: 49-50 fg=12 24: 100-100 fg=4 25: 1-40 fg=8 25: 41-41 fg=4 +25: 52-79 fg=11 25: 100-100 fg=4 26: 1-40 fg=8 26: 41-41 fg=4 -26: 49-50 fg=12 26: 100-100 fg=4 27: 1-40 fg=8 27: 41-41 fg=4 diff --git a/testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.txt b/testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.txt similarity index 61% rename from testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.txt rename to testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.txt index 76a0d31..c3e17f8 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.txt +++ b/testdata/TestRealBinaryFlows/detail-in-place/item-stays-on-top.txt @@ -3,7 +3,21 @@ │ Projects │┃ Move the blog to plain files ┃ │> Move the blog to plain files ○3 ✓1 │┃> ▾ ○ Export posts from the old CMS ≡ [1/3] ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ ┃ -│ Plan the Lisbon trip ○31 ✓0 │┃ 1. Dump the database from the read replica, never ┃ +│ Plan the Lisbon trip ○31 ✓0 │┃ Notes ┃ +│ │┃ ┃ +│ │┃ Export plan ┃ +│ │┃ ┃ +│ │┃ The old CMS stores posts as HTML fragments in a ┃ +│ │┃ single table, with images referenced by absolute ┃ +│ │┃ URLs. The export has to keep every published URL ┃ +│ │┃ working, because search engines and a few old ┃ +│ │┃ forum threads still link to them. Drafts are not ┃ +│ │┃ exported. They stay in the database dump in case ┃ +│ │┃ one is worth finishing. ┃ +│ │┃ ┃ +│ │┃ ▌ Steps ┃ +│ │┃ ┃ +│ │┃ 1. Dump the database from the read replica, never ┃ │ │┃ the primary. ┃ │ │┃ 2. Convert each fragment to markdown with the ┃ │ │┃ script below. ┃ @@ -11,20 +25,6 @@ │ │┃ static/images///. ┃ │ │┃ 4. Rewrite the image links to the new relative ┃ │ │┃ paths. ┃ -│ │┃ 5. Diff a sample of twenty rendered posts against ┃ -│ │┃ the live site. ┃ -│ │┃ ┃ -│ │┃ ▌ Conversion script ┃ -│ │┃ ┃ -│ │┃ ╭─ bash ┃ -│ │┃ │ mysqldump --single-transaction blog posts > ┃ -│ │┃ │ ↪ posts.sql ┃ -│ │┃ │ python3 convert.py --input posts.sql --output ┃ -│ │┃ │ ↪ content/posts ┃ -│ │┃ │ rg --count ' Move the blog to plain files ○3 ✓1 │┃> ▾ ○ Export posts from the old CMS ≡ [1/3] ┃ -│ Replace the kitchen faucet ○3 ✓0 │┃ 1┃ -│ Plan the Lisbon trip ○31 ✓0 │┃ Export plan ┃ -│ │┃ ┃ +│ Replace the kitchen faucet ○3 ✓0 │┃ Export plan ┃ +│ Plan the Lisbon trip ○31 ✓0 │┃ ┃ │ │┃ The old CMS stores posts as HTML fragments in a ┃ │ │┃ single table, with images referenced by absolute ┃ │ │┃ URLs. The export has to keep every published URL ┃ @@ -25,6 +24,7 @@ │ │┃ paths. ┃ │ │┃ 5. Diff a sample of twenty rendered posts against ┃ │ │┃ the live site. ┃ +│ │┃ ┃ │ │┃ 1/7 ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [J/K]scroll [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.style b/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.style new file mode 100644 index 0000000..e3eb5ed --- /dev/null +++ b/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.style @@ -0,0 +1,110 @@ +1: 2-11 fg=4 bold +1: 15-38 fg=8 +2: 1-40 fg=8 +2: 41-100 fg=4 +3: 1-1 fg=8 +3: 3-10 bold +3: 40-40 fg=8 +3: 41-41 fg=4 +3: 43-70 bold +3: 100-100 fg=4 +4: 1-1 fg=8 +4: 2-31 fg=2 bold +4: 33-34 fg=3 +4: 36-37 fg=2 +4: 40-40 fg=8 +4: 41-41 fg=4 +4: 79-79 fg=6 +4: 81-85 fg=8 +4: 100-100 fg=4 +5: 1-1 fg=8 +5: 32-33 fg=3 +5: 35-40 fg=8 +5: 41-41 fg=4 +5: 99-99 fg=8 +5: 100-100 fg=4 +6: 1-1 fg=8 +6: 26-28 fg=3 +6: 30-40 fg=8 +6: 41-41 fg=4 +6: 51-54 fg=8 strike +6: 55-55 strike +6: 56-58 fg=8 strike +6: 59-59 strike +6: 60-67 fg=8 strike +6: 100-100 fg=4 +7: 1-40 fg=8 +7: 41-41 fg=4 +7: 100-100 fg=4 +8: 1-40 fg=8 +8: 41-41 fg=4 +8: 100-100 fg=4 +9: 1-40 fg=8 +9: 41-41 fg=4 +9: 42-46 fg=2 bold +9: 48-51 fg=8 strike +9: 52-52 strike +9: 53-53 fg=8 strike +9: 54-54 strike +9: 55-59 fg=8 strike +9: 100-100 fg=4 +10: 1-40 fg=8 +10: 41-41 fg=4 +10: 99-99 fg=8 +10: 100-100 fg=4 +11: 1-40 fg=8 +11: 41-41 fg=4 +11: 49-63 fg=8 +11: 100-100 fg=4 +12: 1-40 fg=8 +12: 41-41 fg=4 +12: 49-86 fg=8 +12: 100-100 fg=4 +13: 1-40 fg=8 +13: 41-41 fg=4 +13: 95-95 fg=4 +14: 1-40 fg=8 +14: 41-41 fg=4 +14: 100-100 fg=4 +15: 1-40 fg=8 +15: 41-41 fg=4 +15: 99-99 fg=8 +15: 100-100 fg=4 +16: 1-40 fg=8 +16: 41-41 fg=4 +16: 49-96 fg=1 +16: 100-100 fg=4 +17: 1-40 fg=8 +17: 41-41 fg=4 +17: 100-100 fg=4 +18: 1-40 fg=8 +18: 41-41 fg=4 +18: 99-99 fg=8 +18: 100-100 fg=4 +19: 1-40 fg=8 +19: 41-41 fg=4 +19: 49-99 fg=1 +19: 100-100 fg=4 +20: 1-40 fg=8 +20: 41-100 fg=4 +21: 1-40 fg=8 +21: 41-100 fg=4 +22: 1-40 fg=8 +22: 41-100 fg=4 +23: 1-40 fg=8 +23: 41-100 fg=4 +24: 1-40 fg=8 +24: 41-100 fg=4 +25: 1-40 fg=8 +25: 41-100 fg=4 +26: 1-40 fg=8 +26: 41-100 fg=4 +27: 1-40 fg=8 +27: 41-100 fg=4 +28: 1-40 fg=8 +28: 41-100 fg=4 +29: 1-40 fg=8 +29: 41-100 fg=4 +30: 3-79 fg=8 +30: 82-86 fg=2 bold +30: 88-98 fg=8 diff --git a/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.txt b/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.txt new file mode 100644 index 0000000..0677584 --- /dev/null +++ b/testdata/TestRealBinaryFlows/detail-in-place/short-detail-in-place.txt @@ -0,0 +1,30 @@ + By project All items Dependencies +╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +│ Projects │┃ Move the blog to plain files ┃ +│> Move the blog to plain files ○3 ✓1 │┃ ▸ ○ Export posts from the old CMS ≡ [1/3] ┃ +│ Replace the kitchen faucet ○3 ✓0 │┃ 1┃ +│ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ +│ │┃ ○ Convert HTML to markdown ┃ +│ │┃ ○ Download the images ┃ +│ │┃> ▾ ✓ Pick a theme ┃ +│ │┃ 2┃ +│ │┃ Item 2 · ✓ done ┃ +│ │┃ Projects: Move the blog to plain files ┃ +│ │┃ Created: ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ +│ │┃ 3┃ +│ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ +│ │┃ 4┃ +│ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +│ │┃ ┃ +╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.style b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.style new file mode 100644 index 0000000..789edb4 --- /dev/null +++ b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.style @@ -0,0 +1,14 @@ +1: 2-30 bold +2: 2-16 fg=8 +3: 2-39 fg=8 +6: 2-7 fg=12 bold +9: 2-10 fg=12 bold +10: 2-20 fg=8 +14: 2-6 fg=12 bold +16: 2-7 fg=12 bold reverse +16: 8-8 fg=12 reverse +16: 9-12 fg=12 bold reverse +18: 30-43 bold +20: 47-49 italic +23: 2-8 fg=12 bold +27: 51-78 fg=11 diff --git a/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.txt b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.txt new file mode 100644 index 0000000..ffb53c9 --- /dev/null +++ b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-full-screen.txt @@ -0,0 +1,30 @@ + Export posts from the old CMS + Item 1 · ○ open + Projects: Move the blog to plain files + Created: + + Blocks + ○ Set up redirects for the old URLs (3) + + Tasks 1/3 + ✓ Dump the database + ○ Convert HTML to markdown + ○ Download the images + + Notes + + Export plan + + The old CMS stores posts as HTML fragments in a single table, with images referenced by absolute + URLs. The export has to keep every published URL working, because search engines and a few old + forum threads still link to them. Drafts are not exported. They stay in the database dump in case + one is worth finishing. + + ▌ Steps + + 1. Dump the database from the read replica, never the primary. + 2. Convert each fragment to markdown with the script below. + 3. Download every image the posts reference into static/images///. + 4. Rewrite the image links to the new relative paths. + 5. Diff a sample of twenty rendered posts against the live site. +28/79 j/k scroll [/] section / search y copy ? keys esc/space back q quit diff --git a/testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.style b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.style similarity index 70% rename from testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.style rename to testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.style index efeb7f1..f783806 100644 --- a/testdata/TestRealBinaryFlows/note-in-place/item-stays-on-top.style +++ b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.style @@ -21,89 +21,83 @@ 5: 1-1 fg=8 5: 32-33 fg=3 5: 35-40 fg=8 -5: 41-100 fg=4 +5: 41-41 fg=4 +5: 99-99 fg=8 +5: 100-100 fg=4 6: 1-1 fg=8 6: 26-28 fg=3 6: 30-40 fg=8 6: 41-41 fg=4 -6: 49-50 fg=12 +6: 49-63 fg=8 6: 100-100 fg=4 7: 1-40 fg=8 7: 41-41 fg=4 +7: 49-86 fg=8 7: 100-100 fg=4 8: 1-40 fg=8 8: 41-41 fg=4 -8: 49-50 fg=12 -8: 100-100 fg=4 +8: 95-95 fg=4 9: 1-40 fg=8 -9: 41-41 fg=4 -9: 100-100 fg=4 +9: 41-100 fg=4 10: 1-40 fg=8 10: 41-41 fg=4 -10: 49-50 fg=12 +10: 49-54 fg=12 bold 10: 100-100 fg=4 11: 1-40 fg=8 11: 41-41 fg=4 -11: 52-79 fg=11 11: 100-100 fg=4 12: 1-40 fg=8 -12: 41-41 fg=4 -12: 49-50 fg=12 -12: 100-100 fg=4 +12: 41-100 fg=4 13: 1-40 fg=8 13: 41-41 fg=4 +13: 49-57 fg=12 bold 13: 100-100 fg=4 14: 1-40 fg=8 14: 41-41 fg=4 -14: 49-50 fg=12 +14: 49-67 fg=8 14: 100-100 fg=4 15: 1-40 fg=8 15: 41-41 fg=4 15: 100-100 fg=4 16: 1-40 fg=8 -16: 41-100 fg=4 +16: 41-41 fg=4 +16: 100-100 fg=4 17: 1-40 fg=8 -17: 41-41 fg=4 -17: 49-49 fg=12 -17: 51-67 fg=12 bold -17: 100-100 fg=4 +17: 41-100 fg=4 18: 1-40 fg=8 -18: 41-100 fg=4 +18: 41-41 fg=4 +18: 49-53 fg=12 bold +18: 100-100 fg=4 19: 1-40 fg=8 -19: 41-41 fg=4 -19: 49-55 fg=8 -19: 100-100 fg=4 +19: 41-100 fg=4 20: 1-40 fg=8 20: 41-41 fg=4 -20: 49-49 fg=8 +20: 49-54 fg=12 bold reverse +20: 55-55 fg=12 reverse +20: 56-59 fg=12 bold reverse 20: 100-100 fg=4 21: 1-40 fg=8 -21: 41-41 fg=4 -21: 49-51 fg=8 -21: 100-100 fg=4 +21: 41-100 fg=4 22: 1-40 fg=8 22: 41-41 fg=4 -22: 49-49 fg=8 +22: 77-90 bold 22: 100-100 fg=4 23: 1-40 fg=8 23: 41-41 fg=4 -23: 49-51 fg=8 23: 100-100 fg=4 24: 1-40 fg=8 24: 41-41 fg=4 -24: 49-49 fg=8 -24: 62-67 fg=10 24: 100-100 fg=4 25: 1-40 fg=8 25: 41-41 fg=4 -25: 49-51 fg=8 25: 100-100 fg=4 26: 1-40 fg=8 26: 41-41 fg=4 -26: 49-50 fg=8 +26: 94-96 italic 26: 100-100 fg=4 27: 1-40 fg=8 -27: 41-100 fg=4 +27: 41-41 fg=4 +27: 100-100 fg=4 28: 1-40 fg=8 28: 41-41 fg=4 28: 43-45 fg=8 diff --git a/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.txt b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.txt new file mode 100644 index 0000000..1abf153 --- /dev/null +++ b/testdata/TestRealBinaryFlows/detail-in-place/tall-detail-in-place.txt @@ -0,0 +1,30 @@ + By project All items Dependencies +╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +│ Projects │┃ Move the blog to plain files ┃ +│> Move the blog to plain files ○3 ✓1 │┃> ▾ ○ Export posts from the old CMS ≡ [1/3] ┃ +│ Replace the kitchen faucet ○3 ✓0 │┃ 1┃ +│ Plan the Lisbon trip ○31 ✓0 │┃ Item 1 · ○ open ┃ +│ │┃ Projects: Move the blog to plain files ┃ +│ │┃ Created: ┃ +│ │┃ ┃ +│ │┃ Blocks ┃ +│ │┃ ○ Set up redirects for the old URLs (3) ┃ +│ │┃ ┃ +│ │┃ Tasks 1/3 ┃ +│ │┃ ✓ Dump the database ┃ +│ │┃ ○ Convert HTML to markdown ┃ +│ │┃ ○ Download the images ┃ +│ │┃ ┃ +│ │┃ Notes ┃ +│ │┃ ┃ +│ │┃ Export plan ┃ +│ │┃ ┃ +│ │┃ The old CMS stores posts as HTML fragments in a ┃ +│ │┃ single table, with images referenced by absolute ┃ +│ │┃ URLs. The export has to keep every published URL ┃ +│ │┃ working, because search engines and a few old ┃ +│ │┃ forum threads still link to them. Drafts are not ┃ +│ │┃ exported. They stay in the database dump in case ┃ +│ │┃ 1/7 ┃ +╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/edit-note/note-in-place.style b/testdata/TestRealBinaryFlows/edit-note/note-in-place.style index 3721a49..7a91a3f 100644 --- a/testdata/TestRealBinaryFlows/edit-note/note-in-place.style +++ b/testdata/TestRealBinaryFlows/edit-note/note-in-place.style @@ -56,41 +56,48 @@ 10: 100-100 fg=4 11: 1-40 fg=8 11: 41-41 fg=4 +11: 49-63 fg=8 11: 100-100 fg=4 12: 1-40 fg=8 12: 41-41 fg=4 +12: 49-86 fg=8 12: 100-100 fg=4 13: 1-40 fg=8 13: 41-41 fg=4 -13: 99-99 fg=8 -13: 100-100 fg=4 +13: 95-95 fg=4 14: 1-40 fg=8 -14: 41-41 fg=4 -14: 49-96 fg=1 -14: 100-100 fg=4 +14: 41-100 fg=4 15: 1-40 fg=8 15: 41-41 fg=4 +15: 49-53 fg=12 bold 15: 100-100 fg=4 16: 1-40 fg=8 -16: 41-41 fg=4 -16: 99-99 fg=8 -16: 100-100 fg=4 +16: 41-100 fg=4 17: 1-40 fg=8 17: 41-41 fg=4 -17: 49-99 fg=1 17: 100-100 fg=4 18: 1-40 fg=8 -18: 41-100 fg=4 +18: 41-41 fg=4 +18: 100-100 fg=4 19: 1-40 fg=8 -19: 41-100 fg=4 +19: 41-41 fg=4 +19: 99-99 fg=8 +19: 100-100 fg=4 20: 1-40 fg=8 -20: 41-100 fg=4 +20: 41-41 fg=4 +20: 49-96 fg=1 +20: 100-100 fg=4 21: 1-40 fg=8 -21: 41-100 fg=4 +21: 41-41 fg=4 +21: 100-100 fg=4 22: 1-40 fg=8 -22: 41-100 fg=4 +22: 41-41 fg=4 +22: 99-99 fg=8 +22: 100-100 fg=4 23: 1-40 fg=8 -23: 41-100 fg=4 +23: 41-41 fg=4 +23: 49-99 fg=1 +23: 100-100 fg=4 24: 1-40 fg=8 24: 41-100 fg=4 25: 1-40 fg=8 diff --git a/testdata/TestRealBinaryFlows/edit-note/note-in-place.txt b/testdata/TestRealBinaryFlows/edit-note/note-in-place.txt index 963b7da..770d552 100644 --- a/testdata/TestRealBinaryFlows/edit-note/note-in-place.txt +++ b/testdata/TestRealBinaryFlows/edit-note/note-in-place.txt @@ -8,11 +8,17 @@ │ │┃ ○ Download the images ┃ │ │┃> ▾ ✓ Pick a theme ≡ ┃ │ │┃ 2┃ +│ │┃ Item 2 · ✓ done ┃ +│ │┃ Projects: Move the blog to plain files ┃ +│ │┃ Created: ┃ +│ │┃ ┃ +│ │┃ Notes ┃ +│ │┃ ┃ │ │┃ Written from the editor. ┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -20,11 +26,5 @@ │ │┃ ┃ │ │┃ ┃ │ │┃ ┃ -│ │┃ ┃ -│ │┃ ┃ -│ │┃ ┃ -│ │┃ ┃ -│ │┃ ┃ -│ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item updated [?]help LOCAL projects.db + Item updated ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.style b/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.style deleted file mode 100644 index ce15d8e..0000000 --- a/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.style +++ /dev/null @@ -1,4 +0,0 @@ -1: 2-13 bold -2: 2-16 fg=8 -3: 2-39 fg=8 -6: 2-6 fg=12 bold diff --git a/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.txt b/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.txt deleted file mode 100644 index 7501fe0..0000000 --- a/testdata/TestRealBinaryFlows/edit-note/note-in-the-reader.txt +++ /dev/null @@ -1,30 +0,0 @@ - Pick a theme - Item 2 · ✓ done - Projects: Move the blog to plain files - Created: - - Notes - - Written from the editor. - - - - - - - - - - - - - - - - - - - - - -7/7 j/k scroll [/] section / search y copy ? keys esc/space back q quit diff --git a/testdata/TestRealBinaryFlows/edit-note/note-saved.txt b/testdata/TestRealBinaryFlows/edit-note/note-saved.txt index 48d5282..cd33e9c 100644 --- a/testdata/TestRealBinaryFlows/edit-note/note-saved.txt +++ b/testdata/TestRealBinaryFlows/edit-note/note-saved.txt @@ -8,10 +8,10 @@ │ │┃ ○ Download the images ┃ │ │┃> ▸ ✓ Pick a theme ≡ ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item updated [?]help LOCAL projects.db + Item updated ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/filter/all-items-filtered.txt b/testdata/TestRealBinaryFlows/filter/all-items-filtered.txt index c21772e..ee951eb 100644 --- a/testdata/TestRealBinaryFlows/filter/all-items-filtered.txt +++ b/testdata/TestRealBinaryFlows/filter/all-items-filtered.txt @@ -27,4 +27,4 @@ ┃ ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]keep [Esc]clear [?]help LOCAL projects.db + enter keep esc clear ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/filter/cleared.style b/testdata/TestRealBinaryFlows/filter/cleared.style index 097e7f9..e99a40d 100644 --- a/testdata/TestRealBinaryFlows/filter/cleared.style +++ b/testdata/TestRealBinaryFlows/filter/cleared.style @@ -42,7 +42,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/filter/cleared.txt b/testdata/TestRealBinaryFlows/filter/cleared.txt index 4084d16..a8dbe3b 100644 --- a/testdata/TestRealBinaryFlows/filter/cleared.txt +++ b/testdata/TestRealBinaryFlows/filter/cleared.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [M]ove [Tab]view … [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/filter/note-match-kept.txt b/testdata/TestRealBinaryFlows/filter/note-match-kept.txt index 0317db2..05f5c1d 100644 --- a/testdata/TestRealBinaryFlows/filter/note-match-kept.txt +++ b/testdata/TestRealBinaryFlows/filter/note-match-kept.txt @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [a]dd [n]ote [Esc]back [Tab]view … [?]help LOCAL projects.db + c complete a add n note esc back tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/filter/project-filter.txt b/testdata/TestRealBinaryFlows/filter/project-filter.txt index d1571fe..93cf78e 100644 --- a/testdata/TestRealBinaryFlows/filter/project-filter.txt +++ b/testdata/TestRealBinaryFlows/filter/project-filter.txt @@ -1,30 +1,30 @@ By project All items Dependencies ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓╭──────────────────────────────────────────────────────────╮ ┃ Projects ┃│ Plan the Lisbon trip │ -┃ /lisbon ┃│> ○ Ask Sam for a plumber and a place to stay ◈ │ +┃ /lisbon ┃│> ▸ ○ Ask Sam for a plumber and a place to stay ◈ │ ┃> Plan the Lisbon trip ○31 ✓0 ┃│ also in Replace the kitchen faucet 8│ -┃ ┃│ ○ Write up the trip on the new blog │ +┃ ┃│ ▸ ○ Write up the trip on the new blog │ ┃ ┃│ 9│ ┃ ┃│ └─ blocked by: Move the blog…: Point DNS at th… (4)│ -┃ ┃│ ○ Read every neighborhood guide and write down which…│ +┃ ┃│ ▸ ○ Read every neighborhood guide and write down which…│ ┃ ┃│ 10│ -┃ ┃│ ○ Day 1: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 1: walk the next neighborhood │ ┃ ┃│ 11│ -┃ ┃│ ○ Day 2: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 2: walk the next neighborhood │ ┃ ┃│ 12│ -┃ ┃│ ○ Day 3: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 3: walk the next neighborhood │ ┃ ┃│ 13│ -┃ ┃│ ○ Day 4: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 4: walk the next neighborhood │ ┃ ┃│ 14│ -┃ ┃│ ○ Day 5: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 5: walk the next neighborhood │ ┃ ┃│ 15│ -┃ ┃│ ○ Day 6: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 6: walk the next neighborhood │ ┃ ┃│ 16│ -┃ ┃│ ○ Day 7: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 7: walk the next neighborhood │ ┃ ┃│ 17│ -┃ ┃│ ○ Day 8: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 8: walk the next neighborhood │ ┃ ┃│ 18│ -┃ ┃│ ○ Day 9: walk the next neighborhood │ +┃ ┃│ ▸ ○ Day 9: walk the next neighborhood │ ┃ ┃│ 1/31 │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]keep [Esc]clear [?]help LOCAL projects.db + enter keep esc clear ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/filter/title-match.txt b/testdata/TestRealBinaryFlows/filter/title-match.txt index 26c5123..dbd039e 100644 --- a/testdata/TestRealBinaryFlows/filter/title-match.txt +++ b/testdata/TestRealBinaryFlows/filter/title-match.txt @@ -7,7 +7,7 @@ │ │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]keep [Esc]clear [?]help LOCAL projects.db + enter keep esc clear ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.style b/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.style index 64c701a..436febf 100644 --- a/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.style +++ b/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.style @@ -52,7 +52,7 @@ 26: 86-86 fg=4 27: 15-86 fg=4 28: 15-15 fg=4 -28: 20-37 fg=8 +28: 20-36 fg=8 28: 86-86 fg=4 29: 15-86 fg=4 30: 15-86 fg=4 diff --git a/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.txt b/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.txt index 2244199..ed16a7f 100644 --- a/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.txt +++ b/testdata/TestRealBinaryFlows/help-taller-than-the-window/from-the-project-pane.txt @@ -25,6 +25,6 @@ │ ? show these keys │ │ q Ctrl+c quit │ │ │ - │ [Esc]close [q]quit │ + │ esc close q quit │ │ │ ╰──────────────────────────────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/move/carried-down.style b/testdata/TestRealBinaryFlows/move/carried-down.style index b7842d1..b72476b 100644 --- a/testdata/TestRealBinaryFlows/move/carried-down.style +++ b/testdata/TestRealBinaryFlows/move/carried-down.style @@ -14,7 +14,9 @@ 4: 36-37 fg=2 4: 40-40 fg=8 4: 41-41 fg=4 -4: 42-46 strike +4: 42-44 strike +4: 45-45 fg=8 strike +4: 46-46 strike 4: 47-47 fg=8 strike 4: 48-48 strike 4: 49-52 fg=8 strike @@ -101,6 +103,6 @@ 28: 41-100 fg=4 29: 1-40 fg=8 29: 41-100 fg=4 -30: 3-51 fg=3 bold +30: 3-50 fg=3 bold 30: 82-86 fg=2 bold 30: 88-98 fg=8 diff --git a/testdata/TestRealBinaryFlows/move/carried-down.txt b/testdata/TestRealBinaryFlows/move/carried-down.txt index 44ef564..ff13183 100644 --- a/testdata/TestRealBinaryFlows/move/carried-down.txt +++ b/testdata/TestRealBinaryFlows/move/carried-down.txt @@ -1,17 +1,17 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Move the blog to plain files ┃ -│> Move the blog to plain files ○3 ✓1 │┃ ✓ Pick a theme ┃ +│> Move the blog to plain files ○3 ✓1 │┃ ▸ ✓ Pick a theme ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 2┃ │ Plan the Lisbon trip ○31 ✓0 │┃▶ ▸ ○ Export posts from the old CMS ≡ [1/3] ◀ MOVING ┃ │ │┃ 1┃ │ │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [j/k]move [g/G]top/bottom [Enter]drop [Esc]cancel [?]help LOCAL projects.db + j/k move g/G top/bottom enter drop esc cancel ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/move/dropped.style b/testdata/TestRealBinaryFlows/move/dropped.style index 467e030..84954d1 100644 --- a/testdata/TestRealBinaryFlows/move/dropped.style +++ b/testdata/TestRealBinaryFlows/move/dropped.style @@ -14,7 +14,9 @@ 4: 36-37 fg=2 4: 40-40 fg=8 4: 41-41 fg=4 -4: 42-46 strike +4: 42-44 strike +4: 45-45 fg=8 strike +4: 46-46 strike 4: 47-47 fg=8 strike 4: 48-48 strike 4: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/move/dropped.txt b/testdata/TestRealBinaryFlows/move/dropped.txt index 43266e8..314e759 100644 --- a/testdata/TestRealBinaryFlows/move/dropped.txt +++ b/testdata/TestRealBinaryFlows/move/dropped.txt @@ -1,17 +1,17 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Move the blog to plain files ┃ -│> Move the blog to plain files ○3 ✓1 │┃ ✓ Pick a theme ┃ +│> Move the blog to plain files ○3 ✓1 │┃ ▸ ✓ Pick a theme ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 2┃ │ Plan the Lisbon trip ○31 ✓0 │┃> ▸ ○ Export posts from the old CMS ≡ [1/3] ┃ │ │┃ 1┃ │ │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item reordered [?]help LOCAL projects.db + Item reordered ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/move/grabbed.style b/testdata/TestRealBinaryFlows/move/grabbed.style index bc15c2a..c09ca7c 100644 --- a/testdata/TestRealBinaryFlows/move/grabbed.style +++ b/testdata/TestRealBinaryFlows/move/grabbed.style @@ -40,7 +40,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike @@ -101,6 +103,6 @@ 28: 41-100 fg=4 29: 1-40 fg=8 29: 41-100 fg=4 -30: 3-51 fg=3 bold +30: 3-50 fg=3 bold 30: 82-86 fg=2 bold 30: 88-98 fg=8 diff --git a/testdata/TestRealBinaryFlows/move/grabbed.txt b/testdata/TestRealBinaryFlows/move/grabbed.txt index 4fd2599..b8e57b7 100644 --- a/testdata/TestRealBinaryFlows/move/grabbed.txt +++ b/testdata/TestRealBinaryFlows/move/grabbed.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [j/k]move [g/G]top/bottom [Enter]drop [Esc]cancel [?]help LOCAL projects.db + j/k move g/G top/bottom enter drop esc cancel ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/move/project-carried.style b/testdata/TestRealBinaryFlows/move/project-carried.style index 1b33f9a..3f613ff 100644 --- a/testdata/TestRealBinaryFlows/move/project-carried.style +++ b/testdata/TestRealBinaryFlows/move/project-carried.style @@ -13,7 +13,9 @@ 4: 35-36 fg=8 4: 40-40 fg=4 4: 41-41 fg=8 -4: 42-46 strike +4: 42-44 strike +4: 45-45 fg=8 strike +4: 46-46 strike 4: 47-47 fg=8 strike 4: 48-48 strike 4: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/move/project-carried.txt b/testdata/TestRealBinaryFlows/move/project-carried.txt index 1f26dcd..68cafa3 100644 --- a/testdata/TestRealBinaryFlows/move/project-carried.txt +++ b/testdata/TestRealBinaryFlows/move/project-carried.txt @@ -1,17 +1,17 @@ By project All items Dependencies ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓╭──────────────────────────────────────────────────────────╮ ┃ Projects ┃│ Move the blog to plain files │ -┃ Replace the kitchen faucet ○3 ✓0 ┃│ ✓ Pick a theme │ +┃ Replace the kitchen faucet ○3 ✓0 ┃│ ▸ ✓ Pick a theme │ ┃▶ Move the blog to plain fil… ◀ MOVING┃│ 2│ ┃ Plan the Lisbon trip ○31 ✓0 ┃│> ▸ ○ Export posts from the old CMS ≡ [1/3] │ ┃ ┃│ 1│ ┃ ┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - Item reordered [?]help LOCAL projects.db + Item reordered ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/move/put-back.style b/testdata/TestRealBinaryFlows/move/put-back.style index 467e030..84954d1 100644 --- a/testdata/TestRealBinaryFlows/move/put-back.style +++ b/testdata/TestRealBinaryFlows/move/put-back.style @@ -14,7 +14,9 @@ 4: 36-37 fg=2 4: 40-40 fg=8 4: 41-41 fg=4 -4: 42-46 strike +4: 42-44 strike +4: 45-45 fg=8 strike +4: 46-46 strike 4: 47-47 fg=8 strike 4: 48-48 strike 4: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/move/put-back.txt b/testdata/TestRealBinaryFlows/move/put-back.txt index 43266e8..314e759 100644 --- a/testdata/TestRealBinaryFlows/move/put-back.txt +++ b/testdata/TestRealBinaryFlows/move/put-back.txt @@ -1,17 +1,17 @@ By project All items Dependencies ╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │ Projects │┃ Move the blog to plain files ┃ -│> Move the blog to plain files ○3 ✓1 │┃ ✓ Pick a theme ┃ +│> Move the blog to plain files ○3 ✓1 │┃ ▸ ✓ Pick a theme ┃ │ Replace the kitchen faucet ○3 ✓0 │┃ 2┃ │ Plan the Lisbon trip ○31 ✓0 │┃> ▸ ○ Export posts from the old CMS ≡ [1/3] ┃ │ │┃ 1┃ │ │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Item reordered [?]help LOCAL projects.db + Item reordered ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.style b/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.style index e504290..13f55f1 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.style +++ b/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.style @@ -46,7 +46,9 @@ 9: 50-50 fg=4 10: 1-20 fg=8 10: 21-21 fg=4 -10: 22-26 strike +10: 22-24 strike +10: 25-25 fg=8 strike +10: 26-26 strike 10: 27-27 fg=8 strike 10: 28-28 strike 10: 29-32 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.txt b/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.txt index 0d466ca..7a60ab0 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.txt +++ b/testdata/TestRealBinaryFlows/narrow-window/filter-prompt.txt @@ -7,8 +7,8 @@ │ │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to ma…┃ │ │┃ ○ Download the images┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ │ │┃ 1/7 ┃ ╰──────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]keep … [?]help LOCAL projects.db + enter keep … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/narrow-window/first-screen.style b/testdata/TestRealBinaryFlows/narrow-window/first-screen.style index 852213e..ce723c7 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/first-screen.style +++ b/testdata/TestRealBinaryFlows/narrow-window/first-screen.style @@ -41,7 +41,9 @@ 8: 50-50 fg=8 9: 1-20 fg=4 9: 21-21 fg=8 -9: 22-26 strike +9: 22-24 strike +9: 25-25 fg=8 strike +9: 26-26 strike 9: 27-27 fg=8 strike 9: 28-28 strike 9: 29-32 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/narrow-window/first-screen.txt b/testdata/TestRealBinaryFlows/narrow-window/first-screen.txt index 47311a0..d3b38ae 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/first-screen.txt +++ b/testdata/TestRealBinaryFlows/narrow-window/first-screen.txt @@ -6,9 +6,9 @@ ┃ Plan th… ○31 ✓0┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to ma…│ ┃ ┃│ ○ Download the images│ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for…│ +┃ ┃│ ▸ ○ Set up redirects for…│ ┃ ┃│ 1/7 │ ┗━━━━━━━━━━━━━━━━━━┛╰────────────────────────────╯ - [Enter]read … [?]help LOCAL projects.db + enter read … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/narrow-window/items-focused.style b/testdata/TestRealBinaryFlows/narrow-window/items-focused.style index 348045a..e3a3794 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/items-focused.style +++ b/testdata/TestRealBinaryFlows/narrow-window/items-focused.style @@ -42,7 +42,9 @@ 8: 50-50 fg=4 9: 1-20 fg=8 9: 21-21 fg=4 -9: 22-26 strike +9: 22-24 strike +9: 25-25 fg=8 strike +9: 26-26 strike 9: 27-27 fg=8 strike 9: 28-28 strike 9: 29-32 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/narrow-window/items-focused.txt b/testdata/TestRealBinaryFlows/narrow-window/items-focused.txt index c101f13..0bbc136 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/items-focused.txt +++ b/testdata/TestRealBinaryFlows/narrow-window/items-focused.txt @@ -6,9 +6,9 @@ │ Plan th… ○31 ✓0│┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to ma…┃ │ │┃ ○ Download the images┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for…┃ +│ │┃ ▸ ○ Set up redirects for…┃ │ │┃ 1/7 ┃ ╰──────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read … [?]help LOCAL projects.db + c complete a add … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/narrow-window/task-prompt.style b/testdata/TestRealBinaryFlows/narrow-window/task-prompt.style index 2a24735..381e641 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/task-prompt.style +++ b/testdata/TestRealBinaryFlows/narrow-window/task-prompt.style @@ -13,7 +13,7 @@ 8: 49-49 fg=4 9: 2-49 fg=4 10: 2-2 fg=4 -10: 7-32 fg=8 +10: 7-31 fg=8 10: 49-49 fg=4 11: 2-49 fg=4 12: 2-49 fg=4 diff --git a/testdata/TestRealBinaryFlows/narrow-window/task-prompt.txt b/testdata/TestRealBinaryFlows/narrow-window/task-prompt.txt index 621afd9..22eb82b 100644 --- a/testdata/TestRealBinaryFlows/narrow-window/task-prompt.txt +++ b/testdata/TestRealBinaryFlows/narrow-window/task-prompt.txt @@ -7,6 +7,6 @@ │ │ │ > New task... │ │ │ - │ [Enter]confirm [Esc]cancel │ + │ enter confirm esc cancel │ │ │ ╰──────────────────────────────────────────────╯ diff --git a/testdata/TestRealBinaryFlows/note-in-place/scrolled-by-lines.txt b/testdata/TestRealBinaryFlows/note-in-place/scrolled-by-lines.txt deleted file mode 100644 index 6f87bdb..0000000 --- a/testdata/TestRealBinaryFlows/note-in-place/scrolled-by-lines.txt +++ /dev/null @@ -1,30 +0,0 @@ - By project All items Dependencies -╭──────────────────────────────────────╮┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -│ Projects │┃ Move the blog to plain files ┃ -│> Move the blog to plain files ○3 ✓1 │┃> ▾ ○ Export posts from the old CMS ≡ [1/3] ┃ -│ Replace the kitchen faucet ○3 ✓0 │┃ 2. Convert each fragment to markdown with the ┃ -│ Plan the Lisbon trip ○31 ✓0 │┃ script below. ┃ -│ │┃ 3. Download every image the posts reference into ┃ -│ │┃ static/images///. ┃ -│ │┃ 4. Rewrite the image links to the new relative ┃ -│ │┃ paths. ┃ -│ │┃ 5. Diff a sample of twenty rendered posts against ┃ -│ │┃ the live site. ┃ -│ │┃ ┃ -│ │┃ ▌ Conversion script ┃ -│ │┃ ┃ -│ │┃ ╭─ bash ┃ -│ │┃ │ mysqldump --single-transaction blog posts > ┃ -│ │┃ │ ↪ posts.sql ┃ -│ │┃ │ python3 convert.py --input posts.sql --output ┃ -│ │┃ │ ↪ content/posts ┃ -│ │┃ │ rg --count ' ○ Set up redirects for the old URLs ┃ +│ │┃> ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Undo: undid update on item [?]help LOCAL projects.db + Undo: undid update on item ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/undo/archived.txt b/testdata/TestRealBinaryFlows/undo/archived.txt index 73e47a2..86f41db 100644 --- a/testdata/TestRealBinaryFlows/undo/archived.txt +++ b/testdata/TestRealBinaryFlows/undo/archived.txt @@ -6,10 +6,10 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃> ○ Set up redirects for the old URLs ┃ +│ │┃> ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Archived [?]help LOCAL projects.db + Archived ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/undo/refused-while-blocked.style b/testdata/TestRealBinaryFlows/undo/refused-while-blocked.style index ba5e4a0..0ecbb1a 100644 --- a/testdata/TestRealBinaryFlows/undo/refused-while-blocked.style +++ b/testdata/TestRealBinaryFlows/undo/refused-while-blocked.style @@ -41,7 +41,9 @@ 8: 100-100 fg=4 9: 1-40 fg=8 9: 41-41 fg=4 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/undo/refused-while-blocked.txt b/testdata/TestRealBinaryFlows/undo/refused-while-blocked.txt index abb69e6..495b42d 100644 --- a/testdata/TestRealBinaryFlows/undo/refused-while-blocked.txt +++ b/testdata/TestRealBinaryFlows/undo/refused-while-blocked.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃ ✓ Pick a theme ┃ +│ │┃ ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃> ○ Point DNS at the new host ┃ +│ │┃> ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Cannot complete: item has unresolved blockers [?]help LOCAL projects.db + Cannot complete: item has unresolved blockers ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/undo/toggled.txt b/testdata/TestRealBinaryFlows/undo/toggled.txt index 6491e31..7a0c340 100644 --- a/testdata/TestRealBinaryFlows/undo/toggled.txt +++ b/testdata/TestRealBinaryFlows/undo/toggled.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃> ○ Pick a theme ┃ +│ │┃> ▸ ○ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Marked incomplete [?]help LOCAL projects.db + Marked incomplete ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/undo/undone.txt b/testdata/TestRealBinaryFlows/undo/undone.txt index 2b6f737..ebd9cf1 100644 --- a/testdata/TestRealBinaryFlows/undo/undone.txt +++ b/testdata/TestRealBinaryFlows/undo/undone.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃> ✓ Pick a theme ┃ +│ │┃> ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - Undo: undid update on item [?]help LOCAL projects.db + Undo: undid update on item ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/all-items.style b/testdata/TestRealBinaryFlows/views/all-items.style index 6a3c490..04fbbe9 100644 --- a/testdata/TestRealBinaryFlows/views/all-items.style +++ b/testdata/TestRealBinaryFlows/views/all-items.style @@ -30,7 +30,9 @@ 9: 1-1 fg=4 9: 100-100 fg=4 10: 1-1 fg=4 -10: 2-6 strike +10: 2-4 strike +10: 5-5 fg=8 strike +10: 6-6 strike 10: 7-7 fg=8 strike 10: 8-8 strike 10: 9-12 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/views/all-items.txt b/testdata/TestRealBinaryFlows/views/all-items.txt index bac47a6..211cc07 100644 --- a/testdata/TestRealBinaryFlows/views/all-items.txt +++ b/testdata/TestRealBinaryFlows/views/all-items.txt @@ -7,24 +7,24 @@ ┃ ✓ Dump the database ┃ ┃ ○ Convert HTML to markdown ┃ ┃ ○ Download the images ┃ -┃ ✓ Pick a theme ┃ +┃ ▸ ✓ Pick a theme ┃ ┃ 2┃ -┃ ○ Set up redirects for the old URLs ┃ +┃ ▸ ○ Set up redirects for the old URLs ┃ ┃ 3┃ ┃ └─ blocked by: Export posts from the old CMS (1) ┃ -┃ ○ Point DNS at the new host ┃ +┃ ▸ ○ Point DNS at the new host ┃ ┃ 4┃ ┃ └─ blocked by: Set up redirects for the old URLs (3) ┃ ┃ ┃ ┃ ▾ ── Replace the kitchen faucet ── ○3 ✓0 ┃ ┃ ▸ ○ Buy the faucet ≡ ┃ ┃ 6┃ -┃ ○ Shut off the water and swap it ┃ +┃ ▸ ○ Shut off the water and swap it ┃ ┃ 7┃ ┃ └─ blocked by: Buy the faucet (6) ┃ -┃ ○ Ask Sam for a plumber and a place to stay ◈ ┃ +┃ ▸ ○ Ask Sam for a plumber and a place to stay ◈ ┃ ┃ also in Plan the Lisbon trip 8┃ ┃ ┃ ┃ 2/44 ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [space]note [c]omplete [n]ote [Tab]view [/]filter [?]help LOCAL projects.db + c complete n note tab view / filter j/k move [/] jump … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/back-to-by-project.txt b/testdata/TestRealBinaryFlows/views/back-to-by-project.txt index 6815ead..38c5cf2 100644 --- a/testdata/TestRealBinaryFlows/views/back-to-by-project.txt +++ b/testdata/TestRealBinaryFlows/views/back-to-by-project.txt @@ -6,12 +6,12 @@ │ Plan the Lisbon trip ○31 ✓0 │┃ ✓ Dump the database ┃ │ │┃ ○ Convert HTML to markdown ┃ │ │┃ ○ Download the images ┃ -│ │┃> ✓ Pick a theme ┃ +│ │┃> ▸ ✓ Pick a theme ┃ │ │┃ 2┃ -│ │┃ ○ Set up redirects for the old URLs ┃ +│ │┃ ▸ ○ Set up redirects for the old URLs ┃ │ │┃ 3┃ │ │┃ └─ blocked by: Export posts from the old CMS (1) ┃ -│ │┃ ○ Point DNS at the new host ┃ +│ │┃ ▸ ○ Point DNS at the new host ┃ │ │┃ 4┃ │ │┃ └─ blocked by: Set up redirects for the old UR… (3)┃ │ │┃ ┃ @@ -27,4 +27,4 @@ │ │┃ ┃ │ │┃ ┃ ╰──────────────────────────────────────╯┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [a]dd [n]ote [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + c complete a add n note M move tab view / filter j/k move … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/by-project.style b/testdata/TestRealBinaryFlows/views/by-project.style index a174474..9aa3b0f 100644 --- a/testdata/TestRealBinaryFlows/views/by-project.style +++ b/testdata/TestRealBinaryFlows/views/by-project.style @@ -41,7 +41,9 @@ 8: 100-100 fg=8 9: 1-40 fg=4 9: 41-41 fg=8 -9: 42-46 strike +9: 42-44 strike +9: 45-45 fg=8 strike +9: 46-46 strike 9: 47-47 fg=8 strike 9: 48-48 strike 9: 49-52 fg=8 strike diff --git a/testdata/TestRealBinaryFlows/views/by-project.txt b/testdata/TestRealBinaryFlows/views/by-project.txt index 353d508..51243aa 100644 --- a/testdata/TestRealBinaryFlows/views/by-project.txt +++ b/testdata/TestRealBinaryFlows/views/by-project.txt @@ -6,12 +6,12 @@ ┃ Plan the Lisbon trip ○31 ✓0 ┃│ ✓ Dump the database │ ┃ ┃│ ○ Convert HTML to markdown │ ┃ ┃│ ○ Download the images │ -┃ ┃│ ✓ Pick a theme │ +┃ ┃│ ▸ ✓ Pick a theme │ ┃ ┃│ 2│ -┃ ┃│ ○ Set up redirects for the old URLs │ +┃ ┃│ ▸ ○ Set up redirects for the old URLs │ ┃ ┃│ 3│ ┃ ┃│ └─ blocked by: Export posts from the old CMS (1) │ -┃ ┃│ ○ Point DNS at the new host │ +┃ ┃│ ▸ ○ Point DNS at the new host │ ┃ ┃│ 4│ ┃ ┃│ └─ blocked by: Set up redirects for the old UR… (3)│ ┃ ┃│ │ @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰──────────────────────────────────────────────────────────╯ - [Enter]read [space]mark [a]dd [e]dit [M]ove [Tab]view [/]filter [?]help LOCAL projects.db + enter read space mark a add e edit M move tab view / filter … ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/dependencies.txt b/testdata/TestRealBinaryFlows/views/dependencies.txt index 4d987eb..874c596 100644 --- a/testdata/TestRealBinaryFlows/views/dependencies.txt +++ b/testdata/TestRealBinaryFlows/views/dependencies.txt @@ -27,4 +27,4 @@ ┃ ┃│ │ ┃ ┃│ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛╰────────────────────────────────────────────────╯ - [l]drill [Enter]read [.]finished [Tab]view [/]filter [?]help LOCAL projects.db + l drill enter read . finished tab view / filter j/k move q quit ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/group-folded.txt b/testdata/TestRealBinaryFlows/views/group-folded.txt index e3cc618..0206a60 100644 --- a/testdata/TestRealBinaryFlows/views/group-folded.txt +++ b/testdata/TestRealBinaryFlows/views/group-folded.txt @@ -6,25 +6,25 @@ ┃ ▾ ── Replace the kitchen faucet ── ○3 ✓0 ┃ ┃ ▸ ○ Buy the faucet ≡ ┃ ┃ 6┃ -┃ ○ Shut off the water and swap it ┃ +┃ ▸ ○ Shut off the water and swap it ┃ ┃ 7┃ ┃ └─ blocked by: Buy the faucet (6) ┃ -┃ ○ Ask Sam for a plumber and a place to stay ◈ ┃ +┃ ▸ ○ Ask Sam for a plumber and a place to stay ◈ ┃ ┃ also in Plan the Lisbon trip 8┃ ┃ ┃ ┃ ▾ ── Plan the Lisbon trip ── ○31 ✓0 ┃ -┃ ○ Ask Sam for a plumber and a place to stay ◈ ┃ +┃ ▸ ○ Ask Sam for a plumber and a place to stay ◈ ┃ ┃ also in Replace the kitchen faucet 8┃ -┃ ○ Write up the trip on the new blog ┃ +┃ ▸ ○ Write up the trip on the new blog ┃ ┃ 9┃ ┃ └─ blocked by: Move the blog to plain …: Point DNS at the new host (4) ┃ -┃ ○ Read every neighborhood guide and write down which three are worth the walk, the tram ride…┃ +┃ ▸ ○ Read every neighborhood guide and write down which three are worth the walk, the tram ride…┃ ┃ 10┃ -┃ ○ Day 1: walk the next neighborhood ┃ +┃ ▸ ○ Day 1: walk the next neighborhood ┃ ┃ 11┃ -┃ ○ Day 2: walk the next neighborhood ┃ +┃ ▸ ○ Day 2: walk the next neighborhood ┃ ┃ 12┃ -┃ ○ Day 3: walk the next neighborhood ┃ +┃ ▸ ○ Day 3: walk the next neighborhood ┃ ┃ 1/37 ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]fold [Tab]view [/]filter [?]help LOCAL projects.db + tab view / filter j/k move [/] jump enter open space fold q quit ? keys LOCAL projects.db diff --git a/testdata/TestRealBinaryFlows/views/jumped-past-the-tasks.txt b/testdata/TestRealBinaryFlows/views/jumped-past-the-tasks.txt index 42a82ca..12e1b22 100644 --- a/testdata/TestRealBinaryFlows/views/jumped-past-the-tasks.txt +++ b/testdata/TestRealBinaryFlows/views/jumped-past-the-tasks.txt @@ -7,24 +7,24 @@ ┃ ✓ Dump the database ┃ ┃ ○ Convert HTML to markdown ┃ ┃ ○ Download the images ┃ -┃> ✓ Pick a theme ┃ +┃> ▸ ✓ Pick a theme ┃ ┃ 2┃ -┃ ○ Set up redirects for the old URLs ┃ +┃ ▸ ○ Set up redirects for the old URLs ┃ ┃ 3┃ ┃ └─ blocked by: Export posts from the old CMS (1) ┃ -┃ ○ Point DNS at the new host ┃ +┃ ▸ ○ Point DNS at the new host ┃ ┃ 4┃ ┃ └─ blocked by: Set up redirects for the old URLs (3) ┃ ┃ ┃ ┃ ▾ ── Replace the kitchen faucet ── ○3 ✓0 ┃ ┃ ▸ ○ Buy the faucet ≡ ┃ ┃ 6┃ -┃ ○ Shut off the water and swap it ┃ +┃ ▸ ○ Shut off the water and swap it ┃ ┃ 7┃ ┃ └─ blocked by: Buy the faucet (6) ┃ -┃ ○ Ask Sam for a plumber and a place to stay ◈ ┃ +┃ ▸ ○ Ask Sam for a plumber and a place to stay ◈ ┃ ┃ also in Plan the Lisbon trip 8┃ ┃ ┃ ┃ 6/44 ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - [Enter]read [c]omplete [n]ote [Tab]view [/]filter [?]help LOCAL projects.db + c complete n note tab view / filter j/k move [/] jump … ? keys LOCAL projects.db diff --git a/testdata/flows/add-task.keys b/testdata/flows/add-task.keys index b9312df..c466aad 100644 --- a/testdata/flows/add-task.keys +++ b/testdata/flows/add-task.keys @@ -1,7 +1,7 @@ # Add a task from the list, then toggle one and delete one. wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press t wait New task for "Export posts from the old CMS" diff --git a/testdata/flows/browse.keys b/testdata/flows/browse.keys index a8f74b7..c6d05a2 100644 --- a/testdata/flows/browse.keys +++ b/testdata/flows/browse.keys @@ -4,7 +4,7 @@ wait Export posts from the old CMS frame first-screen press l -wait [Enter]read +wait c complete frame items-focused press j @@ -12,9 +12,9 @@ wait /> +✓ Dump the database/ frame cursor-on-task press ] -wait /> +✓ Pick a theme/ +wait /> [▸▾] ✓ Pick a theme/ press G -wait /> +○ Point DNS at the new host/ +wait /> [▸▾] ○ Point DNS at the new host/ frame cursor-on-last-item press g wait /> +▸ ○ Export posts from the old CMS/ @@ -31,7 +31,7 @@ press 0 gone [ALL] press h -wait [space]mark +wait space mark press space wait Selected (1) press j @@ -46,12 +46,12 @@ press G wait > Plan the Lisbon trip frame last-project press l -wait [Enter]read +wait c complete press ctrl+d -wait /> +○ Day 10: walk the next neighborhood/ +wait /> [▸▾] ○ Day 10: walk the next neighborhood/ frame long-list-half-page press G -wait /> +○ Day 28: walk the next neighborhood/ +wait /> [▸▾] ○ Day 28: walk the next neighborhood/ frame long-list-bottom press ctrl+c diff --git a/testdata/flows/dependency-tree.keys b/testdata/flows/dependency-tree.keys index 7d4314a..661c00d 100644 --- a/testdata/flows/dependency-tree.keys +++ b/testdata/flows/dependency-tree.keys @@ -8,7 +8,7 @@ wait All trees frame forest press l -wait [i]flip +wait i flip frame focus-pane press i wait Tree — unblocks @@ -29,7 +29,7 @@ wait All trees press tab wait /(?m)^.*Projects/ press l -wait [Enter]read +wait c complete press b wait Link dependency for: Export posts from the old CMS (1) frame link-overlay diff --git a/testdata/flows/detail-in-place.keys b/testdata/flows/detail-in-place.keys new file mode 100644 index 0000000..c55eb61 --- /dev/null +++ b/testdata/flows/detail-in-place.keys @@ -0,0 +1,46 @@ +# Enter opens an item's detail in place where it is short, and full screen where it runs past +# the pane. Space opens it in place however tall, and closes it again. Every item has a detail, +# so every item's row carries a chevron. Scrolling through the detail keeps the item's line on top. +mask /Created: [A-Z][a-z]+ \d+, \d{4}/ "Created: " +wait Export posts from the old CMS +press l +wait c complete +frame every-item-opens + +press ] +wait > ▸ ✓ Pick a theme +press enter +wait ▾ ✓ Pick a theme +wait Item 2 · +frame short-detail-in-place +press enter +wait ▸ ✓ Pick a theme +gone Item 2 · + +press [ +wait > ▸ ○ Export posts from the old CMS +press enter +wait esc/space back +frame tall-detail-full-screen +press esc +wait c complete + +press space +wait ▾ ○ Export posts from the old CMS +wait Item 1 · +frame tall-detail-in-place + +press ctrl+d +wait /(?m)^.*┃> ▾ ○ Export posts from the old CMS/ +frame item-stays-on-top +press J J J +wait Diff a sample of twenty +frame scrolled-by-lines + +press space +wait ▸ ○ Export posts from the old CMS +gone Item 1 · +frame detail-closed + +press q +exits diff --git a/testdata/flows/edit-note.keys b/testdata/flows/edit-note.keys index 86ba871..6c3b2fd 100644 --- a/testdata/flows/edit-note.keys +++ b/testdata/flows/edit-note.keys @@ -4,9 +4,9 @@ mask /Created: [A-Z][a-z]+ \d+, \d{4}/ "Created: " wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press ] -wait /> +✓ Pick a theme/ +wait /> [▸▾] ✓ Pick a theme/ press e wait /Pick a theme ≡/ @@ -14,11 +14,7 @@ frame note-saved press space wait Written from the editor. frame note-in-place -press enter -wait Notes -frame note-in-the-reader - -press esc -wait [Enter]read +press space +gone Written from the editor. press q exits diff --git a/testdata/flows/filter.keys b/testdata/flows/filter.keys index e13547c..4002218 100644 --- a/testdata/flows/filter.keys +++ b/testdata/flows/filter.keys @@ -2,7 +2,7 @@ # clears it. "replica" is only in the export item's note. wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press / type redirects @@ -18,7 +18,7 @@ type replica wait Export posts from the old CMS gone Pick a theme press enter -gone [Enter]keep +gone enter keep frame note-match-kept press esc wait Pick a theme @@ -44,7 +44,7 @@ wait Buy the faucet gone ── Move the blog to plain files ── frame all-items-filtered press enter -gone [Enter]keep +gone enter keep press q exits diff --git a/testdata/flows/help.keys b/testdata/flows/help.keys index 3ded7ae..932c5d3 100644 --- a/testdata/flows/help.keys +++ b/testdata/flows/help.keys @@ -3,20 +3,20 @@ wait Export posts from the old CMS press ? -wait [Esc]close [q]quit +wait esc close q quit frame from-the-project-pane press ? -gone [Esc]close [q]quit +gone esc close q quit press l -wait [Enter]read +wait c complete press ? -wait [Esc]close [q]quit +wait esc close q quit press esc -wait [Enter]read +wait c complete press j -wait [D]elete +wait D delete press ? wait On a task press esc @@ -24,7 +24,7 @@ press esc press k wait /> +▸ ○ Export posts from the old CMS/ press M -wait [Enter]drop +wait enter drop press ? wait Moving a row press esc diff --git a/testdata/flows/move.keys b/testdata/flows/move.keys index aa439d1..9b332a5 100644 --- a/testdata/flows/move.keys +++ b/testdata/flows/move.keys @@ -1,11 +1,11 @@ # M grabs a row, j and k carry it, Enter drops it and esc puts it back. wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press M wait ◀ MOVING -wait [Enter]drop +wait enter drop frame grabbed press j wait /✓ Pick a theme[\s\S]*▶ .*Export posts from the old CMS/ diff --git a/testdata/flows/narrow-window.keys b/testdata/flows/narrow-window.keys index a7b359d..7a53a10 100644 --- a/testdata/flows/narrow-window.keys +++ b/testdata/flows/narrow-window.keys @@ -15,10 +15,10 @@ press esc gone New task for press / -wait [Enter]keep +wait enter keep frame filter-prompt press esc -gone [Enter]keep +gone enter keep press enter wait Tasks 1/3 diff --git a/testdata/flows/note-in-place.keys b/testdata/flows/note-in-place.keys deleted file mode 100644 index c6866a8..0000000 --- a/testdata/flows/note-in-place.keys +++ /dev/null @@ -1,29 +0,0 @@ -# Space opens a note in place under its row, however tall, and closes it again. A chevron -# sits only on a row that opens. Scrolling through the note keeps the item's line on top. -wait Export posts from the old CMS -press l -wait [Enter]read -frame chevron-only-where-it-opens - -press space -wait ▾ ○ Export posts from the old CMS -wait Export plan -frame note-open - -press ctrl+d -wait Conversion script -gone Export plan -wait /(?m)^.*┃> ▾ ○ Export posts from the old CMS/ -frame item-stays-on-top -press J J J -wait [J/K]scroll -frame scrolled-by-lines - -press space -gone Conversion script -wait ▸ ○ Export posts from the old CMS -wait Pick a theme -frame note-closed - -press q -exits diff --git a/testdata/flows/reader.keys b/testdata/flows/reader.keys index c9264c1..c6497b3 100644 --- a/testdata/flows/reader.keys +++ b/testdata/flows/reader.keys @@ -5,7 +5,7 @@ mask /Project [0-9a-f]{8}/ "Project " wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press enter wait Item 1 · @@ -20,17 +20,17 @@ press G wait Last line of the note. frame item-bottom press esc -wait [Enter]read +wait c complete frame closed-onto-the-list press h -wait [space]mark +wait space mark press enter wait /Project [0-9a-f]{8} · active/ wait Why move frame project press space -wait [space]mark +wait space mark press q exits diff --git a/testdata/flows/undo.keys b/testdata/flows/undo.keys index 95cb8d8..0f9a2e3 100644 --- a/testdata/flows/undo.keys +++ b/testdata/flows/undo.keys @@ -4,23 +4,23 @@ mask /on item [0-9a-f]{8}/ "on item " wait Export posts from the old CMS press l -wait [Enter]read +wait c complete press G -wait /> +○ Point DNS at the new host/ +wait /> [▸▾] ○ Point DNS at the new host/ press c wait Cannot complete: item has unresolved blockers frame refused-while-blocked press [ [ -wait /> +✓ Pick a theme/ +wait /> [▸▾] ✓ Pick a theme/ press c wait Marked incomplete -wait /> +○ Pick a theme/ +wait /> [▸▾] ○ Pick a theme/ frame toggled press u wait Undo: -wait /> +✓ Pick a theme/ +wait /> [▸▾] ✓ Pick a theme/ frame undone press x diff --git a/testdata/flows/views.keys b/testdata/flows/views.keys index 9fc3d5d..61e705a 100644 --- a/testdata/flows/views.keys +++ b/testdata/flows/views.keys @@ -21,7 +21,7 @@ wait > ▾ ── Move the blog to plain files ── press j wait /> +▸ ○ Export posts from the old CMS/ press ] -wait /> +✓ Pick a theme/ +wait /> [▸▾] ✓ Pick a theme/ frame jumped-past-the-tasks press tab diff --git a/tui/action_table.go b/tui/action_table.go index 6c48da5..ebb4ed4 100644 --- a/tui/action_table.go +++ b/tui/action_table.go @@ -7,42 +7,34 @@ import ( tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" "github.com/charmbracelet/x/ansi" + "github.com/datapointchris/gotermboard" "github.com/datapointchris/projects/model" ) -// action is one row of the key table. The key handler, the footer and the ? overlay all read -// the same rows, so a key bound in one shows in the other two. -type action struct { - keys []string - // section heads the action's group in the ? overlay. - section string - label string - // hint is the footer's word for it, such as "[a]dd", or empty to leave it to the overlay. - hint string - run func(*App) tea.Cmd - applies func(*App) bool -} +// action is one row of the key table, in gotermboard's shape. The key handler, the footer and the +// ? overlay all read the same rows, so a key bound in one shows in the other two. Footer is the +// footer's words for the key, or empty to leave it to the overlay, and Section heads its group +// in the overlay. +type action = gotermboard.KeyAction[*App] const ( - sectionMove = "Moving" - sectionProject = "On a project" - sectionItem = "On an item" - sectionTask = "On a task" - sectionGroup = "On a project's group" - sectionViews = "Views and filters" - sectionMap = "In the dependency map" - sectionMoving = "Moving a row" - sectionEveryone = "Everywhere" - sectionPrompt = "Typing" - sectionPicker = "Choosing projects" - sectionLinking = "Choosing a dependency" - sectionKeys = "This list" + sectionProject = "On a project" + sectionItem = "On an item" + sectionTask = "On a task" + sectionViews = "Views and filters" + sectionMap = "In the dependency map" + sectionMoving = "Moving a row" + sectionPrompt = "Typing" + sectionPicker = "Choosing projects" + sectionLinking = "Choosing a dependency" + sectionKeys = "This list" ) // actions is every key the screen can use now, so a key it cannot use is in none of the -// handler, the footer and the overlay. A screen with a text box binds only keys that type -// nothing, and the box takes the rest. +// handler, the footer and the overlay. On the board, its own rows come ahead of gotermboard's +// universal ones, so a key of its own wins where it applies. A screen with a text box binds only +// keys that type nothing, and the box takes the rest. func (m *App) actions() []action { var table []action switch { @@ -61,35 +53,30 @@ func (m *App) actions() []action { case m.appMode != modeNormal: table = promptActions() case m.view == viewDependencies: - table = slices.Concat(mapActions(), viewActions(), everywhereActions()) + return gotermboard.ActionsNow(m, slices.Concat(mapActions(), viewActions(), everywhereActions()), gotermboard.UniversalActions[*App]()) case m.view == viewProjects && m.activePane == projectPane: - table = slices.Concat(listMoveActions(), projectActions(), viewActions(), everywhereActions()) + return gotermboard.ActionsNow(m, slices.Concat(paneActions(), projectActions(), viewActions(), everywhereActions()), gotermboard.UniversalActions[*App]()) default: - table = slices.Concat(listMoveActions(), itemActions(), taskActions(), groupActions(), viewActions(), everywhereActions()) + return gotermboard.ActionsNow(m, slices.Concat(paneActions(), itemActions(), taskActions(), viewActions(), everywhereActions()), gotermboard.UniversalActions[*App]()) } - return slices.DeleteFunc(table, func(a action) bool { return a.applies != nil && !a.applies(m) }) + return gotermboard.ActionsNow(m, table) } // runKey runs the action bound to key, and reports whether one was. func (m *App) runKey(key string) (tea.Cmd, bool) { - for _, a := range m.actions() { - if slices.Contains(a.keys, key) { - return a.run(m), true - } - } - return nil, false + return gotermboard.RunKey(m, m.actions(), key) } +// footerHints is the footer's words for each key the screen can use now, two spaces apart. The +// status bar pins ? at its right, so the list leaves it out. func (m *App) footerHints() string { - var hints []string - for _, a := range m.actions() { - if a.hint != "" { - hints = append(hints, a.hint) - } - } - return strings.Join(hints, " ") + shown := slices.DeleteFunc(m.actions(), func(a action) bool { return a.Keys[0] == "?" }) + return strings.Join(gotermboard.FooterHints(shown), hintGap) } +// hintGap parts one hint from the next, which a hint's own words never hold. +const hintGap = " " + // keyNames is how the overlay writes a key Bubble Tea names otherwise. var keyNames = map[string]string{ "down": "↓", "up": "↑", "left": "←", "right": "→", @@ -109,25 +96,24 @@ func keysText(keys []string) string { return strings.Join(named, " ") } -// helpLines is the ? overlay: every action the screen can use now, under its section, each -// label wrapped at width under its own column so no word of it reads as a key. +// helpLines is the ? overlay: every action the screen can use now, under its section in the +// order each section first appears, each label wrapped at width under its own column so no word +// of it reads as a key. func (m *App) helpLines(width int) []string { var lines []string - section := "" - for _, a := range m.actions() { - if a.section != section { - if section != "" { - lines = append(lines, "") - } - section = a.section - lines = append(lines, " "+overlayTitleStyle.Render(section)) + for i, section := range gotermboard.BySection(m.actions()) { + if i > 0 { + lines = append(lines, "") } - keys := " " + padRight(keysText(a.keys), 18) - indent := strings.Repeat(" ", lipgloss.Width(keys)) - label := strings.Split(ansi.Wordwrap(a.label, max(width-len(indent), 10), ""), "\n") - lines = append(lines, keys+label[0]) - for _, rest := range label[1:] { - lines = append(lines, indent+rest) + lines = append(lines, " "+overlayTitleStyle.Render(section.Section)) + for _, a := range section.Actions { + keys := " " + padRight(keysText(a.Keys), 18) + indent := strings.Repeat(" ", lipgloss.Width(keys)) + label := strings.Split(ansi.Wordwrap(a.Label, max(width-len(indent), 10), ""), "\n") + lines = append(lines, keys+label[0]) + for _, rest := range label[1:] { + lines = append(lines, indent+rest) + } } } return lines @@ -142,45 +128,19 @@ func padRight(s string, width int) string { // --- The tables --- -func listMoveActions() []action { +// paneActions is moving between the panes of the projects view. gotermboard's universal rows move +// within a pane. +func paneActions() []action { return []action{ - {keys: []string{"j", "down"}, section: sectionMove, label: "move down a row", run: func(m *App) tea.Cmd { return m.cursorDown() }}, - {keys: []string{"k", "up"}, section: sectionMove, label: "move up a row", run: func(m *App) tea.Cmd { return m.cursorUp() }}, - {keys: []string{"g", "home"}, section: sectionMove, label: "go to the top", run: func(m *App) tea.Cmd { return m.cursorTop() }}, - {keys: []string{"G", "end"}, section: sectionMove, label: "go to the bottom", run: func(m *App) tea.Cmd { return m.cursorBottom() }}, - { - keys: []string{"ctrl+d", "pgdown"}, section: sectionMove, label: "half a screen down the open note, or down the list", - run: func(m *App) tea.Cmd { return m.halfScreen(1) }, - }, - { - keys: []string{"ctrl+u", "pgup"}, section: sectionMove, label: "half a screen up the open note, or up the list", - run: func(m *App) tea.Cmd { return m.halfScreen(-1) }, - }, - { - keys: []string{"]"}, section: sectionMove, label: "jump to the next item or group, skipping tasks", - run: func(m *App) tea.Cmd { m.jumpRow(1); return nil }, applies: (*App).onItemList, - }, { - keys: []string{"["}, section: sectionMove, label: "jump to the previous item or group, skipping tasks", - run: func(m *App) tea.Cmd { m.jumpRow(-1); return nil }, applies: (*App).onItemList, + Keys: []string{"h", "left"}, Section: gotermboard.SectionMoving, Label: "go to the projects", + Run: func(m *App) tea.Cmd { m.activePane = projectPane; return nil }, + Applies: func(m *App) bool { return m.view == viewProjects && m.activePane == itemPane }, }, { - keys: []string{"J"}, section: sectionMove, label: "scroll the open note down a line", hint: "[J/K]scroll", - run: func(m *App) tea.Cmd { m.scrollOpenText(1); return nil }, applies: (*App).onOpenText, - }, - { - keys: []string{"K"}, section: sectionMove, label: "scroll the open note up a line", - run: func(m *App) tea.Cmd { m.scrollOpenText(-1); return nil }, applies: (*App).onOpenText, - }, - { - keys: []string{"h", "left"}, section: sectionMove, label: "go to the projects", - run: func(m *App) tea.Cmd { m.activePane = projectPane; return nil }, - applies: func(m *App) bool { return m.view == viewProjects && m.activePane == itemPane }, - }, - { - keys: []string{"l", "right"}, section: sectionMove, label: "go to the items", - run: func(m *App) tea.Cmd { m.activePane = itemPane; return nil }, - applies: func(m *App) bool { return m.view == viewProjects && m.activePane == projectPane }, + Keys: []string{"l", "right"}, Section: gotermboard.SectionMoving, Label: "go to the items", + Run: func(m *App) tea.Cmd { m.activePane = itemPane; return nil }, + Applies: func(m *App) bool { return m.view == viewProjects && m.activePane == projectPane }, }, } } @@ -190,84 +150,71 @@ func projectActions() []action { active := func(m *App) bool { return m.onProject() && m.projects[m.projectCursor].Status == model.StatusActive } closed := func(m *App) bool { return m.onProject() && m.projects[m.projectCursor].Status != model.StatusActive } return []action{ - {keys: []string{"enter"}, section: sectionProject, label: "read the project", hint: "[Enter]read", run: (*App).readProject, applies: onProject}, - {keys: []string{"space"}, section: sectionProject, label: "mark the project, to list several projects' items", hint: "[space]mark", run: (*App).toggleProjectMark, applies: onProject}, - {keys: []string{"a"}, section: sectionProject, label: "add a project", hint: "[a]dd", run: (*App).startAddProject}, - {keys: []string{"A"}, section: sectionProject, label: "add an item to several projects", run: (*App).startAddItemToSeveral, applies: onProject}, - {keys: []string{"r"}, section: sectionProject, label: "rename the project", run: (*App).startRenameProject, applies: onProject}, - {keys: []string{"e", "n"}, section: sectionProject, label: "write the description in $EDITOR", hint: "[e]dit", run: (*App).editProjectDescription, applies: onProject}, - {keys: []string{"c"}, section: sectionProject, label: "complete the project", run: (*App).completeProject, applies: active}, - {keys: []string{"c"}, section: sectionProject, label: "reopen the shelved or closed project", hint: "[c]reopen", run: (*App).reopenProject, applies: closed}, - {keys: []string{"x"}, section: sectionProject, label: "drop the project, saying why", run: (*App).startDropProject, applies: active}, - {keys: []string{"S"}, section: sectionProject, label: "shelve the project for someday", run: (*App).shelveProject, applies: active}, + {Keys: []string{"enter"}, Section: sectionProject, Label: "read the project", Footer: "enter read", Run: (*App).readProject, Applies: onProject}, + {Keys: []string{"space"}, Section: sectionProject, Label: "mark the project, to list several projects' items", Footer: "space mark", Run: (*App).toggleProjectMark, Applies: onProject}, + {Keys: []string{"a"}, Section: sectionProject, Label: "add a project", Footer: "a add", Run: (*App).startAddProject}, + {Keys: []string{"A"}, Section: sectionProject, Label: "add an item to several projects", Run: (*App).startAddItemToSeveral, Applies: onProject}, + {Keys: []string{"r"}, Section: sectionProject, Label: "rename the project", Run: (*App).startRenameProject, Applies: onProject}, + {Keys: []string{"e", "n"}, Section: sectionProject, Label: "write the description in $EDITOR", Footer: "e edit", Run: (*App).editProjectDescription, Applies: onProject}, + {Keys: []string{"c"}, Section: sectionProject, Label: "complete the project", Run: (*App).completeProject, Applies: active}, + {Keys: []string{"c"}, Section: sectionProject, Label: "reopen the shelved or closed project", Footer: "c reopen", Run: (*App).reopenProject, Applies: closed}, + {Keys: []string{"x"}, Section: sectionProject, Label: "drop the project, saying why", Run: (*App).startDropProject, Applies: active}, + {Keys: []string{"S"}, Section: sectionProject, Label: "shelve the project for someday", Run: (*App).shelveProject, Applies: active}, { - keys: []string{"M"}, section: sectionProject, label: "move the project, then j and k, Enter to drop", hint: "[M]ove", - run: (*App).grabProject, applies: func(m *App) bool { return m.onProject() && len(m.projects) > 1 && m.projectQuery == "" }, + Keys: []string{"M"}, Section: sectionProject, Label: "move the project, then j and k, Enter to drop", Footer: "M move", + Run: (*App).grabProject, Applies: func(m *App) bool { return m.onProject() && len(m.projects) > 1 && m.projectQuery == "" }, }, - {keys: []string{"T"}, section: sectionProject, label: "open the dependency map", run: func(m *App) tea.Cmd { return m.switchView(viewDependencies, "") }}, - {keys: []string{"C"}, section: sectionProject, label: "open a Claude session on the project", run: (*App).claudeOnProject, applies: onProject}, + {Keys: []string{"T"}, Section: sectionProject, Label: "open the dependency map", Run: func(m *App) tea.Cmd { return m.switchView(viewDependencies, "") }}, + {Keys: []string{"C"}, Section: sectionProject, Label: "open a Claude session on the project", Run: (*App).claudeOnProject, Applies: onProject}, } } +// itemActions is an item's own keys. gotermboard's enter and space open its detail. func itemActions() []action { onItem := func(m *App) bool { return m.onKind(rowItem) } onItemOrTask := func(m *App) bool { return m.onKind(rowItem) || m.onKind(rowTask) } oneProject := func(m *App) bool { return !m.isGroupedView() && m.projectCursor < len(m.projects) } return []action{ - {keys: []string{"enter"}, section: sectionItem, label: "read the item", hint: "[Enter]read", run: (*App).readItem, applies: onItem}, - { - keys: []string{"space"}, section: sectionItem, label: "open or close the note in place", hint: "[space]note", - run: (*App).toggleNote, applies: func(m *App) bool { return onItem(m) && hasNote(m.currentItem().ProjectItem) }, - }, - {keys: []string{"c"}, section: sectionItem, label: "mark the item done or not done", hint: "[c]omplete", run: (*App).toggleItemDone, applies: onItem}, - {keys: []string{"a"}, section: sectionItem, label: "add an item to this project", hint: "[a]dd", run: (*App).startAddItem, applies: oneProject}, - {keys: []string{"A"}, section: sectionItem, label: "add an item to several projects", run: (*App).startAddItemToSeveral, applies: func(m *App) bool { return len(m.allProjects) > 0 }}, - {keys: []string{"n", "e"}, section: sectionItem, label: "write the note in $EDITOR", hint: "[n]ote", run: (*App).editItemNote, applies: onItem}, - {keys: []string{"r"}, section: sectionItem, label: "rename the item", run: (*App).startRenameItem, applies: onItem}, - {keys: []string{"x"}, section: sectionItem, label: "archive the item", run: (*App).archiveItem, applies: onItem}, - {keys: []string{"P"}, section: sectionItem, label: "choose the projects the item is filed in", run: (*App).manageItemProjects, applies: onItem}, - {keys: []string{"b"}, section: sectionItem, label: "link an item this one waits on", run: (*App).startLinkDependency, applies: onItem}, - {keys: []string{"B"}, section: sectionItem, label: "unlink an item this one waits on", run: (*App).startUnlinkDependency, applies: onItem}, + {Keys: []string{"c"}, Section: sectionItem, Label: "mark the item done or not done", Footer: "c complete", Run: (*App).toggleItemDone, Applies: onItem}, + {Keys: []string{"a"}, Section: sectionItem, Label: "add an item to this project", Footer: "a add", Run: (*App).startAddItem, Applies: oneProject}, + {Keys: []string{"A"}, Section: sectionItem, Label: "add an item to several projects", Run: (*App).startAddItemToSeveral, Applies: func(m *App) bool { return len(m.allProjects) > 0 }}, + {Keys: []string{"n", "e"}, Section: sectionItem, Label: "write the note in $EDITOR", Footer: "n note", Run: (*App).editItemNote, Applies: onItem}, + {Keys: []string{"r"}, Section: sectionItem, Label: "rename the item", Run: (*App).startRenameItem, Applies: onItem}, + {Keys: []string{"x"}, Section: sectionItem, Label: "archive the item", Run: (*App).archiveItem, Applies: onItem}, + {Keys: []string{"P"}, Section: sectionItem, Label: "choose the projects the item is filed in", Run: (*App).manageItemProjects, Applies: onItem}, + {Keys: []string{"b"}, Section: sectionItem, Label: "link an item this one waits on", Run: (*App).startLinkDependency, Applies: onItem}, + {Keys: []string{"B"}, Section: sectionItem, Label: "unlink an item this one waits on", Run: (*App).startUnlinkDependency, Applies: onItem}, { - keys: []string{"M"}, section: sectionItem, label: "move the item, then j and k, Enter to drop", hint: "[M]ove", - run: (*App).grabItem, applies: func(m *App) bool { return onItem(m) && oneProject(m) && len(m.items) > 1 && m.itemQuery == "" }, + Keys: []string{"M"}, Section: sectionItem, Label: "move the item, then j and k, Enter to drop", Footer: "M move", + Run: (*App).grabItem, Applies: func(m *App) bool { return onItem(m) && oneProject(m) && len(m.items) > 1 && m.itemQuery == "" }, }, - {keys: []string{"C"}, section: sectionItem, label: "open a Claude session on the item", run: (*App).claudeOnItem, applies: onItem}, - {keys: []string{"t"}, section: sectionItem, label: "add a task to the item", run: (*App).startAddTask, applies: onItemOrTask}, - {keys: []string{"T"}, section: sectionItem, label: "open the dependency map on the item", run: (*App).mapOnItem, applies: onItemOrTask}, + {Keys: []string{"C"}, Section: sectionItem, Label: "open a Claude session on the item", Run: (*App).claudeOnItem, Applies: onItem}, + {Keys: []string{"t"}, Section: sectionItem, Label: "add a task to the item", Run: (*App).startAddTask, Applies: onItemOrTask}, + {Keys: []string{"T"}, Section: sectionItem, Label: "open the dependency map on the item", Run: (*App).mapOnItem, Applies: onItemOrTask}, } } func taskActions() []action { onTask := func(m *App) bool { return m.onKind(rowTask) } return []action{ - {keys: []string{"space", "c"}, section: sectionTask, label: "mark the task done or not done", hint: "[space]done", run: (*App).toggleTaskDone, applies: onTask}, - {keys: []string{"D"}, section: sectionTask, label: "delete the task", hint: "[D]elete", run: (*App).deleteTask, applies: onTask}, - } -} - -func groupActions() []action { - return []action{ - { - keys: []string{"enter", "space"}, section: sectionGroup, label: "fold or open the project's items", hint: "[Enter]fold", - run: (*App).toggleGroup, applies: func(m *App) bool { return m.onKind(rowGroup) }, - }, + {Keys: []string{"space", "c"}, Section: sectionTask, Label: "mark the task done or not done", Footer: "space done", Run: (*App).toggleTaskDone, Applies: onTask}, + {Keys: []string{"D"}, Section: sectionTask, Label: "delete the task", Footer: "D delete", Run: (*App).deleteTask, Applies: onTask}, } } func viewActions() []action { return []action{ - {keys: []string{"esc"}, section: sectionViews, label: "clear the filter, then the marks, or back out of a drill", hint: "[Esc]back", run: (*App).backOut, applies: (*App).canBackOut}, - {keys: []string{"tab"}, section: sectionViews, label: "the next view", hint: "[Tab]view", run: func(m *App) tea.Cmd { return m.cycleView(1) }}, - {keys: []string{"shift+tab"}, section: sectionViews, label: "the previous view", run: func(m *App) tea.Cmd { return m.cycleView(-1) }}, - {keys: []string{"/"}, section: sectionViews, label: "filter the list, matching notes too", hint: "[/]filter", run: (*App).startFilter}, - {keys: []string{"1"}, section: sectionViews, label: "show only blocked items, or every one again", run: func(m *App) tea.Cmd { return m.setFilter(filterBlocked) }, applies: notMap}, - {keys: []string{"2"}, section: sectionViews, label: "show archived items too, or hide them again", run: func(m *App) tea.Cmd { return m.setFilter(filterAll) }, applies: notMap}, + {Keys: []string{"esc"}, Section: sectionViews, Label: "clear the filter, then the marks, or back out of a drill", Footer: "esc back", Run: (*App).backOut, Applies: (*App).canBackOut}, + {Keys: []string{"tab"}, Section: sectionViews, Label: "the next view", Footer: "tab view", Run: func(m *App) tea.Cmd { return m.cycleView(1) }}, + {Keys: []string{"shift+tab"}, Section: sectionViews, Label: "the previous view", Run: func(m *App) tea.Cmd { return m.cycleView(-1) }}, + {Keys: []string{"/"}, Section: sectionViews, Label: "filter the list, matching notes too", Footer: "/ filter", Run: (*App).startFilter}, + {Keys: []string{"1"}, Section: sectionViews, Label: "show only blocked items, or every one again", Run: func(m *App) tea.Cmd { return m.setFilter(filterBlocked) }, Applies: notMap}, + {Keys: []string{"2"}, Section: sectionViews, Label: "show archived items too, or hide them again", Run: func(m *App) tea.Cmd { return m.setFilter(filterAll) }, Applies: notMap}, { - keys: []string{"0"}, section: sectionViews, label: "show every item but the archived", hint: "[0]reset", - run: func(m *App) tea.Cmd { return m.setFilter(filterNone) }, applies: func(m *App) bool { return notMap(m) && m.filter != filterNone }, + Keys: []string{"0"}, Section: sectionViews, Label: "show every item but the archived", Footer: "0 reset", + Run: func(m *App) tea.Cmd { return m.setFilter(filterNone) }, Applies: func(m *App) bool { return notMap(m) && m.filter != filterNone }, }, - {keys: []string{"."}, section: sectionViews, label: "show or hide shelved and closed projects", run: (*App).toggleClosedProjects, applies: notMap}, + {Keys: []string{"."}, Section: sectionViews, Label: "show or hide shelved and closed projects", Run: (*App).toggleClosedProjects, Applies: notMap}, } } @@ -275,80 +222,73 @@ func notMap(m *App) bool { return m.view != viewDependencies } func everywhereActions() []action { return []action{ - {keys: []string{"u"}, section: sectionEveryone, label: "undo the last change", run: func(m *App) tea.Cmd { return undoCmd(m.backend) }}, - {keys: []string{"R"}, section: sectionEveryone, label: "read the data again now", run: (*App).readAgain}, - {keys: []string{"?"}, section: sectionEveryone, label: "show these keys", run: func(m *App) tea.Cmd { m.returnMode = m.appMode; m.appMode = modeHelp; return nil }}, - {keys: []string{"q", "ctrl+c"}, section: sectionEveryone, label: "quit", run: func(*App) tea.Cmd { return tea.Quit }}, + {Keys: []string{"u"}, Section: gotermboard.SectionEverywhere, Label: "undo the last change", Run: func(m *App) tea.Cmd { return undoCmd(m.backend) }}, + {Keys: []string{"R"}, Section: gotermboard.SectionEverywhere, Label: "read the data again now", Run: (*App).readAgain}, } } +// mapActions is the dependency map's own keys. gotermboard's universal rows move through it. func mapActions() []action { focused := func(m *App) bool { return m.depTree.active == focusPane } return []action{ - {keys: []string{"j", "down"}, section: sectionMove, label: "move down a row", run: func(m *App) tea.Cmd { m.depTreeMove(1); return nil }}, - {keys: []string{"k", "up"}, section: sectionMove, label: "move up a row", run: func(m *App) tea.Cmd { m.depTreeMove(-1); return nil }}, - {keys: []string{"g", "home"}, section: sectionMove, label: "go to the top", run: func(m *App) tea.Cmd { m.depTreeJump(0); return nil }}, - {keys: []string{"G", "end"}, section: sectionMove, label: "go to the bottom", run: func(m *App) tea.Cmd { m.depTreeJump(-1); return nil }}, - {keys: []string{"ctrl+d", "pgdown"}, section: sectionMove, label: "half a screen down", run: func(m *App) tea.Cmd { m.depTreeMove(m.depTreePaneHeight() / 2); return nil }}, - {keys: []string{"ctrl+u", "pgup"}, section: sectionMove, label: "half a screen up", run: func(m *App) tea.Cmd { m.depTreeMove(-m.depTreePaneHeight() / 2); return nil }}, - {keys: []string{"l", "right"}, section: sectionMap, label: "go into the tree, then drill into the row", hint: "[l]drill", run: (*App).depTreeRight}, + {Keys: []string{"l", "right"}, Section: sectionMap, Label: "go into the tree, then drill into the row", Footer: "l drill", Run: (*App).depTreeRight}, { - keys: []string{"h", "left"}, section: sectionMap, label: "back out a drill, then back to the map", hint: "[h]back", - run: (*App).depTreeLeft, applies: focused, + Keys: []string{"h", "left"}, Section: sectionMap, Label: "back out a drill, then back to the map", Footer: "h back", + Run: (*App).depTreeLeft, Applies: focused, }, - {keys: []string{"enter"}, section: sectionMap, label: "read the item", hint: "[Enter]read", run: (*App).readMapItem, applies: func(m *App) bool { return m.depTree.activeID() != "" }}, - {keys: []string{"i"}, section: sectionMap, label: "read the tree's edges the other way", hint: "[i]flip", run: (*App).depTreeFlip, applies: focused}, - {keys: []string{"."}, section: sectionMap, label: "show or hide the finished trees", hint: "[.]finished", run: (*App).depTreeToggleFinished}, + {Keys: []string{"enter"}, Section: sectionMap, Label: "read the item", Footer: "enter read", Run: (*App).readMapItem, Applies: func(m *App) bool { return m.depTree.activeID() != "" }}, + {Keys: []string{"i"}, Section: sectionMap, Label: "read the tree's edges the other way", Footer: "i flip", Run: (*App).depTreeFlip, Applies: focused}, + {Keys: []string{"."}, Section: sectionMap, Label: "show or hide the finished trees", Footer: ". finished", Run: (*App).depTreeToggleFinished}, } } func moveActions() []action { return []action{ - {keys: []string{"j", "down"}, section: sectionMoving, label: "move it down", hint: "[j/k]move", run: func(m *App) tea.Cmd { m.moveGrabbed(1); return nil }}, - {keys: []string{"k", "up"}, section: sectionMoving, label: "move it up", run: func(m *App) tea.Cmd { m.moveGrabbed(-1); return nil }}, - {keys: []string{"g", "home"}, section: sectionMoving, label: "move it to the top", hint: "[g/G]top/bottom", run: func(m *App) tea.Cmd { m.moveGrabbedToEnd(-1); return nil }}, - {keys: []string{"G", "end"}, section: sectionMoving, label: "move it to the bottom", run: func(m *App) tea.Cmd { m.moveGrabbedToEnd(1); return nil }}, - {keys: []string{"enter"}, section: sectionMoving, label: "drop it here", hint: "[Enter]drop", run: (*App).dropGrabbed}, - {keys: []string{"esc"}, section: sectionMoving, label: "put it back", hint: "[Esc]cancel", run: (*App).cancelGrab}, - {keys: []string{"?"}, section: sectionEveryone, label: "show these keys", run: func(m *App) tea.Cmd { m.returnMode = m.appMode; m.appMode = modeHelp; return nil }}, - {keys: []string{"ctrl+c"}, section: sectionEveryone, label: "quit", run: func(*App) tea.Cmd { return tea.Quit }}, + {Keys: []string{"j", "down"}, Section: sectionMoving, Label: "move it down", Footer: "j/k move", Run: func(m *App) tea.Cmd { m.moveGrabbed(1); return nil }}, + {Keys: []string{"k", "up"}, Section: sectionMoving, Label: "move it up", Run: func(m *App) tea.Cmd { m.moveGrabbed(-1); return nil }}, + {Keys: []string{"g", "home"}, Section: sectionMoving, Label: "move it to the top", Footer: "g/G top/bottom", Run: func(m *App) tea.Cmd { m.moveGrabbedToEnd(-1); return nil }}, + {Keys: []string{"G", "end"}, Section: sectionMoving, Label: "move it to the bottom", Run: func(m *App) tea.Cmd { m.moveGrabbedToEnd(1); return nil }}, + {Keys: []string{"enter"}, Section: sectionMoving, Label: "drop it here", Footer: "enter drop", Run: (*App).dropGrabbed}, + {Keys: []string{"esc"}, Section: sectionMoving, Label: "put it back", Footer: "esc cancel", Run: (*App).cancelGrab}, + {Keys: []string{"?"}, Section: gotermboard.SectionEverywhere, Label: "show these keys", Run: func(m *App) tea.Cmd { m.ShowKeys(); return nil }}, + {Keys: []string{"ctrl+c"}, Section: gotermboard.SectionEverywhere, Label: "quit", Run: func(*App) tea.Cmd { return tea.Quit }}, } } func helpActions() []action { return []action{ - {keys: []string{"esc", "?"}, section: sectionKeys, label: "close this list", hint: "[Esc]close", run: (*App).closeHelp}, - {keys: []string{"q", "ctrl+c"}, section: sectionKeys, label: "quit", hint: "[q]quit", run: func(*App) tea.Cmd { return tea.Quit }}, + {Keys: []string{"esc", "?"}, Section: sectionKeys, Label: "close this list", Footer: "esc close", Run: (*App).closeHelp}, + {Keys: []string{"q", "ctrl+c"}, Section: sectionKeys, Label: "quit", Footer: "q quit", Run: func(*App) tea.Cmd { return tea.Quit }}, } } func filterActions() []action { return []action{ - {keys: []string{"enter"}, section: sectionViews, label: "keep the filter and go back to the list", hint: "[Enter]keep", run: (*App).keepFilter}, - {keys: []string{"esc"}, section: sectionViews, label: "clear the filter", hint: "[Esc]clear", run: (*App).clearFilter}, + {Keys: []string{"enter"}, Section: sectionViews, Label: "keep the filter and go back to the list", Footer: "enter keep", Run: (*App).keepFilter}, + {Keys: []string{"esc"}, Section: sectionViews, Label: "clear the filter", Footer: "esc clear", Run: (*App).clearFilter}, } } // promptActions is a prompt for a name, a title or a reason. func promptActions() []action { return []action{ - {keys: []string{"enter"}, section: sectionPrompt, label: "do it with what is typed", hint: "[Enter]confirm", run: (*App).confirmPrompt}, - {keys: []string{"esc"}, section: sectionPrompt, label: "close the prompt, keeping nothing", hint: "[Esc]cancel", run: (*App).cancelPrompt}, + {Keys: []string{"enter"}, Section: sectionPrompt, Label: "do it with what is typed", Footer: "enter confirm", Run: (*App).confirmPrompt}, + {Keys: []string{"esc"}, Section: sectionPrompt, Label: "close the prompt, keeping nothing", Footer: "esc cancel", Run: (*App).cancelPrompt}, } } func pickerActions() []action { return []action{ - {keys: []string{"j", "down"}, section: sectionPicker, label: "move down a project", run: func(m *App) tea.Cmd { m.picker.down(); return nil }}, - {keys: []string{"k", "up"}, section: sectionPicker, label: "move up a project", run: func(m *App) tea.Cmd { m.picker.up(); return nil }}, - {keys: []string{"g", "home"}, section: sectionPicker, label: "go to the top", run: func(m *App) tea.Cmd { m.picker.cursor = 0; return nil }}, + {Keys: []string{"j", "down"}, Section: sectionPicker, Label: "move down a project", Run: func(m *App) tea.Cmd { m.picker.down(); return nil }}, + {Keys: []string{"k", "up"}, Section: sectionPicker, Label: "move up a project", Run: func(m *App) tea.Cmd { m.picker.up(); return nil }}, + {Keys: []string{"g", "home"}, Section: sectionPicker, Label: "go to the top", Run: func(m *App) tea.Cmd { m.picker.cursor = 0; return nil }}, { - keys: []string{"G", "end"}, section: sectionPicker, label: "go to the bottom", - run: func(m *App) tea.Cmd { m.picker.cursor = max(len(m.picker.projects)-1, 0); return nil }, + Keys: []string{"G", "end"}, Section: sectionPicker, Label: "go to the bottom", + Run: func(m *App) tea.Cmd { m.picker.cursor = max(len(m.picker.projects)-1, 0); return nil }, }, - {keys: []string{"space"}, section: sectionPicker, label: "tick or untick the project", hint: "[space]toggle", run: func(m *App) tea.Cmd { m.picker.toggle(); return nil }}, - {keys: []string{"enter"}, section: sectionPicker, label: "file the item in the ticked projects", hint: "[Enter]confirm", run: (*App).confirmPicker}, - {keys: []string{"esc"}, section: sectionPicker, label: "close, changing nothing", hint: "[Esc]cancel", run: (*App).cancelPicker}, + {Keys: []string{"space"}, Section: sectionPicker, Label: "tick or untick the project", Footer: "space toggle", Run: func(m *App) tea.Cmd { m.picker.toggle(); return nil }}, + {Keys: []string{"enter"}, Section: sectionPicker, Label: "file the item in the ticked projects", Footer: "enter confirm", Run: (*App).confirmPicker}, + {Keys: []string{"esc"}, Section: sectionPicker, Label: "close, changing nothing", Footer: "esc cancel", Run: (*App).cancelPicker}, } } @@ -362,20 +302,20 @@ func depLinkActions() []action { } return []action{ { - keys: []string{"enter"}, section: sectionLinking, label: "keep the filter and choose from what it kept", hint: "[Enter]keep", - run: func(m *App) tea.Cmd { return m.stopDepFilter(false) }, applies: typing, + Keys: []string{"enter"}, Section: sectionLinking, Label: "keep the filter and choose from what it kept", Footer: "enter keep", + Run: func(m *App) tea.Cmd { return m.stopDepFilter(false) }, Applies: typing, }, - {keys: []string{"esc"}, section: sectionLinking, label: "clear the filter", hint: "[Esc]clear", run: func(m *App) tea.Cmd { return m.stopDepFilter(true) }, applies: typing}, - {keys: []string{"j", "down"}, section: sectionLinking, label: "move down an item", run: func(m *App) tea.Cmd { m.moveDepCursor(m.depCursor + 1); return nil }, applies: listing}, - {keys: []string{"k", "up"}, section: sectionLinking, label: "move up an item", run: func(m *App) tea.Cmd { m.moveDepCursor(m.depCursor - 1); return nil }, applies: listing}, - {keys: []string{"g", "home"}, section: sectionLinking, label: "go to the top", run: func(m *App) tea.Cmd { m.moveDepCursor(0); return nil }, applies: listing}, - {keys: []string{"G", "end"}, section: sectionLinking, label: "go to the bottom", run: func(m *App) tea.Cmd { m.moveDepCursor(len(m.depItems)); return nil }, applies: listing}, - {keys: []string{"enter"}, section: sectionLinking, label: "link the item this one waits on", hint: "[Enter]link", run: (*App).chooseDependency, applies: choosing(modeDepLink)}, - {keys: []string{"enter"}, section: sectionLinking, label: "unlink the item this one waits on", hint: "[Enter]unlink", run: (*App).chooseDependency, applies: choosing(modeDepUnlink)}, + {Keys: []string{"esc"}, Section: sectionLinking, Label: "clear the filter", Footer: "esc clear", Run: func(m *App) tea.Cmd { return m.stopDepFilter(true) }, Applies: typing}, + {Keys: []string{"j", "down"}, Section: sectionLinking, Label: "move down an item", Run: func(m *App) tea.Cmd { m.moveDepCursor(m.depCursor + 1); return nil }, Applies: listing}, + {Keys: []string{"k", "up"}, Section: sectionLinking, Label: "move up an item", Run: func(m *App) tea.Cmd { m.moveDepCursor(m.depCursor - 1); return nil }, Applies: listing}, + {Keys: []string{"g", "home"}, Section: sectionLinking, Label: "go to the top", Run: func(m *App) tea.Cmd { m.moveDepCursor(0); return nil }, Applies: listing}, + {Keys: []string{"G", "end"}, Section: sectionLinking, Label: "go to the bottom", Run: func(m *App) tea.Cmd { m.moveDepCursor(len(m.depItems)); return nil }, Applies: listing}, + {Keys: []string{"enter"}, Section: sectionLinking, Label: "link the item this one waits on", Footer: "enter link", Run: (*App).chooseDependency, Applies: choosing(modeDepLink)}, + {Keys: []string{"enter"}, Section: sectionLinking, Label: "unlink the item this one waits on", Footer: "enter unlink", Run: (*App).chooseDependency, Applies: choosing(modeDepUnlink)}, { - keys: []string{"/"}, section: sectionLinking, label: "filter the items", hint: "[/]filter", run: (*App).startDepFilter, - applies: func(m *App) bool { return listing(m) && m.appMode == modeDepLink }, + Keys: []string{"/"}, Section: sectionLinking, Label: "filter the items", Footer: "/ filter", Run: (*App).startDepFilter, + Applies: func(m *App) bool { return listing(m) && m.appMode == modeDepLink }, }, - {keys: []string{"esc"}, section: sectionLinking, label: "close, changing nothing", hint: "[Esc]cancel", run: (*App).cancelDepLink, applies: listing}, + {Keys: []string{"esc"}, Section: sectionLinking, Label: "close, changing nothing", Footer: "esc cancel", Run: (*App).cancelDepLink, Applies: listing}, } } diff --git a/tui/app.go b/tui/app.go index 9472e1a..eef6648 100644 --- a/tui/app.go +++ b/tui/app.go @@ -40,9 +40,10 @@ type App struct { // rows is the item pane's cursor stops: group headers, items and their tasks. rows []paneRow // folded holds each group folded under its header, by project ID, and opened each item - // whose note shows in place, by item ID. - folded map[string]bool - opened map[string]bool + // whose detail shows in place, by item ID. details is each such item's detail as last read. + folded map[string]bool + opened map[string]bool + details map[string]itemDetailMsg // scrolled says ctrl+d, ctrl+u, J or K moved the item pane through an open note, and the // pane holds that offset until the cursor moves. scrolled bool @@ -146,6 +147,7 @@ func NewApp(b backend.Backend, where Where) *App { itemBlockers: make(map[string][]model.ProjectItem), folded: make(map[string]bool), opened: make(map[string]bool), + details: make(map[string]itemDetailMsg), titleInput: ti, depFilter: df, filterInput: fi, @@ -241,6 +243,7 @@ type itemProjectsMsg struct { } type itemDetailMsg struct { + opening detailOpening detail *model.ProjectItemDetail blockers []model.ProjectItem projectNames map[string][]string @@ -622,7 +625,7 @@ func updateMembershipCmd(b backend.Backend, itemID string, toAdd, toRemove []str } } -func fetchItemDetailCmd(b backend.Backend, itemID string, isBlocked bool) tea.Cmd { +func fetchItemDetailCmd(b backend.Backend, itemID string, isBlocked bool, opening detailOpening) tea.Cmd { return func() tea.Msg { detail, err := b.GetItem(itemID) if err != nil { @@ -668,7 +671,7 @@ func fetchItemDetailCmd(b backend.Backend, itemID string, isBlocked bool) tea.Cm if err != nil { return errMsg{err} } - return itemDetailMsg{detail: detail, blockers: blockers, projectNames: pnames, dependents: dependents, tasks: tasks} + return itemDetailMsg{opening: opening, detail: detail, blockers: blockers, projectNames: pnames, dependents: dependents, tasks: tasks} } } @@ -891,11 +894,13 @@ func (m *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case allItemsMsg: m.takeItems(msg.itemsMsg, msg.groups) - return m, nil + cmd := m.readOpenDetailsAgain() + return m, cmd case itemsMsg: m.takeItems(msg, nil) - return m, nil + cmd := m.readOpenDetailsAgain() + return m, cmd case taskCreatedMsg, taskUpdatedMsg, taskDeletedMsg: cmd := m.fetchItems() @@ -921,12 +926,8 @@ func (m *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } return m, saveCmd - case claudeSessionEndedMsg: - if msg.err != nil { - cmd := m.flash(fmt.Sprintf("The Claude session on %s, in %s, ended: %v", msg.handle, msg.ranIn, msg.err)) - return m, cmd - } - cmd := m.flash(fmt.Sprintf("Back from the Claude session on %s, which ran in %s", msg.handle, msg.ranIn)) + case gotermboard.ClaudeSessionOutcome: + cmd := m.tookClaudeOutcome(msg) return m, cmd case projectCreatedMsg: @@ -942,7 +943,7 @@ func (m *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil case itemDetailMsg: - m.openReader(msg.detail.Title, m.itemDocument(msg)) + m.tookDetail(msg) return m, nil case undoResultMsg: @@ -1479,43 +1480,6 @@ func (m *App) moveBy(rows int) tea.Cmd { return nil } -func (m *App) cursorDown() tea.Cmd { return m.moveBy(1) } -func (m *App) cursorUp() tea.Cmd { return m.moveBy(-1) } - -func (m *App) cursorTop() tea.Cmd { - if m.view == viewProjects && m.activePane == projectPane { - return m.pointAtProject(0) - } - m.moveCursorTo(0) - return nil -} - -func (m *App) cursorBottom() tea.Cmd { - if m.view == viewProjects && m.activePane == projectPane { - return m.pointAtProject(len(m.projects) - 1) - } - m.moveCursorTo(len(m.rows) - 1) - return nil -} - -// halfScreen is ctrl+d and ctrl+u: half a screen through the note open on the cursor's row, -// otherwise of the list. -func (m *App) halfScreen(direction int) tea.Cmd { - half := max(m.paneContentHeight()/2, 1) - if m.onOpenText() { - m.scrollOpenText(direction * half) - return nil - } - return m.moveBy(direction * half) -} - -// scrollOpenText moves the item pane through the open note by lines, and leaves the cursor -// on its row. -func (m *App) scrollOpenText(lines int) { - m.scrolled = true - m.rowScroll = max(m.rowScroll+lines, 0) -} - // paneContentHeight is how many lines a pane's list gets, under the header, its border, its // title and the status bar. func (m *App) paneContentHeight() int { @@ -1530,11 +1494,6 @@ func (m *App) readProject() tea.Cmd { return fetchProjectDetailCmd(m.backend, m.currentProject().ID) } -func (m *App) readItem() tea.Cmd { - item := m.currentItem() - return fetchItemDetailCmd(m.backend, item.ID, m.blockedSet[item.ID]) -} - func (m *App) toggleProjectMark() tea.Cmd { if m.selectedProjects == nil { m.selectedProjects = make(map[string]bool) @@ -1605,13 +1564,6 @@ func (m *App) reopenProject() tea.Cmd { return setProjectStatusCmd(m.backend, m.currentProject().ID, model.StatusActive, nil) } -func (m *App) toggleNote() tea.Cmd { - item := m.currentItem() - m.opened[item.ID] = !m.opened[item.ID] - m.scrolled = false - return nil -} - func (m *App) toggleGroup() tea.Cmd { row := m.currentRow() id := m.groups[row.group].projectID @@ -2038,9 +1990,9 @@ func (m *App) renderDepLinkOverlay() string { } // clipHints narrows a hint line to fit, dropping whole hints rather than -// cutting one in half: a trailing "[T]re…" reads as a rendering fault, where a -// dropped hint reads as a list that continues. Hints are split on the bracket -// that opens each one, since several carry a space of their own. +// cutting one in half: a trailing "T re…" reads as a rendering fault, where a +// dropped hint reads as a list that continues. Hints are split on the gap +// between them, since each carries a space of its own. func clipHints(hints string, maxWidth int) string { if lipgloss.Width(hints) <= maxWidth { return hints @@ -2048,15 +2000,12 @@ func clipHints(hints string, maxWidth int) string { if maxWidth < 4 { return "" } - parts := strings.Split(hints, " [") + parts := strings.Split(hints, hintGap) kept, width := []string{}, 0 for i, part := range parts { - if i > 0 { - part = "[" + part - } next := width + lipgloss.Width(part) if i > 0 { - next++ + next += len(hintGap) } if next+2 > maxWidth { break @@ -2066,7 +2015,7 @@ func clipHints(hints string, maxWidth int) string { if len(kept) == 0 { return "" } - return strings.Join(kept, " ") + " …" + return strings.Join(kept, hintGap) + " …" } func (m *App) statusBarHints() string { @@ -2088,10 +2037,10 @@ func (m *App) renderStatusBar() string { modeStr = modeLocalStyle.Render("LOCAL") + dimStyle.Render(" "+m.where.DatabasePath) } - // [?]help sits on the right, with the things that are always true, rather than at the end - // of the contextual list where clipping reaches it first. It is the one key that leads to - // every other key, so it is the last one that should disappear on a narrow window. - modeStr = "[?]help " + modeStr + // ? sits on the right, with the things that are always true, rather than at the end of the + // contextual list where clipping reaches it first. It is the one key that leads to every + // other key, so it is the last one that should disappear on a narrow window. + modeStr = "? keys " + modeStr modeWidth := lipgloss.Width(modeStr) var left string diff --git a/tui/claude_session.go b/tui/claude_session.go index 71d9118..bb111bd 100644 --- a/tui/claude_session.go +++ b/tui/claude_session.go @@ -3,31 +3,19 @@ package tui import ( "fmt" "os" - "os/exec" + "unicode" tea "charm.land/bubbletea/v2" "github.com/datapointchris/gotermboard" ) -// The first message of the Claude session C opens. It names the record by its handle alone, so -// the session reads the record's words as data with the command it names. +// The first message of the Claude session C opens begins with these. They name the record by its +// handle alone, so the session reads the record's words as data with the command they name. const ( - itemSessionBrief = "This is projects item %[1]s, opened from `projects tui`. " + - "`projects items show %[1]s` prints it whole. Read it, say what it asks for and what you would do, " + - "then wait before changing anything." - projectSessionBrief = "This is the projects project %[1]s, opened from `projects tui`. " + - "`projects show %[1]s` prints it with its open items. Read it, say what it asks for and what you would do, " + - "then wait before changing anything." + itemSessionBrief = "This is projects item %[1]s, opened from `projects tui`. `projects items show %[1]s` prints it whole." + projectSessionBrief = "This is the projects project %[1]s, opened from `projects tui`. `projects show %[1]s` prints it with its open items." ) -// claudeSessionEndedMsg is a Claude session that held the terminal giving it back. ranIn is the -// directory it ran in, with why where it was not the record's checkout. -type claudeSessionEndedMsg struct { - handle string - ranIn string - err error -} - func (m *App) claudeOnItem() tea.Cmd { item := m.currentItem() repo := "" @@ -48,32 +36,27 @@ func (m *App) claudeOnProject() tea.Cmd { return m.openClaudeSession(p.Name, repo, fmt.Sprintf(projectSessionBrief, p.ID)) } -// openClaudeSession is C: a Claude session in the repo's checkout. Inside tmux it opens in a -// window of its own, so the board stays usable while the session works, and outside tmux it -// takes the board's terminal until it ends. A session in the board's own directory is told so -// in its brief, because that directory may hold another repo's code. +// openClaudeSession is C: a Claude session in the repo's checkout, which gotermboard opens. func (m *App) openClaudeSession(handle, repo, brief string) tea.Cmd { - if _, err := exec.LookPath("claude"); err != nil { - return m.flash(fmt.Sprintf("claude is not on PATH, so no session opened on %s", handle)) - } directory, fallback, err := m.sessionDirectory(handle, repo) if err != nil { return m.flash(err.Error()) } - ranIn := directory - if fallback != "" { - ranIn += ", because " + fallback - brief += fmt.Sprintf(" This session runs in %s, because %s.", directory, fallback) + return gotermboard.OpenClaudeSession(gotermboard.ClaudeSession{On: handle, Dir: directory, Fallback: fallback, Brief: brief}) +} + +// tookClaudeOutcome flashes what came of C. A session that held the terminal may have changed +// what the board shows, so the board reads again. +func (m *App) tookClaudeOutcome(outcome gotermboard.ClaudeSessionOutcome) tea.Cmd { + said := []rune(outcome.Said) + if len(said) > 0 { + said[0] = unicode.ToUpper(said[0]) } - if os.Getenv("TMUX") != "" { - if err := gotermboard.OpenWindow("claude "+handle, directory, []string{"claude", brief}); err != nil { - return m.flash(err.Error()) - } - return m.flash(fmt.Sprintf("Opened a Claude session on %s in a tmux window, in %s", handle, ranIn)) + flash := m.flash(string(said)) + if outcome.HeldTerminal { + return tea.Batch(flash, m.rereadCmd()) } - session := exec.Command("claude", brief) - session.Dir = directory - return tea.ExecProcess(session, func(err error) tea.Msg { return claudeSessionEndedMsg{handle: handle, ranIn: ranIn, err: err} }) + return flash } // sessionDirectory is where C opens Claude: the checkout the registry names for the repo, else diff --git a/tui/deptree.go b/tui/deptree.go index 674db09..3ce36ba 100644 --- a/tui/deptree.go +++ b/tui/deptree.go @@ -311,7 +311,7 @@ func (m *App) depTreeToggleFinished() tea.Cmd { // readMapItem reads the item under the cursor. The item lists' blocked set may not hold an item // the map reaches, so its blockers are always read. func (m *App) readMapItem() tea.Cmd { - return fetchItemDetailCmd(m.backend, m.depTree.activeID(), true) + return fetchItemDetailCmd(m.backend, m.depTree.activeID(), true, openFullScreen) } // activeID is the item under whichever pane has focus. @@ -340,24 +340,6 @@ func (m *App) depTreeMove(delta int) { } } -func (m *App) depTreeJump(to int) { - s := &m.depTree - if s.active == focusPane { - if to < 0 { - to = len(s.focusRows) - 1 - } - s.focusCursor = clampCursor(to, len(s.focusRows)) - s.focusScroll = syncScroll(s.focusCursor, s.focusScroll, m.depTreePaneHeight()) - return - } - if to < 0 { - to = len(s.forestRows) - 1 - } - s.forestCursor = clampCursor(to, len(s.forestRows)) - s.forestScroll = syncScroll(s.forestCursor, s.forestScroll, m.depTreePaneHeight()) - s.focusOn(s.forestID()) -} - func clampCursor(value, length int) int { return max(min(value, length-1), 0) } diff --git a/tui/deptree_test.go b/tui/deptree_test.go index 47646fa..ed7a969 100644 --- a/tui/deptree_test.go +++ b/tui/deptree_test.go @@ -1,6 +1,7 @@ package tui import ( + "slices" "strconv" "strings" "testing" @@ -435,12 +436,16 @@ func TestStatusBar_NeverWiderThanTheWindow(t *testing.T) { t.Errorf("main bar is %d columns in a %d-column window", got, width) } // Clipping must not reach the one key that leads to every other key. - if !strings.Contains(bar, "[?]help") { + if !strings.Contains(bar, "? keys") { t.Errorf("help key clipped off at %d columns: %s", width, bar) } // A hint is shown whole or dropped, never cut in half. - if plain := ansi.Strip(bar); strings.Count(plain, "[") != strings.Count(plain, "]") { - t.Errorf("hint cut mid-token at %d columns: %s", width, bar) + whole := strings.Split(app.footerHints(), hintGap) + shown, _, _ := strings.Cut(strings.TrimSpace(ansi.Strip(bar)), " ") + for _, hint := range strings.Split(strings.TrimSuffix(shown, " …"), hintGap) { + if !slices.Contains(whole, hint) { + t.Errorf("hint %q cut mid-token at %d columns: %s", hint, width, bar) + } } openTree(t, app) diff --git a/tui/item_rows.go b/tui/item_rows.go index 1d6d02c..329d3d2 100644 --- a/tui/item_rows.go +++ b/tui/item_rows.go @@ -250,17 +250,6 @@ func (m *App) moveCursorTo(at int) { m.scrolled = false } -// onOpenText says the cursor's row shows its note open under it, which ctrl+d, ctrl+u, J and K -// then read through. -func (m *App) onOpenText() bool { - row := m.currentRow() - return row != nil && row.kind == rowItem && m.noteOpen(m.items[row.itemIdx].ProjectItem) -} - -func (m *App) noteOpen(item model.ProjectItem) bool { - return m.opened[item.ID] && hasNote(item) -} - // --- Layout --- // paneLayout is where every row of the item pane lands in line space. Scrolling counts lines @@ -305,8 +294,8 @@ func (m *App) itemPaneLayout(width int) paneLayout { body := 1 if row.kind == rowItem { body = 2 - if item := m.items[row.itemIdx].ProjectItem; m.noteOpen(item) { - body += len(m.noteLines(item, width)) + if item := m.items[row.itemIdx].ProjectItem; m.detailOpen(item.ID) { + body += len(m.detailLines(item.ID, width)) } } if row.kind != rowGroup && m.rowIsLastOfItem(i) { @@ -509,8 +498,8 @@ func (m *App) renderRowBlock(i, width int) []string { case rowItem: item := m.items[row.itemIdx] lines = append(lines, m.itemLines(item, row.group, i == m.rowCursor, width)...) - if m.noteOpen(item.ProjectItem) { - lines = append(lines, m.noteLines(item.ProjectItem, width)...) + if m.detailOpen(item.ID) { + lines = append(lines, m.detailLines(item.ID, width)...) } case rowTask: lines = append(lines, m.taskLine(row, i == m.rowCursor, width)) @@ -574,8 +563,7 @@ func (m *App) itemLines(item model.ProjectItemInProject, group int, cursor bool, if item.Completed { status = "✓" } - opens := hasNote(item.ProjectItem) - head := lead + chevron(opens, m.opened[item.ID]) + " " + status + " " + head := lead + chevron(true, m.detailOpen(item.ID)) + " " + status + " " var glyphs []string var plain string @@ -583,7 +571,7 @@ func (m *App) itemLines(item model.ProjectItemInProject, group int, cursor bool, plain += " ◈" glyphs = append(glyphs, multiProjectStyle.Render(" ◈")) } - if opens { + if hasNote(item.ProjectItem) { plain += " ≡" glyphs = append(glyphs, notesIndicatorStyle.Render(" ≡")) } @@ -676,17 +664,21 @@ func (m *App) taskLine(row paneRow, cursor bool, width int) string { return lead + check + " " + title } -// noteLines is an item's note laid out by gotermboard's markdown renderer, under its title. -func (m *App) noteLines(item model.ProjectItem, width int) []string { - room := max(min(width-titleColumn-1, gotermboard.ReadingWidth), 10) +// detailLines is the item's detail, as its reader shows it, laid out under its title. +func (m *App) detailLines(itemID string, width int) []string { indent := strings.Repeat(" ", titleColumn) var lines []string - for _, line := range m.markdown.Lines(noteOf(item), room) { + for _, line := range m.itemDocument(m.details[itemID])(detailWidth(width)) { lines = append(lines, ansi.Truncate(indent+line.Paint(m.palette), width, "…")) } return lines } +// detailWidth is the width an item's detail lays out at in place, under its title. +func detailWidth(paneWidth int) int { + return max(min(paneWidth-titleColumn-1, gotermboard.ReadingWidth), 10) +} + // blockerLines is what hangs below an item: each item that blocks it. func (m *App) blockerLines(item model.ProjectItemInProject, group int, width int) []string { here := "" diff --git a/tui/key_host.go b/tui/key_host.go new file mode 100644 index 0000000..b4de34a --- /dev/null +++ b/tui/key_host.go @@ -0,0 +1,159 @@ +package tui + +import ( + tea "charm.land/bubbletea/v2" +) + +// The board is the gotermboard.Host its universal rows act on. A key moves the cursor of the pane +// it works in: the dependency map's, the project list's, or the item list's. + +// MoveBy is gotermboard.Host's. +func (m *App) MoveBy(rows int) tea.Cmd { + if m.view == viewDependencies { + m.depTreeMove(rows) + return nil + } + return m.moveBy(rows) +} + +// HalfScreen is gotermboard.Host's. +func (m *App) HalfScreen() int { + if m.view == viewDependencies { + return max(m.depTreePaneHeight()/2, 1) + } + return max(m.paneContentHeight()/2, 1) +} + +// ScrollBy is gotermboard.Host's: it moves the item pane through the open detail by lines, and +// leaves the cursor on its row. +func (m *App) ScrollBy(lines int) { + m.scrolled = true + m.rowScroll = max(m.rowScroll+lines, 0) +} + +// OnOpenText is gotermboard.Host's. +func (m *App) OnOpenText() bool { + row := m.currentRow() + return m.view != viewDependencies && row != nil && row.kind == rowItem && m.detailOpen(m.items[row.itemIdx].ID) +} + +// JumpGroup is gotermboard.Host's. +func (m *App) JumpGroup(direction int) { m.jumpRow(direction) } + +// HasGroups is gotermboard.Host's. An item is the group its tasks sit in. +func (m *App) HasGroups() bool { return m.view != viewDependencies && m.onItemList() } + +// Toggles is gotermboard.Host's: enter and space open an item's detail or fold a project's +// group. The project list and the map bind their own. +func (m *App) Toggles() bool { + if m.view == viewDependencies || m.view == viewProjects && m.activePane == projectPane { + return false + } + return m.onKind(rowItem) || m.onKind(rowGroup) +} + +// Open is gotermboard.Host's: enter reads an item's detail full screen where it runs past the +// pane, and otherwise opens or closes it in place. The detail is read first, so the choice is +// made on what it holds now. +func (m *App) Open() tea.Cmd { + if m.onKind(rowGroup) { + return m.toggleGroup() + } + item := m.currentItem() + return fetchItemDetailCmd(m.backend, item.ID, m.blockedSet[item.ID], openByEnter) +} + +// ToggleInPlace is gotermboard.Host's: space opens an item's detail in place however tall, or +// closes it. +func (m *App) ToggleInPlace() tea.Cmd { + if m.onKind(rowGroup) { + return m.toggleGroup() + } + item := m.currentItem() + if m.detailOpen(item.ID) { + m.closeDetail(item.ID) + return nil + } + return fetchItemDetailCmd(m.backend, item.ID, m.blockedSet[item.ID], openInPlace) +} + +// ShowKeys is gotermboard.Host's. +func (m *App) ShowKeys() { + m.returnMode = m.appMode + m.appMode = modeHelp +} + +// Quit is gotermboard.Host's. +func (m *App) Quit() tea.Cmd { return tea.Quit } + +// detailOpening is what an item's detail is read for. +type detailOpening int + +const ( + // openFullScreen reads it on the full-screen reader. + openFullScreen detailOpening = iota + // openByEnter reads it full screen where it runs past the pane, and otherwise opens or + // closes it in place. + openByEnter + // openInPlace opens it under the item's row however tall. + openInPlace + // openAgain lays out again a detail open in place, from what the board read since. + openAgain +) + +// detailOpen says the item's detail shows in place under its row. +func (m *App) detailOpen(itemID string) bool { + _, read := m.details[itemID] + return m.opened[itemID] && read +} + +func (m *App) closeDetail(itemID string) { + m.opened[itemID] = false + delete(m.details, itemID) + m.scrolled = false +} + +// tallDetail says the detail runs past the item pane, so enter reads it full screen. +func (m *App) tallDetail(msg itemDetailMsg) bool { + return len(m.itemDocument(msg)(detailWidth(m.itemPaneWidth()-2))) >= m.paneContentHeight() +} + +// tookDetail is an item's detail read for opening. +func (m *App) tookDetail(msg itemDetailMsg) { + id := msg.detail.ID + switch msg.opening { + case openFullScreen: + m.openReader(msg.detail.Title, m.itemDocument(msg)) + return + case openByEnter: + if m.tallDetail(msg) { + m.openReader(msg.detail.Title, m.itemDocument(msg)) + return + } + if m.detailOpen(id) { + m.closeDetail(id) + return + } + case openAgain: + if !m.opened[id] { + return + } + } + m.details[id] = msg + m.opened[id] = true + m.scrolled = false +} + +// readOpenDetailsAgain reads again each detail open in place, after the board read its items, +// so the text under a row says what the item holds now. +func (m *App) readOpenDetailsAgain() tea.Cmd { + var cmds []tea.Cmd + read := map[string]bool{} + for _, item := range m.items { + if m.detailOpen(item.ID) && !read[item.ID] { + read[item.ID] = true + cmds = append(cmds, fetchItemDetailCmd(m.backend, item.ID, m.blockedSet[item.ID], openAgain)) + } + } + return tea.Batch(cmds...) +}