summaryrefslogtreecommitdiff
path: root/lisp/simple.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/simple.el')
-rw-r--r--lisp/simple.el248
1 files changed, 205 insertions, 43 deletions
diff --git a/lisp/simple.el b/lisp/simple.el
index 6148a917f59..ab7370b02ec 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -156,6 +156,15 @@ If `fringe-arrow', indicate the locus by the fringe arrow."
:group 'next-error
:version "22.1")
+(defcustom next-error-recenter nil
+ "*Display the line in the visited source file recentered as specified.
+If non-nil, the value is passed directly to `recenter'."
+ :type '(choice (integer :tag "Line to recenter to")
+ (const :tag "Center of window" (4))
+ (const :tag "No recentering" nil))
+ :group 'next-error
+ :version "23.1")
+
(defcustom next-error-hook nil
"*List of hook functions run by `next-error' after visiting source file."
:type 'hook
@@ -305,6 +314,8 @@ See variables `compilation-parse-errors-function' and
;; we know here that next-error-function is a valid symbol we can funcall
(with-current-buffer next-error-last-buffer
(funcall next-error-function (prefix-numeric-value arg) reset)
+ (when next-error-recenter
+ (recenter next-error-recenter))
(run-hooks 'next-error-hook))))
(defun next-error-internal ()
@@ -313,6 +324,8 @@ See variables `compilation-parse-errors-function' and
;; we know here that next-error-function is a valid symbol we can funcall
(with-current-buffer next-error-last-buffer
(funcall next-error-function 0 nil)
+ (when next-error-recenter
+ (recenter next-error-recenter))
(run-hooks 'next-error-hook)))
(defalias 'goto-next-locus 'next-error)
@@ -1287,55 +1300,61 @@ makes the search case-sensitive."
(defvar minibuffer-temporary-goal-position nil)
+(defun goto-history-element (nabs)
+ "Puts element of the minibuffer history in the minibuffer.
+The argument NABS specifies the absolute history position."
+ (interactive "p")
+ (let ((minimum (if minibuffer-default -1 0))
+ elt minibuffer-returned-to-present)
+ (if (and (zerop minibuffer-history-position)
+ (null minibuffer-text-before-history))
+ (setq minibuffer-text-before-history
+ (minibuffer-contents-no-properties)))
+ (if (< nabs minimum)
+ (if minibuffer-default
+ (error "End of history; no next item")
+ (error "End of history; no default available")))
+ (if (> nabs (length (symbol-value minibuffer-history-variable)))
+ (error "Beginning of history; no preceding item"))
+ (unless (memq last-command '(next-history-element
+ previous-history-element))
+ (let ((prompt-end (minibuffer-prompt-end)))
+ (set (make-local-variable 'minibuffer-temporary-goal-position)
+ (cond ((<= (point) prompt-end) prompt-end)
+ ((eobp) nil)
+ (t (point))))))
+ (goto-char (point-max))
+ (delete-minibuffer-contents)
+ (setq minibuffer-history-position nabs)
+ (cond ((= nabs -1)
+ (setq elt minibuffer-default))
+ ((= nabs 0)
+ (setq elt (or minibuffer-text-before-history ""))
+ (setq minibuffer-returned-to-present t)
+ (setq minibuffer-text-before-history nil))
+ (t (setq elt (nth (1- minibuffer-history-position)
+ (symbol-value minibuffer-history-variable)))))
+ (insert
+ (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
+ (not minibuffer-returned-to-present))
+ (let ((print-level nil))
+ (prin1-to-string elt))
+ elt))
+ (goto-char (or minibuffer-temporary-goal-position (point-max)))))
+
(defun next-history-element (n)
"Puts next element of the minibuffer history in the minibuffer.
With argument N, it uses the Nth following element."
(interactive "p")
(or (zerop n)
- (let ((narg (- minibuffer-history-position n))
- (minimum (if minibuffer-default -1 0))
- elt minibuffer-returned-to-present)
- (if (and (zerop minibuffer-history-position)
- (null minibuffer-text-before-history))
- (setq minibuffer-text-before-history
- (minibuffer-contents-no-properties)))
- (if (< narg minimum)
- (if minibuffer-default
- (error "End of history; no next item")
- (error "End of history; no default available")))
- (if (> narg (length (symbol-value minibuffer-history-variable)))
- (error "Beginning of history; no preceding item"))
- (unless (memq last-command '(next-history-element
- previous-history-element))
- (let ((prompt-end (minibuffer-prompt-end)))
- (set (make-local-variable 'minibuffer-temporary-goal-position)
- (cond ((<= (point) prompt-end) prompt-end)
- ((eobp) nil)
- (t (point))))))
- (goto-char (point-max))
- (delete-minibuffer-contents)
- (setq minibuffer-history-position narg)
- (cond ((= narg -1)
- (setq elt minibuffer-default))
- ((= narg 0)
- (setq elt (or minibuffer-text-before-history ""))
- (setq minibuffer-returned-to-present t)
- (setq minibuffer-text-before-history nil))
- (t (setq elt (nth (1- minibuffer-history-position)
- (symbol-value minibuffer-history-variable)))))
- (insert
- (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
- (not minibuffer-returned-to-present))
- (let ((print-level nil))
- (prin1-to-string elt))
- elt))
- (goto-char (or minibuffer-temporary-goal-position (point-max))))))
+ (goto-history-element (- minibuffer-history-position n))))
(defun previous-history-element (n)
"Puts previous element of the minibuffer history in the minibuffer.
With argument N, it uses the Nth previous element."
(interactive "p")
- (next-history-element (- n)))
+ (or (zerop n)
+ (goto-history-element (+ minibuffer-history-position n))))
(defun next-complete-history-element (n)
"Get next history element which completes the minibuffer before the point.
@@ -1368,6 +1387,137 @@ Return 0 if current buffer is not a minibuffer."
;; the buffer; this should be 0 for normal buffers.
(1- (minibuffer-prompt-end)))
+;; isearch minibuffer history
+(add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup)
+
+(defvar minibuffer-history-isearch-message-overlay)
+(make-variable-buffer-local 'minibuffer-history-isearch-message-overlay)
+
+(defun minibuffer-history-isearch-setup ()
+ "Set up a minibuffer for using isearch to search the minibuffer history.
+Intended to be added to `minibuffer-setup-hook'."
+ (set (make-local-variable 'isearch-search-fun-function)
+ 'minibuffer-history-isearch-search)
+ (set (make-local-variable 'isearch-message-function)
+ 'minibuffer-history-isearch-message)
+ (set (make-local-variable 'isearch-wrap-function)
+ 'minibuffer-history-isearch-wrap)
+ (set (make-local-variable 'isearch-push-state-function)
+ 'minibuffer-history-isearch-push-state)
+ (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
+
+(defun minibuffer-history-isearch-end ()
+ "Clean up the minibuffer after terminating isearch in the minibuffer."
+ (if minibuffer-history-isearch-message-overlay
+ (delete-overlay minibuffer-history-isearch-message-overlay)))
+
+(defun minibuffer-history-isearch-search ()
+ "Return the proper search function, for isearch in minibuffer history."
+ (cond
+ (isearch-word
+ (if isearch-forward 'word-search-forward 'word-search-backward))
+ (t
+ (lambda (string bound noerror)
+ (let ((search-fun
+ ;; Use standard functions to search within minibuffer text
+ (cond
+ (isearch-regexp
+ (if isearch-forward 're-search-forward 're-search-backward))
+ (t
+ (if isearch-forward 'search-forward 'search-backward))))
+ found)
+ ;; Avoid lazy-highlighting matches in the minibuffer prompt when
+ ;; searching forward. Lazy-highlight calls this lambda with the
+ ;; bound arg, so skip the minibuffer prompt.
+ (if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+ (goto-char (minibuffer-prompt-end)))
+ (or
+ ;; 1. First try searching in the initial minibuffer text
+ (funcall search-fun string
+ (if isearch-forward bound (minibuffer-prompt-end))
+ noerror)
+ ;; 2. If the above search fails, start putting next/prev history
+ ;; elements in the minibuffer successively, and search the string
+ ;; in them. Do this only when bound is nil (i.e. not while
+ ;; lazy-highlighting search strings in the current minibuffer text).
+ (unless bound
+ (condition-case nil
+ (progn
+ (while (not found)
+ (cond (isearch-forward
+ (next-history-element 1)
+ (goto-char (minibuffer-prompt-end)))
+ (t
+ (previous-history-element 1)
+ (goto-char (point-max))))
+ (setq isearch-barrier (point) isearch-opoint (point))
+ ;; After putting the next/prev history element, search
+ ;; the string in them again, until next-history-element
+ ;; or previous-history-element raises an error at the
+ ;; beginning/end of history.
+ (setq found (funcall search-fun string
+ (unless isearch-forward
+ ;; For backward search, don't search
+ ;; in the minibuffer prompt
+ (minibuffer-prompt-end))
+ noerror)))
+ ;; Return point of the new search result
+ (point))
+ ;; Return nil when next(prev)-history-element fails
+ (error nil)))))))))
+
+(defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+ "Display the minibuffer history search prompt.
+If there are no search errors, this function displays an overlay with
+the isearch prompt which replaces the original minibuffer prompt.
+Otherwise, it displays the standard isearch message returned from
+`isearch-message'."
+ (if (not (and (minibufferp) isearch-success (not isearch-error)))
+ ;; Use standard function `isearch-message' when not in the minibuffer,
+ ;; or search fails, or has an error (like incomplete regexp).
+ ;; This function overwrites minibuffer text with isearch message,
+ ;; so it's possible to see what is wrong in the search string.
+ (isearch-message c-q-hack ellipsis)
+ ;; Otherwise, put the overlay with the standard isearch prompt over
+ ;; the initial minibuffer prompt.
+ (if (overlayp minibuffer-history-isearch-message-overlay)
+ (move-overlay minibuffer-history-isearch-message-overlay
+ (point-min) (minibuffer-prompt-end))
+ (setq minibuffer-history-isearch-message-overlay
+ (make-overlay (point-min) (minibuffer-prompt-end)))
+ (overlay-put minibuffer-history-isearch-message-overlay 'evaporate t))
+ (overlay-put minibuffer-history-isearch-message-overlay
+ 'display (isearch-message-prefix c-q-hack ellipsis))
+ ;; And clear any previous isearch message.
+ (message "")))
+
+(defun minibuffer-history-isearch-wrap ()
+ "Wrap the minibuffer history search when search is failed.
+Move point to the first history element for a forward search,
+or to the last history element for a backward search."
+ (unless isearch-word
+ ;; When `minibuffer-history-isearch-search' fails on reaching the
+ ;; beginning/end of the history, wrap the search to the first/last
+ ;; minibuffer history element.
+ (if isearch-forward
+ (goto-history-element (length (symbol-value minibuffer-history-variable)))
+ (goto-history-element 0))
+ (setq isearch-success t))
+ (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+
+(defun minibuffer-history-isearch-push-state ()
+ "Save a function restoring the state of minibuffer history search.
+Save `minibuffer-history-position' to the additional state parameter
+in the search status stack."
+ `(lambda (cmd)
+ (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+
+(defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+ "Restore the minibuffer history search state.
+Go to the history element by the absolute history position `hist-pos'."
+ (goto-history-element hist-pos))
+
+
;Put this on C-x u, so we can force that rather than C-_ into startup msg
(defalias 'advertised-undo 'undo)
@@ -2189,6 +2339,18 @@ value passed."
(when stderr-file (delete-file stderr-file))
(when lc (delete-file lc)))))
+(defun start-file-process (name buffer program &rest program-args)
+ "Start a program in a subprocess. Return the process object for it.
+Similar to `start-process', but may invoke a file handler based on
+`default-directory'. The current working directory of the
+subprocess is `default-directory'.
+
+PROGRAM and PROGRAM-ARGS might be file names. They are not
+objects of file handler invocation."
+ (let ((fh (find-file-name-handler default-directory 'start-file-process)))
+ (if fh (apply fh 'start-file-process name buffer program program-args)
+ (apply 'start-process name buffer program program-args))))
+
(defvar universal-argument-map
@@ -5246,10 +5408,10 @@ PREFIX is the string that represents this modifier in an event type symbol."
;;;; Keypad support.
-;;; Make the keypad keys act like ordinary typing keys. If people add
-;;; bindings for the function key symbols, then those bindings will
-;;; override these, so this shouldn't interfere with any existing
-;;; bindings.
+;; Make the keypad keys act like ordinary typing keys. If people add
+;; bindings for the function key symbols, then those bindings will
+;; override these, so this shouldn't interfere with any existing
+;; bindings.
;; Also tell read-char how to handle these keys.
(mapc