From 92e2417787e5f02d0513bb93e52d60aef7ab1c73 Mon Sep 17 00:00:00 2001 From: eidheim Date: Wed, 24 Jun 2015 11:14:15 +0200 Subject: [PATCH] Moved basic indentation to Source::View, Clang specific indentation still in Source::ClangView. Some fixes, improved indentation for non-clang files, also added tab_char to Source::Config. --- juci/source.cc | 80 ++++++++++++++++++++++++++++++++------------------ juci/source.h | 1 + 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/juci/source.cc b/juci/source.cc index b7d794d..1993db2 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -50,9 +50,33 @@ string Source::View::get_line_before_insert() { return line; } +//Basic indentation bool Source::View::on_key_press(GdkEventKey* key) { + const std::regex spaces_regex(std::string("^(")+config.tab_char+"*).*$"); + //Indent as in next or previous line + if(key->keyval==GDK_KEY_Return && key->state==0) { + int line_nr=get_source_buffer()->get_insert()->get_iter().get_line(); + string line(get_line_before_insert()); + std::smatch sm; + if(std::regex_match(line, sm, spaces_regex)) { + if((line_nr+1)get_line_count()) { + string next_line=get_line(line_nr+1); + std::smatch sm2; + if(std::regex_match(next_line, sm2, spaces_regex)) { + if(sm2[1].str().size()>sm[1].str().size()) { + get_source_buffer()->insert_at_cursor("\n"+sm2[1].str()); + scroll_to(get_source_buffer()->get_insert()); + return true; + } + } + } + get_source_buffer()->insert_at_cursor("\n"+sm[1].str()); + scroll_to(get_source_buffer()->get_insert()); + return true; + } + } //Indent right when clicking tab, no matter where in the line the cursor is. Also works on selected text. - if(key->keyval==GDK_KEY_Tab && key->state==0) { + else if(key->keyval==GDK_KEY_Tab && key->state==0) { Gtk::TextIter selection_start, selection_end; get_source_buffer()->get_selection_bounds(selection_start, selection_end); int line_start=selection_start.get_line(); @@ -86,6 +110,22 @@ bool Source::View::on_key_press(GdkEventKey* key) { } return true; } + //"Smart" backspace key + else if(key->keyval==GDK_KEY_BackSpace) { + Gtk::TextIter insert_it=get_source_buffer()->get_insert()->get_iter(); + int line_nr=insert_it.get_line(); + if(line_nr>0) { + string line=get_line(line_nr); + string previous_line=get_line(line_nr-1); + smatch sm; + if(std::regex_match(previous_line, sm, spaces_regex)) { + if(line==sm[1] || line==(std::string(sm[1])+config.tab) || (line+config.tab==sm[1])) { + Gtk::TextIter line_it = get_source_buffer()->get_iter_at_line(line_nr); + get_source_buffer()->erase(line_it, insert_it); + } + } + } + } return false; } @@ -386,15 +426,15 @@ bool Source::ClangView::on_key_release(GdkEventKey* key) { return true; } -//TODO: replace indentation methods with a better implementation or -//maybe use libclang +//Clang indentation +//TODO: replace indentation methods with a better implementation or maybe use libclang bool Source::ClangView::on_key_press(GdkEventKey* key) { - const std::regex bracket_regex("^( *).*\\{ *$"); - const std::regex no_bracket_statement_regex("^( *)(if|for|else if|catch|while) *\\(.*[^;}] *$"); - const std::regex no_bracket_no_para_statement_regex("^( *)(else|try|do) *$"); - const std::regex spaces_regex("^( *).*$"); + const std::regex bracket_regex(std::string("^(")+config.tab_char+"*).*\\{ *$"); + const std::regex no_bracket_statement_regex(std::string("^(")+config.tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); + const std::regex no_bracket_no_para_statement_regex(std::string("^(")+config.tab_char+"*)(else|try|do) *$"); + const std::regex spaces_regex(std::string("^(")+config.tab_char+"*).*$"); - //Indent as in previous line, and indent right after if/else/etc + //Indent depending on if/else/etc and brackets if(key->keyval==GDK_KEY_Return && key->state==0) { string line(get_line_before_insert()); std::smatch sm; @@ -417,14 +457,17 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) { insert_it--; scroll_to(get_source_buffer()->get_insert()); get_source_buffer()->place_cursor(insert_it); + return true; } else if(std::regex_match(line, sm, no_bracket_statement_regex)) { get_source_buffer()->insert_at_cursor("\n"+sm[1].str()+config.tab); scroll_to(get_source_buffer()->get_insert()); + return true; } else if(std::regex_match(line, sm, no_bracket_no_para_statement_regex)) { get_source_buffer()->insert_at_cursor("\n"+sm[1].str()+config.tab); scroll_to(get_source_buffer()->get_insert()); + return true; } else if(std::regex_match(line, sm, spaces_regex)) { std::smatch sm2; @@ -444,17 +487,14 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) { } } } - get_source_buffer()->insert_at_cursor("\n"+sm[1].str()); - scroll_to(get_source_buffer()->get_insert()); } - return true; } //Indent left when writing } on a new line else if(key->keyval==GDK_KEY_braceright) { string line=get_line_before_insert(); if(line.size()>=config.tab_size) { for(auto c: line) { - if(c!=' ') + if(c!=config.tab_char) return false; } Gtk::TextIter insert_it = get_source_buffer()->get_insert()->get_iter(); @@ -467,22 +507,6 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) { } return false; } - //"Smart" backspace key - else if(key->keyval==GDK_KEY_BackSpace) { - Gtk::TextIter insert_it=get_source_buffer()->get_insert()->get_iter(); - int line_nr=insert_it.get_line(); - if(line_nr>0) { - string line=get_line(line_nr); - string previous_line=get_line(line_nr-1); - smatch sm; - if(std::regex_match(previous_line, sm, spaces_regex)) { - if(line==sm[1]) { - Gtk::TextIter line_it = get_source_buffer()->get_iter_at_line(line_nr); - get_source_buffer()->erase(line_it, insert_it); - } - } - } - } return Source::View::on_key_press(key); } diff --git a/juci/source.h b/juci/source.h index e779c35..52d754f 100644 --- a/juci/source.h +++ b/juci/source.h @@ -22,6 +22,7 @@ namespace Source { unsigned tab_size; bool show_line_numbers, highlight_current_line; std::string tab, background, font; + char tab_char=' '; std::vector extensions; std::unordered_map tags, types; }; // class Config