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

Re: Trouble with 'fc -l'

On Feb 16,  5:41pm, Ray Andrews wrote:
} function z ()
} {
}    fc -R
}    fc -l -1
} }
} When 'z' is executed, my entire saved history scrolls past and history 
} itself is 'advanced' by several thousand places.

This is subtle, and the documentation is could be clearer.

     Select a range of commands from FIRST to LAST from the history
     list.  The arguments FIRST and LAST may be specified as a number
     or as a string.  A negative number is used as an offset to the
     current history event number.  A string specifies the most recent
     event beginning with the given string.

     If FIRST is not specified, it will be set to -1 (the most recent
     event), or to -16 if the -l flag is given.  If LAST is not
     specified, it will be set to FIRST, or to -1 if the -l flag is

Note "offset to the current history event number".

Let's say you're on history event number 127, and you have SAVEHIST=100,
and you've been running the shell long enough that there actually are
100 saved commands in $HISTFILE.  This means you actually have 126
events in the shell history and are about to execute number 127.  You
now execute your "z" function.

"fc -R" re-reads 100 events from $HISTFILE and appends then to the
current history.  This increments the largest event number to 227, but
it DOES NOT change the "current history event number" of the command
that you just ran!  Your HISTSIZE now kicks in.  If it's larger than
227, nothing happens.  If it is smaller, say 200, then the oldest 27
events are discarded and you now have 200 events numbered 28 through
227, and you are currently on event 127 ("z").  "fc -R" is done.

Now "fc -l -1" kicks in and applies the "offset to current event" rule,
coming up with a FIRST event of 126.  (If you do not give -1, then it
is offset -16 from the "most recent" history number, and you get 212.)
Next LAST has to be computed, and this is where things get strange:
if you did NOT specify a number for LAST (as is the case here) AND the
"current event" is NOT the "most recent event", then LAST is computed
relative to the "most recent event" instead of the "current event",
and you get a range of 126 through 227.  These 102 events are then
printed and "fc -l" is done.

This oddity with LAST is done so that if you explicitly shove events
onto the the history with "print -s" or the like, "history" ("fc -l")
will show you what you added.  "fc -R" happens to be a (very large)
case of the same thing.  If it behaved exactly the way the doc reads,
you'd see only event 126 (or get "no such event" because HISTSIZE
lopped that event off the front) and be puzzled about why it doesn't
show you the newly-added events.

} But whenever I try to modify " fc -l ... " in any way, I get 
} either a "no such event: 0" message, or ,again, the whole of history 
} scrolls by.

The "no such event" message probably occurs when HISTSIZE has caused
enough events to be thrown away that both FIRST and LAST are before
the earliest remaining history number.  This would only occur if you
actually provided a value for LAST, because in that case it goes back
to counting from "current event" instead of "most recent" (and that
whole history you just loaded with "fc -R" becomes invisible).

So how exactly does one display the most recent event from a newly-
reloaded history?  That's where the HISTCMD parameter comes in:

    z() {
      fc -R
      fc -l $HISTCMD

Unlike the "current event", the value of HISTCMD is incremented when
the new history is read.  (Hmm, seems the doc for HISTCMD is also
incomplete.)  Note that before "fc -R", $HISTCMD refers to the event
number assigned to the current command (as its doc says), but after
"fc -R" (or "print -s") it refers to the last event that was loaded
(and the "most recent event" is $[HISTCMD+1] even though that hasn't
happened yet).

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