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

Re: Completing strings from history?



On Mar 26,  2:34pm, Peter Stephenson wrote:
} Subject: Re: Completing strings from history?
}
} > Is it possible to set things up so that repeatedly typing <ESC-/>
} > cycles back through all matches in the history? (ala Emacs'
} > dabbrev-expand)
} 
} You can do this by setting the `stop' style, which is so called
} because it stops when it has reached as far back into the history as
} it can (unlike normal menu completion which would continue cycling).
} 
}   zstyle ':completion:history-words:*' stop 1

Hmm, this works, but it's a bit strange -- it beeps every time there's a
completion, and stops beeping when it has run out of completions (which
I think is because it believes it has found a unique match).

You can at least see what it's doing if you use:

    zstyle ':completion:history-words:*' stop verbose
 
} You should also be able to turn on menu completion just in this context,
} but I couldn't get that to work with a brief try, for some reason.

Turning on menu completion should have approximately the same effect as
the `stop' style.  (I'm not sure if that's intentional, or if the intent
was instead to cycle, but the function doesn't differentiate between the
`stop' style and menu completion.)

However, _history_complete_word tests for menu completion by examining
compstate[insert], not by examining a style, and _history_complete_word
is a widget wrapper around _main_complete, so the only way that you can
get compstate[insert] to be `menu' is to `setopt menucomplete' and also
to `unsetopt automenu' (I think).

Finally, the manual entry for the `stop' style is a little misleading:
If it's set to ANYTHING, you get stopping-menu behavior, with the extra
effect of `verbose' as described; setting the style to `false' or `0'
won't do what's implied.
 
} What doesn't work which probably ought to is that if you type `\e,'
} (_history-complete-newer) it should cycle back in the other direction.

The function attempts to do that, but it gets it wrong in the boundary
conditions; that is, if you've ever actually reached the beginning or the
end of the history, you lose the ability to reverse direction.  Maybe that
was intentional too (no point in showing you the entire history more than
once) but somehow I doubt it.

The following patch makes `setopt menucomplete' cycle through the history;
the `return 0' are an attempt to stop the accursed beeping, but that does
not work for some reason.  Someone more immersed in the completion code
than I will have to work out the other problems; I don't have more time
this morning to fiddle with it.

Index: Completion/Commands/_history_complete_word
===================================================================
--- Completion/Commands/_history_complete_word	2001/02/28 17:05:07	1.24
+++ Completion/Commands/_history_complete_word	2001/03/26 16:14:23
@@ -56,19 +56,32 @@
     if [[ "$direction" == 'older' ]]; then
       if [[ compstate[old_insert] -eq $_hist_menu_length ||
             "$_hist_stop" == 'oldest' ]]; then
-        _hist_stop='oldest'
         [[ "$stop" = verbose ]] &&
           _message 'beginning of history reached'
+	if [[ -n "$stop" ]]; then
+	  _hist_stop='oldest'
+	else
+	  compstate[old_list]=keep
+	  (( compstate[insert] = 1 ))
+	  return 0
+	fi
       elif [[ "$_hist_stop" == 'newest' ]]; then
         zle -Rc
         _history_complete_word_gen_matches
       else
         compstate[old_list]=keep
         (( compstate[insert] = compstate[old_insert] + 1 ))
+	return 0
       fi
     elif [[ "$direction" == 'newer' ]]; then
       if [[ compstate[old_insert] -eq 1 || "$_hist_stop" == 'newest' ]]; then
-        _hist_stop='newest'
+	if [[ -n "$stop" ]]; then
+          _hist_stop='newest'
+	else
+	  compstate[old_list]=keep
+	  (( compstate[insert] = $_hist_menu_length ))
+	  return 0
+	fi
         [[ "$stop" = verbose ]] && _message 'end of history reached'
       elif [[ "$_hist_stop" == 'oldest' ]]; then
         zle -Rc
@@ -76,6 +89,7 @@
       else
         compstate[old_list]=keep
         (( compstate[insert] = compstate[old_insert] - 1 ))
+	return 0
       fi
     fi
   else

-- 
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