Skip to content

Edit Logic Programmer expressions in place - #1768

Closed
rubensworks wants to merge 7 commits into
feature/expression-textfrom
feature/expression-editor
Closed

rubensworks wants to merge 7 commits into
feature/expression-textfrom
feature/expression-editor

Conversation

@rubensworks

@rubensworks rubensworks commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Stacked on #1767 (feature/expression-text), which is itself stacked on #1766, so this PR only shows the commits on top of it. It should be merged after both, or retargeted once they are in. It started as an experiment on its own branch, so #1767 can still go in without it.

This replaces the separate text mode of #1767 with a single view: the colored expression in the panel can be edited directly, without an Edit button.

Screenshots from the dev client: https://claude.ai/artifact/Fwyz9rB9VqPMmZY6FYasuF

How it works

  • One view. The panel shows the expression as before: the open operator in yellow, errors in red, empty slots in gray, and the part of a hovered slot highlighted. Clicking the text places the caret and opens the operator under it in the slots, so text and slots follow each other.
  • Drafts. Typing makes a draft. The text before and after what was typed keeps its colors, except for the red of errors, as the footer then shows the type of the typed text, or the parse error with its line and column, which is also underlined in the text. Enter applies it, Escape reverts it, and Shift+Enter adds a line. Applying a different root operator switches the element, as in Edit Logic Programmer expressions as text #1767. Applying keeps the open operator in the slots if it still exists. While there is a draft, slots, parameters and tabs ignore clicks, so the draft and the slots cannot both change the expression. Hiding the panel reverts the draft.
  • Undo and Redo go back and forth through up to 64 changes to the expression, from slots, parameters and text alike, also across a change of root operator. They are reset when another element or card is opened. Ctrl+Z and Ctrl+Y (or Ctrl+Shift+Z) work too.
  • Toolbar. Undo, Redo and Copy are 12 px icon buttons right of the title. During a draft, a cross (revert, Esc) and a check (apply, Enter) take their place, and the check is disabled while the text does not parse. The font has no symbols for these, so the icons are drawn pixel by pixel, in the colors and with the shadow of the text of text buttons. Copy shows a check for a moment.
  • Panel cleanup compared to Edit Logic Programmer expressions as text #1767:
    • No row of buttons below the expression, so the expression gets that height.
    • No "Parameters" label. The chips sit under the title, followed by a + that reads + Parameter while there are none, and that is hidden at the limit of 8.
    • No "Type:" prefix or tooltip in the footer. The type is recognizable by its colors.
    • The same 3 px margin on the left as on the top and right. The main texture covers the left of the panel, so the content now starts 1 px further right.

What changed

  • ExpressionTextField (new, client only): vanilla MultilineTextField as the text model, drawn with a color and background per character, a selection, a blinking caret, an underline for parse errors and a scrollbar. Vanilla's edit boxes can only draw a single color. It is kept in the container, so it survives the panel being recreated when navigating. followChanges carries the colors of the printed text over to a draft, for the characters before and after the part that changed.
  • ExpressionHistory (new): undo and redo stacks. Changes are recorded by observing the expression while rendering, so no action needs to know about it.
  • ExpressionPrinter.tokenizeExact: the exact text as tokens with the path of their node, which printExact now joins. This maps each character to its node, for colors and for navigating from the caret.
  • OperatorLPElement.setExpression(expression, editPath) keeps the open operator. ContainerLogicProgrammerBase replaces the text and one-step undo of Edit Logic Programmer expressions as text #1767 with the text field and the history, which setActiveElement resets, except while a set action itself switches the element.
  • ButtonIcon (new): a CyclopsCore ButtonExtended with a pixel icon.
  • OperatorLPElementRenderPattern: the merged view, its input (keys, clicks, selecting by dragging, scrolling), the toolbar, and the parameter row. The hover hint of Edit Logic Programmer expressions as text #1767 is gone.
  • Lang: Edit, Cancel and Copied are gone, Revert, Redo and + Parameter are new. Book: the paragraphs on parameters and on text describe the new buttons and editing in place.

Things to decide on

  • Shift+Enter line breaks do not survive Enter, since the text is printed again from the expression tree. Either drop Shift+Enter, or let the printer break long expressions over lines.
  • The lock during a draft is silent. Clicks on slots, chips and tabs do nothing until the draft is applied or reverted, without saying why. Now that a draft keeps its colors, a draft that is not focused looks almost the same as the expression itself, apart from the cross and check in the toolbar.
  • Hiding the panel throws a draft away, as a hidden draft would otherwise keep the slots locked.

Testing

  • Unit tests: 982 pass, including 4 new in TestExpressionHistory (undo and redo, a new change dropping redo, an equal expression not being a change, and the size limit and clearing) and 5 new in TestExpressionTextField (colors kept around typed, deleted and replaced text, and with repeated characters).
  • Gametests: all 1054 pass, including the new testLogicProgrammerSetExpressionKeepsOpenOperator.
  • In the dev client (screenshots above), I checked:
    • clicking the text placing the caret and opening that operator in the slots
    • typing a draft, applying it with Enter and with the check, and the open operator staying open
    • the open operator staying yellow around a typed character, also with a parse error
    • a parse error underlined, with the check disabled, and reverting with Esc and with the cross, without closing the GUI
    • selecting by dragging, and replacing everything with (a: integer) -> a + #5, which switched to Arithmetic Addition with the real #5 card in its slot
    • undo and redo with the buttons, over text changes, slot changes and a change of root operator
    • slot clicks being ignored during a draft, hiding the panel reverting it, and Clear or loading a card resetting the history
    • Copy, and its check
    • the parameter row without parameters, with three, with a long name that is cut off and wraps, and at the limit of 8
    • dragging a parameter onto a slot
    • the margins, measured in a screenshot
  • Not exercised in the client: Ctrl+Z, Ctrl+Y and Shift+Enter. clientdevbridge sends modifier bits, but vanilla checks the physical key state with Screen.hasControlDown() and Screen.hasShiftDown(), so I used the buttons instead.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y

The text of the expression in the panel can now be edited directly,
instead of switching to a separate text box with an Edit button. It keeps
the colors of the read-only view, and clicking a part places the caret
and opens that operator in the slots. Typing makes a draft: Enter applies
it, Escape reverts it, and slots wait until then. Applying keeps the open
operator if it is still there.

Undo and Redo go back and forth through all changes to the expression,
from slots, parameters and text alike, and are reset when another
expression is opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
The font has no undo, redo or copy symbols, so the icons are drawn
pixel by pixel, in the same colors and with the same shadow as the text
of text buttons. Copying briefly shows a check mark instead of the
"Copied" text. The hint when hovering the expression is removed, as
the button tooltips and the book already explain the editor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
With icons, Undo, Redo and Copy fit right of the title, so the row of
buttons below the expression is removed and the expression gets that
height instead. Revert and Apply become a cross and a check there, with
tooltips naming Esc and Enter. The add parameter button moves down a
pixel so its plus is in line with the Parameters label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
The label sat right under the title like a second heading, while
parameters are optional. The chips now sit under the title on their
own, followed by a plus to add another, which reads "+ Parameter" while
there are none. Chips are as tall as the button, so they line up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
The main texture covers the left of the panel, so its content had a
margin of 2 pixels on the left and 3 on the top and right. It now starts
one pixel further right. The footer shows only the type, recognizable by
its colors, and names it as the type in its tooltip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHtucHo4Qy2pTfBMgeE54y
The type is recognizable by its colors, so the tooltip only got in the
way when moving the mouse over the footer. Errors and text that does not
fit still show a tooltip.

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

coveralls commented Oct 17, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 48.344% (-0.4%) from 48.735% — feature/expression-editor into feature/expression-text

The whole text turned plain as soon as a character was typed, which hid
the open operator and the empty slots. The text before and after what
was typed now keeps its colors. Errors are left out while typing, as the
footer then shows the errors of the draft.

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

Copy link
Copy Markdown
Member Author

Combined into #1766: its branch was fast-forwarded to include these commits and those of #1767, so this PR is closed.


Generated by Claude Code

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