Refactor commands handling and parsing in a CommandManager class
This commit is contained in:
parent
8baf43ece1
commit
03f1520b43
60
src/command_manager.cc
Normal file
60
src/command_manager.cc
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include "command_manager.hh"
|
||||
|
||||
#include "utils.hh"
|
||||
#include <algorithm>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
void CommandManager::register_command(const std::string& command_name, Command command)
|
||||
{
|
||||
m_commands[command_name] = command;
|
||||
}
|
||||
|
||||
void CommandManager::register_command(const std::vector<std::string>& command_names, Command command)
|
||||
{
|
||||
for (auto command_name : command_names)
|
||||
register_command(command_name, command);
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string& line)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
size_t pos = 0;
|
||||
while (pos != line.length())
|
||||
{
|
||||
while(line[pos] == ' ' and pos != line.length())
|
||||
++pos;
|
||||
|
||||
size_t token_start = pos;
|
||||
|
||||
while((line[pos] != ' ' or line[pos-1] == '\\') and pos != line.length())
|
||||
++pos;
|
||||
|
||||
result.push_back(line.substr(token_start, pos - token_start));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct command_not_found : public std::runtime_error
|
||||
{
|
||||
command_not_found(const std::string& what)
|
||||
: std::runtime_error("command not found: " + what) {}
|
||||
};
|
||||
|
||||
void CommandManager::execute(const std::string& command_line)
|
||||
{
|
||||
std::vector<std::string> tokens = split(command_line);
|
||||
if (tokens.empty())
|
||||
return;
|
||||
|
||||
auto command_it = m_commands.find(tokens[0]);
|
||||
if (command_it == m_commands.end())
|
||||
throw command_not_found(tokens[0]);
|
||||
|
||||
CommandParameters params(tokens.begin() + 1, tokens.end());
|
||||
command_it->second(params);
|
||||
}
|
||||
|
||||
}
|
37
src/command_manager.hh
Normal file
37
src/command_manager.hh
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef command_manager_hh_INCLUDED
|
||||
#define command_manager_hh_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
struct wrong_argument_count : public std::runtime_error
|
||||
{
|
||||
wrong_argument_count()
|
||||
: std::runtime_error("wrong argument count") {}
|
||||
};
|
||||
|
||||
typedef std::vector<std::string> CommandParameters;
|
||||
typedef std::function<void (const CommandParameters&)> Command;
|
||||
|
||||
class CommandManager
|
||||
{
|
||||
public:
|
||||
void execute(const std::string& command_line);
|
||||
|
||||
void register_command(const std::string& command_name, Command command);
|
||||
void register_command(const std::vector<std::string>& command_names, Command command);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, Command> m_commands;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // command_manager_hh_INCLUDED
|
72
src/main.cc
72
src/main.cc
|
@ -3,6 +3,7 @@
|
|||
#include "buffer.hh"
|
||||
#include "file.hh"
|
||||
#include "regex_selector.hh"
|
||||
#include "command_manager.hh"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <cassert>
|
||||
|
@ -153,8 +154,12 @@ void do_insert(Window& window)
|
|||
|
||||
std::shared_ptr<Window> current_window;
|
||||
|
||||
void edit(const std::string& filename)
|
||||
void edit(const CommandParameters& params)
|
||||
{
|
||||
if (params.size() != 1)
|
||||
throw wrong_argument_count();
|
||||
|
||||
std::string filename = params[0];
|
||||
try
|
||||
{
|
||||
std::shared_ptr<Buffer> buffer(create_buffer_from_file(filename));
|
||||
|
@ -163,68 +168,45 @@ void edit(const std::string& filename)
|
|||
}
|
||||
catch (file_not_found& what)
|
||||
{
|
||||
print_status("new file " + filename);
|
||||
current_window = std::make_shared<Window>(std::make_shared<Buffer>(filename));
|
||||
}
|
||||
catch (open_file_error& what)
|
||||
{
|
||||
print_status("error opening '" + filename + "' (" + what.what() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
void write_buffer(const std::string& filename)
|
||||
void write_buffer(const CommandParameters& params)
|
||||
{
|
||||
try
|
||||
{
|
||||
Buffer& buffer = *current_window->buffer();
|
||||
write_buffer_to_file(buffer,
|
||||
filename.empty() ? buffer.name() : filename);
|
||||
}
|
||||
catch(open_file_error& what)
|
||||
{
|
||||
print_status("error opening " + filename + "(" + what.what() + ")");
|
||||
}
|
||||
catch(write_file_error& what)
|
||||
{
|
||||
print_status("error writing " + filename + "(" + what.what() + ")");
|
||||
}
|
||||
if (params.size() > 1)
|
||||
throw wrong_argument_count();
|
||||
|
||||
Buffer& buffer = *current_window->buffer();
|
||||
std::string filename = params.empty() ? buffer.name() : params[0];
|
||||
|
||||
write_buffer_to_file(buffer, filename);
|
||||
}
|
||||
|
||||
bool quit_requested = false;
|
||||
|
||||
void quit(const std::string&)
|
||||
void quit(const CommandParameters& params)
|
||||
{
|
||||
if (params.size() != 0)
|
||||
throw wrong_argument_count();
|
||||
|
||||
quit_requested = true;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::function<void (const std::string& param)>> cmdmap =
|
||||
{
|
||||
{ "e", edit },
|
||||
{ "edit", edit },
|
||||
{ "q", quit },
|
||||
{ "quit", quit },
|
||||
{ "w", write_buffer },
|
||||
{ "write", write_buffer },
|
||||
};
|
||||
CommandManager command_manager;
|
||||
|
||||
void do_command()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string cmd = prompt(":");
|
||||
|
||||
size_t cmd_end = cmd.find_first_of(' ');
|
||||
std::string cmd_name = cmd.substr(0, cmd_end);
|
||||
size_t param_start = cmd.find_first_not_of(' ', cmd_end);
|
||||
std::string param;
|
||||
if (param_start != std::string::npos)
|
||||
param = cmd.substr(param_start, cmd.length() - param_start);
|
||||
|
||||
if (cmdmap.find(cmd_name) != cmdmap.end())
|
||||
cmdmap[cmd_name](param);
|
||||
else
|
||||
print_status(cmd_name + ": no such command");
|
||||
command_manager.execute(prompt(":"));
|
||||
}
|
||||
catch (prompt_aborted&) {}
|
||||
catch (std::runtime_error& err)
|
||||
{
|
||||
print_status(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_blank(char c)
|
||||
|
@ -304,6 +286,10 @@ int main()
|
|||
{
|
||||
init_ncurses();
|
||||
|
||||
command_manager.register_command(std::vector<std::string>{ "e", "edit" }, edit);
|
||||
command_manager.register_command(std::vector<std::string>{ "q", "quit" }, quit);
|
||||
command_manager.register_command(std::vector<std::string>{ "w", "write" }, write_buffer);
|
||||
|
||||
try
|
||||
{
|
||||
auto buffer = std::make_shared<Buffer>("<scratch>");
|
||||
|
|
Loading…
Reference in New Issue
Block a user