histdb-sync
uses the remote database IDs as the canonical ones which should make syncing a bit less thrashy. Thanks to Chad Transtrum we use builtin which
rather than which
, for systems which have an unusual which (?!), and an improvement to examples below in the README. Thanks to Klaus Ethgen the invocation of sqlite3
is now unaffected by some potential confusions in your sqlite rc files.
declare -ga
which helps when using antigen or somesuch? Thanks to sheperdjerred and fuero there is now a file which might make antigen and oh-my-zsh work.
There is a breaking change, which is that you no longer need to add-zsh-hook precmd histdb-update-outcome
in your rc file. This now happens when you source sqlite-history.zsh
.
Also thanks to Matthias, the exit status of long-running commands is handled better.
If you want to use it, see the Reverse isearch section below which now covers it.
This is a small bit of zsh code that stores your history into a sqlite3 database. It improves on the normal history by storing, for each history command:
It is also possible to merge multiple history databases together without conflict, so long as all your machines have different hostnames.
You will need sqlite3
and the usual coreutils commands installed on your PATH
. To load and activate history recording you need to source sqlite-history.zsh
from your shell in your zsh startup files.
Example for installing in $HOME/.oh-my-zsh/custom/plugins/zsh-histdb
(note that oh-my-zsh
is not required):
mkdir -p $HOME/.oh-my-zsh/custom/plugins/ git clone https://github.com/larkery/zsh-histdb $HOME/.oh-my-zsh/custom/plugins/zsh-histdb
Add this to your $HOME/.zshrc
:
source $HOME/.oh-my-zsh/custom/plugins/zsh-histdb/sqlite-history.zsh autoload -Uz add-zsh-hook
in your zsh startup files.
Add the following line before you source `sqlite-history.zsh`. See #31 for details.
HISTDB_TABULATE_CMD=(sed -e $'s/\x1f/\t/g')Importing your old history
go-histdbimport and ts-histdbimport are useful tools for doing this! Note that the imported history will not include metadata such as the working directory or the exit status, since that is not stored in the normal history file format, so queries using --in DIR
, etc. will not work as expected.
histdb can be configured exactly as zsh:
(ls|cd|top|htop)
.You can query the history with the histdb
command. With no arguments it will print one screenful of history on the current host.
With arguments, it will print history lines matching their concatenation.
For wildcards within a history line, you can use the %
character, which is like the shell glob *
, so histdb this%that
will match any history line containing this
followed by that
with zero or more characters in-between.
To search on particular hosts, directories, sessions, or time periods, see the help with histdb --help
.
You can also run histdb-top
to see your most frequent commands, and histdb-top dir
to show your favourite directory for running commands in, but these commands are really a bit useless.
$ histdb strace time ses dir cmd 17/03 438 ~ strace conkeror 22/03 522 ~ strace apropos cake 22/03 522 ~ strace -e trace=file s 22/03 522 ~ strace -e trace=file ls 22/03 522 ~ strace -e trace=file cat temp/people.vcf 22/03 522 ~ strace -e trace=file cat temp/gammu.log 22/03 522 ~ run-help strace 24/03 547 ~ man strace
These are all the history entries involving strace
in my history. If there was more than one screenful, I would need to say --limit 1000
or some other large number. The command does not warn you if you haven’t seen all the results. The ses
column contains a unique session number, so all the 522
rows are from the same shell session.
To see all hosts, add --host
after the query terms. To see a specific host, add --host hostname
. To see all of a specific session say e.g. -s 522 --limit 10000
.
zsh-autosuggestions
If you use zsh-autosuggestions you can configure it to search the history database instead of the zsh history file thus:
_zsh_autosuggest_strategy_histdb_top_here() { local query="select commands.argv from history left join commands on history.command_id = commands.rowid left join places on history.place_id = places.rowid where places.dir LIKE '$(sql_escape $PWD)%' and commands.argv LIKE '$(sql_escape $1)%' group by commands.argv order by count(*) desc limit 1" suggestion=$(_histdb_query "$query") } ZSH_AUTOSUGGEST_STRATEGY=histdb_top_here
This query will find the most frequently issued command that is issued in the current directory or any subdirectory. You can get other behaviours by changing the query, for example
_zsh_autosuggest_strategy_histdb_top() { local query=" select commands.argv from history left join commands on history.command_id = commands.rowid left join places on history.place_id = places.rowid where commands.argv LIKE '$(sql_escape $1)%' group by commands.argv, places.dir order by places.dir != '$(sql_escape $PWD)', count(*) desc limit 1 " suggestion=$(_histdb_query "$query") } ZSH_AUTOSUGGEST_STRATEGY=histdb_top
This will find the most frequently issued command issued exactly in this directory, or if there are no matches it will find the most frequently issued command in any directory. You could use other fields like the hostname to restrict to suggestions on this host, etc.
If you want a history-reverse-isearch type feature there is one defined in histdb-interactive.zsh
. If you source that file you will get a new widget called _histdb-isearch which you can bind to a key, e.g.
source histdb-interactive.zsh bindkey '^r' _histdb-isearch
This is like normal history-reverse-isearch
except:
This means pressing C-a
or C-e
or similar will not exit the search like normal history-reverse-isearch
RET
) does not cause the command to run immediately but instead lets you edit itThere are also a few extra keybindings:
M-j
will cd
to the directory for the history entry you’re looking at. This means you can search for ./run-this-command and then M-j
to go to the right directory before running.M-h
will toggle limiting the search to the current host’s history.M-d
will toggle limiting the search to the current directory and subdirectories’ historiesThe database lives by default in $HOME/.histdb/zsh-history.db
. You can look in it easily by running _histdb_query
, as this actually just fires up sqlite with the database.
For inspiration you can also use histdb
with the -d
argument and it will print the SQL it’s running.
You should be able to synchronise the history using git
; a 3-way merge driver is supplied in histdb-merge
.
The 3-way merge will only work properly if all the computers on which you use the repository have different hostnames.
The histdb-sync
function will initialize git in the histdb directory and configure the merge driver for you first time you run it. Subsequent times it will commit all changes, pull all changes, force a merge, and push all changes back again. The commit message is useless, so if you find that kind of thing upsetting you will need to fix it.
The reason for using histdb-sync
instead of doing it by hand is that if you are running the git steps in your shell the history database will be changed each command, and so you will never be able to do a pull / merge.
None, and I’ve used the names with underscores to mean something else.
Pull requests / missing featuresHappy to look at changes. I did at one point have a reverse-isearch thing in here for searching the database interactively, but it didn’t really make my life any better so I deleted it.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4