From 2275e9ab7cb53dbb40887028544e80dd39597402 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Thu, 12 Jan 2017 20:30:40 +0100 Subject: Opening and saving --- buffer.cpp | 23 ++++++++++++++++++++-- config.cpp | 12 ++++++++++-- manager.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++---------------- manager.h | 5 ++++- maybe.h | 35 ++++++++++++++++++++++++++++++++++ textblob.cpp | 10 ++++++++-- textblob.h | 5 +++-- 7 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 maybe.h diff --git a/buffer.cpp b/buffer.cpp index e79b4fb..1366862 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -30,10 +30,23 @@ void Buffer::handleCommand(const Command &cmd){ manager->receive({"error","Cannot open file '"+fname+"'"}); return; } - tb.read(file); + i64 nread=tb.read(file); cursor.line=0; cursor.x=0; screen.clear(); + manager->receive({"info","Opened, read "+to_string(nread)+" characters"}); + } else if(cmd[0]=="save_file"){ + if(filename.size()==0){ + manager->receive({"save_prompt"}); + return; + } + ofstream file(filename); + if(!file){ + manager->receive({"error","Cannot open file '"+filename+"' for writing"}); + return; + } + i64 nwritten=tb.write(file); + manager->receive({"info","Saved, written "+to_string(nwritten)+" characters"}); } else if(cmd[0]=="insert_char"){ char c=cmd[1][0]; assert(c!='\n'); @@ -455,5 +468,11 @@ void Buffer::show(i64 atx,i64 aty,i64 width,i64 height){ } string Buffer::getText() const { - return tb.fullText(); + if(singleLineMode){ + string line=tb.fullText(); + line.pop_back(); + return line; + } else { + return tb.fullText(); + } } diff --git a/config.cpp b/config.cpp index 07db619..f5b5987 100644 --- a/config.cpp +++ b/config.cpp @@ -11,14 +11,22 @@ using namespace std; KeyInputMachine global_keyinput({ {{KEY_CTRL+'Q'},{"quit_app"}}, {{KEY_ALT+';'},{"display_prompt"}}, - {{KEY_BACKSPACE},{"delete_backward"}}, - {{KEY_DELETE},{"delete_forward"}}, + {{KEY_CTRL+'S'},{"save_file"}}, + {{KEY_CTRL+'O'},{"open_prompt"}}, + + {{KEY_ESC},{"cancel"}}, + {{'\n'},{"insert_newline"}}, {{'\t'},{"insert_char","\t"}}, + + {{KEY_BACKSPACE},{"delete_backward"}}, + {{KEY_DELETE},{"delete_forward"}}, {{KEY_RIGHT},{"move_forward"}}, {{KEY_LEFT},{"move_backward"}}, {{KEY_DOWN},{"move_downward"}}, {{KEY_UP},{"move_upward"}}, + {{KEY_PAGEDOWN},{"move_pagedown"}}, + {{KEY_PAGEUP},{"move_pageup"}}, }); class Init{public: Init(){ diff --git a/manager.cpp b/manager.cpp index 059a33f..af8844c 100644 --- a/manager.cpp +++ b/manager.cpp @@ -15,20 +15,38 @@ void Manager::receive(const Command &cmd){ if(cmd[0]=="open_file"){ buffers.emplace_back(this); buffers.back().receive(cmd); - if(activeIdx==-1)activeIdx=buffers.size()-1; - } else if(cmd[0]=="error"){ + activeIdx=buffers.size()-1; + } else if(cmd[0]=="open_prompt"){ + Maybe mfname=runPrompt("open: "); + if(mfname.isNothing())return; + buffers.emplace_back(this); + buffers.back().receive({"open_file",mfname.fromJust()}); + activeIdx=buffers.size()-1; + } else if(cmd[0]=="save_prompt"){ + if(activeIdx==-1){ + receive({"error","No buffers open!"}); + return; + } + Maybe mfname=runPrompt("save: "); + if(mfname.isNothing())return; + buffers[activeIdx].filename=mfname.fromJust(); + buffers[activeIdx].receive({"save_file"}); + } else if(cmd[0]=="error"||cmd[0]=="info"){ + if(!have_screen)return; + bool isError=cmd[0]=="error"; pushcursor(); Size termsize=gettermsize(); - Style errorStyle={1,9,true,false}; + Style style={isError?1:9,9,isError,false}; fillrect(0,termsize.h-1,termsize.w,1,' '); moveto(0,termsize.h-1); - setstyle(&errorStyle); + setstyle(&style); tprintf("%s",cmd[1].data()); popcursor(); } else if(cmd[0]=="quit_app"){ should_quit=true; } else if(cmd[0]=="display_prompt"){ - runPrompt(); + Maybe mline=runPrompt(":"); + if(mline.isJust())receive({"info",{mline.fromJust()}}); } else { if(activeIdx==-1)bel(); else buffers[activeIdx].receive(cmd); @@ -94,6 +112,7 @@ void Manager::show(){ pushcursor(); moveto(0,0); setstyle(&backStyle); + fillrect(0,0,termsize.w,1,' '); if(print_start>=hilight_start+hilight_len||print_start+termsize.w<=hilight_start){ string text=bartext.substr(print_start,termsize.w); tprintf("%s",text.data()); @@ -113,19 +132,23 @@ void Manager::show(){ } class TermioRAII{ + bool *variable; + public: - TermioRAII(){ + TermioRAII(bool *variable):variable(variable){ initscreen(); initkeyboard(true); + *variable=true; } ~TermioRAII(){ + *variable=false; endkeyboard(); endscreen(); } }; int Manager::io(){ - TermioRAII termioRAII; + TermioRAII termioRAII(&have_screen); if(activeIdx==-1){ buffers.emplace_back(this); @@ -156,10 +179,17 @@ int Manager::io(){ } -void Manager::runPrompt(){ +//Returns entered text, or Nothing if cancelled +Maybe Manager::runPrompt(const string &promptString){ Size termsize=gettermsize(); moveto(0,termsize.h-1); - tputc(':'); + i64 leftX=promptString.size(); + if((i64)promptString.size()>termsize.w*3/4){ + string truncated(promptString.begin(),promptString.begin()+(termsize.w*3/4-3)); + tprintf("%s...",truncated.data()); + } else { + tprintf("%s",promptString.data()); + } global_keyinput.cancel(); @@ -167,7 +197,7 @@ void Manager::runPrompt(){ Buffer promptBuffer(this,true); while(true){ termsize=gettermsize(); - promptBuffer.show(1,termsize.h-1,termsize.w-1,1); + promptBuffer.show(leftX,termsize.h-1,termsize.w-leftX,1); redraw(); int key=tgetkey(); @@ -178,14 +208,14 @@ void Manager::runPrompt(){ bel(); } } else { - if(ret.fromRight()[0]=="insert_newline"){ - inputLine=promptBuffer.getText(); - break; + Command cmd=ret.fromRight();; + if(cmd[0]=="insert_newline"){ + return promptBuffer.getText(); + } else if(cmd[0]=="cancel"){ + return {}; } else { - promptBuffer.receive(ret.fromRight()); + promptBuffer.receive(cmd); } } } - - receive({"error",inputLine}); } diff --git a/manager.h b/manager.h index 72fd2d3..55dfc96 100644 --- a/manager.h +++ b/manager.h @@ -5,6 +5,7 @@ #include "buffer.h" #include "command.h" #include "global.h" +#include "maybe.h" using namespace std; @@ -14,7 +15,9 @@ class Manager{ i64 activeIdx; bool should_quit=false; - void runPrompt(); + bool have_screen=false; + + Maybe runPrompt(const string &promptString); public: Manager(); diff --git a/maybe.h b/maybe.h new file mode 100644 index 0000000..95a26b8 --- /dev/null +++ b/maybe.h @@ -0,0 +1,35 @@ +#pragma once + +template +class Maybe{ + T *value; + +public: + Maybe(void):value(NULL){} // 'Nothing' constructor + Maybe(T v):value(new T(move(v))){} + + ~Maybe(void){ + if(value)delete value; + } + + T fromJust(void) const { + return *value; + } + + T fromMaybe(T &def) const { + if(value)return *value; + else return def; + } + + bool isJust(void) const { + return (bool)value; + } + + bool isNothing(void) const { + return !value; + } + + static Maybe Nothing(void){ + return Maybe(); + } +}; diff --git a/textblob.cpp b/textblob.cpp index 65fa1b0..b66f8fa 100644 --- a/textblob.cpp +++ b/textblob.cpp @@ -50,19 +50,25 @@ void TextBlob::clear(){ lines.clear(); } -void TextBlob::read(istream &is){ +i64 TextBlob::read(istream &is){ lines.clear(); string ln; + i64 count=0; while(getline(is,ln)){ + count+=ln.size()+1; lines.push_back(move(ln)); } + return count; } -void TextBlob::write(ostream &os) const { +i64 TextBlob::write(ostream &os) const { + i64 count=0; for(const string &line : lines){ os<