pet
pet copied to clipboard
In bash, PREV=$(fc -lrn | head -n 1) doesn't retrieve the previous command
README.md suggests this function to add the last command to pet:
function prev() {
PREV=$(fc -lrn | head -n 1)
sh -c "pet new `printf %q "$PREV"`"
}
However, in bash PREV=$(fc -lrn | head -n 1)
results in storing PREV=$(fc -lrn | head -n 1) in PREV
:
paulo@monk:~$ ls
bash_completion.d bin bk data default Desktop doc Downloads foto gdrive go log Mail man PDF playlist RCS src stage tmp watch xubuntu 17.10.txt
paulo@monk:~$ PREV=$(fc -lrn | head -n 1)
paulo@monk:~$ echo "$PREV"
PREV=$(fc -lrn | head -n 1)
paulo@monk:~$
To work correctly in bash, that line should be:
PREV=$(fc -ln -1)
as you can see now:
paulo@monk:~$ ls
bash_completion.d bin bk data default Desktop doc Downloads foto gdrive go log Mail man PDF playlist RCS src stage tmp watch xubuntu 17.10.txt
paulo@monk:~$ PREV=$(fc -ln -1)
paulo@monk:~$ echo "$PREV"
ls
paulo@monk:~$
I'm struggling to get rid of the leading tab, piping the output to sed results in changing the history. If I find out a neat way of doing it, I will document it here.
Found out ! If there's a pipeline, bash seems to add the current command to the history BEFORE running fc
, so, to retrieve the last command and get rid of the leading tab, this would do it:
PREV=$(fc -ln -2 -2 | sed 's/[ \t]*//')
To show it in action:
paulo@monk:~$ ls
bash_completion.d bin bk data default Desktop doc Downloads foto gdrive go log Mail man PDF playlist RCS src stage tmp watch xubuntu 17.10.txt
paulo@monk:~$ PREV=$(fc -ln -2 -2 | sed 's/[ \t]*//')
paulo@monk:~$ echo $PREV
ls
paulo@monk:~$
As a suggestion, I'd replace function prev()
with an alias:
alias prev='cmd=$(fc -ln -2 -2 | sed "s/^[ \\t]*//"); eval pet new $(printf %q "$cmd")'
This is still not good. When I use tab completion to complete a command, and the add it to pet with prev
, with the alias that I suggested, the command comes with a trailing ****:
paulo@monk:~$ ls --all
. .bash_functions .cddb .face go .inputrc man .pki .sudo_as_admin_successful watch
.. .bash_history .config foto .goobook_auth.json .kde .mozilla playlist .thumbnails .Xauthority
.aptitude .bash_logout data .gconf .goobook_cache .launchpadlib .mplayer .profile tmp .XCompose
.audacity-data .bashrc default gdrive .goobookrc .lesshst .msmtprc RCS .vim .Xdefaults
.bash_aliases bin Desktop .ghc .gphoto .local .notmuch-config .sane .viminfo .xscreensaver
.bash_aliases.swp bk .dmrc .gimp-2.8 .gtkrc-2.0 log .pacplrc src .viminfo.tmp .xsession-errors
.bash_completion .cabal doc .gnome .gvimrc Mail .parallel stage .vimrc .xsession-errors.old
bash_completion.d .cache Downloads .gnupg .ICEauthority .mailcap PDF .stremio-server .w3m xubuntu 17.10.txt
paulo@monk:~$ prev
Command> ls --all\
Description>
I type ls -al
, then TAB
to autocomplete, typed another l
, TAB
again to continue autocompleting.
There's still some tweaking to do with this alias ...
This will solve the problem:
alias prev='cmd=$(fc -ln -2 -2 | sed -E "s/^[ \\t]*//; s/[ ]*\$//"); eval pet new $(printf %q "$cmd")'
Just discovered now that the problem with the trailing ** has nothing to do with autocompletion: if there are trailing spaces, they'll with be escaped by printf %q
, so they have to be removed before, as I did in the last version of the alias.