Jog: Print the last 10 commands you ran in the current directory
github.com
github.com
jog() {
sqlite3 $HOME/.histdb/zsh-history.db "
SELECT
replace(commands.argv, '
', '
')
FROM commands
JOIN history ON history.command_id = commands.id
JOIN places ON history.place_id = places.id
WHERE history.exit_status = 0
AND dir = '${PWD}'
AND places.host = '${HOST}'
AND commands.argv != 'jog'
AND commands.argv NOT LIKE 'z %'
AND commands.argv NOT LIKE 'cd %'
AND commands.argv != '..'
ORDER BY start_time DESC
LIMIT 10
"
}I understand not wanting to clog up your history with typos, but some configs even default to not being able to press up-arrow to get a command that I just mistyped.
But if you did do a mistake in your command, like referring to a file that doesn't exist, don't you rerun the command again but with the correct parameters? Then it would be included there as well (when running `jog`).
Otherwise, it's trivial to remove the WHERE statement so it shows all the commands, seems zsh-histdb stores everything, successful or not.
The example I was trying to explain above referred to deliberately referencing a filename which may not correspond to an existing file. Like I might stat a file, to know when it was created, but if it hasn't been created yet then that's an answer too.
1. Download the `sqlite-history.zsh` file to somewhere (or use oh-my-zsh)
2. Source that file in your `.zshrc`
3. Run `autoload -Uz add-zsh-hook` in your `.zshrc`
That's it. I can't imagine a way it could be easier in fact.
Are you referring to the "Note for OS X users" section in the README? If so, it's only additional step, so 4 in total... I know macOS users might not be the most technical, but I think most of them (at least developers on macOS) should be able to follow it :)
btw my comment was not here to tell people I was lazy. It was here as feedback. Users are lazy. Online businesses track and look to decrease the number of clicks that lead to a sale, there's no reason developer tools shouldn't try to do the same :)
(I know it's free, not complaining)
zinit light-mode for \
zinit-zsh/z-a-as-monitor \
zinit-zsh/z-a-patch-dl \
reegnz/jq-zsh-plugin \
larkery/zsh-histdb sqlite-utils memory 'SELECT * FROM a JOIN b USING (pkey)' a.json b.json
See https://sqlite-utils.datasette.io/en/stable/cli.html#queryin...Have you thought about bundling it up so it can be installed with antigen or oh-my-zsh[0]
EDIT: you'd basically just put the content in this comment[1] into a file called `jog.plugin.zsh`
[0] https://github.com/zsh-users/antigen/wiki/Development#notes-...
If you are using bash, here's an alternative to save the commands, their start time, stop time, and eventual error code, in a SQLite database that you can query with fzy: https://github.com/csdvrx/bash-timestamping-sqlite
With the mappings, Ctrl-R will do a search history restricted to the current directory AND to successful execution (return == 0), while Ctrl-T will do a global history search for all directories and return values.
EDIT: to answer a question I've seen posted below, if you want to only navigate the commands from the current directory, do Ctrl-R then use the arrows: the command are by default sorted by the time they where previously run. If you then start typing letters, it will filter these commands using fzy.
What does this even mean? Is this IPython backed history using Write-Ahead Logging?
> I manage to corrupt it frequently, presumably due to segfaults in extensions
A C-based program can't defend itself against corrupted memory. Your logger would need to run in a separated process from your actual code.
It has always been a frustration that the current working directory metadata isn't saved along with history entries, so you can never really reconstruct what was run.
Edit: I should really try out https://github.com/larkery/zsh-histdb. There's no reason a modern system's history shouldn't store start and finish timestamps, return code, current working directory, etc.
It is if you use fish shell.
It's not scoped by directory though, but I'm not sure I'd personally need that feature.
(but it won't happen, these days it's crazy rare to "dig in" in a dazzlingly customized environment, we'd rather tweak our skills to work on the widest range of default environments. Certainly not the best conditions for innovation)
Speak for yourself. The time I spend working locally is vastly more than I spend ssh-ing into somewhere vanilla so it's worth making my environment as comfortable and full-featured as possible.
Edit:
> I hardly ever use cd… to get a history [with] path references
That’s one way of solving the problem, but then you miss out on great tools like direnv… and relative paths.
And git branch if applicable.
https://github.com/cantino/mcfly
https://github.com/ellie/atuin
https://loshadki.app/shellhistory/
Agreed. Wild that's not built in at this point.
In fact it seems like Fish does something better: when adding to the history, it sees if any of the arguments to the command are valid file paths. These are stored separately. Fish will then autocomplete the command if detected paths are valid.
So for example if you run "git log somefile", whenever "somefile" is in your cwd you will get an autocompletion for that command.
This matches the documentation (https://fishshell.com/docs/current/interactive.html#history-...) which says "fish suggests commands as you type, based on command history, completions, and valid file paths".
https://github.com/albertz/wiki/blob/master/shell.md#history
It also obviates the need for many scripts and aliases I would otherwise write: Command lines can be (practically) arbitrarily long, and zsh at least has good multiline edit functionality (including just spawning an editor if you really need to). So there's a lot of "impromptu scripts", sometimes with different variations, in my shell's history.
Some other features I would not want to miss (one from zsh, the other also available in bash, I think), albeit less critical:
1. Alt-. (Alt dot) immediately recalls the last argument passed to the last command line. I use this very very often. "mkdir long_name" followed by "cd long_name" is just one example.
2. Alt-q makes the currently typed command line disappear. But the next time you press enter to get a new prompt, even if you have entered a different command line, it will reappear. Super useful if you remember that you want to do something else before completing your command, without opening another terminal (some things like changing the current directory or env variables can't even be done in another terminal). This can even be done multiple times, it's a stack.
Both need Alt behaving as "Meta" (a checkbox in macOS's Terminal.app for example), otherwise you can still type "ESC" followed by "." or "q", but that's two separate keystrokes.
Alt-q isn't in bash, at least by default, but it sounds pretty useful. I accomplish a similar thing with Alt-#, call the (now commented) command back with Up after however many other commands, then Alt-3 Alt-# will uncomment and run it (any number works there, but 3 is on the same key as #.
I have been using vi mode in zsh for so long, I never learned about Alt+.; thank you so much for introducing me!
bindkey -M viins '\e.' insert-last-word
https://stackoverflow.com/questions/34290179/get-last-argume...
export PROMPT_COMMAND='hpwd=$(history 1); hpwd="${hpwd# *[0-9]* }"; if [[ ${hpwd%% *} == "cd" ]]; then cwd=$OLDPWD; else cwd=$PWD; fi; hpwd="${hpwd% ### *} ### $cwd"; history -s "$hpwd"'
Then you can grep your history for your CWD.This is a one line version of the following:
hpwd=$(history 1) # grab the most recent command
hpwd="${hpwd# *[0-9]* }" # strip off the history line number
if [[ ${hpwd%% *} == "cd" ]] # if it's a cd command, we want the old directory
then # so the comment matches other commands "where *were\* you when this was done?"
cwd=$OLDPWD
else
cwd=$PWD
fi
hpwd="${hpwd% ### \*} ### $cwd" # strip off the old ### comment if there was one so they
# don't accumulate, then build the comment
history -s "$hpwd" # replace the most recent command with itself plus the comment
From here:https://stackoverflow.com/questions/945288/saving-current-di...
function cwd() {
cd "$1" || return
if [ -w "${PWD}/.bash_history" ]; then
history -a
history -c
HISTFILE="${PWD}/.bash_history"
history -r
fi
if [ -r "${PWD}/.bashrc" ]; then
source "${PWD}/.bashrc"
fi
}
Yes, a contextual history is very valuable, but the context isn't necessarily tied to the directory I'm currently in. Like git does as well, I'd want an entire subtree to share the same history. I'm sure that there's more elegant solutions for it than having to explicitly use cwd instead of cd to change contexts, but so far it's served me well. function zshaddhistory() {
echo "${1%%$'\n'}|${PWD} " >> ~/.zsh_history_ext
}
function jog() {
grep -v "jog" ~/.zsh_history_ext | grep -a --color=never "${PWD} " | cut -f1 -d"|" | tail
}But then the inconvenient is that it'll stay in the directory if it's renamed/moved/compressed etc... Better be careful if you tend to input sensitive data on the command line.
I use a script to name each GNU screen session "projectA", "sysadmin", etc.
Then in my .bash_profile, I set the Bash history to be a separate file in my ~/.bash_hist_dir subdirectory.
if [ "x$SCREEN_SESSION_NAME" != "x" -a "x$WINDOW" != "x" ]; then
if [ ! -d ~/.bash_hist_dir ]; then
mkdir ~/.bash_hist_dir
fi
export HISTFILE=~/.bash_hist_dir/${SCREEN_SESSION_NAME}.${WINDOW}
fi
So each separate window in each session gets a unique history file.I have up to 10 windows per GNU screen session, and sometimes 6 to 8 terminal tabs.
Each separate GNU screen window is used for specific things: "edit", "build", "debug", etc.
This all makes it easy to maintain the context of all the things I work on.
It feels good enough that you might not need this, but maybe it could learn some tricks from this.
[0]: https://github.com/junegunn/fzf [1]: https://github.com/jimhester/per-directory-history
h -c 10
As a nice bonus, you also get to see the runtime of those 10 commands, out-of-the-box.alias jog="history --max=10"