]> code.delx.au - gnu-emacs/commitdiff
Merge from origin/emacs-25
authorJohn Wiegley <johnw@newartisans.com>
Fri, 4 Mar 2016 07:52:26 +0000 (23:52 -0800)
committerJohn Wiegley <johnw@newartisans.com>
Fri, 4 Mar 2016 07:52:26 +0000 (23:52 -0800)
6620944 (cl-union): Do not ignore :test argument when lists are equal.
17dd3fb Add `isearch' to `basic-faces'
c1ec743 Make $, : and @ "prefix characters" in ruby-mode
e72a26e Make find-tag-default-bounds more strict
1bc0e0a Minor fixes in filenotify.el

1  2 
doc/lispref/display.texi
lisp/progmodes/ruby-mode.el
lisp/replace.el
lisp/subr.el

diff --combined doc/lispref/display.texi
index 457a53cbe8b47a063a3b51f0dea1519511c61e91,e4aff43ccbadcc01b05d3fcda05b3fb24f373788..93c927cbe2a3bb35ba503f5a9622c1f04a2766d6
@@@ -3034,7 -3034,11 +3034,11 @@@ it is commonly assigned to the @code{mo
  highlighting (@pxref{Special Properties}).
  
  @item match
- For text matching a search command.
+ @itemx isearch
+ @itemx lazy-highlight
+ For text matching (respectively) permanent search matches, interactive
+ search matches, and lazy highlighting other matches than the current
+ interactive one.
  
  @item error
  @itemx warning
@@@ -4761,7 -4765,6 +4765,7 @@@ displayed (@pxref{Display Feature Testi
  * XPM Images::          Special features for XPM format.
  * PostScript Images::   Special features for PostScript format.
  * ImageMagick Images::  Special features available through ImageMagick.
 +* SVG Images::          Creating and manipulating SVG images.
  * Other Image Types::   Various other formats are supported.
  * Defining Images::     Convenient ways to define an image for later use.
  * Showing Images::      Convenient ways to display an image once it is defined.
@@@ -5199,16 -5202,6 +5203,16 @@@ and if @code{:height} is set it will ha
  wish.  @code{:max-width} and @code{:max-height} will always preserve
  the aspect ratio.
  
 +@item :scale @var{scale}
 +This should be a number, where values higher than 1 means to increase
 +the size, and lower means to decrease the size.  For instance, a value
 +of 0.25 will make the image a quarter size of what it originally was.
 +If the scaling makes the image larger than specified by
 +@code{:max-width} or @code{:max-height}, the resulting size will not
 +exceed those two values.  If both @code{:scale} and
 +@code{:height}/@code{:width} are specified, the height/width will be
 +adjusted by the specified scaling factor.
 +
  @item :format @var{type}
  The value, @var{type}, should be a symbol specifying the type of the
  image data, as found in @code{image-format-suffixes}.  This is used
@@@ -5223,128 -5216,6 +5227,128 @@@ Specifies a rotation angle in degrees
  @xref{Multi-Frame Images}.
  @end table
  
 +@node SVG Images
 +@subsection SVG Images
 +@cindex SVG images
 +
 +SVG (Scalable Vector Graphics) is an XML format for specifying images.
 +If you build Emacs with SVG support, you can create and manipulate
 +these images with the following commands.
 +
 +@defun svg-create width height &rest args
 +Create a new, empty SVG image with the specified dimensions.
 +@var{args} is an argument plist with you can specify following:
 +
 +@table @code
 +@item :stroke-width
 +The default width (in pixels) of any lines created.
 +
 +@item :stroke
 +The default stroke color on any lines created.
 +@end table
 +
 +This function returns an SVG structure, and all the following commands
 +work on that structure.
 +@end defun
 +
 +@defun svg-gradient svg id type stops
 +Create a gradient in @var{svg} with identifier @var{id}.  @var{type}
 +specifies the gradient type, and can be either @code{linear} or
 +@code{radial}.  @var{stops} is a list of percentage/color pairs.
 +
 +The following will create a linear gradient that goes from red at the
 +start, to green 25% of the way, to blue at the end:
 +
 +@lisp
 +(svg-gradient svg "gradient1" 'linear
 +              '((0 . "red") (25 . "green") (100 . "blue")))
 +@end lisp
 +
 +The gradient created (and inserted into the SVG object) can later be
 +used by all functions that create shapes.
 +@end defun
 +
 +All the following functions take an optional list of keyword
 +parameters that alter the various attributes from their default
 +values.  Valid attributes include:
 +
 +@table @code
 +@item :stroke-width
 +The width (in pixels) of lines drawn, and outlines around solid
 +shapes.
 +
 +@item :stroke-color
 +The color of lines drawn, and outlines around solid shapes.
 +
 +@item :fill-color
 +The color used for solid shapes.
 +
 +@item :id
 +The identified of the shape.
 +
 +@item :gradient
 +If given, this should be the identifier of a previously defined
 +gradient object.
 +@end table
 +
 +@defun svg-rectangle svg x y width height &rest args
 +Add a rectangle to @var{svg} where the upper left corner is at
 +position @var{x}/@var{y} and is of size @var{width}/@var{height}.
 +
 +@lisp
 +(svg-rectangle svg 100 100 500 500 :gradient "gradient1")
 +@end lisp
 +@end defun
 +
 +@defun svg-circle svg x y radius &rest args
 +Add a circle to @var{svg} where the center is at @var{x}/@var{y}
 +and the radius is @var{radius}.
 +@end defun
 +
 +@defun svg-ellipse svg x y x-radius y-radius &rest args
 +Add a circle to @var{svg} where the center is at @var{x}/@var{y} and
 +the horizontal radius is @var{x-radius} and the vertical radius is
 +@var{y-radius}.
 +@end defun
 +
 +@defun svg-line svg x1 y1 x2 y2 &rest args
 +Add a line to @var{svg} that starts at @var{x1}/@var{y1} and extends
 +to @var{x2}/@var{y2}.
 +@end defun
 +
 +@defun svg-polyline svg points &rest args
 +Add a multiple segment line to @var{svg} that goes through
 +@var{points}, which is a list of X/Y position pairs.
 +
 +@lisp
 +(svg-polyline svg '((200 . 100) (500 . 450) (80 . 100))
 +              :stroke-color "green")
 +@end lisp
 +@end defun
 +
 +@defun svg-polygon svg points &rest args
 +Add a polygon to @var{svg} where @var{points} is a list of X/Y pairs
 +that describe the outer circumference of the polygon.
 +
 +@lisp
 +(svg-polygon svg '((100 . 100) (200 . 150) (150 . 90))
 +             :stroke-color "blue" :fill-color "red"")
 +@end lisp
 +@end defun
 +
 +Finally, the @code{svg-image} takes an SVG object as its parameter and
 +returns an image object suitable for use in functions like
 +@code{insert-image}.  Here's a complete example that creates and
 +inserts an image with a circle:
 +
 +@lisp
 +(let ((svg (svg-create 400 400 :stroke-width 10)))
 +  (svg-gradient svg "gradient1" 'linear '((0 . "red") (100 . "blue")))
 +  (svg-circle svg 200 200 100 :gradient "gradient1" :stroke-color "green")
 +  (insert-image (svg-image svg)))
 +@end lisp
 +
 +
  @node Other Image Types
  @subsection Other Image Types
  @cindex PBM
@@@ -5381,6 -5252,9 +5385,6 @@@ Image type @code{jpeg}
  @item PNG
  Image type @code{png}.
  
 -@item SVG
 -Image type @code{svg}.
 -
  @item TIFF
  Image type @code{tiff}.
  Supports the @code{:index} property.  @xref{Multi-Frame Images}.
@@@ -5444,12 -5318,6 +5448,12 @@@ If none of the alternatives will work, 
  as @code{nil}.
  @end defmac
  
 +@defun image-property image property
 +Return the value of @var{property} in @var{image}.  Properties can be
 +set by using @code{setf}.  Setting a property to @code{nil} will
 +remove the property from the image.
 +@end defun
 +
  @defun find-image specs
  This function provides a convenient way to find an image satisfying one
  of a list of image specifications @var{specs}.
@@@ -5520,13 -5388,6 +5524,13 @@@ Here is an example of using @code{image
  @end example
  @end defun
  
 +@vindex image-scaling-factor
 +Images are automatically scaled when created based on the
 +@code{image-scaling-factor} variable.  The value is either a floating
 +point number (where numbers higher than 1 means to increase the size
 +and lower means to shrink the size), or the symbol @code{auto}, which
 +will compute a scaling factor based on the font pixel size.
 +
  @node Showing Images
  @subsection Showing Images
  @cindex show image
@@@ -5636,26 -5497,6 +5640,26 @@@ cache, it can always be displayed, eve
  @code{max-image-size} is subsequently changed (@pxref{Image Cache}).
  @end defvar
  
 +Images inserted with the insertion functions above also get a local
 +keymap installed in the text properties (or overlays) that span the
 +displayed image.  This keymap defines the following commands:
 +
 +@table @kbd
 +@item +
 +Increase the image size (@code{image-increase-size}).  A prefix value
 +of @samp{4} means to increase the size by 40%.  The default is 20%.
 +
 +@item -
 +Decrease the image size (@code{image-increase-size}).  A prefix value
 +of @samp{4} means to decrease the size by 40%.  The default is 20%.
 +
 +@item r
 +Rotate the image by 90 degrees (@code{image-rotate}).
 +
 +@item o
 +Save the image to a file (@code{image-save}).
 +@end table
 +
  @node Multi-Frame Images
  @subsection Multi-Frame Images
  @cindex multi-frame images
index e3fe315f3bd32285c13459cd02e24ece791a37ca,cebc1dc98230818d7cf692e1b570b9d125a0ac91..fb942b34ddc7a0095d82bfec83fb44c7f3e3dfd0
@@@ -32,7 -32,7 +32,7 @@@
  ;; file after putting it on your load path:
  ;;
  ;;    (autoload 'ruby-mode "ruby-mode" "Major mode for ruby files" t)
- ;;    (add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
+ ;;    (add-to-list 'auto-mode-alist '("\\.rb\\'" . ruby-mode))
  ;;    (add-to-list 'interpreter-mode-alist '("ruby" . ruby-mode))
  ;;
  ;; Still needs more docstrings; search below for TODO.
@@@ -188,9 -188,10 +188,10 @@@ This should only be called after matchi
      (modify-syntax-entry ?# "<" table)
      (modify-syntax-entry ?\n ">" table)
      (modify-syntax-entry ?\\ "\\" table)
-     (modify-syntax-entry ?$ "." table)
+     (modify-syntax-entry ?$ "'" table)
      (modify-syntax-entry ?_ "_" table)
-     (modify-syntax-entry ?: "_" table)
+     (modify-syntax-entry ?: "'" table)
+     (modify-syntax-entry ?@ "'" table)
      (modify-syntax-entry ?< "." table)
      (modify-syntax-entry ?> "." table)
      (modify-syntax-entry ?& "." table)
@@@ -450,7 -451,7 +451,7 @@@ It is used when `ruby-encoding-magic-co
  
  (defun ruby-smie--redundant-do-p (&optional skip)
    (save-excursion
 -    (if skip (backward-word-strictly 1))
 +    (if skip (backward-word 1))
      (member (nth 2 (smie-backward-sexp ";")) '("while" "until" "for"))))
  
  (defun ruby-smie--opening-pipe-p ()
              (setq tok (concat "." tok)))
            (cond
             ((member tok '("unless" "if" "while" "until"))
 -            (if (save-excursion (forward-word-strictly -1) (ruby-smie--bosp))
 +            (if (save-excursion (forward-word -1) (ruby-smie--bosp))
                  tok "iuwu-mod"))
             ((string-match-p "\\`|[*&]?\\'" tok)
              (forward-char (- 1 (length tok)))
           ((equal tok "do")
            (cond
             ((not (ruby-smie--redundant-do-p)) tok)
 -           ((> (save-excursion (forward-word-strictly 1)
 +           ((> (save-excursion (forward-word 1)
                                 (forward-comment (point-max)) (point))
                 (line-end-position))
              (ruby-smie--backward-token)) ;Fully redundant.
@@@ -891,7 -892,7 +892,7 @@@ and `\\' when preceded by `?'.
  (defun ruby-singleton-class-p (&optional pos)
    (save-excursion
      (when pos (goto-char pos))
 -    (forward-word-strictly -1)
 +    (forward-word -1)
      (and (or (bolp) (not (eq (char-before (point)) ?_)))
           (looking-at ruby-singleton-class-re))))
  
@@@ -1234,7 -1235,7 +1235,7 @@@ delimiter.
                      ((let ((s (ruby-parse-region (point) ruby-indent-point)))
                         (and (nth 2 s) (> (nth 2 s) 0)
                              (or (goto-char (cdr (nth 1 s))) t)))
 -                     (forward-word-strictly -1)
 +                     (forward-word -1)
                       (setq indent (ruby-indent-size (current-column)
                                                    (nth 2 state))))
                      (t
          (if (null (cdr (nth 1 state)))
              (error "Invalid nesting"))
          (goto-char (cdr (nth 1 state)))
 -        (forward-word-strictly -1)               ; skip back a keyword
 +        (forward-word -1)               ; skip back a keyword
          (setq begin (point))
          (cond
           ((looking-at "do\\>[^_]")      ; iter block is a special case
                                        (forward-char -1)
                                        (not (looking-at "{")))
                                      (progn
 -                                      (forward-word-strictly -1)
 +                                      (forward-word -1)
                                        (not (looking-at "do\\>[^_]")))))
                                (t t))))
                         (not (eq ?, c))
@@@ -1499,10 -1500,11 +1500,10 @@@ With ARG, do it many times.  Negative A
                          (not (eq (char-before (point)) ?.))
                          (not (eq (char-before (point)) ?:)))
                     (ruby-end-of-block)
 -                   (forward-word-strictly 1))
 +                   (forward-word 1))
                    ((looking-at "\\(\\$\\|@@?\\)?\\sw")
                     (while (progn
 -                            (while (progn (forward-word-strictly 1)
 -                                          (looking-at "_")))
 +                            (while (progn (forward-word 1) (looking-at "_")))
                              (cond ((looking-at "::") (forward-char 2) t)
                                    ((> (skip-chars-forward ".") 0))
                                    ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
                         (skip-chars-forward "<"))
                       (not expr))))
              (setq i (1- i)))
 -        ((error) (forward-word-strictly 1)))
 +        ((error) (forward-word 1)))
        i))))
  
  (defun ruby-backward-sexp (&optional arg)
@@@ -1554,7 -1556,7 +1555,7 @@@ With ARG, do it many times.  Negative A
                    ((looking-at "\\s(") nil)
                    (t
                     (forward-char 1)
 -                   (while (progn (forward-word-strictly -1)
 +                   (while (progn (forward-word -1)
                                   (pcase (char-before)
                                     (`?_ t)
                                     (`?. (forward-char -1) t)
@@@ -1858,6 -1860,10 +1859,10 @@@ It will be properly highlighted even wh
              (string-to-syntax "_"))))
        ;; Backtick method redefinition.
        ("^[ \t]*def +\\(`\\)" (1 "_"))
+       ;; Ternary operator colon followed by opening paren or bracket
+       ;; (semi-important for indentation).
+       ("\\(:\\)\\(?:[\({]\\|\\[[^]]\\)"
+        (1 (string-to-syntax ".")))
        ;; Regular expressions.  Start with matching unescaped slash.
        ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)"
         (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1)))))
    "The syntax table to use for fontifying Ruby mode buffers.
  See `font-lock-syntax-table'.")
  
- (defconst ruby-font-lock-keyword-beg-re "\\(?:^\\|[^.@$]\\|\\.\\.\\)")
+ (defconst ruby-font-lock-keyword-beg-re "\\(?:^\\|[^.@$:]\\|\\.\\.\\)")
  
  (defconst ruby-font-lock-keywords
    `(;; Functions.
      ("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
       0 font-lock-variable-name-face)
      ;; Constants.
-     ("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)"
+     ("\\_<\\([A-Z]+\\(\\w\\|_\\)*\\)"
       1 (unless (eq ?\( (char-after)) font-lock-type-face))
      ;; Ruby 1.9-style symbol hash keys.
      ("\\(?:^\\s *\\|[[{(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+:\\)[^:]"
diff --combined lisp/replace.el
index b7e26c96fc51411e8e7a445731e76ec425657d40,2c3aa9b088521271cdd6f3019daf9f92d9504eae..a2ce78a8bb22826f627e71e6aef87a9722b321ee
@@@ -1268,6 -1268,7 +1268,7 @@@ Compatibility function for \\[next-erro
      (t :background "gray"))
    "Face used to highlight matches permanently."
    :group 'matching
+   :group 'basic-faces
    :version "22.1")
  
  (defcustom list-matching-lines-default-context-lines 0
@@@ -1824,8 -1825,6 +1825,8 @@@ C-w to delete match and recursive edit
  C-l to clear the screen, redisplay, and offer same replacement again,
  ! to replace all remaining matches in this buffer with no more questions,
  ^ to move point back to previous match,
 +u to undo previous replacement,
 +U to undo all replacements,
  E to edit the replacement string.
  In multi-buffer replacements type `Y' to replace all remaining
  matches in all remaining buffers with no more questions,
@@@ -1855,8 -1854,6 +1856,8 @@@ in the current buffer.
      (define-key map "\C-l" 'recenter)
      (define-key map "!" 'automatic)
      (define-key map "^" 'backup)
 +    (define-key map "u" 'undo)
 +    (define-key map "U" 'undo-all)
      (define-key map "\C-h" 'help)
      (define-key map [f1] 'help)
      (define-key map [help] 'help)
@@@ -1882,7 -1879,7 +1883,7 @@@ The valid answers include `act', `skip'
  `act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
  `scroll-down', `scroll-other-window', `scroll-other-window-down',
  `edit', `edit-replacement', `delete-and-edit', `automatic',
 -`backup', `quit', and `help'.
 +`backup', `undo', `undo-all', `quit', and `help'.
  
  This keymap is used by `y-or-n-p' as well as `query-replace'.")
  
@@@ -2136,10 -2133,6 +2137,10 @@@ It must return a string.
           (noedit nil)
           (keep-going t)
           (stack nil)
 +         (search-string-replaced nil)    ; last string matching `from-string'
 +         (next-replacement-replaced nil) ; replacement string
 +                                         ; (substituted regexp)
 +         (last-was-undo)
           (replace-count 0)
           (skip-read-only-count 0)
           (skip-filtered-count 0)
                   (match-beginning 0) (match-end 0)
                   start end search-string
                   regexp-flag delimited-flag case-fold-search backward)
 -                ;; Bind message-log-max so we don't fill up the message log
 -                ;; with a bunch of identical messages.
 +                  ;; Obtain the matched groups: needed only when
 +                  ;; regexp-flag non nil.
 +                  (when (and last-was-undo regexp-flag)
 +                    (setq last-was-undo nil
 +                          real-match-data
 +                          (save-excursion
 +                            (goto-char (match-beginning 0))
 +                            (looking-at search-string)
 +                            (match-data t real-match-data))))
 +                  ;; Matched string and next-replacement-replaced
 +                  ;; stored in stack.
 +                  (setq search-string-replaced (buffer-substring-no-properties
 +                                                (match-beginning 0)
 +                                                (match-end 0))
 +                        next-replacement-replaced
 +                        (query-replace-descr
 +                         (save-match-data
 +                           (set-match-data real-match-data)
 +                           (match-substitute-replacement
 +                            next-replacement nocasify literal))))
 +                ;; Bind message-log-max so we don't fill up the
 +                ;; message log with a bunch of identical messages.
                  (let ((message-log-max nil)
                        (replacement-presentation
                         (if query-replace-show-replacement
                               (query-replace-descr from-string)
                               (query-replace-descr replacement-presentation)))
                  (setq key (read-event))
 -                ;; Necessary in case something happens during read-event
 -                ;; that clobbers the match data.
 +                ;; Necessary in case something happens during
 +                ;; read-event that clobbers the match data.
                  (set-match-data real-match-data)
                  (setq key (vector key))
                  (setq def (lookup-key map key))
                            (concat "Query replacing "
                                    (if delimited-flag
                                        (or (and (symbolp delimited-flag)
 -                                               (get delimited-flag 'isearch-message-prefix))
 +                                               (get delimited-flag
 +                                                      'isearch-message-prefix))
                                            "word ") "")
                                    (if regexp-flag "regexp " "")
                                    (if backward "backward " "")
                           (message "No previous match")
                           (ding 'no-terminate)
                           (sit-for 1)))
 +                      ((or (eq def 'undo) (eq def 'undo-all))
 +                       (if (null stack)
 +                             (progn
 +                               (message "Nothing to undo")
 +                               (ding 'no-terminate)
 +                               (sit-for 1))
 +                         (let ((stack-idx         0)
 +                                 (stack-len         (length stack))
 +                                 (num-replacements  0)
 +                                 search-string
 +                                 next-replacement)
 +                             (while (and (< stack-idx stack-len)
 +                                         stack
 +                                         (null replaced))
 +                               (let* ((elt (nth stack-idx stack)))
 +                                 (setq
 +                                  stack-idx (1+ stack-idx)
 +                                  replaced (nth 1 elt)
 +                                  ;; Bind swapped values
 +                                  ;; (search-string <--> replacement)
 +                                  search-string (nth (if replaced 4 3) elt)
 +                                  next-replacement (nth (if replaced 3 4) elt)
 +                                  search-string-replaced search-string
 +                                  next-replacement-replaced next-replacement)
 +
 +                                 (when (and (= stack-idx stack-len)
 +                                            (null replaced)
 +                                            (zerop num-replacements))
 +                                          (message "Nothing to undo")
 +                                          (ding 'no-terminate)
 +                                          (sit-for 1))
 +
 +                                 (when replaced
 +                                   (setq stack (nthcdr stack-idx stack))
 +                                   (goto-char (nth 0 elt))
 +                                   (set-match-data (nth 2 elt))
 +                                   (setq real-match-data
 +                                         (save-excursion
 +                                           (goto-char (match-beginning 0))
 +                                           (looking-at search-string)
 +                                           (match-data t (nth 2 elt)))
 +                                         noedit
 +                                         (replace-match-maybe-edit
 +                                          next-replacement nocasify literal
 +                                          noedit real-match-data backward)
 +                                         replace-count (1- replace-count)
 +                                         real-match-data
 +                                         (save-excursion
 +                                           (goto-char (match-beginning 0))
 +                                           (looking-at next-replacement)
 +                                           (match-data t (nth 2 elt))))
 +                                   ;; Set replaced nil to keep in loop
 +                                   (when (eq def 'undo-all)
 +                                     (setq replaced nil
 +                                           stack-len (- stack-len stack-idx)
 +                                           stack-idx 0
 +                                           num-replacements
 +                                           (1+ num-replacements))))))
 +                             (when (and (eq def 'undo-all)
 +                                        (null (zerop num-replacements)))
 +                               (message "Undid %d %s" num-replacements
 +                                        (if (= num-replacements 1)
 +                                            "replacement"
 +                                          "replacements"))
 +                               (ding 'no-terminate)
 +                               (sit-for 1)))
 +                         (setq replaced nil last-was-undo t)))
                        ((eq def 'act)
                         (or replaced
                             (setq noedit
                                 (match-beginning 0)
                                 (match-end 0)
                                 (current-buffer))
 -                            (match-data t)))
 -                    stack))))))
 -
 +                            (match-data t))
 +                              search-string-replaced
 +                              next-replacement-replaced)
 +                    stack)
 +                (setq next-replacement-replaced nil
 +                      search-string-replaced    nil))))))
        (replace-dehighlight))
      (or unread-command-events
        (message "Replaced %d occurrence%s%s"
diff --combined lisp/subr.el
index 447c3eb1a4fe12470571f718d59a93691cb821fa,dde76916230a1cdc0cc7135ebcbf9b6884b53be4..6eea54f2a32cfb2892d7fc1c20c6f0d68080b226
@@@ -2233,145 -2233,6 +2233,145 @@@ keyboard-quit events while waiting for 
      (message "%s%s" prompt (char-to-string char))
      char))
  
 +(defun read-multiple-choice (prompt choices)
 +  "Ask user a multiple choice question.
 +PROMPT should be a string that will be displayed as the prompt.
 +
 +CHOICES is an alist where the first element in each entry is a
 +character to be entered, the second element is a short name for
 +the entry to be displayed while prompting (if there's room, it
 +might be shortened), and the third, optional entry is a longer
 +explanation that will be displayed in a help buffer if the user
 +requests more help.
 +
 +The return value is the matching entry from the CHOICES list.
 +
 +Usage example:
 +
 +\(read-multiple-choice \"Continue connecting?\"
 +                      '((?a \"always\")
 +                        (?s \"session only\")
 +                        (?n \"no\")))"
 +  (let* ((altered-names nil)
 +         (full-prompt
 +          (format
 +           "%s (%s): "
 +           prompt
 +           (mapconcat
 +            (lambda (elem)
 +              (let* ((name (cadr elem))
 +                     (pos (seq-position name (car elem)))
 +                     (altered-name
 +                      (cond
 +                       ;; Not in the name string.
 +                       ((not pos)
 +                        (format "[%c] %s" (car elem) name))
 +                       ;; The prompt character is in the name, so highlight
 +                       ;; it on graphical terminals...
 +                       ((display-supports-face-attributes-p
 +                         '(:underline t) (window-frame))
 +                        (setq name (copy-sequence name))
 +                        (put-text-property pos (1+ pos)
 +                                           'face 'read-multiple-choice-face
 +                                           name)
 +                        name)
 +                       ;; And put it in [bracket] on non-graphical terminals.
 +                       (t
 +                        (concat
 +                         (substring name 0 pos)
 +                         "["
 +                         (upcase (substring name pos (1+ pos)))
 +                         "]"
 +                         (substring name (1+ pos)))))))
 +                (push (cons (car elem) altered-name)
 +                      altered-names)
 +                altered-name))
 +            (append choices '((?? "?")))
 +            ", ")))
 +         tchar buf wrong-char)
 +    (save-window-excursion
 +      (save-excursion
 +      (while (not tchar)
 +        (message "%s%s"
 +                   (if wrong-char
 +                       "Invalid choice.  "
 +                     "")
 +                   full-prompt)
 +          (setq tchar
 +                (if (and (display-popup-menus-p)
 +                         last-input-event ; not during startup
 +                         (listp last-nonmenu-event)
 +                         use-dialog-box)
 +                    (x-popup-dialog
 +                     t
 +                     (cons prompt
 +                           (mapcar
 +                            (lambda (elem)
 +                              (cons (capitalize (cadr elem))
 +                                    (car elem)))
 +                            choices)))
 +                  (condition-case nil
 +                      (let ((cursor-in-echo-area t))
 +                        (read-char))
 +                    (error nil))))
 +          ;; The user has entered an invalid choice, so display the
 +          ;; help messages.
 +        (when (not (assq tchar choices))
 +          (setq wrong-char (not (memq tchar '(?? ?\C-h)))
 +                  tchar nil)
 +            (when wrong-char
 +              (ding))
 +            (with-help-window (setq buf (get-buffer-create
 +                                         "*Multiple Choice Help*"))
 +              (with-current-buffer buf
 +                (erase-buffer)
 +                (pop-to-buffer buf)
 +                (insert prompt "\n\n")
 +                (let* ((columns (/ (window-width) 25))
 +                       (fill-column 21)
 +                       (times 0)
 +                       (start (point)))
 +                  (dolist (elem choices)
 +                    (goto-char start)
 +                    (unless (zerop times)
 +                      (if (zerop (mod times columns))
 +                          ;; Go to the next "line".
 +                          (goto-char (setq start (point-max)))
 +                        ;; Add padding.
 +                        (while (not (eobp))
 +                          (end-of-line)
 +                          (insert (make-string (max (- (* (mod times columns)
 +                                                          (+ fill-column 4))
 +                                                       (current-column))
 +                                                    0)
 +                                               ?\s))
 +                          (forward-line 1))))
 +                    (setq times (1+ times))
 +                    (let ((text
 +                           (with-temp-buffer
 +                             (insert (format
 +                                      "%c: %s\n"
 +                                      (car elem)
 +                                      (cdr (assq (car elem) altered-names))))
 +                             (fill-region (point-min) (point-max))
 +                             (when (nth 2 elem)
 +                               (let ((start (point)))
 +                                 (insert (nth 2 elem))
 +                                 (unless (bolp)
 +                                   (insert "\n"))
 +                                 (fill-region start (point-max))))
 +                             (buffer-string))))
 +                      (goto-char start)
 +                      (dolist (line (split-string text "\n"))
 +                        (end-of-line)
 +                        (if (bolp)
 +                            (insert line "\n")
 +                          (insert line))
 +                        (forward-line 1)))))))))))
 +    (when (buffer-live-p buf)
 +      (kill-buffer buf))
 +    (assq tchar choices)))
 +
  (defun sit-for (seconds &optional nodisp obsolete)
    "Redisplay, then wait for SECONDS seconds.  Stop when input is available.
  SECONDS may be a floating-point value.
@@@ -2765,29 -2626,7 +2765,7 @@@ See also `locate-user-emacs-file'."
    "Determine the boundaries of the default tag, based on text at point.
  Return a cons cell with the beginning and end of the found tag.
  If there is no plausible default, return nil."
-   (let (from to bound)
-     (when (or (progn
-               ;; Look at text around `point'.
-               (save-excursion
-                 (skip-syntax-backward "w_") (setq from (point)))
-               (save-excursion
-                 (skip-syntax-forward "w_") (setq to (point)))
-               (> to from))
-             ;; Look between `line-beginning-position' and `point'.
-             (save-excursion
-               (and (setq bound (line-beginning-position))
-                    (skip-syntax-backward "^w_" bound)
-                    (> (setq to (point)) bound)
-                    (skip-syntax-backward "w_")
-                    (setq from (point))))
-             ;; Look between `point' and `line-end-position'.
-             (save-excursion
-               (and (setq bound (line-end-position))
-                    (skip-syntax-forward "^w_" bound)
-                    (< (setq from (point)) bound)
-                    (skip-syntax-forward "w_")
-                    (setq to (point)))))
-       (cons from to))))
+   (bounds-of-thing-at-point 'symbol))
  
  (defun find-tag-default ()
    "Determine default tag to search for, based on text at point.
@@@ -4263,6 -4102,41 +4241,6 @@@ If SYNTAX is nil, return nil.
  \f
  ;; Utility motion commands
  
 -(defvar word-move-empty-char-table nil
 -  "Used in `forward-word-strictly' and `backward-word-strictly'
 -to countermand the effect of `find-word-boundary-function-table'.")
 -
 -(defun forward-word-strictly (&optional arg)
 -  "Move point forward ARG words (backward if ARG is negative).
 -If ARG is omitted or nil, move point forward one word.
 -Normally returns t.
 -If an edge of the buffer or a field boundary is reached, point is left there
 -and the function returns nil.  Field boundaries are not noticed if
 -`inhibit-field-text-motion' is non-nil.
 -
 -This function is like `forward-word', but it is not affected
 -by `find-word-boundary-function-table' (as set up by
 -e.g. `subword-mode').  It is also not interactive."
 -  (let ((find-word-boundary-function-table
 -         (if (char-table-p word-move-empty-char-table)
 -             word-move-empty-char-table
 -           (setq word-move-empty-char-table (make-char-table nil)))))
 -    (forward-word (or arg 1))))
 -
 -(defun backward-word-strictly (&optional arg)
 -  "Move backward until encountering the beginning of a word.
 -With argument ARG, do this that many times.
 -If ARG is omitted or nil, move point backward one word.
 -
 -This function is like `forward-word', but it is not affected
 -by `find-word-boundary-function-table' (as set up by
 -e.g. `subword-mode').  It is also not interactive."
 -  (let ((find-word-boundary-function-table
 -         (if (char-table-p word-move-empty-char-table)
 -             word-move-empty-char-table
 -           (setq word-move-empty-char-table (make-char-table nil)))))
 -    (forward-word (- (or arg 1)))))
 -
  ;;  Whitespace
  
  (defun forward-whitespace (arg)