diff options
| author | Delapouite <delapouite@gmail.com> | 2018-01-18 09:57:14 +0100 |
|---|---|---|
| committer | Delapouite <delapouite@gmail.com> | 2018-02-12 14:19:58 +0100 |
| commit | 6b447a0ecb018256c574fc2a36be99698f603cc3 (patch) | |
| tree | 6561f4c13cc5f27ad31be9ab4353f44c0d70f018 /src | |
| parent | 9c25e955dfdddd0ee63c2edb56cde79b18452da8 (diff) | |
Add declare-user-mode / enter-user-mode commands
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands.cc | 82 | ||||
| -rw-r--r-- | src/keymap_manager.cc | 17 | ||||
| -rw-r--r-- | src/keymap_manager.hh | 7 | ||||
| -rw-r--r-- | src/normal.cc | 6 | ||||
| -rw-r--r-- | src/normal.hh | 11 |
5 files changed, 110 insertions, 13 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); } } diff --git a/src/keymap_manager.cc b/src/keymap_manager.cc index 859f420b..8c359082 100644 --- a/src/keymap_manager.cc +++ b/src/keymap_manager.cc @@ -2,6 +2,8 @@ #include "array_view.hh" #include "assert.hh" +#include "exception.hh" +#include "string_utils.hh" #include <algorithm> @@ -49,4 +51,19 @@ KeymapManager::KeyList KeymapManager::get_mapped_keys(KeymapMode mode) const return res; } +void KeymapManager::add_user_mode(const String user_mode_name) +{ + auto modes = {"normal", "insert", "prompt", "menu", "goto", "view", "user", "object"}; + if (contains(modes, user_mode_name)) + throw runtime_error(format("'{}' is already a regular mode", user_mode_name)); + + if (contains(m_user_modes, user_mode_name)) + throw runtime_error(format("user mode '{}' already defined", user_mode_name)); + + if (contains_that(user_mode_name, [](char c){ return not isalnum(c); })) + throw runtime_error(format("invalid mode name: '{}'", user_mode_name)); + + m_user_modes.push_back(user_mode_name); +} + } diff --git a/src/keymap_manager.hh b/src/keymap_manager.hh index 746c02c5..3c8d52ee 100644 --- a/src/keymap_manager.hh +++ b/src/keymap_manager.hh @@ -22,6 +22,7 @@ enum class KeymapMode : char View, User, Object, + FirstUserMode, }; class KeymapManager @@ -43,6 +44,10 @@ public: }; const KeymapInfo& get_mapping(Key key, KeymapMode mode) const; + using UserModeList = Vector<String>; + const UserModeList& user_modes() const { return m_user_modes; } + void add_user_mode(const String user_mode_name); + private: KeymapManager() : m_parent(nullptr) {} @@ -52,6 +57,8 @@ private: KeymapManager* m_parent; using KeyAndMode = std::pair<Key, KeymapMode>; HashMap<KeyAndMode, KeymapInfo, MemoryDomain::Mapping> m_mapping; + + UserModeList m_user_modes; }; } diff --git a/src/normal.cc b/src/normal.cc index d890ab7d..f46f529f 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -127,12 +127,6 @@ void repeat_last_select(Context& context, NormalParams) context.repeat_last_select(); } -struct KeyInfo -{ - ConstArrayView<Key> keys; - StringView docstring; -}; - String build_autoinfo_for_mapping(Context& context, KeymapMode mode, ConstArrayView<KeyInfo> built_ins) { diff --git a/src/normal.hh b/src/normal.hh index 9802f642..9b6693cc 100644 --- a/src/normal.hh +++ b/src/normal.hh @@ -1,8 +1,10 @@ #ifndef normal_hh_INCLUDED #define normal_hh_INCLUDED +#include "context.hh" #include "optional.hh" #include "keys.hh" +#include "keymap_manager.hh" #include "string.hh" namespace Kakoune @@ -24,6 +26,15 @@ struct NormalCmd Optional<NormalCmd> get_normal_command(Key key); +struct KeyInfo +{ + ConstArrayView<Key> keys; + StringView docstring; +}; + +String build_autoinfo_for_mapping(Context& context, KeymapMode mode, + ConstArrayView<KeyInfo> built_ins); + } #endif // normal_hh_INCLUDED |
