summaryrefslogtreecommitdiff
path: root/src/highlighters.cc
AgeCommit message (Collapse)Author
2025-07-08Replace on_scope_end with CTAD with OnScopeEnd directlyMaxime Coste
2025-07-08Replace std::unique_ptr with a custom implementationMaxime Coste
<memory> is a costly header we can avoid by just implementing UniquePtr ourselves, which is a pretty straightforward in modern C++, this saves around 10% of the compilation time here.
2025-06-28Fix wrap interaction with show-whitespaces and test word wrapping moreMaxime Coste
Consider atom boundaries as word boundaries, which should be correct du to passes ordering. Fixes #5350
2025-06-26Rework WrapHighlighter to take replaced ranges into accountMaxime Coste
Replaced ranges will count towards the wrapping column but will not be split. Fixes #4883
2025-06-25Introduce a Replace HighlightPass that runs before WrapMaxime Coste
For WrapHighlighter to be able to take ReplaceRangesHighlighter into account, it needs to run afterwards, moreover, moving TabulationHighlighter to the replace pass means we should be able to remove any tabulation specific handling from WrapHighlighter Also move ShowWhitespaceHighlighter to this pass as it is designed to replace TabulationHighlighter by running before (as builtin highlighters run after non builtin ones for each passes)
2025-06-25Rework highlighting management of cursor positionMaxime Coste
Move the whole responsibility of making the cursor visible to the window, removing cursor_pos from the display setup and resolving the cursor location by finding it in the display buffer afterwards. This simplifies hightlighters' do_compute_display_setup as they do not need to compute the cursor location. Highlighting may run on more lines than necessary after this change but this should be a minor performance hit.
2024-11-04Highlight all atoms for the line regardless of has_buffer_rangeMaxime Coste
This changes the behaviour with say line numbers and other line flags, but can be opted out by using final faces Fixes #5253
2024-08-16include headers cleanupAdrià Arrufat
2024-08-12Move debug utils to debug.hh/debug.ccMaxime Coste
Lots of code includes buffer_utils.hh just for write_to_debug_buffer which pulls many unnecessary dependencies. Reorganise to reduce compile times.
2024-06-23Fix trailing whitespacesMaxime Coste
2024-06-23Allow individual show-whitespace options to be turned offTobias Pisani
This is especially useful to use the indent guides without the other parameters, but in general it can be a useful option. It could be worth considering cleaning up these options to default off instead, but the default also seems useful, so i consider this ok, as it might be the more advanced usecase.
2024-04-12Make removing an unknown highlighter an errorMaxime Coste
Fail instead of silently doing nothing, this makes it easier to toggle highlighters using a try/catch
2024-03-27Slight code cleanup in the DynamicRegexHighlighterMaxime Coste
2024-03-27Add -indent option to show-whitespace highlighterTobias Pisani
A couple of semi-opinionated choices were made in this implementation: 1. The guide is hidden in the first column. 2. The indent guides are highlighted using a new `WhitespaceIndent` face. 3. Nothing is done to continue the guide through empty lines. I believe this to be the correct approach, at least as long as it is kept as a part of the show-whitespaces highlighter. However some people's oppinion may differ, and if so, that could be implemented. 4. The guides default to on, like the other show-whitespace options. Default character is "│". 5. Spaces between the indent guides are currently highlighted as other spaces. Other reasonable options would be no replacement, -tabpad, or a similar -indentpad. 6. Guides are disabled by passing `-indent ""`. 7. Indent guides are separate from tab highlighting. Additionally, we could consider adding a separate face for the "current" indent level as many editors do, but this is a bit harder in kakoune because of multiple selections. Closes #2323
2024-03-22Do not generate more lines to display than window sizeMaxime Coste
The wrap highlighter was pulling all lines until the cursor, regardless of whether the cursor was going to be made visible, this could lead to a display buffer containing much more lines than the actual viewport which eventually could lead to menu being anchored out of view that was leading to past-the-end buffer accesses. Fix the wrap higlighter not to pull lines up to the cursor when it is not tasked with making the cursor visible, and always trim the eventual extra lines after highlighting. Fixes #5118
2024-01-30Support -after switch for flag-lines highlighterMaxime Coste
2023-11-05Replace snprintf with format_toMaxime Coste
2023-11-03Use explicit target types for gather calls to bypass clang regressionMaxime Coste
Since clang-16 there has been a regression in the P0522R0 support. (Bug report at https://github.com/llvm/llvm-project/issue/63281) Closes #4892
2023-09-08Merge remote-tracking branch 'divarvel/show-trailing-whitespace'Maxime Coste
2023-09-02Do not make cursor visible after mouse scrolling and view commandsMaxime Coste
ensure cursor is visible after user input except if the command implementation opted-out. Hooks and timers should not enforce visible cursor. PageUp/PageDown and `<c-f>` / `<c-b>` commands still move the cursor as this seemed a desired behaviour.
2023-08-15Fix segfault when adding an invalid default-region highlighterChris Webb
RegionsHighlighter::create_region() validates the highlighter type argument but RegionsHighlighter::create_default_region() assumes it is correct, segfaulting from dereferencing a null pointer if the given type isn't in the highlighter registry HashMap. @PJungkamp reported this in https://github.com/mawww/kakoune/issues/4959 with a simple recipe to reproduce: :add-highlighter shared/test regions :add-highlighter shared/test/ default-region invalid highlighter :add-highlighter window/test ref test Validate the type argument in RegionsHighlighter::create_default_region() in the same way as RegionsHighlighter::create_region().
2023-06-20Fix invalid access of display line endMaxime Coste
When a line only contains non-range atoms we can end-up accessing past the end atom. Add a test that shows the issue when run with valgrind, it is unfortunately quite hard to trigger a crash because the invalidly accessed byte usually leads to the correct code path being taken (when != DisplayAtom::Range) so we have only 1 in 255 chance of triggerring a crash. Fixes #4927
2023-06-19Fix highlighters being applied to empty display buffersMaxime Coste
In some cases such as with folding we can end-up with regions not having any atoms to highlight which can trigger a crash as we assume display buffers not to be empty Fixes #4926
2023-06-14Add a -previous switch to show-matching highlighterMaxime Coste
This switch makes show-matching fallback to the character preceeding the cursor if the character under the cursor is not a matching character, which should make show-matching more useful in insert mode.
2023-06-12Fix one missing face pre-parsingMaxime Coste
2023-06-12Store region pointers instead of names in the RegionsHighlighter cacheMaxime Coste
Cache get fully invalidated whenever the regions change, so there should be no risk of referencing a removed region, and this removes one hash map lookup for every region in the displayed buffer range.
2023-06-12Trim display lines before the colorize passMaxime Coste
Colorizing long lines can be costly, remove all the invisible atoms earlier. Also optimize ForwardHighlighterApplier further by trimming empty lines.
2023-06-10Pre-parse face specs in HighlightersMaxime Coste
Re-parsing face specs can be expensive as highlighters can be called many times during a redraw with nested regions.
2023-06-09Speed up regions highlighting on files with big linesMaxime Coste
Range atoms should always appear in order, so we can iterate a single time through the display lines and display atoms while applying hightlighters to regions
2023-02-17Complete arguments to "echo -to-file"Johannes Altmanninger
Including this here because grandparent parent commit broke completions for "edit -fifo".
2023-01-23Fix crash in TabulationHighlighter when wrapping just after a tabMaxime Coste
2022-12-15Speed up expand_unprintable by avoiding BufferIteratorMaxime Coste
Using BufferIterator adds overhead, but we know that DisplayAtoms cannot span multiple buffer lines and hence we can directly iterate using char pointers.
2022-12-15Support adding ByteCount to void/char pointers without castingMaxime Coste
2022-12-15Optimize TabulationHighlighterMaxime Coste
2022-12-06Cleanup expand_unprintable and avoid calling iswprint on base asciiMaxime Coste
2022-11-28Fix pasting after when selections are overlappingMaxime Coste
With overlapping selections, pasting after breaks assumption of SelectionList::for_each as our changes are no longer happening in increasing locations. We hence cannot rely on the ForwardChangeTracker in that case and have to rely on the more general (and more costly) ranges update logic. This interacts poorly with paste linewise pastes and we try to preserve the current behaviour by tracking the last paste position. Overall, this change really begs for overlapping selections to be removed, but we will fix them like that for now. Fixes #4779
2022-10-17Fix splitting of display atoms accross multi-columns codepointMaxime Coste
Honor the split request by inserting an empty atom to make sure client code can assume splitting does replace one atom with two Fixes #4753
2022-09-17Fix quadratic runtime when updating region highlighter matchesJohannes Altmanninger
Running %sYeti<ret>casdf on file [example.journal.txt](https://github.com/mawww/kakoune/issues/4685#issuecomment-1193243588) can cause noticeable lag. This is because we insert text at 6000 selections, which means we need to update highlighters in those lines. The runtime for updating range highlighters is quadratic in the number of selections: for each selection, we call on_new_range(), which calls add_matches(), which calls std::rotate(), which needs needs linear time. Fix the quadratic runtime by calling std::inplace_merge() once instead of repeatedly calling std::rotate(). This is works because ranges are already sorted. I used this script to benchmark the improvements. (In hindsight I could have just used "-ui json" instead of tmux). #!/bin/sh set -ex N=${1:-100} kak=${2:-./kak.opt} for i in $(seq "$N") do echo -n "\ 2022-02-06 * Earth expense:electronics:audio 116.7 USD liability:card -116.7 USD 2022-02-06 * Blue Yeti USB Microphone expense:electronics:audio 116.7 USD liability:card -116.7 USD " done > big-journal.ledger echo > .empty-tmux.conf 'set -sg escape-time 5' test_tmux() { tmux -S .tmux-socket -f .empty-tmux.conf "$@" } test_tmux new-session -d "$kak" big-journal.ledger test_tmux send-keys '%sYeti' Enter c 1234567890 sleep .2 test_tmux send-keys Escape while ! test_tmux capture-pane -p | grep 123 do sleep .1 done test_tmux send-keys ':wq' Enter while test_tmux ls do sleep .1 done rm -f .tmux-socket .empty-tmux.conf This script's runtime used to grow super-linearly but now it grows linearly: kak.old kak.new N=10000 1.142 0.897 N=20000 2.879 1.400 Detailed results: $ hyperfine -w 1 './bench.sh 10000 ./kak.opt.'{old,new} Benchmark 1: ./bench.sh 10000 ./kak.opt.old Time (mean ± σ): 1.142 s ± 0.072 s [User: 0.252 s, System: 0.059 s] Range (min … max): 1.060 s … 1.242 s 10 runs Benchmark 2: ./bench.sh 10000 ./kak.opt.new Time (mean ± σ): 897.2 ms ± 19.3 ms [User: 241.6 ms, System: 57.4 ms] Range (min … max): 853.9 ms … 923.6 ms 10 runs Summary './bench.sh 10000 ./kak.opt.new' ran 1.27 ± 0.09 times faster than './bench.sh 10000 ./kak.opt.old' $ hyperfine -w 1 './bench.sh 20000 ./kak.opt.'{old,new} Benchmark 1: ./bench.sh 20000 ./kak.opt.old Time (mean ± σ): 2.879 s ± 0.065 s [User: 0.553 s, System: 0.126 s] Range (min … max): 2.768 s … 2.963 s 10 runs Benchmark 2: ./bench.sh 20000 ./kak.opt.new Time (mean ± σ): 1.400 s ± 0.018 s [User: 0.428 s, System: 0.083 s] Range (min … max): 1.374 s … 1.429 s 10 runs Summary './bench.sh 20000 ./kak.opt.new' ran 2.06 ± 0.05 times faster than '../repro.sh 20000 ./kak.opt.old'
2022-08-21Bypass RegexIterator in RegionsHighlighter::add_matchesMaxime Coste
2022-08-20Refactor RegionsHighlighter to share regexesMaxime Coste
Instead of storing regexes in each regions, move them to the core highlighter in a hash map so that shared regexes between different regions are only applied once per update instead of once per region Also change iteration logic to apply all regex together to each changed lines to improve memory locality on big buffers. For the big_markdown.md file described in #4685 this reduces initial display time from 3.55s to 2.41s on my machine.
2022-07-21Use menu behavior for add-highlighter/remove-highlighter completionJohannes Altmanninger
This means that typing :add-highlighter g c 80 results in :add-highlighter global/ column 80 Paths for add-highlighter do not get the menu behavior because we want to be able to type "global/foo" even if "global/foobar" exists.
2022-07-19Remove out-of-date column computation in show-whitespacesMaxime Coste
Now that we compute display buffer on whole lines, it does not make sense to compute the tab padding based off the window column position Fixes #4674
2022-07-13Re-work line trimming to fix issues with column highightersMaxime Coste
Instead of triming only buffer ranges, add a trim_from method to display line to keep the initial N columns, we know how many columns are used by non-trimable widgets in DisplaySetup::widget_columns so we can just pass this. Also restore the previous logic for face merging Fixes #4670
2022-07-12Fix past-the-eol column highlighter getting highlighted as buffer rangeMaxime Coste
Make the column highlighter faces final, and change final logic to give precedence to the base face when both the base and new face are final. Fixes #4669
2022-07-11Fix buffer location of column highlighter's past-eol atomsMaxime Coste
Using buffer end was confusing Window::display_position that assumes display atom buffer locations are always increasing.
2022-07-10Refactor highlighting logicMaxime Coste
Always start with full buffer lines and trim the display buffer at the very end, treat non-range display atoms as non-trimable in that case and keep track of how many columns are occupied by "widgets" such as line numbers or flags. Fixes #4659
2021-11-21Use std::remove_cvref instead of std::decayMaxime Coste
2021-11-05src highlighters: Factorise docstringsFrank LENORMAND
Fixes #4367.
2021-11-04src highlighters: Sort instantiationsFrank LENORMAND
2021-03-31fix show-whitespace: add missing NNBSP characternojhan
- Add the Narrow No-Break SPace (0x202F, NNBSP) to the list of handled spaces in the show-whitespace highlighter. - Do not add an aditional option, just handle it like NBSP, with the same highlight character.