summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/button.el10
-rw-r--r--lisp/dnd.el5
-rw-r--r--lisp/emacs-lisp/cl-macs.el15
-rw-r--r--lisp/emacs-lisp/eieio.el17
-rw-r--r--lisp/net/browse-url.el176
-rw-r--r--lisp/net/eww.el2
-rw-r--r--lisp/progmodes/cc-align.el32
-rw-r--r--lisp/progmodes/cc-mode.el21
8 files changed, 228 insertions, 50 deletions
diff --git a/lisp/button.el b/lisp/button.el
index b3afc4eca25..3a6a6de774c 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -469,10 +469,12 @@ return t."
;; POS is a mouse event; switch to the proper window/buffer
(let ((posn (event-start pos)))
(with-current-buffer (window-buffer (posn-window posn))
- (if (posn-string posn)
- ;; mode-line, header-line, or display string event.
- (button-activate (posn-string posn) t)
- (push-button (posn-point posn) t))))
+ (let* ((str (posn-string posn))
+ (str-button (and str (get-text-property (cdr str) 'button (car str)))))
+ (if str-button
+ ;; mode-line, header-line, or display string event.
+ (button-activate str t)
+ (push-button (posn-point posn) t)))))
;; POS is just normal position
(let ((button (button-at (or pos (point)))))
(when button
diff --git a/lisp/dnd.el b/lisp/dnd.el
index c185794d6ea..f47f4a2c30e 100644
--- a/lisp/dnd.el
+++ b/lisp/dnd.el
@@ -101,7 +101,10 @@ is what has been dropped. Returns ACTION."
(throw 'done t)))
nil)
(catch 'done
- (let ((browser (browse-url-select-handler url)))
+ ;; Autoloaded but the byte-compiler still complains.
+ (declare-function browse-url-select-handler "browse-url"
+ (url &optional kind))
+ (let ((browser (browse-url-select-handler url 'internal)))
(when browser
(setq ret 'private)
(funcall browser url action)
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 4408bb58464..3317c580028 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1317,13 +1317,12 @@ For more details, see Info node `(cl)Loop Facility'.
((memq word '(across across-ref))
(let ((temp-vec (make-symbol "--cl-vec--"))
- (temp-len (make-symbol "--cl-len--"))
(temp-idx (make-symbol "--cl-idx--")))
(push (list temp-vec (pop cl--loop-args)) loop-for-bindings)
- (push (list temp-len `(length ,temp-vec)) loop-for-bindings)
(push (list temp-idx -1) loop-for-bindings)
+ (push `(setq ,temp-idx (1+ ,temp-idx)) cl--loop-body)
(cl--push-clause-loop-body
- `(< (setq ,temp-idx (1+ ,temp-idx)) ,temp-len))
+ `(< ,temp-idx (length ,temp-vec)))
(if (eq word 'across-ref)
(push (list var `(aref ,temp-vec ,temp-idx))
cl--loop-symbol-macs)
@@ -1337,7 +1336,6 @@ For more details, see Info node `(cl)Loop Facility'.
(error "Expected `of'"))))
(seq (cl--pop2 cl--loop-args))
(temp-seq (make-symbol "--cl-seq--"))
- (temp-len (make-symbol "--cl-len--"))
(temp-idx
(if (eq (car cl--loop-args) 'using)
(if (and (= (length (cadr cl--loop-args)) 2)
@@ -1348,19 +1346,16 @@ For more details, see Info node `(cl)Loop Facility'.
(push (list temp-seq seq) loop-for-bindings)
(push (list temp-idx 0) loop-for-bindings)
(if ref
- (progn
+ (let ((temp-len (make-symbol "--cl-len--")))
(push (list temp-len `(length ,temp-seq))
loop-for-bindings)
(push (list var `(elt ,temp-seq ,temp-idx))
cl--loop-symbol-macs)
- (cl--push-clause-loop-body `(< ,temp-idx ,temp-len)))
- ;; Evaluate seq length just if needed, that is, when seq is not a cons.
- (push (list temp-len (or (consp seq) `(length ,temp-seq)))
- loop-for-bindings)
+ (cl--push-clause-loop-body `(< ,temp-idx ,temp-len)))
(push (list var nil) loop-for-bindings)
(cl--push-clause-loop-body `(and ,temp-seq
(or (consp ,temp-seq)
- (< ,temp-idx ,temp-len))))
+ (< ,temp-idx (length ,temp-seq)))))
(push (list var `(if (consp ,temp-seq)
(pop ,temp-seq)
(aref ,temp-seq ,temp-idx)))
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index fe2b80be01e..999d75f79e9 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -359,16 +359,13 @@ contents of field NAME is matched against PAT, or they can be of
;; FIXME: `pcase' does not do a good job here of sharing tests&code among
;; various branches.
`(and (pred eieio-object-p)
- (app eieio-pcase-slot-index-table ,is)
- ,@(mapcar (lambda (field)
- (let* ((name (if (consp field) (car field) field))
- (pat (if (consp field) (cadr field) field))
- (i (make-symbol "index")))
- `(and (let (and ,i (pred natnump))
- (eieio-pcase-slot-index-from-index-table
- ,is ',name))
- (app (pcase--flip aref ,i) ,pat))))
- fields))))
+ ,@(mapcar (lambda (field)
+ (pcase-exhaustive field
+ (`(,name ,pat)
+ `(app (pcase--flip eieio-oref ',name) ,pat))
+ ((pred symbolp)
+ `(app (pcase--flip eieio-oref ',field) ,field))))
+ fields))))
;;; Simple generators, and query functions. None of these would do
;; well embedded into an object.
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index b34665358ca..f88de98fca7 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -119,6 +119,17 @@
;; could be done by setting `browse-url-browser-function' to an alist
;; but this usage is deprecated now.
+;; All browser functions provided by here have a
+;; `browse-url-browser-kind' symbol property set to either `internal'
+;; or `external' which determines if they browse the given URL inside
+;; Emacs or spawn an external application with it. Some parts of
+;; Emacs make use of that, e.g., when an URL is dragged into Emacs, it
+;; is not sensible to invoke an external browser with it, so here only
+;; internal browsers are considered. Therefore, it is advised to put
+;; that property also on custom browser functions.
+;; (put 'my-browse-url-in-emacs 'browse-url-browser-kind 'internal)
+;; (put 'my-browse-url-externally 'browse-url-browser-kind 'external)
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Code:
@@ -593,26 +604,54 @@ down (this *won't* always work)."
"Wrapper command prepended to the Elinks command-line."
:type '(repeat (string :tag "Wrapper")))
+(defun browse-url--browser-kind (function url)
+ "Return the browser kind of a browser FUNCTION for URL.
+The browser kind is either `internal' (the browser runs inside
+Emacs), `external' (the browser is spawned in an external
+process), or nil (we don't know)."
+ (let ((kind (if (symbolp function)
+ (get function 'browse-url-browser-kind))))
+ (if (functionp kind)
+ (funcall kind url)
+ kind)))
+
(defun browse-url--mailto (url &rest args)
"Calls `browse-url-mailto-function' with URL and ARGS."
(funcall browse-url-mailto-function url args))
+(defun browse-url--browser-kind-mailto (url)
+ (browse-url--browser-kind browse-url-mailto-function url))
+(put 'browse-url--mailto 'browse-url-browser-kind
+ #'browse-url--browser-kind-mailto)
+
(defun browse-url--man (url &rest args)
"Calls `browse-url-man-function' with URL and ARGS."
(funcall browse-url-man-function url args))
+(defun browse-url--browser-kind-man (url)
+ (browse-url--browser-kind browse-url-man-function url))
+(put 'browse-url--man 'browse-url-browser-kind
+ #'browse-url--browser-kind-man)
+
(defun browse-url--browser (url &rest args)
"Calls `browse-url-browser-function' with URL and ARGS."
(funcall browse-url-browser-function url args))
+(defun browse-url--browser-kind-browser (url)
+ (browse-url--browser-kind browse-url-browser-function url))
+(put 'browse-url--browser 'browse-url-browser-kind
+ #'browse-url--browser-kind-browser)
+
+(defun browse-url--non-html-file-url-p (url)
+ "Return non-nil if URL is a file:// URL of a non-HTML file."
+ (and (string-match-p "\\`file://" url)
+ (not (string-match-p "\\`file://.*\\.html?\\b" url))))
+
;;;###autoload
(defvar browse-url-default-handlers
'(("\\`mailto:" . browse-url--mailto)
("\\`man:" . browse-url--man)
- ;; Render file:// URLs if they are HTML pages, otherwise just find
- ;; the file.
- ("\\`file://.*\\.html?\\b" . browse-url--browser)
- ("\\`file://" . browse-url-emacs))
+ (browse-url--non-html-file-url-p . browse-url-emacs))
"Like `browse-url-handlers' but populated by Emacs and packages.
Emacs and external packages capable of browsing certain URLs
@@ -620,46 +659,60 @@ should place their entries in this alist rather than
`browse-url-handlers' which is reserved for the user.")
(defcustom browse-url-handlers nil
- "An alist with elements of the form (REGEXP HANDLER).
-Each REGEXP is matched against the URL to be opened in turn and
-the first match's HANDLER is invoked with the URL.
+ "An alist with elements of the form (REGEXP-OR-PREDICATE . HANDLER).
+Each REGEXP-OR-PREDICATE is matched against the URL to be opened
+in turn and the first match's HANDLER is invoked with the URL.
A HANDLER must be a function with the same arguments as
`browse-url'.
-If no REGEXP matches, the same procedure is performed with the
-value of `browse-url-default-handlers'. If there is also no
-match, the URL is opened using the value of
+If no REGEXP-OR-PREDICATE matches, the same procedure is
+performed with the value of `browse-url-default-handlers'. If
+there is also no match, the URL is opened using the value of
`browse-url-browser-function'."
- :type '(alist :key-type (regexp :tag "Regexp")
+ :type '(alist :key-type (choice
+ (regexp :tag "Regexp")
+ (function :tag "Predicate"))
:value-type (function :tag "Handler"))
:version "28.1")
;;;###autoload
-(defun browse-url-select-handler (url)
- "Return a handler suitable for browsing URL.
+(defun browse-url-select-handler (url &optional kind)
+ "Return a handler of suitable for browsing URL.
This searches `browse-url-handlers', and
`browse-url-default-handlers' for a matching handler. Return nil
if no handler is found.
+If KIND is given, the search is restricted to handlers whose
+function symbol has the symbol-property `browse-url-browser-kind'
+set to KIND.
+
Currently, it also consults `browse-url-browser-function' first
if it is set to an alist, although this usage is deprecated since
Emacs 28.1 and will be removed in a future release."
(catch 'custom-url-handler
- (dolist (regex-handler
+ (dolist (rxpred-handler
(append
;; The alist choice of browse-url-browser-function
;; is deprecated since 28.1, so the (unless ...)
;; can be removed at some point in time.
(when (and (consp browse-url-browser-function)
(not (functionp browse-url-browser-function)))
- (warn "Having `browse-url-browser-function' set to an
+ (lwarn 'browse-url :warning
+ "Having `browse-url-browser-function' set to an
alist is deprecated. Use `browse-url-handlers' instead.")
browse-url-browser-function)
browse-url-handlers
browse-url-default-handlers))
- (when (string-match-p (car regex-handler) url)
- (throw 'custom-url-handler (cdr regex-handler))))))
+ (let ((rx-or-pred (car rxpred-handler))
+ (handler (cdr rxpred-handler)))
+ (when (and (or (null kind)
+ (eq kind (browse-url--browser-kind
+ handler url)))
+ (if (functionp rx-or-pred)
+ (funcall rx-or-pred url)
+ (string-match-p rx-or-pred url)))
+ (throw 'custom-url-handler handler))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; URL encoding
@@ -864,7 +917,7 @@ If ARGS are omitted, the default is to pass
;; which may not even exist any more.
(if (stringp (frame-parameter nil 'display))
(setenv "DISPLAY" (frame-parameter nil 'display)))
- (if (functionp nil)
+ (if (functionp function)
(apply function url args)
(error "No suitable browser for URL %s" url))))
@@ -883,6 +936,34 @@ Optional prefix argument ARG non-nil inverts the value of the option
(error "No URL found"))))
;;;###autoload
+(defun browse-url-with-browser-kind (kind url &optional arg)
+ "Browse URL with a browser of the given browser KIND.
+KIND is either `internal' or `external'.
+
+When called interactively, the default browser kind is the
+opposite of the browser kind of `browse-url-browser-function'."
+ (interactive
+ (let* ((url-arg (browse-url-interactive-arg "URL: "))
+ ;; Default to the inverse kind of the default browser.
+ (default (if (eq (browse-url--browser-kind
+ browse-url-browser-function (car url-arg))
+ 'internal)
+ 'external
+ 'internal))
+ (k (intern (completing-read
+ (format "Browser kind (default %s): " default)
+ '(internal external)
+ nil t nil nil
+ default))))
+ (cons k url-arg)))
+ (let ((function (browse-url-select-handler url kind)))
+ (unless function
+ (setq function (if (eq kind 'external)
+ #'browse-url-default-browser
+ #'eww)))
+ (funcall function url arg)))
+
+;;;###autoload
(defun browse-url-at-mouse (event)
"Ask a WWW browser to load a URL clicked with the mouse.
The URL is the one around or before the position of the mouse click
@@ -929,12 +1010,18 @@ The optional NEW-WINDOW argument is not used."
(url-unhex-string url)
url)))))
+(put 'browse-url-default-windows-browser 'browse-url-browser-kind
+ 'external)
+
(defun browse-url-default-macosx-browser (url &optional _new-window)
"Invoke the macOS system's default Web browser.
The optional NEW-WINDOW argument is not used."
(interactive (browse-url-interactive-arg "URL: "))
(start-process (concat "open " url) nil "open" url))
+(put 'browse-url-default-macosx-browser 'browse-url-browser-kind
+ 'external)
+
;; --- Netscape ---
(defun browse-url-process-environment ()
@@ -991,6 +1078,10 @@ instead of `browse-url-new-window-flag'."
(lambda (&rest _ignore) (error "No usable browser found"))))
url args))
+(put 'browse-url-default-browser 'browse-url-browser-kind
+ ;; Well, most probably external if we ignore w3.
+ 'external)
+
(defun browse-url-can-use-xdg-open ()
"Return non-nil if the \"xdg-open\" program can be used.
xdg-open is a desktop utility that calls your preferred web browser."
@@ -1010,6 +1101,8 @@ The optional argument IGNORED is not used."
(interactive (browse-url-interactive-arg "URL: "))
(call-process "xdg-open" nil 0 nil url))
+(put 'browse-url-xdg-open 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-netscape (url &optional new-window)
"Ask the Netscape WWW browser to load URL.
@@ -1053,6 +1146,8 @@ used instead of `browse-url-new-window-flag'."
`(lambda (process change)
(browse-url-netscape-sentinel process ,url)))))
+(put 'browse-url-netscape 'browse-url-browser-kind 'external)
+
(defun browse-url-netscape-sentinel (process url)
"Handle a change to the process communicating with Netscape."
(declare (obsolete nil "25.1"))
@@ -1123,6 +1218,8 @@ used instead of `browse-url-new-window-flag'."
`(lambda (process change)
(browse-url-mozilla-sentinel process ,url)))))
+(put 'browse-url-mozilla 'browse-url-browser-kind 'external)
+
(defun browse-url-mozilla-sentinel (process url)
"Handle a change to the process communicating with Mozilla."
(or (eq (process-exit-status process) 0)
@@ -1163,6 +1260,8 @@ instead of `browse-url-new-window-flag'."
'("-new-window")))
(list url)))))
+(put 'browse-url-firefox 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-chromium (url &optional _new-window)
"Ask the Chromium WWW browser to load URL.
@@ -1180,6 +1279,8 @@ The optional argument NEW-WINDOW is not used."
browse-url-chromium-arguments
(list url)))))
+(put 'browse-url-chromium 'browse-url-browser-kind 'external)
+
(defun browse-url-chrome (url &optional _new-window)
"Ask the Google Chrome WWW browser to load URL.
Default to the URL around or before point. The strings in
@@ -1196,6 +1297,8 @@ The optional argument NEW-WINDOW is not used."
browse-url-chrome-arguments
(list url)))))
+(put 'browse-url-chrome 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-galeon (url &optional new-window)
"Ask the Galeon WWW browser to load URL.
@@ -1233,6 +1336,8 @@ used instead of `browse-url-new-window-flag'."
`(lambda (process change)
(browse-url-galeon-sentinel process ,url)))))
+(put 'browse-url-galeon 'browse-url-browser-kind 'external)
+
(defun browse-url-galeon-sentinel (process url)
"Handle a change to the process communicating with Galeon."
(declare (obsolete nil "25.1"))
@@ -1279,6 +1384,8 @@ used instead of `browse-url-new-window-flag'."
`(lambda (process change)
(browse-url-epiphany-sentinel process ,url)))))
+(put 'browse-url-epiphany 'browse-url-browser-kind 'external)
+
(defun browse-url-epiphany-sentinel (process url)
"Handle a change to the process communicating with Epiphany."
(or (eq (process-exit-status process) 0)
@@ -1303,6 +1410,8 @@ currently selected window instead."
file-name-handler-alist)))
(if same-window (find-file url) (find-file-other-window url))))
+(put 'browse-url-emacs 'browse-url-browser-kind 'internal)
+
;;;###autoload
(defun browse-url-gnome-moz (url &optional new-window)
"Ask Mozilla/Netscape to load URL via the GNOME program `gnome-moz-remote'.
@@ -1327,6 +1436,8 @@ used instead of `browse-url-new-window-flag'."
'("--newwin"))
(list "--raise" url))))
+(put 'browse-url-gnome-moz 'browse-url-browser-kind 'external)
+
;; --- Mosaic ---
;;;###autoload
@@ -1378,6 +1489,8 @@ used instead of `browse-url-new-window-flag'."
(append browse-url-mosaic-arguments (list url)))
(message "Starting %s...done" browse-url-mosaic-program))))
+(put 'browse-url-mosaic 'browse-url-browser-kind 'external)
+
;; --- Mosaic using CCI ---
;;;###autoload
@@ -1410,6 +1523,8 @@ used instead of `browse-url-new-window-flag'."
(process-send-string "browse-url" "disconnect\r\n")
(delete-process "browse-url"))
+(put 'browse-url-cci 'browse-url-browser-kind 'external)
+
;; --- Conkeror ---
;;;###autoload
(defun browse-url-conkeror (url &optional new-window)
@@ -1446,6 +1561,9 @@ NEW-WINDOW instead of `browse-url-new-window-flag'."
"window")
"buffer")
url))))))
+
+(put 'browse-url-conkeror 'browse-url-browser-kind 'external)
+
;; --- W3 ---
;; External.
@@ -1469,6 +1587,8 @@ used instead of `browse-url-new-window-flag'."
(w3-fetch-other-window url)
(w3-fetch url)))
+(put 'browse-url-w3 'browse-url-browser-kind 'internal)
+
;;;###autoload
(defun browse-url-w3-gnudoit (url &optional _new-window)
;; new-window ignored
@@ -1483,6 +1603,8 @@ The `browse-url-gnudoit-program' program is used with options given by
(list (concat "(w3-fetch \"" url "\")")
"(raise-frame)"))))
+(put 'browse-url-w3-gnudoit 'browse-url-browser-kind 'internal)
+
;; --- Lynx in an xterm ---
;;;###autoload
@@ -1500,6 +1622,8 @@ The optional argument NEW-WINDOW is not used."
,@browse-url-xterm-args "-e" ,browse-url-text-browser
,url)))
+(put 'browse-url-text-xterm 'browse-url-browser-kind 'external)
+
;; --- Lynx in an Emacs "term" window ---
(declare-function term-char-mode "term" ())
@@ -1574,6 +1698,8 @@ used instead of `browse-url-new-window-flag'."
url
"\r")))))
+(put 'browse-url-text-emacs 'browse-url-browser-kind 'internal)
+
;; --- mailto ---
(autoload 'rfc2368-parse-mailto-url "rfc2368")
@@ -1621,6 +1747,8 @@ used instead of `browse-url-new-window-flag'."
(unless (bolp)
(insert "\n"))))))))
+(put 'browse-url-mail 'browse-url-browser-kind 'internal)
+
;; --- man ---
(defvar manual-program)
@@ -1632,7 +1760,9 @@ used instead of `browse-url-new-window-flag'."
(setq url (replace-regexp-in-string "\\`man:" "" url))
(cond
((executable-find manual-program) (man url))
- (t (woman (replace-regexp-in-string "([[:alnum:]]+)" "" url)))))
+ (t (woman (replace-regexp-in-string "([[:alnum:]]+)" "" url)))))
+
+(put 'browse-url-man 'browse-url-browser-kind 'internal)
;; --- Random browser ---
@@ -1651,6 +1781,8 @@ don't offer a form of remote control."
0 nil
(append browse-url-generic-args (list url))))
+(put 'browse-url-generic 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-kde (url &optional _new-window)
"Ask the KDE WWW browser to load URL.
@@ -1661,6 +1793,8 @@ The optional argument NEW-WINDOW is not used."
(apply #'start-process (concat "KDE " url) nil browse-url-kde-program
(append browse-url-kde-args (list url))))
+(put 'browse-url-kde 'browse-url-browser-kind 'external)
+
(defun browse-url-elinks-new-window (url)
"Ask the Elinks WWW browser to load URL in a new window."
(let ((process-environment (browse-url-process-environment)))
@@ -1670,6 +1804,8 @@ The optional argument NEW-WINDOW is not used."
browse-url-elinks-wrapper
(list "elinks" url)))))
+(put 'browse-url-elinks-new-window 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-elinks (url &optional new-window)
"Ask the Elinks WWW browser to load URL.
@@ -1691,6 +1827,8 @@ from `browse-url-elinks-wrapper'."
`(lambda (process change)
(browse-url-elinks-sentinel process ,url))))))
+(put 'browse-url-elinks 'browse-url-browser-kind 'external)
+
(defun browse-url-elinks-sentinel (process url)
"Determines if Elinks is running or a new one has to be started."
;; Try to determine if an instance is running or if we have to
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 9cf9ecea0bf..a6c1abdbb19 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -310,6 +310,8 @@ the default EWW buffer."
(url-retrieve url 'eww-render
(list url nil (current-buffer)))))
+(put 'eww 'browse-url-browser-kind 'internal)
+
(defun eww--dwim-expand-url (url)
(setq url (string-trim url))
(cond ((string-match-p "\\`file:/" url))
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index f30477dc787..c49bdc5c518 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -790,6 +790,38 @@ arglist-cont-nonempty."
(or (c-lineup-assignments langelem)
c-basic-offset))
+(defun c-lineup-ternary-bodies (langelem)
+ "Line up true and false branches of a ternary operator (i.e. ‘?:’).
+More precisely, if the line starts with a colon which is a part of
+a said operator it with corresponding question mark; otherwise return
+nil. For example:
+
+ return arg % 2 == 0 ? arg / 2
+ : (3 * arg + 1); <- c-lineup-ternary-bodies
+
+Works with: arglist-cont, arglist-cont-nonempty and statement-cont.
+"
+ (save-excursion
+ (back-to-indentation)
+ (when (and (eq ?: (char-after))
+ (not (eq ?: (char-after (1+ (point))))))
+ (let ((limit (c-langelem-pos langelem)) (depth 1))
+ (catch 'done
+ (while (c-syntactic-skip-backward "^?:" limit t)
+ (goto-char (1- (point)))
+ (cond ((eq (char-after) ??)
+ ;; If we’ve found a question mark, decrease depth. If we’re
+ ;; reached zero, we’ve found the one we were looking for.
+ (when (zerop (setq depth (1- depth)))
+ (throw 'done (vector (current-column)))))
+ ((or (eq ?: (char-before)) (eq ?? (char-before)))
+ ;; Step over ‘::’ and ‘?:’ operators. We don’t have to
+ ;; handle ‘?:’ here but doing so saves an iteration.
+ (if (eq (point) limit)
+ (throw 'done nil)
+ (goto-char (1- (point)))))
+ ((setq depth (1+ depth)))))))))) ; Otherwise increase depth.
+
(defun c-lineup-cascaded-calls (langelem)
"Line up \"cascaded calls\" under each other.
If the line begins with \"->\" or \".\" and the preceding line ends
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index f92d3efdeb7..e3a924efb06 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -2541,13 +2541,21 @@ Key bindings:
(defconst c-or-c++-mode--regexp
(eval-when-compile
- (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*"))
+ (let ((id "[a-zA-Z_][a-zA-Z0-9_]*") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")
+ (headers '("string" "string_view" "iostream" "map" "unordered_map"
+ "set" "unordered_set" "vector" "tuple")))
(concat "^" ws-maybe "\\(?:"
- "using" ws "\\(?:namespace" ws "std;\\|std::\\)"
- "\\|" "namespace" "\\(:?" ws id "\\)?" ws-maybe "{"
- "\\|" "class" ws id ws-maybe "[:{\n]"
- "\\|" "template" ws-maybe "<.*>"
- "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>"
+ "using" ws "\\(?:namespace" ws
+ "\\|" id "::"
+ "\\|" id ws-maybe "=\\)"
+ "\\|" "\\(?:inline" ws "\\)?namespace"
+ "\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{"
+ "\\|" "class" ws id
+ "\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]"
+ "\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]"
+ "\\|" ws-maybe ":\\)"
+ "\\|" "template" ws-maybe "<.*?>"
+ "\\|" "#include" ws-maybe "<" (regexp-opt headers) ">"
"\\)")))
"A regexp applied to C header files to check if they are really C++.")
@@ -2563,6 +2571,7 @@ should be used.
This function attempts to use file contents to determine whether
the code is C or C++ and based on that chooses whether to enable
`c-mode' or `c++-mode'."
+ (interactive)
(if (save-excursion
(save-restriction
(save-match-data