Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: multiline ZLE w/ bash-like single line .zsh_history...?



Thank you very much for your excellent reply!

I tried your second zshaddhistory example to create a parallel history
file that has the bash-format:

  zshaddhistory() {
    fc -p ${HISTFILE}_bash_format $HISTSIZE $SAVEHIST
    print -sr "${(z)1%%$'\n'}"
    return 0
  }

Unfortunately, it's not working for me...  It creates the file but
never writes any lines to it.  Even worse, the normal history file
($HISTFILE) is no longer written to either.

As an experiment, I tried this:

  zshaddhistory() {
    print -r "${(z)1%%$'\n'}" >>${HISTFILE}_bash_format
    return 0
  }

This works like a champ (and normal history is OK too).  The problem
with this solution is that the new file does not get the benefit of
ZSH's "history smarts".  It does show that the hook and the z-flag
expansion are working though...

On my normal system I'm running this version of ZSH:

  print $ZSH_VERSION $ZSH_PATCHLEVEL 

    4.3.10 Debian

Since I feared a debian bug, I tried it on OpenBSD too:

  print $ZSH_VERSION $ZSH_PATCHLEVEL

    4.3.10 1.4705

Both systems were the same...  I even tried it with a "stripped down"
.zshrc file, and that was also to no avail.

Because maintaining a parallel history file is not super-optimal to
me, and based on inspiration from the above, I took an alternate route
and it seems to be working for me at the moment.  It uses a little
perl hack (sorry it's not in ZSH!):

---------------------------------

#!/usr/bin/perl
#
# zsh_cook_history
#
# This script accepts a zsh format history file on STDIN and will
# print all multiline commands as single line commands (bash-like).
#
# Activate this script in ZSH (.zshrc) like so:
#
#   if ( which zsh_cook_history >/dev/null 2>&1 ) ; then
#     alias history="fc -IA ; cat $HISTFILE | zsh_cook_history"
#   else
#     alias history="fc -IA ; cat $HISTFILE"
#   fi
#   alias h=history
#

while (<>) {
  chomp;                       # remove the newline
  s/(?<=^\s)\s+// if $l;       # allow a lead space if multiline
  s/\s+(?=\\+$)//;             # ... but no trailing white space
  $l .= $_;                    # start building a command line
  unless( $l =~ s{\\\\$}{} ||  # a double slash is merely removed
          $l =~ s{\\$}{;} ) {  # a single slash becomes a ';'...
    print "$l\n";              # no more slashes: print the result
    undef $l;                  # start over
  }
}






On Mon, Dec 06, 2010 at 08:47:48PM -0800, Bart Schaefer wrote:
> On Dec 6, 11:02am, zsh@xxxxxxxx wrote:
> }
> } I like the multiline capability of ZLE, but when history lines are
> } appended to the .zsh_history file, I would like for multiline commands
> } to be morphed into a single line (similar to what bash does).
> 
> In a sufficiently new zsh, there is a zshaddhistory hook function
> (like precmd, chpwd, etc.).  You can manipulate the history any way
> you like; e.g., the following saves each line of the multiline as a
> single line in the history:
> 
>     zshaddhistory() { print -sr "${(z)1%%$'\n'}"; return 1 }
> 
> (And I finally get another chance to point out to PWS why it's a good
> thing that (z) converts newlines into semicolons ... but it also
> reveals a bug in the handling of here-documents ... moving that over
> to zsh-workers.)  [Bash appears to ignore here-documents entirely?]
> 
> As was discussed in a lengthy thread earlier this year, the full multi-
> line command "lingers" in the interactive history for one cycle even
> if zshaddhistory returns nonzero.
> 
> } Is there a way to get zsh to be bash-like when it writes to the
> } history file...?  I'm willing to lose the multiline niceness for old
> } commands in new shells.
> 
> There is not a way to get the interactive history and the history file
> to behave differently from one another, except by using more than one
> history file (the "fc -p" example for zshaddhistory in the manual).
> You could, for example, do
> 
>     zshaddhistory() {
>       fc -p ${HISTFILE}_bash_format $HISTSIZE $SAVEHIST
>       print -sr "${(z)1%%$'\n'}"
>       return 0
>     }
> 
> which would still save in zsh native format in $HISTFILE, but keep a
> bash-format copy in a parallel file.



Messages sorted by: Reverse Date, Date, Thread, Author