mirror of
https://github.com/mawww/kakoune.git
synced 2024-08-16 16:20:38 +03:00
Compare commits
15 Commits
504adf6294
...
4b04f666f7
Author | SHA1 | Date | |
---|---|---|---|
|
4b04f666f7 | ||
|
e0bbd1e7ca | ||
|
8ca7b5815a | ||
|
80fcfebca8 | ||
|
cbdd200e73 | ||
|
0a10612786 | ||
|
07000adb9b | ||
|
374a7a8c99 | ||
|
6674fe7587 | ||
|
4a00a6edea | ||
|
6493ddad42 | ||
|
880ad98a30 | ||
|
0bb355557e | ||
|
1bd5637b56 | ||
|
eb5db3f0fd |
@ -455,8 +455,8 @@ using the built-in `:doc` command.
|
||||
| Q | chunk interactively, and replay the sequence of keys
|
||||
`---' at will. The sequence in question is a macro: the `Q`
|
||||
primitive will create a new one (i.e., record all the keys
|
||||
.---, .---, hit henceforth until the escape key `<esc>` is hit), and
|
||||
|ctl|+| r |_. the `q` primitive will replay the keys saved in the macro.
|
||||
.---, .---, hit henceforth until `Q` is hit again), and the `q`
|
||||
|ctl|+| r |_. primitive will replay the keys saved in the macro.
|
||||
`---' `---' `.---,
|
||||
| @ | Notes: macros can easily be translated into a proper
|
||||
`---' script, as they are saved in the `@` register, which you
|
||||
|
@ -41,22 +41,27 @@ highlighter is replaced with the new one.
|
||||
using the `Whitespace` face, with the following *options*:
|
||||
|
||||
*-lf* <separator>:::
|
||||
a one character long separator that will replace line feeds
|
||||
a one character long separator that will replace line feeds,
|
||||
or an empty string to ignore them.
|
||||
|
||||
*-spc* <separator>:::
|
||||
a one character long separator that will replace spaces
|
||||
a one character long separator that will replace spaces,
|
||||
or an empty string to ignore them.
|
||||
|
||||
*-nbsp* <separator>:::
|
||||
a one character long separator that will replace non-breakable spaces
|
||||
a one character long separator that will replace non-breakable spaces,
|
||||
or an empty string to ignore them.
|
||||
|
||||
*-tab* <separator>:::
|
||||
a one character long separator that will replace tabulations
|
||||
a one character long separator that will replace tabulations,
|
||||
or an empty string to ignore them.
|
||||
|
||||
*-tabpad* <separator>:::
|
||||
a one character long separator that will be appended to tabulations to honor the *tabstop* option
|
||||
|
||||
*-indent* <separator>:::
|
||||
a one character long separator that will replace the first space in indentation according to the *indentwidth* option
|
||||
a one character long separator that will replace the first space in indentation
|
||||
according to the *indentwidth* option, or an empty string to ignore them.
|
||||
This will use the `WhitespaceIndent` face.
|
||||
|
||||
*-only-trailing*:::
|
||||
|
@ -147,6 +147,11 @@ name. Hooks with no description will always use an empty string.
|
||||
*SessionRenamed* `<old name>:<new name>`::
|
||||
executed when a session is renamed using the `rename-session` command
|
||||
|
||||
*EnterDirectory* `path`::
|
||||
executed on startup and when the current working directory is changed
|
||||
using the `change-directory` command. The hook param is an absolute path
|
||||
to the new working directory.
|
||||
|
||||
*RuntimeError* `error message`::
|
||||
an error was encountered while executing a user command
|
||||
|
||||
|
@ -8,7 +8,7 @@ hook global BufCreate .*[.](ex|exs) %{
|
||||
set-option buffer filetype elixir
|
||||
}
|
||||
|
||||
hook global BufCreate .*[.]html[.]l?eex %{
|
||||
hook global BufCreate .*[.]html[.][lh]?eex %{
|
||||
set-option buffer filetype eex
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ add-highlighter shared/elixir/single_string region "'" "(?<!\\)(?:\\\\)*'" fill
|
||||
add-highlighter shared/elixir/comment region '#' '$' fill comment
|
||||
|
||||
add-highlighter shared/elixir/leex region -match-capture '~L("""|")' '(?<!\\)(?:\\\\)*("""|")' ref eex
|
||||
add-highlighter shared/elixir/heex region -match-capture '~H("""|")' '(?<!\\)(?:\\\\)*("""|")' ref eex
|
||||
|
||||
add-highlighter shared/elixir/double_string/base default-region fill string
|
||||
add-highlighter shared/elixir/double_string/interpolation region -recurse \{ \Q#{ \} fill builtin
|
||||
|
@ -75,7 +75,7 @@ hook global BufSetOption filetype=(html|xml) %{
|
||||
set-option buffer comment_block_end '-->'
|
||||
}
|
||||
|
||||
hook global BufSetOption filetype=(latex|mercury) %{
|
||||
hook global BufSetOption filetype=(erlang|latex|mercury) %{
|
||||
set-option buffer comment_line '%'
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
provide-module fifo %{
|
||||
|
||||
define-command -params .. -docstring %{
|
||||
fifo [-name <buffer-name>] [-scroll] [--] <command>...: run command in a fifo buffer
|
||||
fifo [-name <name>] [-scroll] [-script <script>] [--] <args>...: run command in a fifo buffer
|
||||
if <script> is used, eval it with <args> as '$@', else pass arguments directly to the shell
|
||||
} fifo %{ evaluate-commands %sh{
|
||||
name='*fifo*'
|
||||
while true; do
|
||||
case "$1" in
|
||||
"-scroll") scroll="-scroll"; shift ;;
|
||||
"-script") script="$2"; shift 2 ;;
|
||||
"-name") name="$2"; shift 2 ;;
|
||||
"--") shift; break ;;
|
||||
*) break ;;
|
||||
@ -14,7 +16,11 @@ define-command -params .. -docstring %{
|
||||
done
|
||||
output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-fifo.XXXXXXXX)/fifo
|
||||
mkfifo ${output}
|
||||
( eval "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
|
||||
if [ -n "$script" ]; then
|
||||
( eval "$script" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
|
||||
else
|
||||
( "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
|
||||
fi
|
||||
|
||||
printf %s\\n "
|
||||
edit! -fifo ${output} ${scroll} ${name}
|
||||
|
@ -12,8 +12,7 @@ define-command -params .. -docstring %{
|
||||
Passing no argument will perform a literal-string grep for the current selection
|
||||
} grep %{
|
||||
evaluate-commands -try-client %opt{toolsclient} %{
|
||||
fifo -name *grep* %{
|
||||
shift 2
|
||||
fifo -name *grep* -script %{
|
||||
trap - INT QUIT
|
||||
if [ $# -eq 0 ]; then
|
||||
case "$kak_opt_grepcmd" in
|
||||
@ -29,7 +28,7 @@ define-command -params .. -docstring %{
|
||||
esac
|
||||
fi
|
||||
$kak_opt_grepcmd "$@" 2>&1 | tr -d '\r'
|
||||
} 'exit;' %arg{@} # pass arguments for "$@" above, exit to avoid evaluating them
|
||||
} -- %arg{@}
|
||||
set-option buffer filetype grep
|
||||
set-option buffer jump_current_line 0
|
||||
}
|
||||
|
@ -13,11 +13,10 @@ define-command -params .. -docstring %{
|
||||
All the optional arguments are forwarded to the make utility
|
||||
} make %{
|
||||
evaluate-commands -try-client %opt{toolsclient} %{
|
||||
fifo -scroll -name *make* %{
|
||||
shift 2
|
||||
fifo -scroll -name *make* -script %{
|
||||
trap - INT QUIT
|
||||
$kak_opt_makecmd "$@"
|
||||
} 'exit;' %arg{@} # pass arguments for "$@" above, exit to avoid evaluating them
|
||||
} -- %arg{@}
|
||||
set-option buffer filetype make
|
||||
set-option buffer jump_current_line 0
|
||||
}
|
||||
|
@ -2600,13 +2600,15 @@ const CommandDesc change_directory_cmd = {
|
||||
cursor_pos, FilenameFlags::OnlyDirectories),
|
||||
Completions::Flags::Menu };
|
||||
}),
|
||||
[](const ParametersParser& parser, Context&, const ShellContext&)
|
||||
[](const ParametersParser& parser, Context& ctx, const ShellContext&)
|
||||
{
|
||||
StringView target = parser.positional_count() == 1 ? StringView{parser[0]} : "~";
|
||||
if (chdir(parse_filename(target).c_str()) != 0)
|
||||
auto path = real_path(parse_filename(target));
|
||||
if (chdir(path.c_str()) != 0)
|
||||
throw runtime_error(format("unable to change to directory: '{}'", target));
|
||||
for (auto& buffer : BufferManager::instance())
|
||||
buffer->update_display_name();
|
||||
ctx.hooks().run_hook(Hook::EnterDirectory, path, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -981,18 +981,14 @@ struct ShowWhitespacesHighlighter : Highlighter
|
||||
bool only_trailing = (bool) parser.get_switch("only-trailing");
|
||||
auto get_param = [&](StringView param, StringView fallback) {
|
||||
StringView value = parser.get_switch(param).value_or(fallback);
|
||||
if (value.char_length() != 1)
|
||||
throw runtime_error{format("-{} expects a single character parameter", param)};
|
||||
if (value.char_length() > 1)
|
||||
throw runtime_error{format("-{} expects a single character or empty parameter", param)};
|
||||
return value.str();
|
||||
};
|
||||
|
||||
String indent = parser.get_switch("indent").value_or("│").str();
|
||||
if (indent.char_length() > 1)
|
||||
throw runtime_error{format("-indent expects a single character or empty parameter")};
|
||||
|
||||
return std::make_unique<ShowWhitespacesHighlighter>(
|
||||
get_param("tab", "→"), get_param("tabpad", " "), get_param("spc", "·"),
|
||||
get_param("lf", "¬"), get_param("nbsp", "⍽"), indent, only_trailing);
|
||||
get_param("lf", "¬"), get_param("nbsp", "⍽"), get_param("indent", "│"), only_trailing);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1043,28 +1039,28 @@ private:
|
||||
if (it != end)
|
||||
atom_it = line.split(atom_it, it.coord());
|
||||
|
||||
if (cp == '\t')
|
||||
if (cp == '\t' and not m_tab.empty() and not m_tabpad.empty())
|
||||
{
|
||||
const ColumnCount column = get_column(buffer, tabstop, coord);
|
||||
const ColumnCount count = tabstop - (column % tabstop);
|
||||
atom_it->replace(m_tab + String(m_tabpad[(CharCount)0], count - m_tab.column_length()));
|
||||
}
|
||||
else if (cp == ' ') {
|
||||
if (m_indent.empty() or indentwidth == 0 or not is_indentation) {
|
||||
else if (cp == ' ' and is_indentation and indentwidth > 0 and not m_indent.empty()) {
|
||||
const ColumnCount column = get_column(buffer, tabstop, coord);
|
||||
if (column % indentwidth == 0 and column != 0) {
|
||||
atom_it->replace(m_indent);
|
||||
face = indentface;
|
||||
}
|
||||
else {
|
||||
atom_it->replace(m_spc);
|
||||
} else {
|
||||
const ColumnCount column = get_column(buffer, tabstop, coord);
|
||||
if (column % indentwidth == 0 and column != 0) {
|
||||
atom_it->replace(m_indent);
|
||||
face = indentface;
|
||||
} else {
|
||||
atom_it->replace(m_spc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cp == '\n')
|
||||
else if (cp == ' ' and not m_spc.empty()) {
|
||||
atom_it->replace(m_spc);
|
||||
}
|
||||
else if (cp == '\n' and not m_lf.empty())
|
||||
atom_it->replace(m_lf);
|
||||
else if (cp == 0xA0 or cp == 0x202F)
|
||||
else if ((cp == 0xA0 or cp == 0x202F) and not m_nbsp.empty())
|
||||
atom_it->replace(m_nbsp);
|
||||
atom_it->face = merge_faces(atom_it->face, face);
|
||||
break;
|
||||
|
@ -50,6 +50,7 @@ enum class Hook
|
||||
NextKeyIdle,
|
||||
NormalKey,
|
||||
ModeChange,
|
||||
EnterDirectory,
|
||||
RawKey,
|
||||
RegisterModified,
|
||||
WinClose,
|
||||
@ -97,6 +98,7 @@ constexpr auto enum_desc(Meta::Type<Hook>)
|
||||
{Hook::NextKeyIdle, "NextKeyIdle"},
|
||||
{Hook::NormalKey, "NormalKey"},
|
||||
{Hook::ModeChange, "ModeChange"},
|
||||
{Hook::EnterDirectory, "EnterDirectory"},
|
||||
{Hook::RawKey, "RawKey"},
|
||||
{Hook::RegisterModified, "RegisterModified"},
|
||||
{Hook::WinClose, "WinClose"},
|
||||
|
@ -842,6 +842,7 @@ int run_server(StringView session, StringView server_init,
|
||||
|
||||
{
|
||||
Context empty_context{Context::EmptyContextFlag{}};
|
||||
global_scope.hooks().run_hook(Hook::EnterDirectory, real_path("."), empty_context);
|
||||
global_scope.hooks().run_hook(Hook::KakBegin, session, empty_context);
|
||||
}
|
||||
|
||||
|
@ -589,13 +589,13 @@ void pipe(Context& context, NormalParams params)
|
||||
return;
|
||||
|
||||
Buffer& buffer = context.buffer();
|
||||
SelectionList selections = context.selections();
|
||||
if (replace)
|
||||
{
|
||||
buffer.throw_if_read_only();
|
||||
ScopedEdition edition(context);
|
||||
ForwardChangesTracker changes_tracker;
|
||||
size_t timestamp = buffer.timestamp();
|
||||
Vector<Selection> new_sels;
|
||||
SelectionList selections = context.selections();
|
||||
for (auto& sel : selections)
|
||||
{
|
||||
const auto beg = changes_tracker.get_new_coord_tolerant(sel.min());
|
||||
@ -614,20 +614,27 @@ void pipe(Context& context, NormalParams params)
|
||||
|
||||
auto new_end = apply_diff(buffer, beg, in, out);
|
||||
if (new_end != beg)
|
||||
new_sels.push_back(keep_direction({beg, buffer.char_prev(new_end), std::move(sel.captures())}, sel));
|
||||
{
|
||||
auto& min = sel.min();
|
||||
auto& max = sel.max();
|
||||
min = beg;
|
||||
max = buffer.char_prev(new_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_end != BufferCoord{})
|
||||
new_end = buffer.char_prev(new_end);
|
||||
new_sels.push_back({new_end, new_end, std::move(sel.captures())});
|
||||
sel.set(new_end);
|
||||
}
|
||||
|
||||
changes_tracker.update(buffer, timestamp);
|
||||
}
|
||||
context.selections_write_only().set(std::move(new_sels), selections.main_index());
|
||||
selections.force_timestamp(timestamp);
|
||||
context.selections_write_only() = std::move(selections);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectionList& selections = context.selections();
|
||||
const auto old_main = selections.main_index();
|
||||
for (int i = 0; i < selections.size(); ++i)
|
||||
{
|
||||
|
@ -753,7 +753,10 @@ private:
|
||||
{
|
||||
auto node = compile_node<direction>(child);
|
||||
if (child != index+1)
|
||||
m_program.instructions[--split_pos].param.split = CompiledRegex::Param::Split{.offset = offset(node, split_pos), .prioritize_parent = true};
|
||||
{
|
||||
--split_pos;
|
||||
m_program.instructions[split_pos].param.split = {.offset = offset(node, split_pos), .prioritize_parent = true};
|
||||
}
|
||||
if (get_node(child).children_end != end)
|
||||
{
|
||||
auto jump = push_inst(CompiledRegex::Jump);
|
||||
|
Loading…
Reference in New Issue
Block a user