From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7239 invoked by alias); 2 Aug 2013 11:18:43 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 17906 Received: (qmail 24945 invoked from network); 2 Aug 2013 11:18:34 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI, SPF_HELO_PASS autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at samsung.com does not designate permitted sender hosts) X-AuditID: cbfec7f5-b7f376d000001ec6-a8-51fb932b069a Date: Fri, 02 Aug 2013 12:08:26 +0100 From: Peter Stephenson To: zsh-users@zsh.org Subject: Re: search through alternative HISTFILE Message-id: <20130802120826.616671d9@pwslap01u.europe.root.pri> In-reply-to: <51FB8C33.30108@gmail.com> References: <51FB8C33.30108@gmail.com> Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: multipart/mixed; boundary="MP_/Suyv2y/_vB3D/oov3Yc4zdo" X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrLLMWRmVeSWpSXmKPExsVy+t/xK7rak38HGmxdxWmx4+RKRgdGj1UH PzAFMEZx2aSk5mSWpRbp2yVwZVzpP8xU8NK5Ytr99cwNjOtMuhg5OSQETCQuHrnGCGGLSVy4 t56ti5GLQ0hgKaPEiem9rFAOk8S/B0dZQapYBFQlmq8/AOtgEzCUmLppNpgtIiAqsXzFZvYu Rg4OYQEDib+PLEHCvAL2EpPXzWUDsTkF1CVOvPnEAmILCahJzFz0H8zmF9CXuPr3ExPEEfYS M6+cYYToFZT4MfkeC8hIZgFXiU8rdCYw8s9CkpmFkAEJMwtoSTz8dYsFwpaX2P52DjNEibTE 8n8cEGEJiYMvXjCjKgGxHSWW9i1lxK/GVmLVgaesCxi5VzGKppYmFxQnpeca6RUn5haX5qXr JefnbmKERMnXHYxLj1kdYhTgYFTi4bXI+RUoxJpYVlyZe4hRgoNZSYT3z2ygEG9KYmVValF+ fFFpTmrxIUYmDk6pBsayV+c+Z/0JUQpaqjtx/4VFT62uJ+ovPs6QtkKQqVK6a5XjhH9xVWuP P9M9+axvFefOrvXxgXPtPU1E8q2OCz9+uuqmn/6u1Tvfqv9aPTmXvfziBcFVuecvLi7fsMqr eebGfU+9rl2x6z6tNLFw4p+3bp86Xx+/92nl18ccG013BhgsXDhx3bJyDiWW4oxEQy3mouJE AFYb7LFwAgAA --MP_/Suyv2y/_vB3D/oov3Yc4zdo Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline On Fri, 02 Aug 2013 12:38:43 +0200 Maarten Grachten wrote: > As part of an attempt to archive my command line history, I have a need > for bck-i-search (as normally invoked by Ctrl-R), but with a history > file that is not $HISTFILE, that is, a different file from that which > the current shell uses for saving its history. > > As I envision it, Ctrl-R would still search through the current shell's > history (i.e. through $HISTFILE), and another key binding would search > through an alternative but constant histfile (say > $HOME/.accumulated-history). > > Is this possible, and if so, can any of you give me a hint as to how to > achieve it? It's not quite what you want but it might provide a start since the bits underneath are pretty similar... I've attached a ZLE widget I've been using for a few years that I never quite made neat enough to post. It uses the history-beginning-search-backward interface rather than the isearch interface, but that shouldn't be too hard to change. The idea is it can search backwards both through the main history and a local history file with the name defined by a style; as an optional extra it decides by means of what's on the command line so far whether to search the local history. Your use is actually slightly simpler. For good measure, I've also attached a hook function for use with the zshaddhistory hook that decides whether to save a command locally (again, this is more than you actually asked for but might be useful). pws --MP_/Suyv2y/_vB3D/oov3Yc4zdo Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=history-beginning-local # history-beginning-local # # Mostly a drop-in replacement for history-beginning-search-backward # or -forward, depending on the name. # # Allows a local history file to be searched for certain commands to execute. # The style local-history-file should be set to a list of files that # can contain the local history, in the same format as $HISTFILE. # The files are searched in order until the first is find. They # can contain a relative or absolute path; clearly an absolute # path to an existing file will always match. # # local-history-commands should be set to a list of commands # (or patterns matching commands) that should use the local history # file; this can be "*" to handle all commands. Both styles be set. # # Alternatively (or in addition), local-history-pattern is a scalar # that gives a pattern that must match the command line exactly to # initiate use of the mechanism. Typically this will end in a "*". # # If the style local-history-only is not set the global history # will be searched if there is no match in the local history. # The global history is tried again from the most recent entry; # no ordering is implied between the two histories. (Note # this style is also checked by zshaddhistory-local to decide # whether to save a history entry to the global history.) # # If the style local-history-verbose is set a notice is printed # below the command line if the local history was searched. # # Styles use the standard form of components separated by colons. # The components are # - The string "zhist": used rather than "zle" to make this consistent # across different functions handling history in different parts of # the shell. # - The widget name # - The current directory as given by $PWD. # There is a terminating colon. It is recommended that a wildcard be # used at the end to protect against future enhancements. # # For example, # zstyle ':zhist:*' local-history-file .zsh-local-history # zstyle ':zhist:*' local-history-commands make gcc gdb emulate -L zsh setopt extendedglob local w f new lhp curline local -a lhf lhc integer lhv lho restore typeset -gA __history_beginning_matches if [[ $WIDGET != $LASTWIDGET ]]; then __history_beginning_matches=() fi integer oldcursor=CURSOR zstyle -a ":zhist:${WIDGET}:${PWD}:" local-history-file lhf || return 1 zstyle -a ":zhist:${WIDGET}:${PWD}:" local-history-commands lhc || return 1 zstyle -s ":zhist:${WIDGET}:${PWD}:" local-history-pattern lhp zstyle -t ":zhist:${WIDGET}:${PWD}:" local-history-verbose && lhv=1 zstyle -t ":zhist:${WIDGET}:${PWD}:" local-history-only && lho=1 # try / always block for restoring history { for f in $lhf; do if [[ -f $f ]]; then integer iline local -a words found words=(${(z)BUFFER}) if [[ ${(Q)words[1]} = (${(j.|.)~lhc}) || \ ( -n $lhp && ${BUFFER} = ${~lhp} ) ]]; then (( restore = 1 )) fc -p $f # Search history for pattern. # As $history is an associative array we can get all matches. if [[ $WIDGET = *forw* ]]; then # Searching forward. Look back through matches until we # get back to the current history number. found=(${(kOn)history[(R)${LBUFFER}*]}) for iline in $found; do (( $iline <= HISTNO )) && break # Skip duplicates. curline=$history[$iline] [[ $curline = $BUFFER ]] && continue [[ -n ${__history_beginning_matches[$curline]} ]] && continue new=$iline done else # Searching backward. Look forward through matches until we # reach the current history number. found=(${(kon)history[(R)${LBUFFER}*]}) for iline in $found; do (( $iline >= HISTNO )) && break # Skip duplicates. curline=$history[$iline] [[ $curline = $BUFFER ]] && continue [[ -n ${__history_beginning_matches[$curline]} ]] && continue new=$iline done fi [[ -n $new ]] && break fc -P (( restore = 0 )) fi fi done if [[ -n $new ]]; then # Match found. Move to line. HISTNO=$new __history_beginning_matches[$history[$HISTNO]]=1 if [[ $WIDGET = *-end* ]]; then zle end-of-line else (( CURSOR = oldcursor )) fi (( lhv )) && zle -M "Matched in local history" return 0 elif (( lho )); then (( lhv )) && zle -M "No match in local history" return 1 else (( lhv )) && zle -M "No match in local history; falling through" fi } always { (( restore )) && fc -P } if [[ $WIDGET = *forw* ]]; then zle history-beginning-search-forward else zle history-beginning-search-backward fi local stat=$? if (( $stat == 0 )); then __history_beginning_matches[$history[$HISTNO]]=1 fi if [[ $WIDGET = *-end* ]]; then zle end-of-line else (( CURSOR = oldcursor )) fi return $stat # end --MP_/Suyv2y/_vB3D/oov3Yc4zdo Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=zshaddhistory-local # This function is an adjunct to the history-beginning-local # zle widget. It saves any history entries that would be # found by that widget in the local history file, provided that # already exists. It also saves the history globally unless # the local-history-only style is set in the context. # # The context is :zhist: followed by the function name, a colon, the # current directory from $PWD, and another colon. emulate -L zsh setopt extendedglob warncreateglobal zmodload -i zsh/parameter local name=${funcstack[1]} lhp f local -a lhf lhc integer lho zstyle -a ":zhist:${name}:${PWD}:" local-history-file lhf || return 1 zstyle -a ":zhist:${name}:${PWD}:" local-history-commands lhc || return 1 zstyle -s ":zhist:${WIDGET}:${PWD}:" local-history-pattern lhp zstyle -t ":zhist:${name}:${PWD}:" local-history-only && lho=1 for f in $lhf; do if [[ -f $f ]]; then local -a words words=(${(z)1}) if [[ ${(Q)words[1]} = (${(j.|.)~lhc}) || \ ( -n $lhp && $1 = ${~lhp} ) ]]; then # Save on the global history unless we're told not to. # If we define multiple zshaddhistory hooks we want a # a way of signalling that we've done this. One way # of doing this would be to set a global parameter to $HISTCMD, # although that doesn't change if we've ignored the previous line. # Another way would be to have a zshaddhistoryhook that reset # a global parameter (since this is called first) and rely # on all the other hooks being in zshaddhistory_functions, # as they should be for neatness. (( lho )) || print -Sr -- ${1%%$'\n'} fc -p -- $f break fi fi done --MP_/Suyv2y/_vB3D/oov3Yc4zdo--