Merge branch 'master' into remove-buffer-change-listener
This commit is contained in:
commit
1ffafa8650
|
@ -340,6 +340,7 @@ object you want.
|
||||||
* _s_: select the sentence
|
* _s_: select the sentence
|
||||||
* _p_: select the paragraph
|
* _p_: select the paragraph
|
||||||
* _i_: select the current indentation block
|
* _i_: select the current indentation block
|
||||||
|
* _n_: select the number
|
||||||
|
|
||||||
For nestable objects, a count can be used in order to specify which surrounding
|
For nestable objects, a count can be used in order to specify which surrounding
|
||||||
level to select.
|
level to select.
|
||||||
|
|
|
@ -30,21 +30,11 @@ void CommandManager::register_command(String command_name,
|
||||||
std::move(completer) };
|
std::move(completer) };
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::register_commands(memoryview<String> command_names,
|
void CommandManager::register_alias(String alias, String command)
|
||||||
Command command,
|
|
||||||
String docstring,
|
|
||||||
ParameterDesc param_desc,
|
|
||||||
CommandFlags flags,
|
|
||||||
CommandCompleter completer)
|
|
||||||
{
|
{
|
||||||
kak_assert(not command_names.empty());
|
kak_assert(not alias.empty());
|
||||||
m_commands[command_names[0]] = { std::move(command),
|
kak_assert(command_defined(command));
|
||||||
std::move(docstring),
|
m_aliases[alias] = std::move(command);
|
||||||
std::move(param_desc),
|
|
||||||
flags,
|
|
||||||
completer };
|
|
||||||
for (size_t i = 1; i < command_names.size(); ++i)
|
|
||||||
m_aliases[command_names[i]] = command_names[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct parse_error : runtime_error
|
struct parse_error : runtime_error
|
||||||
|
|
|
@ -79,12 +79,7 @@ public:
|
||||||
ParameterDesc param_desc,
|
ParameterDesc param_desc,
|
||||||
CommandFlags flags = CommandFlags::None,
|
CommandFlags flags = CommandFlags::None,
|
||||||
CommandCompleter completer = CommandCompleter());
|
CommandCompleter completer = CommandCompleter());
|
||||||
|
void register_alias(String alias, String command);
|
||||||
void register_commands(memoryview<String> command_names, Command command,
|
|
||||||
String docstring,
|
|
||||||
ParameterDesc param_desc,
|
|
||||||
CommandFlags flags = CommandFlags::None,
|
|
||||||
CommandCompleter completer = CommandCompleter());
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void execute_single_command(CommandParameters params,
|
void execute_single_command(CommandParameters params,
|
||||||
|
|
|
@ -568,6 +568,14 @@ void define_command(const ParametersParser& parser, Context& context)
|
||||||
if (parser.has_option("docstring"))
|
if (parser.has_option("docstring"))
|
||||||
docstring = parser.option_value("docstring");
|
docstring = parser.option_value("docstring");
|
||||||
|
|
||||||
|
String alias;
|
||||||
|
if (parser.has_option("alias"))
|
||||||
|
{
|
||||||
|
alias = parser.option_value("alias");
|
||||||
|
if (alias.empty())
|
||||||
|
throw runtime_error("alias should not be an empty string");
|
||||||
|
}
|
||||||
|
|
||||||
String commands = parser[1];
|
String commands = parser[1];
|
||||||
Command cmd;
|
Command cmd;
|
||||||
ParameterDesc desc;
|
ParameterDesc desc;
|
||||||
|
@ -649,13 +657,11 @@ void define_command(const ParametersParser& parser, Context& context)
|
||||||
return Completions{ 0_byte, params[token_to_complete].length(), split(output, '\n') };
|
return Completions{ 0_byte, params[token_to_complete].length(), split(output, '\n') };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (parser.has_option("alias"))
|
|
||||||
CommandManager::instance().register_commands(
|
auto& cm = CommandManager::instance();
|
||||||
{ cmd_name, parser.option_value("alias") },
|
cm.register_command(cmd_name, cmd, std::move(docstring), desc, flags, completer);
|
||||||
cmd, std::move(docstring), desc, flags, completer);
|
if (not alias.empty())
|
||||||
else
|
cm.register_alias(std::move(alias), cmd_name);
|
||||||
CommandManager::instance().register_command(
|
|
||||||
cmd_name, cmd, std::move(docstring), desc, flags, completer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommandDesc define_command_cmd = {
|
const CommandDesc define_command_cmd = {
|
||||||
|
@ -1322,10 +1328,9 @@ void exec_keys(const KeyList& keys, Context& context)
|
||||||
|
|
||||||
static void register_command(CommandManager& cm, const CommandDesc& c)
|
static void register_command(CommandManager& cm, const CommandDesc& c)
|
||||||
{
|
{
|
||||||
if (c.alias)
|
|
||||||
cm.register_commands({ c.name, c.alias }, c.func, c.docstring, c.params, c.flags, c.completer);
|
|
||||||
else
|
|
||||||
cm.register_command(c.name, c.func, c.docstring, c.params, c.flags, c.completer);
|
cm.register_command(c.name, c.func, c.docstring, c.params, c.flags, c.completer);
|
||||||
|
if (c.alias)
|
||||||
|
cm.register_alias(c.alias, c.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_commands()
|
void register_commands()
|
||||||
|
|
|
@ -18,6 +18,9 @@ public:
|
||||||
using iterator = typename container_type::iterator;
|
using iterator = typename container_type::iterator;
|
||||||
using const_iterator = typename container_type::const_iterator;
|
using const_iterator = typename container_type::const_iterator;
|
||||||
|
|
||||||
|
id_map() = default;
|
||||||
|
id_map(std::initializer_list<value_type> val) : m_content{val} {}
|
||||||
|
|
||||||
void append(const value_type& value)
|
void append(const value_type& value)
|
||||||
{
|
{
|
||||||
m_content.push_back(value);
|
m_content.push_back(value);
|
||||||
|
@ -91,6 +94,8 @@ public:
|
||||||
prefix, cursor_pos, [](const value_type&) { return true; });
|
prefix, cursor_pos, [](const value_type&) { return true; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool empty() const { return m_content.empty(); }
|
||||||
|
|
||||||
iterator begin() { return m_content.begin(); }
|
iterator begin() { return m_content.begin(); }
|
||||||
iterator end() { return m_content.end(); }
|
iterator end() { return m_content.end(); }
|
||||||
const_iterator begin() const { return m_content.begin(); }
|
const_iterator begin() const { return m_content.begin(); }
|
||||||
|
|
35
src/keys.cc
35
src/keys.cc
|
@ -1,6 +1,7 @@
|
||||||
#include "keys.hh"
|
#include "keys.hh"
|
||||||
|
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
|
#include "utf8_iterator.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -40,19 +41,21 @@ static const KeyAndName keynamemap[] = {
|
||||||
KeyList parse_keys(StringView str)
|
KeyList parse_keys(StringView str)
|
||||||
{
|
{
|
||||||
KeyList result;
|
KeyList result;
|
||||||
for (ByteCount pos = 0; pos < str.length(); ++pos)
|
using PassPolicy = utf8::InvalidBytePolicy::Pass;
|
||||||
|
using Utf8It = utf8::utf8_iterator<const char*, PassPolicy>;
|
||||||
|
for (Utf8It it = str.begin(), str_end = str.end(); it < str_end; ++it)
|
||||||
{
|
{
|
||||||
if (str[pos] == '<')
|
if (*it == '<')
|
||||||
{
|
{
|
||||||
ByteCount end_pos = pos;
|
Utf8It end_it = it;
|
||||||
while (end_pos < str.length() and str[end_pos] != '>')
|
while (end_it < str_end and *end_it != '>')
|
||||||
++end_pos;
|
++end_it;
|
||||||
|
|
||||||
if (end_pos < str.length())
|
if (end_it < str_end)
|
||||||
{
|
{
|
||||||
Key::Modifiers modifier = Key::Modifiers::None;
|
Key::Modifiers modifier = Key::Modifiers::None;
|
||||||
|
|
||||||
auto keyname = str.substr(pos+1, end_pos - pos - 1);
|
StringView keyname{it.base()+1, end_it.base()};
|
||||||
if (keyname.length() > 2)
|
if (keyname.length() > 2)
|
||||||
{
|
{
|
||||||
if (tolower(keyname[0]) == 'c' and keyname[1] == '-')
|
if (tolower(keyname[0]) == 'c' and keyname[1] == '-')
|
||||||
|
@ -66,19 +69,19 @@ KeyList parse_keys(StringView str)
|
||||||
keyname = keyname.substr(2_byte);
|
keyname = keyname.substr(2_byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keyname.length() == 1)
|
if (keyname.char_length() == 1)
|
||||||
{
|
{
|
||||||
result.push_back(Key{ modifier, Codepoint(keyname[0]) });
|
result.push_back(Key{ modifier, utf8::codepoint<PassPolicy>(keyname.begin()) });
|
||||||
pos = end_pos;
|
it = end_it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto it = find_if(keynamemap, [&keyname](const KeyAndName& item)
|
auto name_it = find_if(keynamemap, [&keyname](const KeyAndName& item)
|
||||||
{ return item.first == keyname; });
|
{ return item.first == keyname; });
|
||||||
if (it != end(keynamemap))
|
if (name_it != end(keynamemap))
|
||||||
{
|
{
|
||||||
Key key = canonicalize_ifn(Key{ modifier, it->second });
|
Key key = canonicalize_ifn(Key{ modifier, name_it->second });
|
||||||
result.push_back(key);
|
result.push_back(key);
|
||||||
pos = end_pos;
|
it = end_it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((keyname[0] == 'f' or keyname[0] == 'F') and
|
if ((keyname[0] == 'f' or keyname[0] == 'F') and
|
||||||
|
@ -100,13 +103,13 @@ KeyList parse_keys(StringView str)
|
||||||
if (val >= 1 and val <= 12)
|
if (val >= 1 and val <= 12)
|
||||||
{
|
{
|
||||||
result.push_back(Key{ modifier, Key::F1 + (val - 1) });
|
result.push_back(Key{ modifier, Key::F1 + (val - 1) });
|
||||||
pos = end_pos;
|
it = end_it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.push_back({Key::Modifiers::None, Codepoint(str[pos])});
|
result.push_back({Key::Modifiers::None, *it});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -840,6 +840,7 @@ void select_object(Context& context, int param)
|
||||||
{ 's', select_sentence },
|
{ 's', select_sentence },
|
||||||
{ 'p', select_paragraph },
|
{ 'p', select_paragraph },
|
||||||
{ 'i', select_indent },
|
{ 'i', select_indent },
|
||||||
|
{ 'n', select_number },
|
||||||
};
|
};
|
||||||
for (auto& sel : selectors)
|
for (auto& sel : selectors)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
#define parameters_parser_hh_INCLUDED
|
#define parameters_parser_hh_INCLUDED
|
||||||
|
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
|
#include "id_map.hh"
|
||||||
#include "memoryview.hh"
|
#include "memoryview.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ struct SwitchDesc
|
||||||
String description;
|
String description;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SwitchMap = std::unordered_map<String, SwitchDesc>;
|
using SwitchMap = id_map<SwitchDesc>;
|
||||||
|
|
||||||
String generate_switches_doc(const SwitchMap& opts);
|
String generate_switches_doc(const SwitchMap& opts);
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,31 @@ Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection
|
||||||
return utf8_range(begin, end == buffer.begin() ? end : end+1);
|
return utf8_range(begin, end == buffer.begin() ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Selection select_number(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
|
||||||
|
{
|
||||||
|
auto is_number = [&](char c) {
|
||||||
|
return (c >= '0' and c <= '9') or
|
||||||
|
(not (flags & ObjectFlags::Inner) and c == '.');
|
||||||
|
};
|
||||||
|
|
||||||
|
BufferIterator first = buffer.iterator_at(selection.cursor());
|
||||||
|
if (flags & ObjectFlags::ToBegin)
|
||||||
|
{
|
||||||
|
skip_while_reverse(first, buffer.begin(), is_number);
|
||||||
|
if (not is_number(*first) or not *first == '-')
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
BufferIterator last = buffer.iterator_at(selection.cursor());
|
||||||
|
if (flags & ObjectFlags::ToEnd)
|
||||||
|
{
|
||||||
|
skip_while(last, buffer.end(), is_number);
|
||||||
|
--last;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (flags & ObjectFlags::ToEnd) ? Selection{first.coord(), last.coord()}
|
||||||
|
: Selection{last.coord(), first.coord()};
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_end_of_sentence(char c)
|
static bool is_end_of_sentence(char c)
|
||||||
{
|
{
|
||||||
return c == '.' or c == ';' or c == '!' or c == '?';
|
return c == '.' or c == ';' or c == '!' or c == '?';
|
||||||
|
|
|
@ -134,10 +134,8 @@ Selection select_to_previous_word(const Buffer& buffer, const Selection& selecti
|
||||||
return utf8_range(begin, with_end ? end : end+1);
|
return utf8_range(begin, with_end ? end : end+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_line(const Buffer& buffer,
|
Selection select_line(const Buffer& buffer, const Selection& selection);
|
||||||
const Selection& selection);
|
Selection select_matching(const Buffer& buffer, const Selection& selection);
|
||||||
Selection select_matching(const Buffer& buffer,
|
|
||||||
const Selection& selection);
|
|
||||||
|
|
||||||
Selection select_to(const Buffer& buffer, const Selection& selection,
|
Selection select_to(const Buffer& buffer, const Selection& selection,
|
||||||
Codepoint c, int count, bool inclusive);
|
Codepoint c, int count, bool inclusive);
|
||||||
|
@ -159,7 +157,9 @@ constexpr ObjectFlags operator|(ObjectFlags lhs, ObjectFlags rhs)
|
||||||
{ return (ObjectFlags)((int)lhs | (int) rhs); }
|
{ return (ObjectFlags)((int)lhs | (int) rhs); }
|
||||||
|
|
||||||
template<WordType word_type>
|
template<WordType word_type>
|
||||||
Selection select_word(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
|
Selection select_word(const Buffer& buffer,
|
||||||
|
const Selection& selection,
|
||||||
|
ObjectFlags flags)
|
||||||
{
|
{
|
||||||
Utf8Iterator first = buffer.iterator_at(selection.cursor());
|
Utf8Iterator first = buffer.iterator_at(selection.cursor());
|
||||||
Utf8Iterator last = first;
|
Utf8Iterator last = first;
|
||||||
|
@ -200,6 +200,10 @@ Selection select_word(const Buffer& buffer, const Selection& selection, ObjectFl
|
||||||
: utf8_range(last, first);
|
: utf8_range(last, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Selection select_number(const Buffer& buffer,
|
||||||
|
const Selection& selection,
|
||||||
|
ObjectFlags flags);
|
||||||
|
|
||||||
Selection select_sentence(const Buffer& buffer,
|
Selection select_sentence(const Buffer& buffer,
|
||||||
const Selection& selection,
|
const Selection& selection,
|
||||||
ObjectFlags flags);
|
ObjectFlags flags);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user