283
288
ft->name = g_strdup("Txt2tags");
284
289
filetype_make_title(ft, TITLE_SOURCE_FILE);
285
290
ft->mime_type = g_strdup("text/x-txt2tags");
286
ft->group = GEANY_FILETYPE_GROUP_MISC;
291
ft->group = GEANY_FILETYPE_GROUP_MARKUP;
289
294
ft = filetypes[GEANY_FILETYPES_ABC];
291
296
ft->name = g_strdup("Abc");
292
filetype_make_title(ft, TITLE_SOURCE_FILE);
297
filetype_make_title(ft, TITLE_FILE);
293
298
ft->group = GEANY_FILETYPE_GROUP_MISC;
296
301
ft = filetypes[GEANY_FILETYPES_SH];
298
303
ft->name = g_strdup("Sh");
299
ft->title = g_strdup(_("Shell script file"));
304
ft->title = g_strdup(_("Shell script"));
300
305
ft->mime_type = g_strdup("application/x-shellscript");
301
306
ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
343
348
ft = filetypes[GEANY_FILETYPES_SQL];
345
350
ft->name = g_strdup("SQL");
346
ft->title = g_strdup(_("SQL Dump file"));
351
filetype_make_title(ft, TITLE_FILE);
347
352
ft->mime_type = g_strdup("text/x-sql");
348
353
ft->group = GEANY_FILETYPE_GROUP_MISC;
356
ft = filetypes[GEANY_FILETYPES_COBOL];
358
ft->name = g_strdup("COBOL");
359
filetype_make_title(ft, TITLE_SOURCE_FILE);
360
ft->mime_type = g_strdup("text/x-cobol");
361
ft->group = GEANY_FILETYPE_GROUP_COMPILED;
351
364
ft = filetypes[GEANY_FILETYPES_LATEX];
353
366
ft->name = g_strdup("LaTeX");
354
367
filetype_make_title(ft, TITLE_SOURCE_FILE);
355
368
ft->mime_type = g_strdup("text/x-tex");
356
ft->group = GEANY_FILETYPE_GROUP_MISC;
369
ft->group = GEANY_FILETYPE_GROUP_MARKUP;
359
372
ft = filetypes[GEANY_FILETYPES_VHDL];
501
520
if (G_UNLIKELY(ft2->id == GEANY_FILETYPES_NONE))
504
return utils_str_casecmp(ft1->title, ft2->title);
524
utils_str_casecmp(ft1->name, ft2->name) :
525
utils_str_casecmp(ft1->title, ft2->title);
529
/** Gets a list of filetype pointers sorted by name.
530
* The list does not change on subsequent calls.
531
* @return The list - do not free.
532
* @see filetypes_by_title. */
533
const GSList *filetypes_get_sorted_by_name(void)
535
static GSList *list = NULL;
537
g_return_val_if_fail(filetypes_by_title, NULL);
541
list = g_slist_copy(filetypes_by_title);
542
list = g_slist_sort_with_data(list, cmp_filetype, GINT_TO_POINTER(TRUE));
598
637
filetype_add(filetypes[ft_id]);
600
639
init_custom_filetypes(app->datadir);
601
init_custom_filetypes(utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, NULL));
640
f = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, NULL);
641
init_custom_filetypes(f);
603
644
/* sort last instead of on insertion to prevent exponential time */
604
filetypes_by_title = g_slist_sort(filetypes_by_title, cmp_filetype);
645
filetypes_by_title = g_slist_sort_with_data(filetypes_by_title,
646
cmp_filetype, GINT_TO_POINTER(FALSE));
648
read_filetype_config();
608
652
static void on_document_save(G_GNUC_UNUSED GObject *object, GeanyDocument *doc)
610
656
g_return_if_fail(NZV(doc->real_path));
612
if (utils_str_equal(doc->real_path,
613
utils_build_path(app->configdir, "filetype_extensions.conf", NULL)))
614
filetypes_read_extensions();
615
else if (utils_str_equal(doc->real_path,
616
utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL)))
658
f = utils_build_path(app->configdir, "filetype_extensions.conf", NULL);
659
if (utils_str_equal(doc->real_path, f))
660
filetypes_reload_extensions();
663
f = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL);
664
if (utils_str_equal(doc->real_path, f))
624
672
foreach_document(i)
625
673
document_reload_config(documents[i]);
630
679
static void setup_config_file_menus(void)
632
ui_add_config_file_menu_item(
633
utils_build_path(app->configdir, "filetype_extensions.conf", NULL), NULL, NULL);
634
ui_add_config_file_menu_item(
635
utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL), NULL, NULL);
683
f = utils_build_path(app->configdir, "filetype_extensions.conf", NULL);
684
ui_add_config_file_menu_item(f, NULL, NULL);
685
setptr(f, utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL));
686
ui_add_config_file_menu_item(f, NULL, NULL);
637
689
g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL);
1113
static void load_indent_settings(GeanyFiletype *ft, GKeyFile *config, GKeyFile *configh)
1115
ft->indent_width = utils_get_setting(integer, configh, config, "indentation", "width", -1);
1116
ft->indent_type = utils_get_setting(integer, configh, config, "indentation", "type", -1);
1117
/* check whether the indent type is OK */
1118
switch (ft->indent_type)
1120
case GEANY_INDENT_TYPE_TABS:
1121
case GEANY_INDENT_TYPE_SPACES:
1122
case GEANY_INDENT_TYPE_BOTH:
1127
g_warning("Invalid indent type %d in file type %s", ft->indent_type, ft->name);
1128
ft->indent_type = -1;
1067
1134
static void load_settings(gint ft_id, GKeyFile *config, GKeyFile *configh)
1069
1136
GeanyFiletype *ft = filetypes[ft_id];
1071
GError *error = NULL;
1074
1139
/* default extension */
1075
result = g_key_file_get_string(configh, "settings", "extension", NULL);
1076
if (result == NULL) result = g_key_file_get_string(config, "settings", "extension", NULL);
1077
if (G_LIKELY(result != NULL))
1140
result = utils_get_setting(string, configh, config, "settings", "extension", NULL);
1079
1143
setptr(filetypes[ft_id]->extension, result);
1082
1146
/* read comment notes */
1083
result = g_key_file_get_string(configh, "settings", "comment_open", NULL);
1084
if (result == NULL) result = g_key_file_get_string(config, "settings", "comment_open", NULL);
1085
if (G_LIKELY(result != NULL))
1087
g_free(filetypes[ft_id]->comment_open);
1088
filetypes[ft_id]->comment_open = result;
1091
result = g_key_file_get_string(configh, "settings", "comment_close", NULL);
1092
if (result == NULL) result = g_key_file_get_string(config, "settings", "comment_close", NULL);
1093
if (G_LIKELY(result != NULL))
1095
g_free(filetypes[ft_id]->comment_close);
1096
filetypes[ft_id]->comment_close = result;
1099
tmp = g_key_file_get_boolean(configh, "settings", "comment_use_indent", &error);
1102
g_error_free(error);
1104
tmp = g_key_file_get_boolean(config, "settings", "comment_use_indent", &error);
1105
if (error) g_error_free(error);
1106
else filetypes[ft_id]->comment_use_indent = tmp;
1108
else filetypes[ft_id]->comment_use_indent = tmp;
1147
result = utils_get_setting(string, configh, config, "settings", "comment_open", NULL);
1150
setptr(filetypes[ft_id]->comment_open, result);
1153
result = utils_get_setting(string, configh, config, "settings", "comment_close", NULL);
1156
setptr(filetypes[ft_id]->comment_close, result);
1159
result = utils_get_setting(string, configh, config, "settings", "comment_single", NULL);
1162
setptr(filetypes[ft_id]->comment_single, result);
1164
/* import correctly filetypes that use old-style single comments */
1165
else if (! NZV(filetypes[ft_id]->comment_close))
1167
setptr(filetypes[ft_id]->comment_single, filetypes[ft_id]->comment_open);
1168
filetypes[ft_id]->comment_open = NULL;
1171
filetypes[ft_id]->comment_use_indent = utils_get_setting(boolean, configh, config,
1172
"settings", "comment_use_indent", FALSE);
1110
1174
/* read context action */
1111
result = g_key_file_get_string(configh, "settings", "context_action_cmd", NULL);
1112
if (result == NULL) result = g_key_file_get_string(config, "settings", "context_action_cmd", NULL);
1113
if (G_LIKELY(result != NULL))
1175
result = utils_get_setting(string, configh, config, "settings", "context_action_cmd", NULL);
1115
1178
setptr(filetypes[ft_id]->context_action_cmd, result);
1118
result = utils_get_setting_string(configh, "settings", "tag_parser", NULL);
1120
result = utils_get_setting_string(config, "settings", "tag_parser", NULL);
1181
result = utils_get_setting(string, configh, config, "settings", "tag_parser", NULL);
1123
1184
ft->lang = tm_source_file_get_named_lang(result);
1124
1185
if (ft->lang < 0)
1142
1201
ft->priv->xml_indent_tags = utils_get_setting(boolean, configh, config, "settings",
1143
1202
"xml_indent_tags", FALSE);
1204
/* read indent settings */
1205
load_indent_settings(ft, config, configh);
1145
1207
/* read build settings */
1146
1208
build_load_menu(config, GEANY_BCS_FT, (gpointer)ft);
1147
1209
build_load_menu(configh, GEANY_BCS_HOME_FT, (gpointer)ft);
1213
static void add_keys(GKeyFile *dest, const gchar *group, GKeyFile *src)
1215
gchar **keys = g_key_file_get_keys(src, group, NULL, NULL);
1218
foreach_strv(ptr, keys)
1221
gchar *value = g_key_file_get_value(src, group, key, NULL);
1223
g_key_file_set_value(dest, group, key, value);
1230
static gchar *filetypes_get_filename(GeanyFiletype *ft, gboolean user)
1232
gchar *ext = filetypes_get_conf_extension(ft);
1236
f = utils_make_filename(app->configdir,
1237
GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S, "filetypes.", ext, NULL);
1239
f = utils_make_filename(app->datadir, "filetypes.", ext, NULL);
1246
static void add_group_keys(GKeyFile *kf, const gchar *group, GeanyFiletype *ft)
1249
gboolean loaded = FALSE;
1252
files[0] = filetypes_get_filename(ft, FALSE);
1253
files[1] = filetypes_get_filename(ft, TRUE);
1255
for (i = 0; i < G_N_ELEMENTS(files); i++)
1257
GKeyFile *src = g_key_file_new();
1259
if (g_key_file_load_from_file(src, files[i], G_KEY_FILE_NONE, NULL))
1261
add_keys(kf, group, src);
1264
g_key_file_free(src);
1268
geany_debug("Could not read config file %s for [%s=%s]!", files[0], group, ft->name);
1275
static void copy_ft_groups(GKeyFile *kf)
1277
gchar **groups = g_key_file_get_groups(kf, NULL);
1280
foreach_strv(ptr, groups)
1282
gchar *group = *ptr;
1283
gchar *name = strstr(*ptr, "=");
1289
/* terminate group at '=' */
1295
ft = filetypes_lookup_by_name(name);
1297
add_group_keys(kf, group, ft);
1151
1303
/* simple wrapper function to print file errors in DEBUG mode */
1152
1304
static void load_system_keyfile(GKeyFile *key_file, const gchar *file, GKeyFileFlags flags,
1153
1305
GeanyFiletype *ft)
1193
1345
config_home = g_key_file_new();
1195
1347
/* highlighting uses GEANY_FILETYPES_NONE for common settings */
1196
gchar *ext = filetypes_get_conf_extension(ft_id);
1197
gchar *f0 = g_strconcat(app->datadir, G_DIR_SEPARATOR_S "filetypes.", ext, NULL);
1198
gchar *f = g_strconcat(app->configdir,
1199
G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", ext, NULL);
1201
load_system_keyfile(config, f0, G_KEY_FILE_KEEP_COMMENTS, ft);
1350
f = filetypes_get_filename(ft, FALSE);
1351
load_system_keyfile(config, f, G_KEY_FILE_KEEP_COMMENTS, ft);
1353
setptr(f, filetypes_get_filename(ft, TRUE));
1202
1354
g_key_file_load_from_file(config_home, f, G_KEY_FILE_KEEP_COMMENTS, NULL);
1357
/* Copy keys for any groups with [group=C] from system keyfile */
1358
copy_ft_groups(config);
1359
copy_ft_groups(config_home);
1209
1361
load_settings(ft_id, config, config_home);
1210
1362
highlighting_init_styles(ft_id, config, config_home);
1217
gchar *filetypes_get_conf_extension(gint filetype_idx)
1369
static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft)
1219
gchar *result, *ptr;
1220
GeanyFiletype *ft = filetypes[filetype_idx];
1222
1373
if (ft->priv->custom)
1223
1374
return g_strconcat(ft->name, ".conf", NULL);
1225
1376
/* Handle any special extensions different from lowercase filetype->name */
1226
switch (filetype_idx)
1228
1379
case GEANY_FILETYPES_CPP: result = g_strdup("cpp"); break;
1229
1380
case GEANY_FILETYPES_CS: result = g_strdup("cs"); break;
1230
1381
case GEANY_FILETYPES_MAKE: result = g_strdup("makefile"); break;
1231
1382
case GEANY_FILETYPES_NONE: result = g_strdup("common"); break;
1383
/* name is Matlab/Octave */
1384
case GEANY_FILETYPES_MATLAB: result = g_strdup("matlab"); break;
1233
1386
result = g_ascii_strdown(ft->name, -1);
1234
/* truncate at slash (e.g. for Matlab/Octave) */
1235
ptr = strstr(result, "/");
1244
void filetypes_save_commands(void)
1393
void filetypes_save_commands(GeanyFiletype *ft)
1246
gchar *conf_prefix = g_strconcat(app->configdir,
1247
G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", NULL);
1250
for (i = 0; i < filetypes_array->len; i++)
1252
GKeyFile *config_home;
1253
gchar *fname, *ext, *data;
1255
if (filetypes[i]->home_save_needed)
1257
ext = filetypes_get_conf_extension(i);
1258
fname = g_strconcat(conf_prefix, ext, NULL);
1260
config_home = g_key_file_new();
1261
g_key_file_load_from_file(config_home, fname, G_KEY_FILE_KEEP_COMMENTS, NULL);
1262
build_save_menu(config_home, (gpointer)(filetypes[i]), GEANY_BCS_HOME_FT);
1263
data = g_key_file_to_data(config_home, NULL, NULL);
1264
utils_write_file(fname, data);
1266
g_key_file_free(config_home);
1270
g_free(conf_prefix);
1395
GKeyFile *config_home;
1396
gchar *fname, *data;
1398
fname = filetypes_get_filename(ft, TRUE);
1399
config_home = g_key_file_new();
1400
g_key_file_load_from_file(config_home, fname, G_KEY_FILE_KEEP_COMMENTS, NULL);
1401
build_save_menu(config_home, ft, GEANY_BCS_HOME_FT);
1402
data = g_key_file_to_data(config_home, NULL, NULL);
1403
utils_write_file(fname, data);
1405
g_key_file_free(config_home);
1455
void filetypes_read_extensions(void)
1591
static void read_extensions(GKeyFile *sysconfig, GKeyFile *userconfig)
1459
gchar *sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S,
1460
"filetype_extensions.conf", NULL);
1461
gchar *userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S,
1462
"filetype_extensions.conf", NULL);
1463
GKeyFile *sysconfig = g_key_file_new();
1464
GKeyFile *userconfig = g_key_file_new();
1466
g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
1467
g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
1469
1596
/* read the keys */
1470
1597
for (i = 0; i < filetypes_array->len; i++)
1484
1611
convert_filetype_extensions_to_lower_case(filetypes[i]->pattern, len);
1617
static void read_group(GKeyFile *config, const gchar *group_name, gint group_id)
1619
gchar **names = g_key_file_get_string_list(config, "Groups", group_name, NULL, NULL);
1622
foreach_strv(name, names)
1624
GeanyFiletype *ft = filetypes_lookup_by_name(*name);
1628
ft->group = group_id;
1629
if (ft->priv->custom &&
1630
(group_id == GEANY_FILETYPE_GROUP_COMPILED || group_id == GEANY_FILETYPE_GROUP_SCRIPT))
1632
setptr(ft->title, NULL);
1633
filetype_make_title(ft, TITLE_SOURCE_FILE);
1637
geany_debug("Filetype '%s' not found for group '%s'!", *name, group_name);
1643
static void read_groups(GKeyFile *config)
1645
read_group(config, "Programming", GEANY_FILETYPE_GROUP_COMPILED);
1646
read_group(config, "Script", GEANY_FILETYPE_GROUP_SCRIPT);
1647
read_group(config, "Markup", GEANY_FILETYPE_GROUP_MARKUP);
1648
read_group(config, "Misc", GEANY_FILETYPE_GROUP_MISC);
1649
read_group(config, "None", GEANY_FILETYPE_GROUP_NONE);
1653
static void read_filetype_config(void)
1655
gchar *sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S,
1656
"filetype_extensions.conf", NULL);
1657
gchar *userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S,
1658
"filetype_extensions.conf", NULL);
1659
GKeyFile *sysconfig = g_key_file_new();
1660
GKeyFile *userconfig = g_key_file_new();
1662
g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
1663
g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
1665
read_extensions(sysconfig, userconfig);
1666
read_groups(sysconfig);
1667
read_groups(userconfig);
1488
1669
g_free(sysconfigfile);
1489
1670
g_free(userconfigfile);
1490
1671
g_key_file_free(sysconfig);
1491
1672
g_key_file_free(userconfig);
1676
void filetypes_reload_extensions(void)
1680
read_filetype_config();
1493
1682
/* Redetect filetype of any documents with none set */
1494
1683
foreach_document(i)