mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
5.5 KiB
5.5 KiB
🔧 Auto-Insert Newline After #language Trigger
Problem
When the user typed #python (or other language triggers), the code mode would activate and the IDE box would open. However, if the user continued typing, the text would be added to the same line as #python, which would:
- Break the trigger pattern (e.g.,
#pythonmy codeis not a valid trigger) - Exit code mode
- Render the text as plain text instead of inside the code block
Expected Behavior: After typing #python, the cursor should automatically move to a new line inside the code block, ready for code input.
Solution
Modified the code mode detection useEffect to automatically insert a newline after the language trigger when code mode is activated.
Implementation
// Detect code mode triggers (#language) - can be anywhere in the text
useEffect(() => {
const languageTriggerRegex = /#(javascript|typescript|python|java|cpp|c|go|rust|ruby|php|swift|kotlin|scala|html|css|json|yaml|sql|bash|shell|powershell|r|matlab|lua|perl|haskell|elixir|clojure|dart|jsx|tsx)(\s|$)/i;
const match = value.match(languageTriggerRegex);
if (match && !codeMode) {
// Enter code mode
const language = match[1].toLowerCase();
const triggerStart = match.index || 0;
const triggerLength = match[0].length;
console.log('💻 CODE MODE ACTIVATED:', language, 'at position', triggerStart);
// Check if there's a newline right after the trigger
const charAfterTrigger = value[triggerStart + triggerLength];
const needsNewline = charAfterTrigger !== '\n' && charAfterTrigger !== undefined;
if (needsNewline) {
// Insert a newline after the trigger to move cursor into code block
const beforeTrigger = value.slice(0, triggerStart + triggerLength);
const afterTrigger = value.slice(triggerStart + triggerLength);
const newValue = beforeTrigger + '\n' + afterTrigger;
const newCursorPos = triggerStart + triggerLength + 1; // Position after the newline
console.log('💻 CODE MODE: Inserting newline after trigger');
onChange(newValue, newCursorPos);
// Set cursor position in textarea
if (hiddenTextareaRef.current) {
setTimeout(() => {
hiddenTextareaRef.current?.setSelectionRange(newCursorPos, newCursorPos);
setCursorPosition(newCursorPos);
}, 0);
}
}
setCodeMode({
active: true,
language: language,
startPos: triggerStart + triggerLength + (needsNewline ? 1 : 0) // Account for the newline
});
} else if (!match && codeMode) {
// Exit code mode if trigger is removed
console.log('💻 CODE MODE DEACTIVATED');
setCodeMode(null);
}
}, [value, codeMode, onChange]);
How It Works
Step-by-Step Flow
-
User types
#python- The regex matches the trigger
- Code mode is not yet active (
!codeMode)
-
Check for existing newline
- Look at the character immediately after the trigger
needsNewline = charAfterTrigger !== '\n' && charAfterTrigger !== undefined
-
Insert newline if needed
- Split the value:
beforeTrigger+\n+afterTrigger - Calculate new cursor position:
triggerStart + triggerLength + 1 - Call
onChangewith the new value and cursor position
- Split the value:
-
Update cursor in textarea
- Use
setSelectionRangeto move the cursor - Use
setTimeoutto ensure it happens after the value update
- Use
-
Set code mode
startPosaccounts for the inserted newlinestartPos = triggerStart + triggerLength + 1(if newline was inserted)
Before the Fix
User types: #python
Value: "#python"
Cursor: at position 7 (after "n")
User continues typing: "def hello():"
Value: "#pythondef hello():" ❌ Breaks the trigger!
After the Fix
User types: #python
Value: "#python"
Trigger detected → Insert newline
Value: "#python\n"
Cursor: at position 8 (after "\n")
User continues typing: "def hello():"
Value: "#python\ndef hello():" ✅ Code inside the block!
Edge Cases Handled
- Newline already exists: If the user manually types
#python\n, we don't insert another newline - End of input: If
#pythonis at the very end with nothing after, we still insert a newline - Inline triggers: Works with text before the trigger (e.g.,
"some text #python") - Cursor positioning: Ensures the cursor is correctly positioned after the newline
Testing
To verify the fix:
-
Basic Test:
- Type
#python - ✅ Code box opens
- ✅ Cursor automatically moves to a new line
- ✅ Continue typing - text appears inside the code block
- Type
-
Inline Test:
- Type
some text #python - ✅ Code box opens after "some text"
- ✅ Cursor moves to new line
- ✅ Code appears in the block
- Type
-
Manual Newline Test:
- Type
#pythonthen press Enter manually - ✅ Only one newline exists (no duplicate)
- ✅ Code mode still works correctly
- Type
Related Files
ui/desktop/src/components/RichChatInput.tsx- Main implementation
Commits
commit fb635770ffa
Auto-insert newline after #language trigger to move cursor into code block
Benefits
- Better UX: Users don't need to manually press Enter after typing the trigger
- Prevents errors: Can't accidentally break the trigger by continuing to type
- Natural flow: Typing feels seamless - trigger activates and you're immediately ready to code
- Consistent behavior: Works the same way regardless of where the trigger appears in the text