These changes are compatible with clang-format 16 and will be mandatory
when we eventually bump clang-format version. So, since there are no
real downsides, let's commit them now.
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).
This commit is auto-generated:
$ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
Meta Ports Ladybird Tests Kernel)
$ perl -pie 's/\bDeprecatedString\b/ByteString/g;
s/deprecated_string/byte_string/g' $xs
$ clang-format --style=file -i \
$(git diff --name-only | grep \.cpp\|\.h)
$ gn format $(git ls-files '*.gn' '*.gni')
This moves some stuff around to make LibGUI depend on LibSyntax instead
of the other way around, as not every application that wishes to do
syntax highlighting is necessarily a LibGUI (or even a GUI) application.
Previously, this was reimplementing the same thing by removing all the
document text and then inserting the new text - which internally would
insert each code-point individually and fire change notifications for
each one. This made the "Reformat GML" button very slow, since it not
only had to recalculate the visual lines of the document each time, but
also rebuild the preview GUI.
The reason not to use `set_text()` is that it would throw away the undo
stack, since it always behaved as if the text is a new document. So,
let's add a parameter to disable that behaviour.
This takes the time for reformatting a ~200 line GML file from several
seconds, to basically instantaneous. :^)
When the user hits <Ctrl-Backspace> where the previous content has the
format [Punctuation|Seperator]+ before the cursor, there will be a
size_t index underflow in TextDocument::first_word_break_before,
which returns an invalid word break position with a huge column index
(18446744073709551615, -1 in size_t). The invalid text position later
used for executing RemoveTextCommand will cause a crash.
The while loop condition in TextDocument::first_word_break_before is
not right, the loop will never stop when the target.column() becomes
0 inside.
When you undo some forward delete shortcuts like <Del> or <Ctrl-Del>,
the cursor will be put at the end of the text deleted, while the right
position should be the start of those text.
That's what this class really is; in fact that's what the first line of
the comment says it is.
This commit does not rename the main files, since those will contain
other time-related classes in a little bit.
<Ctrl-Del> will crash when deleting at the end of line
where the next line contains only punctuation and seperator characters,
because TextDocument::first_word_break_after will return a wrong index
of the next word break (+1 bigger than the correct index),
thus RemoveTextCommand will try to remove a out-of-bound text range
causing a crash.
<Ctrl-Backspace> will stuck when deleting at the end of line
which contains only one single character. When finding the
previous word break position starting at column 0 in
TextDocument::first_word_break_before, the code enters an
infinite while loop. The early return should simply fix this.
TextDocument::merge_span_collections() automatically makes sure that the
spans are valid, move forwards, are in order, and do not overlap. This
means we don't have to check these things every time TextEditor paints
the document.
merge_span_collections() now does these checks instead. I am not certain
they are still useful, but someone in the past certainly did. I have
modified them to take advantage of the operator overloads and Formatter
that we now have.
Updated TextDocument and TextEditor to use calls to
`find_grapheme_segmentation_boundary` in order to make "correct-feeling"
deletions on backspace and delete keys being pressed
Note that for traversing words with ctrl+(left or right arrow) on the
keyboard, we want to "skip" some boundaries. Consider the text:
The ("quick") fox can't jump 32.3 feet, right?
Using "|" to denote word break boundaries, we will have:
|The| |(|"|quick|"|)| |fox| |can't| |jump| |32.3| |feet|,| |right|?|
When starting at "The" and using ctrl+right to move rightward in this
text, it is unlikely that users will want to break at every single one
of those boundaries. Most text editors, for example, will skip from the
end of "The" to the end of "quick", not breaking at the parentheses or
opening quotation marks.
We try to mimic such desired behavior here. It likely isn't perfect, but
we can improve upon it as we find edge cases.
Having an alias function that only wraps another one is silly, and
keeping the more obvious name should flush out more uses of deprecated
strings.
No behavior change.
This adds shortcut for inserting a new empty indented line
above/below current cursor position.
- <Ctrl-Return> for inserting line below.
- <Ctrl-Shift-Return> for inserting line above.
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.
One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
If selected text is less than a whole line, usual delete/replace takes
place. Otherwise, if the selected text is a whole line or spans
multiple lines, the selection will be indented.
TextDocument::set_spans() now also takes a "span collection index"
argument.
TextDocument keeps a map between a span collection index and its spans.
It merges the spans from all collections into a single set of spans
whenever set_spans() is called.
This allows us to style a document with multiple layers of spans, where
as previously we only supported a single layer of spans that was set
from the SyntaxHighlighter.
This impacts text editors' ctrl+left, ctrl+shift+right, ctrl+backspace,
etc..
For example, consider the text "Hello world |", pressing
ctrl+backspace each time.
Before: "hello world |"
"hello world|"
"hello |"
"hello|"
"|"
After: "hello world |"
"hello|"
"|"
Note that this breaks a nice symmetry. Doing ctrl+left and then
ctrl+right doesn't necessarily get you to the same place like it use to.
Before: " hello |"
" hello| "
" hello |" // same as initial
After: " hello |"
"|hello "
" hello| " // different from initial
There used to be the silly bug that when the cursor was already at the
end of a span (e.g. because the user just pressed Ctrl-Right), then
Ctrl-Right had no effect.
This bug does not appear with Ctrl-Left because due to the order in
which the spans are iterated, the effective result is always correct.
This patch also makes it more apparent that the algorithm is
unnecessarily inefficient.
This is a helpful option to prevent unwanted side effects, distinguish
between user and programmatic input, etc. Sliders and SpinBoxes were
implementing it idiosyncratically, so let's generalize the API and
give Buttons and TextEditors the same ability.
Previously, pressing 'x' for deletion on an otherwise empty line
insinuated a crash in TextEditor because a nonexistent code point was
accessed -- likewise for visual mode.
In Vim's insert mode, Ctrl-W deletes the word before the cursor, like
Ctrl-Backspace. Unlike Ctrl-Backspace, if only whitespace exists between
the end of the word and the cursor, the word will be deleted with the
whitespace.
To do so, this commit introduces two methods: delete_previous_word() for
TextEditor and first_word_before() for TextDocument, where the former
depends on the latter. delete_previous_word() is then called in
VimEditingEngine.
This replaces ctype.h with CharacterType.h everywhere I could find
issues with narrowing conversions. While using it will probably make
sense almost everywhere in the future, the most critical places should
have been addressed.