summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-01-12 22:10:20 +0100
committertomsmeding <tom.smeding@gmail.com>2017-01-12 22:10:20 +0100
commit66e0b88d27966adae568f4f2ddbf2ff10bb812d9 (patch)
tree106ff2d11f0f01fa6f69f3f3e1b25be02f6b13f5
parent790a796de93c6f9868ce78f4aea9262461e2b8c9 (diff)
Proper tab closing
-rw-r--r--buffer.cpp4
-rw-r--r--config.cpp1
-rw-r--r--manager.cpp112
-rw-r--r--manager.h6
4 files changed, 98 insertions, 25 deletions
diff --git a/buffer.cpp b/buffer.cpp
index b185b99..6fa7420 100644
--- a/buffer.cpp
+++ b/buffer.cpp
@@ -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;
diff --git a/config.cpp b/config.cpp
index f5b5987..77e3ed5 100644
--- a/config.cpp
+++ b/config.cpp
@@ -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();
+ }
+}
diff --git a/manager.h b/manager.h
index 55dfc96..80f9ef9 100644
--- a/manager.h
+++ b/manager.h
@@ -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();