Skip to content

Restore TUI command entry and suspend, clean up tech debt#35

Merged
ScottMorris merged 6 commits intomainfrom
fix/issue-33-command-entry-and-suspend
Mar 18, 2026
Merged

Restore TUI command entry and suspend, clean up tech debt#35
ScottMorris merged 6 commits intomainfrom
fix/issue-33-command-entry-and-suspend

Conversation

@ScottMorris
Copy link
Copy Markdown
Contributor

@ScottMorris ScottMorris commented Mar 13, 2026

Summary

Rebased onto main after PR #40 was merged. This PR takes the best from both branches (#40's command palette UX, #35's extensible structs), then applies a comprehensive tech debt cleanup across the TUI and core crates.

User-facing changes

  • Slash command entry: Manually typed slash commands now leave the command palette once the command is recognised and argument entry begins, so Enter submits the command normally again. (shipped in Restore TUI command submission and suspend handling #40)
  • Terminal suspend: Ctrl+Z now suspends flo, restores the terminal cleanly, and allows the TUI to resume properly after fg. (shipped in Restore TUI command submission and suspend handling #40)
  • Command consistency: The core parser now recognises /resume, /park, and /archive as first-class intents with full slash-command handlers, so they work consistently whether typed or selected from the palette.
  • Smarter palette behaviour: Commands that require an argument (like /now, /branch, /note) keep the palette open until the argument is started; commands without arguments (like /done, /where, /resume) close the palette immediately.
  • Palette correction workflow: The palette reopens when editing a command token back to an unrecognised prefix (e.g. /branch meow → backspace → /branc meow shows filtered matches), supporting inline command correction.
  • Cursor keys work in palette: Left, Right, Home, End, and Delete now work while the command palette is open instead of being swallowed.

Code quality — tech debt cleanup

  • Data-driven command parsing: Replaced the ~75-line if-chain in parse_slash_command with a static COMMAND_TABLE lookup. Added Copy to the Intent enum (all unit variants) to support use in the const table.
  • SlashCommand struct: Replaces the (&str, &str) tuple array with a struct that carries syntax, description, and requires_argument. This makes palette behaviour data-driven instead of string-matching.
  • Removed redundant wrappers: Eliminated should_show_command_palette (delegated directly to should_keep_command_palette_open) and made command_palette_query private (only used within state.rs).
  • Unified key handling: Merged duplicate Backspace/Char(_) match arms in both the palette-open and normal insert mode branches. All insert-mode keys now trigger palette state refresh.
  • apply_input_result helper: Extracted repeated match result { Reply/Error/None } blocks from the Normal mode keybinding handlers (r, p, d, A) and the Enter/submit handler.
  • From<Result<String>> for InputResult: Unifies error handling between functions returning InputResult and those returning Result<String>.
  • Intent-based should_follow_active_after_submit: Replaced hand-rolled string matching with parsed_intent() + matches! on Intent variants.
  • Removed suspend_terminal(): Replaced by the extracted enter_tui_terminal() / restore_tui_terminal() helpers that are also used by run() and the panic hook.

Documentation

  • Updated help text, README.md, and SPEC.md so the documented command and suspend behaviour match the implementation.

Test plan

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace — 93 tests pass
  • Manual TUI: palette opens for partial commands, closes for complete ones
  • Manual TUI: palette reopens when editing command token back to partial
  • Manual TUI: cursor keys and Delete work while palette is open
  • Manual TUI: Ctrl+Z suspend and fg resume

Closes #32, Closes #33

🤖 Generated with Claude Code

@ScottMorris ScottMorris added bug Something isn't working tui liminal-flow-tui crate labels Mar 13, 2026
@ScottMorris ScottMorris force-pushed the fix/issue-33-command-entry-and-suspend branch from fcc1ba4 to 538ec09 Compare March 18, 2026 02:41
**What changed**
- close the command palette once a full slash command is recognised and argument entry begins, so typed commands submit normally again
- add parser and intent coverage for selected-item slash commands such as `/resume`, `/park`, and `/archive`
- handle `Ctrl+Z` by restoring the terminal before suspend and re-entering the TUI cleanly on resume
- update help text and docs so the documented TUI behaviour matches the shipped fixes

**Why**
- manually typed slash commands in `v0.0.3` could stay trapped in palette mode and block submission
- suspend was being swallowed by the raw-mode event loop, which made `flo` behave unlike a normal terminal app
- the parser, selected-item handlers, and docs had drifted apart, which increased the risk of more command UX regressions
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 18, 2026

Flow Tests

95 tests  +10   95 ✅ +10   0s ⏱️ ±0s
 4 suites ± 0    0 💤 ± 0 
 1 files   ± 0    0 ❌ ± 0 

Results for commit 52c70b0. ± Comparison against base commit 9c6967b.

This pull request removes 3 and adds 13 tests. Note that renamed tests count towards both.
liminal-flow-tui ‑ app::tests::command_palette_closes_once_command_token_is_complete
liminal-flow-tui ‑ app::tests::command_palette_reopens_for_partial_command_after_backspace
liminal-flow-tui ‑ app::tests::command_palette_stays_open_for_partial_commands
liminal-flow-core ‑ rules::tests::parse_archive_command
liminal-flow-core ‑ rules::tests::parse_archive_command_with_note
liminal-flow-core ‑ rules::tests::parse_park_command
liminal-flow-core ‑ rules::tests::parse_park_command_with_note
liminal-flow-core ‑ rules::tests::parse_resume_command
liminal-flow-core ‑ rules::tests::parse_resume_command_with_note
liminal-flow-core ‑ rules::tests::parse_where_rejects_trailing_text
liminal-flow-tui ‑ app::tests::palette_close_cases_not_covered_in_state_tests
liminal-flow-tui ‑ app::tests::palette_open_cases_not_covered_in_state_tests
liminal-flow-tui ‑ state::tests::palette_closes_for_complete_commands_and_argument_entry
…

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown

CI check summary

  • [PASS] Format: success
  • [PASS] Clippy: success
  • [PASS] Test: success

ScottMorris and others added 3 commits March 17, 2026 23:12
Replace the ~75-line if-chain in parse_slash_command with a static
COMMAND_TABLE lookup. Add Copy to the Intent enum (all unit variants)
to support use in the const table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tech debt:
- Remove redundant should_show_command_palette wrapper; call
  should_keep_command_palette_open directly
- Make command_palette_query private (only used within state.rs)
- Unify duplicate Backspace/Char key arms in both palette-open and
  normal insert mode branches
- Extract apply_input_result helper to replace repeated match blocks
  in Normal mode keybinding handlers (r, p, d, A) and Enter/submit
- Add From<Result<String>> impl on InputResult to unify error handling

Bug fix:
- Close the command palette when trailing text follows an unrecognised
  command token (e.g. "/bran meow") — previously trapped the user in
  a "No matching commands" dead-end
- Forward Delete, Left, Right, Home, End keys to the textarea while
  the palette is open instead of swallowing them

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The palette now reopens when cursor movement and editing change the
command token back to an unrecognised prefix (e.g. /branch meow →
backspace → /branc meow shows palette filtered to matching commands).

- Keep palette open for unknown prefixes even with trailing text, to
  support the command-correction workflow (/now → /no → select /note)
- Refresh palette state on all insert-mode keys (including cursor
  movement and Delete), not just Char/Backspace

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ScottMorris ScottMorris changed the title Restore TUI command entry and suspend behaviour Restore TUI command entry and suspend, clean up tech debt Mar 18, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ScottMorris
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b7d6c7f4c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…ase matching

- Add accepts_trailing column to COMMAND_TABLE so /where only matches
  its exact form, preventing silent argument loss
- Make slash_command_by_name use exact case matching to stay consistent
  with the core parser (which only recognises lowercase commands)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ScottMorris ScottMorris merged commit cd46f81 into main Mar 18, 2026
5 checks passed
@ScottMorris ScottMorris deleted the fix/issue-33-command-entry-and-suspend branch March 18, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working tui liminal-flow-tui crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Command parsing doesn't stop after command is entered Terminal suspend doesn't work in the TUI

1 participant