102
105
static gboolean handle_xml(GeanyEditor *editor, gint pos, gchar ch);
103
106
static void insert_indent_after_line(GeanyEditor *editor, gint line);
104
107
static void auto_multiline(GeanyEditor *editor, gint pos);
105
static gboolean is_code_style(gint lexer, gint style);
106
static gboolean is_string_style(gint lexer, gint style);
107
108
static void auto_close_chars(ScintillaObject *sci, gint pos, gchar c);
108
static void auto_table(GeanyEditor *editor, gint pos);
109
109
static void close_block(GeanyEditor *editor, gint pos);
110
110
static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos);
111
111
static void read_current_word(GeanyEditor *editor, gint pos, gchar *word, size_t wordlen,
112
112
const gchar *wc, gboolean stem);
113
113
static gsize count_indent_size(GeanyEditor *editor, const gchar *base_indent);
114
static const gchar *snippets_find_completion_by_name(const gchar *type, const gchar *name);
115
static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
116
119
void editor_snippets_free(void)
118
121
g_hash_table_destroy(snippet_hash);
119
122
g_queue_free(snippet_offsets);
123
gtk_window_remove_accel_group(GTK_WINDOW(main_widgets.window), snippet_accel_group);
123
void editor_snippets_init(void)
127
static void snippets_load(GKeyFile *sysconfig, GKeyFile *userconfig)
125
129
gsize i, j, len = 0, len_keys = 0;
126
gchar *sysconfigfile, *userconfigfile;
127
130
gchar **groups_user, **groups_sys;
128
131
gchar **keys_user, **keys_sys;
130
GKeyFile *sysconfig = g_key_file_new();
131
GKeyFile *userconfig = g_key_file_new();
134
snippet_offsets = g_queue_new();
136
sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S, "snippets.conf", NULL);
137
userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "snippets.conf", NULL);
139
/* check for old autocomplete.conf files (backwards compatibility) */
140
if (! g_file_test(userconfigfile, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))
141
setptr(userconfigfile,
142
g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "autocomplete.conf", NULL));
144
/* load the actual config files */
145
g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
146
g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
148
135
/* keys are strings, values are GHashTables, so use g_free and g_hash_table_destroy */
150
137
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
195
187
g_strfreev(keys_user);
189
g_strfreev(groups_user);
193
static void on_snippet_keybinding_activate(gchar *key)
195
GeanyDocument *doc = document_get_current();
197
GHashTable *specials;
199
if (!doc || !GTK_WIDGET_HAS_FOCUS(doc->editor->sci))
202
s = snippets_find_completion_by_name(doc->file_type->name, key);
203
if (!s) /* allow user to specify keybindings for "special" snippets */
205
specials = g_hash_table_lookup(snippet_hash, "Special");
206
if (G_LIKELY(specials != NULL))
207
s = g_hash_table_lookup(specials, key);
215
editor_insert_snippet(doc->editor, sci_get_current_position(doc->editor->sci), s);
216
sci_scroll_caret(doc->editor->sci);
220
static void add_kb(GKeyFile *keyfile, const gchar *group, gchar **keys)
226
for (i = 0; i < g_strv_length(keys); i++)
229
GdkModifierType mods;
230
gchar *accel_string = g_key_file_get_value(keyfile, group, keys[i], NULL);
232
gtk_accelerator_parse(accel_string, &key, &mods);
233
g_free(accel_string);
235
if (key == 0 && mods == 0)
237
g_warning("Can not parse accelerator \"%s\" from user snippets.conf", accel_string);
240
gtk_accel_group_connect(snippet_accel_group, key, mods, 0,
241
g_cclosure_new_swap((GCallback)on_snippet_keybinding_activate,
242
g_strdup(keys[i]), (GClosureNotify)g_free));
247
static void load_kb(GKeyFile *sysconfig, GKeyFile *userconfig)
249
const gchar kb_group[] = "Keybindings";
250
gchar **keys = g_key_file_get_keys(userconfig, kb_group, NULL, NULL);
253
/* remove overridden keys from system keyfile */
254
foreach_strv(ptr, keys)
255
g_key_file_remove_key(sysconfig, kb_group, *ptr, NULL);
257
add_kb(userconfig, kb_group, keys);
260
keys = g_key_file_get_keys(sysconfig, kb_group, NULL, NULL);
261
add_kb(sysconfig, kb_group, keys);
266
void editor_snippets_init(void)
268
gchar *sysconfigfile, *userconfigfile;
269
GKeyFile *sysconfig = g_key_file_new();
270
GKeyFile *userconfig = g_key_file_new();
272
snippet_offsets = g_queue_new();
274
sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S, "snippets.conf", NULL);
275
userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "snippets.conf", NULL);
277
/* check for old autocomplete.conf files (backwards compatibility) */
278
if (! g_file_test(userconfigfile, G_FILE_TEST_IS_REGULAR))
279
setptr(userconfigfile,
280
g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "autocomplete.conf", NULL));
282
/* load the actual config files */
283
g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
284
g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
286
snippets_load(sysconfig, userconfig);
288
/* setup snippet keybindings */
289
snippet_accel_group = gtk_accel_group_new();
290
gtk_window_add_accel_group(GTK_WINDOW(main_widgets.window), snippet_accel_group);
291
load_kb(sysconfig, userconfig);
198
293
g_free(sysconfigfile);
199
294
g_free(userconfigfile);
200
g_strfreev(groups_sys);
201
g_strfreev(groups_user);
202
295
g_key_file_free(sysconfig);
203
296
g_key_file_free(userconfig);
290
383
case 1: /* use global settings */
292
385
case 2: /* custom (enabled) */
293
return editor_prefs.long_line_global_type;
386
return editor_prefs.long_line_type;
296
if (!editor_prefs.long_line_global_enabled)
389
if (!editor_prefs.long_line_enabled)
299
return editor_prefs.long_line_global_type;
392
return editor_prefs.long_line_type;
303
gint editor_get_long_line_column(void)
396
static gint editor_get_long_line_column(void)
305
398
if (app->project && app->project->long_line_behaviour != 1 /* use global settings */)
306
399
return app->project->long_line_column;
308
return editor_prefs.long_line_global_column;
401
return editor_prefs.long_line_column;
405
static const GeanyEditorPrefs *
406
get_default_prefs(void)
408
static GeanyEditorPrefs eprefs;
410
eprefs = editor_prefs;
412
/* project overrides */
413
eprefs.indentation = (GeanyIndentPrefs*)editor_get_indent_prefs(NULL);
414
eprefs.long_line_type = editor_get_long_line_type();
415
eprefs.long_line_column = editor_get_long_line_column();
420
/* Gets the prefs for the editor.
421
* Prefs can be different according to project or document.
422
* @warning Always get a fresh result instead of keeping a pointer to it if the editor/project
423
* settings may have changed, or if this function has been called for a different editor.
424
* @param editor The editor, or @c NULL to get the default prefs.
425
* @return The prefs. */
426
const GeanyEditorPrefs *editor_get_prefs(GeanyEditor *editor)
428
static GeanyEditorPrefs eprefs;
429
const GeanyEditorPrefs *dprefs = get_default_prefs();
431
/* Return the address of the default prefs to allow returning default and editor
432
* pref pointers without invalidating the contents of either. */
437
eprefs.indentation = (GeanyIndentPrefs*)editor_get_indent_prefs(editor);
438
/* add other editor & document overrides as needed */
3340
/* Checks whether the given style is a string for the given lexer.
3341
* It doesn't handle LEX_HTML, this should be done by the caller.
3342
* Returns true if the style is a string, FALSE otherwise.
3344
* Don't forget STRINGEOL, to prevent completion whilst typing a string with no closing char.
3346
static gboolean is_string_style(gint lexer, gint style)
3351
return (style == SCE_C_CHARACTER ||
3352
style == SCE_C_STRING ||
3353
style == SCE_C_STRINGEOL);
3356
return (style == SCE_PAS_CHARACTER ||
3357
style == SCE_PAS_STRING ||
3358
style == SCE_PAS_STRINGEOL);
3361
return (style == SCE_D_STRING ||
3362
style == SCE_D_STRINGEOL ||
3363
style == SCE_D_CHARACTER ||
3364
style == SCE_D_STRINGB ||
3365
style == SCE_D_STRINGR);
3368
return (style == SCE_P_STRING ||
3369
style == SCE_P_TRIPLE ||
3370
style == SCE_P_TRIPLEDOUBLE ||
3371
style == SCE_P_CHARACTER ||
3372
style == SCE_P_STRINGEOL);
3376
return (style == SCE_F_STRING1 ||
3377
style == SCE_F_STRING2 ||
3378
style == SCE_F_STRINGEOL);
3381
return (/*style == SCE_PL_STRING ||*/ /* may want variable autocompletion "$(foo)" */
3382
style == SCE_PL_CHARACTER ||
3383
style == SCE_PL_HERE_DELIM ||
3384
style == SCE_PL_HERE_Q ||
3385
style == SCE_PL_HERE_QQ ||
3386
style == SCE_PL_HERE_QX ||
3387
style == SCE_PL_POD ||
3388
style == SCE_PL_STRING_Q ||
3389
style == SCE_PL_STRING_QQ ||
3390
style == SCE_PL_STRING_QX ||
3391
style == SCE_PL_STRING_QR ||
3392
style == SCE_PL_STRING_QW ||
3393
style == SCE_PL_POD_VERB);
3396
return (style == SCE_R_STRING);
3399
return (style == SCE_RB_CHARACTER ||
3400
style == SCE_RB_STRING ||
3401
style == SCE_RB_HERE_DELIM ||
3402
style == SCE_RB_HERE_Q ||
3403
style == SCE_RB_HERE_QQ ||
3404
style == SCE_RB_HERE_QX ||
3405
style == SCE_RB_POD);
3408
return (style == SCE_SH_STRING);
3411
return (style == SCE_SQL_STRING);
3414
return (style == SCE_TCL_IN_QUOTE);
3417
return (style == SCE_LUA_LITERALSTRING ||
3418
style == SCE_LUA_CHARACTER ||
3419
style == SCE_LUA_STRINGEOL ||
3420
style == SCE_LUA_STRING);
3423
return (style == SCE_HA_CHARACTER ||
3424
style == SCE_HA_STRING);
3426
case SCLEX_FREEBASIC:
3427
return (style == SCE_B_STRING ||
3428
style == SCE_B_STRINGEOL);
3431
return (style == SCE_MATLAB_STRING ||
3432
style == SCE_MATLAB_DOUBLEQUOTESTRING);
3436
style == SCE_HBA_STRING ||
3437
style == SCE_HBA_STRINGEOL ||
3438
style == SCE_HB_STRING ||
3439
style == SCE_HB_STRINGEOL ||
3440
style == SCE_H_CDATA ||
3441
style == SCE_H_DOUBLESTRING ||
3442
style == SCE_HJA_DOUBLESTRING ||
3443
style == SCE_HJA_SINGLESTRING ||
3444
style == SCE_HJA_STRINGEOL ||
3445
style == SCE_HJ_DOUBLESTRING ||
3446
style == SCE_HJ_SINGLESTRING ||
3447
style == SCE_HJ_STRINGEOL ||
3448
style == SCE_HPA_CHARACTER ||
3449
style == SCE_HPA_STRING ||
3450
style == SCE_HPA_TRIPLE ||
3451
style == SCE_HPA_TRIPLEDOUBLE ||
3452
style == SCE_HP_CHARACTER ||
3453
style == SCE_HPHP_HSTRING ||
3454
style == SCE_HPHP_HSTRING || /* HSTRING is a heredoc */
3455
style == SCE_HPHP_HSTRING_VARIABLE ||
3456
style == SCE_HPHP_SIMPLESTRING ||
3457
style == SCE_HPHP_SIMPLESTRING ||
3458
style == SCE_HP_STRING ||
3459
style == SCE_HP_TRIPLE ||
3460
style == SCE_HP_TRIPLEDOUBLE ||
3461
style == SCE_H_SGML_DOUBLESTRING ||
3462
style == SCE_H_SGML_SIMPLESTRING ||
3463
style == SCE_H_SINGLESTRING);
3466
return (style == SCE_CMAKE_STRINGDQ ||
3467
style == SCE_CMAKE_STRINGLQ ||
3468
style == SCE_CMAKE_STRINGRQ ||
3469
style == SCE_CMAKE_STRINGVAR);
3472
return (style == SCE_NSIS_STRINGDQ ||
3473
style == SCE_NSIS_STRINGLQ ||
3474
style == SCE_NSIS_STRINGRQ ||
3475
style == SCE_NSIS_STRINGVAR);
3478
return (style == SCE_ADA_CHARACTER ||
3479
style == SCE_ADA_STRING ||
3480
style == SCE_ADA_CHARACTEREOL ||
3481
style == SCE_ADA_STRINGEOL);
3487
/* Checks whether the given style is a comment for the given lexer.
3488
* It doesn't handle LEX_HTML, this should be done by the caller.
3489
* Returns true if the style is a comment, FALSE otherwise.
3491
static gboolean is_comment_style(gint lexer, gint style)
3496
return (style == SCE_C_COMMENT ||
3497
style == SCE_C_COMMENTLINE ||
3498
style == SCE_C_COMMENTDOC ||
3499
style == SCE_C_COMMENTLINEDOC ||
3500
style == SCE_C_COMMENTDOCKEYWORD ||
3501
style == SCE_C_COMMENTDOCKEYWORDERROR);
3504
return (style == SCE_PAS_COMMENT ||
3505
style == SCE_PAS_COMMENT2 ||
3506
style == SCE_PAS_COMMENTLINE);
3509
return (style == SCE_D_COMMENT ||
3510
style == SCE_D_COMMENTLINE ||
3511
style == SCE_D_COMMENTDOC ||
3512
style == SCE_D_COMMENTNESTED ||
3513
style == SCE_D_COMMENTLINEDOC ||
3514
style == SCE_D_COMMENTDOCKEYWORD ||
3515
style == SCE_D_COMMENTDOCKEYWORDERROR);
3518
return (style == SCE_P_COMMENTLINE ||
3519
style == SCE_P_COMMENTBLOCK);
3523
return (style == SCE_F_COMMENT);
3526
return (style == SCE_PL_COMMENTLINE);
3528
case SCLEX_PROPERTIES:
3529
return (style == SCE_PROPS_COMMENT);
3532
return (style == SCE_PO_COMMENT);
3535
return (style == SCE_L_COMMENT);
3537
case SCLEX_MAKEFILE:
3538
return (style == SCE_MAKE_COMMENT);
3541
return (style == SCE_RB_COMMENTLINE);
3544
return (style == SCE_SH_COMMENTLINE);
3547
return (style == SCE_R_COMMENT);
3550
return (style == SCE_SQL_COMMENT ||
3551
style == SCE_SQL_COMMENTLINE ||
3552
style == SCE_SQL_COMMENTDOC);
3555
return (style == SCE_TCL_COMMENT ||
3556
style == SCE_TCL_COMMENTLINE ||
3557
style == SCE_TCL_COMMENT_BOX ||
3558
style == SCE_TCL_BLOCK_COMMENT);
3561
return (style == SCE_MATLAB_COMMENT);
3564
return (style == SCE_LUA_COMMENT ||
3565
style == SCE_LUA_COMMENTLINE ||
3566
style == SCE_LUA_COMMENTDOC);
3569
return (style == SCE_HA_COMMENTLINE ||
3570
style == SCE_HA_COMMENTBLOCK ||
3571
style == SCE_HA_COMMENTBLOCK2 ||
3572
style == SCE_HA_COMMENTBLOCK3);
3574
case SCLEX_FREEBASIC:
3575
return (style == SCE_B_COMMENT);
3578
return (style == SCE_YAML_COMMENT);
3582
style == SCE_HBA_COMMENTLINE ||
3583
style == SCE_HB_COMMENTLINE ||
3584
style == SCE_H_COMMENT ||
3585
style == SCE_HJA_COMMENT ||
3586
style == SCE_HJA_COMMENTDOC ||
3587
style == SCE_HJA_COMMENTLINE ||
3588
style == SCE_HJ_COMMENT ||
3589
style == SCE_HJ_COMMENTDOC ||
3590
style == SCE_HJ_COMMENTLINE ||
3591
style == SCE_HPA_COMMENTLINE ||
3592
style == SCE_HP_COMMENTLINE ||
3593
style == SCE_HPHP_COMMENT ||
3594
style == SCE_HPHP_COMMENTLINE ||
3595
style == SCE_H_SGML_COMMENT);
3598
return (style == SCE_CMAKE_COMMENT);
3601
return (style == SCE_NSIS_COMMENT ||
3602
style == SCE_NSIS_COMMENTBOX);
3605
return (style == SCE_ADA_COMMENTLINE ||
3606
style == SCE_NSIS_COMMENTBOX);
3612
/* Checks whether the given style is normal code (not string, comment, preprocessor, etc).
3613
* It doesn't handle LEX_HTML, this should be done by the caller.
3615
static gboolean is_code_style(gint lexer, gint style)
3620
if (style == SCE_C_PREPROCESSOR)
3624
return !(is_comment_style(lexer, style) ||
3625
is_string_style(lexer, style));
3630
3466
static gboolean editor_lexer_is_c_like(gint lexer)
3831
/* find the start or end of a paragraph by searching all lines in direction (UP or DOWN)
3832
* starting at the given line and return the found line or return -1 if called on an empty line */
3666
static gboolean sci_is_blank_line(ScintillaObject *sci, gint line)
3668
return sci_get_line_indent_position(sci, line) ==
3669
sci_get_line_end_position(sci, line);
3673
/* Returns first line of paragraph for GTK_DIR_UP, line after paragraph
3674
* ends for GTK_DIR_DOWN or -1 if called on an empty line. */
3833
3675
static gint find_paragraph_stop(GeanyEditor *editor, gint line, gint direction)
3835
gboolean found_end = FALSE;
3837
gchar *line_buf, *x;
3838
3678
ScintillaObject *sci = editor->sci;
3840
3680
/* first check current line and return -1 if it is empty to skip creating of a selection */
3841
line_buf = x = sci_get_line(sci, line);
3681
if (sci_is_blank_line(sci, line))
3850
3684
if (direction == GTK_DIR_UP)
3859
/* sci_get_line checks for sanity of the given line, sci_get_line always return a string
3860
* containing at least '\0' so no need to check for NULL */
3861
line_buf = x = sci_get_line(sci, line);
3863
/* check whether after skipping all whitespace we are at end of line and if so, assume
3864
* this line as end of paragraph */
3871
/* called on the first line but there is no previous line so return line 0 */
3694
/* start of document */
3698
if (line == sci_get_line_count(sci))
3701
if (sci_is_blank_line(sci, line))
3703
/* return line paragraph starts on */
3704
if (direction == GTK_DIR_UP)
3734
/* Returns first line of block for GTK_DIR_UP, line after block
3735
* ends for GTK_DIR_DOWN or -1 if called on an empty line. */
3736
static gint find_block_stop(GeanyEditor *editor, gint line, gint direction)
3739
ScintillaObject *sci = editor->sci;
3741
/* first check current line and return -1 if it is empty to skip creating of a selection */
3742
if (sci_is_blank_line(sci, line))
3745
if (direction == GTK_DIR_UP)
3750
ind = sci_get_line_indentation(sci, line);
3756
/* start of document */
3760
if (line == sci_get_line_count(sci))
3763
if (sci_get_line_indentation(sci, line) != ind ||
3764
sci_is_blank_line(sci, line))
3766
/* return line block starts on */
3767
if (direction == GTK_DIR_UP)
3776
void editor_select_indent_block(GeanyEditor *editor)
3778
gint pos_start, pos_end, line_start, line_found;
3780
g_return_if_fail(editor != NULL);
3782
line_start = sci_get_current_line(editor->sci);
3784
line_found = find_block_stop(editor, line_start, GTK_DIR_UP);
3785
if (line_found == -1)
3788
pos_start = SSM(editor->sci, SCI_POSITIONFROMLINE, line_found, 0);
3790
line_found = find_block_stop(editor, line_start, GTK_DIR_DOWN);
3791
pos_end = SSM(editor->sci, SCI_POSITIONFROMLINE, line_found, 0);
3793
sci_set_selection(editor->sci, pos_start, pos_end);
3907
3797
/* simple indentation to indent the current line with the same indent as the previous one */
3908
3798
static void smart_line_indentation(GeanyEditor *editor, gint first_line, gint last_line)