M src/Editor.cc => src/Editor.cc +32 -17
@@ 4,7 4,7 @@
#include "Editor.h"
#include "Prompt.h"
#include "Gutter.h"
-#include "StatusBar.h"
+#include "Status.h"
void Editor::draw() {
tb_clear();
@@ 19,28 19,35 @@ void Editor::draw() {
}
bool Editor::handle_key(tb_event* ev) {
+ m_status.handle_key(ev);
+
switch(ev->key) {
case TB_KEY_CTRL_G:
- m_status.prompt = std::make_unique<Prompt>(L"Go to line : ", [&buf = *m_buf](auto answer) {
+ m_status.prompt = std::make_unique<Prompt>(L"Go to line : ", [this](auto answer) {
int line = -1;
-
try {
line = std::stoi(answer);
+ if(line < 0) throw;
} catch(std::exception& e) {
- // TODO show error
+ m_status.set_msg(L"Invalid line number", StatusType::ERROR);
+ return;
}
- if(line > 0) {
- buf.move_to(line);
- }
+ m_buf->move_to(line);
});
return true;
case TB_KEY_CTRL_F:
- m_status.prompt = std::make_unique<Prompt>(L"Find : ", [&buf = *m_buf](auto answer) {
- if(answer == L"") return;
- auto result = buf.m_text.search(answer);
- buf.move_to(result.first, result.second);
- // TODO show no matches
+ m_status.prompt = std::make_unique<Prompt>(L"Find : ", [this](auto answer) {
+ // TODO highlight matches
+ if(*answer == L'\0') {
+ // TODO jump to next match instead
+ m_status.set_msg(L"No text given, not searching.", StatusType::INFO);
+ return;
+ }
+
+ auto result = m_buf->m_text.search(answer);
+ m_buf->move_to(result.first, result.second);
+ // TODO show more information (no matches / match X of X)
});
return true;
case TB_KEY_CTRL_Q:
@@ 54,19 61,27 @@ bool Editor::handle_key(tb_event* ev) {
return true;
case TB_KEY_CTRL_O:
m_status.prompt = std::make_unique<Prompt>(L"Open file : ", [this](auto answer) {
- if(answer == L"") return; // TODO show error
+ if(*answer == L'\0') {
+ m_status.set_msg(L"No filename given, not opening.", StatusType::INFO);
+ return;
+ }
auto str = Convert::from_wide_string(answer);
+ // TODO check if file can be opened
open(str.get());
});
return true;
case TB_KEY_CTRL_S:
// Ctrl-Alt-S
if(ev->mod == TB_MOD_ALT || m_buf->filename == "") {
- m_status.prompt = std::make_unique<Prompt>(L"Save as : ", [&buf = *m_buf](auto answer) {
- if(answer == L"") return; // TODO show error
+ m_status.prompt = std::make_unique<Prompt>(L"Save as : ", [this](auto answer) {
+ if(*answer == L'\0') {
+ m_status.set_msg(L"No filename given, not saving.", StatusType::ERROR);
+ return;
+ }
auto str = Convert::from_wide_string(answer);
- buf.filename = str.get();
- buf.save();
+ m_buf->filename = str.get();
+ // TODO if file was saved successfully
+ m_buf->save();
});
auto wstr = Convert::to_wide_string(m_buf->filename.c_str());
M src/Editor.h => src/Editor.h +2 -2
@@ 1,13 1,13 @@
#pragma once
#include <memory>
#include "Buffer.h"
-#include "StatusBar.h"
+#include "Status.h"
// TODO remove shared_ptr
class Editor : public InputHandler {
private:
std::shared_ptr<Buffer> m_buf;
- StatusBar m_status;
+ Status m_status;
public:
void draw();
R src/StatusBar.cc => src/Status.cc +52 -5
@@ 1,13 1,16 @@
-#include "StatusBar.h"
+#include "Status.h"
#include "Buffer.h"
#include "Conversion.h"
#include "Editor.h"
#include "File.h"
#include "Line.h"
#include <sstream>
+#include <stdlib.h>
#include <termbox.h>
-void StatusBar::draw(Buffer& buf) {
+void Status::draw(Buffer& buf) {
+ int16_t fg = 232, bg = 220;
+
// Text aligned to the left
std::wostringstream left;
// Filename
@@ 34,7 37,7 @@ void StatusBar::draw(Buffer& buf) {
right << L"/" << buf.m_text.get_nb_lines();
right << L" ";
auto right_str = right.str();
- auto rwidth = right_str.size();
+ int rwidth = right_str.size();
// Yellow background
for(int i = 0; i < tb_width(); i++) {
@@ 47,7 50,36 @@ void StatusBar::draw(Buffer& buf) {
// Text
Canvas::print(right_str.c_str(), tb_width() - rwidth, tb_height() - 1, fg, bg);
- // Prompt
+ // Print message if there is one
+ if(_msg != nullptr) {
+ // Set message colors
+ switch(_type) {
+ case StatusType::DEFAULT:
+ case StatusType::INFO:
+ break;
+ case StatusType::ERROR:
+ bg = 9;
+ fg = 15;
+ break;
+ case StatusType::SUCCESS:
+ bg = 2;
+ fg = 15;
+ break;
+/*
+ case StatusType::PROMPT:
+ bg = 0;
+ fg = 234;
+ break;
+*/
+ }
+
+ // Draw the message
+ for(int i = 0; i < tb_width() - rwidth; i++) {
+ tb_change_cell(i, tb_height() - 1, ' ', fg, bg);
+ }
+ Canvas::print(_msg, 1, tb_height() - 1, fg, bg);
+ }
+
if(prompt != nullptr) {
if(prompt->is_prompting()) {
prompt->draw(rwidth);
@@ 57,7 89,22 @@ void StatusBar::draw(Buffer& buf) {
}
}
-int StatusBar::height() {
+int Status::height() {
// Could be higher in the future
return 1;
}
+
+void Status::handle_key(tb_event* ev) {
+ if(_msg == nullptr) return;
+ // if(_type == StatusType::PROMPT) return;
+
+ // Remove currently displayed msg
+ free(_msg);
+ _msg = nullptr;
+}
+
+void Status::set_msg(const wchar_t* msg, StatusType type) {
+ if(_msg != nullptr) free(_msg);
+ _msg = wcsdup(msg);
+ _type = type;
+}
A src/Status.h => src/Status.h +34 -0
@@ 0,0 1,34 @@
+#pragma once
+#include <memory>
+#include <termbox.h>
+#include "Prompt.h"
+
+class Buffer;
+
+enum class StatusType {
+ DEFAULT,
+ INFO,
+ ERROR,
+ SUCCESS,
+// PROMPT,
+};
+
+class Status {
+private:
+ wchar_t* _msg = nullptr;
+ StatusType _type;
+
+public:
+ std::unique_ptr<Prompt> prompt = nullptr;
+
+ ~Status() {
+ if(_msg != nullptr) {
+ free(_msg);
+ }
+ }
+
+ void draw(Buffer& buf);
+ int height();
+ void handle_key(tb_event* ev);
+ void set_msg(const wchar_t* msg, StatusType type);
+};
D src/StatusBar.h => src/StatusBar.h +0 -17
@@ 1,17 0,0 @@
-#pragma once
-#include <memory>
-#include "Prompt.h"
-
-class Buffer;
-
-class StatusBar {
-private:
- const int16_t fg = 232;
- const int16_t bg = 220;
-
-public:
- std::unique_ptr<Prompt> prompt = nullptr;
-
- void draw(Buffer& buf);
- int height();
-};