CommandManager: support per command configurable completion
This commit is contained in:
parent
aeea1c610c
commit
63191f1900
|
@ -1,20 +1,24 @@
|
||||||
#include "command_manager.hh"
|
#include "command_manager.hh"
|
||||||
|
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
|
#include "assert.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
void CommandManager::register_command(const std::string& command_name, Command command)
|
void CommandManager::register_command(const std::string& command_name, Command command,
|
||||||
|
const CommandCompleter& completer)
|
||||||
{
|
{
|
||||||
m_commands[command_name] = command;
|
m_commands[command_name] = CommandAndCompleter { command, completer };
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandManager::register_command(const std::vector<std::string>& command_names, Command command)
|
void CommandManager::register_command(const std::vector<std::string>& command_names, Command command,
|
||||||
|
const CommandCompleter& completer)
|
||||||
{
|
{
|
||||||
for (auto command_name : command_names)
|
for (auto command_name : command_names)
|
||||||
register_command(command_name, command);
|
register_command(command_name, command, completer);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::vector<std::pair<size_t, size_t>> TokenList;
|
typedef std::vector<std::pair<size_t, size_t>> TokenList;
|
||||||
|
@ -65,7 +69,7 @@ void CommandManager::execute(const std::string& command_line)
|
||||||
it->second - it->first));
|
it->second - it->first));
|
||||||
}
|
}
|
||||||
|
|
||||||
command_it->second(params);
|
command_it->second.command(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
Completions CommandManager::complete(const std::string& command_line, size_t cursor_pos)
|
Completions CommandManager::complete(const std::string& command_line, size_t cursor_pos)
|
||||||
|
@ -96,14 +100,44 @@ Completions CommandManager::complete(const std::string& command_line, size_t cur
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (token_to_complete == 1) // filename completion
|
|
||||||
|
assert(not tokens.empty());
|
||||||
|
std::string command_name =
|
||||||
|
command_line.substr(tokens[0].first,
|
||||||
|
tokens[0].second - tokens[0].first);
|
||||||
|
|
||||||
|
auto command_it = m_commands.find(command_name);
|
||||||
|
if (command_it == m_commands.end() or not command_it->second.completer)
|
||||||
|
return Completions();
|
||||||
|
|
||||||
|
CommandParameters params;
|
||||||
|
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it)
|
||||||
{
|
{
|
||||||
Completions result(tokens[1].first, cursor_pos);
|
params.push_back(command_line.substr(it->first,
|
||||||
std::string prefix = command_line.substr(tokens[1].first, cursor_pos);
|
it->second - it->first));
|
||||||
result.candidates = complete_filename(prefix);
|
}
|
||||||
|
Completions result(tokens[token_to_complete].first, cursor_pos);
|
||||||
|
size_t cursor_pos_in_token = cursor_pos - tokens[token_to_complete].first;
|
||||||
|
|
||||||
|
result.candidates = command_it->second.completer(params,
|
||||||
|
token_to_complete - 1,
|
||||||
|
cursor_pos_in_token);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return Completions(cursor_pos, cursor_pos);
|
|
||||||
|
CandidateList PerArgumentCommandCompleter::operator()(const CommandParameters& params,
|
||||||
|
size_t token_to_complete,
|
||||||
|
size_t pos_in_token) const
|
||||||
|
{
|
||||||
|
if (token_to_complete >= m_completers.size())
|
||||||
|
return CandidateList();
|
||||||
|
|
||||||
|
// it is possible to try to complete a new argument
|
||||||
|
assert(token_to_complete <= params.size());
|
||||||
|
|
||||||
|
const std::string& argument = token_to_complete < params.size() ?
|
||||||
|
params[token_to_complete] : std::string();
|
||||||
|
return m_completers[token_to_complete](argument, pos_in_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
#include "exception.hh"
|
#include "exception.hh"
|
||||||
#include "completion.hh"
|
#include "completion.hh"
|
||||||
|
@ -20,17 +21,53 @@ struct wrong_argument_count : runtime_error
|
||||||
typedef std::vector<std::string> CommandParameters;
|
typedef std::vector<std::string> CommandParameters;
|
||||||
typedef std::function<void (const CommandParameters&)> Command;
|
typedef std::function<void (const CommandParameters&)> Command;
|
||||||
|
|
||||||
|
typedef std::function<CandidateList (const CommandParameters&,
|
||||||
|
size_t, size_t)> CommandCompleter;
|
||||||
|
|
||||||
|
class PerArgumentCommandCompleter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::function<CandidateList (const std::string&, size_t)> ArgumentCompleter;
|
||||||
|
typedef std::vector<ArgumentCompleter> ArgumentCompleterList;
|
||||||
|
|
||||||
|
PerArgumentCommandCompleter(const ArgumentCompleterList& completers)
|
||||||
|
: m_completers(completers) {}
|
||||||
|
|
||||||
|
PerArgumentCommandCompleter(ArgumentCompleterList&& completers)
|
||||||
|
: m_completers(completers) {}
|
||||||
|
|
||||||
|
PerArgumentCommandCompleter(std::initializer_list<ArgumentCompleter> completers)
|
||||||
|
: m_completers(completers) {}
|
||||||
|
|
||||||
|
CandidateList operator()(const CommandParameters& params,
|
||||||
|
size_t token_to_complete,
|
||||||
|
size_t pos_in_token) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArgumentCompleterList m_completers;
|
||||||
|
};
|
||||||
|
|
||||||
class CommandManager
|
class CommandManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void execute(const std::string& command_line);
|
void execute(const std::string& command_line);
|
||||||
Completions complete(const std::string& command_line, size_t cursor_pos);
|
Completions complete(const std::string& command_line, size_t cursor_pos);
|
||||||
|
|
||||||
void register_command(const std::string& command_name, Command command);
|
void register_command(const std::string& command_name,
|
||||||
void register_command(const std::vector<std::string>& command_names, Command command);
|
Command command,
|
||||||
|
const CommandCompleter& completer = CommandCompleter());
|
||||||
|
|
||||||
|
void register_command(const std::vector<std::string>& command_names,
|
||||||
|
Command command,
|
||||||
|
const CommandCompleter& completer = CommandCompleter());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, Command> m_commands;
|
struct CommandAndCompleter
|
||||||
|
{
|
||||||
|
Command command;
|
||||||
|
CommandCompleter completer;
|
||||||
|
};
|
||||||
|
std::unordered_map<std::string, CommandAndCompleter> m_commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user