]> code.delx.au - gnu-emacs/blobdiff - lisp/simple.el
(choose-completion-string): Don't rely on minibuffer-completing-file-name
[gnu-emacs] / lisp / simple.el
index d6245a3b76baa48944e9e229941ca774943f89b8..c8e537cdf5084bc066f64fd56eb9d6194215ddb7 100644 (file)
@@ -183,9 +183,16 @@ of the errors before moving.
 Major modes providing compile-like functionality should set this variable
 to indicate to `next-error' that this is a candidate buffer and how
 to navigate in it.")
-
 (make-variable-buffer-local 'next-error-function)
 
+(defvar next-error-move-function nil
+  "Function to use to move to an error locus.
+It takes two arguments, a buffer position in the error buffer
+and a buffer position in the error locus buffer.
+The buffer for the error locus should already be current.
+nil means use goto-char using the second argument position.")
+(make-variable-buffer-local 'next-error-move-function)
+
 (defsubst next-error-buffer-p (buffer
                               &optional avoid-current
                               extra-test-inclusive
@@ -361,7 +368,7 @@ select the source buffer."
   (interactive "p")
   (next-error-no-select (- (or n 1))))
 
-;;; Internal variable for `next-error-follow-mode-post-command-hook'.
+;; Internal variable for `next-error-follow-mode-post-command-hook'.
 (defvar next-error-follow-last-line nil)
 
 (define-minor-mode next-error-follow-minor-mode
@@ -375,8 +382,8 @@ location."
     (add-hook 'post-command-hook 'next-error-follow-mode-post-command-hook nil t)
     (make-local-variable 'next-error-follow-last-line)))
 
-;;; Used as a `post-command-hook' by `next-error-follow-mode'
-;;; for the *Compilation* *grep* and *Occur* buffers.
+;; Used as a `post-command-hook' by `next-error-follow-mode'
+;; for the *Compilation* *grep* and *Occur* buffers.
 (defun next-error-follow-mode-post-command-hook ()
   (unless (equal next-error-follow-last-line (line-number-at-pos))
     (setq next-error-follow-last-line (line-number-at-pos))
@@ -847,12 +854,15 @@ that uses or sets the mark."
   "Goto LINE, counting from line 1 at beginning of buffer.
 Normally, move point in the current buffer, and leave mark at the
 previous position.  With just \\[universal-argument] as argument,
-move point in the most recently selected other buffer, and switch
-to it.  When called from Lisp code, the optional argument BUFFER
-specifies a buffer to switch to.
+move point in the most recently selected other buffer, and switch to it.
+
+If there's a number in the buffer at point, it is the default for LINE.
 
-If there's a number in the buffer at point, it is the default for
-LINE."
+This function is usually the wrong thing to use in a Lisp program.
+What you probably want instead is something like:
+  (goto-char (point-min)) (forward-line (1- N))
+If at all possible, an even better solution is to use char counts
+rather than line counts."
   (interactive
    (if (and current-prefix-arg (not (consp current-prefix-arg)))
        (list (prefix-numeric-value current-prefix-arg))
@@ -892,7 +902,7 @@ LINE."
   ;; Move to the specified line number in that buffer.
   (save-restriction
     (widen)
-    (goto-char 1)
+    (goto-char (point-min))
     (if (eq selective-display t)
        (re-search-forward "[\n\C-m]" nil 'end (1- line))
       (forward-line (1- line)))))
@@ -2054,6 +2064,23 @@ to `shell-command-history'."
           (or hist 'shell-command-history)
           args)))
 
+(defun async-shell-command (command &optional output-buffer error-buffer)
+  "Execute string COMMAND asynchronously in background.
+
+Like `shell-command' but if COMMAND doesn't end in ampersand, adds `&'
+surrounded by whitespace and executes the command asynchronously.
+The output appears in the buffer `*Async Shell Command*'."
+  (interactive
+   (list
+    (read-shell-command "Async shell command: " nil nil
+                       (and buffer-file-name
+                            (file-relative-name buffer-file-name)))
+    current-prefix-arg
+    shell-command-default-error-buffer))
+  (unless (string-match "&[ \t]*\\'" command)
+    (setq command (concat command " &")))
+  (shell-command command output-buffer error-buffer))
+
 (defun shell-command (command &optional output-buffer error-buffer)
   "Execute string COMMAND in inferior shell; display output, if any.
 With prefix argument, insert the COMMAND's output at point.
@@ -3455,16 +3482,33 @@ a mistake; see the documentation of `set-mark'."
       (marker-position (mark-marker))
     (signal 'mark-inactive nil)))
 
+(defcustom select-active-regions nil
+  "If non-nil, an active region automatically becomes the window selection."
+  :type 'boolean
+  :group 'killing
+  :version "23.1")
+
 ;; Many places set mark-active directly, and several of them failed to also
 ;; run deactivate-mark-hook.  This shorthand should simplify.
-(defsubst deactivate-mark ()
+(defsubst deactivate-mark (&optional force)
   "Deactivate the mark by setting `mark-active' to nil.
-\(That makes a difference only in Transient Mark mode.)
-Also runs the hook `deactivate-mark-hook'."
-  (when transient-mark-mode
-    (if (or (eq transient-mark-mode 'lambda)
-           (and (eq (car-safe transient-mark-mode) 'only)
-                (null (cdr transient-mark-mode))))
+Unless FORCE is non-nil, this function does nothing if Transient
+Mark mode is disabled.
+This function also runs `deactivate-mark-hook'."
+  (when (or transient-mark-mode force)
+    ;; Copy the latest region into the primary selection, if desired.
+    (and select-active-regions
+        mark-active
+        (display-selections-p)
+        (x-selection-owner-p 'PRIMARY)
+        (x-set-selection 'PRIMARY (buffer-substring-no-properties
+                                   (region-beginning) (region-end))))
+    (if (and (null force)
+            (or (eq transient-mark-mode 'lambda)
+                (and (eq (car-safe transient-mark-mode) 'only)
+                     (null (cdr transient-mark-mode)))))
+       ;; When deactivating a temporary region, don't change
+       ;; `mark-active' or run `deactivate-mark-hook'.
        (setq transient-mark-mode nil)
       (if (eq (car-safe transient-mark-mode) 'only)
          (setq transient-mark-mode (cdr transient-mark-mode)))
@@ -3476,13 +3520,10 @@ Also runs the hook `deactivate-mark-hook'."
   (when (mark t)
     (setq mark-active t)
     (unless transient-mark-mode
-      (setq transient-mark-mode 'lambda))))
-
-(defcustom select-active-regions nil
-  "If non-nil, an active region automatically becomes the window selection."
-  :type 'boolean
-  :group 'killing
-  :version "23.1")
+      (setq transient-mark-mode 'lambda))
+    (when (and select-active-regions
+              (display-selections-p))
+      (x-set-selection 'PRIMARY (current-buffer)))))
 
 (defun set-mark (pos)
   "Set this buffer's mark to POS.  Don't use this function!
@@ -3505,15 +3546,14 @@ store it in a Lisp variable.  Example:
       (progn
        (setq mark-active t)
        (run-hooks 'activate-mark-hook)
-       (and select-active-regions
-            (x-set-selection
-             nil (buffer-substring (region-beginning) (region-end))))
+       (when (and select-active-regions
+                  (display-selections-p))
+         (x-set-selection 'PRIMARY (current-buffer)))
        (set-marker (mark-marker) pos (current-buffer)))
     ;; Normally we never clear mark-active except in Transient Mark mode.
-    ;; But when we actually clear out the mark value too,
-    ;; we must clear mark-active in any mode.
-    (setq mark-active nil)
-    (run-hooks 'deactivate-mark-hook)
+    ;; But when we actually clear out the mark value too, we must
+    ;; clear mark-active in any mode.
+    (deactivate-mark t)
     (set-marker (mark-marker) nil)))
 
 (defcustom use-empty-active-region nil
@@ -3532,23 +3572,25 @@ point otherwise."
 (defun use-region-p ()
   "Return t if the region is active and it is appropriate to act on it.
 This is used by commands that act specially on the region under
-Transient Mark mode.  It returns t if and only if Transient Mark
-mode is enabled, the mark is active, and the region is non-empty.
-If `use-empty-active-region' is non-nil, it returns t even if the
-region is empty.
+Transient Mark mode.
+
+The return value is t provided Transient Mark mode is enabled and
+the mark is active; and, when `use-empty-active-region' is
+non-nil, provided the region is empty.  Otherwise, the return
+value is nil.
 
-For some commands, it may be appropriate to disregard the value
-of `use-empty-active-region'; in that case, use `region-active-p'."
+For some commands, it may be appropriate to ignore the value of
+`use-empty-active-region'; in that case, use `region-active-p'."
   (and (region-active-p)
        (or use-empty-active-region (> (region-end) (region-beginning)))))
 
 (defun region-active-p ()
   "Return t if Transient Mark mode is enabled and the mark is active.
 
-Most commands that act on the region if it is active and
-Transient Mark mode is enabled, and on the text near point
-otherwise, should use `use-region-p' instead.  That function
-checks the value of `use-empty-active-region' as well."
+Some commands act specially on the region when Transient Mark
+mode is enabled.  Usually, such commands should use
+`use-region-p' instead of this function, because `use-region-p'
+also checks the value of `use-empty-active-region'."
   (and transient-mark-mode mark-active))
 
 (defvar mark-ring nil
@@ -3760,20 +3802,20 @@ shift-translation."
   :group 'editing-basics)
 
 (defun handle-shift-selection ()
-  "Activate/deactivate mark depending on invocation thru ``shift translation.''
-
-\(See `this-command-keys-shift-translated' for the meaning of
-shift translation.)
-
-This is called whenever a command with a `^' character in its
-`interactive' spec is invoked.
-Its behavior is controlled by `shift-select-mode'.
-
-If the command was invoked through shift translation, set the
-mark and activate the region temporarily, unless it was already
-set in this way.  If the command was invoked without shift
-translation, or if the region was activated by the mouse,
-deactivate the mark if the region is temporarily active."
+  "Activate/deactivate mark depending on invocation thru shift translation.
+This function is called by `call-interactively' when a command
+with a `^' character in its `interactive' spec is invoked, before
+running the command itself.
+
+If `shift-select-mode' is enabled and the command was invoked
+through shift translation, set the mark and activate the region
+temporarily, unless it was already set in this way.  See
+`this-command-keys-shift-translated' for the meaning of shift
+translation.
+
+Otherwise, if the region has been activated temporarily,
+deactivate it, and restore the variable `transient-mark-mode' to
+its earlier value."
   (cond ((and shift-select-mode this-command-keys-shift-translated)
          (unless (and mark-active
                       (eq (car-safe transient-mark-mode) 'only))
@@ -3956,10 +3998,14 @@ This has no effect when `line-move-visual' is non-nil."
 (defvar temporary-goal-column 0
   "Current goal column for vertical motion.
 It is the column where point was at the start of the current run
-of vertical motion commands.  It is a floating point number when
-moving by visual lines via `line-move-visual'; this is the
-x-position, in pixels, divided by the default column width.  When
-the `track-eol' feature is doing its job, the value is
+of vertical motion commands.
+
+When moving by visual lines via `line-move-visual', it is a cons
+cell (COL . HSCROLL), where COL is the x-position, in pixels,
+divided by the default column width, and HSCROLL is the number of
+columns by which window is scrolled from left margin.
+
+When the `track-eol' feature is doing its job, the value is
 `most-positive-fixnum'.")
 
 (defcustom line-move-ignore-invisible t
@@ -4056,24 +4102,47 @@ into account variable-width characters and line continuation."
 ;; Arg says how many lines to move.  The value is t if we can move the
 ;; specified number of lines.
 (defun line-move-visual (arg &optional noerror)
-  (unless (and (floatp temporary-goal-column)
-              (or (memq last-command '(next-line previous-line))
-                  ;; In case we're called from some other command.
-                  (eq last-command this-command)))
-    (let ((posn (posn-at-point))
-         x)
-      (cond ((eq (nth 1 posn) 'right-fringe) ; overflow-newline-into-fringe
-            (setq temporary-goal-column (- (window-width) 1)))
-           ((setq x (car (nth 2 posn)))
-            (setq temporary-goal-column (/ (float x) (frame-char-width)))))))
-  (or (= (vertical-motion
-         (cons (or goal-column (truncate temporary-goal-column)) arg))
-        arg)
-      (unless noerror
-       (signal (if (< arg 0)
-                   'beginning-of-buffer
-                 'end-of-buffer)
-               nil))))
+  (let ((opoint (point))
+       (hscroll (window-hscroll))
+       target-hscroll)
+    ;; Check if the previous command was a line-motion command, or if
+    ;; we were called from some other command.
+    (if (and (consp temporary-goal-column)
+            (memq last-command `(next-line previous-line ,this-command)))
+       ;; If so, there's no need to reset `temporary-goal-column',
+       ;; but we may need to hscroll.
+       (if (or (/= (cdr temporary-goal-column) hscroll)
+               (>  (cdr temporary-goal-column) 0))
+           (setq target-hscroll (cdr temporary-goal-column)))
+      ;; Otherwise, we should reset `temporary-goal-column'.
+      (let ((posn (posn-at-point)))
+       (cond
+        ;; Handle the `overflow-newline-into-fringe' case:
+        ((eq (nth 1 posn) 'right-fringe)
+         (setq temporary-goal-column (cons (- (window-width) 1) hscroll)))
+        ((car (posn-x-y posn))
+         (setq temporary-goal-column
+               (cons (/ (float (car (posn-x-y posn)))
+                        (frame-char-width)) hscroll))))))
+    (if target-hscroll
+       (set-window-hscroll (selected-window) target-hscroll))
+    (or (and (= (vertical-motion
+                (cons (or goal-column
+                          (if (consp temporary-goal-column)
+                              (truncate (car temporary-goal-column))
+                            temporary-goal-column))
+                      arg))
+               arg)
+            (or (>= arg 0)
+                (/= (point) opoint)
+                ;; If the goal column lies on a display string,
+                ;; `vertical-motion' advances the cursor to the end
+                ;; of the string.  For arg < 0, this can cause the
+                ;; cursor to get stuck.  (Bug#3020).
+                (= (vertical-motion arg) arg)))
+       (unless noerror
+         (signal (if (< arg 0) 'beginning-of-buffer 'end-of-buffer)
+                 nil)))))
 
 ;; This is the guts of next-line and previous-line.
 ;; Arg says how many lines to move.
@@ -4084,8 +4153,9 @@ into account variable-width characters and line continuation."
   (let ((inhibit-point-motion-hooks t)
        (opoint (point))
        (orig-arg arg))
-    (if (floatp temporary-goal-column)
-       (setq temporary-goal-column (truncate temporary-goal-column)))
+    (if (consp temporary-goal-column)
+       (setq temporary-goal-column (+ (car temporary-goal-column)
+                                      (cdr temporary-goal-column))))
     (unwind-protect
        (progn
          (if (not (memq last-command '(next-line previous-line)))
@@ -4226,7 +4296,7 @@ into account variable-width characters and line continuation."
               (point))))
 
        ;; Move to the desired column.
-       (line-move-to-column column)
+       (line-move-to-column (truncate column))
 
        ;; Corner case: suppose we start out in a field boundary in
        ;; the middle of a continued line.  When we get to
@@ -4405,8 +4475,8 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
                                     (/= arg 1) t nil)))))
 
 
-;;; Many people have said they rarely use this feature, and often type
-;;; it by accident.  Maybe it shouldn't even be on a key.
+;; Many people have said they rarely use this feature, and often type
+;; it by accident.  Maybe it shouldn't even be on a key.
 (put 'set-goal-column 'disabled t)
 
 (defun set-goal-column (arg)
@@ -4464,20 +4534,10 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
 
 (defun kill-visual-line (&optional arg)
   "Kill the rest of the visual line.
-If there are only whitespace characters there, kill through the
-newline as well.
-
-With prefix argument ARG, kill that many lines from point.
-Negative arguments kill lines backward.
-With zero argument, kill the text before point on the current line.
-
-When calling from a program, nil means \"no arg\",
-a number counts as a prefix arg.
-
-If `kill-whole-line' is non-nil, then this command kills the whole line
-including its terminating newline, when used at the beginning of a line
-with no argument.  As a consequence, you can always kill a whole line
-by typing \\[beginning-of-line] \\[kill-line].
+With prefix argument ARG, kill that many visual lines from point.
+If ARG is negative, kill visual lines backward.
+If ARG is zero, kill the text before point on the current visual
+line.
 
 If you want to append the killed line to the last killed text,
 use \\[append-next-kill] before \\[kill-line].
@@ -4488,30 +4548,24 @@ you can use this command to copy text from a read-only buffer.
 \(If the variable `kill-read-only-ok' is non-nil, then this won't
 even beep.)"
   (interactive "P")
+  ;; Like in `kill-line', it's better to move point to the other end
+  ;; of the kill before killing.
   (let ((opoint (point))
-       (line-move-visual t)
-       end)
-    ;; It is better to move point to the other end of the kill before
-    ;; killing.  That way, in a read-only buffer, point moves across
-    ;; the text that is copied to the kill ring.  The choice has no
-    ;; effect on undo now that undo records the value of point from
-    ;; before the command was run.
+       (kill-whole-line (and kill-whole-line (bolp))))
     (if arg
        (vertical-motion (prefix-numeric-value arg))
-      (if (eobp)
-         (signal 'end-of-buffer nil))
-      (setq end (save-excursion
-                 (end-of-visual-line) (point)))
-      (if (or (save-excursion
-               ;; If trailing whitespace is visible,
-               ;; don't treat it as nothing.
-               (unless show-trailing-whitespace
-                 (skip-chars-forward " \t" end))
-               (= (point) end))
-             (and kill-whole-line (bolp)))
-         (line-move 1)
-       (goto-char end)))
-    (kill-region opoint (point))))
+      (end-of-visual-line 1)
+      (if (= (point) opoint)
+         (vertical-motion 1)
+       ;; Skip any trailing whitespace at the end of the visual line.
+       ;; We used to do this only if `show-trailing-whitespace' is
+       ;; nil, but that's wrong; the correct thing would be to check
+       ;; whether the trailing whitespace is highlighted.  But, it's
+       ;; OK to just do this unconditionally.
+       (skip-chars-forward " \t")))
+    (kill-region opoint (if (and kill-whole-line (looking-at "\n"))
+                           (1+ (point))
+                         (point)))))
 
 (defun next-logical-line (&optional arg try-vscroll)
   "Move cursor vertically down ARG lines.
@@ -5211,9 +5265,10 @@ It is also ignored if `show-paren-mode' is enabled."
   :type 'boolean
   :group 'paren-blinking)
 
-(defcustom blink-matching-paren-distance (* 25 1024)
+(defcustom blink-matching-paren-distance (* 100 1024)
   "If non-nil, maximum distance to search backwards for matching open-paren.
 If nil, search stops at the beginning of the accessible portion of the buffer."
+  :version "23.2"                       ; 25->100k
   :type '(choice (const nil) integer)
   :group 'paren-blinking)
 
@@ -5400,7 +5455,7 @@ See also `mail-user-agent' concerning sending mail."
   :version "21.1"
   :group 'mail)
 
-(defcustom mail-user-agent 'sendmail-user-agent
+(defcustom mail-user-agent 'message-user-agent
   "Your preference for a mail composition package.
 Various Emacs Lisp packages (e.g. Reporter) require you to compose an
 outgoing email message.  This variable lets you specify which
@@ -5408,12 +5463,12 @@ mail-sending package you prefer.
 
 Valid values include:
 
-  `sendmail-user-agent' -- use the default Emacs Mail package.
+  `message-user-agent'  -- use the Message package.
+                           See Info node `(message)'.
+  `sendmail-user-agent' -- use the Mail package.
                            See Info node `(emacs)Sending Mail'.
   `mh-e-user-agent'     -- use the Emacs interface to the MH mail system.
                            See Info node `(mh-e)'.
-  `message-user-agent'  -- use the Gnus Message package.
-                           See Info node `(message)'.
   `gnus-user-agent'     -- like `message-user-agent', but with Gnus
                            paraphernalia, particularly the Gcc: header for
                            archiving.
@@ -5423,19 +5478,20 @@ your package for details.  The function should return non-nil if it
 succeeds.
 
 See also `read-mail-command' concerning reading mail."
-  :type '(radio (function-item :tag "Default Emacs mail"
+  :type '(radio (function-item :tag "Message package"
+                              :format "%t\n"
+                              message-user-agent)
+               (function-item :tag "Mail package"
                               :format "%t\n"
                               sendmail-user-agent)
                (function-item :tag "Emacs interface to MH"
                               :format "%t\n"
                               mh-e-user-agent)
-               (function-item :tag "Gnus Message package"
-                              :format "%t\n"
-                              message-user-agent)
-               (function-item :tag "Gnus Message with full Gnus features"
+               (function-item :tag "Message with full Gnus features"
                               :format "%t\n"
                               gnus-user-agent)
                (function :tag "Other"))
+  :version "23.2"                       ; sendmail->message
   :group 'mail)
 
 (define-mail-user-agent 'sendmail-user-agent
@@ -5614,6 +5670,7 @@ With a prefix argument, set VARIABLE to VALUE buffer-locally."
     (define-key map "\e\e\e" 'delete-completion-window)
     (define-key map [left] 'previous-completion)
     (define-key map [right] 'next-completion)
+    (define-key map "q" 'quit-window)
     map)
   "Local map for completion list buffers.")
 
@@ -5798,13 +5855,19 @@ to decide what to delete."
             minibuffer-completion-table
             ;; If this is reading a file name, and the file name chosen
             ;; is a directory, don't exit the minibuffer.
-            (if (and minibuffer-completing-file-name
-                     (file-directory-p (field-string (point-max))))
-                (let ((mini (active-minibuffer-window)))
-                  (select-window mini)
-                  (when minibuffer-auto-raise
-                    (raise-frame (window-frame mini))))
-              (exit-minibuffer)))))))
+             (let* ((result (buffer-substring (field-beginning) (point)))
+                    (bounds
+                     (completion-boundaries result minibuffer-completion-table
+                                            minibuffer-completion-predicate
+                                            "")))
+               (if (eq (car bounds) (length result))
+                   ;; The completion chosen leads to a new set of completions
+                   ;; (e.g. it's a directory): don't exit the minibuffer yet.
+                   (let ((mini (active-minibuffer-window)))
+                     (select-window mini)
+                     (when minibuffer-auto-raise
+                       (raise-frame (window-frame mini))))
+                 (exit-minibuffer))))))))
 
 (define-derived-mode completion-list-mode nil "Completion List"
   "Major mode for buffers showing lists of possible completions.
@@ -5843,20 +5906,22 @@ Called from `temp-buffer-show-hook'."
 ;; after the text of the completion list buffer is written.
 (defun completion-setup-function ()
   (let* ((mainbuf (current-buffer))
-         (mbuf-contents (minibuffer-completion-contents))
-         common-string-length)
-    ;; When reading a file name in the minibuffer,
-    ;; set default-directory in the minibuffer
-    ;; so it will get copied into the completion list buffer.
-    (if minibuffer-completing-file-name
-       (with-current-buffer mainbuf
-         (setq default-directory
-                (file-name-directory (expand-file-name mbuf-contents)))))
+         (base-dir
+          ;; When reading a file name in the minibuffer,
+          ;; try and find the right default-directory to set in the
+          ;; completion list buffer.
+          ;; FIXME: Why do we do that, actually?  --Stef
+          (if minibuffer-completing-file-name
+              (file-name-as-directory
+               (expand-file-name
+                (substring (minibuffer-completion-contents)
+                           0 (or completion-base-size 0)))))))
     (with-current-buffer standard-output
       (let ((base-size completion-base-size)) ;Read before killing localvars.
         (completion-list-mode)
         (set (make-local-variable 'completion-base-size) base-size))
       (set (make-local-variable 'completion-reference-buffer) mainbuf)
+      (if base-dir (setq default-directory base-dir))
       (unless completion-base-size
         ;; This shouldn't be needed any more, but further analysis is needed
         ;; to make sure it's the case.
@@ -6260,8 +6325,8 @@ have both Backspace, Delete and F1 keys.
 See also `normal-erase-is-backspace'."
   (interactive "P")
   (let ((enabled (or (and arg (> (prefix-numeric-value arg) 0))
-                    (and (not arg)
-                         (not (eq 1 (terminal-parameter
+                    (not (or arg
+                              (eq 1 (terminal-parameter
                                      nil 'normal-erase-is-backspace)))))))
     (set-terminal-parameter nil 'normal-erase-is-backspace
                            (if enabled 1 0))