Add support for generating global tags files for non-C-like

filetypes.


git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1480 ea778897-0a13-0410-b9d1-a72fbfd435f5
master
Nick Treleaven 2007-04-27 11:00:29 +00:00
parent 3489b63b7d
commit f39df4005f
5 changed files with 156 additions and 66 deletions

View File

@ -1,3 +1,14 @@
2007-04-26 Nick Treleaven <nick.treleaven@btinternet.com>
* tagmanager/tm_source_file.c, tagmanager/include/tm_source_file.h:
Add tm_source_file_get_lang_name() as a wrapper for getLanguageName()
in parse.c.
* src/main.c, src/symbols.c, tagmanager/tm_workspace.c,
tagmanager/include/tm_workspace.h:
Add support for generating global tags files for non-C-like
filetypes.
2007-04-25 Nick Treleaven <nick.treleaven@btinternet.com>
* src/filetypes.c, src/filetypes.h, src/main.c:

View File

@ -467,6 +467,8 @@ static void parse_command_line_options(gint *argc, gchar ***argv)
{
gboolean ret;
filetypes_init_types();
configuration_read_filetype_extensions(); // needed for *.lang.tags filetype matching
ret = symbols_generate_global_tags(*argc, *argv);
exit(ret);
}

View File

@ -704,10 +704,33 @@ gboolean symbols_recreate_tag_list(gint idx)
}
/* Detects a global tags filetype from the *.lang.* language extension.
* Returns NULL if there was no matching TM language. */
static filetype *detect_global_tags_filetype(const gchar *utf8_filename)
{
gchar *tags_ext;
gchar *shortname = g_strdup(utf8_filename);
filetype *ft = NULL;
tags_ext = strstr(shortname, ".tags");
if (tags_ext)
{
*tags_ext = '\0'; // remove .tags extension
ft = filetypes_detect_from_filename(shortname);
}
g_free(shortname);
if (filetypes[FILETYPE_ID(ft)]->lang < 0)
return NULL;
return ft;
}
/* Adapted from anjuta-2.0.2/global-tags/tm_global_tags.c, thanks.
* Needs full path and \" quoting characters around filenames.
* Needs full paths for filenames, except for C/C++ tag files, when CFLAGS includes
* the relevant path.
* Example:
* geany -g tagsfile \"/home/nmt/svn/geany/src/d*.h\" */
* CFLAGS=-I/home/user/libname-1.x geany -g libname.d.tags libname.h */
int symbols_generate_global_tags(int argc, char **argv)
{
/* -E pre-process, -dD output user macros, -p prof info (?),
@ -719,15 +742,34 @@ int symbols_generate_global_tags(int argc, char **argv)
/* Create global taglist */
int status;
char *command;
command = g_strdup_printf("%s %s", pre_process,
NVL(getenv("CFLAGS"), ""));
//printf(">%s<\n", command);
const char *tags_file = argv[1];
char *utf8_fname;
filetype *ft;
utf8_fname = utils_get_utf8_from_locale(tags_file);
ft = detect_global_tags_filetype(utf8_fname);
g_free(utf8_fname);
if (ft == NULL)
{
fprintf(stderr, "Unknown filetype extension for \"%s\".\n", tags_file);
return 1;
}
if (ft->lang == 0 || ft->lang == 1) /* C/C++ */
command = g_strdup_printf("%s %s", pre_process, NVL(getenv("CFLAGS"), ""));
else
command = NULL; // don't preprocess
geany_debug("Generating %s tags file.", ft->name);
status = tm_workspace_create_global_tags(command,
(const char **) (argv + 2),
argc - 2, argv[1]);
argc - 2, tags_file, ft->lang);
g_free(command);
if (!status)
if (! status)
{
fprintf(stderr, "Failed to create tags file.\n");
return 1;
}
}
else
{
@ -741,34 +783,6 @@ int symbols_generate_global_tags(int argc, char **argv)
}
// fname should be in locale encoding
static gboolean load_tags_filename(const gchar *fname)
{
gchar *tags_ext;
gchar *shortname = g_strdup(fname);
gboolean ret = FALSE;
tags_ext = strstr(shortname, ".tags");
if (tags_ext)
{
gchar *utf8_shortname;
filetype *ft;
*tags_ext = '\0'; // remove .tags extension
utf8_shortname = utils_get_utf8_from_locale(shortname);
ft = filetypes_detect_from_filename(utf8_shortname);
g_free(utf8_shortname);
if (ft)
{
ret = tm_workspace_load_global_tags(fname, ft->lang);
}
}
g_free(shortname);
return ret;
}
void symbols_show_load_tags_dialog()
{
GtkWidget *dialog;
@ -793,13 +807,16 @@ void symbols_show_load_tags_dialog()
{
gchar *fname = item->data;
gchar *utf8_fname;
gboolean ok;
ok = load_tags_filename(fname);
filetype *ft;
utf8_fname = utils_get_utf8_from_locale(fname);
msgwin_status_add(ok ? _("Loaded tags file '%s'.") :
_("Could not load tags file '%s'."), utf8_fname);
ft = detect_global_tags_filetype(utf8_fname);
if (ft != NULL && tm_workspace_load_global_tags(fname, ft->lang))
msgwin_status_add(_("Loaded %s tags file '%s'."), ft->name, utf8_fname);
else
msgwin_status_add(_("Could not load tags file '%s'."), utf8_fname);
g_free(utf8_fname);
g_free(fname);
}

View File

@ -100,10 +100,11 @@ gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode);
\param includes Include files to process. Wildcards such as '/usr/include/a*.h'
are allowed.
\param tags_file The file where the tags will be stored.
\param lang The language to use for the tags file.
\return TRUE on success, FALSE on failure.
*/
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
, int includes_count, const char *tags_file);
, int includes_count, const char *tags_file, int lang);
/*! Recreates the tag array of the workspace by collecting the tags of
all member work objects. You shouldn't have to call this directly since

View File

@ -187,8 +187,68 @@ static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer use
*pp_list = g_list_prepend(*pp_list, value);
}
static void write_includes_file(FILE *fp, GList *includes_files)
{
GList *node;
node = includes_files;
while (node)
{
char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
int str_len = strlen(str);
fwrite(str, str_len, 1, fp);
free(str);
node = g_list_next (node);
}
}
static void append_to_temp_file(FILE *fp, GList *file_list)
{
GList *node;
node = file_list;
while (node)
{
const char *fname = node->data;
char *contents;
size_t length;
GError *err = NULL;
if (! g_file_get_contents(fname, &contents, &length, &err))
{
fprintf(stderr, "Unable to read file: %s\n", err->message);
g_error_free(err);
}
else
{
fwrite(contents, length, 1, fp);
fwrite("\n", 1, 1, fp); // in case file doesn't end in newline (e.g. windows).
g_free(contents);
}
node = g_list_next (node);
}
}
static gint get_global_tag_type_mask(gint lang)
{
switch (lang)
{
case 0:
case 1:
// C/C++
return tm_tag_class_t | tm_tag_typedef_t | tm_tag_enum_t | tm_tag_enumerator_t |
tm_tag_prototype_t |
tm_tag_function_t | tm_tag_method_t | // for inline functions
tm_tag_macro_t | tm_tag_macro_with_arg_t;
default:
return tm_tag_max_t;
}
}
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
, int includes_count, const char *tags_file)
, int includes_count, const char *tags_file, int lang)
{
#ifdef HAVE_GLOB_H
glob_t globbuf;
@ -202,7 +262,6 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
GPtrArray *tags_array;
GHashTable *includes_files_hash;
GList *includes_files = NULL;
GList *node;
#ifdef G_OS_WIN32
char *temp_file = g_strdup_printf("%s_%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
char *temp_file2 = g_strdup_printf("%s_%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
@ -259,6 +318,7 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
}
else
#endif
// no glob support or globbing not wanted
for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
{
if (!g_hash_table_lookup(includes_files_hash,
@ -279,16 +339,10 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
#ifdef TM_DEBUG
g_message ("writing out files to %s\n", temp_file);
#endif
node = includes_files;
while (node)
{
char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
int str_len = strlen(str);
fwrite(str, str_len, 1, fp);
free(str);
node = g_list_next (node);
}
if (pre_process != NULL)
write_includes_file(fp, includes_files);
else
append_to_temp_file(fp, includes_files);
g_list_free (includes_files);
g_hash_table_destroy(includes_files_hash);
@ -302,18 +356,26 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
* following these lines are incorrectly parsed. The real fix should,
* of course be in tagmanager (c) parser. This is just a temporary fix.
*/
command = g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
if (pre_process != NULL)
{
command = g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
pre_process, temp_file, temp_file2);
#ifdef TM_DEBUG
g_message("Executing: %s", command);
g_message("Executing: %s", command);
#endif
system(command);
g_free(command);
unlink(temp_file);
g_free(temp_file);
source_file = tm_source_file_new(temp_file2, TRUE, NULL);
system(command);
g_free(command);
unlink(temp_file);
g_free(temp_file);
}
else
{
// no pre-processing needed, so temp_file2 = temp_file
g_free(temp_file2);
temp_file2 = temp_file;
temp_file = NULL;
}
source_file = tm_source_file_new(temp_file2, TRUE, tm_source_file_get_lang_name(lang));
if (NULL == source_file)
{
unlink(temp_file2);
@ -326,10 +388,7 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
tm_source_file_free(source_file);
return FALSE;
}
tags_array = tm_tags_extract(source_file->tags_array, tm_tag_class_t |
tm_tag_typedef_t | tm_tag_enum_t | tm_tag_enumerator_t |
tm_tag_prototype_t | tm_tag_function_t | tm_tag_method_t | // for inline functions
tm_tag_macro_t | tm_tag_macro_with_arg_t);
tags_array = tm_tags_extract(source_file->tags_array, get_global_tag_type_mask(lang));
if ((NULL == tags_array) || (0 == tags_array->len))
{
if (tags_array)