Browse Source

Improved JavaScript and JSON indentation

merge-requests/389/head
eidheim 8 years ago
parent
commit
ead8b42c17
  1. 101
      src/source.cc
  2. 2
      src/source.h

101
src/source.cc

@ -1270,8 +1270,11 @@ Gtk::TextIter Source::View::find_start_of_sentence(Gtk::TextIter iter) {
square_count--; square_count--;
else if(*iter=='{' && is_code_iter(iter)) else if(*iter=='{' && is_code_iter(iter))
curly_count++; curly_count++;
else if(*iter=='}' && is_code_iter(iter)) else if(*iter=='}' && is_code_iter(iter)) {
curly_count--; curly_count--;
if(iter.starts_line())
break;
}
if(curly_count>0) if(curly_count>0)
break; break;
@ -1334,18 +1337,18 @@ bool Source::View::find_open_curly_bracket_backward(Gtk::TextIter iter, Gtk::Tex
return false; return false;
} }
bool Source::View::find_close_curly_bracket_forward(Gtk::TextIter iter, Gtk::TextIter &found_iter) { bool Source::View::find_close_symbol_forward(Gtk::TextIter iter, Gtk::TextIter &found_iter, unsigned int positive_char, unsigned int negative_char) {
long count=0; long count=0;
do { do {
if(*iter=='}' && is_code_iter(iter)) { if(*iter==negative_char && is_code_iter(iter)) {
if(count==0) { if(count==0) {
found_iter=iter; found_iter=iter;
return true; return true;
} }
count--; count--;
} }
else if(*iter=='{' && is_code_iter(iter)) else if(*iter==positive_char && is_code_iter(iter))
count++; count++;
} while(iter.forward_char()); } while(iter.forward_char());
return false; return false;
@ -1875,7 +1878,7 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
return false; return false;
} }
// get iter for if expressions below, which is moved backwards past any comment // Get iter for if expressions below, which is moved backwards past any comment
auto get_condition_iter=[this](const Gtk::TextIter &iter) { auto get_condition_iter=[this](const Gtk::TextIter &iter) {
auto condition_iter=iter; auto condition_iter=iter;
condition_iter.backward_char(); condition_iter.backward_char();
@ -1892,7 +1895,7 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
return condition_iter; return condition_iter;
}; };
//Indent depending on if/else/etc and brackets // Indent depending on if/else/etc and brackets
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) { if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) {
cleanup_whitespace_characters_on_return(iter); cleanup_whitespace_characters_on_return(iter);
iter=get_buffer()->get_insert()->get_iter(); iter=get_buffer()->get_insert()->get_iter();
@ -1930,14 +1933,14 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
Gtk::TextIter found_iter; Gtk::TextIter found_iter;
// Check if an '}' is needed // Check if an '}' is needed
bool has_right_curly_bracket=false; bool has_right_curly_bracket=false;
bool found_right_bracket=find_close_curly_bracket_forward(iter, found_iter); bool found_right_bracket=find_close_symbol_forward(iter, found_iter, '{', '}');
if(found_right_bracket) { if(found_right_bracket) {
auto tabs_end_iter=get_tabs_end_iter(found_iter); auto tabs_end_iter=get_tabs_end_iter(found_iter);
auto line_tabs=get_line_before(tabs_end_iter); auto line_tabs=get_line_before(tabs_end_iter);
if(tabs.size()==line_tabs.size()) if(tabs.size()==line_tabs.size())
has_right_curly_bracket=true; has_right_curly_bracket=true;
} }
// special case for functions and classes with no indentation after: namespace { // Special case for functions and classes with no indentation after: namespace {
if(tabs.empty() && has_right_curly_bracket) if(tabs.empty() && has_right_curly_bracket)
has_right_curly_bracket=symbol_count(iter, '{', '}')!=1; has_right_curly_bracket=symbol_count(iter, '{', '}')!=1;
@ -2016,12 +2019,76 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
return true; return true;
} }
} }
// Special indentation of [ and ( for JavaScript and JSON
if(language && (language->get_id()=="js" || language->get_id()=="json")) {
unsigned int open_symbol=0, close_symbol=0;
if(*condition_iter=='[') {
open_symbol='[';
close_symbol=']';
}
else if(*condition_iter=='(') {
open_symbol='(';
close_symbol=')';
}
if(open_symbol!=0 && is_code_iter(condition_iter)) {
Gtk::TextIter found_iter;
// Check if an ']' is needed
bool has_right_bracket=false;
bool found_right_bracket=find_close_symbol_forward(iter, found_iter, open_symbol, close_symbol);
if(found_right_bracket) {
auto tabs_end_iter=get_tabs_end_iter(found_iter);
auto line_tabs=get_line_before(tabs_end_iter);
if(tabs.size()==line_tabs.size())
has_right_bracket=true;
}
if(*get_buffer()->get_insert()->get_iter()==close_symbol) {
get_buffer()->insert_at_cursor("\n"+tabs+tab+"\n"+tabs);
auto insert_it = get_buffer()->get_insert()->get_iter();
if(insert_it.backward_chars(tabs.size()+1)) {
scroll_to(get_buffer()->get_insert());
get_buffer()->place_cursor(insert_it);
}
return true;
}
else if(!has_right_bracket) {
//Insert new lines with bracket end
get_buffer()->insert_at_cursor("\n"+tabs+tab+"\n"+tabs+static_cast<char>(close_symbol));
auto insert_it = get_buffer()->get_insert()->get_iter();
if(insert_it.backward_chars(tabs.size()+2)) {
scroll_to(get_buffer()->get_insert());
get_buffer()->place_cursor(insert_it);
}
return true;
}
else {
get_buffer()->insert_at_cursor("\n"+tabs+tab);
scroll_to(get_buffer()->get_insert());
return true;
}
}
// JavaScript: simplified indentations inside brackets, after for example:
// [\n 1, 2, 3,\n
// return (\n
// ReactDOM.render(\n <div>\n
if(open_non_curly_bracket_iter_found && (*open_non_curly_bracket_iter=='[' || *open_non_curly_bracket_iter=='(')) {
if(condition_iter.get_line()==open_non_curly_bracket_iter.get_line())
tabs=get_line_before(start_iter)+tab;
else {
start_iter=get_tabs_end_iter(get_buffer()->get_iter_at_line(condition_iter.get_line()));
tabs=get_line_before(start_iter);
}
get_buffer()->insert_at_cursor("\n"+tabs);
scroll_to(get_buffer()->get_insert());
return true;
}
}
//Indent multiline expressions // Indent multiline expressions
if(open_non_curly_bracket_iter_found) { if(open_non_curly_bracket_iter_found) {
auto tabs_end_iter=get_tabs_end_iter(open_non_curly_bracket_iter); auto iter=get_tabs_end_iter(open_non_curly_bracket_iter);
auto tabs=get_line_before(get_tabs_end_iter(open_non_curly_bracket_iter)); auto tabs=get_line_before(iter);
auto iter=tabs_end_iter;
while(iter<=open_non_curly_bracket_iter) { while(iter<=open_non_curly_bracket_iter) {
tabs+=' '; tabs+=' ';
iter.forward_char(); iter.forward_char();
@ -2030,16 +2097,18 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
scroll_to(get_buffer()->get_insert()); scroll_to(get_buffer()->get_insert());
return true; return true;
} }
auto after_condition_iter=condition_iter; auto after_condition_iter=condition_iter;
after_condition_iter.forward_char(); after_condition_iter.forward_char();
std::string sentence=get_buffer()->get_text(start_iter, after_condition_iter); std::string sentence=get_buffer()->get_text(start_iter, after_condition_iter);
std::smatch sm; std::smatch sm;
// Indenting after for instance: if(...)\n
if(std::regex_match(sentence, sm, no_bracket_statement_regex)) { if(std::regex_match(sentence, sm, no_bracket_statement_regex)) {
get_buffer()->insert_at_cursor("\n"+tabs+tab); get_buffer()->insert_at_cursor("\n"+tabs+tab);
scroll_to(get_buffer()->get_insert()); scroll_to(get_buffer()->get_insert());
return true; return true;
} }
//Indenting after for instance if(...)\n...;\n // Indenting after for instance: if(...)\n...;\n
else if(*condition_iter==';' && condition_iter.get_line()>0 && is_code_iter(condition_iter)) { else if(*condition_iter==';' && condition_iter.get_line()>0 && is_code_iter(condition_iter)) {
auto previous_end_iter=start_iter; auto previous_end_iter=start_iter;
while(previous_end_iter.backward_char() && !previous_end_iter.ends_line()) {} while(previous_end_iter.backward_char() && !previous_end_iter.ends_line()) {}
@ -2056,7 +2125,7 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
return true; return true;
} }
} }
//Indenting after ':' // Indenting after ':'
else if(*condition_iter==':' && is_code_iter(condition_iter)) { else if(*condition_iter==':' && is_code_iter(condition_iter)) {
bool perform_indent=true; bool perform_indent=true;
auto iter=condition_iter; auto iter=condition_iter;
@ -2090,7 +2159,7 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
scroll_to(get_buffer()->get_insert()); scroll_to(get_buffer()->get_insert());
return true; return true;
} }
//Indent left when writing } on a new line // Indent left when writing } on a new line
else if(key->keyval==GDK_KEY_braceright) { else if(key->keyval==GDK_KEY_braceright) {
std::string line=get_line_before(); std::string line=get_line_before();
if(line.size()>=tab_size && iter.ends_line()) { if(line.size()>=tab_size && iter.ends_line()) {
@ -2112,7 +2181,7 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
} }
} }
} }
//Indent left when writing { on a new line after for instance if(...)\n... // Indent left when writing { on a new line after for instance if(...)\n...
else if(key->keyval==GDK_KEY_braceleft) { else if(key->keyval==GDK_KEY_braceleft) {
auto tabs_end_iter=get_tabs_end_iter(); auto tabs_end_iter=get_tabs_end_iter();
auto tabs=get_line_before(tabs_end_iter); auto tabs=get_line_before(tabs_end_iter);

2
src/source.h

@ -117,7 +117,7 @@ namespace Source {
Gtk::TextIter find_start_of_sentence(Gtk::TextIter iter); Gtk::TextIter find_start_of_sentence(Gtk::TextIter iter);
bool find_open_non_curly_bracket_backward(Gtk::TextIter iter, Gtk::TextIter &found_iter); bool find_open_non_curly_bracket_backward(Gtk::TextIter iter, Gtk::TextIter &found_iter);
bool find_open_curly_bracket_backward(Gtk::TextIter iter, Gtk::TextIter &found_iter); bool find_open_curly_bracket_backward(Gtk::TextIter iter, Gtk::TextIter &found_iter);
bool find_close_curly_bracket_forward(Gtk::TextIter iter, Gtk::TextIter &found_iter); bool find_close_symbol_forward(Gtk::TextIter iter, Gtk::TextIter &found_iter, unsigned int positive_char, unsigned int negative_char);
long symbol_count(Gtk::TextIter iter, unsigned int positive_char, unsigned int negative_char); long symbol_count(Gtk::TextIter iter, unsigned int positive_char, unsigned int negative_char);
bool is_templated_function(Gtk::TextIter iter, Gtk::TextIter &parenthesis_end_iter); bool is_templated_function(Gtk::TextIter iter, Gtk::TextIter &parenthesis_end_iter);

Loading…
Cancel
Save