Browse Source

Implemented menu item Source.Comments.Add Documentation

merge-requests/365/head
eidheim 9 years ago
parent
commit
cea6db59bf
  1. 2
      src/menu.cc
  2. 115
      src/source.cc
  3. 4
      src/source.h
  4. 44
      src/source_clang.cc
  5. 43
      src/window.cc

2
src/menu.cc

@ -275,7 +275,7 @@ const Glib::ustring menu_xml= R"RAW(<interface>
<attribute name='action'>app.source_comments_toggle</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Add _Documentation (not yet implemented)</attribute>
<attribute name='label' translatable='yes'>_Add _Documentation</attribute>
<attribute name='action'>app.source_comments_add_documentation</attribute>
</item>
</submenu>

115
src/source.cc

@ -1244,6 +1244,25 @@ std::string Source::View::get_token(Gtk::TextIter iter) {
return get_buffer()->get_text(start, end);
}
void Source::View::cleanup_whitespace_characters_on_return(const Gtk::TextIter &iter) {
auto start_blank_iter=iter;
auto end_blank_iter=iter;
while((*end_blank_iter==' ' || *end_blank_iter=='\t') &&
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {}
if(!start_blank_iter.starts_line()) {
start_blank_iter.backward_char();
while((*start_blank_iter==' ' || *start_blank_iter=='\t') &&
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {}
if(*start_blank_iter!=' ' && *start_blank_iter!='\t')
start_blank_iter.forward_char();
}
if(start_blank_iter.starts_line())
get_buffer()->erase(iter, end_blank_iter);
else
get_buffer()->erase(start_blank_iter, end_blank_iter);
}
bool Source::View::on_key_press_event(GdkEventKey* key) {
if(SelectionDialog::get() && SelectionDialog::get()->is_visible()) {
if(SelectionDialog::get()->on_key_press(key))
@ -1327,24 +1346,6 @@ bool Source::View::on_key_press_event(GdkEventKey* key) {
get_buffer()->end_user_action();
return true;
}
if(get_buffer()->get_has_selection()) {
auto return_value=on_key_press_event_basic(key);
get_buffer()->end_user_action();
if(return_value)
return true;
else
return Gsv::View::on_key_press_event(key);
}
if(!is_code_iter(get_buffer()->get_insert()->get_iter())) {
auto return_value=on_key_press_event_basic(key);
get_buffer()->end_user_action();
if(return_value)
return true;
else
return Gsv::View::on_key_press_event(key);
}
if(is_bracket_language && on_key_press_event_bracket_language(key)) {
get_buffer()->end_user_action();
@ -1363,23 +1364,10 @@ bool Source::View::on_key_press_event(GdkEventKey* key) {
//Basic indentation
bool Source::View::on_key_press_event_basic(GdkEventKey* key) {
auto iter=get_buffer()->get_insert()->get_iter();
//Indent as in next or previous line
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !get_buffer()->get_has_selection() && !iter.starts_line()) {
//First remove spaces or tabs around cursor
auto start_blank_iter=iter;
auto end_blank_iter=iter;
while((*end_blank_iter==' ' || *end_blank_iter=='\t') &&
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {}
start_blank_iter.backward_char();
while((*start_blank_iter==' ' || *start_blank_iter=='\t') &&
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {}
if(start_blank_iter.starts_line() && (*start_blank_iter==' ' || *start_blank_iter=='\t'))
get_buffer()->erase(iter, end_blank_iter);
else {
start_blank_iter.forward_char();
get_buffer()->erase(start_blank_iter, end_blank_iter);
}
cleanup_whitespace_characters_on_return(iter);
iter=get_buffer()->get_insert()->get_iter();
auto tabs=get_line_before(get_tabs_end_iter(iter));
@ -1595,22 +1583,39 @@ bool Source::View::on_key_press_event_basic(GdkEventKey* key) {
//Bracket language indentation
bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
auto iter=get_buffer()->get_insert()->get_iter();
if(get_buffer()->get_has_selection())
return false;
if(!is_code_iter(iter)) {
// Add * at start of line in comment blocks
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) {
cleanup_whitespace_characters_on_return(iter);
iter=get_buffer()->get_insert()->get_iter();
auto start_iter=get_tabs_end_iter(iter.get_line());
auto end_iter=start_iter;
end_iter.forward_chars(2);
auto start_of_sentence=get_buffer()->get_text(start_iter, end_iter);
if(!start_of_sentence.empty()) {
if(start_of_sentence=="/*" || start_of_sentence[0]=='*') {
auto tabs=get_line_before(start_iter);
auto insert_str="\n"+tabs;
if(start_of_sentence[0]=='/')
insert_str+=' ';
insert_str+="* ";
get_buffer()->insert_at_cursor(insert_str);
return true;
}
}
}
return false;
}
//Indent depending on if/else/etc and brackets
if((key->keyval==GDK_KEY_Return || key->keyval==GDK_KEY_KP_Enter) && !iter.starts_line()) {
//First remove spaces or tabs around cursor
auto start_blank_iter=iter;
auto end_blank_iter=iter;
while((*end_blank_iter==' ' || *end_blank_iter=='\t') &&
!end_blank_iter.ends_line() && end_blank_iter.forward_char()) {}
start_blank_iter.backward_char();
while((*start_blank_iter==' ' || *start_blank_iter=='\t' || start_blank_iter.ends_line()) &&
!start_blank_iter.starts_line() && start_blank_iter.backward_char()) {}
if(!start_blank_iter.starts_line()) {
start_blank_iter.forward_char();
get_buffer()->erase(start_blank_iter, end_blank_iter);
}
else
get_buffer()->erase(iter, end_blank_iter);
cleanup_whitespace_characters_on_return(iter);
iter=get_buffer()->get_insert()->get_iter();
auto previous_iter=iter;
@ -1627,6 +1632,22 @@ bool Source::View::on_key_press_event_bracket_language(GdkEventKey* key) {
else
start_iter=get_tabs_end_iter(get_buffer()->get_iter_at_line(find_start_of_sentence(start_iter).get_line()));
auto tabs=get_line_before(start_iter);
/*
* Change tabs after ending comment block with an extra space (as in this case)
*/
if(tabs.size()%tab_size==1) {
iter=get_buffer()->get_insert()->get_iter();
auto tabs_end_iter=get_tabs_end_iter(iter);
if(!tabs_end_iter.ends_line() && !is_code_iter(tabs_end_iter)) {
auto end_of_line_iter=tabs_end_iter;
end_of_line_iter.forward_to_line_end();
auto line=get_buffer()->get_text(tabs_end_iter, end_of_line_iter);
if(!line.empty() && line.compare(0, 2, "*/")==0)
tabs.pop_back();
}
}
if(*previous_iter=='{') {
Gtk::TextIter found_iter;
bool found_right_bracket=find_close_curly_bracket_forward(iter, found_iter);

4
src/source.h

@ -77,7 +77,7 @@ namespace Source {
std::function<void()> goto_next_diagnostic;
std::function<std::vector<FixIt>()> get_fix_its;
std::function<void()> toggle_comments;
std::function<void()> add_documentation;
std::function<std::tuple<Source::Offset, std::string, size_t>()> get_documentation_template;
std::function<void(int)> toggle_breakpoint;
Gtk::TextIter get_iter_for_dialog();
@ -136,6 +136,8 @@ namespace Source {
std::string get_token(Gtk::TextIter iter);
void cleanup_whitespace_characters_on_return(const Gtk::TextIter &iter);
const static std::regex bracket_regex;
const static std::regex no_bracket_statement_regex;
const static std::regex no_bracket_no_para_statement_regex;

44
src/source_clang.cc

@ -1403,6 +1403,50 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
Info::get().print("No fix-its found in current buffer");
return fix_its;
};
get_documentation_template=[this]() {
if(!parsed) {
Info::get().print("Buffer is parsing");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
auto identifier=get_identifier();
if(identifier) {
auto cursor=identifier.cursor.get_canonical();
if(!clang_Range_isNull(clang_Cursor_getCommentRange(cursor.cx_cursor))) {
Info::get().print("Symbol is already documented");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
auto clang_offsets=cursor.get_source_range().get_offsets();
auto source_offset=Offset(clang_offsets.first.line-1, 0, cursor.get_source_location().get_path());
std::string tabs;
for(size_t c=0;c<clang_offsets.first.index-1;++c)
tabs+=' ';
auto first_line=tabs+"/**\n";
auto second_line=tabs+" * \n";
auto iter_offset=first_line.size()+second_line.size()-1;
std::string param_lines;
for(int c=0;c<clang_Cursor_getNumArguments(cursor.cx_cursor);++c)
param_lines+=tabs+" * @param "+clang::Cursor(clang_Cursor_getArgument(cursor.cx_cursor, c)).get_spelling()+'\n';
std::string return_line;
auto return_spelling=cursor.get_type().get_result().get_spelling();
if(!return_spelling.empty() && return_spelling!="void")
return_line+=tabs+" * @return\n";
auto documentation=first_line+second_line;
if(!param_lines.empty() || !return_line.empty())
documentation+=tabs+" *\n";
documentation+=param_lines+return_line+tabs+" */\n";
return std::tuple<Source::Offset, std::string, size_t>(source_offset, documentation, iter_offset);
}
else {
Info::get().print("No symbol found at current cursor location");
return std::tuple<Source::Offset, std::string, size_t>(Source::Offset(), "", 0);
}
};
}
Source::ClangViewRefactor::Identifier Source::ClangViewRefactor::get_identifier() {

43
src/window.cc

@ -651,8 +651,23 @@ void Window::set_menu_actions() {
});
menu.add_action("source_comments_add_documentation", [this]() {
if(auto view=Notebook::get().get_current_view()) {
if(view->add_documentation) {
view->add_documentation();
if(view->get_documentation_template) {
auto documentation_template=view->get_documentation_template();
auto offset=std::get<0>(documentation_template);
if(offset) {
boost::system::error_code ec;
auto canonical_path=boost::filesystem::canonical(offset.file_path, ec);
if(ec)
return;
Notebook::get().open(canonical_path);
auto view=Notebook::get().get_current_view();
auto iter=view->get_buffer()->get_iter_at_line_index(offset.line, offset.index);
view->get_buffer()->insert(iter, std::get<1>(documentation_template));
iter=view->get_buffer()->get_iter_at_line_index(offset.line, offset.index);
iter.forward_chars(std::get<2>(documentation_template));
view->get_buffer()->place_cursor(iter);
view->scroll_to_cursor_delayed(view, true, false);
}
}
}
});
@ -1174,18 +1189,18 @@ void Window::activate_menu_items() {
menu.actions["source_goto_line"]->set_enabled(view);
menu.actions["source_center_cursor"]->set_enabled(view);
menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(view && static_cast<bool>(view->format_style));
menu.actions["source_comments_toggle"]->set_enabled(view && static_cast<bool>(view->toggle_comments));
menu.actions["source_comments_add_documentation"]->set_enabled(view && static_cast<bool>(view->add_documentation));
menu.actions["source_find_documentation"]->set_enabled(view && static_cast<bool>(view->get_token_data));
menu.actions["source_goto_declaration"]->set_enabled(view && static_cast<bool>(view->get_declaration_location));
menu.actions["source_goto_implementation"]->set_enabled(view && static_cast<bool>(view->get_implementation_locations));
menu.actions["source_goto_usage"]->set_enabled(view && static_cast<bool>(view->get_usages));
menu.actions["source_goto_method"]->set_enabled(view && static_cast<bool>(view->get_methods));
menu.actions["source_rename"]->set_enabled(view && static_cast<bool>(view->rename_similar_tokens));
menu.actions["source_implement_method"]->set_enabled(view && static_cast<bool>(view->get_method));
menu.actions["source_goto_next_diagnostic"]->set_enabled(view && static_cast<bool>(view->goto_next_diagnostic));
menu.actions["source_apply_fix_its"]->set_enabled(view && static_cast<bool>(view->get_fix_its));
menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(view && view->format_style);
menu.actions["source_comments_toggle"]->set_enabled(view && view->toggle_comments);
menu.actions["source_comments_add_documentation"]->set_enabled(view && view->get_documentation_template);
menu.actions["source_find_documentation"]->set_enabled(view && view->get_token_data);
menu.actions["source_goto_declaration"]->set_enabled(view && view->get_declaration_location);
menu.actions["source_goto_implementation"]->set_enabled(view && view->get_implementation_locations);
menu.actions["source_goto_usage"]->set_enabled(view && view->get_usages);
menu.actions["source_goto_method"]->set_enabled(view && view->get_methods);
menu.actions["source_rename"]->set_enabled(view && view->rename_similar_tokens);
menu.actions["source_implement_method"]->set_enabled(view && view->get_method);
menu.actions["source_goto_next_diagnostic"]->set_enabled(view && view->goto_next_diagnostic);
menu.actions["source_apply_fix_its"]->set_enabled(view && view->get_fix_its);
#ifdef JUCI_ENABLE_DEBUG
Project::debug_activate_menu_items();
#endif

Loading…
Cancel
Save