> Well… I don't quite love the proposed query API, but well, I don't know. But 
> it's not too crazy -- well, not more than a DB API would be crazy at least.
> 
> But maybe you could show real use cases of why this kind of API is good and 
> fits everyone?

Below is the python code of that I can improve with the new API. As I 
mentioned, the initial code causes a half-second UI lag which is unbearable. 
And my session doesn't even have too much tags, although I use ProjectManager 
to load tags for the project so it's just not open files (this is when I work 
on Geany, not the Linux kernel). It was under 10000 tags when I profiled the 
python code.

Let me describe my use case and what I found when I searched for an existing 
good fit. 
- My use case is: I'm developing a 
[quickswitch](https://github.com/kugel-/peasy/blob/master/plugins/quickswitch.py)
 plugin (inside Peasy). The plugin adds a dialog and a keybinding to allow to 
quickly type the prefix of a tag name to jump to its definition or location. If 
the prefix is ambigious, it gives a list of candidates so I can chose one. So I 
press Alt+3, type tm_q, then it opens a list of tm_query_* functions to jump 
to. If I type tm_query_ex, then it immediately jumps to the definition of 
tm_query_exec.
- I found `tm_workspace_find()` which does exact match (I need prefix 
matching). `tm_workspace_find()` is tied to the use case of finding the 
destination of go-to-definition/declaraiton
- I found `tm_workspace_find_prefix()` which dedups. I don't want 
deduplication. `tm_workspace_find_prefix()` is tied to the use case of showing 
candidates in the autocomplete list
- Both have a bug that "lang == -1" doesn't actually work (despite their doc 
comments) because `tm_tag_langs_compatible()` doesn't actually look for -1. I 
cannot specifiy a lang in the plugin.
- Both unconditionally search in the global tags as well which is isn't needed 
in my case so just a waste of resources.

So I thought it would be more useful to implement a generic, query interface 
that can be used by Geany itself and plugins, instead of adding one more 
special-purpose `tm_workspace_find_prefix_no_dedup_no_global` function. One 
could also add tons of parameters to `tm_workspace_find()` to make it fit, but 
I really liked the idea of having a dedicated C file with a generic query API 
more. I always care about extensibility if stuff is in the plugin API. The 
query API can be easily extended with more filters or other stuff without 
breaking existing users, which is not possible with a single, one-size-fits-all 
function (new stuff would require new argments, therefore an API break).

The idea is also to use query API inside geany so that `tm_workspace_find*` can 
be removed or refactored. The API is generic enough that `tm_workspace_find`, 
`tm_workspace_find_prefix` and `tm_workspace_find_scope_members` can be 
replaced or implemented with the query interface.
Yes, it kind of resembles a DB query. This is quite on purpose because that 
makes it extensible. Plus, we could probably even replace tagmanager with 
sqlite and without having to change this interface :-)

```
    def search_tags2(self, prefix):
        print("search_tags2")
        ws = self.geany_plugin.geany_data.app.tm_workspace
        q = Geany.tm_query_create(ws, Geany.TMQuerySource.SESSION_TAGS);
        q.add_name(prefix, len(prefix))
        return q.exec(None, None)

    def search_tags(self, prefix):
        if (hasattr(Geany, "tm_query_create")):
            return self.search_tags2(prefix)
        ret = []
        # This is super slow with lots of tags. pygobject seems to call 
getattr()
        # for all elements on the first use, regardless of how it used
        array = self.geany_plugin.geany_data.app.tm_workspace.tags_array
        n = tag_bisect_left(array, prefix)
        for tag in array[n:]:
            if (tag.name.startswith(prefix)):
                ret.append(tag)
            else:
                break
        return ret
```

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/geany/geany/pull/1187#issuecomment-241653636

Reply via email to