| Age | Commit message (Collapse) | Author |
|
|
|
|
|
Commit ba41928aa (Remove spurious newline when | replaces at buffer end,
2024-11-28) also tried to fix a "DiffOp::Add" code path. Unless I'm
misremembering, I had run into a crash and extracted this unit test.
When apply_diff() decides to erase the last line, and then insert something
at the end, buffer changes might look like:
{.type=Erase, .begin={2, 0}, .end={3, 0}}
{.type=Insert, .begin={1, 5}, .end={5, 0}}
The "{1, 5}" is caused by "pos = buffer.prev(pos);" added by the
aforementioned commit. It's problematic because it breaks the caller's
"ForwardChangesTracker" invariant: the previous Erase leaves the cursor at
{2, 0}, so the insert cannot start before that.
Additionally, the inserted range returned by apply_diff() would be
"{ {2, 0}, {4, 0} }" whose end position is weirdly different from the Insert's
end position. It questionable that we are passing on this weird state.
The "pos = buffer.prev(pos);" statement was added so we actually delete the
current final newline. We still leave "tried_to_erase_final_newline" set,
meaning we'll also delete the the final newline after we're done.
But deleting the "current final newline" the way we do it is confusing,
because we do it at every step DiffOp::Add step. This would blow up if
there are multiple successive contiguous DiffOp::Add events. I doubt this
ever happens but it's still confusing.
Remove this logic, and restore historical behavior in case we append at the
buffer end. This does not break the system test added by ba41928aa because
in that case, we
1. first delete the entire buffer, setting pos={0, 0}, but also restoring
the EOL invariant, so the end position would be {0, 1}.
2. then we insert at pos={0, 0}, and since "buffer.is_end(pos)" is false we
don't run into this bad code path.
While at it add an assertion to clarify that we already assume that the
diff algorithm never gives us empty DiffOp::Keep, and always monotonically
increasing positions, except for the very special case where we deleted
until buffer end, which should already be handled.
The unit test is not perfect because it depends on the current behavior of
the diff algorithm.
|
|
My
kak -e "exec %{%ca<ret>b<esc>%|printf '\n\n'<ret>}"
adds a spurious third line.
When we replace up to the end everything, we keep around a single
newline to uphold the buffer invariant, but that newline
Commit de1433d30 (Avoid the spurious newline insertion when replacing
at end of buffer, 2016-03-16) fixed an issue for most commands that
replace until the buffer end.
A similar issue exists for the "|" command. It triggers in fewer
cases because the replacement is implemented by applying edits
computed by the diff algorithm. It does trigger when "|" replaces
the entire buffer.
Fix that by erasing the spurious newline.
Alternatively, we could allow the diff steps of kind "remove" to
delete the entire buffer, and only restore the invariant after the
whole diff is applied. This should work because the one-past-end
position is valid for Buffer::insert() even if the buffer is empty. It
is not valid for Buffer::erase() or Buffer::advance() where count>0
but if we do that when we're already at the buffer end, that is
probably a bug in the diff. I tried this but ran into a assertion
in ForwardChangesTracker (kak_assert(change.begin >= cur_pos)).
Alternatively, we could change the diff algorithm to always insert
before deleting.
I encountered this issue when using ansi-enable on a fifo buffer.
Specifically, the first BufReadFifo hook would replace the entire
inserted text but leave around a spurious newline.
|
|
|
|
Without doing this, replace with multiple selection at buffer end
breaks as the first selection will replace the end-of-line with a
non-eol character, then a new eol will automatically be added which
will put remaining selections past the end of the buffer.
Fixes #5316
|
|
We use linewise paste if any of the pasted register elements has a trailing
newline. As shown in the previous patch, this leads to awkward situations
where insertion positions from <a-P> are not monotonically increasing.
This complicated behavior is questionable. The root cause is that linewise
paste may insert some strings that don't have a trailing newline. This leads
to weird cases of GIGO, especially when using <a-P> when the last element
is missing a trailing newline.
Simplify the implementation by not activating linewise paste in that case.
Instead of special-casing the last element, try to simplify the behavior
further by using line-wise paste only if *all* elements are properly
terminated. I can't think of a real-world case where the existing behavior
would be desired.
A regression test shows a change in behavior. Might be less weird now.
The added test case is a copy except it uses "P" instead of "p" (the extra
newline is because "d" deletes the last newline in the buffer which gets
added back implicitly).
(I think the list of register elements is never empty, so this should never
cause a trivial linewise paste. Even if so, that would be fine because
inserting nothing is a nop either way.)
Fixes #5312
|
|
The <?> and <a-?> commands drop selections where the search wrapped.
If a selection is dropped this way, we adjust the new main index.
If the very first selection is dropped this way, *and* it happens to
be the main index, "--main_index" overflows and chaos ensues.
Fix this by saturating main index at zero. This seems more intuitive
than wrapping around ("% new_sels.size()").
This issue only happens to <a-?>, not <?>. When <?> wraps when starting
from the first selection, it necessarily also wraps after all other
selections. (Based on this insight, I started drafting an optimization
to skip searches whose results would be discarded anyway because they
will definitely wrap. Not sure if it's worth it, since it applies
only to the rare edge case of <?>/<a-?> with multiple selections.)
Fixes #5314
|
|
Macros are already recorded with keymaps resolved, so there's
no need to resolve them again.
|
|
Commit e3122ab2c (Refactor prompt history handling, 2023-07-05) was a nice
simplification but it breaks a rare edge case. It suppresses history
recording if all keys the prompt receives were synthesized. That's not
quite the right criteria:
it means that if prompt is created, edited and and executed, all via mapped
keys, we fail to add to history.
The criteria should rather be something like "if all keys the prompt receives
came from synthesized events".
Make it so. This allows us to get rid of the "noninteractive" nested bool
that was only used for disabling history.
|
|
We have only one place where we handle actual keys typed by the user.
|
|
Since shell-script-completions now runs the script asynchronously
and unconditionally, there is no use for the CompletionFlags::Fast
anymore which means we can remove that type altogether.
|
|
Refactor ShellManager and pipe to feed lines from the buffer directly,
this should reduce memory use when piping big chunks of buffers.
The pipe output is still provided as a single big buffer.
|
|
|
|
Move more code into the implementation files to reduce the amount
of code pulled by headers.
|
|
|
|
This led to lots of duplicated code gen, longer compile time, and
most likely unnoticeable performance difference
|
|
|
|
Now the scrolloff can be specified in the configuration file and
if either one of the column or line offset given is too large to
fit in the buffer, half of the window dimension is taken in it's
place. `v<` and `v>` account custom scroll offset as well.
|
|
Make last insert and macro recording closer together, paving the
way towards moving last insert to a register.
Use a FunctionRef for insert completer key insertion support.
|
|
`vt` and `vb` respect custom scroll offset
|
|
This removes lots of duplicated codegen at the expense of slightly
worse constant folding optimizations
|
|
Throwing early avoids losing selections in this case.
|
|
|
|
This seems like a better overall behaviour.
Closes #5135
|
|
tabs <-> space conversion functions did not create a ScopedEdition
leading to uncommited modifications. Fixing this did fix the
interactive error, but that error still existed in non interactive
context so redo now considers there there is no redo child if there
are uncommited modifiations (which is correct as this means we are
currently creating a new leaf in the undo tree)
Fixes #5124
|
|
Fixes #5076
|
|
Users who rebind default keys and unmap the originals by binding them
to empty strings with empty docstrings end up with empty lines in the
autoinfo. For example, https://github.com/mawww/kakoune/issues/4918.
Hide completely null bindings which have both an empty mapping and an
empty docstring in the autoinfo, as an easy mechanism for these users to
eliminate the UI noise.
Fixes https://github.com/mawww/kakoune/issues/4918
|
|
This make the completer lifetime tied to the Prompt mode and removes
the need for the Start flag. It also makes it possible to cleanup
on completer destruction.
|
|
Regressed in a2c41593a (Fix partial regex text being pushed in history,
2023-11-02).
|
|
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
|
|
|
|
Fixes #4993
|
|
This unfortunately breaks the testing framework, more work
necessary before we can do that.
This reverts commit 9b1f4f5f204072ceec6481c2b57a7c4c66d8feab.
|
|
|
|
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.
|
|
This was mostly redundant with Client::force_redraw.
|
|
This is currently broken on various corner cases and breaks the
"master branch should be good for day to day work" implicit rule,
ongoing work to stabilize this feature will take place on the
no-cursor-move-on-scroll branch until its deemed ready.
This reverts commit 1e38045d702ec6eb2425016d9b02636270ab1b1e.
Closes #4963
|
|
Kakoune now does not touch cursors when scrolling. It checks
if either the buffer or selections has been modified since
last redraw.
Fixes #4124
Fixes #2844
|
|
The current exponential behaviour does not seem that useful, it seems
more predictible that pressing `+` twice would end up with 3 copies
of the original selections instead of 4.
Fixes #4533
|
|
|
|
|
|
Share incremental regex logic, pass the synthetized nature of keys
through to input handlers.
|
|
|
|
Fixes #4942
|
|
My terminal allows to map <c-[> and <esc> independently. I like
to use <c-[> as escape key so I have this mapping:
map global prompt <c-[> <esc>
Unfortunately, this is not equivalent to <esc>. Since mappings are
run with history disabled, <c-[> will not add the command to the
prompt history.
So disabling command history inside mappings is wrong in case the
command prompt was created before mapping execution. The behavior
should be: "a prompt that is both created and closed inside a
noninteractive context does not add to prompt history", where
"noninteractive" means inside a mapping, hook, command, execute-keys
or evaluate-commands.
Implement this behavior, it should better meet user expectations.
Scripts can always use "set-register" to add to history.
Here are my test cases:
1. Basic regression test (needs above mapping):
:nop should be added to history<c-[>
---
2. Create the prompt in a noninteractive context:
:exec %{:}
now we're back in the interactive context, so we can type:
nop should be added to history<ret>
---
3. To check if it works for nested prompts, first set up this mapping.
map global prompt <c-j> '<a-semicolon>:nop should NOT be added to history<ret>'
map global prompt <c-h> '<a-semicolon>:nop should be added to history first'
Then type
:nop should be added to history second<c-j><c-h><ret><ret>
the inner command run by <c-j> should not be added to history because
it only existed in a noninteractive context.
---
See also the discussion https://github.com/mawww/kakoune/pull/4692
We could automate the tests if we had a test setup that allowed
feeding interactive key input into Kakoune instead of using
"execute-commands". Some projects use tmux, or maybe we can mock
the terminal.
|
|
The commit after next will fix a bug where we wrongly disable prompt
history in some scenarios. The root cause is that life span of
"disable_history" does not model when we actually want to disable
history.
Let's rename the state variable to "noninteractive". It's set whenever
we are executing a hook, mapping or command.
Note that it's also active inside ":prompt"'s callback, which doesn't
play well with the new name :(
|
|
Moving across history moved to <c-j>/<c-k> to keep <a-u>/<a-U>
for selection undo/redo
This reverts commit e0d33f51b36c9f0be7ae2467dab455d211bbf561.
|
|
Add an iterator based remove to HashMap as that was missing. Make
KeymapManager responsible for throwing on unmap an executing mapping.
|
|
When unmapping a key sequence that is currently executing, we continue
executing freed memory which can have weird effects. Let's instead
throw an error if that happens. In future we can support unmap in
this scenario.
Closes #4896
|