parent
043ca99983
commit
f2580a366d
|
@ -194,8 +194,8 @@ public:
|
||||||
|
|
||||||
if (m_waiting_for_reg)
|
if (m_waiting_for_reg)
|
||||||
{
|
{
|
||||||
if (key.modifiers == Key::Modifiers::None)
|
if (auto cp = key.codepoint())
|
||||||
m_params.reg = key.key;
|
m_params.reg = *cp;
|
||||||
m_waiting_for_reg = false;
|
m_waiting_for_reg = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -212,8 +212,9 @@ public:
|
||||||
if (context().has_ui())
|
if (context().has_ui())
|
||||||
context().ui().info_hide();
|
context().ui().info_hide();
|
||||||
|
|
||||||
if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
|
auto cp = key.codepoint();
|
||||||
m_params.count = m_params.count * 10 + key.key - '0';
|
if (cp and isdigit(*cp))
|
||||||
|
m_params.count = m_params.count * 10 + *cp - '0';
|
||||||
else if (key == Key::Backspace)
|
else if (key == Key::Backspace)
|
||||||
m_params.count /= 10;
|
m_params.count /= 10;
|
||||||
else if (key == '\\')
|
else if (key == '\\')
|
||||||
|
@ -397,9 +398,9 @@ public:
|
||||||
to_next_word_end<Word>(m_cursor_pos, m_line);
|
to_next_word_end<Word>(m_cursor_pos, m_line);
|
||||||
else if (key == ctrlalt('e'))
|
else if (key == ctrlalt('e'))
|
||||||
to_next_word_end<WORD>(m_cursor_pos, m_line);
|
to_next_word_end<WORD>(m_cursor_pos, m_line);
|
||||||
else if (key.modifiers == Key::Modifiers::None)
|
else if (auto cp = key.codepoint())
|
||||||
{
|
{
|
||||||
m_line = m_line.substr(0, m_cursor_pos) + codepoint_to_str(key.key)
|
m_line = m_line.substr(0, m_cursor_pos) + codepoint_to_str(*cp)
|
||||||
+ m_line.substr(m_cursor_pos);
|
+ m_line.substr(m_cursor_pos);
|
||||||
++m_cursor_pos;
|
++m_cursor_pos;
|
||||||
}
|
}
|
||||||
|
@ -646,11 +647,14 @@ public:
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
||||||
[this](Key key, Context&) {
|
[this](Key key, Context&) {
|
||||||
StringView reg = context().main_sel_register_value(String{key.key});
|
if (auto cp = key.codepoint())
|
||||||
m_line_editor.insert(reg);
|
{
|
||||||
|
StringView reg = context().main_sel_register_value(String{*cp});
|
||||||
|
m_line_editor.insert(reg);
|
||||||
|
|
||||||
display();
|
display();
|
||||||
m_callback(m_line_editor.line(), PromptEvent::Change, context());
|
m_callback(m_line_editor.line(), PromptEvent::Change, context());
|
||||||
|
}
|
||||||
}, "Enter register name", register_doc);
|
}, "Enter register name", register_doc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1013,21 +1017,17 @@ public:
|
||||||
}
|
}
|
||||||
selections.sort_and_merge_overlapping();
|
selections.sort_and_merge_overlapping();
|
||||||
}
|
}
|
||||||
else if (key.modifiers == Key::Modifiers::None)
|
else if (auto cp = key.codepoint())
|
||||||
insert(key.key);
|
insert(*cp);
|
||||||
else if (key == ctrl('r'))
|
else if (key == ctrl('r'))
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
||||||
[this](Key key, Context&) {
|
[this](Key key, Context&) {
|
||||||
if (key.modifiers == Key::Modifiers::None)
|
if (auto cp = key.codepoint())
|
||||||
insert(RegisterManager::instance()[key.key].values(context()));
|
insert(RegisterManager::instance()[*cp].values(context()));
|
||||||
}, "Enter register name", register_doc);
|
}, "Enter register name", register_doc);
|
||||||
update_completions = false;
|
update_completions = false;
|
||||||
}
|
}
|
||||||
else if (key == ctrl('m'))
|
|
||||||
insert('\n');
|
|
||||||
else if (key == ctrl('i'))
|
|
||||||
insert('\t');
|
|
||||||
else if (key == ctrl('n'))
|
else if (key == ctrl('n'))
|
||||||
{
|
{
|
||||||
last_insert().keys.pop_back();
|
last_insert().keys.pop_back();
|
||||||
|
@ -1044,11 +1044,11 @@ public:
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
on_next_key_with_autoinfo(context(), KeymapMode::None,
|
||||||
[this](Key key, Context&) {
|
[this](Key key, Context&) {
|
||||||
if (key.key == 'f')
|
if (key == 'f')
|
||||||
m_completer.explicit_file_complete();
|
m_completer.explicit_file_complete();
|
||||||
if (key.key == 'w')
|
if (key == 'w')
|
||||||
m_completer.explicit_word_complete();
|
m_completer.explicit_word_complete();
|
||||||
if (key.key == 'l')
|
if (key == 'l')
|
||||||
m_completer.explicit_line_complete();
|
m_completer.explicit_line_complete();
|
||||||
}, "Complete",
|
}, "Complete",
|
||||||
" Enter completion type:\n"
|
" Enter completion type:\n"
|
||||||
|
|
14
src/keys.cc
14
src/keys.cc
|
@ -10,7 +10,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
Key canonicalize_ifn(Key key)
|
static Key canonicalize_ifn(Key key)
|
||||||
{
|
{
|
||||||
if (key.key > 0 and key.key < 27)
|
if (key.key > 0 and key.key < 27)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,18 @@ Key canonicalize_ifn(Key key)
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<Codepoint> Key::codepoint() const
|
||||||
|
{
|
||||||
|
if (*this == ctrl('m'))
|
||||||
|
return '\n';
|
||||||
|
if (*this == ctrl('i'))
|
||||||
|
return '\t';
|
||||||
|
if (modifiers == Modifiers::None and key > 27 and
|
||||||
|
(key < 0xD800 or key > 0xDFFF)) // avoid surrogates
|
||||||
|
return key;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
struct KeyAndName { const char* name; Codepoint key; };
|
struct KeyAndName { const char* name; Codepoint key; };
|
||||||
static constexpr KeyAndName keynamemap[] = {
|
static constexpr KeyAndName keynamemap[] = {
|
||||||
{ "ret", '\r' },
|
{ "ret", '\r' },
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#ifndef keys_hh_INCLUDED
|
#ifndef keys_hh_INCLUDED
|
||||||
#define keys_hh_INCLUDED
|
#define keys_hh_INCLUDED
|
||||||
|
|
||||||
#include "unicode.hh"
|
#include "coord.hh"
|
||||||
#include "flags.hh"
|
#include "flags.hh"
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
|
#include "optional.hh"
|
||||||
|
#include "unicode.hh"
|
||||||
#include "vector.hh"
|
#include "vector.hh"
|
||||||
#include "coord.hh"
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -75,6 +76,8 @@ struct Key
|
||||||
constexpr bool operator<(Key other) const { return val() < other.val(); }
|
constexpr bool operator<(Key other) const { return val() < other.val(); }
|
||||||
|
|
||||||
constexpr CharCoord mouse_coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
|
constexpr CharCoord mouse_coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
|
||||||
|
|
||||||
|
Optional<Codepoint> codepoint() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct WithBitOps<Key::Modifiers> : std::true_type {};
|
template<> struct WithBitOps<Key::Modifiers> : std::true_type {};
|
||||||
|
|
|
@ -110,10 +110,11 @@ void goto_commands(Context& context, NormalParams params)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::Goto,
|
on_next_key_with_autoinfo(context, KeymapMode::Goto,
|
||||||
[](Key key, Context& context) {
|
[](Key key, Context& context) {
|
||||||
if (key.modifiers != Key::Modifiers::None)
|
auto cp = key.codepoint();
|
||||||
|
if (not cp)
|
||||||
return;
|
return;
|
||||||
auto& buffer = context.buffer();
|
auto& buffer = context.buffer();
|
||||||
switch (tolower(key.key))
|
switch (tolower(*cp))
|
||||||
{
|
{
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'k':
|
case 'k':
|
||||||
|
@ -234,12 +235,13 @@ void view_commands(Context& context, NormalParams params)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::View,
|
on_next_key_with_autoinfo(context, KeymapMode::View,
|
||||||
[params](Key key, Context& context) {
|
[params](Key key, Context& context) {
|
||||||
if (key.modifiers != Key::Modifiers::None or not context.has_window())
|
auto cp = key.codepoint();
|
||||||
|
if (not cp or not context.has_window())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LineCount cursor_line = context.selections().main().cursor().line;
|
LineCount cursor_line = context.selections().main().cursor().line;
|
||||||
Window& window = context.window();
|
Window& window = context.window();
|
||||||
switch (tolower(key.key))
|
switch (tolower(*cp))
|
||||||
{
|
{
|
||||||
case 'v':
|
case 'v':
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -278,7 +280,8 @@ void replace_with_char(Context& context, NormalParams)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[](Key key, Context& context) {
|
[](Key key, Context& context) {
|
||||||
if (not iswprint(key.key))
|
auto cp = key.codepoint();
|
||||||
|
if (not cp)
|
||||||
return;
|
return;
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
Buffer& buffer = context.buffer();
|
Buffer& buffer = context.buffer();
|
||||||
|
@ -287,7 +290,7 @@ void replace_with_char(Context& context, NormalParams)
|
||||||
for (auto& sel : selections)
|
for (auto& sel : selections)
|
||||||
{
|
{
|
||||||
CharCount count = char_length(buffer, sel);
|
CharCount count = char_length(buffer, sel);
|
||||||
strings.emplace_back(key.key, count);
|
strings.emplace_back(*cp, count);
|
||||||
}
|
}
|
||||||
selections.insert(strings, InsertMode::Replace);
|
selections.insert(strings, InsertMode::Replace);
|
||||||
}, "replace with char", "enter char to replace with\n");
|
}, "replace with char", "enter char to replace with\n");
|
||||||
|
@ -857,9 +860,9 @@ void select_object(Context& context, NormalParams params)
|
||||||
const int level = params.count <= 0 ? 0 : params.count - 1;
|
const int level = params.count <= 0 ? 0 : params.count - 1;
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::Object,
|
on_next_key_with_autoinfo(context, KeymapMode::Object,
|
||||||
[level](Key key, Context& context) {
|
[level](Key key, Context& context) {
|
||||||
if (key.modifiers != Key::Modifiers::None)
|
auto cp = key.codepoint();
|
||||||
|
if (not cp)
|
||||||
return;
|
return;
|
||||||
const Codepoint c = key.key;
|
|
||||||
|
|
||||||
static constexpr struct
|
static constexpr struct
|
||||||
{
|
{
|
||||||
|
@ -876,11 +879,11 @@ void select_object(Context& context, NormalParams params)
|
||||||
};
|
};
|
||||||
for (auto& sel : selectors)
|
for (auto& sel : selectors)
|
||||||
{
|
{
|
||||||
if (c == sel.key)
|
if (*cp == sel.key)
|
||||||
return select<mode>(context, std::bind(sel.func, _1, _2, flags));
|
return select<mode>(context, std::bind(sel.func, _1, _2, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 'u')
|
if (*cp == 'u')
|
||||||
{
|
{
|
||||||
return select<mode>(context, std::bind(select_argument, _1, _2, level, flags));
|
return select<mode>(context, std::bind(select_argument, _1, _2, level, flags));
|
||||||
}
|
}
|
||||||
|
@ -900,8 +903,8 @@ void select_object(Context& context, NormalParams params)
|
||||||
};
|
};
|
||||||
for (auto& sur : surrounding_pairs)
|
for (auto& sur : surrounding_pairs)
|
||||||
{
|
{
|
||||||
if (sur.pair.opening == c or sur.pair.closing == c or
|
if (sur.pair.opening == *cp or sur.pair.closing == *cp or
|
||||||
(sur.name != 0 and sur.name == c))
|
(sur.name != 0 and sur.name == *cp))
|
||||||
return select<mode>(context, std::bind(select_surrounding, _1, _2,
|
return select<mode>(context, std::bind(select_surrounding, _1, _2,
|
||||||
sur.pair, level, flags));
|
sur.pair, level, flags));
|
||||||
}
|
}
|
||||||
|
@ -1026,10 +1029,13 @@ void select_to_next_char(Context& context, NormalParams params)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[params](Key key, Context& context) {
|
[params](Key key, Context& context) {
|
||||||
select<flags & SelectFlags::Extend ? SelectMode::Extend : SelectMode::Replace>(
|
constexpr auto new_flags = flags & SelectFlags::Extend ? SelectMode::Extend
|
||||||
context,
|
: SelectMode::Replace;
|
||||||
std::bind(flags & SelectFlags::Reverse ? select_to_reverse : select_to,
|
if (auto cp = key.codepoint())
|
||||||
_1, _2, key.key, params.count, flags & SelectFlags::Inclusive));
|
select<new_flags>(
|
||||||
|
context,
|
||||||
|
std::bind(flags & SelectFlags::Reverse ? select_to_reverse : select_to,
|
||||||
|
_1, _2, *cp, params.count, flags & SelectFlags::Inclusive));
|
||||||
}, "select to next char","enter char to select to");
|
}, "select to next char","enter char to select to");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,8 +1051,9 @@ void start_or_end_macro_recording(Context& context, NormalParams)
|
||||||
else
|
else
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[](Key key, Context& context) {
|
[](Key key, Context& context) {
|
||||||
if (key.modifiers == Key::Modifiers::None and is_basic_alpha(key.key))
|
auto cp = key.codepoint();
|
||||||
context.input_handler().start_recording(tolower(key.key));
|
if (cp and is_basic_alpha(*cp))
|
||||||
|
context.input_handler().start_recording(tolower(*cp));
|
||||||
}, "record macro", "enter macro name ");
|
}, "record macro", "enter macro name ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,10 +1067,11 @@ void replay_macro(Context& context, NormalParams params)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[params](Key key, Context& context) mutable {
|
[params](Key key, Context& context) mutable {
|
||||||
if (key.modifiers == Key::Modifiers::None and is_basic_alpha(key.key))
|
auto cp = key.codepoint();
|
||||||
|
if (cp and is_basic_alpha(*cp))
|
||||||
{
|
{
|
||||||
static bool running_macros[26] = {};
|
static bool running_macros[26] = {};
|
||||||
const char name = tolower(key.key);
|
const char name = tolower(*cp);
|
||||||
const size_t idx = (size_t)(name - 'a');
|
const size_t idx = (size_t)(name - 'a');
|
||||||
if (running_macros[idx])
|
if (running_macros[idx])
|
||||||
throw runtime_error("recursive macros call detected");
|
throw runtime_error("recursive macros call detected");
|
||||||
|
@ -1255,18 +1263,18 @@ void save_selections(Context& context, NormalParams)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[](Key key, Context& context) {
|
[](Key key, Context& context) {
|
||||||
if (key.modifiers != Key::Modifiers::None or key == Key::Escape)
|
auto cp = key.codepoint();
|
||||||
|
if (not cp or not is_basic_alpha(*cp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const char reg = key.key;
|
|
||||||
String desc = format("{}@{}%{}",
|
String desc = format("{}@{}%{}",
|
||||||
selection_list_to_string(context.selections()),
|
selection_list_to_string(context.selections()),
|
||||||
context.buffer().name(),
|
context.buffer().name(),
|
||||||
context.buffer().timestamp());
|
context.buffer().timestamp());
|
||||||
|
|
||||||
RegisterManager::instance()[reg] = desc;
|
RegisterManager::instance()[*cp] = desc;
|
||||||
|
|
||||||
context.print_status({format("Saved selections in register '{}'", reg), get_face("Information")});
|
context.print_status({format("Saved selections in register '{}'", *cp), get_face("Information")});
|
||||||
}, "Save selections", "Enter register to save selections into");
|
}, "Save selections", "Enter register to save selections into");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,22 +1282,21 @@ void restore_selections(Context& context, NormalParams)
|
||||||
{
|
{
|
||||||
on_next_key_with_autoinfo(context, KeymapMode::None,
|
on_next_key_with_autoinfo(context, KeymapMode::None,
|
||||||
[](Key key, Context& context) {
|
[](Key key, Context& context) {
|
||||||
if (key.modifiers != Key::Modifiers::None or key == Key::Escape)
|
auto cp = key.codepoint();
|
||||||
|
if (not cp or not is_basic_alpha(*cp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const char reg = key.key;
|
auto content = RegisterManager::instance()[*cp].values(context);
|
||||||
|
|
||||||
auto content = RegisterManager::instance()[reg].values(context);
|
|
||||||
|
|
||||||
if (content.size() != 1)
|
if (content.size() != 1)
|
||||||
throw runtime_error(format("Register {} does not contain a selections desc", reg));
|
throw runtime_error(format("Register {} does not contain a selections desc", *cp));
|
||||||
|
|
||||||
StringView desc = content[0];
|
StringView desc = content[0];
|
||||||
auto arobase = find(desc, '@');
|
auto arobase = find(desc, '@');
|
||||||
auto percent = find(desc, '%');
|
auto percent = find(desc, '%');
|
||||||
|
|
||||||
if (arobase == desc.end() or percent == desc.end())
|
if (arobase == desc.end() or percent == desc.end())
|
||||||
throw runtime_error(format("Register {} does not contain a selections desc", reg));
|
throw runtime_error(format("Register {} does not contain a selections desc", *cp));
|
||||||
|
|
||||||
Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent});
|
Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent});
|
||||||
size_t timestamp = str_to_int({percent + 1, desc.end()});
|
size_t timestamp = str_to_int({percent + 1, desc.end()});
|
||||||
|
@ -1305,7 +1312,7 @@ void restore_selections(Context& context, NormalParams)
|
||||||
|
|
||||||
context.selections_write_only() = std::move(sel_list);
|
context.selections_write_only() = std::move(sel_list);
|
||||||
|
|
||||||
context.print_status({format("Restored selections from register '{}'", reg), get_face("Information")});
|
context.print_status({format("Restored selections from register '{}'", *cp), get_face("Information")});
|
||||||
}, "Restore selections", "Enter register to restore selections from");
|
}, "Restore selections", "Enter register to restore selections from");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user