1
1
mirror of https://github.com/mawww/kakoune.git synced 2024-08-16 16:20:38 +03:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Johannes Altmanninger
ba0e64ad88
Merge 09cd7207c0 into 80fcfebca8 2024-06-27 08:29:13 +00:00
Maxime Coste
80fcfebca8 Fix order of evaluation issue when compiling regex alternations
The previous implementation was relying on the left hand side of the
assignement's side effects to be sequenced before the right hand side
evaluation (so --split_pos was expected to have taken place)

This is actually counter to C++17 which guarantees evaluation of the
right hand side of the assignement first. For some reason this is
not the case with GCC on linux.
2024-06-26 22:38:01 +10:00
Maxime Coste
cbdd200e73 Fix corner case in passin arguments to grep and make 2024-06-26 20:35:34 +10:00
Maxime Coste
374a7a8c99 Remove some selection copies in pipe and throw early if read only
Throwing early avoids losing selections in this case.
2024-06-24 21:18:17 +10:00
Maxime Coste
6674fe7587 Merge remote-tracking branch 'stacyharper/elixir-heex' 2024-06-23 11:14:34 +10:00
Maxime Coste
4a00a6edea Fix trailing whitespaces 2024-06-23 11:03:50 +10:00
Tobias Pisani
6493ddad42 Allow individual show-whitespace options to be turned off
This is especially useful to use the indent guides without the  other
parameters, but in general it can be a useful option.

It could be worth considering cleaning up these options to default off instead, but
the default also seems useful, so i consider this ok, as it might be the more advanced
usecase.
2024-06-23 11:03:03 +10:00
Maxime Coste
880ad98a30 Add a -script switch to the fifo to cater for grep/make use cases
Avoid the brittle `exit; %arg{@}` trick
2024-06-22 17:02:54 +10:00
Willow Barraco
0bb355557e
elixir: detect heex additionaly to leex 2024-06-19 12:45:20 +02:00
Maxime Coste
ba504431dc Small code style tweak 2024-06-15 16:09:14 +10:00
Maxime Coste
c4684d0d84 Store instruction pointers directly in ThreadedRegexVM::Thread
The previous tradeoff of having a very small Thread struct is not
necessary anymore as we do not memcpy Threads on swap_next since
d708b77186.

This requires offsets to be used instead of indices for jump/split
ops.
2024-06-15 14:36:33 +10:00
Maxime Coste
c84942c2ac Add perf-annotate highlighting to perf.kak 2024-06-15 11:45:19 +10:00
Johannes Altmanninger
09cd7207c0 Use menu behavior when completing %opt/%val expansions
Now that the completions include closing delimiters, this is actually
useful because we can type

	echo %val{bufn<ret>

and it will do the right thing.

Don't include register expansions because we currently don't offer
completions for all registers. (We could add that fairly easily.
We'd want to handle some interesting edge cases.  For example query
%reg| should be completed to %reg|:| but also %reg||||.)

File expansions of files that contain a quoting delimiter will be
wrong but that's an unrelated problem, and also pretty minor since
%file{} is rarely used interactively.
2023-05-09 11:32:37 +02:00
Johannes Altmanninger
52b8828a06 Add closing delimiter to completions of %opt/%file/%reg/%val expansion
This looks a bit weird but it's exactly what the user needs to type
anyway.  Adding the closing delimiter later (when the completion is
accepted) would be less predictable.
2023-05-09 11:32:37 +02:00
Johannes Altmanninger
9dde483741 Teach token about its closing delimiter
Will use in the next commit.
2023-05-09 11:32:37 +02:00
Johannes Altmanninger
c6e022725f Use "" instead of {} to initialize empty tokens' contents
Makes it a bit easier to see which constructor argument is which.
2023-05-09 11:32:37 +02:00
Johannes Altmanninger
9ad39c5263 Complete possible expansions in prompt
When typing %, suggest possible expansion types.
This is pretty minor, happy to drop it.
2023-05-09 11:32:37 +02:00
20 changed files with 174 additions and 111 deletions

View File

@ -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*:::

View File

@ -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

View File

@ -16,3 +16,17 @@ hook -group perf-report-highlight global WinSetOption filetype=perf-report %{
map window normal <ret> ': perf-report-focus<ret>'
}
provide-module perf-annotate %{
require-module gas
add-highlighter shared/perf-annotate group
add-highlighter shared/perf-annotate/gas ref gas
add-highlighter shared/perf-annotate/above_threshold regex '^\h+([1-9]|\d{2})\.\d+\b' 0:red
add-highlighter shared/perf-annotate/below_threshold regex '^\h+0\.\d+\b' 0:green
}
hook -group perf-annotate-highlight global WinSetOption filetype=perf-annotate %{
require-module perf-annotate
add-highlighter window/perf-annotate ref perf-annotate
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/perf-annotate }
}

View File

@ -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}

View File

@ -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
}

View File

@ -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
}

View File

@ -280,6 +280,8 @@ Token parse_percent_token(ParseState& state, bool throw_on_unterminated)
if (throw_on_unterminated)
throw parse_error{format("expected a string delimiter after '%{}'",
type_name)};
if (at_end)
return {Token::Type::UnknownExpand, type_start - state.str.begin(), type_name.str()};
return {};
}
@ -307,7 +309,7 @@ Token parse_percent_token(ParseState& state, bool throw_on_unterminated)
it->opening, it->closing)};
}
return {type, byte_pos, std::move(quoted.content), quoted.terminated};
return {type, byte_pos, std::move(quoted.content), {{(Codepoint)it->closing, quoted.terminated}}};
}
else
{
@ -322,7 +324,7 @@ Token parse_percent_token(ParseState& state, bool throw_on_unterminated)
opening_delimiter, opening_delimiter)};
}
return {type, byte_pos, std::move(quoted.content), quoted.terminated};
return {type, byte_pos, std::move(quoted.content), {{opening_delimiter, quoted.terminated}}};
}
}
@ -431,7 +433,7 @@ Optional<Token> CommandParser::read_token(bool throw_on_unterminated)
return Token{c == '"' ? Token::Type::Expand
: Token::Type::RawQuoted,
start - line.begin(), std::move(quoted.content),
quoted.terminated};
{{(Codepoint)c, quoted.terminated}}};
}
else if (c == '%')
{
@ -440,7 +442,7 @@ Optional<Token> CommandParser::read_token(bool throw_on_unterminated)
}
else if (is_command_separator(c))
return Token{Token::Type::CommandSeparator,
++m_state.pos - line.begin(), {}};
++m_state.pos - line.begin(), ""};
else
{
if (c == '\\' and m_state.pos + 1 != m_state.str.end())
@ -659,37 +661,51 @@ static Completions complete_expansion(const Context& context, CompletionFlags fl
Token token, ByteCount start,
ByteCount cursor_pos, ByteCount pos_in_token)
{
CandidateList candidates;
switch (token.type) {
case Token::Type::RegisterExpand:
return { start, cursor_pos,
RegisterManager::instance().complete_register_name(
token.content, pos_in_token) };
candidates = RegisterManager::instance().complete_register_name(token.content, pos_in_token);
break;
case Token::Type::OptionExpand:
return { start, cursor_pos,
GlobalScope::instance().option_registry().complete_option_name(
token.content, pos_in_token) };
candidates = GlobalScope::instance().option_registry().complete_option_name(token.content, pos_in_token);
break;
case Token::Type::ShellExpand:
return offset_pos(shell_complete(context, flags, token.content,
pos_in_token), start);
case Token::Type::ValExpand:
return { start, cursor_pos,
ShellManager::instance().complete_env_var(
token.content, pos_in_token) };
candidates = ShellManager::instance().complete_env_var(token.content, pos_in_token);
break;
case Token::Type::FileExpand:
{
const auto& ignored_files = context.options()["ignored_files"].get<Regex>();
return { start, cursor_pos, complete_filename(
token.content, ignored_files, pos_in_token, FilenameFlags::Expand) };
candidates = complete_filename(token.content, ignored_files, pos_in_token, FilenameFlags::Expand);
break;
}
case Token::Type::UnknownExpand:
return { start, cursor_pos, Kakoune::complete(token.content, cursor_pos, Array{"exp", "file", "opt", "reg", "sh", "val"}) };
default:
kak_assert(false);
throw runtime_error("unknown expansion");
}
for (auto &c : candidates)
{
if ((token.type == Token::Type::ValExpand and c.ends_with("_")) // opt_, reg_, client_env_
or (token.type == Token::Type::FileExpand and c.ends_with("/")))
continue;
kak_assert(not token.terminator->present);
c += to_string(token.terminator->character);
}
auto completions_flags = token.type == Token::Type::RegisterExpand
? Completions::Flags::None : Completions::Flags::Menu;
return { start, cursor_pos, candidates, completions_flags };
}
static Completions complete_expand(const Context& context, CompletionFlags flags,
@ -706,7 +722,7 @@ static Completions complete_expand(const Context& context, CompletionFlags flags
else
{
auto token = parse_percent_token(state, false);
if (token.terminated)
if (token.terminator and token.terminator->present)
continue;
if (token.type == Token::Type::Raw or token.type == Token::Type::RawQuoted)
return {};
@ -771,11 +787,11 @@ Completions CommandManager::Completer::operator()(
}
if (is_last_token)
tokens.push_back({Token::Type::Raw, prefix.length(), {}});
tokens.push_back({Token::Type::Raw, prefix.length(), ""});
kak_assert(not tokens.empty());
const auto& token = tokens.back();
if (token.terminated) // do not complete past explicit token close
if (token.terminator and token.terminator->present) // do not complete past explicit token close
return Completions{};
const ByteCount start = token.pos;
@ -797,6 +813,7 @@ Completions CommandManager::Completer::operator()(
case Token::Type::ShellExpand:
case Token::Type::ValExpand:
case Token::Type::FileExpand:
case Token::Type::UnknownExpand:
return complete_expansion(context, flags, token, start, cursor_pos, pos_in_token);
case Token::Type::Raw:

View File

@ -52,13 +52,18 @@ struct Token
ValExpand,
ArgExpand,
FileExpand,
CommandSeparator
CommandSeparator,
UnknownExpand
};
Type type;
ByteCount pos;
String content;
bool terminated = false;
struct Terminator {
Codepoint character;
bool present;
};
Optional<Terminator> terminator{};
};
struct ParseState

View File

@ -424,7 +424,7 @@ StringView Context::main_sel_register_value(StringView reg) const
return RegisterManager::instance()[reg].get_main(*this, index);
}
void Context::set_name(String name) {
void Context::set_name(String name) {
String old_name = std::exchange(m_name, std::move(name));
hooks().run_hook(Hook::ClientRenamed, format("{}:{}", old_name, m_name), *this);
}

View File

@ -239,7 +239,7 @@ struct HashMap
constexpr bool contains(const KeyType& key) const { return find_index(key) >= 0; }
template<typename KeyType> requires IsHashCompatible<Key, std::remove_cvref_t<KeyType>>
constexpr EffectiveValue& operator[](KeyType&& key)
constexpr EffectiveValue& operator[](KeyType&& key)
{
const auto hash = hash_value(key);
auto index = find_index(key, hash);

View File

@ -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;

View File

@ -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)
{

View File

@ -706,7 +706,7 @@ private:
{
auto& node = get_node(index);
const uint32_t start_pos = (uint32_t)m_program.instructions.size();
const OpIndex start_pos = op_count();
const bool ignore_case = node.ignore_case;
const bool save = (node.op == ParsedRegex::Alternation or node.op == ParsedRegex::Sequence) and
@ -746,14 +746,17 @@ private:
if (child != index+1)
push_inst(CompiledRegex::Split);
}
auto split_pos = m_program.instructions.size();
auto split_pos = op_count();
const auto end = node.children_end;
for (auto child : Children<>{m_parsed_regex, index})
{
auto node = compile_node<direction>(child);
if (child != index+1)
m_program.instructions[--split_pos].param.split = CompiledRegex::Param::Split{.target = node, .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);
@ -801,8 +804,8 @@ private:
break;
}
for (auto& offset : goto_inner_end_offsets)
m_program.instructions[offset].param.jump_target = m_program.instructions.size();
for (auto& index : goto_inner_end_offsets)
m_program.instructions[index].param.jump_offset = offset(op_count(), index);
if (save)
push_inst(CompiledRegex::Save, {.save_index=int16_t(node.value * 2 + (forward ? 1 : 0))});
@ -810,19 +813,29 @@ private:
return start_pos;
}
OpIndex op_count() const
{
return static_cast<OpIndex>(m_program.instructions.size());
}
static OpIndex offset(OpIndex to, OpIndex from)
{
return static_cast<OpIndex>(to - from);
}
template<RegexMode direction>
OpIndex compile_node(ParsedRegex::NodeIndex index)
{
auto& node = get_node(index);
const OpIndex start_pos = (OpIndex)m_program.instructions.size();
const OpIndex start_pos = op_count();
Vector<OpIndex> goto_ends;
auto& quantifier = node.quantifier;
if (quantifier.allows_none())
{
auto split_pos = push_inst(CompiledRegex::Split, {.split={.target=0, .prioritize_parent=quantifier.greedy}});
auto split_pos = push_inst(CompiledRegex::Split, {.split={.offset=0, .prioritize_parent=quantifier.greedy}});
goto_ends.push_back(split_pos);
}
@ -832,18 +845,18 @@ private:
inner_pos = compile_node_inner<direction>(index);
if (quantifier.allows_infinite_repeat())
push_inst(CompiledRegex::Split, {.split = {.target=inner_pos, .prioritize_parent=not quantifier.greedy}});
push_inst(CompiledRegex::Split, {.split = {.offset=offset(inner_pos, op_count()), .prioritize_parent=not quantifier.greedy}});
// Write the node as an optional match for the min -> max counts
else for (int i = std::max((int16_t)1, quantifier.min); // STILL UGLY !
i < quantifier.max; ++i)
{
auto split_pos = push_inst(CompiledRegex::Split, {.split={.target=0, .prioritize_parent=quantifier.greedy}});
auto split_pos = push_inst(CompiledRegex::Split, {.split={.offset=0, .prioritize_parent=quantifier.greedy}});
goto_ends.push_back(split_pos);
compile_node_inner<direction>(index);
}
for (auto offset : goto_ends)
m_program.instructions[offset].param.split.target = m_program.instructions.size();
for (auto index : goto_ends)
m_program.instructions[index].param.split.offset = offset(op_count(), index);
return start_pos;
}
@ -851,7 +864,7 @@ private:
OpIndex push_inst(CompiledRegex::Op op, CompiledRegex::Param param = {})
{
constexpr auto max_instructions = std::numeric_limits<OpIndex>::max();
const auto res = m_program.instructions.size();
const auto res = op_count();
if (res >= max_instructions)
throw regex_error(format("regex compiled to more than {} instructions", max_instructions));
m_program.instructions.push_back({ op, 0, param });
@ -1031,7 +1044,7 @@ private:
{
auto& inst = m_program.instructions[i];
if (is_jump(inst.op))
m_program.instructions[inst.param.jump_target].last_step = 0xffff; // tag as jump target
m_program.instructions[i + inst.param.jump_offset].last_step = 0xffff; // tag as jump target
}
for (auto block_begin = begin; block_begin < end; )
@ -1071,11 +1084,11 @@ private:
String dump_regex(const CompiledRegex& program)
{
String res;
int count = 0;
int index = 0;
for (auto& inst : program.instructions)
{
char buf[20];
format_to(buf, " {:03} ", count++);
format_to(buf, " {:03} ", index);
res += buf;
switch (inst.op)
{
@ -1095,13 +1108,13 @@ String dump_regex(const CompiledRegex& program)
res += format("character type {}\n", to_underlying(inst.param.character_type));
break;
case CompiledRegex::Jump:
res += format("jump {}\n", inst.param.jump_target);
res += format("jump {} ({:03})\n", inst.param.jump_offset, index + inst.param.jump_offset);
break;
case CompiledRegex::Split:
{
res += format("split (prioritize {}) {}\n",
res += format("split (prioritize {}) {} ({:03})\n",
(inst.param.split.prioritize_parent) ? "parent" : "child",
inst.param.split.target);
inst.param.split.offset, index + inst.param.split.offset);
break;
}
case CompiledRegex::Save:
@ -1135,6 +1148,7 @@ String dump_regex(const CompiledRegex& program)
case CompiledRegex::Match:
res += "match\n";
}
++index;
}
auto dump_start_desc = [&](const CompiledRegex::StartDesc& desc, StringView name) {
res += name + " start desc: [";

View File

@ -54,11 +54,11 @@ struct CharacterClass
if (ignore_case)
cp = to_lower(cp);
for (auto& range : ranges)
for (auto& [min, max] : ranges)
{
if (cp < range.min)
if (cp < min)
break;
else if (cp <= range.max)
else if (cp <= max)
return not negative;
}
@ -106,11 +106,11 @@ struct CompiledRegex : UseMemoryDomain<MemoryDomain::Regex>
} literal;
int16_t character_class_index;
CharacterType character_type;
int16_t jump_target;
int16_t jump_offset;
int16_t save_index;
struct Split
{
int16_t target;
int16_t offset;
bool prioritize_parent : 1;
} split;
bool line_start;
@ -351,10 +351,10 @@ private:
--saves.refcount;
};
struct alignas(int32_t) Thread
struct Thread
{
int16_t inst;
int16_t saves;
const CompiledRegex::Instruction* inst;
int saves;
};
using StartDesc = CompiledRegex::StartDesc;
@ -370,8 +370,7 @@ private:
// Steps a thread until it consumes the current character, matches or fail
[[gnu::always_inline]]
void step_thread(const CompiledRegex::Instruction* instructions, const Iterator& pos, Codepoint cp,
uint16_t current_step, Thread thread, const ExecConfig& config)
void step_thread(const Iterator& pos, Codepoint cp, uint16_t current_step, Thread thread, const ExecConfig& config)
{
auto failed = [this, &thread]() {
release_saves(thread.saves);
@ -382,7 +381,7 @@ private:
while (true)
{
auto& inst = instructions[thread.inst++];
auto& inst = *thread.inst++;
// if this instruction was already executed for this step in another thread,
// then this thread is redundant and can be dropped
if (inst.last_step == current_step)
@ -416,19 +415,20 @@ private:
return consumed();
return failed();
case CompiledRegex::CharClass:
if (pos == config.end)
return failed();
return m_program.character_classes[inst.param.character_class_index].matches(cp) ? consumed() : failed();
if (pos != config.end and
m_program.character_classes[inst.param.character_class_index].matches(cp))
return consumed();
return failed();
case CompiledRegex::CharType:
if (pos == config.end)
return failed();
return is_ctype(inst.param.character_type, cp) ? consumed() : failed();
if (pos != config.end and is_ctype(inst.param.character_type, cp))
return consumed();
return failed();
case CompiledRegex::Jump:
thread.inst = inst.param.jump_target;
thread.inst = &inst + inst.param.jump_offset;
break;
case CompiledRegex::Split:
if (auto target = inst.param.split.target;
instructions[target].last_step != current_step)
if (auto* target = &inst + inst.param.split.offset;
target->last_step != current_step)
{
if (thread.saves >= 0)
++m_saves[thread.saves].refcount;
@ -478,7 +478,8 @@ private:
m_captures = -1;
m_threads.ensure_initial_capacity();
const int16_t first_inst = forward ? 0 : m_program.first_backward_inst;
ConstArrayView<CompiledRegex::Instruction> insts{m_program.instructions};
const auto* first_inst = insts.begin() + (forward ? 0 : m_program.first_backward_inst);
m_threads.push_current({first_inst, -1});
const auto* start_desc = (forward ? m_program.forward_start_desc : m_program.backward_start_desc).get();
@ -486,7 +487,6 @@ private:
constexpr bool search = mode & RegexMode::Search;
constexpr bool any_match = mode & RegexMode::AnyMatch;
ConstArrayView<CompiledRegex::Instruction> insts{m_program.instructions};
uint16_t current_step = -1;
m_found_match = false;
while (true) // Iterate on all codepoints and once at the end
@ -506,7 +506,7 @@ private:
Codepoint cp = codepoint(next, config);
while (not m_threads.current_is_empty())
step_thread(insts.pointer(), pos, cp, current_step, m_threads.pop_current(), config);
step_thread(pos, cp, current_step, m_threads.pop_current(), config);
if (pos == config.end or
(m_threads.next_is_empty() and (not search or m_found_match)) or

View File

@ -40,7 +40,7 @@ void HistoryRegister::set(Context& context, ConstArrayView<String> values, bool
return;
}
for (auto&& entry : values | reverse())
for (auto&& entry : values | reverse())
{
m_content.erase(std::remove(m_content.begin(), m_content.end(), entry), m_content.end());
m_content.insert(m_content.begin(), entry);

View File

@ -6,7 +6,7 @@
namespace Kakoune
{
namespace
namespace
{
// Avoid including all of <algorithm> just for this.
constexpr auto max(auto lhs, auto rhs) { return lhs > rhs ? lhs : rhs;}
@ -69,7 +69,7 @@ void String::Data::reserve(size_t new_capacity)
if (current_capacity != 0 and new_capacity <= current_capacity)
return;
if (!is_long() and new_capacity <= Short::capacity)
if (!is_long() and new_capacity <= Short::capacity)
return;
kak_assert(new_capacity <= Long::max_capacity);

View File

@ -169,9 +169,9 @@ public:
using Alloc = Allocator<char, MemoryDomain::String>;
Data() { set_empty(); }
Data(NoCopy, const char* data, size_t size) : u{Long{const_cast<char*>(data),
Data(NoCopy, const char* data, size_t size) : u{Long{const_cast<char*>(data),
size,
/*capacity=*/0,
/*capacity=*/0,
/*mode=*/Long::active_mask}} {}
Data(const char* data, size_t size, size_t capacity);

View File

@ -202,7 +202,7 @@ InplaceString<23> to_string(Grouped val)
InplaceString<23> res;
for (int pos = 0, len = ungrouped.m_length; pos != len; ++pos)
{
if (res.m_length and ((len - pos) % 3) == 0)
if (res.m_length and ((len - pos) % 3) == 0)
res.m_data[res.m_length++] = ',';
res.m_data[res.m_length++] = ungrouped.m_data[pos];
}

View File

@ -144,10 +144,10 @@ decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
namespace detail
{
template<typename T> requires std::is_convertible_v<T, StringView>
template<typename T> requires std::is_convertible_v<T, StringView>
StringView format_param(const T& val) { return val; }
template<typename T> requires (not std::is_convertible_v<T, StringView>)
template<typename T> requires (not std::is_convertible_v<T, StringView>)
decltype(auto) format_param(const T& val) { return to_string(val); }
}

View File

@ -377,7 +377,7 @@ void TerminalUI::Screen::output(bool force, bool synchronized, Writer& writer)
{
for (int line = 0; line < (int)size.line; ++line)
{
auto hash = hash_line(lines[line]);
auto hash = hash_line(lines[line]);
if (hash == hashes[line])
continue;
hashes[line] = hash;