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-a72fbfd435f5master
parent
3489b63b7d
commit
f39df4005f
11
ChangeLog
11
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue