summaryrefslogtreecommitdiff
path: root/src/commands.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands.cc')
-rw-r--r--src/commands.cc82
1 files changed, 75 insertions, 7 deletions
diff --git a/src/commands.cc b/src/commands.cc
index 8101a6f1..7267a6dd 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -15,6 +15,7 @@
#include "highlighter.hh"
#include "highlighters.hh"
#include "insert_completer.hh"
+#include "normal.hh"
#include "option_manager.hh"
#include "option_types.hh"
#include "parameters_parser.hh"
@@ -1096,7 +1097,7 @@ const CommandDesc echo_cmd = {
}
};
-KeymapMode parse_keymap_mode(const String& str)
+KeymapMode parse_keymap_mode(const String& str, const KeymapManager::UserModeList& user_modes)
{
if (prefix_match("normal", str)) return KeymapMode::Normal;
if (prefix_match("insert", str)) return KeymapMode::Insert;
@@ -1107,7 +1108,12 @@ KeymapMode parse_keymap_mode(const String& str)
if (prefix_match("user", str)) return KeymapMode::User;
if (prefix_match("object", str)) return KeymapMode::Object;
- throw runtime_error(format("unknown keymap mode '{}'", str));
+ auto it = find(user_modes, str);
+ if (it == user_modes.end())
+ throw runtime_error(format("unknown keymap mode '{}'", str));
+
+ char offset = static_cast<char>(KeymapMode::FirstUserMode);
+ return (KeymapMode)(std::distance(user_modes.begin(), it) + offset);
}
const CommandDesc debug_cmd = {
@@ -1186,7 +1192,7 @@ const CommandDesc debug_cmd = {
write_to_debug_buffer("Mappings:");
for (auto& mode : modes)
{
- KeymapMode m = parse_keymap_mode(mode);
+ KeymapMode m = parse_keymap_mode(mode, keymaps.user_modes());
for (auto& key : keymaps.get_mapped_keys(m))
write_to_debug_buffer(format(" * {} {}: {}",
mode, key_to_str(key),
@@ -1415,11 +1421,13 @@ auto map_key_completer =
if (token_to_complete == 0)
return { 0_byte, params[0].length(),
complete(params[0], pos_in_token, scopes) };
+
if (token_to_complete == 1)
{
- constexpr const char* modes[] = { "normal", "insert", "menu", "prompt", "goto", "view", "user", "object" };
+ static constexpr auto modes = { "normal", "insert", "menu", "prompt", "goto", "view", "user", "object" };
+ auto& user_modes = get_scope(params[0], context).keymaps().user_modes();
return { 0_byte, params[1].length(),
- complete(params[1], pos_in_token, modes) };
+ complete(params[1], pos_in_token, concatenated(modes, user_modes) | gather<Vector<String>>()) };
}
return {};
};
@@ -1447,7 +1455,7 @@ const CommandDesc map_key_cmd = {
[](const ParametersParser& parser, Context& context, const ShellContext&)
{
KeymapManager& keymaps = get_scope(parser[0], context).keymaps();
- KeymapMode keymap_mode = parse_keymap_mode(parser[1]);
+ KeymapMode keymap_mode = parse_keymap_mode(parser[1], keymaps.user_modes());
KeyList key = parse_keys(parser[2]);
if (key.size() != 1)
@@ -1480,7 +1488,7 @@ const CommandDesc unmap_key_cmd = {
[](const ParametersParser& parser, Context& context, const ShellContext&)
{
KeymapManager& keymaps = get_scope(parser[0], context).keymaps();
- KeymapMode keymap_mode = parse_keymap_mode(parser[1]);
+ KeymapMode keymap_mode = parse_keymap_mode(parser[1], keymaps.user_modes());
KeyList key = parse_keys(parser[2]);
if (key.size() != 1)
@@ -2101,6 +2109,64 @@ const CommandDesc fail_cmd = {
}
};
+const CommandDesc declare_user_mode_cmd = {
+ "declare-user-mode",
+ nullptr,
+ "declare-user-mode <scope> <name>: add a new user keymap mode in given <scope>",
+ ParameterDesc{ {}, ParameterDesc::Flags::None, 2, 2 },
+ CommandFlags::None,
+ CommandHelper{},
+ make_completer(complete_scope),
+ [](const ParametersParser& parser, Context& context, const ShellContext&)
+ {
+ KeymapManager& keymaps = get_scope(parser[0], context).keymaps();
+ keymaps.add_user_mode(std::move(parser[1]));
+ }
+};
+
+const CommandDesc enter_user_mode_cmd = {
+ "enter-user-mode",
+ nullptr,
+ "enter-user-mode <scope> <name>: enable <name> keymap mode for next key",
+ ParameterDesc{ {}, ParameterDesc::Flags::None, 2, 2 },
+ CommandFlags::None,
+ CommandHelper{},
+ [](const Context& context, CompletionFlags flags,
+ CommandParameters params, size_t token_to_complete,
+ ByteCount pos_in_token) -> Completions
+ {
+ if (token_to_complete == 0)
+ return { 0_byte, params[0].length(),
+ complete(params[0], pos_in_token, scopes) };
+ if (token_to_complete == 1)
+ {
+ KeymapManager& keymaps = get_scope(params[0], context).keymaps();
+ return { 0_byte, params[1].length(),
+ complete(params[1], pos_in_token, keymaps.user_modes()) };
+ }
+ return {};
+ },
+ [](const ParametersParser& parser, Context& context, const ShellContext&)
+ {
+ KeymapManager& keymaps = get_scope(parser[0], context).keymaps();
+ KeymapMode mode = parse_keymap_mode(parser[1], keymaps.user_modes());
+ on_next_key_with_autoinfo(context, mode,
+ [mode](Key key, Context& context) mutable {
+ if (not context.keymaps().is_mapped(key, mode))
+ return;
+
+ auto& mapping = context.keymaps().get_mapping(key, mode);
+ ScopedSetBool disable_keymaps(context.keymaps_disabled());
+
+ InputHandler::ScopedForceNormal force_normal{context.input_handler(), {}};
+
+ ScopedEdition edition(context);
+ for (auto& key : mapping.keys)
+ context.input_handler().handle_key(key);
+ }, parser[1], build_autoinfo_for_mapping(context, mode, {}));
+ }
+};
+
}
void register_commands()
@@ -2163,6 +2229,8 @@ void register_commands()
register_command(change_directory_cmd);
register_command(rename_session_cmd);
register_command(fail_cmd);
+ register_command(declare_user_mode_cmd);
+ register_command(enter_user_mode_cmd);
}
}