diff options
| author | Andrea Corallo | 2020-05-09 14:06:55 +0100 |
|---|---|---|
| committer | Andrea Corallo | 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.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. | |||
| 2926 | @vindex browse-url-handlers | 2926 | @vindex browse-url-handlers |
| 2927 | You can define that certain URLs are browsed with other functions by | 2927 | You can define that certain URLs are browsed with other functions by |
| 2928 | customizing @code{browse-url-handlers}, an alist of regular | 2928 | customizing @code{browse-url-handlers}, an alist of regular |
| 2929 | expressions paired with functions to browse matching URLs. | 2929 | expressions or predicates paired with functions to browse matching |
| 2930 | URLs. | ||
| 2930 | 2931 | ||
| 2931 | For more information, view the package commentary by typing @kbd{C-h P | 2932 | For more information, view the package commentary by typing @kbd{C-h P |
| 2932 | browse-url @key{RET}}. | 2933 | 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 | |||
| 6395 | 6395 | ||
| 6396 | @comment ------------------------------------------------------------ | 6396 | @comment ------------------------------------------------------------ |
| 6397 | 6397 | ||
| 6398 | @defun c-lineup-ternary-bodies | ||
| 6399 | @findex lineup-ternary-bodies @r{(c-)} | ||
| 6400 | Line up true and false branches of a ternary operator | ||
| 6401 | (i.e. @code{?:}). More precisely, if the line starts with a colon | ||
| 6402 | which is a part of a said operator it with corresponding question | ||
| 6403 | mark. For example: | ||
| 6404 | |||
| 6405 | @example | ||
| 6406 | @group | ||
| 6407 | return arg % 2 == 0 ? arg / 2 | ||
| 6408 | : (3 * arg + 1); @hereFn{c-lineup-ternary-bodies} | ||
| 6409 | @end group | ||
| 6410 | @end example | ||
| 6411 | |||
| 6412 | @workswith @code{arglist-cont}, @code{arglist-cont-nonempty} and | ||
| 6413 | @code{statement-cont}. | ||
| 6414 | @end defun | ||
| 6415 | |||
| 6416 | @comment ------------------------------------------------------------ | ||
| 6417 | |||
| 6398 | @defun c-lineup-cascaded-calls | 6418 | @defun c-lineup-cascaded-calls |
| 6399 | @findex lineup-cascaded-calls @r{(c-)} | 6419 | @findex lineup-cascaded-calls @r{(c-)} |
| 6400 | Line up ``cascaded calls'' under each other. If the line begins with | 6420 | Line up ``cascaded calls'' under each other. If the line begins with |
| @@ -305,21 +305,48 @@ use ‘doxygen’ by default one might evaluate: | |||
| 305 | 305 | ||
| 306 | or use it in a custom ‘c-style’. | 306 | or use it in a custom ‘c-style’. |
| 307 | 307 | ||
| 308 | *** Added support to line up ‘?’ and ‘:’ of a ternary operator. | ||
| 309 | The new ‘c-lineup-ternary-bodies’ function can be used as a lineup | ||
| 310 | function to align question mark and colon which are part of a ternary | ||
| 311 | operator (‘?:’). For example: | ||
| 312 | |||
| 313 | return arg % 2 == 0 ? arg / 2 | ||
| 314 | : (3 * arg + 1); | ||
| 315 | |||
| 316 | To enable, add it to appropriate entries in ‘c-offsets-alist’, e.g.: | ||
| 317 | |||
| 318 | (c-set-offset 'arglist-cont '(c-lineup-ternary-bodies | ||
| 319 | c-lineup-gcc-asm-reg)) | ||
| 320 | (c-set-offset 'arglist-cont-nonempty '(c-lineup-ternary-bodies | ||
| 321 | c-lineup-gcc-asm-reg | ||
| 322 | c-lineup-arglist)) | ||
| 323 | (c-set-offset 'statement-cont '(c-lineup-ternary-bodies +)) | ||
| 324 | |||
| 308 | ** browse-url | 325 | ** browse-url |
| 309 | 326 | ||
| 310 | *** Added support for custom URL handlers | 327 | *** Added support for custom URL handlers |
| 311 | 328 | ||
| 312 | There is a new defvar 'browse-url-default-handlers' and a defcustom | 329 | There is a new defvar 'browse-url-default-handlers' and a defcustom |
| 313 | 'browse-url-handlers' being alists with (REGEXP . FUNCTION) entries | 330 | 'browse-url-handlers' being alists with (REGEXP-OR-PREDICATE |
| 314 | allowing to define different browsing FUNCTIONs depending on the URL | 331 | . FUNCTION) entries allowing to define different browsing FUNCTIONs |
| 315 | to be browsed. The defvar is for default handlers provided by Emacs | 332 | depending on the URL to be browsed. The defvar is for default |
| 316 | itself or external packages, the defcustom is for the user (and allows | 333 | handlers provided by Emacs itself or external packages, the defcustom |
| 317 | for overriding the default handlers). | 334 | is for the user (and allows for overriding the default handlers). |
| 318 | 335 | ||
| 319 | Formerly, one could do the same by setting | 336 | Formerly, one could do the same by setting |
| 320 | 'browse-url-browser-function' to such an alist. This usage is still | 337 | 'browse-url-browser-function' to such an alist. This usage is still |
| 321 | supported but deprecated. | 338 | supported but deprecated. |
| 322 | 339 | ||
| 340 | *** Categorization of browsing functions in internal vs. external | ||
| 341 | |||
| 342 | All standard browsing functions such as 'browse-url-firefox', | ||
| 343 | 'browse-url-mail', or 'eww' have been categorized into internal (URL | ||
| 344 | is browsed in Emacs) or external (an external application is spawned | ||
| 345 | with the URL). This is done by adding a 'browse-url-browser-kind' | ||
| 346 | symbol property to the browsing functions. With a new command | ||
| 347 | 'browse-url-with-browser-kind', an URL can explicitly be browsed with | ||
| 348 | either an internal or external browser. | ||
| 349 | |||
| 323 | 350 | ||
| 324 | * New Modes and Packages in Emacs 28.1 | 351 | * New Modes and Packages in Emacs 28.1 |
| 325 | 352 | ||
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." | |||
| 469 | ;; POS is a mouse event; switch to the proper window/buffer | 469 | ;; POS is a mouse event; switch to the proper window/buffer |
| 470 | (let ((posn (event-start pos))) | 470 | (let ((posn (event-start pos))) |
| 471 | (with-current-buffer (window-buffer (posn-window posn)) | 471 | (with-current-buffer (window-buffer (posn-window posn)) |
| 472 | (if (posn-string posn) | 472 | (let* ((str (posn-string posn)) |
| 473 | ;; mode-line, header-line, or display string event. | 473 | (str-button (and str (get-text-property (cdr str) 'button (car str))))) |
| 474 | (button-activate (posn-string posn) t) | 474 | (if str-button |
| 475 | (push-button (posn-point posn) t)))) | 475 | ;; mode-line, header-line, or display string event. |
| 476 | (button-activate str t) | ||
| 477 | (push-button (posn-point posn) t))))) | ||
| 476 | ;; POS is just normal position | 478 | ;; POS is just normal position |
| 477 | (let ((button (button-at (or pos (point))))) | 479 | (let ((button (button-at (or pos (point))))) |
| 478 | (when button | 480 | (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." | |||
| 101 | (throw 'done t))) | 101 | (throw 'done t))) |
| 102 | nil) | 102 | nil) |
| 103 | (catch 'done | 103 | (catch 'done |
| 104 | (let ((browser (browse-url-select-handler url))) | 104 | ;; Autoloaded but the byte-compiler still complains. |
| 105 | (declare-function browse-url-select-handler "browse-url" | ||
| 106 | (url &optional kind)) | ||
| 107 | (let ((browser (browse-url-select-handler url 'internal))) | ||
| 105 | (when browser | 108 | (when browser |
| 106 | (setq ret 'private) | 109 | (setq ret 'private) |
| 107 | (funcall browser url action) | 110 | (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'. | |||
| 1317 | 1317 | ||
| 1318 | ((memq word '(across across-ref)) | 1318 | ((memq word '(across across-ref)) |
| 1319 | (let ((temp-vec (make-symbol "--cl-vec--")) | 1319 | (let ((temp-vec (make-symbol "--cl-vec--")) |
| 1320 | (temp-len (make-symbol "--cl-len--")) | ||
| 1321 | (temp-idx (make-symbol "--cl-idx--"))) | 1320 | (temp-idx (make-symbol "--cl-idx--"))) |
| 1322 | (push (list temp-vec (pop cl--loop-args)) loop-for-bindings) | 1321 | (push (list temp-vec (pop cl--loop-args)) loop-for-bindings) |
| 1323 | (push (list temp-len `(length ,temp-vec)) loop-for-bindings) | ||
| 1324 | (push (list temp-idx -1) loop-for-bindings) | 1322 | (push (list temp-idx -1) loop-for-bindings) |
| 1323 | (push `(setq ,temp-idx (1+ ,temp-idx)) cl--loop-body) | ||
| 1325 | (cl--push-clause-loop-body | 1324 | (cl--push-clause-loop-body |
| 1326 | `(< (setq ,temp-idx (1+ ,temp-idx)) ,temp-len)) | 1325 | `(< ,temp-idx (length ,temp-vec))) |
| 1327 | (if (eq word 'across-ref) | 1326 | (if (eq word 'across-ref) |
| 1328 | (push (list var `(aref ,temp-vec ,temp-idx)) | 1327 | (push (list var `(aref ,temp-vec ,temp-idx)) |
| 1329 | cl--loop-symbol-macs) | 1328 | cl--loop-symbol-macs) |
| @@ -1337,7 +1336,6 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1337 | (error "Expected `of'")))) | 1336 | (error "Expected `of'")))) |
| 1338 | (seq (cl--pop2 cl--loop-args)) | 1337 | (seq (cl--pop2 cl--loop-args)) |
| 1339 | (temp-seq (make-symbol "--cl-seq--")) | 1338 | (temp-seq (make-symbol "--cl-seq--")) |
| 1340 | (temp-len (make-symbol "--cl-len--")) | ||
| 1341 | (temp-idx | 1339 | (temp-idx |
| 1342 | (if (eq (car cl--loop-args) 'using) | 1340 | (if (eq (car cl--loop-args) 'using) |
| 1343 | (if (and (= (length (cadr cl--loop-args)) 2) | 1341 | (if (and (= (length (cadr cl--loop-args)) 2) |
| @@ -1348,19 +1346,16 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1348 | (push (list temp-seq seq) loop-for-bindings) | 1346 | (push (list temp-seq seq) loop-for-bindings) |
| 1349 | (push (list temp-idx 0) loop-for-bindings) | 1347 | (push (list temp-idx 0) loop-for-bindings) |
| 1350 | (if ref | 1348 | (if ref |
| 1351 | (progn | 1349 | (let ((temp-len (make-symbol "--cl-len--"))) |
| 1352 | (push (list temp-len `(length ,temp-seq)) | 1350 | (push (list temp-len `(length ,temp-seq)) |
| 1353 | loop-for-bindings) | 1351 | loop-for-bindings) |
| 1354 | (push (list var `(elt ,temp-seq ,temp-idx)) | 1352 | (push (list var `(elt ,temp-seq ,temp-idx)) |
| 1355 | cl--loop-symbol-macs) | 1353 | cl--loop-symbol-macs) |
| 1356 | (cl--push-clause-loop-body `(< ,temp-idx ,temp-len))) | 1354 | (cl--push-clause-loop-body `(< ,temp-idx ,temp-len))) |
| 1357 | ;; Evaluate seq length just if needed, that is, when seq is not a cons. | ||
| 1358 | (push (list temp-len (or (consp seq) `(length ,temp-seq))) | ||
| 1359 | loop-for-bindings) | ||
| 1360 | (push (list var nil) loop-for-bindings) | 1355 | (push (list var nil) loop-for-bindings) |
| 1361 | (cl--push-clause-loop-body `(and ,temp-seq | 1356 | (cl--push-clause-loop-body `(and ,temp-seq |
| 1362 | (or (consp ,temp-seq) | 1357 | (or (consp ,temp-seq) |
| 1363 | (< ,temp-idx ,temp-len)))) | 1358 | (< ,temp-idx (length ,temp-seq))))) |
| 1364 | (push (list var `(if (consp ,temp-seq) | 1359 | (push (list var `(if (consp ,temp-seq) |
| 1365 | (pop ,temp-seq) | 1360 | (pop ,temp-seq) |
| 1366 | (aref ,temp-seq ,temp-idx))) | 1361 | (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 | |||
| 359 | ;; FIXME: `pcase' does not do a good job here of sharing tests&code among | 359 | ;; FIXME: `pcase' does not do a good job here of sharing tests&code among |
| 360 | ;; various branches. | 360 | ;; various branches. |
| 361 | `(and (pred eieio-object-p) | 361 | `(and (pred eieio-object-p) |
| 362 | (app eieio-pcase-slot-index-table ,is) | 362 | ,@(mapcar (lambda (field) |
| 363 | ,@(mapcar (lambda (field) | 363 | (pcase-exhaustive field |
| 364 | (let* ((name (if (consp field) (car field) field)) | 364 | (`(,name ,pat) |
| 365 | (pat (if (consp field) (cadr field) field)) | 365 | `(app (pcase--flip eieio-oref ',name) ,pat)) |
| 366 | (i (make-symbol "index"))) | 366 | ((pred symbolp) |
| 367 | `(and (let (and ,i (pred natnump)) | 367 | `(app (pcase--flip eieio-oref ',field) ,field)))) |
| 368 | (eieio-pcase-slot-index-from-index-table | 368 | fields)))) |
| 369 | ,is ',name)) | ||
| 370 | (app (pcase--flip aref ,i) ,pat)))) | ||
| 371 | fields)))) | ||
| 372 | 369 | ||
| 373 | ;;; Simple generators, and query functions. None of these would do | 370 | ;;; Simple generators, and query functions. None of these would do |
| 374 | ;; well embedded into an object. | 371 | ;; 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 @@ | |||
| 119 | ;; could be done by setting `browse-url-browser-function' to an alist | 119 | ;; could be done by setting `browse-url-browser-function' to an alist |
| 120 | ;; but this usage is deprecated now. | 120 | ;; but this usage is deprecated now. |
| 121 | 121 | ||
| 122 | ;; All browser functions provided by here have a | ||
| 123 | ;; `browse-url-browser-kind' symbol property set to either `internal' | ||
| 124 | ;; or `external' which determines if they browse the given URL inside | ||
| 125 | ;; Emacs or spawn an external application with it. Some parts of | ||
| 126 | ;; Emacs make use of that, e.g., when an URL is dragged into Emacs, it | ||
| 127 | ;; is not sensible to invoke an external browser with it, so here only | ||
| 128 | ;; internal browsers are considered. Therefore, it is advised to put | ||
| 129 | ;; that property also on custom browser functions. | ||
| 130 | ;; (put 'my-browse-url-in-emacs 'browse-url-browser-kind 'internal) | ||
| 131 | ;; (put 'my-browse-url-externally 'browse-url-browser-kind 'external) | ||
| 132 | |||
| 122 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 133 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 123 | ;;; Code: | 134 | ;;; Code: |
| 124 | 135 | ||
| @@ -593,26 +604,54 @@ down (this *won't* always work)." | |||
| 593 | "Wrapper command prepended to the Elinks command-line." | 604 | "Wrapper command prepended to the Elinks command-line." |
| 594 | :type '(repeat (string :tag "Wrapper"))) | 605 | :type '(repeat (string :tag "Wrapper"))) |
| 595 | 606 | ||
| 607 | (defun browse-url--browser-kind (function url) | ||
| 608 | "Return the browser kind of a browser FUNCTION for URL. | ||
| 609 | The browser kind is either `internal' (the browser runs inside | ||
| 610 | Emacs), `external' (the browser is spawned in an external | ||
| 611 | process), or nil (we don't know)." | ||
| 612 | (let ((kind (if (symbolp function) | ||
| 613 | (get function 'browse-url-browser-kind)))) | ||
| 614 | (if (functionp kind) | ||
| 615 | (funcall kind url) | ||
| 616 | kind))) | ||
| 617 | |||
| 596 | (defun browse-url--mailto (url &rest args) | 618 | (defun browse-url--mailto (url &rest args) |
| 597 | "Calls `browse-url-mailto-function' with URL and ARGS." | 619 | "Calls `browse-url-mailto-function' with URL and ARGS." |
| 598 | (funcall browse-url-mailto-function url args)) | 620 | (funcall browse-url-mailto-function url args)) |
| 599 | 621 | ||
| 622 | (defun browse-url--browser-kind-mailto (url) | ||
| 623 | (browse-url--browser-kind browse-url-mailto-function url)) | ||
| 624 | (put 'browse-url--mailto 'browse-url-browser-kind | ||
| 625 | #'browse-url--browser-kind-mailto) | ||
| 626 | |||
| 600 | (defun browse-url--man (url &rest args) | 627 | (defun browse-url--man (url &rest args) |
| 601 | "Calls `browse-url-man-function' with URL and ARGS." | 628 | "Calls `browse-url-man-function' with URL and ARGS." |
| 602 | (funcall browse-url-man-function url args)) | 629 | (funcall browse-url-man-function url args)) |
| 603 | 630 | ||
| 631 | (defun browse-url--browser-kind-man (url) | ||
| 632 | (browse-url--browser-kind browse-url-man-function url)) | ||
| 633 | (put 'browse-url--man 'browse-url-browser-kind | ||
| 634 | #'browse-url--browser-kind-man) | ||
| 635 | |||
| 604 | (defun browse-url--browser (url &rest args) | 636 | (defun browse-url--browser (url &rest args) |
| 605 | "Calls `browse-url-browser-function' with URL and ARGS." | 637 | "Calls `browse-url-browser-function' with URL and ARGS." |
| 606 | (funcall browse-url-browser-function url args)) | 638 | (funcall browse-url-browser-function url args)) |
| 607 | 639 | ||
| 640 | (defun browse-url--browser-kind-browser (url) | ||
| 641 | (browse-url--browser-kind browse-url-browser-function url)) | ||
| 642 | (put 'browse-url--browser 'browse-url-browser-kind | ||
| 643 | #'browse-url--browser-kind-browser) | ||
| 644 | |||
| 645 | (defun browse-url--non-html-file-url-p (url) | ||
| 646 | "Return non-nil if URL is a file:// URL of a non-HTML file." | ||
| 647 | (and (string-match-p "\\`file://" url) | ||
| 648 | (not (string-match-p "\\`file://.*\\.html?\\b" url)))) | ||
| 649 | |||
| 608 | ;;;###autoload | 650 | ;;;###autoload |
| 609 | (defvar browse-url-default-handlers | 651 | (defvar browse-url-default-handlers |
| 610 | '(("\\`mailto:" . browse-url--mailto) | 652 | '(("\\`mailto:" . browse-url--mailto) |
| 611 | ("\\`man:" . browse-url--man) | 653 | ("\\`man:" . browse-url--man) |
| 612 | ;; Render file:// URLs if they are HTML pages, otherwise just find | 654 | (browse-url--non-html-file-url-p . browse-url-emacs)) |
| 613 | ;; the file. | ||
| 614 | ("\\`file://.*\\.html?\\b" . browse-url--browser) | ||
| 615 | ("\\`file://" . browse-url-emacs)) | ||
| 616 | "Like `browse-url-handlers' but populated by Emacs and packages. | 655 | "Like `browse-url-handlers' but populated by Emacs and packages. |
| 617 | 656 | ||
| 618 | Emacs and external packages capable of browsing certain URLs | 657 | Emacs and external packages capable of browsing certain URLs |
| @@ -620,46 +659,60 @@ should place their entries in this alist rather than | |||
| 620 | `browse-url-handlers' which is reserved for the user.") | 659 | `browse-url-handlers' which is reserved for the user.") |
| 621 | 660 | ||
| 622 | (defcustom browse-url-handlers nil | 661 | (defcustom browse-url-handlers nil |
| 623 | "An alist with elements of the form (REGEXP HANDLER). | 662 | "An alist with elements of the form (REGEXP-OR-PREDICATE . HANDLER). |
| 624 | Each REGEXP is matched against the URL to be opened in turn and | 663 | Each REGEXP-OR-PREDICATE is matched against the URL to be opened |
| 625 | the first match's HANDLER is invoked with the URL. | 664 | in turn and the first match's HANDLER is invoked with the URL. |
| 626 | 665 | ||
| 627 | A HANDLER must be a function with the same arguments as | 666 | A HANDLER must be a function with the same arguments as |
| 628 | `browse-url'. | 667 | `browse-url'. |
| 629 | 668 | ||
| 630 | If no REGEXP matches, the same procedure is performed with the | 669 | If no REGEXP-OR-PREDICATE matches, the same procedure is |
| 631 | value of `browse-url-default-handlers'. If there is also no | 670 | performed with the value of `browse-url-default-handlers'. If |
| 632 | match, the URL is opened using the value of | 671 | there is also no match, the URL is opened using the value of |
| 633 | `browse-url-browser-function'." | 672 | `browse-url-browser-function'." |
| 634 | :type '(alist :key-type (regexp :tag "Regexp") | 673 | :type '(alist :key-type (choice |
| 674 | (regexp :tag "Regexp") | ||
| 675 | (function :tag "Predicate")) | ||
| 635 | :value-type (function :tag "Handler")) | 676 | :value-type (function :tag "Handler")) |
| 636 | :version "28.1") | 677 | :version "28.1") |
| 637 | 678 | ||
| 638 | ;;;###autoload | 679 | ;;;###autoload |
| 639 | (defun browse-url-select-handler (url) | 680 | (defun browse-url-select-handler (url &optional kind) |
| 640 | "Return a handler suitable for browsing URL. | 681 | "Return a handler of suitable for browsing URL. |
| 641 | This searches `browse-url-handlers', and | 682 | This searches `browse-url-handlers', and |
| 642 | `browse-url-default-handlers' for a matching handler. Return nil | 683 | `browse-url-default-handlers' for a matching handler. Return nil |
| 643 | if no handler is found. | 684 | if no handler is found. |
| 644 | 685 | ||
| 686 | If KIND is given, the search is restricted to handlers whose | ||
| 687 | function symbol has the symbol-property `browse-url-browser-kind' | ||
| 688 | set to KIND. | ||
| 689 | |||
| 645 | Currently, it also consults `browse-url-browser-function' first | 690 | Currently, it also consults `browse-url-browser-function' first |
| 646 | if it is set to an alist, although this usage is deprecated since | 691 | if it is set to an alist, although this usage is deprecated since |
| 647 | Emacs 28.1 and will be removed in a future release." | 692 | Emacs 28.1 and will be removed in a future release." |
| 648 | (catch 'custom-url-handler | 693 | (catch 'custom-url-handler |
| 649 | (dolist (regex-handler | 694 | (dolist (rxpred-handler |
| 650 | (append | 695 | (append |
| 651 | ;; The alist choice of browse-url-browser-function | 696 | ;; The alist choice of browse-url-browser-function |
| 652 | ;; is deprecated since 28.1, so the (unless ...) | 697 | ;; is deprecated since 28.1, so the (unless ...) |
| 653 | ;; can be removed at some point in time. | 698 | ;; can be removed at some point in time. |
| 654 | (when (and (consp browse-url-browser-function) | 699 | (when (and (consp browse-url-browser-function) |
| 655 | (not (functionp browse-url-browser-function))) | 700 | (not (functionp browse-url-browser-function))) |
| 656 | (warn "Having `browse-url-browser-function' set to an | 701 | (lwarn 'browse-url :warning |
| 702 | "Having `browse-url-browser-function' set to an | ||
| 657 | alist is deprecated. Use `browse-url-handlers' instead.") | 703 | alist is deprecated. Use `browse-url-handlers' instead.") |
| 658 | browse-url-browser-function) | 704 | browse-url-browser-function) |
| 659 | browse-url-handlers | 705 | browse-url-handlers |
| 660 | browse-url-default-handlers)) | 706 | browse-url-default-handlers)) |
| 661 | (when (string-match-p (car regex-handler) url) | 707 | (let ((rx-or-pred (car rxpred-handler)) |
| 662 | (throw 'custom-url-handler (cdr regex-handler)))))) | 708 | (handler (cdr rxpred-handler))) |
| 709 | (when (and (or (null kind) | ||
| 710 | (eq kind (browse-url--browser-kind | ||
| 711 | handler url))) | ||
| 712 | (if (functionp rx-or-pred) | ||
| 713 | (funcall rx-or-pred url) | ||
| 714 | (string-match-p rx-or-pred url))) | ||
| 715 | (throw 'custom-url-handler handler)))))) | ||
| 663 | 716 | ||
| 664 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 717 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 665 | ;; URL encoding | 718 | ;; URL encoding |
| @@ -864,7 +917,7 @@ If ARGS are omitted, the default is to pass | |||
| 864 | ;; which may not even exist any more. | 917 | ;; which may not even exist any more. |
| 865 | (if (stringp (frame-parameter nil 'display)) | 918 | (if (stringp (frame-parameter nil 'display)) |
| 866 | (setenv "DISPLAY" (frame-parameter nil 'display))) | 919 | (setenv "DISPLAY" (frame-parameter nil 'display))) |
| 867 | (if (functionp nil) | 920 | (if (functionp function) |
| 868 | (apply function url args) | 921 | (apply function url args) |
| 869 | (error "No suitable browser for URL %s" url)))) | 922 | (error "No suitable browser for URL %s" url)))) |
| 870 | 923 | ||
| @@ -883,6 +936,34 @@ Optional prefix argument ARG non-nil inverts the value of the option | |||
| 883 | (error "No URL found")))) | 936 | (error "No URL found")))) |
| 884 | 937 | ||
| 885 | ;;;###autoload | 938 | ;;;###autoload |
| 939 | (defun browse-url-with-browser-kind (kind url &optional arg) | ||
| 940 | "Browse URL with a browser of the given browser KIND. | ||
| 941 | KIND is either `internal' or `external'. | ||
| 942 | |||
| 943 | When called interactively, the default browser kind is the | ||
| 944 | opposite of the browser kind of `browse-url-browser-function'." | ||
| 945 | (interactive | ||
| 946 | (let* ((url-arg (browse-url-interactive-arg "URL: ")) | ||
| 947 | ;; Default to the inverse kind of the default browser. | ||
| 948 | (default (if (eq (browse-url--browser-kind | ||
| 949 | browse-url-browser-function (car url-arg)) | ||
| 950 | 'internal) | ||
| 951 | 'external | ||
| 952 | 'internal)) | ||
| 953 | (k (intern (completing-read | ||
| 954 | (format "Browser kind (default %s): " default) | ||
| 955 | '(internal external) | ||
| 956 | nil t nil nil | ||
| 957 | default)))) | ||
| 958 | (cons k url-arg))) | ||
| 959 | (let ((function (browse-url-select-handler url kind))) | ||
| 960 | (unless function | ||
| 961 | (setq function (if (eq kind 'external) | ||
| 962 | #'browse-url-default-browser | ||
| 963 | #'eww))) | ||
| 964 | (funcall function url arg))) | ||
| 965 | |||
| 966 | ;;;###autoload | ||
| 886 | (defun browse-url-at-mouse (event) | 967 | (defun browse-url-at-mouse (event) |
| 887 | "Ask a WWW browser to load a URL clicked with the mouse. | 968 | "Ask a WWW browser to load a URL clicked with the mouse. |
| 888 | The URL is the one around or before the position of the mouse click | 969 | 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." | |||
| 929 | (url-unhex-string url) | 1010 | (url-unhex-string url) |
| 930 | url))))) | 1011 | url))))) |
| 931 | 1012 | ||
| 1013 | (put 'browse-url-default-windows-browser 'browse-url-browser-kind | ||
| 1014 | 'external) | ||
| 1015 | |||
| 932 | (defun browse-url-default-macosx-browser (url &optional _new-window) | 1016 | (defun browse-url-default-macosx-browser (url &optional _new-window) |
| 933 | "Invoke the macOS system's default Web browser. | 1017 | "Invoke the macOS system's default Web browser. |
| 934 | The optional NEW-WINDOW argument is not used." | 1018 | The optional NEW-WINDOW argument is not used." |
| 935 | (interactive (browse-url-interactive-arg "URL: ")) | 1019 | (interactive (browse-url-interactive-arg "URL: ")) |
| 936 | (start-process (concat "open " url) nil "open" url)) | 1020 | (start-process (concat "open " url) nil "open" url)) |
| 937 | 1021 | ||
| 1022 | (put 'browse-url-default-macosx-browser 'browse-url-browser-kind | ||
| 1023 | 'external) | ||
| 1024 | |||
| 938 | ;; --- Netscape --- | 1025 | ;; --- Netscape --- |
| 939 | 1026 | ||
| 940 | (defun browse-url-process-environment () | 1027 | (defun browse-url-process-environment () |
| @@ -991,6 +1078,10 @@ instead of `browse-url-new-window-flag'." | |||
| 991 | (lambda (&rest _ignore) (error "No usable browser found")))) | 1078 | (lambda (&rest _ignore) (error "No usable browser found")))) |
| 992 | url args)) | 1079 | url args)) |
| 993 | 1080 | ||
| 1081 | (put 'browse-url-default-browser 'browse-url-browser-kind | ||
| 1082 | ;; Well, most probably external if we ignore w3. | ||
| 1083 | 'external) | ||
| 1084 | |||
| 994 | (defun browse-url-can-use-xdg-open () | 1085 | (defun browse-url-can-use-xdg-open () |
| 995 | "Return non-nil if the \"xdg-open\" program can be used. | 1086 | "Return non-nil if the \"xdg-open\" program can be used. |
| 996 | xdg-open is a desktop utility that calls your preferred web browser." | 1087 | xdg-open is a desktop utility that calls your preferred web browser." |
| @@ -1010,6 +1101,8 @@ The optional argument IGNORED is not used." | |||
| 1010 | (interactive (browse-url-interactive-arg "URL: ")) | 1101 | (interactive (browse-url-interactive-arg "URL: ")) |
| 1011 | (call-process "xdg-open" nil 0 nil url)) | 1102 | (call-process "xdg-open" nil 0 nil url)) |
| 1012 | 1103 | ||
| 1104 | (put 'browse-url-xdg-open 'browse-url-browser-kind 'external) | ||
| 1105 | |||
| 1013 | ;;;###autoload | 1106 | ;;;###autoload |
| 1014 | (defun browse-url-netscape (url &optional new-window) | 1107 | (defun browse-url-netscape (url &optional new-window) |
| 1015 | "Ask the Netscape WWW browser to load URL. | 1108 | "Ask the Netscape WWW browser to load URL. |
| @@ -1053,6 +1146,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1053 | `(lambda (process change) | 1146 | `(lambda (process change) |
| 1054 | (browse-url-netscape-sentinel process ,url))))) | 1147 | (browse-url-netscape-sentinel process ,url))))) |
| 1055 | 1148 | ||
| 1149 | (put 'browse-url-netscape 'browse-url-browser-kind 'external) | ||
| 1150 | |||
| 1056 | (defun browse-url-netscape-sentinel (process url) | 1151 | (defun browse-url-netscape-sentinel (process url) |
| 1057 | "Handle a change to the process communicating with Netscape." | 1152 | "Handle a change to the process communicating with Netscape." |
| 1058 | (declare (obsolete nil "25.1")) | 1153 | (declare (obsolete nil "25.1")) |
| @@ -1123,6 +1218,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1123 | `(lambda (process change) | 1218 | `(lambda (process change) |
| 1124 | (browse-url-mozilla-sentinel process ,url))))) | 1219 | (browse-url-mozilla-sentinel process ,url))))) |
| 1125 | 1220 | ||
| 1221 | (put 'browse-url-mozilla 'browse-url-browser-kind 'external) | ||
| 1222 | |||
| 1126 | (defun browse-url-mozilla-sentinel (process url) | 1223 | (defun browse-url-mozilla-sentinel (process url) |
| 1127 | "Handle a change to the process communicating with Mozilla." | 1224 | "Handle a change to the process communicating with Mozilla." |
| 1128 | (or (eq (process-exit-status process) 0) | 1225 | (or (eq (process-exit-status process) 0) |
| @@ -1163,6 +1260,8 @@ instead of `browse-url-new-window-flag'." | |||
| 1163 | '("-new-window"))) | 1260 | '("-new-window"))) |
| 1164 | (list url))))) | 1261 | (list url))))) |
| 1165 | 1262 | ||
| 1263 | (put 'browse-url-firefox 'browse-url-browser-kind 'external) | ||
| 1264 | |||
| 1166 | ;;;###autoload | 1265 | ;;;###autoload |
| 1167 | (defun browse-url-chromium (url &optional _new-window) | 1266 | (defun browse-url-chromium (url &optional _new-window) |
| 1168 | "Ask the Chromium WWW browser to load URL. | 1267 | "Ask the Chromium WWW browser to load URL. |
| @@ -1180,6 +1279,8 @@ The optional argument NEW-WINDOW is not used." | |||
| 1180 | browse-url-chromium-arguments | 1279 | browse-url-chromium-arguments |
| 1181 | (list url))))) | 1280 | (list url))))) |
| 1182 | 1281 | ||
| 1282 | (put 'browse-url-chromium 'browse-url-browser-kind 'external) | ||
| 1283 | |||
| 1183 | (defun browse-url-chrome (url &optional _new-window) | 1284 | (defun browse-url-chrome (url &optional _new-window) |
| 1184 | "Ask the Google Chrome WWW browser to load URL. | 1285 | "Ask the Google Chrome WWW browser to load URL. |
| 1185 | Default to the URL around or before point. The strings in | 1286 | Default to the URL around or before point. The strings in |
| @@ -1196,6 +1297,8 @@ The optional argument NEW-WINDOW is not used." | |||
| 1196 | browse-url-chrome-arguments | 1297 | browse-url-chrome-arguments |
| 1197 | (list url))))) | 1298 | (list url))))) |
| 1198 | 1299 | ||
| 1300 | (put 'browse-url-chrome 'browse-url-browser-kind 'external) | ||
| 1301 | |||
| 1199 | ;;;###autoload | 1302 | ;;;###autoload |
| 1200 | (defun browse-url-galeon (url &optional new-window) | 1303 | (defun browse-url-galeon (url &optional new-window) |
| 1201 | "Ask the Galeon WWW browser to load URL. | 1304 | "Ask the Galeon WWW browser to load URL. |
| @@ -1233,6 +1336,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1233 | `(lambda (process change) | 1336 | `(lambda (process change) |
| 1234 | (browse-url-galeon-sentinel process ,url))))) | 1337 | (browse-url-galeon-sentinel process ,url))))) |
| 1235 | 1338 | ||
| 1339 | (put 'browse-url-galeon 'browse-url-browser-kind 'external) | ||
| 1340 | |||
| 1236 | (defun browse-url-galeon-sentinel (process url) | 1341 | (defun browse-url-galeon-sentinel (process url) |
| 1237 | "Handle a change to the process communicating with Galeon." | 1342 | "Handle a change to the process communicating with Galeon." |
| 1238 | (declare (obsolete nil "25.1")) | 1343 | (declare (obsolete nil "25.1")) |
| @@ -1279,6 +1384,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1279 | `(lambda (process change) | 1384 | `(lambda (process change) |
| 1280 | (browse-url-epiphany-sentinel process ,url))))) | 1385 | (browse-url-epiphany-sentinel process ,url))))) |
| 1281 | 1386 | ||
| 1387 | (put 'browse-url-epiphany 'browse-url-browser-kind 'external) | ||
| 1388 | |||
| 1282 | (defun browse-url-epiphany-sentinel (process url) | 1389 | (defun browse-url-epiphany-sentinel (process url) |
| 1283 | "Handle a change to the process communicating with Epiphany." | 1390 | "Handle a change to the process communicating with Epiphany." |
| 1284 | (or (eq (process-exit-status process) 0) | 1391 | (or (eq (process-exit-status process) 0) |
| @@ -1303,6 +1410,8 @@ currently selected window instead." | |||
| 1303 | file-name-handler-alist))) | 1410 | file-name-handler-alist))) |
| 1304 | (if same-window (find-file url) (find-file-other-window url)))) | 1411 | (if same-window (find-file url) (find-file-other-window url)))) |
| 1305 | 1412 | ||
| 1413 | (put 'browse-url-emacs 'browse-url-browser-kind 'internal) | ||
| 1414 | |||
| 1306 | ;;;###autoload | 1415 | ;;;###autoload |
| 1307 | (defun browse-url-gnome-moz (url &optional new-window) | 1416 | (defun browse-url-gnome-moz (url &optional new-window) |
| 1308 | "Ask Mozilla/Netscape to load URL via the GNOME program `gnome-moz-remote'. | 1417 | "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'." | |||
| 1327 | '("--newwin")) | 1436 | '("--newwin")) |
| 1328 | (list "--raise" url)))) | 1437 | (list "--raise" url)))) |
| 1329 | 1438 | ||
| 1439 | (put 'browse-url-gnome-moz 'browse-url-browser-kind 'external) | ||
| 1440 | |||
| 1330 | ;; --- Mosaic --- | 1441 | ;; --- Mosaic --- |
| 1331 | 1442 | ||
| 1332 | ;;;###autoload | 1443 | ;;;###autoload |
| @@ -1378,6 +1489,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1378 | (append browse-url-mosaic-arguments (list url))) | 1489 | (append browse-url-mosaic-arguments (list url))) |
| 1379 | (message "Starting %s...done" browse-url-mosaic-program)))) | 1490 | (message "Starting %s...done" browse-url-mosaic-program)))) |
| 1380 | 1491 | ||
| 1492 | (put 'browse-url-mosaic 'browse-url-browser-kind 'external) | ||
| 1493 | |||
| 1381 | ;; --- Mosaic using CCI --- | 1494 | ;; --- Mosaic using CCI --- |
| 1382 | 1495 | ||
| 1383 | ;;;###autoload | 1496 | ;;;###autoload |
| @@ -1410,6 +1523,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1410 | (process-send-string "browse-url" "disconnect\r\n") | 1523 | (process-send-string "browse-url" "disconnect\r\n") |
| 1411 | (delete-process "browse-url")) | 1524 | (delete-process "browse-url")) |
| 1412 | 1525 | ||
| 1526 | (put 'browse-url-cci 'browse-url-browser-kind 'external) | ||
| 1527 | |||
| 1413 | ;; --- Conkeror --- | 1528 | ;; --- Conkeror --- |
| 1414 | ;;;###autoload | 1529 | ;;;###autoload |
| 1415 | (defun browse-url-conkeror (url &optional new-window) | 1530 | (defun browse-url-conkeror (url &optional new-window) |
| @@ -1446,6 +1561,9 @@ NEW-WINDOW instead of `browse-url-new-window-flag'." | |||
| 1446 | "window") | 1561 | "window") |
| 1447 | "buffer") | 1562 | "buffer") |
| 1448 | url)))))) | 1563 | url)))))) |
| 1564 | |||
| 1565 | (put 'browse-url-conkeror 'browse-url-browser-kind 'external) | ||
| 1566 | |||
| 1449 | ;; --- W3 --- | 1567 | ;; --- W3 --- |
| 1450 | 1568 | ||
| 1451 | ;; External. | 1569 | ;; External. |
| @@ -1469,6 +1587,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1469 | (w3-fetch-other-window url) | 1587 | (w3-fetch-other-window url) |
| 1470 | (w3-fetch url))) | 1588 | (w3-fetch url))) |
| 1471 | 1589 | ||
| 1590 | (put 'browse-url-w3 'browse-url-browser-kind 'internal) | ||
| 1591 | |||
| 1472 | ;;;###autoload | 1592 | ;;;###autoload |
| 1473 | (defun browse-url-w3-gnudoit (url &optional _new-window) | 1593 | (defun browse-url-w3-gnudoit (url &optional _new-window) |
| 1474 | ;; new-window ignored | 1594 | ;; new-window ignored |
| @@ -1483,6 +1603,8 @@ The `browse-url-gnudoit-program' program is used with options given by | |||
| 1483 | (list (concat "(w3-fetch \"" url "\")") | 1603 | (list (concat "(w3-fetch \"" url "\")") |
| 1484 | "(raise-frame)")))) | 1604 | "(raise-frame)")))) |
| 1485 | 1605 | ||
| 1606 | (put 'browse-url-w3-gnudoit 'browse-url-browser-kind 'internal) | ||
| 1607 | |||
| 1486 | ;; --- Lynx in an xterm --- | 1608 | ;; --- Lynx in an xterm --- |
| 1487 | 1609 | ||
| 1488 | ;;;###autoload | 1610 | ;;;###autoload |
| @@ -1500,6 +1622,8 @@ The optional argument NEW-WINDOW is not used." | |||
| 1500 | ,@browse-url-xterm-args "-e" ,browse-url-text-browser | 1622 | ,@browse-url-xterm-args "-e" ,browse-url-text-browser |
| 1501 | ,url))) | 1623 | ,url))) |
| 1502 | 1624 | ||
| 1625 | (put 'browse-url-text-xterm 'browse-url-browser-kind 'external) | ||
| 1626 | |||
| 1503 | ;; --- Lynx in an Emacs "term" window --- | 1627 | ;; --- Lynx in an Emacs "term" window --- |
| 1504 | 1628 | ||
| 1505 | (declare-function term-char-mode "term" ()) | 1629 | (declare-function term-char-mode "term" ()) |
| @@ -1574,6 +1698,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1574 | url | 1698 | url |
| 1575 | "\r"))))) | 1699 | "\r"))))) |
| 1576 | 1700 | ||
| 1701 | (put 'browse-url-text-emacs 'browse-url-browser-kind 'internal) | ||
| 1702 | |||
| 1577 | ;; --- mailto --- | 1703 | ;; --- mailto --- |
| 1578 | 1704 | ||
| 1579 | (autoload 'rfc2368-parse-mailto-url "rfc2368") | 1705 | (autoload 'rfc2368-parse-mailto-url "rfc2368") |
| @@ -1621,6 +1747,8 @@ used instead of `browse-url-new-window-flag'." | |||
| 1621 | (unless (bolp) | 1747 | (unless (bolp) |
| 1622 | (insert "\n")))))))) | 1748 | (insert "\n")))))))) |
| 1623 | 1749 | ||
| 1750 | (put 'browse-url-mail 'browse-url-browser-kind 'internal) | ||
| 1751 | |||
| 1624 | ;; --- man --- | 1752 | ;; --- man --- |
| 1625 | 1753 | ||
| 1626 | (defvar manual-program) | 1754 | (defvar manual-program) |
| @@ -1632,7 +1760,9 @@ used instead of `browse-url-new-window-flag'." | |||
| 1632 | (setq url (replace-regexp-in-string "\\`man:" "" url)) | 1760 | (setq url (replace-regexp-in-string "\\`man:" "" url)) |
| 1633 | (cond | 1761 | (cond |
| 1634 | ((executable-find manual-program) (man url)) | 1762 | ((executable-find manual-program) (man url)) |
| 1635 | (t (woman (replace-regexp-in-string "([[:alnum:]]+)" "" url))))) | 1763 | (t (woman (replace-regexp-in-string "([[:alnum:]]+)" "" url))))) |
| 1764 | |||
| 1765 | (put 'browse-url-man 'browse-url-browser-kind 'internal) | ||
| 1636 | 1766 | ||
| 1637 | ;; --- Random browser --- | 1767 | ;; --- Random browser --- |
| 1638 | 1768 | ||
| @@ -1651,6 +1781,8 @@ don't offer a form of remote control." | |||
| 1651 | 0 nil | 1781 | 0 nil |
| 1652 | (append browse-url-generic-args (list url)))) | 1782 | (append browse-url-generic-args (list url)))) |
| 1653 | 1783 | ||
| 1784 | (put 'browse-url-generic 'browse-url-browser-kind 'external) | ||
| 1785 | |||
| 1654 | ;;;###autoload | 1786 | ;;;###autoload |
| 1655 | (defun browse-url-kde (url &optional _new-window) | 1787 | (defun browse-url-kde (url &optional _new-window) |
| 1656 | "Ask the KDE WWW browser to load URL. | 1788 | "Ask the KDE WWW browser to load URL. |
| @@ -1661,6 +1793,8 @@ The optional argument NEW-WINDOW is not used." | |||
| 1661 | (apply #'start-process (concat "KDE " url) nil browse-url-kde-program | 1793 | (apply #'start-process (concat "KDE " url) nil browse-url-kde-program |
| 1662 | (append browse-url-kde-args (list url)))) | 1794 | (append browse-url-kde-args (list url)))) |
| 1663 | 1795 | ||
| 1796 | (put 'browse-url-kde 'browse-url-browser-kind 'external) | ||
| 1797 | |||
| 1664 | (defun browse-url-elinks-new-window (url) | 1798 | (defun browse-url-elinks-new-window (url) |
| 1665 | "Ask the Elinks WWW browser to load URL in a new window." | 1799 | "Ask the Elinks WWW browser to load URL in a new window." |
| 1666 | (let ((process-environment (browse-url-process-environment))) | 1800 | (let ((process-environment (browse-url-process-environment))) |
| @@ -1670,6 +1804,8 @@ The optional argument NEW-WINDOW is not used." | |||
| 1670 | browse-url-elinks-wrapper | 1804 | browse-url-elinks-wrapper |
| 1671 | (list "elinks" url))))) | 1805 | (list "elinks" url))))) |
| 1672 | 1806 | ||
| 1807 | (put 'browse-url-elinks-new-window 'browse-url-browser-kind 'external) | ||
| 1808 | |||
| 1673 | ;;;###autoload | 1809 | ;;;###autoload |
| 1674 | (defun browse-url-elinks (url &optional new-window) | 1810 | (defun browse-url-elinks (url &optional new-window) |
| 1675 | "Ask the Elinks WWW browser to load URL. | 1811 | "Ask the Elinks WWW browser to load URL. |
| @@ -1691,6 +1827,8 @@ from `browse-url-elinks-wrapper'." | |||
| 1691 | `(lambda (process change) | 1827 | `(lambda (process change) |
| 1692 | (browse-url-elinks-sentinel process ,url)))))) | 1828 | (browse-url-elinks-sentinel process ,url)))))) |
| 1693 | 1829 | ||
| 1830 | (put 'browse-url-elinks 'browse-url-browser-kind 'external) | ||
| 1831 | |||
| 1694 | (defun browse-url-elinks-sentinel (process url) | 1832 | (defun browse-url-elinks-sentinel (process url) |
| 1695 | "Determines if Elinks is running or a new one has to be started." | 1833 | "Determines if Elinks is running or a new one has to be started." |
| 1696 | ;; Try to determine if an instance is running or if we have to | 1834 | ;; 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." | |||
| 310 | (url-retrieve url 'eww-render | 310 | (url-retrieve url 'eww-render |
| 311 | (list url nil (current-buffer))))) | 311 | (list url nil (current-buffer))))) |
| 312 | 312 | ||
| 313 | (put 'eww 'browse-url-browser-kind 'internal) | ||
| 314 | |||
| 313 | (defun eww--dwim-expand-url (url) | 315 | (defun eww--dwim-expand-url (url) |
| 314 | (setq url (string-trim url)) | 316 | (setq url (string-trim url)) |
| 315 | (cond ((string-match-p "\\`file:/" url)) | 317 | (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." | |||
| 790 | (or (c-lineup-assignments langelem) | 790 | (or (c-lineup-assignments langelem) |
| 791 | c-basic-offset)) | 791 | c-basic-offset)) |
| 792 | 792 | ||
| 793 | (defun c-lineup-ternary-bodies (langelem) | ||
| 794 | "Line up true and false branches of a ternary operator (i.e. ‘?:’). | ||
| 795 | More precisely, if the line starts with a colon which is a part of | ||
| 796 | a said operator it with corresponding question mark; otherwise return | ||
| 797 | nil. For example: | ||
| 798 | |||
| 799 | return arg % 2 == 0 ? arg / 2 | ||
| 800 | : (3 * arg + 1); <- c-lineup-ternary-bodies | ||
| 801 | |||
| 802 | Works with: arglist-cont, arglist-cont-nonempty and statement-cont. | ||
| 803 | " | ||
| 804 | (save-excursion | ||
| 805 | (back-to-indentation) | ||
| 806 | (when (and (eq ?: (char-after)) | ||
| 807 | (not (eq ?: (char-after (1+ (point)))))) | ||
| 808 | (let ((limit (c-langelem-pos langelem)) (depth 1)) | ||
| 809 | (catch 'done | ||
| 810 | (while (c-syntactic-skip-backward "^?:" limit t) | ||
| 811 | (goto-char (1- (point))) | ||
| 812 | (cond ((eq (char-after) ??) | ||
| 813 | ;; If we’ve found a question mark, decrease depth. If we’re | ||
| 814 | ;; reached zero, we’ve found the one we were looking for. | ||
| 815 | (when (zerop (setq depth (1- depth))) | ||
| 816 | (throw 'done (vector (current-column))))) | ||
| 817 | ((or (eq ?: (char-before)) (eq ?? (char-before))) | ||
| 818 | ;; Step over ‘::’ and ‘?:’ operators. We don’t have to | ||
| 819 | ;; handle ‘?:’ here but doing so saves an iteration. | ||
| 820 | (if (eq (point) limit) | ||
| 821 | (throw 'done nil) | ||
| 822 | (goto-char (1- (point))))) | ||
| 823 | ((setq depth (1+ depth)))))))))) ; Otherwise increase depth. | ||
| 824 | |||
| 793 | (defun c-lineup-cascaded-calls (langelem) | 825 | (defun c-lineup-cascaded-calls (langelem) |
| 794 | "Line up \"cascaded calls\" under each other. | 826 | "Line up \"cascaded calls\" under each other. |
| 795 | If the line begins with \"->\" or \".\" and the preceding line ends | 827 | 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: | |||
| 2541 | 2541 | ||
| 2542 | (defconst c-or-c++-mode--regexp | 2542 | (defconst c-or-c++-mode--regexp |
| 2543 | (eval-when-compile | 2543 | (eval-when-compile |
| 2544 | (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")) | 2544 | (let ((id "[a-zA-Z_][a-zA-Z0-9_]*") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*") |
| 2545 | (headers '("string" "string_view" "iostream" "map" "unordered_map" | ||
| 2546 | "set" "unordered_set" "vector" "tuple"))) | ||
| 2545 | (concat "^" ws-maybe "\\(?:" | 2547 | (concat "^" ws-maybe "\\(?:" |
| 2546 | "using" ws "\\(?:namespace" ws "std;\\|std::\\)" | 2548 | "using" ws "\\(?:namespace" ws |
| 2547 | "\\|" "namespace" "\\(:?" ws id "\\)?" ws-maybe "{" | 2549 | "\\|" id "::" |
| 2548 | "\\|" "class" ws id ws-maybe "[:{\n]" | 2550 | "\\|" id ws-maybe "=\\)" |
| 2549 | "\\|" "template" ws-maybe "<.*>" | 2551 | "\\|" "\\(?:inline" ws "\\)?namespace" |
| 2550 | "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>" | 2552 | "\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{" |
| 2553 | "\\|" "class" ws id | ||
| 2554 | "\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]" | ||
| 2555 | "\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]" | ||
| 2556 | "\\|" ws-maybe ":\\)" | ||
| 2557 | "\\|" "template" ws-maybe "<.*?>" | ||
| 2558 | "\\|" "#include" ws-maybe "<" (regexp-opt headers) ">" | ||
| 2551 | "\\)"))) | 2559 | "\\)"))) |
| 2552 | "A regexp applied to C header files to check if they are really C++.") | 2560 | "A regexp applied to C header files to check if they are really C++.") |
| 2553 | 2561 | ||
| @@ -2563,6 +2571,7 @@ should be used. | |||
| 2563 | This function attempts to use file contents to determine whether | 2571 | This function attempts to use file contents to determine whether |
| 2564 | the code is C or C++ and based on that chooses whether to enable | 2572 | the code is C or C++ and based on that chooses whether to enable |
| 2565 | `c-mode' or `c++-mode'." | 2573 | `c-mode' or `c++-mode'." |
| 2574 | (interactive) | ||
| 2566 | (if (save-excursion | 2575 | (if (save-excursion |
| 2567 | (save-restriction | 2576 | (save-restriction |
| 2568 | (save-match-data | 2577 | (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). | |||
| 766 | If OBJECT is a string, POSITION is a 0-based index into it. | 766 | If OBJECT is a string, POSITION is a 0-based index into it. |
| 767 | 767 | ||
| 768 | In a string, scan runs to the end of the string, unless LIMIT is non-nil. | 768 | In a string, scan runs to the end of the string, unless LIMIT is non-nil. |
| 769 | In a buffer, if LIMIT is nil or omitted, it runs to (point-max), and the | 769 | In a buffer, scan runs to end of buffer, unless LIMIT is non-nil. |
| 770 | value cannot exceed that. | ||
| 771 | If the optional fourth argument LIMIT is non-nil, don't search | 770 | If the optional fourth argument LIMIT is non-nil, don't search |
| 772 | past position LIMIT; return LIMIT if nothing is found before LIMIT. | 771 | past position LIMIT; return LIMIT if nothing is found before LIMIT. |
| 772 | However, if OBJECT is a buffer and LIMIT is beyond the end of the | ||
| 773 | buffer, this function returns `point-max', not LIMIT. | ||
| 773 | 774 | ||
| 774 | The property values are compared with `eq'. | 775 | The property values are compared with `eq'. */) |
| 775 | If the property is constant all the way to the end of OBJECT, return the | ||
| 776 | last valid position in OBJECT. */) | ||
| 777 | (Lisp_Object position, Lisp_Object prop, Lisp_Object object, Lisp_Object limit) | 776 | (Lisp_Object position, Lisp_Object prop, Lisp_Object object, Lisp_Object limit) |
| 778 | { | 777 | { |
| 779 | if (STRINGP (object)) | 778 | if (STRINGP (object)) |
| @@ -832,6 +831,9 @@ last valid position in OBJECT. */) | |||
| 832 | value = Fget_char_property (position, prop, object); | 831 | value = Fget_char_property (position, prop, object); |
| 833 | if (!EQ (value, initial_value)) | 832 | if (!EQ (value, initial_value)) |
| 834 | break; | 833 | break; |
| 834 | |||
| 835 | if (XFIXNAT (position) >= ZV) | ||
| 836 | break; | ||
| 835 | } | 837 | } |
| 836 | 838 | ||
| 837 | position = unbind_to (count, position); | 839 | 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 @@ | |||
| 39 | collect (list c b a)) | 39 | collect (list c b a)) |
| 40 | '((4.0 2 1) (8.3 6 5) (10.4 9 8))))) | 40 | '((4.0 2 1) (8.3 6 5) (10.4 9 8))))) |
| 41 | 41 | ||
| 42 | (ert-deftest cl-macs-loop-and-arrays () | ||
| 43 | "Bug#40727" | ||
| 44 | (should (equal (cl-loop for y = (- (or x 0)) and x across [1 2] | ||
| 45 | collect (cons x y)) | ||
| 46 | '((1 . 0) (2 . -1)))) | ||
| 47 | (should (equal (cl-loop for x across [1 2] and y = (- (or x 0)) | ||
| 48 | collect (cons x y)) | ||
| 49 | '((1 . 0) (2 . -1))))) | ||
| 50 | |||
| 42 | (ert-deftest cl-macs-loop-destructure () | 51 | (ert-deftest cl-macs-loop-destructure () |
| 43 | (should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4)) | 52 | (should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4)) |
| 44 | collect (list c b a)) | 53 | 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 @@ | |||
| 40 | (insert content) | 40 | (insert content) |
| 41 | (setq mode nil) | 41 | (setq mode nil) |
| 42 | (c-or-c++-mode) | 42 | (c-or-c++-mode) |
| 43 | (unless(eq expected mode) | 43 | (unless (eq expected mode) |
| 44 | (ert-fail | 44 | (ert-fail |
| 45 | (format "expected %s but got %s when testing '%s'" | 45 | (format "expected %s but got %s when testing '%s'" |
| 46 | expected mode content))))) | 46 | expected mode content))))) |
| @@ -53,11 +53,18 @@ | |||
| 53 | (funcall do-test (concat " * " content) 'c-mode)) | 53 | (funcall do-test (concat " * " content) 'c-mode)) |
| 54 | '("using \t namespace \t std;" | 54 | '("using \t namespace \t std;" |
| 55 | "using \t std::string;" | 55 | "using \t std::string;" |
| 56 | "using Foo = Bar;" | ||
| 56 | "namespace \t {" | 57 | "namespace \t {" |
| 57 | "namespace \t foo \t {" | 58 | "namespace \t foo \t {" |
| 58 | "class \t Blah_42 \t {" | 59 | "namespace \t foo::bar \t {" |
| 60 | "inline namespace \t foo \t {" | ||
| 61 | "inline namespace \t foo::bar \t {" | ||
| 59 | "class \t Blah_42 \t \n" | 62 | "class \t Blah_42 \t \n" |
| 63 | "class \t Blah_42;" | ||
| 64 | "class \t Blah_42 \t final {" | ||
| 65 | "struct \t Blah_42 \t final {" | ||
| 60 | "class \t _42_Blah:public Foo {" | 66 | "class \t _42_Blah:public Foo {" |
| 67 | "struct \t _42_Blah:public Foo {" | ||
| 61 | "template \t < class T >" | 68 | "template \t < class T >" |
| 62 | "template< class T >" | 69 | "template< class T >" |
| 63 | "#include <string>" | 70 | "#include <string>" |
| @@ -67,6 +74,7 @@ | |||
| 67 | (mapc (lambda (content) (funcall do-test content 'c-mode)) | 74 | (mapc (lambda (content) (funcall do-test content 'c-mode)) |
| 68 | '("struct \t Blah_42 \t {" | 75 | '("struct \t Blah_42 \t {" |
| 69 | "struct template {" | 76 | "struct template {" |
| 77 | "struct Blah;" | ||
| 70 | "#include <string.h>"))))) | 78 | "#include <string.h>"))))) |
| 71 | 79 | ||
| 72 | (ert-deftest c-mode-macro-comment () | 80 | (ert-deftest c-mode-macro-comment () |
| @@ -78,4 +86,25 @@ | |||
| 78 | (insert macro-string) | 86 | (insert macro-string) |
| 79 | (c-mode)))) | 87 | (c-mode)))) |
| 80 | 88 | ||
| 89 | (ert-deftest c-lineup-ternary-bodies () | ||
| 90 | "Test for c-lineup-ternary-bodies function" | ||
| 91 | (with-temp-buffer | ||
| 92 | (c-mode) | ||
| 93 | (let* ((common-prefix "int value = condition ") | ||
| 94 | (expected-column (length common-prefix))) | ||
| 95 | (dolist (test '(("? a : \n b" . nil) | ||
| 96 | ("? a \n ::b" . nil) | ||
| 97 | ("a \n : b" . nil) | ||
| 98 | ("? a \n : b" . t) | ||
| 99 | ("? ::a \n : b" . t) | ||
| 100 | ("? (p ? q : r) \n : b" . t) | ||
| 101 | ("? p ?: q \n : b" . t) | ||
| 102 | ("? p ? : q \n : b" . t) | ||
| 103 | ("? p ? q : r \n : b" . t))) | ||
| 104 | (delete-region (point-min) (point-max)) | ||
| 105 | (insert common-prefix (car test)) | ||
| 106 | (should (equal | ||
| 107 | (and (cdr test) (vector expected-column)) | ||
| 108 | (c-lineup-ternary-bodies '(statement-cont . 1)))))))) | ||
| 109 | |||
| 81 | ;;; cc-mode-tests.el ends here | 110 | ;;; cc-mode-tests.el ends here |