Merge remote-tracking branch 'krobelus/fuzzy-menu'
This commit is contained in:
commit
c93c57a46f
|
@ -879,15 +879,6 @@ progressively displaying their result in Kakoune.
|
||||||
|
|
||||||
See <<doc/pages/buffers#fifo-buffers,`:doc buffers fifo-buffers`>>.
|
See <<doc/pages/buffers#fifo-buffers,`:doc buffers fifo-buffers`>>.
|
||||||
|
|
||||||
Menus
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
When a menu is displayed, you can use `j`, `<c-n>` or `<tab>` to select the next
|
|
||||||
entry, and `k`, `<c-p>` or `<shift-tab>` to select the previous one.
|
|
||||||
|
|
||||||
Using the `/` key, you can enter some regex in order to restrict available choices
|
|
||||||
to the matching ones.
|
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -342,19 +342,6 @@ but not really useful in that context.
|
||||||
so inside a draft context like `evaluate-commands -draft`, it only
|
so inside a draft context like `evaluate-commands -draft`, it only
|
||||||
responds to an `execute-keys` command in the same context.
|
responds to an `execute-keys` command in the same context.
|
||||||
|
|
||||||
*menu* [<switches>] <label1> <commands1> <label2> <commands2> ...::
|
|
||||||
display a menu using labels, the selected label’s commands are
|
|
||||||
executed. The *menu* command can take an *-auto-single* argument, to automatically
|
|
||||||
run commands when only one choice is provided, and a *-select-cmds*
|
|
||||||
argument, in which case menu takes three argument per item, the
|
|
||||||
last one being a command to execute when the item is selected (but
|
|
||||||
not validated)
|
|
||||||
|
|
||||||
NOTE: The menu is displayed in and receives input from the
|
|
||||||
current client context, so inside a draft context like
|
|
||||||
`evaluate-commands -draft`, it is invisible and only responds to
|
|
||||||
an `execute-keys` command in the same context.
|
|
||||||
|
|
||||||
*info* [<switches>] <text>::
|
*info* [<switches>] <text>::
|
||||||
display text in an information box with the following *switches*:
|
display text in an information box with the following *switches*:
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,6 @@ The *map* command makes *key* behave as if the *keys* sequence was typed.
|
||||||
*prompt*::
|
*prompt*::
|
||||||
prompts, such as when entering a command through *:*, or a regex through */*
|
prompts, such as when entering a command through *:*, or a regex through */*
|
||||||
|
|
||||||
*menu*::
|
|
||||||
mode entered when a menu is displayed with the 'menu' command
|
|
||||||
|
|
||||||
*user*::
|
*user*::
|
||||||
mode entered when the user prefix is hit (default: '<space>')
|
mode entered when the user prefix is hit (default: '<space>')
|
||||||
|
|
||||||
|
|
|
@ -67,11 +67,6 @@ as scrolling or centering the main selection cursor.
|
||||||
|
|
||||||
See view commands <<keys#view-commands,`:doc keys view-commands`>>.
|
See view commands <<keys#view-commands,`:doc keys view-commands`>>.
|
||||||
|
|
||||||
=== Menu mode
|
|
||||||
|
|
||||||
Menu mode is entered when a menu is displayed with the `menu` command.
|
|
||||||
Mappings are used to filter and select intended items.
|
|
||||||
|
|
||||||
=== Prompt mode
|
=== Prompt mode
|
||||||
|
|
||||||
Mode entered with `:`, `/` or the `prompt` command. During prompt mode a
|
Mode entered with `:`, `/` or the `prompt` command. During prompt mode a
|
||||||
|
|
|
@ -58,13 +58,13 @@ evaluate-commands %sh{
|
||||||
keywords="add-highlighter alias arrange-buffers buffer buffer-next buffer-previous catch
|
keywords="add-highlighter alias arrange-buffers buffer buffer-next buffer-previous catch
|
||||||
change-directory colorscheme debug declare-option declare-user-mode define-command complete-command
|
change-directory colorscheme debug declare-option declare-user-mode define-command complete-command
|
||||||
delete-buffer delete-buffer! echo edit edit! enter-user-mode evaluate-commands execute-keys
|
delete-buffer delete-buffer! echo edit edit! enter-user-mode evaluate-commands execute-keys
|
||||||
fail hook info kill kill! map menu nop on-key prompt provide-module quit quit!
|
fail hook info kill kill! map nop on-key prompt provide-module quit quit!
|
||||||
remove-highlighter remove-hooks rename-buffer rename-client rename-session require-module
|
remove-highlighter remove-hooks rename-buffer rename-client rename-session require-module
|
||||||
select set-face set-option set-register source trigger-user-hook try
|
select set-face set-option set-register source trigger-user-hook try
|
||||||
unalias unmap unset-face unset-option update-option
|
unalias unmap unset-face unset-option update-option
|
||||||
write write! write-all write-all-quit write-quit write-quit!"
|
write write! write-all write-all-quit write-quit write-quit!"
|
||||||
attributes="global buffer window current
|
attributes="global buffer window current
|
||||||
normal insert menu prompt goto view user object
|
normal insert prompt goto view user object
|
||||||
number-lines show-matching show-whitespaces fill regex dynregex group flag-lines
|
number-lines show-matching show-whitespaces fill regex dynregex group flag-lines
|
||||||
ranges line column wrap ref regions region default-region replace-ranges"
|
ranges line column wrap ref regions region default-region replace-ranges"
|
||||||
types="int bool str regex int-list str-list completions line-specs range-specs str-to-str-map"
|
types="int bool str regex int-list str-list completions line-specs range-specs str-to-str-map"
|
||||||
|
|
|
@ -30,7 +30,7 @@ define-command -params ..1 \
|
||||||
ctags-search [<symbol>]: jump to a symbol's definition
|
ctags-search [<symbol>]: jump to a symbol's definition
|
||||||
If no symbol is passed then the current selection is used as symbol name
|
If no symbol is passed then the current selection is used as symbol name
|
||||||
} \
|
} \
|
||||||
ctags-search %[ evaluate-commands %sh[
|
ctags-search %[ require-module menu; evaluate-commands %sh[
|
||||||
realpath() { ( cd "$(dirname "$1")"; printf "%s/%s\n" "$(pwd -P)" "$(basename "$1")" ) }
|
realpath() { ( cd "$(dirname "$1")"; printf "%s/%s\n" "$(pwd -P)" "$(basename "$1")" ) }
|
||||||
export tagname="${1:-${kak_selection}}"
|
export tagname="${1:-${kak_selection}}"
|
||||||
eval "set -- $kak_quoted_opt_ctagsfiles"
|
eval "set -- $kak_quoted_opt_ctagsfiles"
|
||||||
|
@ -49,7 +49,7 @@ define-command -params ..1 \
|
||||||
menu_item = $2; gsub("!", "!!", menu_item);
|
menu_item = $2; gsub("!", "!!", menu_item);
|
||||||
edit_path = path($2); gsub("&", "&&", edit_path); gsub("#", "##", edit_path); gsub("\\|", "||", edit_path);
|
edit_path = path($2); gsub("&", "&&", edit_path); gsub("#", "##", edit_path); gsub("\\|", "||", edit_path);
|
||||||
select = $1; gsub(/</, "<lt>", select); gsub(/\t/, "<c-v><c-i>", select); gsub("!", "!!", select); gsub("&", "&&", select); gsub("#", "##", select); gsub("\\|", "||", select);
|
select = $1; gsub(/</, "<lt>", select); gsub(/\t/, "<c-v><c-i>", select); gsub("!", "!!", select); gsub("&", "&&", select); gsub("#", "##", select); gsub("\\|", "||", select);
|
||||||
out = out "%!" menu_item ": {MenuInfo}{\\}" menu_info "! %!evaluate-commands %# try %& edit -existing %|" edit_path "|; execute-keys %|/\\Q" keys "<ret>vc| & catch %& fail unable to find tag &; try %& execute-keys %|s\\Q" select "<ret>| & # !"
|
out = out "%!" menu_item ": " menu_info "! %!evaluate-commands %# try %& edit -existing %|" edit_path "|; execute-keys %|/\\Q" keys "<ret>vc| & catch %& fail unable to find tag &; try %& execute-keys %|s\\Q" select "<ret>| & # !"
|
||||||
}
|
}
|
||||||
/[^\t]+\t[^\t]+\t[0-9]+/ {
|
/[^\t]+\t[^\t]+\t[0-9]+/ {
|
||||||
menu_item = $2; gsub("!", "!!", menu_item);
|
menu_item = $2; gsub("!", "!!", menu_item);
|
||||||
|
@ -57,7 +57,7 @@ define-command -params ..1 \
|
||||||
menu_info = $3; gsub("!", "!!", menu_info);
|
menu_info = $3; gsub("!", "!!", menu_info);
|
||||||
edit_path = path($2); gsub("!", "!!", edit_path); gsub("#", "##", edit_path); gsub("&", "&&", edit_path); gsub("\\|", "||", edit_path);
|
edit_path = path($2); gsub("!", "!!", edit_path); gsub("#", "##", edit_path); gsub("&", "&&", edit_path); gsub("\\|", "||", edit_path);
|
||||||
line_number = $3;
|
line_number = $3;
|
||||||
out = out "%!" menu_item ": {MenuInfo}{\\}" menu_info "! %!evaluate-commands %# try %& edit -existing %|" edit_path "|; execute-keys %|" line_number "gx| & catch %& fail unable to find tag &; try %& execute-keys %|s\\Q" select "<ret>| & # !"
|
out = out "%!" menu_item ": " menu_info "! %!evaluate-commands %# try %& edit -existing %|" edit_path "|; execute-keys %|" line_number "gx| & catch %& fail unable to find tag &; try %& execute-keys %|s\\Q" select "<ret>| & # !"
|
||||||
}
|
}
|
||||||
END { print ( length(out) == 0 ? "fail no such tag " ENVIRON["tagname"] : "menu -markup -auto-single " out ) }
|
END { print ( length(out) == 0 ? "fail no such tag " ENVIRON["tagname"] : "menu -markup -auto-single " out ) }
|
||||||
# Ensure x is an absolute file path, by prepending with tagroot
|
# Ensure x is an absolute file path, by prepending with tagroot
|
||||||
|
|
85
rc/tools/menu.kak
Normal file
85
rc/tools/menu.kak
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
provide-module menu %§§
|
||||||
|
|
||||||
|
define-command menu -params 1.. -docstring %{
|
||||||
|
menu [<switches>] <name1> <commands1> <name2> <commands2>...: display a
|
||||||
|
menu and execute commands for the selected item
|
||||||
|
|
||||||
|
-auto-single instantly validate if only one item is available
|
||||||
|
-select-cmds each item specify an additional command to run when selected
|
||||||
|
} %{
|
||||||
|
evaluate-commands %sh{
|
||||||
|
auto_single=false
|
||||||
|
select_cmds=false
|
||||||
|
stride=2
|
||||||
|
on_abort=
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
(-auto-single) auto_single=true ;;
|
||||||
|
(-select-cmds) select_cmds=true; stride=3 ;;
|
||||||
|
(-on-abort) on_abort="$2"; shift ;;
|
||||||
|
(-markup) ;; # no longer supported
|
||||||
|
(*) break ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if [ $(( $# % $stride )) -ne 0 ]; then
|
||||||
|
echo fail "wrong argument count"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if $auto_single && [ $# -eq $stride ]; then
|
||||||
|
printf %s "$2"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
shellquote() {
|
||||||
|
printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g; s/§/§§/g; $2")"
|
||||||
|
}
|
||||||
|
cases=
|
||||||
|
select_cases=
|
||||||
|
completion=
|
||||||
|
nl=$(printf '\n.'); nl=${nl%.}
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
title=$1
|
||||||
|
command=$2
|
||||||
|
completion="${completion}${title}${nl}"
|
||||||
|
cases="${cases}
|
||||||
|
($(shellquote "$title" s/¶/¶¶/g))
|
||||||
|
printf '%s\\n' $(shellquote "$command" s/¶/¶¶/g)
|
||||||
|
;;"
|
||||||
|
if $select_cmds; then
|
||||||
|
select_command=$3
|
||||||
|
select_cases="${select_cases}
|
||||||
|
($(shellquote "$title" s/¶/¶¶/g))
|
||||||
|
printf '%s\\n' $(shellquote "$select_command" s/¶/¶¶/g)
|
||||||
|
;;"
|
||||||
|
fi
|
||||||
|
shift $stride
|
||||||
|
done
|
||||||
|
printf "\
|
||||||
|
prompt '' %%§
|
||||||
|
evaluate-commands %%sh¶
|
||||||
|
case \"\$kak_text\" in \
|
||||||
|
%s
|
||||||
|
(*) echo fail -- no such item: \"'\$(printf %%s \"\$kak_text\" | sed \"s/'/''/g\")'\" ;;
|
||||||
|
esac
|
||||||
|
¶
|
||||||
|
§" "$cases"
|
||||||
|
if $select_cmds; then
|
||||||
|
printf " \
|
||||||
|
-on-change %%§
|
||||||
|
evaluate-commands %%sh¶
|
||||||
|
case \"\$kak_text\" in \
|
||||||
|
%s
|
||||||
|
(*) : ;;
|
||||||
|
esac
|
||||||
|
¶
|
||||||
|
§" "$select_cases"
|
||||||
|
fi
|
||||||
|
if [ -n "$on_abort" ]; then
|
||||||
|
printf " -on-abort '%s'" "$(printf %s "$on_abort" | sed "s/'/''/g")"
|
||||||
|
fi
|
||||||
|
printf ' -menu -shell-script-candidates %%§
|
||||||
|
printf %%s %s
|
||||||
|
§\n' "$(shellquote "$completion")"
|
||||||
|
}
|
||||||
|
}
|
|
@ -2274,65 +2274,6 @@ const CommandDesc prompt_cmd = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const CommandDesc menu_cmd = {
|
|
||||||
"menu",
|
|
||||||
nullptr,
|
|
||||||
"menu [<switches>] <name1> <commands1> <name2> <commands2>...: display a "
|
|
||||||
"menu and execute commands for the selected item",
|
|
||||||
ParameterDesc{
|
|
||||||
{ { "auto-single", { {}, "instantly validate if only one item is available" } },
|
|
||||||
{ "select-cmds", { {}, "each item specify an additional command to run when selected" } },
|
|
||||||
{ "markup", { {}, "parse menu entries as markup text" } } }
|
|
||||||
},
|
|
||||||
CommandFlags::None,
|
|
||||||
CommandHelper{},
|
|
||||||
CommandCompleter{},
|
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext& shell_context)
|
|
||||||
{
|
|
||||||
const bool with_select_cmds = (bool)parser.get_switch("select-cmds");
|
|
||||||
const bool markup = (bool)parser.get_switch("markup");
|
|
||||||
const size_t modulo = with_select_cmds ? 3 : 2;
|
|
||||||
|
|
||||||
const size_t count = parser.positional_count();
|
|
||||||
if (count == 0 or (count % modulo) != 0)
|
|
||||||
throw wrong_argument_count();
|
|
||||||
|
|
||||||
if (count == modulo and parser.get_switch("auto-single"))
|
|
||||||
{
|
|
||||||
ScopedSetBool noninteractive{context.noninteractive()};
|
|
||||||
|
|
||||||
CommandManager::instance().execute(parser[1], context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<DisplayLine> choices;
|
|
||||||
Vector<String> commands;
|
|
||||||
Vector<String> select_cmds;
|
|
||||||
for (int i = 0; i < count; i += modulo)
|
|
||||||
{
|
|
||||||
if (parser[i].empty())
|
|
||||||
throw runtime_error(format("entry #{} is empty", i+1));
|
|
||||||
|
|
||||||
choices.push_back(markup ? parse_display_line(parser[i], context.faces())
|
|
||||||
: DisplayLine{ parser[i], {} });
|
|
||||||
commands.push_back(parser[i+1]);
|
|
||||||
if (with_select_cmds)
|
|
||||||
select_cmds.push_back(parser[i+2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
CapturedShellContext sc{shell_context};
|
|
||||||
context.input_handler().menu(std::move(choices),
|
|
||||||
[=](int choice, MenuEvent event, Context& context) {
|
|
||||||
ScopedSetBool noninteractive{context.noninteractive()};
|
|
||||||
|
|
||||||
if (event == MenuEvent::Validate and choice >= 0 and choice < commands.size())
|
|
||||||
CommandManager::instance().execute(commands[choice], context, sc);
|
|
||||||
if (event == MenuEvent::Select and choice >= 0 and choice < select_cmds.size())
|
|
||||||
CommandManager::instance().execute(select_cmds[choice], context, sc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const CommandDesc on_key_cmd = {
|
const CommandDesc on_key_cmd = {
|
||||||
"on-key",
|
"on-key",
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -2820,7 +2761,6 @@ void register_commands()
|
||||||
register_command(execute_keys_cmd);
|
register_command(execute_keys_cmd);
|
||||||
register_command(evaluate_commands_cmd);
|
register_command(evaluate_commands_cmd);
|
||||||
register_command(prompt_cmd);
|
register_command(prompt_cmd);
|
||||||
register_command(menu_cmd);
|
|
||||||
register_command(on_key_cmd);
|
register_command(on_key_cmd);
|
||||||
register_command(info_cmd);
|
register_command(info_cmd);
|
||||||
register_command(try_catch_cmd);
|
register_command(try_catch_cmd);
|
||||||
|
|
|
@ -632,143 +632,6 @@ private:
|
||||||
const FaceRegistry& m_faces;
|
const FaceRegistry& m_faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Menu : public InputMode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Menu(InputHandler& input_handler, Vector<DisplayLine> choices,
|
|
||||||
MenuCallback callback)
|
|
||||||
: InputMode(input_handler),
|
|
||||||
m_callback(std::move(callback)), m_choices(choices.begin(), choices.end()),
|
|
||||||
m_selected(m_choices.begin()),
|
|
||||||
m_filter_editor{context().faces()}
|
|
||||||
{
|
|
||||||
if (not context().has_client())
|
|
||||||
return;
|
|
||||||
context().client().menu_show(std::move(choices), {}, MenuStyle::Prompt);
|
|
||||||
context().client().menu_select(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_key(Key key, bool) override
|
|
||||||
{
|
|
||||||
auto match_filter = [this](const DisplayLine& choice) {
|
|
||||||
for (auto& atom : choice)
|
|
||||||
{
|
|
||||||
const auto& contents = atom.content();
|
|
||||||
if (regex_match(contents.begin(), contents.end(), m_filter))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (key == Key::Return)
|
|
||||||
{
|
|
||||||
if (context().has_client())
|
|
||||||
context().client().menu_hide();
|
|
||||||
context().print_status(DisplayLine{});
|
|
||||||
|
|
||||||
// Maintain hooks disabled in callback if they were before pop_mode
|
|
||||||
ScopedSetBool disable_hooks(context().hooks_disabled(),
|
|
||||||
context().hooks_disabled());
|
|
||||||
pop_mode();
|
|
||||||
int selected = m_selected - m_choices.begin();
|
|
||||||
m_callback(selected, MenuEvent::Validate, context());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (key == Key::Escape or key == ctrl('c'))
|
|
||||||
{
|
|
||||||
if (m_edit_filter)
|
|
||||||
{
|
|
||||||
m_edit_filter = false;
|
|
||||||
m_filter = Regex{".*"};
|
|
||||||
m_filter_editor.reset("", "");
|
|
||||||
context().print_status(DisplayLine{});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (context().has_client())
|
|
||||||
context().client().menu_hide();
|
|
||||||
|
|
||||||
// Maintain hooks disabled in callback if they were before pop_mode
|
|
||||||
ScopedSetBool disable_hooks(context().hooks_disabled(),
|
|
||||||
context().hooks_disabled());
|
|
||||||
pop_mode();
|
|
||||||
int selected = m_selected - m_choices.begin();
|
|
||||||
m_callback(selected, MenuEvent::Abort, context());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (key == Key::Down or key == Key::Tab or
|
|
||||||
key == ctrl('n') or (not m_edit_filter and key == 'j'))
|
|
||||||
{
|
|
||||||
auto it = std::find_if(m_selected+1, m_choices.end(), match_filter);
|
|
||||||
if (it == m_choices.end())
|
|
||||||
it = std::find_if(m_choices.begin(), m_selected, match_filter);
|
|
||||||
select(it);
|
|
||||||
}
|
|
||||||
else if (key == Key::Up or key == shift(Key::Tab) or
|
|
||||||
key == ctrl('p') or (not m_edit_filter and key == 'k'))
|
|
||||||
{
|
|
||||||
ChoiceList::const_reverse_iterator selected(m_selected+1);
|
|
||||||
auto it = std::find_if(selected+1, m_choices.rend(), match_filter);
|
|
||||||
if (it == m_choices.rend())
|
|
||||||
it = std::find_if(m_choices.rbegin(), selected, match_filter);
|
|
||||||
select(it.base()-1);
|
|
||||||
}
|
|
||||||
else if (key == '/' and not m_edit_filter)
|
|
||||||
{
|
|
||||||
m_edit_filter = true;
|
|
||||||
}
|
|
||||||
else if (m_edit_filter)
|
|
||||||
{
|
|
||||||
m_filter_editor.handle_key(key);
|
|
||||||
|
|
||||||
auto search = ".*" + m_filter_editor.line() + ".*";
|
|
||||||
m_filter = Regex{search};
|
|
||||||
auto it = std::find_if(m_selected, m_choices.end(), match_filter);
|
|
||||||
if (it == m_choices.end())
|
|
||||||
it = std::find_if(m_choices.begin(), m_selected, match_filter);
|
|
||||||
select(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_edit_filter and context().has_client())
|
|
||||||
{
|
|
||||||
auto prompt = "filter:"_str;
|
|
||||||
auto width = context().client().dimensions().column - prompt.column_length();
|
|
||||||
auto display_line = m_filter_editor.build_display_line(width);
|
|
||||||
display_line.insert(display_line.begin(), { prompt, context().faces()["Prompt"] });
|
|
||||||
context().print_status(display_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayLine mode_line() const override
|
|
||||||
{
|
|
||||||
return { "menu", context().faces()["StatusLineMode"] };
|
|
||||||
}
|
|
||||||
|
|
||||||
KeymapMode keymap_mode() const override { return KeymapMode::Menu; }
|
|
||||||
|
|
||||||
StringView name() const override { return "menu"; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
MenuCallback m_callback;
|
|
||||||
|
|
||||||
using ChoiceList = Vector<DisplayLine>;
|
|
||||||
const ChoiceList m_choices;
|
|
||||||
ChoiceList::const_iterator m_selected;
|
|
||||||
|
|
||||||
void select(ChoiceList::const_iterator it)
|
|
||||||
{
|
|
||||||
m_selected = it;
|
|
||||||
int selected = m_selected - m_choices.begin();
|
|
||||||
if (context().has_client())
|
|
||||||
context().client().menu_select(selected);
|
|
||||||
m_callback(selected, MenuEvent::Select, context());
|
|
||||||
}
|
|
||||||
|
|
||||||
Regex m_filter = Regex{".*"};
|
|
||||||
bool m_edit_filter = false;
|
|
||||||
LineEditor m_filter_editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Optional<Codepoint> get_raw_codepoint(Key key)
|
static Optional<Codepoint> get_raw_codepoint(Key key)
|
||||||
{
|
{
|
||||||
if (auto cp = key.codepoint())
|
if (auto cp = key.codepoint())
|
||||||
|
@ -1744,11 +1607,6 @@ void InputHandler::set_prompt_face(Face prompt_face)
|
||||||
prompt->set_prompt_face(prompt_face);
|
prompt->set_prompt_face(prompt_face);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHandler::menu(Vector<DisplayLine> choices, MenuCallback callback)
|
|
||||||
{
|
|
||||||
push_mode(new InputModes::Menu(*this, std::move(choices), std::move(callback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputHandler::on_next_key(StringView mode_name, KeymapMode keymap_mode, KeyCallback callback,
|
void InputHandler::on_next_key(StringView mode_name, KeymapMode keymap_mode, KeyCallback callback,
|
||||||
Timer::Callback idle_callback)
|
Timer::Callback idle_callback)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,14 +16,6 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
enum class MenuEvent
|
|
||||||
{
|
|
||||||
Select,
|
|
||||||
Abort,
|
|
||||||
Validate
|
|
||||||
};
|
|
||||||
using MenuCallback = std::function<void (int, MenuEvent, Context&)>;
|
|
||||||
|
|
||||||
enum class PromptEvent
|
enum class PromptEvent
|
||||||
{
|
{
|
||||||
Change,
|
Change,
|
||||||
|
@ -85,12 +77,6 @@ public:
|
||||||
void set_prompt_face(Face prompt_face);
|
void set_prompt_face(Face prompt_face);
|
||||||
bool history_enabled() const;
|
bool history_enabled() const;
|
||||||
|
|
||||||
// enter menu mode, callback is called on each selection change,
|
|
||||||
// abort or validation with corresponding MenuEvent value
|
|
||||||
// returns to normal mode after validation if callback does
|
|
||||||
// not change the mode itself
|
|
||||||
void menu(Vector<DisplayLine> choices, MenuCallback callback);
|
|
||||||
|
|
||||||
// execute callback on next keypress and returns to normal mode
|
// execute callback on next keypress and returns to normal mode
|
||||||
// if callback does not change the mode itself
|
// if callback does not change the mode itself
|
||||||
void on_next_key(StringView mode_name, KeymapMode mode, KeyCallback callback,
|
void on_next_key(StringView mode_name, KeymapMode mode, KeyCallback callback,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user