Identifying an editor bug by inspecting wrapped Rust objects in Glamorous Toolkit
For quite some time we had an issue
in the text editor related to the cursor getting stuck when it was at the end of a paragraph. It was annoying, but we did not know how to address it and it stayed open for half a year.
We knew that the issue was likely due to something in the lower levels, but we did not know what it could be. We did not even have a hypothesis.
Indeed, Glamorous Toolkit
relies on Rust plugins. For example, the current implementation of the text editor is based on a wrapper over Rust objects. This is nice because it allows us to reuse external libraries. At the same time, to find issues visible in the high level editor, we need to understand how the low level objects work. To this end, we need at least the ability to inspect.
It was only until we extended the inspector to allow us to explore Rust objects that we could find the issue. The screenshot below shows the actual exploration that led to the bug resolution.
instance shows an
Info view that is actually served by the wrapped Rust object. We can see how selecting the
Line ranges item, leads to an inspector over a Rust object.
So, what was the issue? Looking at the line ranges, we notice that index
is both the end of the first interval, and the beginning of the second interval. Once we saw this, it became obvious that 6 cannot belong in both. It turned out that the end of the interval was expected by the low level library to be exclusive, while our implementation assumed it is inclusive. Once we saw the problem, the fix
was rather straightforward.
The differentiator between not knowing how to approach the problem at all and actually solving it was just a matter of seeing the problem in the first place. That is the power of Moldable Development.
Reproducing the exploration
Consider this editor:
stream := BlTextStream new.
stream glamorousRegularFont fontSize: 40.
putAll: 'This is a piece of text in an editor. The editor is made out of '.
foreground: Color blue;
putAll: ' paragraph objects. These paragraph objects have correspondent objects in the '.
foreground: Color red;
stream next putAll: ' world which can be inspected seamlessly, too.'.
editor := BrEditor new
text: stream contents;
aptitude: BrGlamorousRegularEditorAptitude new
The editor is made out of paragraph elements. In the current implenentation they are instances of
. To draw themselves, these objects depend on
instances that are actually wrappers over Rust objects.
How does it work? Follow this:
First, inspect the editor above to make it render.
Then let's inspect one of the children and access the lower
editor children first buildParagraph layoutWithWidth: 400
The resulting inspector has an
R icon. If you press it, you will get to the Rust object.