Skip to content

feat: select first command argument on autocomplete completion#8046

Open
dclstn wants to merge 1 commit into
masterfrom
feature/command-arg-autocomplete-selection
Open

feat: select first command argument on autocomplete completion#8046
dclstn wants to merge 1 commit into
masterfrom
feature/command-arg-autocomplete-selection

Conversation

@dclstn

@dclstn dclstn commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

What

When completing a chatbot command that takes arguments via the command autocomplete, the first argument placeholder is now inserted and selected, so the next keystroke replaces it.

  • !shoutout → completes to !shoutout [user] with [user] selected → typing immediately overwrites it.
  • Commands with no arguments are unchanged: !command with the caret at the end.

Only the first argument is inserted (commands can have several — [user]/[word]/[phrase]); the placeholder text is reused from ArgumentDisplayTextByArgumentType so it stays consistent with the autocomplete row subtitle. Twitch only for now.

How

twitch.setChatInputValue(text, shouldFocus, selection?) gains an optional selection ({start, end} character offsets into text). When a range is requested, it's applied through Slate rather than the controlled value setters.

This matters because Twitch's chat input is a controlled Slate editor whose value prop reaches editor.children asynchronously. Setting the value and then selecting [start, end) immediately lands the range on stale (usually empty) content — an invalid selection that corrupts the next keystrokes (e.g. inserting newlines). A raw DOM selection doesn't work either: the controlled re-render collapses it back to a caret.

So for the range case we drive everything through Slate synchronously — select-all → insertText(text) → select(range) — which populates the content before selecting and keeps Twitch's value in sync via onChange. Collapsed-caret callers (emote menu, tab completion, mod cards, no-arg commands) are unchanged.

Testing

Verified live on twitch.tv/popout/<channel>/chat: after completion the input shows !shoutout [user] as a single block with a valid selection over [user], and a keystroke replaces it cleanly (!shoutout x) with no extra blocks/newlines.

🤖 Generated with Claude Code

When completing a chatbot command that takes arguments, insert the first
argument placeholder (e.g. `!shoutout [user]`) and select it so the next
keystroke replaces it. Commands without arguments keep the previous behavior
(`!command ` with the caret at the end).

`twitch.setChatInputValue` gains an optional `selection` ({start, end}) arg.
For a range selection the value and selection are applied through Slate
(select-all -> insertText -> select range), because the controlled value
setters update the editor asynchronously and selecting right after would land
the range on stale/empty content, producing an invalid selection that corrupts
typing. Slate's onChange keeps Twitch's value in sync. Collapsed-caret callers
are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread src/utils/twitch.js
return;
}

// TODO: remove setSelectionRange branch after legacy slate is gone

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Am I safe to remove this legacy selection range?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant