-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
browser-hist: Use a dynamic completion table #15
Conversation
GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.41, cairo version 1.18.0) of 2024-03-16 I'm trying to figure out why. Oh wait. It doesn't break. It just didn't work the first time for some reason. I think it's due to lag between copying the db over and search you've mentioned. |
Few things I noticed:
Other than these, it works very nicely. I can start a |
I'm not sure why this is happening, I can find history items by description alone. You can run a query directly (for testing) in the following way. In a lisp interaction buffer, run (browser-hist--send-query "agzam dynamic")
;; produces =>
(("https://github.com/agzam/browser-hist.el/issues/14" . "Some changes (dynamic completion table, etc) · Issue #14 · agzam/browser-hist.el")
("https://github.com/agzam/browser-hist.el/issues/14#issuecomment-2014242357" . "Some changes (dynamic completion table, etc) · Issue #14 · agzam/browser-hist.el")
("https://github.com/agzam/browser-hist.el/pull/15" . "browser-hist: Use a dynamic completion table by karthink · Pull Request #15 · agzam/browser-hist.el")) So it searched against the description as well. |
Should be quite easy. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
browser-hist.el
Outdated
(cl-loop for s in (split-string strings) | ||
collect (format " ( %s LIKE '%%%s%%' OR %s LIKE '%%%s%%' ) " | ||
title s url s) | ||
into queries | ||
finally return | ||
(concat (format "SELECT DISTINCT %s, %s FROM %s WHERE" | ||
title url table) | ||
(mapconcat #'identity queries " AND ") | ||
rest))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, crafting beautiful sushi with cl-loop. As someone who never learned the magic and intricacies of cl-loop, I have great respect for people who know how to use it. Very nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I just threw that one in without much thought. cl-loop
s are usually better than map
in performance-critical "hot-loops", but it's probably not required here.
That said, the updated version reduces the whole function to two cl-loops, including handling the case of no input (where it returns the latest history).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beautifully done. Thank you for such amazing work.
This comment was marked as resolved.
This comment was marked as resolved.
@agzam are you interested in this cache-timeout feature, either as part of this PR or as another one? I use it since I don't want (almost) every invocation of the command to copy a 80 MB sqlite db first, and most of the time I'm searching for urls I visited a while ago. (If I need the immediate history I call |
This comment was marked as resolved.
This comment was marked as resolved.
browser-hist.el
Outdated
(unless (member '(".*\t" . browser-hist--url-handler) | ||
browse-url-handlers) | ||
(add-to-list 'browse-url-handlers '(".*\t" . browser-hist--url-handler))) | ||
|
||
(when (boundp 'embark-transformer-alist) | ||
(unless (member '(url . browser-hist--url-transformer) | ||
(unless (memq '(url . browser-hist--url-transformer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unless (memq '(url . browser-hist--url-transformer) | |
(let ((tfa '(url . browser-hist--url-transformer))) | |
(unless (memq tfa embark-transformer-alist) |
I noticed that byte-compile throws warning: 'memq' called with literal list...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could just go back to member
then? memq
is technically faster but embark-transformer-alist
is tiny so it won't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whichever you say is the best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it back to member
.
To be honest, I'm not sure. It's a very good idea on one hand, but on the other, I don't want to disrupt the current behavior if people expect the most recent history items to appear immediately. But I believe the custom variable can be set to zero in that case, right? So I think it's just a matter of choosing the initial default value? Do you want to add this feature in the same PR or as a separate thing? It's up to you. Or I can try to grab your code and make the changes myself so you don't have to waste time on it. |
Yes, the default value should be zero so there is no breaking change to anyone's usage.
I can add it to this PR. If you merge the PR via rebase it should appear as an atomic commit so it should be fine. |
I updated it and checked that there are no byte-compile warnings here -- but byte-compile operations are a finicky Emacs state-dependent thing and I don't have one of those CI packages to sandbox things, so please let me know. |
browser-hist.el (browser-hist--sqlite-open, browser-hist--sqlite-select, browser-hist-minimum-query-length, browser-hist--db-fields, browser-hist--db-connection, browser-hist--send-query, browser-hist--completion-table, browser-hist-search): - Instead of querying the full history every time, use a dynamic completion table and query the history database as needed. - Don't include the annotation in the url as invisible text, this hack is no longer needed. - Only re-copy the history database to the temp directory if it's newer. - New variable `browser-hist-minimum-query-length` for minimum query string length -- otherwise the sql query will return everything. - Autoload `browser-hist-search` and make `browser-hist` a feature for easy package management. - Move checks (is sql built-in, etc) to the installation stage instead of the "runtime" stage. - Close the db connection after using completing read -- sqlite is C code, and opening too many simultaenous connections to the db can crash or mess up the Emacs session.
browser-hist.el (browser-hist-db-fields, browser-hist--send-query, browser-hist--completion-table, browser-hist-search): When input is shorter than `browser-hist-minimum-query-length`, show the latest 100 items from the browser history instead. Additional changes: - Make browser-hist--send-query more efficient: `seq-remove` creates a duplicate, this is unnecessary. Convert result construction to a simpler cl-loop. - Don't require subr-x, it's no longer used. Require cl-lib but only at compile time, reducing the overall dependencies of the package. - Add a FORCE-UPDATE prefix arg to `browser-hist-search`: This is useless right now but can be used to force updating the browser history cache (via copying) in the future. - Enforce the basic completion style in `browser-hist-search` to avoid conflicts with users' Orderless (or other) configuration.
browser-hist.el (browser-hist--sqlite-open, browser-hist--sqlite-select): Make the inbuilt-sqlite vs sqlite.el dispatch decision a compile-time macro expansion operation, hopefully appeasing our byte-compiler lords.
browser-hist.el (browser-hist-cache-timeout, browser-hist--make-db-copy): Optionally work using an out of date cache to prevent copying the history db with each invocation. The default behavior is unchanged.
browser-hist.el (browser-hist--send-query): Filter results with empty titles in the SQL query instead of in elisp afterwards.
@karthink let me know when I can merge it, or feel free to merge it yourself. |
Is the db access error gone? I don't experience it any more but I'd like to be sure before merging. |
browser-hist.el (browser-hist--sqlite-open,
browser-hist--sqlite-select, browser-hist-minimum-query-length, browser-hist--db-fields, browser-hist--db-connection, browser-hist--send-query, browser-hist--completion-table, browser-hist-search):
Instead of querying the full history every time, use a dynamic completion table and query the history database as needed.
Don't include the annotation in the url as invisible text, this hack is no longer needed.
Only re-copy the history database to the temp directory if it's newer.
New variable
browser-hist-minimum-query-length
for minimum query string length -- otherwise the sql query will return everything.Autoload
browser-hist-search
and makebrowser-hist
a feature for easy package management.Move checks (is sql built-in, etc) to the installation stage instead of the "runtime" stage.
Close the db connection after using completing read -- sqlite is C code, and opening too many simultaenous connections to the db can crash or mess up the Emacs session.