Skip to content

Instantly share code, notes, and snippets.

@geekskick
Last active February 11, 2018 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geekskick/2b3a9751af65962fcda1dda885f9092b to your computer and use it in GitHub Desktop.
Save geekskick/2b3a9751af65962fcda1dda885f9092b to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
class LineBuffer;
class Output{
public:
void refresh(void){
std::cout << "Output::refresh\n";
}
// ...
};
class KeyCommand{
public:
virtual ~KeyCommand(void){}
virtual int Execute(LineBuffer&, Output&) = 0;
};
class Line{
public:
Line(void):cursorPosition(0){}
void moveCursorLeft(const int numberChars = 1) { this->cursorPosition-= numberChars; }
void moveCursorRight(const int numberChars = 1) { this->cursorPosition+= numberChars; }
void overwriteLetters(const std::string& letters){ this->letters = letters; }
std::string& string(void) { return this->letters; }
void removeLetter(void){
this->letters.erase(this->letters.begin() + --this->cursorPosition);
}
void insert(const char letter) {
this->letters.insert(this->cursorPosition, this->letters);
this->cursorPosition++;
}
void operator +=(const char& rhs){
this->letters += rhs;
moveCursorRight();
}
void operator +=(const std::string& rhs){
this->letters += rhs;
moveCursorRight(rhs.length());
}
protected:
std::string letters;
int cursorPosition;
};
class LineBuffer{
public:
LineBuffer(void): activeLineNumber(-1){}
void addLine(void){
this->buffer.emplace_back();
this->activeLineNumber++;
}
void moveActiveLineUp(const int numberLines = 1){
if(this->activeLineNumber+numberLines >= 0){
this->activeLineNumber -= numberLines;
}
}
void moveActiveLineDown(const int numberLines = 1){
if(this->activeLineNumber + numberLines <= this->buffer.size()){
this->activeLineNumber += numberLines;
}
}
std::vector<Line>& history(void){ return this->buffer; }
void copyLine(const int from, const int to){ this->buffer[to] = this->buffer[from]; }
Line& activeLine(void){ return this->buffer[this->activeLineNumber];}
void clear(void){ this->buffer.clear(); this->activeLineNumber = -1; }
friend std::ostream& operator <<(std::ostream& os, LineBuffer& lb){
int i = 1;
for (auto& line: lb.buffer) {
os << i++ << ":\t" << line.string() << "\n";
}
return os;
}
protected:
std::vector<Line> buffer;
int activeLineNumber;
};
class Key: public KeyCommand{
public:
virtual ~Key(void){}
Key(const char v) : visualOutput(v){}
char visual(void){return this->visualOutput; }
protected:
char visualOutput;
};
class ReturnKey: public Key{
public:
ReturnKey(void) : Key('\r') {}
~ReturnKey(void){}
int Execute(LineBuffer& lb, Output& o){
lb.addLine();
o.refresh();
return 1;
}
};
class DeleteKey: public Key{
public:
DeleteKey(void) : Key(0x8) {}
~DeleteKey(void){}
int Execute(LineBuffer& lb, Output &o){
lb.activeLine().removeLetter();
o.refresh();
return 1;
}
};
class UpKey:public Key{
public:
UpKey(void) : Key('\033[A') {}
int Execute(LineBuffer&lb, Output&){
lb.moveActiveLineUp();
return 1;
}
};
class DownKey:public Key{
public:
DownKey(void) : Key('\033[B') {}
int Execute(LineBuffer&lb, Output&){
lb.moveActiveLineDown();
return 1;
}
};
class LeftKey:public Key{
public:
LeftKey(void) : Key('\033[C') {}
int Execute(LineBuffer&lb, Output&){
lb.activeLine().moveCursorLeft();
return 1;
}
};
class RightKey:public Key{
public:
RightKey(void) : Key('\033[D') {}
int Execute(LineBuffer&lb, Output&){
lb.activeLine().moveCursorRight();
return 1;
}
};
int main(int argc, const char * argv[]) {
LineBuffer lb;
ReturnKey rKey;
DeleteKey delKey;
UpKey upKey;
DownKey downKey;
LeftKey leftKey;
RightKey rightKey;
std::unordered_map<std::string, KeyCommand*> commands;
Output out;
std::string in;
commands["ret"] = &rKey;
commands["del"] = &delKey;
commands["movup"] = &upKey;
commands["movdown"] = &downKey;
commands["movleft"] = &leftKey;
commands["movright"] = &rightKey;
lb.addLine();
while(1){
std::cin >> in;
if(in == "quit"){
break;
}
else if(in == "print"){
std::cout << lb;
}
else if(commands.end() != commands.find(in)){
commands[in]->Execute(lb, out);
}
else{
lb.activeLine() += in;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment