Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Autofill comment when inserting a new line while being on a documenta…
…tion comment line
  • Loading branch information
Cronos87 committed Dec 23, 2024
commit fea517b1dfd334ba465673749866c992a15ab84b
1 change: 1 addition & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class ScriptLanguage : public Object {
virtual bool is_control_flow_keyword(const String &p_string) const = 0;
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_doc_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_delimiters) const = 0;
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { return Ref<Script>(); }
virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) { return Vector<ScriptTemplate>(); }
Expand Down
1 change: 1 addition & 0 deletions core/object/script_language_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void ScriptLanguageExtension::_bind_methods() {
GDVIRTUAL_BIND(_is_control_flow_keyword, "keyword");
GDVIRTUAL_BIND(_get_comment_delimiters);
GDVIRTUAL_BIND(_get_doc_comment_delimiters);
GDVIRTUAL_BIND(_get_doc_comment_block_delimiters);
GDVIRTUAL_BIND(_get_string_delimiters);
GDVIRTUAL_BIND(_make_template, "template", "class_name", "base_class_name");
GDVIRTUAL_BIND(_get_built_in_templates, "object");
Expand Down
14 changes: 14 additions & 0 deletions core/object/script_language_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,20 @@ class ScriptLanguageExtension : public ScriptLanguage {
}
}

GDVIRTUAL0RC(Vector<String>, _get_doc_comment_block_delimiters)

virtual void get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_words) const override {
Vector<String> ret;
GDVIRTUAL_CALL(_get_doc_comment_block_delimiters, ret);
for (const String &delimiter : ret) {
HashMap<String, String> word;
word["delimiter_begin"] = delimiter;
word["delimiter_block"] = "";
word["delimiter_end"] = "";
p_words->push_back(word);
}
}

GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_string_delimiters)

virtual void get_string_delimiters(List<String> *p_words) const override {
Expand Down
5 changes: 5 additions & 0 deletions doc/classes/ScriptLanguageExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@
<description>
</description>
</method>
<method name="_get_doc_comment_block_delimiters" qualifiers="virtual const">
<return type="PackedStringArray" />
<description>
</description>
</method>
<method name="_get_doc_comment_delimiters" qualifiers="virtual const">
<return type="PackedStringArray" />
<description>
Expand Down
102 changes: 102 additions & 0 deletions editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,107 @@ void ScriptTextEditor::_gutter_clicked(int p_line, int p_gutter) {
}
}

void ScriptTextEditor::_auto_fill_doc_comments(bool p_above) {
CodeEdit *tx = code_editor->get_text_editor();

if (tx->get_comment_delimiters().is_empty()) {
return;
}

List<HashMap<String, String>> doc_comments_block;
script->get_language()->get_doc_comment_block_delimiters(&doc_comments_block);

// Store the operations to apply, as complex operations need to be used only if comments are added.
List<Vector<Variant>> operations;

for (int i = 0; i < tx->get_caret_count(); i++) {
if (tx->multicaret_edit_ignore_caret(i)) {
continue;
}

const int cl = p_above ? (tx->get_caret_line(i) + 1) : (tx->get_caret_line(i) - 1);
const String line = tx->get_line(cl);

if (tx->is_in_comment(cl) != -1) {
for (const HashMap<String, String> &doc_comment_block : doc_comments_block) {
const String delimiter_begin = doc_comment_block["delimiter_begin"];
const String delimiter_block = doc_comment_block["delimiter_block"];
const String delimiter_end = doc_comment_block["delimiter_end"];
const bool is_inline_delimiter = delimiter_end.is_empty();
String line_strip = line.strip_edges();

// Case for inline comments.
if (is_inline_delimiter) {
if (line_strip.begins_with(delimiter_begin)) {
operations.push_back({ i, delimiter_begin });
break;
}

continue;
}

// Case when the caret is on the same line as a block comment.
if (!p_above && line_strip.begins_with(delimiter_begin)) {
const String next_line = tx->get_line(cl + 1);

if (next_line.ends_with(delimiter_end.strip_edges())) {
const int non_whitespace_column = tx->get_first_non_whitespace_column(cl);
const String indent = line.substr(0, non_whitespace_column);

operations.push_back({ i, vformat("%s \n%s", delimiter_block, indent), cl + 1 });
break;
}

operations.push_back({ i, delimiter_block });
break;
}

// Case when the caret is on the same line as the end delimiter.
if (p_above && line_strip.ends_with(delimiter_end)) {
operations.push_back({ i, delimiter_block });
break;
}

// Case when the caret is in a block comment; needs to go up to
// find the beginning of the current doc comment.
for (int j = cl - 1; j >= 0; --j) {
line_strip = tx->get_line(j).strip_edges();

if (tx->is_in_comment(j) == -1) {
break;
}

if (line_strip.begins_with(delimiter_begin)) {
operations.push_back({ i, delimiter_block });
break;
}
}
}
}
}

if (!operations.is_empty()) {
tx->begin_complex_operation();

for (const Vector<Variant> &op : operations) {
const int caret = op[0];
const String delimiter = op[1].operator String();

tx->insert_text_at_caret(delimiter + " ", caret);

if (op.size() == 3) {
const int line_to_move_on = op[2];
const int line_length = tx->get_line(line_to_move_on).length();
tx->set_caret_line(line_to_move_on, false, true, -1, caret);
tx->set_caret_column(line_length, false, caret);
}
}

tx->merge_overlapping_carets();
tx->end_complex_operation();
}
}

void ScriptTextEditor::_edit_option(int p_op) {
CodeEdit *tx = code_editor->get_text_editor();
tx->apply_ime();
Expand Down Expand Up @@ -2484,6 +2585,7 @@ ScriptTextEditor::ScriptTextEditor() {
code_editor->get_text_editor()->set_draw_executing_lines_gutter(true);
code_editor->get_text_editor()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled));
code_editor->get_text_editor()->connect("caret_changed", callable_mp(this, &ScriptTextEditor::_on_caret_moved));
code_editor->get_text_editor()->add_new_line_actions(callable_mp(this, &ScriptTextEditor::_auto_fill_doc_comments));
code_editor->connect("navigation_preview_ended", callable_mp(this, &ScriptTextEditor::_on_caret_moved));

connection_gutter = 1;
Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/script_text_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class ScriptTextEditor : public ScriptEditorBase {
Color folded_code_region_color = Color(1, 1, 1);
int previous_line = 0;

void _auto_fill_doc_comments(bool p_above);

PopupPanel *color_panel = nullptr;
ColorPicker *color_picker = nullptr;
Vector2 color_position;
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ class GDScriptLanguage : public ScriptLanguage {
virtual bool is_control_flow_keyword(const String &p_keywords) const override;
virtual void get_comment_delimiters(List<String> *p_delimiters) const override;
virtual void get_doc_comment_delimiters(List<String> *p_delimiters) const override;
virtual void get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_delimiters) const override;
virtual void get_string_delimiters(List<String> *p_delimiters) const override;
virtual bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
Expand Down
9 changes: 9 additions & 0 deletions modules/gdscript/gdscript_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ void GDScriptLanguage::get_doc_comment_delimiters(List<String> *p_delimiters) co
p_delimiters->push_back("##");
}

void GDScriptLanguage::get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_delimiters) const {
HashMap<String, String> first;
first["delimiter_begin"] = "##";
first["delimiter_block"] = "";
first["delimiter_end"] = "";

p_delimiters->push_back(first);
}

void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("\" \"");
p_delimiters->push_back("' '");
Expand Down
15 changes: 15 additions & 0 deletions modules/mono/csharp_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,21 @@ void CSharpLanguage::get_doc_comment_delimiters(List<String> *p_delimiters) cons
p_delimiters->push_back("/** */"); // delimited doc comment
}

void CSharpLanguage::get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_delimiters) const {
HashMap<String, String> first;
first["delimiter_begin"] = "///";
first["delimiter_block"] = "";
first["delimiter_end"] = "";

HashMap<String, String> second;
second["delimiter_begin"] = "/**";
second["delimiter_block"] = " *";
second["delimiter_end"] = "*/";

p_delimiters->push_back(first);
p_delimiters->push_back(second);
}

void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("' '"); // character literal
p_delimiters->push_back("\" \""); // regular string literal
Expand Down
1 change: 1 addition & 0 deletions modules/mono/csharp_script.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ class CSharpLanguage : public ScriptLanguage {
bool is_control_flow_keyword(const String &p_keyword) const override;
void get_comment_delimiters(List<String> *p_delimiters) const override;
void get_doc_comment_delimiters(List<String> *p_delimiters) const override;
void get_doc_comment_block_delimiters(List<HashMap<String, String>> *p_delimiters) const override;
void get_string_delimiters(List<String> *p_delimiters) const override;
bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
Expand Down
10 changes: 10 additions & 0 deletions scene/gui/code_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,16 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {

end_multicaret_edit();
end_complex_operation();

if (new_lines_actions.size() > 0) {
for (Callable &action : new_lines_actions) {
action.call_deferred(p_above);
}
}
}

void CodeEdit::add_new_line_actions(const Callable &p_action) {
new_lines_actions.push_back(p_action);
}

/* Auto brace completion */
Expand Down
3 changes: 3 additions & 0 deletions scene/gui/code_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ class CodeEdit : public TextEdit {
void _text_changed();

void _apply_project_settings();
Vector<Callable> new_lines_actions;

protected:
void _notification(int p_what);
Expand Down Expand Up @@ -516,6 +517,8 @@ class CodeEdit : public TextEdit {
void duplicate_selection();
void duplicate_lines();

void add_new_line_actions(const Callable &p_action);

CodeEdit();
~CodeEdit();
};
Expand Down