In a noninteractive shell, asynchronous commands ignore SIGINT and
SIGQUIT. We typically use such shells to feed fifo buffers which we
do want to cancel them on Control-C. Make it so.
Same for SIGQUIT; that one is not typically used but I expect that
along the Kakoune server it kills any child processes that (haven't
been daemonized).
Note that for unknown reasons, Bash already doesn't ignore SIGINT in
async processes that use "eval".
Note that Dash has a bug that prevents this from working;
proposed fix is at
https://lore.kernel.org/dash/20240329153905.154792-2-aclopte@gmail.com/
(While at it balance out some parens, to help the m command)
Overloading SIGTERM like that causes issues; specifically if the
editor is invoked (without exec) from a wrapper script.
By sending SIGTERM to whole process group, we kill our parent process
(the wrapper script) which then sends SIGTERM to Kakoune. By this
time Kakoune has already reset the SIGTERM handler to the default
action and terminates.
We can use a different fix for the problem that some shells don't
cancel "make", see the next patch.
This reverts commit ec44d98347.
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
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
Only record non-synthetized insertions, removing the need to
re-record on replay and fixing the last replay getting dropped by
macro execution.
Fixes#5122
<c-n>/<c-p> handling in insert was always dropping the last key in
the last_insert() vector (in order to replace it with the actual
completion text inserted), this was not valid for synthetized keys
that are not added to that vector in the first place.
Take the opportunity to merge insert completion handling code between
<c-n>/<c-p> and direct menu selection.
Fixes#5120
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
After extracting the whole buffer content, a line can end up with
only non-range highlgihters pending which makes its range become
0.0,0.0, after running highlighting on the extracted range it gets
re-inserted but taking the min of existing range and inserted range
wrongly returns 0.0. Avoid this by detecting that the 0.0,0.0 range
does not actually mean anything when we have no ranged atoms.
Fixes#5001
It appears that the command to specify the `PREFIX` variable to the makefile has changed.
I had to run `make PREFIX=$HOME/.local install` in order to override the hardcoded `PREFIX` value in the makefile. I infer that the instructions need to be changed for those who don't know. (TIL. ;) )
Framed info boxes need one cell for the border and one for inner
space padding. That's 4 extra columns when counting both sides.
Frameless boxes have neither border nor padding so 0 columns here.
Closes#5106
Commit e43c7d6ab (Use complete-command for the :doc command,
2022-10-19) forgot to carry over the "-menu" flag, which means that
:doc completions are no longer auto-selected, even though they are
the only valid inputs.
Fix that.
Closes#4790
This sometimes allocates saves too eagerly, but it removes a branch
in release saves that executes on every thread failing which seems
slightly better.
When creating a new save, we had to clear all iterators to have valid
values. This operation is relatively costly because it gets optimized
to a memset whose call overhead is pretty high (as we usually have
less than 32 bytes to clear). Bypass this by storing a bitmap of
valid iterators.
Consider
sh -c 'sleep 5 & sleep inf'
Since the shell is non-interactive, there is no job control.
This makes the shell spawn the "sleep 5" process in the shell's own
process group[1] - presumably, because only interactive shells have
a need to forward signals to all processes in its foreground job.
When this non-interactive shell process is cancelled with SIGINT,
"sleep 5" keeps running [2]. At least the dash shell implements this
by running "signal(SIGINT, SIG_IGN)" in the forked child. Unless the
child process explicitly overrides that (to SIG_DFL for example), it
will ignore SIGINT. Probably the reason for this behavior is to feign
consistency with interactive shells, without needing to actually run
background jobs in a dedicated process group like interactive shells
do. Bash documents this behavior[3]:
> When job control is not in effect, asynchronous commands ignore
> SIGINT and SIGQUIT in addition to these inherited handlers.
Several of our scripts[4] - most prominently ":make" - use the
"</dev/null >/dev/null 2>&1 &" pattern to run potentially long-running
processes in the background, without blocking the editor.
On <c-c>, we send SIGINT to our process group.
As explained above, this will generally not terminate any background processes.
This problem has been masked by a behavior that is unique to using
both Bash and its "eval" builtin. Given
nop %sh{
rm -f /tmp/fifo
mkfifo /tmp/fifo
(
eval make >/tmp/fifo 2>&1 &
) >/dev/null 2>&1 </dev/null
}
edit -fifo /tmp/fifo *my-fifo*
When running this and pressing Control+C, Bash actually terminates
the Make processes. However if I remove the "eval", it no longer does.
This doesn't seems like something we should rely on.
Other commands like ":git blame" don't use "eval" so they cannot be
cancelled today.
Fix these issues by sending SIGTERM instead of SIGINT, which should
apply to the whole process group with pretty much the same effect.
Barely tested, let's see if this breaks some weird build system.
In future we might allow more fine-grained control over which processes
are cancelled by <c-c>.
{{{
Alternative solution:
With the above fix, scripts can opt-out of being terminated by <c-c>
by using setsid (though that's not POSIX unfortunately, and may
require nesting quotes) or the classic Unix double-forking trick to
create a daemon process.
Though it is certainly possible that someone expects commands like
this to survive <c-c>:
nop %sh{ tail -f my-log </dev/null 2>&1 | grep some-error > some-file 2>&1 & }
I think it would be ideal to stick to SIGINT and match semantics of
a noninteractive shell, to avoid muddying the waters.
Background processes could still **opt into** being terminated by
<c-c>. For example by providing a simple program in libexec/ that does
// interruptible.c
int main(int argc, char** argv) {
signal(SIGINT, SIG_DFL);
execv(argv[1], &argv[1]);
}
used as
diff --git a/rc/tools/make.kak b/rc/tools/make.kak
index b88f7e538..f6e041908 100644
--- a/rc/tools/make.kak
+++ b/rc/tools/make.kak
@@ -16,3 +16,3 @@ define-command -params .. \
mkfifo ${output}
- ( eval "${kak_opt_makecmd}" "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
+ ( eval "interruptible ${kak_opt_makecmd}" "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
Unfortunately, it's inconvenient to add "interruptible" to commands
like clang-parse and git-blame because they background a whole subshell
with many commands, so we'd need to nest quotes. Also I'm not sure
if this brings any benefit.
So I didn't explore this further yet although we can definitely do that.
}}}
Fixes#3751
[1]: https://stackoverflow.com/questions/45106725/why-do-shells-ignore-sigint-and-sigquit-in-backgrounded-processes/45106961#45106961
[2]: https://unix.stackexchange.com/questions/372541/why-doesnt-sigint-work-on-a-background-process-in-a-script/677742#677742
[3]: https://www.gnu.org/software/bash/manual/html_node/Signals.html
[4]: clang-parse, ctags-*, git blame, git log, gopls references,
grep, jedi-complete, lint-*, make; I don't think any of these
should be uninterruptible.
The tmux-terminal commands typically run
tmux split-window kak -c ${kak_session} </dev/null >/dev/null 2>&1 &
The tmux process runs in the background with output silenced. This is
not necessary because "tmux split-window" is a thin client that
merely forwards its arguments to the tmux server. All our wrappers
for other terminal-servers (kitty, iterm, screen, wezterm, zellij)
simply run in the foreground, not silencing any errors.
The tmux backgrounding was added in 208b91627 (Move client.kak as
x11.kak and change tmux.kak to be its peer, 2015-11-17), probably for
consistency with x11.kak. That one is different however because it
potentially spawns a full terminal, not just a client that briefly
talks to a terminal server - that's why x11-terminal needs to use
"setsid," to avoid killing said terminal when we signal our process
group.
Remove the backgrounding from tmux.kak for consistency and to reduce
surprise.
`grep-next-match` works only on the `*grep*` buffer so it can't be used
on buffers that were preserved by renaming or on other grep-flavored
buffers created by 3rd party plugins kakoune-find and kakoune-lsp,
like `*find*` and `*references*`.
Let's generalize `grep-next-match` with a `jump-next` command that
takes a buffer argument.
This renames some options but I think they're not commonly used.
kakoune-lsp is an exception that uses grep_current_line but it's no big
deal, things will fail loud and early if options are missing.
Since grep.kak and friends now depend on jump.kak, move the jumpclient
declaration there as well.