1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-17 19:30:38 -08:00

Merge remote-tracking branch 'savannah/master' into HEAD

This commit is contained in:
Andrea Corallo 2020-05-09 14:06:55 +01:00
commit c6eb276076
14 changed files with 329 additions and 63 deletions

View file

@ -2926,7 +2926,8 @@ specifies your default browser.
@vindex browse-url-handlers
You can define that certain URLs are browsed with other functions by
customizing @code{browse-url-handlers}, an alist of regular
expressions paired with functions to browse matching URLs.
expressions or predicates paired with functions to browse matching
URLs.
For more information, view the package commentary by typing @kbd{C-h P
browse-url @key{RET}}.

View file

@ -6395,6 +6395,26 @@ function is the same as specifying a list @code{(c-lineup-assignments
@comment ------------------------------------------------------------
@defun c-lineup-ternary-bodies
@findex lineup-ternary-bodies @r{(c-)}
Line up true and false branches of a ternary operator
(i.e. @code{?:}). More precisely, if the line starts with a colon
which is a part of a said operator it with corresponding question
mark. For example:
@example
@group
return arg % 2 == 0 ? arg / 2
: (3 * arg + 1); @hereFn{c-lineup-ternary-bodies}
@end group
@end example
@workswith @code{arglist-cont}, @code{arglist-cont-nonempty} and
@code{statement-cont}.
@end defun
@comment ------------------------------------------------------------
@defun c-lineup-cascaded-calls
@findex lineup-cascaded-calls @r{(c-)}
Line up ``cascaded calls'' under each other. If the line begins with

View file

@ -305,21 +305,48 @@ use doxygen by default one might evaluate:
or use it in a custom c-style.
*** Added support to line up ? and : of a ternary operator.
The new c-lineup-ternary-bodies function can be used as a lineup
function to align question mark and colon which are part of a ternary
operator (?:). For example:
return arg % 2 == 0 ? arg / 2
: (3 * arg + 1);
To enable, add it to appropriate entries in c-offsets-alist, e.g.:
(c-set-offset 'arglist-cont '(c-lineup-ternary-bodies
c-lineup-gcc-asm-reg))
(c-set-offset 'arglist-cont-nonempty '(c-lineup-ternary-bodies
c-lineup-gcc-asm-reg
c-lineup-arglist))
(c-set-offset 'statement-cont '(c-lineup-ternary-bodies +))
** browse-url
*** Added support for custom URL handlers
There is a new defvar 'browse-url-default-handlers' and a defcustom
'browse-url-handlers' being alists with (REGEXP . FUNCTION) entries
allowing to define different browsing FUNCTIONs depending on the URL
to be browsed. The defvar is for default handlers provided by Emacs
itself or external packages, the defcustom is for the user (and allows
for overriding the default handlers).
'browse-url-handlers' being alists with (REGEXP-OR-PREDICATE
. FUNCTION) entries allowing to define different browsing FUNCTIONs
depending on the URL to be browsed. The defvar is for default
handlers provided by Emacs itself or external packages, the defcustom
is for the user (and allows for overriding the default handlers).
Formerly, one could do the same by setting
'browse-url-browser-function' to such an alist. This usage is still
supported but deprecated.
*** Categorization of browsing functions in internal vs. external
All standard browsing functions such as 'browse-url-firefox',
'browse-url-mail', or 'eww' have been categorized into internal (URL
is browsed in Emacs) or external (an external application is spawned
with the URL). This is done by adding a 'browse-url-browser-kind'
symbol property to the browsing functions. With a new command
'browse-url-with-browser-kind', an URL can explicitly be browsed with
either an internal or external browser.
* New Modes and Packages in Emacs 28.1

View file

@ -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)
(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 (posn-string posn) t)
(push-button (posn-point posn) t))))
(button-activate str t)
(push-button (posn-point posn) t)))))
;; POS is just normal position
(let ((button (button-at (or pos (point)))))
(when button

View file

@ -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)

View file

@ -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)
(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)))

View file

@ -359,15 +359,12 @@ 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))))
(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

View file

@ -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))))
@ -882,6 +935,34 @@ Optional prefix argument ARG non-nil inverts the value of the option
browse-url-new-window-flag))
(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.
@ -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)
@ -1634,6 +1762,8 @@ used instead of `browse-url-new-window-flag'."
((executable-find manual-program) (man url))
(t (woman (replace-regexp-in-string "([[:alnum:]]+)" "" url)))))
(put 'browse-url-man 'browse-url-browser-kind 'internal)
;; --- Random browser ---
;;;###autoload
@ -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

View file

@ -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))

View file

@ -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 weve found a question mark, decrease depth. If were
;; reached zero, weve 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 dont 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

View file

@ -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

View file

@ -766,14 +766,13 @@ the current buffer), POSITION is a buffer position (integer or marker).
If OBJECT is a string, POSITION is a 0-based index into it.
In a string, scan runs to the end of the string, unless LIMIT is non-nil.
In a buffer, if LIMIT is nil or omitted, it runs to (point-max), and the
value cannot exceed that.
In a buffer, scan runs to end of buffer, unless LIMIT is non-nil.
If the optional fourth argument LIMIT is non-nil, don't search
past position LIMIT; return LIMIT if nothing is found before LIMIT.
However, if OBJECT is a buffer and LIMIT is beyond the end of the
buffer, this function returns `point-max', not LIMIT.
The property values are compared with `eq'.
If the property is constant all the way to the end of OBJECT, return the
last valid position in OBJECT. */)
The property values are compared with `eq'. */)
(Lisp_Object position, Lisp_Object prop, Lisp_Object object, Lisp_Object limit)
{
if (STRINGP (object))
@ -832,6 +831,9 @@ last valid position in OBJECT. */)
value = Fget_char_property (position, prop, object);
if (!EQ (value, initial_value))
break;
if (XFIXNAT (position) >= ZV)
break;
}
position = unbind_to (count, position);

View file

@ -39,6 +39,15 @@
collect (list c b a))
'((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
(ert-deftest cl-macs-loop-and-arrays ()
"Bug#40727"
(should (equal (cl-loop for y = (- (or x 0)) and x across [1 2]
collect (cons x y))
'((1 . 0) (2 . -1))))
(should (equal (cl-loop for x across [1 2] and y = (- (or x 0))
collect (cons x y))
'((1 . 0) (2 . -1)))))
(ert-deftest cl-macs-loop-destructure ()
(should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
collect (list c b a))

View file

@ -53,11 +53,18 @@
(funcall do-test (concat " * " content) 'c-mode))
'("using \t namespace \t std;"
"using \t std::string;"
"using Foo = Bar;"
"namespace \t {"
"namespace \t foo \t {"
"class \t Blah_42 \t {"
"namespace \t foo::bar \t {"
"inline namespace \t foo \t {"
"inline namespace \t foo::bar \t {"
"class \t Blah_42 \t \n"
"class \t Blah_42;"
"class \t Blah_42 \t final {"
"struct \t Blah_42 \t final {"
"class \t _42_Blah:public Foo {"
"struct \t _42_Blah:public Foo {"
"template \t < class T >"
"template< class T >"
"#include <string>"
@ -67,6 +74,7 @@
(mapc (lambda (content) (funcall do-test content 'c-mode))
'("struct \t Blah_42 \t {"
"struct template {"
"struct Blah;"
"#include <string.h>")))))
(ert-deftest c-mode-macro-comment ()
@ -78,4 +86,25 @@
(insert macro-string)
(c-mode))))
(ert-deftest c-lineup-ternary-bodies ()
"Test for c-lineup-ternary-bodies function"
(with-temp-buffer
(c-mode)
(let* ((common-prefix "int value = condition ")
(expected-column (length common-prefix)))
(dolist (test '(("? a : \n b" . nil)
("? a \n ::b" . nil)
("a \n : b" . nil)
("? a \n : b" . t)
("? ::a \n : b" . t)
("? (p ? q : r) \n : b" . t)
("? p ?: q \n : b" . t)
("? p ? : q \n : b" . t)
("? p ? q : r \n : b" . t)))
(delete-region (point-min) (point-max))
(insert common-prefix (car test))
(should (equal
(and (cdr test) (vector expected-column))
(c-lineup-ternary-bodies '(statement-cont . 1))))))))
;;; cc-mode-tests.el ends here