From: Lars Ingebrigtsen Date: Mon, 14 Oct 2019 03:09:32 +0000 (+0200) Subject: Allow zap-to-char to use a history X-Git-Tag: emacs-27.0.90~1089 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a590a8058d52c1cbe0f80b7ed0d8b0abed7bf7ef;p=emacs.git Allow zap-to-char to use a history * doc/emacs/killing.texi (Other Kill Commands): Document it. * lisp/simple.el (read-char-with-history): New function (bug#10477). (zap-to-char): Use it to have a history. --- diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi index c554d2e2839..80e2868908a 100644 --- a/doc/emacs/killing.texi +++ b/doc/emacs/killing.texi @@ -244,7 +244,10 @@ with @kbd{C-x @key{DEL}} and @kbd{M-k} (@pxref{Sentences}). searching: it reads a character and kills from point up to (and including) the next occurrence of that character in the buffer. A numeric argument acts as a repeat count; a negative argument means to -search backward and kill text before point. +search backward and kill text before point. A history of previously +used characters is maintained and can be accessed via the +@kbd{M-p}/@kbd{M-n} keystrokes. This is mainly useful if the +character to be used has to be entered via a complicated input method. @node Kill Options @subsection Options for Killing diff --git a/etc/NEWS b/etc/NEWS index 4e62627f907..8f95496705f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -453,6 +453,12 @@ Note that this key binding will not work on MS-Windows systems if * Editing Changes in Emacs 27.1 ++++ +** 'zap-to-char' uses the new 'read-char-with-history' function to allow +navigating through the history of characters that have been input. +This is mostly useful for characters that have complex input methods +where inputting the character again may involve many keystrokes. + +++ ** 'save-some-buffers' now has a new action in the prompt: 'C-f' will exit the command and switch to the buffer currently being asked about. @@ -2376,6 +2382,10 @@ scrolling. * Lisp Changes in Emacs 27.1 +** There is a new function 'read-char-with-history' that works like +'read-char', but maintains a history that can be navigated via the +'M-p'/'M-n' keystrokes. + ** 'setq-local' can now set an arbitrary number of variables, which makes the syntax more like 'setq'. diff --git a/lisp/simple.el b/lisp/simple.el index 4d80c4c1b4d..2add2669604 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5159,12 +5159,80 @@ and KILLP is t if a prefix arg was specified." ;; Avoid warning about delete-backward-char (with-no-warnings (delete-backward-char n killp)))) +(defvar read-char-with-history--history nil + "The default history for `read-char-with-history'.") + +(defun read-char-with-history (prompt &optional inherit-input-method seconds + history) + "Like `read-char', but allows navigating in a history. +HISTORY is like HIST in `read-from-minibuffer'. + +The navigation commands are `M-p' and `M-n', with `RET' to select +a character from history." + (let* ((result nil) + (real-prompt prompt) + (hist-format + (lambda (char) + (if (string-match ": *\\'" real-prompt) + (format "%s (default %c): " + (substring real-prompt 0 (match-beginning 0)) + char) + (format "%s (default %c) " real-prompt char)))) + (index 0) + histvar) + ;; Use the same history interface as `read-from-minibuffer'. + (cond + ((null history) + (setq histvar 'read-char-with-history--history)) + ((consp history) + (setq histvar (car history) + index (cdr history))) + ((symbolp history) + (setq histvar history)) + (t + (error "Invalid history: %s" history))) + (while (not result) + (setq result (read-char prompt inherit-input-method seconds)) + ;; Go back in history. + (cond + ((eq result ?\M-p) + (if (>= index (length (symbol-value histvar))) + (progn + (message "Beginning of history; no preceding item") + (ding) + (sit-for 2)) + (setq index (1+ index) + prompt (funcall hist-format + (elt (symbol-value histvar) (1- index))))) + (setq result nil)) + ;; Go forward in history. + ((eq result ?\M-n) + (if (zerop index) + (progn + (message "End of history; no next item") + (ding) + (sit-for 2)) + (setq index (1- index) + prompt (if (zerop index) + real-prompt + (funcall hist-format + (elt (symbol-value histvar) (1- index)))))) + (setq result nil)) + ;; The user hits RET to either select a history item or to + ;; return RET. + ((eq result ?\r) + (unless (zerop index) + (setq result (elt (symbol-value histvar) (1- index))))))) + ;; Record the chosen key. + (set histvar (cons result (symbol-value histvar))) + result)) + (defun zap-to-char (arg char) "Kill up to and including ARGth occurrence of CHAR. Case is ignored if `case-fold-search' is non-nil in the current buffer. Goes backward if ARG is negative; error if CHAR not found." (interactive (list (prefix-numeric-value current-prefix-arg) - (read-char "Zap to char: " t))) + (read-char-with-history "Zap to char: " t))) ;; Avoid "obsolete" warnings for translation-table-for-input. (with-no-warnings (if (char-table-p translation-table-for-input)