summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2018-02-18 20:20:35 +1100
committerMaxime Coste <mawww@kakoune.org>2018-02-18 20:20:35 +1100
commitf88195d2d91c19a32d54588476950c263ab415dc (patch)
treef28c87fc4c674608cc316ce1219c07470df2d1f8 /src
parent4f75358ce315ba9658f29bce581b8dc7dbdc4a06 (diff)
parent6b447a0ecb018256c574fc2a36be99698f603cc3 (diff)
Merge remote-tracking branch 'Delapouite/user-mode'
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc82
-rw-r--r--src/keymap_manager.cc17
-rw-r--r--src/keymap_manager.hh7
-rw-r--r--src/normal.cc6
-rw-r--r--src/normal.hh11
5 files changed, 110 insertions, 13 deletions
diff --git a/src/commands.cc b/src/commands.cc
index 8e58a7e6..974f1eed 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"
@@ -1099,7 +1100,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;
@@ -1110,7 +1111,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 = {
@@ -1189,7 +1195,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),
@@ -1427,11 +1433,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 {};
};
@@ -1459,7 +1467,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)
@@ -1492,7 +1500,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)
@@ -2113,6 +2121,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()
@@ -2175,6 +2241,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 1b83ec8b..16270c18 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