From 7ee15dee3eb9b8d0fc49206b9fd9a56e84bd0a1a Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Wed, 11 Jan 2017 10:26:57 +0100 Subject: Multi-key keybindings --- config.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 12 deletions(-) (limited to 'config.cpp') diff --git a/config.cpp b/config.cpp index 76cf3a2..8bd86f7 100644 --- a/config.cpp +++ b/config.cpp @@ -1,25 +1,87 @@ +#include #include #include "command.h" #include "config.h" +#include "throw.h" using namespace std; -Keybindings global_keybindings={ - {KEY_CTRL+'Q',{"quit_app"}}, - {KEY_BACKSPACE,{"delete_backward"}}, - {KEY_DELETE,{"delete_forward"}}, - {'\n',{"insert_newline"}}, - {'\t',{"insert_char","\t"}}, - {KEY_RIGHT,{"move_forward"}}, - {KEY_LEFT,{"move_backward"}}, - {KEY_DOWN,{"move_downward"}}, - {KEY_UP,{"move_upward"}}, -}; +KeyInputMachine global_keyinput({ + {{KEY_CTRL+'X',KEY_CTRL+'Q'},{"quit_app"}}, + {{KEY_BACKSPACE},{"delete_backward"}}, + {{KEY_DELETE},{"delete_forward"}}, + {{'\n'},{"insert_newline"}}, + {{'\t'},{"insert_char","\t"}}, + {{KEY_RIGHT},{"move_forward"}}, + {{KEY_LEFT},{"move_backward"}}, + {{KEY_DOWN},{"move_downward"}}, + {{KEY_UP},{"move_upward"}}, +}); class Init{public: Init(){ for(int i=32;i<127;i++){ - global_keybindings.emplace(i,Command("insert_char",string(1,(char)i))); + global_keyinput.insert({i},Command("insert_char",string(1,(char)i))); } }} init_object; + + +KeyInputMachine::TreeNode::~TreeNode(){ + if(cmd)delete cmd; + if(m){ + for(const pair &p : *m){ + if(p.second!=nullptr)delete p.second; + } + } +} + +KeyInputMachine::KeyInputMachine(){} + +KeyInputMachine::KeyInputMachine(const vector,Command>> &list){ + for(const pair,Command> &p : list){ + insert(p.first,p.second); + } +} + +void KeyInputMachine::insert(const vector &keys,const Command &cmd){ + assert(keys.size()>0); + TreeNode *node=&root; + for(int key : keys){ + if(node->m==nullptr){ + if(node->cmd){ + THROW("Ambiguous keybinding!"); + } + node->m=new unordered_map; + } + TreeNode *newnode=new TreeNode; + (*node->m)[key]=newnode; + node=newnode; + } + if(node->cmd!=nullptr)delete node->cmd; + node->cmd=new Command(cmd); +} + +Either KeyInputMachine::input(int key){ + if(current->m==nullptr){ + current=&root; + return {Left(),false}; + } + auto it=current->m->find(key); + if(it==current->m->end()){ + current=&root; + return {Left(),false}; + } + current=it->second; + if(current->cmd!=nullptr){ + Command *cmd=current->cmd; + current=&root; + return {Right(),*cmd}; + } else { + return {Left(),true}; + } +} + +void KeyInputMachine::cancel(){ + current=&root; +} -- cgit v1.2.3-54-g00ecf