[geany/geany] 5a369a: Merge pull request #3055 from techee/tagfilter-new
Enrico Tröger
git-noreply at xxxxx
Sun Jan 23 23:06:51 UTC 2022
Branch: refs/heads/master
Author: Enrico Tröger <enrico.troeger at uvena.de>
Committer: GitHub <noreply at github.com>
Date: Sun, 23 Jan 2022 23:06:51 UTC
Commit: 5a369a41e3cb6fd1bc57e602fa567e8c0d153bfc
https://github.com/geany/geany/commit/5a369a41e3cb6fd1bc57e602fa567e8c0d153bfc
Log Message:
-----------
Merge pull request #3055 from techee/tagfilter-new
Filter for symbol tree - improved version
Modified Paths:
--------------
HACKING
data/geany.glade
doc/geany.txt
src/callbacks.c
src/callbacks.h
src/document.c
src/documentprivate.h
src/editor.c
src/symbols.c
src/tagmanager/tm_parser.c
src/tagmanager/tm_parser.h
src/tagmanager/tm_tag.c
src/tagmanager/tm_workspace.c
Modified: HACKING
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -676,7 +676,7 @@ MAP_ENTRY(FOO) to parser_map.
(You may want to make the symbols.c change before doing this).
In src/tagmanager/tm_parser.c:
-Update tm_parser_context_separator() and tm_parser_has_full_context() to
+Update tm_parser_scope_separator() and tm_parser_has_full_scope() to
handle the new parser if applicable, by adding a TM_PARSER_FOO case entry.
In filetypes.c, init_builtin_filetypes():
Modified: data/geany.glade
45 lines changed, 39 insertions(+), 6 deletions(-)
===================================================================
@@ -8245,17 +8245,50 @@
<signal name="switch-page" handler="on_tv_notebook_switch_page" swapped="no"/>
<signal name="switch-page" handler="on_tv_notebook_switch_page_after" after="yes" swapped="no"/>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <object class="GtkVBox" id="vbox46">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="entry_tagfilter">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Filter the symbol list using the entered text. Separate multiple filters with a space.</property>
+ <property name="invisible_char">•</property>
+ <property name="primary_icon_stock">gtk-find</property>
+ <property name="secondary_icon_stock">gtk-clear</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">True</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ <signal name="changed" handler="on_entry_tagfilter_changed" swapped="no"/>
+ <signal name="activate" handler="on_entry_tagfilter_activate" swapped="no"/>
+ <signal name="icon-press" handler="on_entry_tagfilter_icon_press" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
- <object class="GtkTreeView" id="treeview2">
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="enable_search">False</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="enable_search">False</property>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
</child>
Modified: doc/geany.txt
25 lines changed, 25 insertions(+), 0 deletions(-)
===================================================================
@@ -253,6 +253,31 @@ The position of the tabs can be selected in the interface preferences.
The sizes of the sidebar and message window can be adjusted by
dragging the dividers.
+Sidebar Usage
+^^^^^^^^^^^^^
+
+The sidebar has a right click menu that can control what is visible and
+has actions specific to the tab (other tabs added by plugins are
+described by that plugin documentation):
+
+* Symbols
+
+ * expand/collapse the tree
+ * control sorting order
+ * locate the symbol in documents
+
+ The symbols tab can also be filtered by typing a string into
+ the entry at the top of the tab. All symbols that contain the entered
+ string as a substring will be shown in the tree. Multiple filters can
+ be separated by a space.
+
+* Documents
+
+ * expand/collapse the tree
+ * save to or reload from files
+ * search tree based at selected file
+ * show or hide the document paths
+
Command line options
--------------------
Modified: src/callbacks.c
49 lines changed, 48 insertions(+), 1 deletions(-)
===================================================================
@@ -437,6 +437,44 @@ void on_toolbutton_search_clicked(GtkAction *action, gpointer user_data)
}
+void on_entry_tagfilter_changed(GtkAction *action, gpointer user_data)
+{
+ GeanyDocument *doc = document_get_current();
+ GtkEntry *filter_entry;
+
+ if (!doc)
+ return;
+
+ filter_entry = GTK_ENTRY(ui_lookup_widget(main_widgets.window, "entry_tagfilter"));
+ g_free(doc->priv->tag_filter);
+ doc->priv->tag_filter = g_strdup(gtk_entry_get_text(filter_entry));
+
+ /* make sure the tree is fully re-created so it appears correctly
+ * after applying filter */
+ if (doc->priv->tag_store)
+ gtk_tree_store_clear(doc->priv->tag_store);
+ sidebar_update_tag_list(doc, TRUE);
+}
+
+
+void on_entry_tagfilter_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data)
+{
+ if (event->button.button == 1)
+ gtk_entry_set_text(entry, "");
+}
+
+
+void on_entry_tagfilter_activate(GtkEntry *entry, gpointer user_data)
+{
+ GeanyDocument *doc = document_get_current();
+
+ if (!doc)
+ return;
+
+ gtk_widget_grab_focus(doc->priv->tag_tree);
+}
+
+
/* hides toolbar from toolbar popup menu */
static void on_hide_toolbar1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
@@ -491,14 +529,23 @@ static void on_notebook1_switch_page_after(GtkNotebook *notebook, gpointer page,
if (doc != NULL)
{
+ GtkEntry *filter_entry = GTK_ENTRY(ui_lookup_widget(main_widgets.window, "entry_tagfilter"));
+ const gchar *entry_text = gtk_entry_get_text(filter_entry);
+
sidebar_select_openfiles_item(doc);
ui_save_buttons_toggle(doc->changed);
ui_set_window_title(doc);
ui_update_statusbar(doc, -1);
ui_update_popup_reundo_items(doc);
ui_document_show_hide(doc); /* update the document menu */
build_menu_update(doc);
- sidebar_update_tag_list(doc, FALSE);
+ if (g_strcmp0(entry_text, doc->priv->tag_filter) != 0)
+ {
+ /* calls sidebar_update_tag_list() in on_entry_tagfilter_changed() */
+ gtk_entry_set_text(filter_entry, doc->priv->tag_filter);
+ }
+ else
+ sidebar_update_tag_list(doc, TRUE);
document_highlight_tags(doc);
document_check_disk_status(doc, TRUE);
Modified: src/callbacks.h
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -72,6 +72,12 @@ void on_toolbar_search_entry_changed(GtkAction *action, const gchar *text, gpoin
void on_toolbar_search_entry_activate(GtkAction *action, const gchar *text, gpointer user_data);
+void on_entry_tagfilter_changed(GtkAction *action, gpointer user_data);
+
+void on_entry_tagfilter_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data);
+
+void on_entry_tagfilter_activate(GtkEntry *entry, gpointer user_data);
+
void on_toggle_case1_activate(GtkMenuItem *menuitem, gpointer user_data);
void on_find_usage1_activate(GtkMenuItem *menuitem, gpointer user_data);
Modified: src/document.c
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -647,6 +647,7 @@ static GeanyDocument *document_create(const gchar *utf8_filename)
/* initialize default document settings */
doc->priv = g_new0(GeanyDocumentPrivate, 1);
+ doc->priv->tag_filter = g_strdup("");
doc->id = ++doc_id_counter;
doc->index = new_idx;
doc->file_name = g_strdup(utf8_filename);
@@ -734,6 +735,7 @@ static gboolean remove_page(guint page_num)
}
g_free(doc->encoding);
g_free(doc->priv->saved_encoding.encoding);
+ g_free(doc->priv->tag_filter);
g_free(doc->file_name);
g_free(doc->real_path);
if (doc->tm_file)
Modified: src/documentprivate.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -112,6 +112,8 @@ typedef struct GeanyDocumentPrivate
GtkWidget *info_bars[NUM_MSG_TYPES];
/* Keyed Data List to attach arbitrary data to the document */
GData *data;
+ /* Text used for filtering symbol tree. */
+ gchar *tag_filter;
}
GeanyDocumentPrivate;
Modified: src/editor.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -645,7 +645,7 @@ static void show_tags_list(GeanyEditor *editor, const GPtrArray *tags, gsize roo
static gint scope_autocomplete_suffix(ScintillaObject *sci, TMParserType lang,
gint pos, gboolean *scope_sep)
{
- const gchar *sep = tm_parser_context_separator(lang);
+ const gchar *sep = tm_parser_scope_separator(lang);
const gsize max_len = 3;
gboolean is_scope_sep;
gchar *buf;
@@ -708,7 +708,7 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
gboolean scope_sep_typed = FALSE;
gboolean ret = FALSE;
const gchar *current_scope;
- const gchar *context_sep = tm_parser_context_separator(ft->lang);
+ const gchar *context_sep = tm_parser_scope_separator(ft->lang);
gint autocomplete_suffix_len;
if (autocomplete_scope_shown)
@@ -1866,7 +1866,7 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
{
const TMTagType arg_types = tm_tag_function_t | tm_tag_prototype_t |
tm_tag_method_t | tm_tag_macro_with_arg_t;
- const gchar *scope_sep = tm_parser_context_separator(ft->lang);
+ const gchar *scope_sep = tm_parser_scope_separator(ft->lang);
gchar *scope = EMPTY(tag->scope) ? g_strdup(tag->name) :
g_strjoin(scope_sep, tag->scope, tag->name, NULL);
Modified: src/symbols.c
54 lines changed, 43 insertions(+), 11 deletions(-)
===================================================================
@@ -265,7 +265,7 @@ GString *symbols_find_typenames_as_string(TMParserType lang, gboolean global)
GEANY_API_SYMBOL
const gchar *symbols_get_context_separator(gint ft_id)
{
- return tm_parser_context_separator(filetypes[ft_id]->lang);
+ return tm_parser_scope_separator(filetypes[ft_id]->lang);
}
@@ -319,26 +319,58 @@ static gint compare_symbol_lines(gconstpointer a, gconstpointer b)
static GList *get_tag_list(GeanyDocument *doc, TMTagType tag_types)
{
GList *tag_names = NULL;
- guint i;
+ guint i, j;
+ gchar **tf_strv;
g_return_val_if_fail(doc, NULL);
if (! doc->tm_file || ! doc->tm_file->tags_array)
return NULL;
+ tf_strv = g_strsplit_set(doc->priv->tag_filter, " ", -1);
+
for (i = 0; i < doc->tm_file->tags_array->len; ++i)
{
TMTag *tag = TM_TAG(doc->tm_file->tags_array->pdata[i]);
- if (G_UNLIKELY(tag == NULL))
- return NULL;
-
if (tag->type & tag_types)
{
- tag_names = g_list_prepend(tag_names, tag);
+ gboolean filtered = FALSE;
+ gchar **val;
+ gchar *full_tagname = g_strconcat(tag->scope ? tag->scope : "",
+ tag->scope ? tm_parser_scope_separator_printable(tag->lang) : "",
+ tag->name, NULL);
+ gchar *normalized_tagname = g_utf8_normalize(full_tagname, -1, G_NORMALIZE_ALL);
+
+ foreach_strv(val, tf_strv)
+ {
+ gchar *normalized_val = g_utf8_normalize(*val, -1, G_NORMALIZE_ALL);
+
+ if (normalized_tagname != NULL && normalized_val != NULL)
+ {
+ gchar *case_normalized_tagname = g_utf8_casefold(normalized_tagname, -1);
+ gchar *case_normalized_val = g_utf8_casefold(normalized_val, -1);
+
+ filtered = strstr(case_normalized_tagname, case_normalized_val) == NULL;
+ g_free(case_normalized_tagname);
+ g_free(case_normalized_val);
+ }
+ g_free(normalized_val);
+
+ if (filtered)
+ break;
+ }
+ if (!filtered)
+ tag_names = g_list_prepend(tag_names, tag);
+
+ g_free(normalized_tagname);
+ g_free(full_tagname);
}
}
tag_names = g_list_sort(tag_names, compare_symbol_lines);
+
+ g_strfreev(tf_strv);
+
return tag_names;
}
@@ -940,7 +972,7 @@ static const gchar *get_symbol_name(GeanyDocument *doc, const TMTag *tag, gboole
if (!found_parent && scope &&
strpbrk(scope, GEANY_WORDCHARS) == scope)
{
- const gchar *sep = symbols_get_context_separator(doc->file_type->id);
+ const gchar *sep = tm_parser_scope_separator_printable(tag->lang);
g_string_append(buffer, scope);
g_string_append(buffer, sep);
@@ -1196,7 +1228,7 @@ static void update_parents_table(GHashTable *table, const TMTag *tag, const GtkT
/* simple case, just use the tag name */
name = tag->name;
}
- else if (! tm_parser_has_full_context(tag->lang))
+ else if (! tm_parser_has_full_scope(tag->lang))
{
/* if the parser doesn't use fully qualified scope, use the name alone but
* prevent Foo::Foo from making parent = child */
@@ -1208,7 +1240,7 @@ static void update_parents_table(GHashTable *table, const TMTag *tag, const GtkT
else
{
/* build the fully qualified scope as get_parent_name() would return it for a child tag */
- name_free = g_strconcat(tag->scope, tm_parser_context_separator(tag->lang), tag->name, NULL);
+ name_free = g_strconcat(tag->scope, tm_parser_scope_separator(tag->lang), tag->name, NULL);
name = name_free;
}
@@ -1378,7 +1410,7 @@ static void update_tree_tags(GeanyDocument *doc, GList **tags)
/* Build hash tables holding tags and parents */
/* parent table is GHashTable<tag_name, GTree<line_num, GtkTreeIter>>
* where tag_name might be a fully qualified name (with scope) if the language
- * parser reports scope properly (see tm_parser_has_full_context()). */
+ * parser reports scope properly (see tm_parser_has_full_scope()). */
parents_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, parents_table_value_free);
/* tags table is another representation of the @tags list,
* GHashTable<TMTag, GTree<line_num, GList<GList<TMTag>>>> */
@@ -2431,7 +2463,7 @@ static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, TMTagType
{
if (tag->scope)
*tagname = g_strconcat(tag->scope,
- symbols_get_context_separator(doc->file_type->id), tag->name, NULL);
+ tm_parser_scope_separator(tag->lang), tag->name, NULL);
else
*tagname = g_strdup(tag->name);
Modified: src/tagmanager/tm_parser.c
26 lines changed, 21 insertions(+), 5 deletions(-)
===================================================================
@@ -835,7 +835,7 @@ void tm_parser_verify_type_mappings(void)
* zero otherwise. */
gint tm_parser_scope_autocomplete_suffix(TMParserType lang, const gchar *str)
{
- const gchar *sep = tm_parser_context_separator(lang);
+ const gchar *sep = tm_parser_scope_separator(lang);
if (g_str_has_suffix(str, sep))
return strlen(sep);
@@ -971,7 +971,7 @@ gchar *tm_parser_format_function(TMParserType lang, const gchar *fname, const gc
if (scope)
{
g_string_append(str, scope);
- g_string_append(str, tm_parser_context_separator(lang));
+ g_string_append(str, tm_parser_scope_separator_printable(lang));
}
g_string_append(str, fname);
g_string_append_c(str, ' ');
@@ -1017,7 +1017,7 @@ gchar *tm_parser_format_function(TMParserType lang, const gchar *fname, const gc
}
-const gchar *tm_parser_context_separator(TMParserType lang)
+const gchar *tm_parser_scope_separator(TMParserType lang)
{
switch (lang)
{
@@ -1046,11 +1046,27 @@ const gchar *tm_parser_context_separator(TMParserType lang)
}
-gboolean tm_parser_has_full_context(TMParserType lang)
+const gchar *tm_parser_scope_separator_printable(TMParserType lang)
{
switch (lang)
{
- /* These parsers include full hierarchy in the tag scope, separated by tm_parser_context_separator() */
+ case TM_PARSER_TXT2TAGS:
+ case TM_PARSER_ASCIIDOC:
+ case TM_PARSER_CONF:
+ case TM_PARSER_REST:
+ return " > ";
+
+ default:
+ return tm_parser_scope_separator(lang);
+ }
+}
+
+
+gboolean tm_parser_has_full_scope(TMParserType lang)
+{
+ switch (lang)
+ {
+ /* These parsers include full hierarchy in the tag scope, separated by tm_parser_scope_separator() */
case TM_PARSER_ACTIONSCRIPT:
case TM_PARSER_C:
case TM_PARSER_CPP:
Modified: src/tagmanager/tm_parser.h
6 lines changed, 4 insertions(+), 2 deletions(-)
===================================================================
@@ -140,9 +140,11 @@ gchar *tm_parser_format_variable(TMParserType lang, const gchar *name, const gch
gchar *tm_parser_format_function(TMParserType lang, const gchar *fname, const gchar *args,
const gchar *retval, const gchar *scope);
-const gchar *tm_parser_context_separator(TMParserType lang);
+const gchar *tm_parser_scope_separator(TMParserType lang);
-gboolean tm_parser_has_full_context(TMParserType lang);
+const gchar *tm_parser_scope_separator_printable(TMParserType lang);
+
+gboolean tm_parser_has_full_scope(TMParserType lang);
gboolean tm_parser_langs_compatible(TMParserType lang, TMParserType other);
Modified: src/tagmanager/tm_tag.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -781,7 +781,7 @@ void tm_tags_array_print(GPtrArray *tags, FILE *fp)
*/
gint tm_tag_scope_depth(const TMTag *t)
{
- const gchar *context_sep = tm_parser_context_separator(t->lang);
+ const gchar *context_sep = tm_parser_scope_separator(t->lang);
gint depth;
char *s;
if(!(t && t->scope))
Modified: src/tagmanager/tm_workspace.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -750,7 +750,7 @@ find_scope_members_tags (const GPtrArray *all, TMTag *type_tag, gboolean namespa
member_types = tm_tag_max_t;
if (type_tag->scope && *(type_tag->scope))
- scope = g_strconcat(type_tag->scope, tm_parser_context_separator(type_tag->lang), type_tag->name, NULL);
+ scope = g_strconcat(type_tag->scope, tm_parser_scope_separator(type_tag->lang), type_tag->name, NULL);
else
scope = g_strdup(type_tag->name);
@@ -785,7 +785,7 @@ static gchar *strip_type(const gchar *scoped_name, TMParserType lang)
if (scoped_name != NULL)
{
/* remove scope prefix */
- const gchar *sep = tm_parser_context_separator(lang);
+ const gchar *sep = tm_parser_scope_separator(lang);
const gchar *base = g_strrstr(scoped_name, sep);
gchar *name = base ? g_strdup(base + strlen(sep)) : g_strdup(scoped_name);
@@ -881,7 +881,7 @@ find_scope_members (const GPtrArray *tags_array, const gchar *name, TMSourceFile
static gboolean member_at_method_scope(const GPtrArray *tags, const gchar *method_scope, TMTag *member_tag,
TMParserType lang)
{
- const gchar *sep = tm_parser_context_separator(lang);
+ const gchar *sep = tm_parser_scope_separator(lang);
gboolean ret = FALSE;
gchar **comps;
guint len;
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list