Skip to content

Commit 7d3a043

Browse files
committed
Add multiple programming language support to class reference
1 parent 0cd98ec commit 7d3a043

File tree

4 files changed

+138
-44
lines changed

4 files changed

+138
-44
lines changed

doc/tools/makerst.py

+62-37
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,43 @@ def escape_rst(text, until_pos=-1): # type: (str) -> str
600600
return text
601601

602602

603+
def format_codeblock(code_type, post_text, indent_level, state): # types: str, str, int, state
604+
end_pos = post_text.find("[/" + code_type + "]")
605+
if end_pos == -1:
606+
print_error("[" + code_type + "] without a closing tag, file: {}".format(state.current_class), state)
607+
return None
608+
609+
code_text = post_text[len("[" + code_type + "]") : end_pos]
610+
post_text = post_text[end_pos:]
611+
612+
# Remove extraneous tabs
613+
code_pos = 0
614+
while True:
615+
code_pos = code_text.find("\n", code_pos)
616+
if code_pos == -1:
617+
break
618+
619+
to_skip = 0
620+
while code_pos + to_skip + 1 < len(code_text) and code_text[code_pos + to_skip + 1] == "\t":
621+
to_skip += 1
622+
623+
if to_skip > indent_level:
624+
print_error(
625+
"Four spaces should be used for indentation within ["
626+
+ code_type
627+
+ "], file: {}".format(state.current_class),
628+
state,
629+
)
630+
631+
if len(code_text[code_pos + to_skip + 1 :]) == 0:
632+
code_text = code_text[:code_pos] + "\n"
633+
code_pos += 1
634+
else:
635+
code_text = code_text[:code_pos] + "\n " + code_text[code_pos + to_skip + 1 :]
636+
code_pos += 5 - to_skip
637+
return ["\n[" + code_type + "]" + code_text + post_text, len("\n[" + code_type + "]" + code_text)]
638+
639+
603640
def rstize_text(text, state): # type: (str, State) -> str
604641
# Linebreak + tabs in the XML should become two line breaks unless in a "codeblock"
605642
pos = 0
@@ -616,43 +653,17 @@ def rstize_text(text, state): # type: (str, State) -> str
616653
post_text = text[pos + 1 :]
617654

618655
# Handle codeblocks
619-
if post_text.startswith("[codeblock]"):
620-
end_pos = post_text.find("[/codeblock]")
621-
if end_pos == -1:
622-
print_error("[codeblock] without a closing tag, file: {}".format(state.current_class), state)
656+
if (
657+
post_text.startswith("[codeblock]")
658+
or post_text.startswith("[gdscript]")
659+
or post_text.startswith("[csharp]")
660+
):
661+
block_type = post_text[1:].split("]")[0]
662+
result = format_codeblock(block_type, post_text, indent_level, state)
663+
if result is None:
623664
return ""
624-
625-
code_text = post_text[len("[codeblock]") : end_pos]
626-
post_text = post_text[end_pos:]
627-
628-
# Remove extraneous tabs
629-
code_pos = 0
630-
while True:
631-
code_pos = code_text.find("\n", code_pos)
632-
if code_pos == -1:
633-
break
634-
635-
to_skip = 0
636-
while code_pos + to_skip + 1 < len(code_text) and code_text[code_pos + to_skip + 1] == "\t":
637-
to_skip += 1
638-
639-
if to_skip > indent_level:
640-
print_error(
641-
"Four spaces should be used for indentation within [codeblock], file: {}".format(
642-
state.current_class
643-
),
644-
state,
645-
)
646-
647-
if len(code_text[code_pos + to_skip + 1 :]) == 0:
648-
code_text = code_text[:code_pos] + "\n"
649-
code_pos += 1
650-
else:
651-
code_text = code_text[:code_pos] + "\n " + code_text[code_pos + to_skip + 1 :]
652-
code_pos += 5 - to_skip
653-
654-
text = pre_text + "\n[codeblock]" + code_text + post_text
655-
pos += len("\n[codeblock]" + code_text)
665+
text = pre_text + result[0]
666+
pos += result[1]
656667

657668
# Handle normal text
658669
else:
@@ -697,7 +708,7 @@ def rstize_text(text, state): # type: (str, State) -> str
697708
else: # command
698709
cmd = tag_text
699710
space_pos = tag_text.find(" ")
700-
if cmd == "/codeblock":
711+
if cmd == "/codeblock" or cmd == "/gdscript" or cmd == "/csharp":
701712
tag_text = ""
702713
tag_depth -= 1
703714
inside_code = False
@@ -813,6 +824,20 @@ def rstize_text(text, state): # type: (str, State) -> str
813824
tag_depth += 1
814825
tag_text = "\n::\n"
815826
inside_code = True
827+
elif cmd == "gdscript":
828+
tag_depth += 1
829+
tag_text = "\n .. code-tab:: gdscript GDScript\n"
830+
inside_code = True
831+
elif cmd == "csharp":
832+
tag_depth += 1
833+
tag_text = "\n .. code-tab:: csharp\n"
834+
inside_code = True
835+
elif cmd == "codeblocks":
836+
tag_depth += 1
837+
tag_text = "\n.. tabs::"
838+
elif cmd == "/codeblocks":
839+
tag_depth -= 1
840+
tag_text = ""
816841
elif cmd == "br":
817842
# Make a new paragraph instead of a linebreak, rst is not so linebreak friendly
818843
tag_text = "\n\n"

editor/editor_help.cpp

+70-7
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,20 @@ void EditorHelp::_class_desc_resized() {
177177
class_desc->add_theme_style_override("normal", class_desc_stylebox);
178178
}
179179

180+
String EditorHelp::_convert_case(const String &p_name) {
181+
switch ((int)EDITOR_GET("text_editor/help/class_reference_language")) {
182+
case 0: // GDScript
183+
return p_name;
184+
case 1: {
185+
// C#
186+
bool first_is_underscore = p_name[0] == '_';
187+
String result = p_name.capitalize();
188+
return (first_is_underscore ? "_" : "") + result.replace(" ", "");
189+
}
190+
}
191+
return p_name;
192+
}
193+
180194
void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
181195
String t = p_type;
182196
if (t.empty()) {
@@ -263,7 +277,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
263277
}
264278

265279
class_desc->push_color(headline_color);
266-
_add_text(p_method.name);
280+
_add_text(_convert_case(p_method.name));
267281
class_desc->pop();
268282

269283
if (p_overview && p_method.description != "") {
@@ -558,7 +572,7 @@ void EditorHelp::_update_doc() {
558572
class_desc->push_meta("@member " + cd.properties[i].name);
559573
}
560574

561-
_add_text(cd.properties[i].name);
575+
_add_text(_convert_case(cd.properties[i].name));
562576

563577
if (describe) {
564578
class_desc->pop();
@@ -1013,7 +1027,7 @@ void EditorHelp::_update_doc() {
10131027
class_desc->push_cell();
10141028
class_desc->push_font(doc_code_font);
10151029
class_desc->push_color(headline_color);
1016-
_add_text(cd.properties[i].name);
1030+
_add_text(_convert_case(cd.properties[i].name));
10171031
class_desc->pop(); // color
10181032

10191033
if (cd.properties[i].default_value != "") {
@@ -1048,10 +1062,10 @@ void EditorHelp::_update_doc() {
10481062
if (method_map[cd.properties[i].setter].arguments.size() > 1) {
10491063
// Setters with additional arguments are exposed in the method list, so we link them here for quick access.
10501064
class_desc->push_meta("@method " + cd.properties[i].setter);
1051-
class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
1065+
class_desc->add_text(_convert_case(cd.properties[i].setter) + TTR("(value)"));
10521066
class_desc->pop();
10531067
} else {
1054-
class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
1068+
class_desc->add_text(_convert_case(cd.properties[i].setter) + TTR("(value)"));
10551069
}
10561070
class_desc->pop(); // color
10571071
class_desc->push_color(comment_color);
@@ -1072,10 +1086,10 @@ void EditorHelp::_update_doc() {
10721086
if (method_map[cd.properties[i].getter].arguments.size() > 0) {
10731087
// Getters with additional arguments are exposed in the method list, so we link them here for quick access.
10741088
class_desc->push_meta("@method " + cd.properties[i].getter);
1075-
class_desc->add_text(cd.properties[i].getter + "()");
1089+
class_desc->add_text(_convert_case(cd.properties[i].getter) + "()");
10761090
class_desc->pop();
10771091
} else {
1078-
class_desc->add_text(cd.properties[i].getter + "()");
1092+
class_desc->add_text(_convert_case(cd.properties[i].getter) + "()");
10791093
}
10801094
class_desc->pop(); //color
10811095
class_desc->push_color(comment_color);
@@ -1252,6 +1266,55 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
12521266

12531267
String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
12541268

1269+
// Select the correct code examples
1270+
switch ((int)EDITOR_GET("text_editor/help/class_reference_examples")) {
1271+
case 0: // GDScript
1272+
bbcode = bbcode.replace("[gdscript]", "[codeblock]");
1273+
bbcode = bbcode.replace("[/gdscript]", "[/codeblock]");
1274+
1275+
for (int pos = bbcode.find("[csharp]"); pos != -1; pos = bbcode.find("[csharp]")) {
1276+
if (bbcode.find("[/csharp]") == -1) {
1277+
WARN_PRINT("Unclosed [csharp] block or parse fail in code (search for tag errors)");
1278+
break;
1279+
}
1280+
1281+
bbcode.erase(pos, bbcode.find("[/csharp]") + 9 - pos);
1282+
while (bbcode[pos] == '\n') {
1283+
bbcode.erase(pos, 1);
1284+
}
1285+
}
1286+
break;
1287+
case 1: // C#
1288+
bbcode = bbcode.replace("[csharp]", "[codeblock]");
1289+
bbcode = bbcode.replace("[/csharp]", "[/codeblock]");
1290+
1291+
for (int pos = bbcode.find("[gdscript]"); pos != -1; pos = bbcode.find("[gdscript]")) {
1292+
if (bbcode.find("[/gdscript]") == -1) {
1293+
WARN_PRINT("Unclosed [gdscript] block or parse fail in code (search for tag errors)");
1294+
break;
1295+
}
1296+
1297+
bbcode.erase(pos, bbcode.find("[/gdscript]") + 11 - pos);
1298+
while (bbcode[pos] == '\n') {
1299+
bbcode.erase(pos, 1);
1300+
}
1301+
}
1302+
break;
1303+
case 2: // GDScript and C#
1304+
bbcode = bbcode.replace("[csharp]", "[b]C#:[/b]\n[codeblock]");
1305+
bbcode = bbcode.replace("[gdscript]", "[b]GDScript:[/b]\n[codeblock]");
1306+
1307+
bbcode = bbcode.replace("[/csharp]", "[/codeblock]");
1308+
bbcode = bbcode.replace("[/gdscript]", "[/codeblock]");
1309+
break;
1310+
}
1311+
1312+
// Remove codeblocks (they would be printed otherwise)
1313+
bbcode = bbcode.replace("[codeblocks]\n", "");
1314+
bbcode = bbcode.replace("\n[/codeblocks]", "");
1315+
bbcode = bbcode.replace("[codeblocks]", "");
1316+
bbcode = bbcode.replace("[/codeblocks]", "");
1317+
12551318
// remove extra new lines around code blocks
12561319
bbcode = bbcode.replace("[codeblock]\n", "[codeblock]");
12571320
bbcode = bbcode.replace("\n[/codeblock]", "[/codeblock]");

editor/editor_help.h

+2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ class EditorHelp : public VBoxContainer {
152152
void _class_desc_input(const Ref<InputEvent> &p_input);
153153
void _class_desc_resized();
154154

155+
String _convert_case(const String &p_name);
156+
155157
Error _goto_desc(const String &p_class, int p_vscr = -1);
156158
//void _update_history_buttons();
157159
void _update_doc();

editor/editor_settings.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
495495
hints["text_editor/help/help_source_font_size"] = PropertyInfo(Variant::INT, "text_editor/help/help_source_font_size", PROPERTY_HINT_RANGE, "8,48,1");
496496
_initial_set("text_editor/help/help_title_font_size", 23);
497497
hints["text_editor/help/help_title_font_size"] = PropertyInfo(Variant::INT, "text_editor/help/help_title_font_size", PROPERTY_HINT_RANGE, "8,48,1");
498+
_initial_set("text_editor/help/class_reference_language", 0);
499+
hints["text_editor/help/class_reference_language"] = PropertyInfo(Variant::INT, "text_editor/help/class_reference_language", PROPERTY_HINT_ENUM, "GDScript,C#");
500+
_initial_set("text_editor/help/class_reference_examples", 0);
501+
hints["text_editor/help/class_reference_examples"] = PropertyInfo(Variant::INT, "text_editor/help/class_reference_examples", PROPERTY_HINT_ENUM, "GDScript,C#,GDScript and C#");
498502

499503
/* Editors */
500504

0 commit comments

Comments
 (0)