diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-01-12 22:10:20 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-01-12 22:10:20 +0100 |
commit | 66e0b88d27966adae568f4f2ddbf2ff10bb812d9 (patch) | |
tree | 106ff2d11f0f01fa6f69f3f3e1b25be02f6b13f5 | |
parent | 790a796de93c6f9868ce78f4aea9262461e2b8c9 (diff) |
Proper tab closing
-rw-r--r-- | buffer.cpp | 4 | ||||
-rw-r--r-- | config.cpp | 1 | ||||
-rw-r--r-- | manager.cpp | 112 | ||||
-rw-r--r-- | manager.h | 6 |
4 files changed, 98 insertions, 25 deletions
@@ -189,6 +189,8 @@ void Buffer::handleCommand(const Command &cmd){ } else { cursor.x=screen[sp.y].cells[sp.x].linex; } + } else if(cmd[0]=="cancel"){ + bel(); //nothing to cancel, apparently } else { THROW("Unknown command: "+cmd[0]); } @@ -401,7 +403,7 @@ Buffer::Screenpos Buffer::findCursorInScreen() const { } } -i64 numberWidth(i64 number){ +static i64 numberWidth(i64 number){ if(number<0)return 1+numberWidth(-number); if(number==0)return 1; return (i64)log10(number)+1; @@ -13,6 +13,7 @@ KeyInputMachine global_keyinput({ {{KEY_ALT+';'},{"display_prompt"}}, {{KEY_CTRL+'S'},{"save_file"}}, {{KEY_CTRL+'O'},{"open_prompt"}}, + {{KEY_CTRL+'W'},{"close_tab"}}, {{KEY_ESC},{"cancel"}}, diff --git a/manager.cpp b/manager.cpp index a3e9738..fdc7641 100644 --- a/manager.cpp +++ b/manager.cpp @@ -11,26 +11,45 @@ using namespace std; Manager::Manager() :activeIdx(-1){} +Manager::~Manager(){ + for(Buffer *buffer : buffers){ + delete buffer; + } +} + void Manager::receive(const Command &cmd){ if(cmd[0]=="open_file"){ - buffers.emplace_back(this); - buffers.back().receive(cmd); + buffers.push_back(new Buffer(this)); + buffers.back()->receive(cmd); activeIdx=buffers.size()-1; } else if(cmd[0]=="open_prompt"){ - Maybe<string> mfname=runPrompt("open: "); + Maybe<string> mfname=promptString("open: "); if(mfname.isNothing())return; - buffers.emplace_back(this); - buffers.back().receive({"open_file",mfname.fromJust()}); + buffers.push_back(new Buffer(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<string> mfname=runPrompt("save: "); + Maybe<string> mfname=promptString("save: "); if(mfname.isNothing())return; - buffers[activeIdx].filename=mfname.fromJust(); - buffers[activeIdx].receive({"save_file"}); + buffers[activeIdx]->filename=mfname.fromJust(); + buffers[activeIdx]->receive({"save_file"}); + } else if(cmd[0]=="close_tab"){ + if(activeIdx==-1){ + receive({"error","No buffers open!"}); + return; + } + if(buffers[activeIdx]->isDirty()){ + char choice=promptChar("Unsaved changes; discard? [y/N]","yn",'n'); + if(choice=='n')return; + } + delete buffers[activeIdx]; + buffers.erase(buffers.begin()+activeIdx); + if(activeIdx>0)activeIdx--; + if(buffers.size()==0)buffers.push_back(new Buffer(this)); } else if(cmd[0]=="error"||cmd[0]=="info"){ if(!have_screen)return; bool isError=cmd[0]=="error"; @@ -43,13 +62,23 @@ void Manager::receive(const Command &cmd){ tprintf("%s",cmd[1].data()); popcursor(); } else if(cmd[0]=="quit_app"){ + Size termsize=gettermsize(); + for(i64 i=0;i<(i64)buffers.size();i++){ + if(!buffers[i]->isDirty())continue; + activeIdx=i; + buffers[activeIdx]->show(0,1,termsize.w,termsize.h-2); + show(); + if(promptChar("Unsaved changes in this buffer; discard? [y/N]","yn",'n')=='n'){ + return; + } + } should_quit=true; } else if(cmd[0]=="display_prompt"){ - Maybe<string> mline=runPrompt(":"); + Maybe<string> mline=promptString(":"); if(mline.isJust())receive({"info",{mline.fromJust()}}); } else { if(activeIdx==-1)bel(); - else buffers[activeIdx].receive(cmd); + else buffers[activeIdx]->receive(cmd); } } @@ -59,7 +88,7 @@ void Manager::show(){ string bartext; i64 hilight_start=-1,hilight_len; for(size_t i=0;i<buffers.size();i++){ - string fname=buffers[i].filename.size()==0?"<New file>":buffers[i].filename; + string fname=buffers[i]->filename.size()==0?"<New file>":buffers[i]->filename; string tabtext=" "; for(size_t j=0;j<fname.size();j++){ if(fname[j]=='/'){ @@ -82,7 +111,7 @@ void Manager::show(){ //+1 because the first char was already appended tabtext+=fname.substr(nameidx+1,string::npos); - if(buffers[i].isDirty())tabtext+='*'; + if(buffers[i]->isDirty())tabtext+='*'; tabtext+=' '; if((i64)i==activeIdx){ @@ -152,14 +181,14 @@ int Manager::io(){ TermioRAII termioRAII(&have_screen); if(activeIdx==-1){ - buffers.emplace_back(this); + buffers.push_back(new Buffer(this)); activeIdx=0; } while(true){ Size termsize=gettermsize(); show(); - buffers[activeIdx].show(0,1,termsize.w,termsize.h-2); + buffers[activeIdx]->show(0,1,termsize.w,termsize.h-2); redraw(); int key=tgetkey(); @@ -180,17 +209,24 @@ int Manager::io(){ } +string truncatePromptString(const string &promptString,i64 width){ + if((i64)promptString.size()>width*3/4){ + string truncated(promptString.begin(),promptString.begin()+(width*3/4-3)); + return truncated+"..."; + } else { + return promptString; + } +} + //Returns entered text, or Nothing if cancelled -Maybe<string> Manager::runPrompt(const string &promptString){ +Maybe<string> Manager::promptString(const string &promptString){ Size termsize=gettermsize(); moveto(0,termsize.h-1); - 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()); - } + string truncated=truncatePromptString(promptString,termsize.w); + i64 leftX=truncated.size(); + Style promptStyle={9,9,false,false}; + setstyle(&promptStyle); + tprintf("%s",truncated.data()); global_keyinput.cancel(); @@ -211,8 +247,12 @@ Maybe<string> Manager::runPrompt(const string &promptString){ } else { Command cmd=ret.fromRight();; if(cmd[0]=="insert_newline"){ + termsize=gettermsize(); + fillrect(0,termsize.h-1,termsize.w,1,' '); return promptBuffer.getText(); } else if(cmd[0]=="cancel"){ + termsize=gettermsize(); + fillrect(0,termsize.h-1,termsize.w,1,' '); return {}; } else { promptBuffer.receive(cmd); @@ -220,3 +260,31 @@ Maybe<string> Manager::runPrompt(const string &promptString){ } } } + +char Manager::promptChar(const string &promptString,const string &options,char def){ + Size termsize=gettermsize(); + moveto(0,termsize.h-1); + string truncated=truncatePromptString(promptString,termsize.w); + Style promptStyle={9,9,false,false}; + setstyle(&promptStyle); + tprintf("%s",truncated.data()); + redraw(); + + global_keyinput.cancel(); + + while(true){ + int key=tgetkey(); + if(key==KEY_ESC)return def; + if(key<=0||key>=127){ + bel(); + continue; + } + key=tolower(key); + if(options.find((char)key)!=string::npos){ + termsize=gettermsize(); + fillrect(0,termsize.h-1,termsize.w,1,' '); + return (char)key; + } + bel(); + } +} @@ -11,16 +11,18 @@ using namespace std; class Manager{ - vector<Buffer> buffers; + vector<Buffer*> buffers; i64 activeIdx; bool should_quit=false; bool have_screen=false; - Maybe<string> runPrompt(const string &promptString); + Maybe<string> promptString(const string &promptString); + char promptChar(const string &promptString,const string &options,char def); public: Manager(); + ~Manager(); void receive(const Command &cmd); void show(); |