From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10290 invoked by alias); 20 Dec 2011 03:18:25 -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: 16652 Received: (qmail 7752 invoked from network); 20 Dec 2011 03:18:13 -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=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <111219191758.ZM9817@torch.brasslantern.com> Date: Mon, 19 Dec 2011 19:17:58 -0800 In-reply-to: Comments: In reply to milk "Zle history feature like that of many IRC clients?" (Dec 19, 10:39pm) References: X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users@zsh.org Subject: Re: Zle history feature like that of many IRC clients? MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Dec 19, 10:39pm, milk wrote: : : Specifically, if I were to type something, then : press the down arrow and get a blank input line So what you're asking for is to bind down-arrow to a sort of "put this in the history but don't send it" action? Presumably, though, if you've already pressed up-arrow at least once so you are in the middle of the history, then you just want down-arrow to move through the history like it normally does. Let's build it up from some pieces. First, a "fake-accept-line" to not really execute the command, but put it on the history. There are several different ways to do this with preexec hooks etc., but let's just do it the old-fashioned way: fake-accept-line() { if [[ -n "$BUFFER" ]]; then print -S "$BUFFER" zle .send-break fi return 0 } zle -N fake-accept-line If your version of zsh doesn't have "print -S", use "-s" instead. It's not perfect but it'll do. Using "zle .send-break" at the end sets the correct return value and makes the history from "print -S" immediately available for recall, but interrupts whatever else you have going on so it does mean that fake-accept-line has to be the last thing you want to do before getting a new prompt. The leading dot in ".send-break" tells zle to call the widget by its unalterable name, so you won't be messed up by some other configuration rebinding the widget. Make note of this for below. Also note that you can't create an unalterable name for a user-defined widget, those are only for builtins. Next you want a function that does down-line-or-history [probably; you might want down-history instead, but I can't tell from your description] unless there is nowhere to go, in which case it does fake-accept-line. down-or-fake-accept-line() { (( HISTNO == HISTCMD )) && zle fake-accept-line zle .down-line-or-history "$@" } zle -N down-or-fake-accept-line There I've done a shortcut: I know fake-accept-line is going to break out of the surrounding function if it does anything at all, so there's no need for an else-case, I can fall through to down-line-or-history. Finally you just need to bind it to a key. To avoid all the messiness of figuring out what sequence of characters your down-arrow key may send, it's often easier to simply grab the widget that is already bound to that key and alias it to your new widget. zle -N down-line-or-history down-or-fake-accept-line This has now swapped out down-line-or history for this widget anywhere that down-line-or-history was used (such as, all the default keymaps), but not inside down-or-fake-accept-line itself, where we have avoided infinite recursion by using the unalterable name. If you prefer not to do it this way, add a bindkey command such as bindkey '^[[B' down-or-fake-accept-line which depending on your terminal might mean down-arrow.