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"
|
" view\n"
|
||||||
" user\n"
|
" user\n"
|
||||||
" object\n",
|
" object\n",
|
||||||
ParameterDesc{{}, ParameterDesc::Flags::None, 4, 4},
|
ParameterDesc{
|
||||||
|
{ { "docstring", { true, "specify mapping description" } } },
|
||||||
|
ParameterDesc::Flags::None, 4, 4
|
||||||
|
},
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
map_key_completer,
|
map_key_completer,
|
||||||
|
@ -1418,7 +1421,8 @@ const CommandDesc map_key_cmd = {
|
||||||
throw runtime_error("only a single key can be mapped");
|
throw runtime_error("only a single key can be mapped");
|
||||||
|
|
||||||
KeyList mapping = parse_keys(parser[3]);
|
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
|
if (keymaps.is_mapped(key[0], keymap_mode) and
|
||||||
(parser.positional_count() < 4 or
|
(parser.positional_count() < 4 or
|
||||||
(keymaps.get_mapping(key[0], keymap_mode) ==
|
(keymaps.get_mapping(key[0], keymap_mode).keys ==
|
||||||
ConstArrayView<Key>{parse_keys(parser[3])})))
|
parse_keys(parser[3]))))
|
||||||
keymaps.unmap_key(key[0], keymap_mode);
|
keymaps.unmap_key(key[0], keymap_mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1453,7 +1453,7 @@ void InputHandler::handle_key(Key key)
|
||||||
not m_context.keymaps_disabled())
|
not m_context.keymaps_disabled())
|
||||||
{
|
{
|
||||||
ScopedSetBool disable_history{context().history_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);
|
current_mode().handle_key(k);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -3,12 +3,15 @@
|
||||||
#include "array_view.hh"
|
#include "array_view.hh"
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Kakoune
|
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)
|
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));
|
(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});
|
auto it = m_mapping.find({key, mode});
|
||||||
if (it != m_mapping.end())
|
if (it != m_mapping.end())
|
||||||
return { it->second };
|
return it->second;
|
||||||
kak_assert(m_parent);
|
kak_assert(m_parent);
|
||||||
return m_parent->get_mapping(key, mode);
|
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 "array_view.hh"
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
|
#include "string.hh"
|
||||||
#include "unordered_map.hh"
|
#include "unordered_map.hh"
|
||||||
#include "vector.hh"
|
#include "vector.hh"
|
||||||
|
|
||||||
|
@ -29,11 +30,19 @@ public:
|
||||||
KeymapManager(KeymapManager& parent) : m_parent(&parent) {}
|
KeymapManager(KeymapManager& parent) : m_parent(&parent) {}
|
||||||
|
|
||||||
using KeyList = Vector<Key, MemoryDomain::Mapping>;
|
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);
|
void unmap_key(Key key, KeymapMode mode);
|
||||||
|
|
||||||
bool is_mapped(Key key, KeymapMode mode) const;
|
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:
|
private:
|
||||||
KeymapManager()
|
KeymapManager()
|
||||||
: m_parent(nullptr) {}
|
: m_parent(nullptr) {}
|
||||||
|
@ -41,10 +50,8 @@ private:
|
||||||
friend class Scope;
|
friend class Scope;
|
||||||
|
|
||||||
KeymapManager* m_parent;
|
KeymapManager* m_parent;
|
||||||
|
|
||||||
using KeyAndMode = std::pair<Key, KeymapMode>;
|
using KeyAndMode = std::pair<Key, KeymapMode>;
|
||||||
using Keymap = UnorderedMap<KeyAndMode, KeyList, MemoryDomain::Mapping>;
|
UnorderedMap<KeyAndMode, KeyMapInfo, MemoryDomain::Mapping> m_mapping;
|
||||||
Keymap 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();
|
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>
|
template<SelectMode mode>
|
||||||
void goto_commands(Context& context, NormalParams params)
|
void goto_commands(Context& context, NormalParams params)
|
||||||
{
|
{
|
||||||
|
@ -233,18 +276,19 @@ void goto_commands(Context& context, NormalParams params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "goto",
|
}, "goto",
|
||||||
"g,k: buffer top \n"
|
build_autoinfo_for_mapping(context, KeymapMode::Goto,
|
||||||
"l: line end \n"
|
{{{'g','k'},"buffer top"},
|
||||||
"h: line begin \n"
|
{{'l'}, "line end"},
|
||||||
"i: line non blank start\n"
|
{{'h'}, "line begin"},
|
||||||
"j: buffer bottom \n"
|
{{'i'}, "line non blank start"},
|
||||||
"e: buffer end \n"
|
{{'j'}, "buffer bottom"},
|
||||||
"t: window top \n"
|
{{'e'}, "buffer end"},
|
||||||
"b: window bottom \n"
|
{{'t'}, "window top"},
|
||||||
"c: window center \n"
|
{{'b'}, "window bottom"},
|
||||||
"a: last buffer \n"
|
{{'c'}, "window center"},
|
||||||
"f: file \n"
|
{{'a'}, "last buffer"},
|
||||||
".: last buffer change \n");
|
{{'f'}, "file"},
|
||||||
|
{{'.'}, "last buffer change"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,14 +340,15 @@ void view_commands(Context& context, NormalParams params)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, "view",
|
}, "view",
|
||||||
"v,c: center cursor (vertically)\n"
|
build_autoinfo_for_mapping(context, KeymapMode::View,
|
||||||
"m: center cursor (horizontally)\n"
|
{{{'v','c'}, "center cursor (vertically)"},
|
||||||
"t: cursor on top \n"
|
{{'m'}, "center cursor (horizontally)"},
|
||||||
"b: cursor on bottom\n"
|
{{'t'}, "cursor on top"},
|
||||||
"h: scroll left \n"
|
{{'b'}, "cursor on bottom"},
|
||||||
"j: scroll down \n"
|
{{'h'}, "scroll left"},
|
||||||
"k: scroll up \n"
|
{{'j'}, "scroll down"},
|
||||||
"l: scroll right \n");
|
{{'k'}, "scroll up"},
|
||||||
|
{{'l'}, "scroll right"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void replace_with_char(Context& context, NormalParams)
|
void replace_with_char(Context& context, NormalParams)
|
||||||
|
@ -1085,22 +1130,23 @@ void select_object(Context& context, NormalParams params)
|
||||||
utf8cp, utf8cp, count, flags));
|
utf8cp, utf8cp, count, flags));
|
||||||
}
|
}
|
||||||
}, get_title(),
|
}, get_title(),
|
||||||
"b,(,): parenthesis block\n"
|
build_autoinfo_for_mapping(context, KeymapMode::Object,
|
||||||
"B,{,}: braces block \n"
|
{{{'b','(',')'}, "parenthesis block"},
|
||||||
"r,[,]: brackets block \n"
|
{{'B','{','}'}, "braces block"},
|
||||||
"a,<,>: angle block \n"
|
{{'r','[',']'}, "brackets block"},
|
||||||
"\",Q: double quote string\n"
|
{{'a','<','>'}, "angle block"},
|
||||||
"',q: single quote string\n"
|
{{'"','Q'}, "double quote string"},
|
||||||
"`,g: grave quote string \n"
|
{{'\'','q'}, "single quote string"},
|
||||||
"w: word \n"
|
{{'`','g'}, "grave quote string"},
|
||||||
"W: WORD \n"
|
{{'w'}, "word"},
|
||||||
"s: sentence \n"
|
{{'W'}, "WORD"},
|
||||||
"p: paragraph \n"
|
{{'s'}, "sentence"},
|
||||||
"␣: whitespaces \n"
|
{{'p'}, "paragraph"},
|
||||||
"i: indent \n"
|
{{' '}, "whitespaces"},
|
||||||
"u: argument \n"
|
{{'i'}, "indent"},
|
||||||
"n: number \n"
|
{{'u'}, "argument"},
|
||||||
":: custom object desc \n");
|
{{'n'}, "number"},
|
||||||
|
{{':'}, "custom object desc"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Direction direction, bool half = false>
|
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))
|
if (not context.keymaps().is_mapped(key, KeymapMode::User))
|
||||||
return;
|
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());
|
ScopedSetBool disable_keymaps(context.keymaps_disabled());
|
||||||
|
|
||||||
InputHandler::ScopedForceNormal force_normal{context.input_handler(), params};
|
InputHandler::ScopedForceNormal force_normal{context.input_handler(), params};
|
||||||
|
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
for (auto& key : mapping)
|
for (auto& key : mapping.keys)
|
||||||
context.input_handler().handle_key(key);
|
context.input_handler().handle_key(key);
|
||||||
}, "user mapping", "enter user key");
|
}, "user mapping",
|
||||||
|
build_autoinfo_for_mapping(context, KeymapMode::User, {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user