Commit Graph

5681 Commits

Author SHA1 Message Date
Maxime Coste
fa060c2a17 Fix fatal exception when checking if buffer needs to be reloaded
If, for example, the buffer path now is a directory, MappedFile will
throw on construction. Using a try block to explicitely allow errors
fixes the issue.
2023-02-21 16:59:16 +11:00
Maxime Coste
be49f36205 Only decode current codepoint once per step
Instead of potentially decoding for each thread, always decode as
its only slightly slower than finding next codepoint (which will
be necessary anyway) and pass the codepoint to each thread.
2023-02-19 12:15:33 +11:00
Maxime Coste
2b74cd4b59 Remove instructions from ExecConfig
We can just compute whenever we reset last_step, which does not happen
often and we know `forward` at compile time anyway
2023-02-19 11:46:17 +11:00
Maxime Coste
f115af7a57 Optimize Regex CharacterClass matching
Take advantage of ranges sorting to early out, make the logic
inline.
2023-02-19 11:16:14 +11:00
Johannes Altmanninger
213ea922b1 Complete arguments to "echo -to-file"
Including this here because grandparent parent commit broke completions
for "edit -fifo".
2023-02-17 20:50:58 +01:00
Johannes Altmanninger
9e0502a1ca Do not complete redundant switches 2023-02-17 20:50:58 +01:00
Johannes Altmanninger
64d4d29d43 Use parameter parser to skip switch args in completion
The command line "hook -group xyz " should get scope completions but
it actually gets hook completions because "xyz" is wrongly interpreted
as positional argument.

Fix this by using the parameters parser to compute positional
arguments.

Fixes #4840
2023-02-17 20:50:58 +01:00
Ameer Ghani
6acc18373d Add option to set maximum info box width
Some plugins (*cough* kak-lsp) and help texts tend to have immensely long content
in a single line. This generates info boxes that span the entire terminal width.
This is made especially worse on widescreen monitors or at small text size.

This grants user control over how wide these boxes are.

I deliberately avoid pushing this change to `kak-lsp` because it's not the only
plugin that this could help--see the `hook` help text for an example of this
problem in vanilla Kakoune. I would also suggest that since this is a rendering
concern, it be handled by the terminal rendering logic.
2023-02-15 21:17:22 -05:00
Maxime Coste
afaa47e93f Fix trimming of line front halfway through a double-width glyph
Insert a space to replace the half glyph and ensure the rest of the
line is correctly aligned.

Fixes #4843
2023-02-15 13:04:53 +11:00
Maxime Coste
0630b4f4f6 Fix scroll_window not ensuring cursor lies on a codepoint start
Fixes #4839
2023-02-14 22:00:12 +11:00
Maxime Coste
458e3ef20a Immediately execute ModuleLoaded hooks for already loaded modules
This is trickier than expected because ModuleLoaded hooks can (as
any other hooks) use arbitrary regular expressions for their filter.

Fixes #4841
2023-02-14 21:31:29 +11:00
Maxime Coste
85ceef29bd Fix broken corner cases in DualThreadStack::grow_ifn
We only grow when the ring buffer is full, which allows for a nice
simplification of the code.

Tell grow_ifn if we pushed in current or next so that we can
distinguish between filled by next or filled by current when
m_current == m_next_begin
2023-02-14 17:13:31 +11:00
Maxime Coste
d708b77186 Refactor DualThreadStack as a RingBuffer
Instead of two stacks growing from the two ends of a buffer, use
a ring buffer growing from the same mid spot.

This avoids the costly memory copy every step when we set next
threads as the current ones.
2023-02-14 07:04:54 +11:00
Maxime Coste
762064dc68 Remove scheduled optimization from ThreadedRegexVM
This does not seem to actually speed up execution as threads will
be dropped on next step anyway
2023-02-13 21:15:55 +11:00
Maxime Coste
3150e9b3cd Avoid extra indirection for storing FifoWatcher
By improving the Value interface we can avoid storing a unique_ptr
to a FifoWatcher and directly store the FifoWatcher.
2023-02-10 12:56:32 +11:00
Maxime Coste
eb0e983133 Fix DisplayLine::trim_front quadratic behaviour
Erasing fully trimmed display atoms one by one means we have to
shift all the remaining ones every time. This is wasteful and we
can just erase all the fully trimmed atom in one go.

Fixes #4797
2023-02-03 11:31:13 +11:00
Maxime Coste
d5ae08498c Merge remote-tracking branch 'krobelus/selection-undo-fix-standstill-after-buffer-change' 2023-01-28 08:29:41 +11:00
Maxime Coste
37b160e935 Merge remote-tracking branch 'occivink/fix-split-stray-sel' 2023-01-27 10:58:38 +11:00
Maxime Coste
5097884608 Fix crash in TabulationHighlighter when wrapping just after a tab 2023-01-23 17:39:40 +11:00
Maxime Coste
f5d5274c5f Fix incorrect use of subject end/begin in regex execution
This could lead to reading past subject string end in certain
conditions

Fixes #4794
2023-01-23 17:38:02 +11:00
Maxime Coste
a02bd19533 Revert "Remove compare include that seems to break clang"
Looks clang breaks differently when this is not included

This reverts commit 7030b3c47c.
2023-01-21 11:27:05 +11:00
Maxime Coste
702358b559 Replace std::strong_ordering with auto return type to not require <compare> 2023-01-21 11:19:39 +11:00
Maxime Coste
7030b3c47c Remove compare include that seems to break clang 2023-01-21 11:06:22 +11:00
Olivier Perret
b039a313a4 fix 'split' operation when the pattern occurs at the beginning
Previously it would result in a stray single-character selection at the
beginning of the input text.

For example:
[abcabc] -> split on 'a' -> [a][bc]a[bc]
or
[foobarfoobar] -> split on 'foo' -> [f]oo[bar]foo[bar]

Note that this behavior was not occuring if the input text was at the
beginning of the buffer
2023-01-20 18:05:04 +01:00
Maxime Coste
d8883d47c0 Merge remote-tracking branch 'krobelus/fix-mouse-click-during-insert' 2023-01-18 07:48:37 +11:00
Maxime Coste
029b28a85c Merge remote-tracking branch 'potatoalienof13/fix-buffer-advance' 2023-01-18 07:47:23 +11:00
Maxime Coste
f720ded96a Merge remote-tracking branch 'krobelus/missing-error-when-open-fails' 2023-01-18 07:40:35 +11:00
Johannes Altmanninger
4f7d7a5e33 Fix regression when file on command line cannot be opened
Commit 933e4a599 (Load buffer in command line order, 2022-12-06)
introduced a regression: the command

	$ kak /boot/grub/grub.cfg
	Fatal error: no such buffer '/boot/grub/grub.cfg'

quits with no indication of the underlying error.

Prior to 933e4a599, it would open the *scratch* buffer instead,
and show an error in the status line, pointing to the debug buffer,
which would contain:

	error while opening file '/boot/grub/grub.cfg':
	    /boot/grub/grub.cfg: Permission denied

Let's fix this scenario by matching the old behavior.
2023-01-08 17:26:15 +01:00
Johannes Altmanninger
35f23d6fad Remove bogus assertions preventing mouse clicks in insert mode
Recent changes for selection-undo added an assertion that triggers
when a mouse-drag overlaps with an insert mode, because both events
record selection history.  However this is actually fine.  The one
that finishes last concludes the selection edition, while the other
one will be a nop.

The test could be simpler (i.e. not require sleeps) but I figured it
doesn't hurt add this since we don't have any comparable tests.
2023-01-08 10:47:36 +01:00
Johannes Altmanninger
516759bb2f Make selection undo skip over entries that are nop after buffer change
After buffer modification - in particular after deletion - adjacent
selection history entries may correspond to the same effective
selection when applied to the current buffer. This means that we
sometimes need to press <c-h> multiple times to make one visible
change. This is not what the user expects, so let's keep walking the
selection history until we hit an actual change.

Alternatively, we could minimize the selection history after buffer
changes but I think that would make the it worse after content
undo+redo.
2022-12-27 18:24:55 +01:00
Johannes Altmanninger
8427379a5d Tweak selection-undo interaction with WinDisplay hooks
Each selection undo operation is surrounded by pair of
begin_edition()/end_edition() calls.
The original reason for adding these was that in one of my preliminary
versions, a WinDisplay hook could break an undo chain, even if the
hook did not affect selections at all. This has since been fixed.

By surrounding the undo with begin_edition()/end_edition(), try to
ensure that any selection modification that happens in a WinDisplay
hook would not break the undo chain. Essentially this means that,
after using <c-h> to undo a buffer change, this was meant to
make sure that <c-k> could redo that buffer change.

However, it turns out this actually doesn't work.  The attached test
case triggers an assertion.  As described in the first paragraph,
the only real-world motivation for this is gone, so let's simplify
the behavior.
The assertion fix means that we can test the next commit better.
2022-12-27 18:24:55 +01:00
Johannes Altmanninger
016e1be77f Extract variable and add comment in selection change recording
No functional change.
2022-12-27 18:24:55 +01:00
Johannes Altmanninger
02d0584e0f Extract variable in selection undo
No functional change.
2022-12-27 18:24:55 +01:00
Johannes Altmanninger
a50cb5f6e7 Share logic for undo/redo selection changes
I will suggest a few changes to this code.
No functional change.
2022-12-27 18:24:55 +01:00
potatoalienof13
eb447f1c43 Remove a check for inclusivity in select_to_reverse.
It turns out that neither <a-f> or <a-t> make sense when run at the
beginning of the buffer. When I first created the check, I thought
that <a-f> made sense if the character under the cursor was the
character being searched for.  I was wrong, <a-f> should always go
at least one character backwards.
2022-12-26 09:17:06 -05:00
potatoalienof13
1a4737cd20 <a-t> should not succeed when run on the first character of a file. 2022-12-25 17:57:28 -05:00
potatoalienof13
293d46837d Fix Buffer::advance out of bounds access.
This commit fixes a bug in Buffer::advance where it would first access
m_lines[-1], and then check whether or not that access would have
segfaulted.  This commit moves the check to before the segfault would
occur.
2022-12-22 17:34:42 -05:00
Maxime Coste
c31e53e8a4 Merge remote-tracking branch 'krobelus/fix-cd-after-backspace' 2022-12-22 09:51:58 +11:00
potatoalienof13
041c88c930 This commit attempts to fix a crash with -f. Specifically when kakoune
is run as

> ./kak -f '2oK.k<c-n><ret><c-n>' /dev/null

The crash occurs because when <c-n> is pressed for the second time,
it attempts to use m_completions from the first press of <c-n>.
This only happens when kakoune is run with -f, because when this is done
interactively, there is a client, which means that m_completions gets
reset.  This removes the check that causes that difference.

I am not *completely* sure that this is the best way to solve the
problem, since I am not completely sure why that check was put there
in the first place.
2022-12-21 17:46:49 -05:00
Maxime Coste
938be7a7b0 Merge remote-tracking branch 'krobelus/no-selection-history-in-draft-context' 2022-12-17 10:10:10 +11:00
Maxime Coste
f3201cb956 Speed up expand_unprintable by avoiding BufferIterator
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-15 17:09:37 +11:00
Maxime Coste
20278ed52b Support adding ByteCount to void/char pointers without casting 2022-12-15 13:29:45 +11:00
Maxime Coste
8279a3776f Optimize TabulationHighlighter 2022-12-15 13:17:00 +11:00
Maxime Coste
36d1713b09 Fix a couple bugs with underline highlighting
Add missing curly_underline attribute to json-rpc
Fix underline color not correct after attrbute only change
2022-12-13 12:14:29 +11:00
Johannes Altmanninger
f79580680a Do not record selection history in draft context
Each draft context gets its own private copy of the selections.
Any selection changes will be thrown away when the draft context
is disposed. Since selection-undo is only supported as top-level
command, it can never be used inside a draft context, so let's stop
recording it.
No functional change.
2022-12-10 15:40:19 +01:00
Maxime Coste
a52bb9146e Cleanup expand_unprintable and avoid calling iswprint on base ascii 2022-12-06 17:55:20 +11:00
Maxime Coste
93c50b3cd9 Avoid calculating atom length in DisplayLine::trim_from
Calculating the length of an atom means we need to decode every
codepoint and compute its column width. This can prove quite expensive
in trim_from as we can have full buffer lines, so on buffer with long
lines we might have to go through megabytes of undisplayed data.
2022-12-06 17:51:28 +11:00
Maxime Coste
933e4a599c Load buffer in command line order
Pass the first buffer on the the command line explicitely to client
creation. This ensure the buffer list matches the command line, which
makes buffer-next/buffer-previous a bit more useful.

Fixes #2705
2022-12-06 17:48:42 +11:00
Maxime Coste
78c44e94dc Rework StringOps::substr implementation
Avoid iterating over the whole string when the length is not provided
just use the end iterator directly.
2022-12-03 08:24:38 +11:00
Maxime Coste
cd73f2aa17 Use some template magic to automatically deserialize UI messages
We always deserialize arguments in order, and we can extract
argument types from the type of the pointer to method.
2022-11-29 17:19:09 +11:00
Maxime Coste
2688893156 Fix pasting after when selections are overlapping
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-11-28 20:27:44 +11:00
Maxime Coste
b7b036c210 Change BufferIterator comparison to assert same buffer
Comparing iterators between buffers should never happen, and the
only place we did was with default constructed BufferIterator which
we replace by casting the iterator to bool.

This should improve performance on iterator heavy code.
2022-11-20 16:59:08 +11:00
Johannes Altmanninger
a5f684737f Print OS error when ":write -force" fails to change permissions
When the file system runs out of space, "write -force" will fail but
doesn't print "No space left on device".
Let's fix this by including such an underlying error. Untested.

Backstory: I alias "w" to a command that runs "write -force %arg{@}".
so I can overwrite files that already exist outside the editor (I
should probably get used to the new behavior).
2022-11-19 15:21:38 +01:00
Johannes Altmanninger
59b8b99577 Accept "cd dir/" again instead of using a subdirectory
Commit 69053d962 (Use menu behavior when completing change-directory,
2022-07-19) made ":cd dir/" actually run ":cd dir/first-subdir",
which can be surprising.
This is usually irrelevant because you rarely type the trailing slash.
However it does happen after correcting an error with `<backspace>`
and friends. For for example,

	:cd d<tab>/f<backspace>

results in

	:cd dir/

We should probably fix user expectations here. Do this by adding "dir/"
as valid completion.  This requires us to allow empty candidates in
"RankedMatch" but there's no harm in that. This means we need to
filter out empty completions from shell-script-candidates elsewhere.

Alternative fix: we could revert 69053d962. This would remove the
convenient menu behavior but that wouldn't be a huge deal.

Fixes #4775
2022-11-19 15:20:31 +01:00
Maxime Coste
91d45a100a Merge remote-tracking branch 'krobelus/undo-selection-change' 2022-11-10 08:56:42 +11:00
Olivier Perret
84379f4466 Add a %val{selection_count} expansion 2022-11-04 19:16:38 +01:00
Maxime Coste
dcdafdea77 Remove wrong rejection of upper case mappings in goto mode
Mapping upper case keys is legitimate, for exampled so that they behave
the same as a lower case mapping. The current rejection of those mappings
is a misguided attempt to prevent mapping *to* upper case keys as those
will never get triggered.

Closes #4769
2022-11-04 16:43:55 +11:00
Maxime Coste
ca6a701b80 Add -to-shell-script echo switch
This feature simplifies various small use cases and is a good
companion to the existing -to-file switch.
2022-11-04 16:40:07 +11:00
Maxime Coste
98b84f2b05 Kakoune 2022.10.31 2022-10-31 09:05:58 +11:00
Maxime Coste
0a21dc0e99 Fix memory domain for cached command completion 2022-10-29 16:10:41 +11:00
Maxime Coste
2cbcdf2fb4 Merge remote-tracking branch 'krobelus/write-autoinfo2' 2022-10-19 20:23:18 +11:00
Maxime Coste
ae6ee02cb2 Refactor insert_output command to avoid intermediate vector
This is like a paste with a different source, so the same logic
should work. This means we now correctly fix overflowing selections.

Fixes #4750
2022-10-19 20:16:09 +11:00
Maxime Coste
d1ac4dbff3 Remove unused History MemoryDomain 2022-10-19 20:16:09 +11:00
Maxime Coste
287217b987 Fix splitting of display atoms accross multi-columns codepoint
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-10-17 17:48:39 +11:00
Johannes Altmanninger
91c43c0f67 Allow to put switches after :write's positional argument
After a failed

	:write file-that-already-exists

a user might want to type ":<up> -f<ret>" to force-overwrite.
This doesn't work because :write's switches must precede the filename.
It's dual :edit does not have this restriction.

Some commands require switches to precede positional arguments for a
good reason; for example because positional arguments might start with
"-" (like ":echo 1 - 1").

There seems to be no reason for the :write restriction, so remove
it. Same for :enter-user-mode.

Thanks to alexherbo2 for reporting.
2022-10-16 19:49:43 +02:00
Maxime Coste
360a6847be Merge remote-tracking branch 'vsyl/c_description' 2022-10-11 20:39:10 +11:00
Jakub Wasilewski
69f4d1261b Correct and unify descriptions of normal mode C key behavior
Fixes #4747
2022-10-11 08:39:34 +02:00
Hampus Fröjdholm
18a84c6b3c Fix compilation failure with clang 12 and debug=yes
The pointer type alias was missing from FlattenedView::Iterator causing
std::iterator_traits to be an empty class.
2022-10-02 14:04:07 +02:00
Maxime Coste
24d6072353 Merge remote-tracking branch 'krobelus/faster-update-matches' 2022-09-17 20:16:14 +02:00
Johannes Altmanninger
803873c91c Fix quadratic runtime when updating region highlighter matches
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-09-17 06:44:57 -05:00
Johannes Altmanninger
a33ec8dc80 Avoid potentially quadratic runtime when updating selections after modification
LineRangeSet::add_range() calls Vector::erase() in a loop over the
same vector. This could cause performance problems when there are many
selections. Fix this by only calling Vector::erase() once.  I didn't
measure anything because my benchmark is dominated by another issue
(see next commit).

LineRangeSet::remove_range() also has a suspicious call to erase()
but that one is only used in test code, so it doesn't matter.
2022-09-17 06:44:57 -05:00
Adrià Arrufat
f50ee5bb5a Fix crash when trying to display the menu in a tiny window 2022-09-17 00:51:34 +09:00
Maxime Coste
1a8f379a43 Merge remote-tracking branch 'krobelus/embrace-menu-3' 2022-09-09 17:10:53 +02:00
Maxime Coste
1831c4da4b Merge remote-tracking branch 'krobelus/to-string' 2022-09-09 17:03:59 +02:00
Maxime Coste
c428d3296d Merge remote-tracking branch 'krobelus/write-autoinfo' 2022-09-09 15:43:22 +02:00
Maxime Coste
1b4a6a03ee Merge remote-tracking branch 'krobelus/hashset-no-braces' 2022-09-09 15:40:08 +02:00
Maxime Coste
6828c9cb4d Merge remote-tracking branch 'krobelus/cleanup' 2022-09-09 15:37:48 +02:00
Johannes Altmanninger
c2ab5d4694 Allow to undo and redo selection changes
From the issue:

> It often happens to me that I carefully craft a selection with multiple
> cursors, ready to make changes elegantly, only to completely mess it
> up by pressing a wrong key (by merging the cursors for example). Being
> able to undo the last selection change (even if only until the previous
> buffer change) would make this much less painful.

Fix this by recording selection changes and allowing simple linear
undo/redo of selection changes.

The preliminary key bindings are <c-h> and <c-k>.
Here are some other vacant normal mode keys I considered

	X Y
	<backspace> <minus>
	# ^ =
	<plus> '

unfortunately none of them is super convenient to type.  Maybe we
can kick out some other normal mode command?

---

This feature has some overlap with the jump list (<c-o>/<c-i>) and
with undo (u) but each of the three features have their moment.

Currently there's no special integration with either peer feature;
the three histories are completely independent.  In future we might
want to synchronize them so we can implement Sublime Text's "Soft
undo" feature.

Note that it is possible to restore selections that predate a buffer
modification. Depending on the buffer modification, the selections
might look different of course. (When trying to apply an old buffer's
selection to the new buffer, Kakoune computes a diff of the buffers
and updates the selection accordingly. This works quite well for
many practical examples.)

This makes us record the full history of all selections for each
client. This seems wasteful, we could set a limit. I don't expect
excessive memory usage in practice (we also keep the full history of
buffer changes) but I could be wrong.

Closes #898
2022-09-02 02:59:47 +02:00
Johannes Altmanninger
dd4ba2ee88 Prepare to record selection changes as perceived by the user
To be able to undo selection changes, we want to record selections
from all commands that modify selections. Each such command will get
its own private copy of the selections object.

This copy will live until the command is finished executing.
All child commands that are run while the command is executing,
will also use the same copy, because to the user it's all just one
selection change anyway.

Add an RAII object in all places where we might modify selections.
The next commit will use this to create the private selections copy
in the constructor (if there is none) and remove redundant history
items in the destructor.

We could avoid the RAII object in some places but that seems worse.
For lifetimes that don't correspond to a lexical scope, we use a
std::unique_ptr. For lambdas that require conversion to std::function,
we use std::shared_ptr because we need something that's copyable.
2022-09-02 02:56:41 +02:00
Johannes Altmanninger
611bdebf3c Access selections via helper methods
The next commit changes the selections to a history of
selections. Today we directly access the selections data member. Let's
instead use an accessor method, to reduce the number of changes in
the next commit.
2022-08-29 08:01:43 +02:00
Johannes Altmanninger
aeae2fba37 Pass entire context to select_coord
This allows a following commit to record selection history inside
select_coord() instead of at every call site.
2022-08-29 08:01:43 +02:00
Johannes Altmanninger
3165f28a3c Make parameter const 2022-08-29 08:01:43 +02:00
Johannes Altmanninger
1333fe21d0 Fix clang warning regarding useless braces when using HashSet
clang/clangd complain about the new HashSet type:

	hash_map.cc:98:20: warning: braces around scalar initializer [-Wbraced-scalar-init]
	        set.insert({10});
	                   ^~~~

The argument to HashSet<int>::insert is just an int, so we don't
need braces.  Only an actual HashMap would need braces to construct
a HashItem object.
2022-08-28 15:23:29 +02:00
Johannes Altmanninger
7ae31b6778 Show write -force parameter only for commands that support it
When passing a filename parameter to "write", the -force parameter
allows overwriting an existing file.
The "write!" variant (which allows writing files where the current
user does not have write permissions) already implies -force.
All other variants (like write-quit or write-all) do not take a
file parameter.
Hence -force is relevant only for "write".  Let's hide it from the
autoinfo of the other commands.

It's difficult to avoid duplication when constructing the constexpr
SwitchMap because String is not constexpr-enabled.  Today, all our
SwitchMap objects are known at compile time, so we could make SwitchMap
use StringView to work around this. In future we might want to allow
adding switches at runtime, which would need String again to avoid
lifetime issues.
2022-08-28 09:28:06 +02:00
Johannes Altmanninger
348b3f9d9d Fix synopsis of write-quit commands
Like other write commands, these support the -method switch, so
indicate that in the synopsis.
2022-08-24 22:21:06 +02:00
Maxime Coste
13a95b0ba0 Merge remote-tracking branch 'krobelus/set-remove-autoinfo' 2022-08-21 18:38:28 +02:00
Maxime Coste
d076c033e7 Avoid calling memcpy from empty string views
ubsan is unhappy when passing a nullptr as the source pointer to
memcpy even if the length is 0.

Fixes #4720
2022-08-21 17:52:51 +02:00
Maxime Coste
efa45f8bdd Bypass RegexIterator in RegionsHighlighter::add_matches 2022-08-21 10:25:51 +02:00
Maxime Coste
021da117cf Add support for field width and digit grouping in format 2022-08-20 11:03:03 +02:00
Maxime Coste
0c1d4808fa Slight code style tweak 2022-08-20 11:03:03 +02:00
Maxime Coste
21047db4a0 Remove unnecessary utf8 decoding when looking for EOL in regex 2022-08-20 11:03:03 +02:00
Maxime Coste
c8c8051bd0 Refactor RegionsHighlighter to share regexes
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-08-20 11:02:59 +02:00
Johannes Altmanninger
d324e506e3 Use make_array to avoid specifying the array size
When I wrote this line I wanted to avoid adding the array size but
I didn't know about make_array().

I had unsuccessfully tried some alternatives, for example

	Array{"a", "b", "c"}

which doesn't work because we need StringView (c.f. git blame on
this line)

also

	Array<StringView>{"a", "b", "c"}

doesn't work because it's missing a template argument.
2022-08-17 00:42:12 +02:00
Johannes Altmanninger
0eb4e68c40 Rename button_to_str() to the more idiomatic to_string()
Analogous to the parent commit.

This returns StringView, but it's immortal so it's even better
than String.
2022-08-17 00:38:58 +02:00
Johannes Altmanninger
01f3d7cbda Rename key_to_str() to the more idiomatic to_string()
This makes the function easier to find for newcomers because
to_string() is the obvious name. It enables format() to do the
conversion automatically which seems like good idea (since there is
no other obvious representation).

Of course this change makes it a bit harder to grep but that's not
a problem with clang tooling.

We need to cast the function in one place when calling transform()
but that's acceptable.
2022-08-17 00:38:58 +02:00
Johannes Altmanninger
08ea6d07e4 Remove stale comment about StaticRegister
Commit d470bd2cc (Make numeric registers setable, 2017-02-14) removed
the user-provided StaticRegister::operator= in favor of a set()
member function, so this comment is no longer valid.
2022-08-16 19:15:22 +02:00
Maxime Coste
ca71d8997d Reuse existing character classes when possible in regex 2022-08-05 20:31:39 +10:00
Maxime Coste
26d14d52bb uniquify selection contents before generating regex for '*'
Avoid generating regex with the same alternative repeated multiple
times.
2022-08-05 20:10:11 +10:00
Maxime Coste
89cd3c52eb Add HashSet implemented as HashMap with void value type 2022-08-05 20:06:34 +10:00
Maxime Coste
9fb7d90449 Change HashMap not to support multiple identical keys by default
We do not seem to have any uses for this remaining, and this is
better opt-in with MultiHashMap
2022-08-05 19:20:00 +10:00
Maxime Coste
31e9fc3cef Merge remote-tracking branch 'krobelus/history-in-mappings' 2022-08-03 20:37:44 +10:00
Maxime Coste
fa209a9a97 Merge remote-tracking branch 'krobelus/document-history-registers' 2022-08-03 19:51:22 +10:00
Johannes Altmanninger
e13b435783 Do not complete command switches after --
Recently, switch completion were given the menu behavior.
Unfortunately this breaks cases like

	:echo -- -mark<ret>

where the hypothetical user wanted to actually display "-mark", not
"-markup".

Simply bail if there is a double-dash. This is not fully correct,
for example it wrongly disables switch completion on

	echo -to-file -- -

but that's minor, we can fix it later.

In future, we should reuse the ParametersParser when computing completions,
which will obsolete this workaround.
2022-08-01 12:34:22 +02:00
Johannes Altmanninger
a36473f4bb Do not record prompt history when executing user mode mappings
Commit 217dd6a1d (Disable history when executing maps, 2015-11-10)
made it so with

	map global normal X %{:echo 123<ret>}

X does not add to prompt history (%reg{:}).

Unfortunately this behavior was not extended to mappings in the "user"
keymap, nor to mappings in custom user modes.
In my experience, not adding to history is almost always the expected
behavior for mappings. Most users achieve this by adding a leading space:

	map global user X %{: echo 123<ret>}

but that's awkward. We should have good defaults (no nnoremap)
and map should work the same way across all modes.

Fix this by also disabling history when executing user mappings. This
is a breaking change but I think it only breaks hypothetical scenarios.

I found some uses where user mappings add to history but none of them
looks intentional.

f702a641d1/.config/kak/kakrc (L169)
604ef1c1c2/kakrc (L96)
d22e7d6f68/kak/kakrc (L71)
https://grep.app/search?q=map%20%28global%7Cbuffer%7Cwindow%29%20user%20.%2A%5B%21%3A/%5D%5B%5E%20%5D.%2A%3Cret%3E&regexp=true
2022-08-01 07:37:02 +02:00
Johannes Altmanninger
253b13281e Show the default values for -save-regs in autoinfo of exec/eval
They are documented in ":doc execeval" but it seems like a good idea
to make this info more prominent.
2022-08-01 07:15:08 +02:00
Johannes Altmanninger
d999a00b0c Fix typo in eval/exec code
Will touch similar code
2022-08-01 07:15:08 +02:00
Johannes Altmanninger
031de6d28c Use menu behavior for completing builtins where appropriate
This allows to select completions without pressing Tab.

There are two different obvious ways to add the menu bit.
1. When creating the "Completions" object, pass the
   Completions::Flags::Menu parameter.
2. If there is a completer function like "complete_scope", wrap
   it, e.g. "menu(complete_scope)".

I have settled on always using 2 if there is a completer function
and 1 otherwise.
The advantage of 2 over 1 is that it allows to use the completer
function in a context where we don't want the menu behavior
(e.g. "complete-command").

---

Now the only* completion type where we usually don't use menu behavior
is file completion. Unfortunately, menu behavior has poor interaction
with directories' trailing slashes. Consider this (contrived) example:

	define-command ls -docstring "list directory contents" -params .. %{
		echo -- %sh{ls "$@"}
	}
	complete-command -menu ls file

Run ":ls kakoun<ret>".  The prompt expands to ":ls kakoune/"
before executing. Next, run ":<c-p>".  This recalls ":ls kakoune/"
and immediately selects the first completion, so on validation,
the command will be ":ls kakoune/colors/", which is weird.

[*] Also, expansions like %val{bufname} also don't use menu
behavior.  It wouldn't add value since validation doesn't add a
closing delimiter. I have an experimental patch that adds closing
delimiters automatically but I'm not sure if that's the right
direction.
2022-07-30 22:17:32 +02:00
Johannes Altmanninger
69053d9623 Use menu behavior when completing change-directory
This makes "cd<space><ret>" change to the first completion,
not to $HOME.  This might be surprising but it should make sense.
I don't have a concrete motivation but this should save a Tab press
in some scenarios.
2022-07-28 15:10:28 +02:00
Johannes Altmanninger
a1715a0c41 Use menu behavior when completing scope arguments
We allow to abbreviate scopes ("set g" means the same thing as "set
global") but that feature is a bit obscure.  Users might figure out the
menu completion behavior faster, so let's maybe use it here as well?
2022-07-28 15:10:28 +02:00
Johannes Altmanninger
5aa0241124 Use and extract functions for completing scope arguments
Not really attached to this but it enables the next commit to use
menu() for completing scopes.

This refactoring is possible because we always have

	params[token_to_complete].length() == pos_in_token

---

Instead of three separate functions, I originally tried to add
template arguments to complete_scope().  That worked fine with g++
12.1 but clang 14.0 complained when wrapping a menu() around a
complete_scope() that relied on defaulted template arguments:

	commands.cc:1087:20: error: no matching function for call to 'menu'
	    make_completer(menu(complete_scope), menu(complete_hooks), complete_nothing,
	                   ^~~~
	commands.cc:116:6: note: candidate template ignored: couldn't infer template argument 'Completer'
	auto menu(Completer completer)
	     ^
2022-07-28 15:10:28 +02:00
Johannes Altmanninger
23fcf77160 Fix autoinfo for "set-option -remove" not showing option-specific info
On a command prompt like

	"set-option -remove buffer aligntab "

we fail to show the aligntab-specific info . Fix this by skipping a
leading -remove, just like we skip -add.

Add an explicit specialization of contains() because otherwise I'd
need to write something like

	contains(Array{"-add", "remove"}, param)
2022-07-28 15:02:20 +02:00
Johannes Altmanninger
4b6abfaedf Remove redundant handling of "-add" from set-option completer
Switches are removed before invoking a command's completer (look for
"std::not_fn(is_switch)". Remove completer code that attempts to
handle switches.
2022-07-28 14:02:20 +02:00
Maxime Coste
e83dbdcd2c Merge remote-tracking branch 'krobelus/embrace-menu-2' 2022-07-28 21:34:31 +10:00
Maxime Coste
79ff3c29e5 Merge remote-tracking branch 'krobelus/support-prompt-menu' 2022-07-28 21:33:07 +10:00
Maxime Coste
99874a1e25 Merge remote-tracking branch 'krobelus/prompt-completion-cut-at-cursor' 2022-07-28 21:29:21 +10:00
Maxime Coste
935261c8be Merge remote-tracking branch 'krobelus/support-shift-backspace' 2022-07-28 21:23:03 +10:00
Maxime Coste
08f5bc3959 Merge remote-tracking branch 'krobelus/startup-info' 2022-07-24 10:12:58 +10:00
Maxime Coste
b2bdaf8288 Merge remote-tracking branch 'krobelus/complete-expansions-in-double-quotes' 2022-07-24 10:12:22 +10:00
Maxime Coste
626e1fec43 Merge remote-tracking branch 'krobelus/no-redundant-menu' 2022-07-24 10:10:51 +10:00
Johannes Altmanninger
6e4b0d8859 Support "prompt -menu" to mark completions as authoritative
This gives the "prompt" command the same "-menu" switch as
"complete-command" and "define-command". I don't think anyone has
asked for it but it seems like a good idea?
2022-07-22 21:14:23 +02:00
Johannes Altmanninger
aa8f29eff1 Extract function for parsing completion switches
Both "define-command" and "prompt" use the same logic, so share
it. This will make it easy to implement "prompt -menu".

This reveals a problem with PromptCompleterAdapter: when converting
it to std::function and then to bool, it always evaluates to true
because it has an operator().  However, it should evaluate to false
if the adaptee holds no valid function (e.g. is a default-constructed
std::function). Otherwise we try to call a non-existant function. Tweak
PromptCompleterAdapter to work for empty inputs.
2022-07-22 21:06:33 +02:00
Johannes Altmanninger
47329260da Move input completer when constructing PromptCompleterAdapter
I think we usually do this when passing completers.
2022-07-22 20:56:20 +02:00
Johannes Altmanninger
19fccc1587 Compute prompt completion only from characters left of the cursor
If I type

	:echo -mx

I get no completions, even when I move the cursor on the x.
If I replace the x  with a k, I get a completion "-markup".
The odd thing is that if I accept the completion while the cursor is
on the k, then the commandline will be

	:echo markupk

Evidently, the characters under cursor (x/k) influence the completion
(actually all letters right of the cursor do), but they are not
incorporated in the final result, which is weird.

I think there are two consistent behaviors:
1. Compute completions only from characters left of the cursor. We already
   do this in insert mode completion, and when completing the command name
   in a prompt.
2. Compute completions from the whole token, and when accepting a completion,
   replace the whole token.

Most readline-style completion systems out there implement 1. A
notable exception is fish's tab-completion. I think we should stick
to 1 because it's more predictable and familiar. Do that.

This allows us to get rid of a special case for completing command
names, because the new behavior subsumes it.

In fact, I think this would allow us to get rid of most "pos_in_token"
or "cursor_pos" completer parameters. I believe the only place where we
it's actually different from the end of the query is in "shell-script"
completers, where we expose "$kak_pos_in_token". I think we can still
remove that parameter and just cut the commandline at the cursor
position before passing it to a "shell-script" completer. Then we
also don't need "$kak_token_to_complete" (but we can still keep
expose them for backwards compatibility).
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
19d2de41c0 Update startup info with p/P breaking change 2022-07-21 16:48:44 +02:00
Johannes Altmanninger
59dd3eaf15 Complete double-quoted expansions in prompt mode
This adds completions for

	:echo "%val{
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
34c489170f Elide temporary vector when completing register names
Just like in the parent commit, this requires us to use a non-owning
type. Technically, these strings all benefit from SSO, so there is
no lifetime issue, but we can't deduce that from the types.
I guess we could use InplaceString just as well.
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
7f08ac3de2 Use menu behavior for add-highlighter/remove-highlighter completion
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-21 16:48:44 +02:00
Johannes Altmanninger
b2f45a29e4 Elide temporary vector when completing keymap modes (user modes)
complete() merely iterates over its input, so we can pass it a range
instead of a vector.  For some reason, this requires specifying the
type of the static array, or else its elements become String which
triggers this assertion:

    static_assert(not std::is_same<decltype(*begin(container)), String>::value,
                  "complete require long lived strings, not temporaries");

Specify the type with an explicit Array<StringView, 8>. This is
pretty ugly but the alternative of appending "_sv" to every single
array element seems worse?

If we modify the vector of user modes while complete() is iterating
over, we could crash -- but that scenario is impossible since both
only happen inside the single-threaded server process.
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
8fac31ba76 Use menu behavior for completion of switches
We already use the menu behavior in complete_command_name(); let's do
the same for switches, since we can complete all valid inputs and
it can save a Tab key in some scenarios.

CommandManager::complete is fairly complex. We can't expect callers
to add the menu bit when appropriate, so we currently do it here.
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
ba557e90a2 Offer "--" as completion when completing switches
The next commit will give switch completions the menu behavior, so this
is necessary so we can still type "echo --" without an auto-expansion
to "echo -to-file".
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
1358fc3cef Deduplicate functions for completing alias names
"complete_alias_name" is a better name then "complete_alias" because
it's consistent with more similar names, which are:

	complete_client_name
	complete_command_name
	complete_module_name
	complete_option_name
	complete_register_name
	complete_scope
	complete_face
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
57a98880ab Make completers take "StringView" instead of "const String&" for compatibility with PromptCompleter
We define

	using PromptCompleter = std::function<Completions (const Context&, CompletionFlags,
	                                                   StringView, ByteCount)>;

Some command completers are *almost* convertible to PromptCompleter;
the only difference is the string type of the prefix argument.
The later commits in this series want to use menu() on the
completers. Enable this by harmonizing the types.
2022-07-21 16:48:44 +02:00
Johannes Altmanninger
a4696eb33a Remove redundant check for menu bit
can_auto_insert_completion already requires the menu bit.
2022-07-21 16:43:54 +02:00
Maxime Coste
559af669c7 Remove out-of-date column computation in show-whitespaces
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-19 22:47:39 +10:00
Maxime Coste
9ebd0cd9c1 Improve readability of debug memory command output
Group memory usage digits with commas to make it easier to
read those numbers.
2022-07-18 17:39:19 +10:00
Maxime Coste
c7fbf1f390 Re-work line trimming to fix issues with column highighters
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-13 12:24:14 +10:00
Maxime Coste
195fe8fd29 Fix past-the-eol column highlighter getting highlighted as buffer range
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-12 21:11:53 +10:00
Maxime Coste
50cacc0758 Fix buffer location of column highlighter's past-eol atoms
Using buffer end was confusing Window::display_position that
assumes display atom buffer locations are always increasing.
2022-07-11 18:17:51 +10:00
Johannes Altmanninger
dbd8cf2145 Make Shift+Backspace erase a character in insert mode
Terminals that support CSI u escape codes (like iTerm2, Kitty and foot)
allow us to map <s-backspace> independently of <backspace>.

Users expect that <s-backspace> does the same as <backspace>,
especially when typing ALL_CAPS. Make it so.

The first version of 0cf719103 (Make Shift+Space insert a space in
insert mode, 2022-02-09) did that already but I later dropped it
because I wasn't sure if it's right.
2022-07-10 13:46:33 +02:00
Maxime Coste
ce75867e44 Merge branch 'roam-murmurhash-endian' of http://github.com/ppentchev/kakoune 2022-07-10 17:46:07 +10:00
Maxime Coste
94f5479e1a Refactor highlighting logic
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
2022-07-10 14:58:24 +10:00
Peter Pentchev
ded97628f7 murmurhash: always load byte by byte
Also reverse the order of bytes, loading the most significant parts first,
and use bitwise "or" instead of addition.
2022-07-07 08:53:57 +03:00
Maxime Coste
f3cb2e4340 Remove <esc> as end macro recording, Q should be enough
Besides being redundant, it is easy to press esc by mistake/habit
while recording a macro.
2022-07-05 08:43:40 +10:00
Maxime Coste
df79d0c245 Distinguish between non-eol max column target and plain max column 2022-07-05 08:43:40 +10:00
Maxime Coste
b5e565bd6a Store HistoryRegisters with most recent entry in front
Closes #3105
2022-07-05 08:43:40 +10:00
Maxime Coste
2d8456db10 Move user mappings to <space> and keep/remove selection to , 2022-07-05 08:43:40 +10:00
Maxime Coste
266d1c37d0 Select pasted text on paste
This is more consistent with the recently changed ! and <a-!>
behaviour
2022-07-05 08:43:40 +10:00
Maxime Coste
ef8a11b3db Make x just select the full lines
`x` is often criticized as hard to predict due to its slightly complex
behaviour of selecting next line if the current one is fully selected.

Change `x` to use the previous `<a-x>` behaviour, and change `<a-x>` to
trim to fully selected lines as `<a-X>` did.

Adapt existing indentation script to the new behaviour
2022-07-05 08:43:40 +10:00
Maxime Coste
5965acc811 Merge remote-tracking branch 'krobelus/escape-xmessage-args' 2022-06-30 19:47:05 +10:00
Maxime Coste
d87ee212ba Insert all register values in prompt after <c-r> when Alt-modified
`<c-r><a-.>` will insert all selections joined by space instead of only
the main one as `<c-r>.` would.
2022-06-30 16:39:18 +10:00