diff options
author | Andrea Corallo <akrl@sdf.org> | 2020-05-09 14:06:55 +0100 |
---|---|---|
committer | Andrea Corallo <akrl@sdf.org> | 2020-05-09 14:06:55 +0100 |
commit | c6eb2760766b402fb620a733d100adfd320e4df5 (patch) | |
tree | 9a116468d6b11f22a68680d05dd5bfaacd2e0c4c | |
parent | 40f655e0505d954e507ead5f5bda7dc7113adc06 (diff) | |
parent | ae3c510696f02f01d03052f070e5ce65b4018a45 (diff) | |
download | emacs-c6eb2760766b402fb620a733d100adfd320e4df5.tar.gz emacs-c6eb2760766b402fb620a733d100adfd320e4df5.tar.bz2 emacs-c6eb2760766b402fb620a733d100adfd320e4df5.zip |
Merge remote-tracking branch 'savannah/master' into HEAD
-rw-r--r-- | doc/emacs/misc.texi | 3 | ||||
-rw-r--r-- | doc/misc/cc-mode.texi | 20 | ||||
-rw-r--r-- | etc/NEWS | 37 | ||||
-rw-r--r-- | lisp/button.el | 10 | ||||
-rw-r--r-- | lisp/dnd.el | 5 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 15 | ||||
-rw-r--r-- | lisp/emacs-lisp/eieio.el | 17 | ||||
-rw-r--r-- | lisp/net/browse-url.el | 176 | ||||
-rw-r--r-- | lisp/net/eww.el | 2 | ||||
-rw-r--r-- | lisp/progmodes/cc-align.el | 32 | ||||
-rw-r--r-- | lisp/progmodes/cc-mode.el | 21 | ||||
-rw-r--r-- | src/textprop.c | 12 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/cl-macs-tests.el | 9 | ||||
-rw-r--r-- | test/lisp/progmodes/cc-mode-tests.el | 33 |
14 files changed, 329 insertions, 63 deletions
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index d1854f31ff3..1336da12b07 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -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}}. diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index f9c9f5e1830..16eac4828c7 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -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 @@ -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 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 diff --git a/src/textprop.c b/src/textprop.c index 960dba3f8dc..0876badc873 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -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); diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el index 9ca84f156a0..983e79ac57c 100644 --- a/test/lisp/emacs-lisp/cl-macs-tests.el +++ b/test/lisp/emacs-lisp/cl-macs-tests.el @@ -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)) diff --git a/test/lisp/progmodes/cc-mode-tests.el b/test/lisp/progmodes/cc-mode-tests.el index 0729841ce6f..64d52a952b6 100644 --- a/test/lisp/progmodes/cc-mode-tests.el +++ b/test/lisp/progmodes/cc-mode-tests.el @@ -40,7 +40,7 @@ (insert content) (setq mode nil) (c-or-c++-mode) - (unless(eq expected mode) + (unless (eq expected mode) (ert-fail (format "expected %s but got %s when testing '%s'" expected mode content))))) @@ -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 |