~kiwec/ke

cabcee5afb548eb5d49a20a9ce4d6048d63a69b1 — Wolf Clément 3 years ago 6389eb8
Add better indentation
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)) {