This commit allows using the <semicolon> expansion in commands, instead
of `\;`.
It makes commands look more elegant, and prevents new-comers from
falling into the trap of using <a-;> without escaping the semicolon.
Pass an ArrayView<DisplayAtom> instead of a DisplayLine& so that
the newly common case of passing a single atom does not require
constructing a Vector.
When trimming indent, the last line, if only containing
whitespaces does not need to match the indent, so that
this indentation style works:
-docstring %{
indented string
}
std::function is not necessary when we just want to pass a type
erased callback that does not need to own its target. FunctionRef
provides that functionality for a much lower compile time cost.
Whenever a tool spawns the editor (e.g. Git), suspending it with ^Z is not
enough to be sent back to the calling shell - another ^Z is necessary.
Fixes#3061
The UI now can send a 'Scroll' key, whose value is the scrolling
amount encoded as a signed integer. This replaces the MouseWheelUp
and MouseWheelDown keys.
The NCursesUI now has a ncurses_wheel_scroll_amount ui_option that
controls that amount, it can be negative to swap scrolling direction.
Fixes#3045
First try to break at a whitespace, if that fails (likely because
that last WORD is too long for the wrapping width), then try to
wrap at a 'word' boundary (on a non alphanumeric character).
Fixes#3048
Falls back on old mechanism if `XDG_RUNTIME_DIR` is not set.
The ability to specify a session as "<user>/<name>" was removed, since
it isn't possible to compute the value of `XDG_RUNTIME_DIR` for another
user, we wouldn't have access to it if we could, and it would be awkward
to support this feature only when `XDG_RUNTIME_DIR` is unset. Also,
`rename-session` did not work when another user's session was specified.
Closes#3019
This commit implements formatting behaviour when the first character of a
docstring is a newline. In that case, the exact indentation level of the
next line will be removed from that line and all subsequent non-empty lines.
An error will be returned if a subsequent non-empty line does not have the
same indentation level.
The docstrings are always trimmed (surrounding whitespaces) whether the
first character is a newline or not, as was the case prior to this commit.
Example: the following declaration
```
define-command test -docstring %{
test: do something
Nothing really.
More
indented
lines.
} nop
```
would be rendered as
```
test: do something
Nothing really.
More
indented
lines.
```
Related to #2405
file.cc:390:21: error: use of undeclared identifier 'rename'; did you mean 'devname'?
if (replace and rename(temp_filename, zfilename) != 0)
^~~~~~
devname
/usr/include/stdlib.h:277:7: note: 'devname' declared here
char *devname(__dev_t, __mode_t);
^
file.cc:390:28: error: cannot initialize a parameter of type '__dev_t' (aka 'unsigned long') with an lvalue of type 'char [1024]'
if (replace and rename(temp_filename, zfilename) != 0)
^~~~~~~~~~~~~
/usr/include/stdlib.h:277:22: note: passing argument to parameter here
char *devname(__dev_t, __mode_t);
^
2 errors generated.
---
highlighters.cc:1110:13: error: use of undeclared identifier 'snprintf'; did you mean 'vswprintf'?
snprintf(buffer, 16, format, std::abs(line_to_format));
^~~~~~~~
vswprintf
/usr/include/wchar.h:139:5: note: 'vswprintf' declared here
int vswprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
highlighters.cc:1110:22: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'char [16]'
snprintf(buffer, 16, format, std::abs(line_to_format));
^~~~~~
/usr/include/wchar.h:139:35: note: passing argument to parameter here
int vswprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
2 errors generated.
---
json_ui.cc:60:13: error: use of undeclared identifier 'sprintf'; did you mean 'swprintf'?
sprintf(buf, "\\u%04x", *next);
^~~~~~~
swprintf
/usr/include/wchar.h:133:5: note: 'swprintf' declared here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
json_ui.cc:60:21: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'char [7]'
sprintf(buf, "\\u%04x", *next);
^~~
/usr/include/wchar.h:133:34: note: passing argument to parameter here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
json_ui.cc:74:9: error: use of undeclared identifier 'sprintf'
sprintf(buffer, R"("#%02x%02x%02x")", color.r, color.g, color.b);
^
3 errors generated.
---
regex_impl.cc:1039:9: error: use of undeclared identifier 'sprintf'; did you mean 'swprintf'?
sprintf(buf, " %03d ", count++);
^~~~~~~
swprintf
/usr/include/wchar.h:133:5: note: 'swprintf' declared here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
regex_impl.cc:1039:17: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'char [20]'
sprintf(buf, " %03d ", count++);
^~~
/usr/include/wchar.h:133:34: note: passing argument to parameter here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
regex_impl.cc:1197:17: error: use of undeclared identifier 'puts'
{ if (dump) puts(dump_regex(*this).c_str()); }
^
regex_impl.cc:1208:18: note: in instantiation of member function 'Kakoune::(anonymous namespace)::TestVM<Kakoune::RegexMode::Forward>::TestVM' requested here
TestVM<> vm{R"(a*b)"};
^
regex_impl.cc:1197:17: error: use of undeclared identifier 'puts'
{ if (dump) puts(dump_regex(*this).c_str()); }
^
regex_impl.cc:1283:56: note: in instantiation of member function 'Kakoune::(anonymous namespace)::TestVM<5>::TestVM' requested here
TestVM<RegexMode::Forward | RegexMode::Search> vm{R"(f.*a(.*o))"};
^
regex_impl.cc:1197:17: error: use of undeclared identifier 'puts'
{ if (dump) puts(dump_regex(*this).c_str()); }
^
regex_impl.cc:1423:57: note: in instantiation of member function 'Kakoune::(anonymous namespace)::TestVM<6>::TestVM' requested here
TestVM<RegexMode::Backward | RegexMode::Search> vm{R"(fo{1,})"};
^
5 errors generated.
---
remote.cc:829:9: error: use of undeclared identifier 'rename'; did you mean 'devname'?
if (rename(old_socket_file.c_str(), new_socket_file.c_str()) != 0)
^~~~~~
devname
/usr/include/stdlib.h:277:7: note: 'devname' declared here
char *devname(__dev_t, __mode_t);
^
remote.cc:829:16: error: cannot initialize a parameter of type '__dev_t' (aka 'unsigned long') with an rvalue of type 'const char *'
if (rename(old_socket_file.c_str(), new_socket_file.c_str()) != 0)
^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/stdlib.h:277:22: note: passing argument to parameter here
char *devname(__dev_t, __mode_t);
^
2 errors generated.
---
string_utils.cc:126:20: error: use of undeclared identifier 'sprintf'; did you mean 'swprintf'?
res.m_length = sprintf(res.m_data, "%i", val);
^~~~~~~
swprintf
/usr/include/wchar.h:133:5: note: 'swprintf' declared here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
string_utils.cc:126:28: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'char [15]'
res.m_length = sprintf(res.m_data, "%i", val);
^~~~~~~~~~
/usr/include/wchar.h:133:34: note: passing argument to parameter here
int swprintf(wchar_t * __restrict, size_t n, const wchar_t * __restrict,
^
string_utils.cc:133:20: error: use of undeclared identifier 'sprintf'; did you mean 'swprintf'?
res.m_length = sprintf(res.m_data, "%u", val);
^~~~~~~
swprintf
[...]
History registers (for prompt commands, pipe primitive commands etc) are
populated interactively by the users, and currently have no size limit.
This commits silently drops the oldest entries in the storage space to
allow at most 100 entries, to prevent long-running editing sessions from
hogging memory for data most likely never used.
This commit makes the `*` and <a-*> primitives compose a search pattern
comprised of all the current selections, as opposed to only the main one.
All selections are OR'd into the default search register, which makes it
convenient to search for several identifiers already selected.
To retain the old behaviour, the following mappings can be used:
```
map global normal * ': exec -draft -save-regs "" %{<space>*}<ret>'
map global normal <a-*> ': exec -draft -save-regs "" %{<space><a-*>}<ret>'
```
Fixes#2994
The `parse_keys()` function is case insensitive when parsing function keys,
while the `key_to_str()` function always returns a capitalized key
description.
When users hook on the lowercase name of a function key,
e.g. `NormalKey <f10>`, and later hit that same key in normal mode, the
`key_to_str()` will convert it to the uppercase description ("<F10>").
This results into a hook with a lowercase regex predicate being unsuccessfully
matched against an uppercase key description by the hook manager, which
works on a case sensitive basis.
One solution could be to uppercase all function key descriptions passed as
hook filter upon declaration, but detecting that is not trivial as the
filter can contain more than just the simple <f\d+> data, e.g.
---
hook global InsertKey '<(?<name>\w+)>' %{…}
---
Another simpler solution that this commit implements is to allow only <F\d+>
descriptions in `parse_keys()`, and hope users will know not to use the
lowercase notation when declaring hooks.
Fixes#2907
The previous "optimized" history register logic was unfortunately
not restoring correctly as the order of entries in the history
register could have been mutated.
The hook parameter should not be adjusted for the prevention of
scrolling. Also, ensure that the last BufReadFifo is triggered if we
encounter an error or EOF after appending some data to the buffer.
Closes#2946
On my system, some optimizations are on by default (NixOS), resulting in
variables being optimized out on debug builds. It *seems to be*
something about a "_FORTIFY_SOURCE" feature? In any case, `-Og` is
documented as "Optimize debugging experience".
Using <fg>,<bg>+<attr>@<base> will apply the given fg color,
bg color and attributes on top of base dynamically. Simply giving
<base> is a shorthand for default,default@<base>.
Inspired by the discussion in #2862
Sometimes we really need to have a String instead of a StringView,
but some of those strings might not need to own their data. Make
it possible to explicitely construct a String that does not own
the underlying buffer.
Use it when parsing balanced strings.
This permit to choose if files should be written by overwriting their
content (the default), or by writing to a separate temporary file
and rename it to the current file.
As discussed in #2036
The current implementation is wrong as it crosses basic blocks
boundaries. Doing basic block decomposition of regex is probably
a tad too complex for this single optimization.
Fixes#2711
This should reduce the number of allocations as the memory allocated
for the thread stack and the saves can be re-used between runs instead
of being cleared every time.
The current implementation treats left mouse button clicks as a
generic "mouse press" modifier, this commit extends the list of
modifiers by adding a "right mouse click" one.
The proper way to implement this would be to ship the coordinates
of mouse key press events in each `Key` object, and pass whichever
button was clicked as a codepoint value (instead of coordinates
currently), but this would require more work.
This commit allows:
* right clicks to set the cursor of the main selection
* control-right clicks to merge all the selections, and then set
its cursor
Fixes#843
By setting the ncurses_builtin_key_parser ui_option to true, we
can disable ncurses parsing of key strokes to get less portable
parsing but support for more complex modifiers.
Probably, the extra «s» at the end of «exist» was added accidentally. A verb after «does not» in Present Simple definitely shouldn't have this extra «s».
Ideally, something better should be done (re #2554) but this is a decent
intermediate step for some useful keys.
Note: NCurses supports parsing these keys when shifted (KEY_SR,
_SLEFT, S_RIGHT, etc), but it does not do the same thing for the other
modifiers.
Not having the `test` target (in the Makefile) depend on the `kak` one
prevents users from running commands that make use of parallelism, e.g.:
$ make -j all test
The above command sometimes results in the test suite running before
the binary has been compiled and symlinked, resulting in failures.
SIG_IGN is inherited after 'execve' and requires us to reset
that signal handler, which does not work well with vfork on
OSX. Using an empty function does the trick and will be auto
reset to default on exec.
When large buffers have been opened, copying Kakoune's memory
page descriptors can get pretty slow, making fork more expensive
than necessary.
vfork avoids that problem. While not strictly conforming, it seems
the few calls we do before execve (open, close, dup2 and
set_signal_handler) would not cause any problems on platforms we
care about.