M src/Buffer.cpp => src/Buffer.cpp +36 -20
@@ 1,3 1,4 @@
+#include <sstream>
#include <termbox.h>
#include "Buffer.hpp"
#include "Editor.hpp"
@@ 182,13 183,13 @@ bool Buffer::handle_key(tb_event *ev) {
}
break;
case TB_KEY_PGDN:
- for(int i = 0; i < 0.8 * tb_height(); i++) {
+ for(int i = 0; i < 0.8 * m_canvas.height(); i++) {
if(!move_down())
break;
}
break;
case TB_KEY_PGUP:
- for(int i = 0; i < 0.8 * tb_height(); i++) {
+ for(int i = 0; i < 0.8 * m_canvas.height(); i++) {
if(!move_up())
break;
}
@@ 199,6 200,9 @@ bool Buffer::handle_key(tb_event *ev) {
case TB_KEY_TAB:
insert(L'\t', true);
break;
+ case TB_KEY_SPACE:
+ insert(L' ', true);
+ break;
case TB_KEY_CTRL_Z:
m_history.undo(*this);
break;
@@ 209,17 213,13 @@ bool Buffer::handle_key(tb_event *ev) {
handled = false;
}
+ if(!handled && ev->ch) {
+ insert(ev->ch, true);
+ handled = true;
+ }
+
if(!handled) {
handled = Editable::handle_key(ev);
- std::wstring key = L"";
- if(ev->ch)
- key.insert(0, 1, ev->ch);
- else if(ev->key == TB_KEY_SPACE)
- key = L" ";
-
- if(!key.empty()) {
- m_history.log_event(new WriteEvent(key, current_line_nb, get_x()));
- }
}
if(handled) {
@@ 230,9 230,12 @@ bool Buffer::handle_key(tb_event *ev) {
}
void Buffer::insert(wchar_t c, bool log_events) {
+ force = L"";
+
if(c == L'\n') {
bool at_end = is_at_EOL();
auto x = get_x();
+ int next_indent = current_line->get_next_indentation();
auto& old_text = current_line->text;
add_line();
move_down();
@@ 252,19 255,32 @@ void Buffer::insert(wchar_t c, bool log_events) {
// Make sure we have a correct start_commented on the new line
Syntax::MarkStartCommented(current_line);
- // Keep previous line indentation
- std::wstring indentation = L"";
- for(uint i = 0; i < old_text.length(); i++) {
- if(old_text[i] == L' ' || old_text[i] == L'\t') {
- indentation += old_text[i];
- } else {
- break;
+ // Auto-indent
+ if(next_indent > 0) {
+ std::wstring indentation = L"";
+ for(int i = 0; i < next_indent; i++) {
+ indentation += L'\t';
}
- }
- if(indentation.length() > 0) {
insert(indentation, log_events);
}
} else {
+ if(!current_line->is_first()) {
+ auto x = get_x();
+ auto normal_indent = current_line->prev()->get_next_indentation();
+ auto current_indent = current_line->get_current_indentation();
+
+ std::wostringstream tmp;
+ tmp << "current " << current_indent << " - normal " << normal_indent << " - x " << x << " - c " << c;
+ force = tmp.str();
+
+ // Deindent
+ if(c == L'}' && x > 0 && current_indent == normal_indent) {
+ if(current_line->text[x - 1] == L'\t') {
+ erase_backwards(log_events);
+ }
+ }
+ }
+
Editable::insert(c);
if(log_events) {
M src/Buffer.hpp => src/Buffer.hpp +2 -0
@@ 25,6 25,8 @@ public:
goto_end();
}
+ std::wstring force = L"";
+
void draw(Canvas canvas);
/// Handle keypresses
M src/Editor.cpp => src/Editor.cpp +11 -9
@@ 14,16 14,18 @@ void Editor::draw() {
tb_clear();
// Draw buffer (file text)
- m_buf->draw(Canvas{ 0, 0, tb_width(), tb_height() - status.height() });
+ m_buf->draw(Canvas{ 0, 0, tb_width(), tb_height() - m_status.height() });
tb_set_cursor(Gutter::width(*m_buf) + m_buf->get_visible_x(), m_buf->get_visible_y());
- status.draw(*m_buf);
+ m_status.draw(*m_buf);
+
+ tb_present();
}
bool Editor::handle_key(tb_event* ev) {
switch(ev->key) {
case TB_KEY_CTRL_G:
- 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 : ", [&buf = *m_buf](auto answer) {
int line = -1;
try {
@@ 38,7 40,7 @@ bool Editor::handle_key(tb_event* ev) {
});
return true;
case TB_KEY_CTRL_F:
- status.prompt = std::make_unique<Prompt>(L"Find : ", [&buf = *m_buf](auto answer) {
+ m_status.prompt = std::make_unique<Prompt>(L"Find : ", [&buf = *m_buf](auto answer) {
if(answer == L"") return;
auto result = buf.search(answer);
auto old_x = buf.get_current_line_nb();
@@ 52,7 54,7 @@ bool Editor::handle_key(tb_event* ev) {
shutdown();
return true;
case TB_KEY_CTRL_O:
- status.prompt = std::make_unique<Prompt>(L"Open file : ", [this](auto answer) {
+ m_status.prompt = std::make_unique<Prompt>(L"Open file : ", [this](auto answer) {
if(answer == L"") return; // TODO show error
open(answer);
});
@@ 60,20 62,20 @@ bool Editor::handle_key(tb_event* ev) {
case TB_KEY_CTRL_S:
// Ctrl-Alt-S
if(ev->mod == TB_MOD_ALT || m_buf->filename == L"") {
- status.prompt = std::make_unique<Prompt>(L"Save as : ", [&buf = *m_buf](auto answer) {
+ m_status.prompt = std::make_unique<Prompt>(L"Save as : ", [&buf = *m_buf](auto answer) {
if(answer == L"") return; // TODO show error
buf.filename = answer;
buf.save();
});
- status.prompt->insert(m_buf->filename);
+ m_status.prompt->insert(m_buf->filename);
} else {
m_buf->save();
}
return true;
}
- if(status.prompt->is_prompting()) {
- if(status.prompt->handle_key(ev)) {
+ if(m_status.prompt->is_prompting()) {
+ if(m_status.prompt->handle_key(ev)) {
return true;
}
}
M src/Editor.hpp => src/Editor.hpp +1 -2
@@ 6,10 6,9 @@
class Editor : public InputHandler {
private:
std::shared_ptr<Buffer> m_buf;
+ StatusBar m_status;
public:
- StatusBar status;
-
void draw();
/// Handle keypresses
M src/Line.cpp => src/Line.cpp +14 -0
@@ 46,6 46,20 @@ void Line::set_next(Line* line) {
m_next = line;
}
+int Line::get_current_indentation() {
+ int indent = 0;
+ while(indent < (int)text.length() && text[indent] == L'\t') {
+ indent++;
+ }
+ return indent;
+}
+
+int Line::get_next_indentation() {
+ if(text.length() == 0) return 0;
+ if(text[text.length() - 1] == '{') return get_current_indentation() + 1;
+ return get_current_indentation();
+}
+
bool Line::is_first() {
return m_prev == nullptr;
}
M src/Line.hpp => src/Line.hpp +6 -0
@@ 22,6 22,9 @@ public:
/// Add a line or a set of lines after itself
void set_next(Line* line);
+
+ int get_current_indentation();
+ int get_next_indentation();
bool is_first();
bool is_last();
@@ 34,6 37,9 @@ public:
/// Print on screen with syntax highlighting, from start and up
void printFrom(uint start, uint x, uint y, uint bg = 0);
+ /// Returns the number of lines the line would take in a specific buffer
uint height(Buffer& buf) const;
+
+ /// Returns max width of the line, counting tabs as 4 characters
uint width() const;
};
M src/StatusBar.cpp => src/StatusBar.cpp +2 -4
@@ 12,6 12,8 @@ void StatusBar::draw(Buffer& buf) {
// Filename
left << L" " << buf.filename;
+ left << L" " << buf.force;
+
// Modified
if(buf.modified) {
left << L" [modified]";
@@ 52,7 54,3 @@ int StatusBar::height() {
// Could be higher in the future
return 1;
}
-
-int StatusBar::width() {
- return tb_width();
-}
M src/StatusBar.hpp => src/StatusBar.hpp +0 -1
@@ 18,5 18,4 @@ public:
void draw(Buffer& buf);
int height();
- int width();
};
M src/main.cpp => src/main.cpp +0 -1
@@ 30,7 30,6 @@ int main(int argc, const char** argv) {
editor.open(argc == 2 ? converter.from_bytes(argv[1]) : L"");
for(;;) {
editor.draw();
- tb_present();
tb_event ev;
switch(tb_poll_event(&ev)) {