Add option --generate-tags (-g) to generate a global tags file from
a list of source files. Currently this is only likely to work correctly for C-like source files. Run 'geany -g' for syntax info. Remove short option for hidden option --generate-data-files. Update tm_workspace_create_global_tags() from Anjuta 1.2.4a. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1411 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
parent
1a8ecdbfe3
commit
d3dfe1dd1d
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
* src/project.c:
|
* src/project.c:
|
||||||
Made all project dialogs modal.
|
Made all project dialogs modal.
|
||||||
|
* src/main.c, src/symbols.c, src/symbols.h, tagmanager/tm_workspace.c:
|
||||||
|
Add option --generate-tags (-g) to generate a global tags file from
|
||||||
|
a list of source files. Currently this is only likely to work
|
||||||
|
correctly for C-like source files. Run 'geany -g' for syntax info.
|
||||||
|
Remove short option for hidden option --generate-data-files.
|
||||||
|
Update tm_workspace_create_global_tags() from Anjuta 1.2.4a.
|
||||||
|
|
||||||
|
|
||||||
2007-03-20 Enrico Tröger <enrico.troeger@uvena.de>
|
2007-03-20 Enrico Tröger <enrico.troeger@uvena.de>
|
||||||
|
10
src/main.c
10
src/main.c
@ -87,13 +87,15 @@ static gchar *lib_vte = NULL;
|
|||||||
static gboolean ignore_socket = FALSE;
|
static gboolean ignore_socket = FALSE;
|
||||||
#endif
|
#endif
|
||||||
static gboolean generate_datafiles = FALSE;
|
static gboolean generate_datafiles = FALSE;
|
||||||
|
static gboolean generate_tags = FALSE;
|
||||||
|
|
||||||
static GOptionEntry entries[] =
|
static GOptionEntry entries[] =
|
||||||
{
|
{
|
||||||
{ "column", 0, 0, G_OPTION_ARG_INT, &cl_options.goto_column, N_("set initial column number for the first opened file (useful in conjunction with --line)"), NULL },
|
{ "column", 0, 0, G_OPTION_ARG_INT, &cl_options.goto_column, N_("set initial column number for the first opened file (useful in conjunction with --line)"), NULL },
|
||||||
{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("use an alternate configuration directory"), NULL },
|
{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("use an alternate configuration directory"), NULL },
|
||||||
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_mode, N_("runs in debug mode (means being verbose)"), NULL },
|
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_mode, N_("runs in debug mode (means being verbose)"), NULL },
|
||||||
{ "generate-data-files", 'g', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &generate_datafiles, "", NULL },
|
{ "generate-tags", 'g', 0, G_OPTION_ARG_NONE, &generate_tags, N_("generate global tags file (see documentation)"), NULL },
|
||||||
|
{ "generate-data-files", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &generate_datafiles, "", NULL },
|
||||||
#ifdef HAVE_SOCKET
|
#ifdef HAVE_SOCKET
|
||||||
{ "new-instance", 'i', 0, G_OPTION_ARG_NONE, &ignore_socket, N_("don't open files in a running instance, force opening a new instance"), NULL },
|
{ "new-instance", 'i', 0, G_OPTION_ARG_NONE, &ignore_socket, N_("don't open files in a running instance, force opening a new instance"), NULL },
|
||||||
#endif
|
#endif
|
||||||
@ -433,6 +435,12 @@ static void parse_command_line_options(gint *argc, gchar ***argv)
|
|||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
if (generate_tags)
|
||||||
|
{
|
||||||
|
gboolean ret = symbols_generate_global_tags(*argc, *argv);
|
||||||
|
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
app->debug_mode = debug_mode;
|
app->debug_mode = debug_mode;
|
||||||
#ifdef GEANY_DEBUG
|
#ifdef GEANY_DEBUG
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "symbols.h"
|
#include "symbols.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -688,3 +689,41 @@ gboolean symbols_recreate_tag_list(gint idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Adapted from anjuta-2.0.2/global-tags/tm_global_tags.c, thanks.
|
||||||
|
* Needs full path and \" quoting characters around filenames.
|
||||||
|
* Example:
|
||||||
|
* geany -g tagsfile \"/home/nmt/svn/geany/src/d*.h\" */
|
||||||
|
int symbols_generate_global_tags(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* -E pre-process, -dD output user macros, -p prof info (?),
|
||||||
|
* -undef remove builtin macros (seems to be needed with FC5 gcc 4.1.1 */
|
||||||
|
const char pre_process[] = "gcc -E -dD -p -undef";
|
||||||
|
|
||||||
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
/* Create global taglist */
|
||||||
|
int status;
|
||||||
|
char *command;
|
||||||
|
command = g_strdup_printf("%s %s", pre_process,
|
||||||
|
NVL(getenv("CFLAGS"), ""));
|
||||||
|
//printf(">%s<\n", command);
|
||||||
|
status = tm_workspace_create_global_tags(command,
|
||||||
|
(const char **) (argv + 2),
|
||||||
|
argc - 2, argv[1]);
|
||||||
|
g_free(command);
|
||||||
|
if (!status)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s -g <Tag File> <File list>\n\n", argv[0]);
|
||||||
|
fprintf(stderr, "Each file in <File list> must be enclosed in double quotes.\n");
|
||||||
|
fprintf(stderr, "Example:\n"
|
||||||
|
"CFLAGS=`pkg-config gtk+-2.0 --cflags` %s -g gtk2.c.tags"
|
||||||
|
" \\\"/usr/include/gtk-2.0/gtk/gtk.h\\\"\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,4 +48,6 @@ void symbols_finalize();
|
|||||||
|
|
||||||
gboolean symbols_recreate_tag_list(gint idx);
|
gboolean symbols_recreate_tag_list(gint idx);
|
||||||
|
|
||||||
|
int symbols_generate_global_tags(int argc, char **argv);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "tm_workspace.h"
|
#include "tm_workspace.h"
|
||||||
#include "tm_project.h"
|
#include "tm_project.h"
|
||||||
|
|
||||||
|
|
||||||
static TMWorkspace *theWorkspace = NULL;
|
static TMWorkspace *theWorkspace = NULL;
|
||||||
guint workspace_class_id = 0;
|
guint workspace_class_id = 0;
|
||||||
|
|
||||||
@ -156,6 +157,31 @@ gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint tm_file_inode_hash(gconstpointer key)
|
||||||
|
{
|
||||||
|
struct stat file_stat;
|
||||||
|
const char *filename = (const char*)key;
|
||||||
|
if (stat(filename, &file_stat) == 0)
|
||||||
|
{
|
||||||
|
#ifdef TM_DEBUG
|
||||||
|
g_message ("Hash for '%s' is '%d'\n", filename, file_stat.st_ino);
|
||||||
|
#endif
|
||||||
|
return g_direct_hash (GUINT_TO_POINTER (file_stat.st_ino));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
GList **pp_list = (GList**)user_data;
|
||||||
|
|
||||||
|
if (user_data == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*pp_list = g_list_prepend(*pp_list, value);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
|
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)
|
||||||
{
|
{
|
||||||
@ -169,11 +195,9 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
TMWorkObject *source_file;
|
TMWorkObject *source_file;
|
||||||
GPtrArray *tags_array;
|
GPtrArray *tags_array;
|
||||||
|
GHashTable *includes_files_hash;
|
||||||
GList *includes_files = NULL;
|
GList *includes_files = NULL;
|
||||||
guint list_len;
|
GList *node;
|
||||||
guint idx_main;
|
|
||||||
guint idx_sub;
|
|
||||||
int remove_count = 0;
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
char *temp_file = g_strdup_printf("%s_%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
|
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));
|
char *temp_file2 = g_strdup_printf("%s_%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
|
||||||
@ -181,11 +205,18 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
|
|||||||
char *temp_file = g_strdup_printf("%s/%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
|
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));
|
char *temp_file2 = g_strdup_printf("%s/%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
|
||||||
#endif
|
#endif
|
||||||
TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_scope_t
|
TMTagAttrType sort_attrs[] = {
|
||||||
, tm_tag_attr_type_t, 0};
|
tm_tag_attr_name_t, tm_tag_attr_scope_t,
|
||||||
|
tm_tag_attr_type_t, 0
|
||||||
|
};
|
||||||
|
|
||||||
if (NULL == (fp = fopen(temp_file, "w")))
|
if (NULL == (fp = fopen(temp_file, "w")))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
includes_files_hash = g_hash_table_new_full (tm_file_inode_hash,
|
||||||
|
g_direct_equal,
|
||||||
|
NULL, g_free);
|
||||||
|
|
||||||
#ifdef HAVE_GLOB_H
|
#ifdef HAVE_GLOB_H
|
||||||
globbuf.gl_offs = 0;
|
globbuf.gl_offs = 0;
|
||||||
for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
|
for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
|
||||||
@ -195,91 +226,87 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
|
|||||||
strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1);
|
strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1);
|
||||||
clean_path[dirty_len - 2] = 0;
|
clean_path[dirty_len - 2] = 0;
|
||||||
|
|
||||||
//printf("[o][%s]\n", clean_path);
|
#ifdef TM_DEBUG
|
||||||
|
g_message ("[o][%s]\n", clean_path);
|
||||||
|
#endif
|
||||||
glob(clean_path, 0, NULL, &globbuf);
|
glob(clean_path, 0, NULL, &globbuf);
|
||||||
//printf("matches: %d\n", globbuf.gl_pathc);
|
|
||||||
|
#ifdef TM_DEBUG
|
||||||
|
g_message ("matches: %d\n", globbuf.gl_pathc);
|
||||||
|
#endif
|
||||||
|
|
||||||
for(idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
|
for(idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
|
||||||
{
|
{
|
||||||
includes_files = g_list_append(includes_files, strdup(globbuf.gl_pathv[idx_glob]));
|
#ifdef TM_DEBUG
|
||||||
//printf(">>> %s\n", globbuf.gl_pathv[idx_glob]);
|
g_message (">>> %s\n", globbuf.gl_pathv[idx_glob]);
|
||||||
|
#endif
|
||||||
|
if (!g_hash_table_lookup(includes_files_hash,
|
||||||
|
globbuf.gl_pathv[idx_glob]))
|
||||||
|
{
|
||||||
|
char* file_name_copy = strdup(globbuf.gl_pathv[idx_glob]);
|
||||||
|
g_hash_table_insert(includes_files_hash, file_name_copy,
|
||||||
|
file_name_copy);
|
||||||
|
#ifdef TM_DEBUG
|
||||||
|
g_message ("Added ...\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
globfree(&globbuf);
|
globfree(&globbuf);
|
||||||
free(clean_path);
|
free(clean_path);
|
||||||
}
|
}
|
||||||
#else
|
#else // no glob support
|
||||||
for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
|
for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
|
||||||
{
|
{
|
||||||
includes_files = g_list_append(includes_files, strdup(includes[idx_inc]));
|
if (!g_hash_table_lookup(includes_files_hash,
|
||||||
|
includes[idx_inc]))
|
||||||
|
{
|
||||||
|
char* file_name_copy = strdup(includes[idx_inc]);
|
||||||
|
g_hash_table_insert(includes_files_hash, file_name_copy,
|
||||||
|
file_name_copy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Checks for duplicate file entries which would case trouble */
|
/* Checks for duplicate file entries which would case trouble */
|
||||||
|
g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list,
|
||||||
|
&includes_files);
|
||||||
|
|
||||||
|
includes_files = g_list_reverse (includes_files);
|
||||||
|
|
||||||
|
#ifdef TM_DEBUG
|
||||||
|
g_message ("writing out files to %s\n", temp_file);
|
||||||
|
#endif
|
||||||
|
node = includes_files;
|
||||||
|
while (node)
|
||||||
{
|
{
|
||||||
struct stat main_stat;
|
char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
|
||||||
struct stat sub_stat;
|
|
||||||
|
|
||||||
remove_count = 0;
|
|
||||||
|
|
||||||
list_len = g_list_length(includes_files);
|
|
||||||
|
|
||||||
/* We look for files with the same inode */
|
|
||||||
for(idx_main = 0; idx_main < list_len; idx_main++)
|
|
||||||
{
|
|
||||||
// printf("%d / %d\n", idx_main, list_len - 1);
|
|
||||||
stat(g_list_nth_data(includes_files, idx_main), &main_stat);
|
|
||||||
for(idx_sub = idx_main + 1; idx_sub < list_len; idx_sub++)
|
|
||||||
{
|
|
||||||
GList *element = NULL;
|
|
||||||
|
|
||||||
stat(g_list_nth_data(includes_files, idx_sub), &sub_stat);
|
|
||||||
|
|
||||||
|
|
||||||
if(main_stat.st_ino != sub_stat.st_ino)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Inodes match */
|
|
||||||
|
|
||||||
element = g_list_nth(includes_files, idx_sub);
|
|
||||||
|
|
||||||
/* printf("%s == %s\n", g_list_nth_data(includes_files, idx_main),
|
|
||||||
g_list_nth_data(includes_files, idx_sub)); */
|
|
||||||
|
|
||||||
/* We delete the duplicate entry from the list */
|
|
||||||
includes_files = g_list_remove_link(includes_files, element);
|
|
||||||
remove_count++;
|
|
||||||
|
|
||||||
/* Don't forget to free the mallocs (we duplicated every string earlier!) */
|
|
||||||
free(element->data);
|
|
||||||
|
|
||||||
idx_sub--; /* Cause the inner loop not to move; good since we removed
|
|
||||||
an element at the current position; we don't have to worry
|
|
||||||
about the outer loop because the inner loop always starts
|
|
||||||
after the outer loop's index */
|
|
||||||
|
|
||||||
list_len = g_list_length(includes_files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
printf("writing out files to %s\n", temp_file);
|
|
||||||
for(idx_main = 0; idx_main < g_list_length(includes_files); idx_main++)
|
|
||||||
{
|
|
||||||
char *str = g_strdup_printf("#include \"%s\"\n",
|
|
||||||
(char*)g_list_nth_data(includes_files,
|
|
||||||
idx_main));
|
|
||||||
int str_len = strlen(str);
|
int str_len = strlen(str);
|
||||||
|
|
||||||
fwrite(str, str_len, 1, fp);
|
fwrite(str, str_len, 1, fp);
|
||||||
|
|
||||||
free(str);
|
free(str);
|
||||||
free(g_list_nth(includes_files, idx_main) -> data);
|
node = g_list_next (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_list_free (includes_files);
|
||||||
|
g_hash_table_destroy(includes_files_hash);
|
||||||
|
includes_files_hash = NULL;
|
||||||
|
includes_files = NULL;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
command = g_strdup_printf("%s %s >%s", pre_process, temp_file, temp_file2);
|
/* FIXME: The following grep command it be remove the lines
|
||||||
|
* G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
|
||||||
|
* that in tagmanager, the files are not correctly parsed and the typedefs
|
||||||
|
* 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",
|
||||||
|
pre_process, temp_file, temp_file2);
|
||||||
|
|
||||||
|
#ifdef TM_DEBUG
|
||||||
|
g_message("Executing: %s", command);
|
||||||
|
#endif
|
||||||
|
|
||||||
system(command);
|
system(command);
|
||||||
g_free(command);
|
g_free(command);
|
||||||
unlink(temp_file);
|
unlink(temp_file);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user