Skip to content

Fix scripting terminal editor bugs (scroll, cursor, focus, sync) - #77

Merged
rubensworks merged 12 commits into
master-1.21-ltsfrom
terminal-ux/1-editor-fixes
Oct 18, 2026
Merged

rubensworks merged 12 commits into
master-1.21-ltsfrom
terminal-ux/1-editor-fixes

Conversation

@rubensworks

@rubensworks rubensworks commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Phase 1 of the scripting terminal UX improvements, and the base of a stack: #77 ← #78 ← #79 ← #80 ← #81 ← #82. Each commit fixes one problem.

Each problem below was first reproduced on master-1.21-lts in a dev client driven by clientdevbridge, then checked again with this branch.

Commit Problem on master Result with this PR
Don't reset the editor scroll position on every edit Scrolled to row 10, typed one character: the view jumped to row 0 while the scrollbar stayed in the middle. View stays at row 10. Deleting the whole script while scrolled to the bottom doesn't crash (the #52 scenario).
Keep the cursor visible in the editor Pressing Enter on the last visible line moved the cursor off-screen; it was hidden and the view didn't follow. View scrolls with the cursor.
Don't lose editor focus on unhandled keys Tab, then E, closed the terminal: unhandled keys unfocused the editor. Terminal stays open and typing continues.
Keep trailing newlines when syncing scripts String.split dropped trailing empty lines when syncing. New unit test; it fails on master ("a\n\n" became "a") and passes here.
Start editor line numbers at 1 The gutter starts at 0, while GraalJS errors count from 1 (an error on the second line is reported as script0.js:2:6). Gutter starts at 1.
Don't wrap editor text below the scrollbar Long wrapped lines were drawn underneath the scrollbar. Wrapping stops before the scrollbar.
Make page up and page down move through the editor Both keys were consumed but did nothing. Cursor and view move by one page.
Keep the open script when the scripting terminal is resized Data loss. After resizing the window or changing the GUI scale, the editor was empty, and the next keystroke replaced the whole script with that character (a 40-line file became z). After resizing, the script and cursor are restored, and typing edits the real content.
Use the macOS keys for moving by word and line in the script editor On macOS, Cmd+Left/Right jumped by word, and Option+Left/Right only moved one character, unlike native macOS text fields. On macOS: Option+Left/Right and Option+Backspace/Delete work by word, Cmd+Left/Right go to the line start/end, Cmd+Up/Down to the script start/end. Other platforms keep Ctrl. Covered by unit tests for both platforms; checked in-game on Linux that Ctrl+Left/Right and Ctrl+Backspace still work. I could not run the macOS path in-game, since the dev client runs on Linux.
Don't draw the selection over the bottom border of the script editor The editor has room for part of a 13th row. A selection continuing below the last visible line drew that hidden row's highlight over the bottom border. The highlight stops at the last visible line.
Don't block dragging items over slots in the scripting terminal The editor claimed every mouse drag, so dragging a held stack over inventory slots put the whole stack in one slot (in a chest, the same drag spreads it). The stack is spread over the slots, and dragging in the editor still selects text.
Don't put the cursor on the hidden row below the script editor's last line Clicking the strip below the last visible line put the cursor on the hidden 13th line, drawn over the bottom border. Such clicks go to the last visible line.

About the focus fix

Since WidgetTextArea extends EditBox (bfe27b7, #40), EditBox.charTyped consumes every character into its own unused value while the widget is focused. Typing only worked because each key press unfocused the widget right before its character arrived. This PR keeps focus, so it also stops delegating charTyped to EditBox. I checked that normal typing still works with real key press and character events.

Testing

  • ./gradlew build passes, including the new unit tests.
  • ./gradlew runGameTestServer: all 22 tests pass.

Not fixed here

While testing, the terminal's disk list contained a disk with ID -1. I didn't look into the cause.

🤖 Generated with Claude Code

https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9

Editing reset the first visible row to the top, while the scrollbar
stayed in place. Only reset it when a new script is loaded, and clamp
the scroll position when the text shrinks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
Only up and down arrow keys scrolled the editor, so typing, pressing
enter, home/end and pasting could move the cursor out of view. Scroll to
the cursor after every handled key or typed character, and allow the
cursor to be placed on the empty line after a trailing newline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
Pressing a key the editor doesn't handle, such as tab or a function key,
unfocused it, so a following 'e' closed the terminal. Consume all keys
except escape while focused.

Typing only worked before because of this unfocusing: once the widget
stays focused, EditBox.charTyped consumes every character into its own
unused value. Handle characters without delegating to EditBox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
String.split dropped trailing empty strings, so blank lines at the end of
a script were lost when sending it between client and server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
Script error messages count lines from 1, so a 0-based gutter made them
off by one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
The wrap width didn't account for the scrollbar, so long lines were
drawn underneath it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
Both keys were consumed without doing anything. Move the cursor and the
viewport by one page instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
@coveralls

coveralls commented Oct 17, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 39131310929

Coverage decreased (-0.6%) to 46.751%

Details

  • Coverage decreased (-0.6%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 312 coverage regressions across 2 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

312 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
org/cyclops/integratedscripting/client/gui/component/input/WidgetTextArea.java 207 0.0%
org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java 105 0.0%

Coverage Stats

Coverage Status
Relevant Lines: 2662
Covered Lines: 1364
Line Coverage: 51.24%
Relevant Branches: 908
Covered Branches: 305
Branch Coverage: 33.59%
Branches in Coverage %: Yes
Coverage Strength: 23.24 hits per line

💛 - Coveralls

Resizing the window, or changing the GUI scale, recreated the editor
without the open script. The next key press then replaced the whole
script with what was typed into the empty editor. Restore the open script
and cursor position when the screen is initialized again, and close the
removal dialog if it was open, as its widgets are removed as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
On macOS, Cmd+Left/Right jumped by word, while native text fields use
Option+Left/Right for that, and Cmd+Left/Right to go to the start or end of
the line. The editor now follows these conventions on macOS, including
Option+Backspace to delete a word and Cmd+Up/Down to go to the start or end
of the script. Other platforms keep using Ctrl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
When a selection continued below the last visible line, the highlight of
the hidden next line was drawn over the editor's bottom border.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
The script editor claimed every mouse drag, even outside of it, so
spreading a held stack over inventory slots by dragging put the whole
stack in one slot. The editor now only claims drags it handles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
… line

The editor has room for part of a row below its last visible line.
Clicking or dragging there put the cursor on that hidden line, and the
cursor was drawn over the editor's bottom border. Such positions now go to
the last visible line instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9
@rubensworks
rubensworks merged commit afcdb74 into master-1.21-lts Oct 18, 2026
23 checks passed
@rubensworks
rubensworks deleted the terminal-ux/1-editor-fixes branch October 18, 2026 15:19
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.

3 participants