Add docstring support for mappings, and use them in autoinfo
Fixes #105 Fixes #1100 Closes #1165
This commit is contained in:
parent
7d487e3b4c
commit
e3cfde6d07
|
@ -1404,7 +1404,10 @@ const CommandDesc map_key_cmd = {
|
|||
" view\n"
|
||||
" user\n"
|
||||
" object\n",
|
||||
ParameterDesc{{}, ParameterDesc::Flags::None, 4, 4},
|
||||
ParameterDesc{
|
||||
{ { "docstring", { true, "specify mapping description" } } },
|
||||
ParameterDesc::Flags::None, 4, 4
|
||||
},
|
||||
CommandFlags::None,
|
||||
CommandHelper{},
|
||||
map_key_completer,
|
||||
|
@ -1418,7 +1421,8 @@ const CommandDesc map_key_cmd = {
|
|||
throw runtime_error("only a single key can be mapped");
|
||||
|
||||
KeyList mapping = parse_keys(parser[3]);
|
||||
keymaps.map_key(key[0], keymap_mode, std::move(mapping));
|
||||
keymaps.map_key(key[0], keymap_mode, std::move(mapping),
|
||||
parser.get_switch("docstring").value_or("").str());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1451,8 +1455,8 @@ const CommandDesc unmap_key_cmd = {
|
|||
|
||||
if (keymaps.is_mapped(key[0], keymap_mode) and
|
||||
(parser.positional_count() < 4 or
|
||||
(keymaps.get_mapping(key[0], keymap_mode) ==
|
||||
ConstArrayView<Key>{parse_keys(parser[3])})))
|
||||
(keymaps.get_mapping(key[0], keymap_mode).keys ==
|
||||
parse_keys(parser[3]))))
|
||||
keymaps.unmap_key(key[0], keymap_mode);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1453,7 +1453,7 @@ void InputHandler::handle_key(Key key)
|
|||
not m_context.keymaps_disabled())
|
||||
{
|
||||
ScopedSetBool disable_history{context().history_disabled()};
|
||||
for (auto& k : keymaps.get_mapping(key, keymap_mode))
|
||||
for (auto& k : keymaps.get_mapping(key, keymap_mode).keys)
|
||||
current_mode().handle_key(k);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
#include "array_view.hh"
|
||||
#include "assert.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
void KeymapManager::map_key(Key key, KeymapMode mode, KeyList mapping)
|
||||
void KeymapManager::map_key(Key key, KeymapMode mode,
|
||||
KeyList mapping, String docstring)
|
||||
{
|
||||
m_mapping[{key, mode}] = std::move(mapping);
|
||||
m_mapping[{key, mode}] = {std::move(mapping), std::move(docstring)};
|
||||
}
|
||||
|
||||
void KeymapManager::unmap_key(Key key, KeymapMode mode)
|
||||
|
@ -23,13 +26,29 @@ bool KeymapManager::is_mapped(Key key, KeymapMode mode) const
|
|||
(m_parent and m_parent->is_mapped(key, mode));
|
||||
}
|
||||
|
||||
ConstArrayView<Key> KeymapManager::get_mapping(Key key, KeymapMode mode) const
|
||||
const KeymapManager::KeyMapInfo&
|
||||
KeymapManager::get_mapping(Key key, KeymapMode mode) const
|
||||
{
|
||||
auto it = m_mapping.find({key, mode});
|
||||
if (it != m_mapping.end())
|
||||
return { it->second };
|
||||
return it->second;
|
||||
kak_assert(m_parent);
|
||||
return m_parent->get_mapping(key, mode);
|
||||
}
|
||||
|
||||
KeymapManager::KeyList KeymapManager::get_mapped_keys(KeymapMode mode) const
|
||||
{
|
||||
KeyList res;
|
||||
if (m_parent)
|
||||
res = m_parent->get_mapped_keys(mode);
|
||||
for (auto& map : m_mapping)
|
||||
{
|
||||
if (map.first.second == mode)
|
||||
res.emplace_back(map.first.first);
|
||||
}
|
||||
std::sort(res.begin(), res.end());
|
||||
res.erase(std::unique(res.begin(), res.end()), res.end());
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "array_view.hh"
|
||||
#include "keys.hh"
|
||||
#include "hash.hh"
|
||||
#include "string.hh"
|
||||
#include "unordered_map.hh"
|
||||
#include "vector.hh"
|
||||
|
||||
|
@ -29,11 +30,19 @@ public:
|
|||
KeymapManager(KeymapManager& parent) : m_parent(&parent) {}
|
||||
|
||||
using KeyList = Vector<Key, MemoryDomain::Mapping>;
|
||||
void map_key(Key key, KeymapMode mode, KeyList mapping);
|
||||
void map_key(Key key, KeymapMode mode, KeyList mapping, String docstring);
|
||||
void unmap_key(Key key, KeymapMode mode);
|
||||
|
||||
bool is_mapped(Key key, KeymapMode mode) const;
|
||||
ConstArrayView<Key> get_mapping(Key key, KeymapMode mode) const;
|
||||
KeyList get_mapped_keys(KeymapMode mode) const;
|
||||
|
||||
struct KeyMapInfo
|
||||
{
|
||||
KeyList keys;
|
||||
String docstring;
|
||||
};
|
||||
const KeyMapInfo& get_mapping(Key key, KeymapMode mode) const;
|
||||
|
||||
private:
|
||||
KeymapManager()
|
||||
: m_parent(nullptr) {}
|
||||
|
@ -41,10 +50,8 @@ private:
|
|||
friend class Scope;
|
||||
|
||||
KeymapManager* m_parent;
|
||||
|
||||
using KeyAndMode = std::pair<Key, KeymapMode>;
|
||||
using Keymap = UnorderedMap<KeyAndMode, KeyList, MemoryDomain::Mapping>;
|
||||
Keymap m_mapping;
|
||||
UnorderedMap<KeyAndMode, KeyMapInfo, MemoryDomain::Mapping> m_mapping;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
125
src/normal.cc
125
src/normal.cc
|
@ -110,6 +110,49 @@ 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)
|
||||
{
|
||||
auto& keymaps = context.keymaps();
|
||||
|
||||
Vector<std::pair<String, StringView>> descs;
|
||||
for (auto& built_in : built_ins)
|
||||
{
|
||||
String keys = join(built_in.keys |
|
||||
filter([&](Key k){ return not keymaps.is_mapped(k, mode); }) |
|
||||
transform([](Key k) { return key_to_str(k); }),
|
||||
',', false);
|
||||
if (not keys.empty())
|
||||
descs.emplace_back(std::move(keys), built_in.docstring);
|
||||
}
|
||||
|
||||
for (auto& key : keymaps.get_mapped_keys(mode))
|
||||
descs.emplace_back(key_to_str(key),
|
||||
keymaps.get_mapping(key, mode).docstring);
|
||||
|
||||
auto max_len = 0_col;
|
||||
for (auto& desc : descs)
|
||||
{
|
||||
auto len = desc.first.column_length();
|
||||
if (len > max_len)
|
||||
max_len = len;
|
||||
}
|
||||
|
||||
String res;
|
||||
for (auto& desc : descs)
|
||||
res += format("{}:{}{}\n",
|
||||
desc.first,
|
||||
String{' ', max_len - desc.first.column_length() + 1},
|
||||
desc.second);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<SelectMode mode>
|
||||
void goto_commands(Context& context, NormalParams params)
|
||||
{
|
||||
|
@ -233,18 +276,19 @@ void goto_commands(Context& context, NormalParams params)
|
|||
}
|
||||
}
|
||||
}, "goto",
|
||||
"g,k: buffer top \n"
|
||||
"l: line end \n"
|
||||
"h: line begin \n"
|
||||
"i: line non blank start\n"
|
||||
"j: buffer bottom \n"
|
||||
"e: buffer end \n"
|
||||
"t: window top \n"
|
||||
"b: window bottom \n"
|
||||
"c: window center \n"
|
||||
"a: last buffer \n"
|
||||
"f: file \n"
|
||||
".: last buffer change \n");
|
||||
build_autoinfo_for_mapping(context, KeymapMode::Goto,
|
||||
{{{'g','k'},"buffer top"},
|
||||
{{'l'}, "line end"},
|
||||
{{'h'}, "line begin"},
|
||||
{{'i'}, "line non blank start"},
|
||||
{{'j'}, "buffer bottom"},
|
||||
{{'e'}, "buffer end"},
|
||||
{{'t'}, "window top"},
|
||||
{{'b'}, "window bottom"},
|
||||
{{'c'}, "window center"},
|
||||
{{'a'}, "last buffer"},
|
||||
{{'f'}, "file"},
|
||||
{{'.'}, "last buffer change"}}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,14 +340,15 @@ void view_commands(Context& context, NormalParams params)
|
|||
break;
|
||||
}
|
||||
}, "view",
|
||||
"v,c: center cursor (vertically)\n"
|
||||
"m: center cursor (horizontally)\n"
|
||||
"t: cursor on top \n"
|
||||
"b: cursor on bottom\n"
|
||||
"h: scroll left \n"
|
||||
"j: scroll down \n"
|
||||
"k: scroll up \n"
|
||||
"l: scroll right \n");
|
||||
build_autoinfo_for_mapping(context, KeymapMode::View,
|
||||
{{{'v','c'}, "center cursor (vertically)"},
|
||||
{{'m'}, "center cursor (horizontally)"},
|
||||
{{'t'}, "cursor on top"},
|
||||
{{'b'}, "cursor on bottom"},
|
||||
{{'h'}, "scroll left"},
|
||||
{{'j'}, "scroll down"},
|
||||
{{'k'}, "scroll up"},
|
||||
{{'l'}, "scroll right"}}));
|
||||
}
|
||||
|
||||
void replace_with_char(Context& context, NormalParams)
|
||||
|
@ -1085,22 +1130,23 @@ void select_object(Context& context, NormalParams params)
|
|||
utf8cp, utf8cp, count, flags));
|
||||
}
|
||||
}, get_title(),
|
||||
"b,(,): parenthesis block\n"
|
||||
"B,{,}: braces block \n"
|
||||
"r,[,]: brackets block \n"
|
||||
"a,<,>: angle block \n"
|
||||
"\",Q: double quote string\n"
|
||||
"',q: single quote string\n"
|
||||
"`,g: grave quote string \n"
|
||||
"w: word \n"
|
||||
"W: WORD \n"
|
||||
"s: sentence \n"
|
||||
"p: paragraph \n"
|
||||
"␣: whitespaces \n"
|
||||
"i: indent \n"
|
||||
"u: argument \n"
|
||||
"n: number \n"
|
||||
":: custom object desc \n");
|
||||
build_autoinfo_for_mapping(context, KeymapMode::Object,
|
||||
{{{'b','(',')'}, "parenthesis block"},
|
||||
{{'B','{','}'}, "braces block"},
|
||||
{{'r','[',']'}, "brackets block"},
|
||||
{{'a','<','>'}, "angle block"},
|
||||
{{'"','Q'}, "double quote string"},
|
||||
{{'\'','q'}, "single quote string"},
|
||||
{{'`','g'}, "grave quote string"},
|
||||
{{'w'}, "word"},
|
||||
{{'W'}, "WORD"},
|
||||
{{'s'}, "sentence"},
|
||||
{{'p'}, "paragraph"},
|
||||
{{' '}, "whitespaces"},
|
||||
{{'i'}, "indent"},
|
||||
{{'u'}, "argument"},
|
||||
{{'n'}, "number"},
|
||||
{{':'}, "custom object desc"}}));
|
||||
}
|
||||
|
||||
template<Direction direction, bool half = false>
|
||||
|
@ -1588,15 +1634,16 @@ void exec_user_mappings(Context& context, NormalParams params)
|
|||
if (not context.keymaps().is_mapped(key, KeymapMode::User))
|
||||
return;
|
||||
|
||||
auto mapping = context.keymaps().get_mapping(key, KeymapMode::User);
|
||||
auto& mapping = context.keymaps().get_mapping(key, KeymapMode::User);
|
||||
ScopedSetBool disable_keymaps(context.keymaps_disabled());
|
||||
|
||||
InputHandler::ScopedForceNormal force_normal{context.input_handler(), params};
|
||||
|
||||
ScopedEdition edition(context);
|
||||
for (auto& key : mapping)
|
||||
for (auto& key : mapping.keys)
|
||||
context.input_handler().handle_key(key);
|
||||
}, "user mapping", "enter user key");
|
||||
}, "user mapping",
|
||||
build_autoinfo_for_mapping(context, KeymapMode::User, {}));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in New Issue
Block a user