#include #include #include #include #include "treap.hpp" using std::string; #define ESC 27 #define ENTER 10 #define BS 127 #define adds(s) addstr(s.c_str()) enum mode_type { INSERT, NORMAL, SELECT }; // Global variables treap file; int row = 0, col = 0; int file_offset = 0; // Accessing the file string get_line(int r) { string line = (*file.find(file_offset+r)).text; for(int i = 0; i < line.size(); ++i) if(line[i] == '\t') line[i] = ' '; return line; } char get(int r, int s) { return get_line(file_offset+r)[s]; } void set(int r, int s, char ch) { file.find(file_offset+r)->text[s] = ch; } void new_line(int r, string text = "") { file.insert(file_offset+r, text); } void insert(int r, int s, string t) { file.find(file_offset+r)->text.insert(s, t); } void insert(int r, int s, char ch) { insert(r, s, string{ch}); } void append(string t) { file.append(t); } void remove(int r, int s, int len=1) { file.find(file_offset+r)->text.erase(s,len); } void remove(int r) { file.remove(file_offset+r); } int get_number() { char ch = '0'; string s = ""; while(ch >= '0' && ch <= '9') { s += ch; ch = getch(); } return stoi(s); } // Load file to buffer bool load(string filename) { std::ifstream infile(filename); if(!infile.good()) return 1; string line; while (std::getline(infile, line)) append(line); return 0; } // Save file from buffer bool save(string filename) { std::ofstream outfile(filename); if(!outfile.good()) return 1; for(int i = 0; i < file.size(); ++i) outfile << get_line(i-file_offset) << std::endl; return 0; } // Clear line void clear_line(int pos) { move(pos, 0); clrtoeol(); } // Print line void print_line(int pos) { clear_line(pos); move(pos, 0); adds(get_line(pos)); } // Print file content void print_file(int start = 0) { for(int i = start; i < LINES; i++) if(file_offset+i < file.size()) print_line(i); else clear_line(i); } // Splitting lines string split_line(int r, int s) { string line = get_line(r); string ret = line.substr(s, line.size()); remove(r, s, line.size()-s); return ret; } // TODO kopirování // TODO hledání a nahrazování // TODO undo // Jump to end of line void jump_line_end() { int line_size = get_line(row).size(); if(col > line_size) col = line_size; } // Cursor movement void move_cursor(char ch) { switch(ch) { case 'h': if(col > 0) move(row, --col); break; case 'j': if(file_offset + row >= file.size()-1) break; if(row < LINES-1) { move(++row, col); jump_line_end(); } else if(row == LINES-1) { file_offset++; jump_line_end(); print_file(); } break; case 'k': if(row > 0) { move(--row, col); jump_line_end(); } else if(file_offset > 0) { file_offset--; jump_line_end(); print_file(); } break; case 'l': if(col < get_line(row).size()) move(row, ++col); break; } } // Skoky a přesuny void jump(int r) { file_offset = std::min(r, std::max((int)(file.size()-LINES), 0)); row = 0; jump_line_end(); } int main(int argc, char* argv[]) { // Check valid filename and load if(argc <= 1) return 1; string filename = argv[1]; if(load(filename)) return 1; // Init initscr(); refresh(); print_file(); mode_type mode = NORMAL; // Main loop bool run = true; while(run) { move(row, col); char ch = getch(); switch(mode) { case NORMAL: print_line(row); switch(ch) { case 'h': case 'j': case 'k': case 'l': move_cursor(ch); break; case 'g': jump(get_number()); print_file(); break; case 'd': remove(row); print_file(row); break; case 'x': remove(row, col); print_line(row); break; case 'o': new_line(row); print_file(row); break; case 'q': run = false; break; case 'w': save(filename); break; case 'i': mode = INSERT; break; default: break; } break; case INSERT: switch(ch) { case ESC: mode = NORMAL; print_line(row); break; case BS: if(col>0) remove(row, --col); print_line(row); break; case ENTER: new_line(row+1, split_line(row, col)); print_file(row++); jump_line_end(); break; default: insert(row, col++, ch); print_line(row); break; } break; } refresh(); } // End endwin(); return 0; }