Text Editor: Auto close relevant characters

Support the ability to close relevant characters like '(', '[' and '{'.

It will also delete the pair character if they're empty.

Ref D13119

Reviewed By: campbellbarton
This commit is contained in:
Matheus Santos 2021-11-13 13:49:09 +11:00 committed by Campbell Barton
parent 1143bf281a
commit c4ea5cb1a3
Notes: blender-bot 2023-02-14 05:43:04 +01:00
Referenced by issue #95932, Drag n drop of object from Outliner into Text Editor is broken (when using Auto Close Text Editor Preference)
4 changed files with 70 additions and 2 deletions

View File

@ -477,6 +477,16 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
col.active = view.use_weight_color_range
col.template_color_ramp(view, "weight_color_range", expand=True)
class USERPREF_PT_edit_text_editor(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Text Editor"
bl_options = {'DEFAULT_CLOSED'}
def draw_centered(self, context, layout):
prefs = context.preferences
edit = prefs.edit
layout.prop(edit, "use_text_edit_auto_close")
class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Miscellaneous"
@ -2357,6 +2367,7 @@ classes = (
USERPREF_PT_edit_annotations,
USERPREF_PT_edit_weight_paint,
USERPREF_PT_edit_gpencil,
USERPREF_PT_edit_text_editor,
USERPREF_PT_edit_misc,
USERPREF_PT_animation_timeline,

View File

@ -85,6 +85,30 @@ static void test_line_start(char c, bool *r_last_state)
}
}
/**
* This function receives a character and returns its closing pair if it exists.
* \param character: Characater to find the closing pair.
* \return The closing pair of the character if it exists.
*/
static char text_closing_character_pair_get(const char character)
{
switch (character) {
case '(':
return ')';
case '[':
return ']';
case '{':
return '}';
case '"':
return '"';
case '\'':
return '\'';
default:
return 0;
}
}
/**
* This function converts the indentation tabs from a buffer to spaces.
* \param in_buf: A pointer to a cstring.
@ -2403,7 +2427,17 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
}
if (U.text_flag & USER_TEXT_EDIT_AUTO_CLOSE) {
const char *current = text->curl->line + text->curc;
if (*current != '\0') {
const char *prev = BLI_str_find_prev_char_utf8(text->curl->line + text->curc,
text->curl->line);
if (*current == text_closing_character_pair_get(*prev)) {
txt_move_right(text, false);
txt_backspace_char(text);
}
}
}
txt_backspace_char(text);
}
else if (type == DEL_NEXT_WORD) {
@ -3443,6 +3477,12 @@ static int text_insert_exec(bContext *C, wmOperator *op)
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, str_len, &i);
done |= txt_add_char(text, code);
if (U.text_flag & USER_TEXT_EDIT_AUTO_CLOSE) {
if (text_closing_character_pair_get(code)) {
done |= txt_add_char(text, text_closing_character_pair_get(code));
txt_move_left(text, false);
}
}
}
}

View File

@ -938,7 +938,8 @@ typedef struct UserDef {
short sequencer_proxy_setup; /* eUserpref_SeqProxySetup */
float collection_instance_empty_size;
char _pad10[2];
char text_flag;
char _pad10[1];
char file_preview_type; /* eUserpref_File_Preview_Type */
char statusbar_flag; /* eUserpref_StatusBar_Flag */
@ -1262,6 +1263,14 @@ typedef enum eDupli_ID_Flags {
USER_DUP_LINKED_ID = (1 << 30),
} eDupli_ID_Flags;
/**
* Text Editor options
* #UserDef.text_flag
*/
typedef enum eTextEdit_Flags {
USER_TEXT_EDIT_AUTO_CLOSE = (1 << 0),
} eTextEdit_Flags;
/**
* Text draw options
* #UserDef.text_render

View File

@ -5024,6 +5024,14 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
"Collection Instance Empty Size",
"Display size of the empty when new collection instances are created");
/* Text Editor */
prop = RNA_def_property(srna, "use_text_edit_auto_close", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "text_flag", USER_TEXT_EDIT_AUTO_CLOSE);
RNA_def_property_ui_text(
prop, "Auto Close", "Auto close relevant characters inside the text editor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
/* Undo */
prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE);