emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Losing minibuffer input


From: Juri Linkov
Subject: Losing minibuffer input
Date: Sun, 09 Nov 2014 19:57:27 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (x86_64-pc-linux-gnu)

There is a long-standing usability problem when editing multi-line text in
the minibuffer: it's too easy to lose edited text by pressing an up-down
arrow key with the intention to go to the next/previous line like in a
normal buffer.  The changes are lost because the up-down key has a special
meaning in the minibuffer to go to the next/previous history item.

The fix is simple: allow up-down arrow keys to have their usual behavior
and only on hitting the beginning/end of the minibuffer move to the next
or previous history item, thus making navigation more smooth and continuous.

=== modified file 'lisp/bindings.el'
--- lisp/bindings.el    2014-07-21 05:38:17 +0000
+++ lisp/bindings.el    2014-11-09 17:56:08 +0000
@@ -839,11 +839,11 @@ (define-key global-map [XF86Back] 'previ
 (let ((map minibuffer-local-map))
   (define-key map "\en"   'next-history-element)
   (define-key map [next]  'next-history-element)
-  (define-key map [down]  'next-history-element)
+  (define-key map [down]  'next-line-or-history-element)
   (define-key map [XF86Forward] 'next-history-element)
   (define-key map "\ep"   'previous-history-element)
   (define-key map [prior] 'previous-history-element)
-  (define-key map [up]    'previous-history-element)
+  (define-key map [up]    'previous-line-or-history-element)
   (define-key map [XF86Back] 'previous-history-element)
   (define-key map "\es"   'next-matching-history-element)
   (define-key map "\er"   'previous-matching-history-element)

=== modified file 'lisp/simple.el'
--- lisp/simple.el      2014-11-08 23:52:59 +0000
+++ lisp/simple.el      2014-11-09 17:57:01 +0000
@@ -1982,6 +1982,36 @@ (defun previous-history-element (n)
   (or (zerop n)
       (goto-history-element (+ minibuffer-history-position n))))
 
+(defun next-line-or-history-element (&optional arg)
+  "Move cursor vertically down ARG lines, or to the next history element.
+When point is at the bottom line of multi-line minibuffer, puts ARGth
+next element of the minibuffer history in the minibuffer."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (let ((old-point (point)))
+    (condition-case nil
+       (next-line arg)
+      (end-of-buffer
+       ;; Restore old position since `line-move-visual' moves point to
+       ;; the end of the line when it fails to go to the next line.
+       (goto-char old-point)
+       (next-history-element arg)))))
+
+(defun previous-line-or-history-element (&optional arg)
+  "Move cursor vertically up ARG lines, or to the previous history element.
+When point is at the top line of multi-line minibuffer, puts ARGth
+previous element of the minibuffer history in the minibuffer."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (let ((old-point (point)))
+    (condition-case nil
+       (previous-line arg)
+      (beginning-of-buffer
+       ;; Restore old position since `line-move-visual' moves point to
+       ;; the beginning of the line when it fails to go to the previous line.
+       (goto-char old-point)
+       (previous-history-element arg)))))
+
 (defun next-complete-history-element (n)
   "Get next history element which completes the minibuffer before the point.
 The contents of the minibuffer after the point are deleted, and replaced




reply via email to

[Prev in Thread] Current Thread [Next in Thread]