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

Re: Working with the historywords special parameter



On Aug 27, 11:19pm, Felix Rosencrantz wrote:
}
} --- Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
} >Have you tried using $history instead of $historywords?  You want the
} >word that comes immediately after $words[CURRENT-1] in every history
} >line that contains $word[CURRENT-1], right?
} >
} >    local w p h r
} >    w=${(q)words[CURRENT-1]}
} >    p=$'\0'$w$'\0'
} >    h=$'\0'${(pj:\0:)${(z)history[(R)*$w*]}}
} >    r=( ${${(ps:\1:)h//$~p/$'\1'}%%$'\0'*} )
} >    compadd -a r
} >
} >This assumes there are no literal NUL or ctrl-A characters in the
} >history, but that seems a pretty safe assumption.
} 
} The other problem is that it didn't know about line boundaries. So if
} the searched for word was at the end of the line, then it would return
} a match for the previous command, which is wrong.

Stick a $'\1' on the end of each line so that $'\0'$w$'\0' won't match
the last word:

    local w p h r
    w=${(q)words[CURRENT-1]}
    p=$'\0'$w$'\0'
    #
    h=( ${^history[(R)*$w*]}$'\1' )
    h=$'\0'${(pj:\0:)${(z)h}}
    r=( ${${(ps:\1:)h//$~p/$'\1'}%%$'\0'*} )
    #
    compadd -a r

To see which is faster, you can replace the three lines between the `#'
with:

    r=()
    for h in $history[(R)*$w*]
    do
	h=$'\0'${(pj:\0:)${(z)h}}
	r[$#r+1]=( ${${(ps:\1:)h//$~p/$'\1'}%%$'\0'*} )
    done

I suspect the first way is faster because it does fewer, though larger,
memory allocations.

The loop body could be one line if not for the need to prepend $'\0' to
the join.

} Also, I was wondering if the (z) modifier applied to the elements of
} history would always return the same results as found by historywords?

No, it won't.  $historywords is more like $=history, but it isn't quite
that either -- the rules for what is a "word" in $historywords are a bit
odd.  E.g., quoted strings are broken up at whitespace, but =(...) are
kept as single words.  Also, it appears that $historywords has the words
from the current input line, whereas $history doesn't get that line added
until after the command has been parsed -- but I'm not sure about that.

I think ${(z)history} is more accurate for purposes of completion.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   



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