Skip to content

feat(app,tui): slash picker on any line and multi-command prompts#34710

Closed
mayankkg wants to merge 2 commits into
anomalyco:devfrom
mayankkg:fix-slash-multiline-trigger
Closed

feat(app,tui): slash picker on any line and multi-command prompts#34710
mayankkg wants to merge 2 commits into
anomalyco:devfrom
mayankkg:fix-slash-multiline-trigger

Conversation

@mayankkg

@mayankkg mayankkg commented Jul 1, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Problem

The slash command picker (/) only opened when / was the very first character of the entire input (position 0). The regex was rawText.match(/^\/(\S*)$/) — anchored to the whole string. This made two things impossible:

  1. Typing context text on one line and a slash command on the next line
  2. Composing multiple slash commands in a single prompt

Changes

Fix: picker triggers at the start of any line (web + TUI)

Web UI (prompt-input.tsx): changed the regex from a whole-string anchor to a cursor-aware line-start match that mirrors the existing @ trigger:

// before
const slashMatch = rawText.match(/^\/(\S*)$/)
// after
const slashMatch = rawText.substring(0, cursorPosition).match(/(?:^|\n)\/(\S*)$/)

TUI (autocomplete.tsx): replaced value.startsWith('/') with a lastIndexOf('\n') line-start computation. store.index is now set to lineStart so the filter and hide logic work correctly on any line.

Feature: multi-command prompts

Each slash command goes on its own line. The picker opens per-line. On submit, if every non-empty line is a known custom command they fire sequentially.

transient-state.ts: added slashTriggerOffset: number to record where the / was in the editor text.

handleSlashSelect in prompt-input.tsx: previously called setEditorText(text) which replaced the entire editor. Now splices only the /filter token at slashTriggerOffset, keeping the rest of the editor intact.

submit.ts: added a multi-command path before the existing single-command check. Parses all lines, verifies each resolves to a known command, fires them sequentially. Single-command and plain-prompt paths are fully unchanged.

Path collision handling

/Users/foo/bar mid-sentence does not trigger the picker. The rule is / must be the first non-whitespace character on its line — matching how Notion, Linear, and Slack handle slash commands.

How did you verify your code works?

  • Ran the app dev server (packages/app vite dev against the running opencode backend on port 4096)
  • Confirmed / on an empty input opens the picker (existing behaviour unchanged)
  • Confirmed typing context text, pressing Shift+Enter, then typing / opens the picker on the second line
  • Confirmed selecting a command on line 2 inserts it there without clearing line 1
  • Confirmed typing /update-docs on line 1, Shift+Enter, /code-review on line 2, then Enter fires both commands sequentially
  • Confirmed /Users/foo/bar mid-sentence does not open the picker

Screenshots / recordings

UI change — picker now opens on the second line after context text on the first line.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

mayank-db added 2 commits July 1, 2026 08:21
…ion 0

Previously both the web UI and TUI only opened the slash command picker
when / was the very first character of the entire input (position 0).
This made it impossible to compose multi-line prompts that combine
context text on earlier lines with a slash command on a new line.

Web UI (prompt-input.tsx):
- Was: rawText.match(/^\/(\S*)$/) — anchored to whole-string start+end
- Now: rawText.substring(0, cursorPosition).match(/(?:^\|\n)\/(\S*)$/)
  Slices to cursor first (same as @ trigger) and matches / at the start
  of any line, not just the absolute start of the input.

TUI (autocomplete.tsx):
- Was: value.startsWith('/') — only triggered at position 0
- Now: finds the current line start via lastIndexOf('\n'), then checks
  if that line starts with /. store.index is set to lineStart so the
  filter correctly reads text from / to cursor.
- Hide condition updated to check value.slice(store.index) instead of
  the whole value, so it works regardless of which line the / is on.

Path collision handling: / mid-sentence (e.g. 'see /Users/foo/bar') does
NOT trigger the picker because there is non-whitespace content before /
on the same line. Only / at the first non-whitespace position of a line
opens the picker, matching the intent of every other slash-command UI.

AI-Assist: no
Allows composing multiple slash commands in a single prompt by putting
each command on its own line. The picker now opens whenever / appears
at the start of any line (not just position 0), and selecting a command
inserts it at that line without clearing the rest of the editor.

transient-state.ts:
- Add slashTriggerOffset: number — records the character offset of the
  / that opened the picker so handleSlashSelect knows which token to
  replace.

prompt-input.tsx (handleInput):
- When slashMatch is found, compute slashOffset from match.index and
  store it as slashTriggerOffset before opening the picker.

prompt-input.tsx (handleSlashSelect):
- Fast path unchanged when the editor is empty (triggerOffset 0, cursor
  at end of only content).
- Multi-command path: reconstruct fullText from prompt parts, splice in
  the chosen command between the before-slash content and anything after
  the cursor, then restore cursor to end of the inserted token.

submit.ts:
- Before the existing single-command check, parse all non-empty lines.
- If every line resolves to a known slash command, fire them
  sequentially via fireSequentially(index) recursion.
- Single-command and plain-prompt paths are untouched (backward compat).

tui/autocomplete.tsx (from previous commit):
- Already updated to trigger on any line start and track lineStart as
  store.index so the filter and hide logic work correctly.

AI-Assist: no
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Hey! Your PR title feat(app,tui): slash picker on any line and multi-command prompts doesn't follow conventional commit format.

Please update it to start with one of:

  • feat: or feat(scope): new feature
  • fix: or fix(scope): bug fix
  • docs: or docs(scope): documentation changes
  • chore: or chore(scope): maintenance tasks
  • refactor: or refactor(scope): code refactoring
  • test: or test(scope): adding or updating tests

Where scope is the package name (e.g., app, desktop, opencode).

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • No issue referenced. Please add Closes #<number> linking to the relevant issue.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, here are potentially related PRs to monitor:

Related PRs (not exact duplicates):

  1. #27632 - fix(tui): insert skill name without wiping existing prompt text

    • Directly related: addresses the same issue of preserving prompt text when inserting commands, which is core to the multi-command feature in this PR
  2. #32715 - fix(tui): preserve text when editing slash command with argument

    • Related: also about preserving text when working with slash commands
  3. #33904 - fix(tui): ignore bare slash autocomplete submit

    • Related: handles edge cases with slash command parsing
  4. #33019 - feat(tui): add inline skill picker

    • Related: involves picker functionality and command selection

Note: PR #34710 (the current PR) is the primary result in all searches, indicating it's likely a new, unique contribution. The related PRs above address complementary issues with slash command handling and text preservation.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jul 1, 2026
@github-actions github-actions Bot closed this Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants