summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-01-12 20:30:40 +0100
committertomsmeding <tom.smeding@gmail.com>2017-01-12 20:30:40 +0100
commit2275e9ab7cb53dbb40887028544e80dd39597402 (patch)
tree75c29e8a67c1bb4a90e348eb02b3972c1d4eb560
parent5c890325cb32602814804bb511c6399fe2395802 (diff)
Opening and saving
-rw-r--r--buffer.cpp23
-rw-r--r--config.cpp12
-rw-r--r--manager.cpp62
-rw-r--r--manager.h5
-rw-r--r--maybe.h35
-rw-r--r--textblob.cpp10
-rw-r--r--textblob.h5
7 files changed, 127 insertions, 25 deletions
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<string> 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<string> 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<string> 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<string> 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<string> 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 <typename T>
+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<T> Nothing(void){
+ return Maybe<T>();
+ }
+};
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<<line<<'\n';
+ count+=line.size()+1;
}
os<<flush;
+ return count;
}
void TextBlob::setText(const string &text){
diff --git a/textblob.h b/textblob.h
index 3246c8d..b1a4dc4 100644
--- a/textblob.h
+++ b/textblob.h
@@ -32,8 +32,9 @@ public:
void clear();
- void read(istream &is);
- void write(ostream &os) const;
+ //Return how many characters were read/written.
+ i64 read(istream &is);
+ i64 write(ostream &os) const;
void setText(const string &text);
string fullText() const;