commit 604a985a1a1066679895d2ec80c7b351ecbf8ff4 (HEAD, refs/remotes/origin/master) Author: Wolfgang Scherer Date: Mon Oct 7 06:58:59 2019 +0200 Set correct svn:ignore property for relative filenames * lisp/vc/vc-svn.el: (vc-svn-ignore) Use svn:ignore property of immediate parent directory for wildcard specification (bug#37216). diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el index 88a280d10f..942dbd5fa5 100644 --- a/lisp/vc/vc-svn.el +++ b/lisp/vc/vc-svn.el @@ -353,15 +353,18 @@ to the SVN command." (defun vc-svn-ignore (file &optional directory remove) "Ignore FILE under Subversion. -FILE is a file wildcard, relative to the root directory of DIRECTORY." - (let* ((ignores (vc-svn-ignore-completion-table directory)) - (file (file-relative-name file directory)) +FILE is a wildcard specification, either relative to +DIRECTORY or absolute." + (let* ((path (directory-file-name (expand-file-name file directory))) + (directory (file-name-directory path)) + (file (file-name-nondirectory path)) + (ignores (vc-svn-ignore-completion-table directory)) (ignores (if remove (delete file ignores) (push file ignores)))) (vc-svn-command nil 0 nil nil "propset" "svn:ignore" (mapconcat #'identity ignores "\n") - (expand-file-name directory)))) + directory))) (defun vc-svn-ignore-completion-table (directory) "Return the list of ignored files in DIRECTORY." commit f2346b5788338dbceabc30233234e4a3308f32c2 Author: Paul Eggert Date: Sun Oct 6 23:08:34 2019 -0700 Fix port of file-acl errno checking to non-GNU I had misinterpreted the private email from Ashish Shukla. * src/fileio.c (Ffile_acl): Fix typo in previous change by negating the call to acl_errno_valid. diff --git a/src/fileio.c b/src/fileio.c index 781a71bcf3..f1860e8a93 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3248,7 +3248,7 @@ Return nil if file does not exist. */) acl_t acl = acl_get_file (SSDATA (ENCODE_FILE (absname)), ACL_TYPE_EXTENDED); if (acl == NULL) { - if (errno == ENOENT || errno == ENOTDIR || acl_errno_valid (errno)) + if (errno == ENOENT || errno == ENOTDIR || !acl_errno_valid (errno)) return Qnil; report_file_error ("Getting ACLs", absname); } commit 78ac0551e77110cfdc9b01fadec19d862b5957c4 Author: Lars Ingebrigtsen Date: Mon Oct 7 06:53:17 2019 +0200 Fix the colours on Motif horizontal scroll bars * src/xterm.c (x_create_horizontal_toolkit_scroll_bar): Use the same foreground/background colours as the vertical scroll bar (bug#37359). diff --git a/src/xterm.c b/src/xterm.c index 5baa29a846..b49c9d6893 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6303,17 +6303,19 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) XtSetArg (av[ac], XmNincrement, 1); ++ac; XtSetArg (av[ac], XmNpageIncrement, 1); ++ac; + /* Note: "background" is the thumb color, and "trough" is the color behind + everything. */ pixel = f->output_data.x->scroll_bar_foreground_pixel; if (pixel != -1) { - XtSetArg (av[ac], XmNforeground, pixel); + XtSetArg (av[ac], XmNbackground, pixel); ++ac; } pixel = f->output_data.x->scroll_bar_background_pixel; if (pixel != -1) { - XtSetArg (av[ac], XmNbackground, pixel); + XtSetArg (av[ac], XmNtroughColor, pixel); ++ac; } commit c11910a8beb2a953ddcb420bfeb681724efdba4b Author: Lars Ingebrigtsen Date: Mon Oct 7 06:32:36 2019 +0200 cl-reduce doc fix * lisp/emacs-lisp/cl-seq.el (cl-reduce): Clarify what happens when SEQ is the empty list (bug#37400). diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el index a15c994bc1..520d450481 100644 --- a/lisp/emacs-lisp/cl-seq.el +++ b/lisp/emacs-lisp/cl-seq.el @@ -133,6 +133,11 @@ If :INITIAL-VALUE is specified, it is added to the front of SEQ. If SEQ is empty, return :INITIAL-VALUE and FUNCTION is not called. +If SEQ is empty and no :INITIAL-VALUE is given, then the function +is called with zero arguments, and reduce returns whatever +function does. This is the only case where the function is called +with other than two arguments. + \n(fn FUNCTION SEQ [KEYWORD VALUE]...)" (cl--parsing-keywords (:from-end (:start 0) :end :initial-value :key) () (or (listp cl-seq) (setq cl-seq (append cl-seq nil))) commit cfbd1255c21ed28df8facc9b0f9ff257d70505c4 Author: Hong Xu Date: Mon Oct 7 06:13:27 2019 +0200 tags-complete-tags-table-file doc string fix * lisp/progmodes/etags.el (tags-complete-tags-table-file): Doc string fix (bug#37538). diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 5edced5080..c40422dbc5 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -1843,13 +1843,18 @@ For non-interactive use, superceded by `fileloop-initialize-replace'." delimited) (fileloop-continue)) -(defun tags-complete-tags-table-file (string predicate what) ; Doc string? +(defun tags-complete-tags-table-file (string predicate what) + "Complete STRING from file names in the current tags table. +The meaning of the arguments are the same as the function form of +COLLECTION as explained in Info node `(elisp) Programmed +Completion', except that if WHAT does not equal t, it is treated +as if it were nil." (save-excursion ;; If we need to ask for the tag table, allow that. (let ((enable-recursive-minibuffers t)) (visit-tags-table-buffer)) (if (eq what t) - (all-completions string (tags-table-files) predicate) + (all-completions string (tags-table-files) predicate) (try-completion string (tags-table-files) predicate)))) (defun tags--get-current-buffer-name-in-tags-file () commit 273dd6542d96e09f90308187bac341ebaa0c770d Author: Hong Xu Date: Mon Oct 7 06:03:21 2019 +0200 Default FILE to the current buffer for list-tags * doc/emacs/maintaining.texi (List Identifiers): Update `list-tags' doc (bug#37611). * lisp/progmodes/etags.el (list-tags) (tags--get-current-buffer-name-in-tags-file): Default FILE to the current buffer for list-tags. diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 9a9957069f..519667dfbe 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2124,7 +2124,9 @@ the selected tags table, and displays a list of tags defined in that file. Do not include a directory as part of the file name unless the file name recorded in the tags table includes a directory. This command works only with the etags backend, and requires a tags table -for the project to be available. @xref{Tags Tables}. +for the project to be available. @xref{Tags Tables}. If used +interactively, the default tag is file name of the current buffer if +used interactively. @c Sadly, the new-and-improved Xref feature doesn't provide anything @c close to the described below features of the now-obsoleted diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index a035161000..5edced5080 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -1852,15 +1852,28 @@ For non-interactive use, superceded by `fileloop-initialize-replace'." (all-completions string (tags-table-files) predicate) (try-completion string (tags-table-files) predicate)))) +(defun tags--get-current-buffer-name-in-tags-file () + "Get the file name that the current buffer corresponds in the tags file." + (let ((tag-dir + (save-excursion + (visit-tags-table-buffer) + (file-name-directory (buffer-file-name))))) + (file-relative-name (buffer-file-name) tag-dir))) + ;;;###autoload (defun list-tags (file &optional _next-match) "Display list of tags in file FILE. -This searches only the first table in the list, and no included tables. -FILE should be as it appeared in the `etags' command, usually without a -directory specification." - (interactive (list (completing-read "List tags in file: " - 'tags-complete-tags-table-file - nil t nil))) +This searches only the first table in the list, and no included +tables. FILE should be as it appeared in the `etags' command, +usually without a directory specification. If called +interactively, FILE defaults to the file name of the current +buffer." + (interactive (list (completing-read + "List tags in file: " + 'tags-complete-tags-table-file + nil t + ;; Default FILE to the current buffer. + (tags--get-current-buffer-name-in-tags-file)))) (with-output-to-temp-buffer "*Tags List*" (princ (substitute-command-keys "Tags in file `")) (tags-with-face 'highlight (princ file)) commit a5a967b43dd2810635d7a06ea70510c4a8e5c10f Author: Lars Ingebrigtsen Date: Mon Oct 7 05:00:16 2019 +0200 Make mailcap-prefer-mailcap-viewers work as documented * lisp/emacs-lisp/seq.el (seq-find): Autoload. * lisp/net/mailcap.el (mailcap-parse-mailcaps): Note where all the entries come from so that we can later distinguish between user values and system values (bug#36771). (mailcap-parse-mailcap): Take a source parameter. (mailcap-possible-viewers): No need to sort wildcards/exact matches; these are later sorted anyway. (mailcap-add-mailcap-entry): Remove `after' parameter. (mailcap-mime-info): Make mailcap-prefer-mailcap-viewers work as documented. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 3413cd1513..f001dceece 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -334,6 +334,7 @@ If so, return the first non-nil value returned by PRED." (throw 'seq--break result)))) nil)) +;;;###autoload (cl-defgeneric seq-find (pred sequence &optional default) "Return the first element for which (PRED element) is non-nil in SEQUENCE. If no element is found, return DEFAULT. diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index eb4312ef3b..600ed86f27 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el @@ -421,38 +421,41 @@ MAILCAPS if set; otherwise (on Unix) use the path from RFC 1524, plus (interactive (list nil t)) (when (or (not mailcap-parsed-p) force) + ;; Clear out all old data. + (setq mailcap-mime-data nil) (cond (path nil) - ((getenv "MAILCAPS") (setq path (getenv "MAILCAPS"))) + ((getenv "MAILCAPS") + (setq path (getenv "MAILCAPS"))) ((memq system-type mailcap-poor-system-types) - (setq path '("~/.mailcap" "~/mail.cap" "~/etc/mail.cap"))) - (t (setq path - ;; This is per RFC 1524, specifically with /usr before - ;; /usr/local. - '("~/.mailcap" - ("/etc/mailcap" 'after) - ("/usr/etc/mailcap" 'after) - ("/usr/local/etc/mailcap" 'after))))) - ;; We read the entries from ~/.mailcap before the built-in values, - ;; but place the rest of then afterwards as fallback values. + (setq path '(("~/.mailcap" user) + ("~/mail.cap" user) + ("~/etc/mail.cap" user)))) + (t + (setq path + ;; This is per RFC 1524, specifically with /usr before + ;; /usr/local. + '(("~/.mailcap" user) + ("/etc/mailcap" system) + ("/usr/etc/mailcap" system) + ("/usr/local/etc/mailcap" system))))) + ;; The ~/.mailcap entries will end up first in the resulting data. (dolist (spec (reverse - (if (stringp path) - (split-string path path-separator t) - path))) - (let ((afterp (and (consp spec) - (cadr spec))) + (if (stringp path) + (split-string path path-separator t) + path))) + (let ((source (and (consp spec) (cadr spec))) (file-name (if (stringp spec) spec (car spec)))) (when (and (file-readable-p file-name) (file-regular-p file-name)) - (mailcap-parse-mailcap file-name afterp)))) + (mailcap-parse-mailcap file-name source)))) (setq mailcap-parsed-p t))) -(defun mailcap-parse-mailcap (fname &optional after) +(defun mailcap-parse-mailcap (fname &optional source) "Parse out the mailcap file specified by FNAME. -If AFTER, place the entries from the file after the ones that are -already there." +If SOURCE, mark the entry with this as the source." (let (major ; The major mime type (image/audio/etc) minor ; The minor mime type (gif, basic, etc) save-pos ; Misc saved positions used in parsing @@ -522,7 +525,10 @@ already there." "*" minor)))) (mailcap-parse-mailcap-extras save-pos (point)))) (mailcap-mailcap-entry-passes-test info) - (mailcap-add-mailcap-entry major minor info after)) + ;; Record where the data came from. + (when source + (setq info (nconc info (list (cons 'source source))))) + (mailcap-add-mailcap-entry major minor info)) (beginning-of-line))))) (defun mailcap-parse-mailcap-extras (st nd) @@ -607,15 +613,13 @@ the test clause will be unchanged." (defun mailcap-possible-viewers (major minor) "Return a list of possible viewers from MAJOR for minor type MINOR." - (let ((exact '()) - (wildcard '())) + (let ((result nil)) (pcase-dolist (`(,type . ,attrs) major) - (cond - ((equal type minor) - (push attrs exact)) - ((and minor (string-match (concat "^" type "$") minor)) - (push attrs wildcard)))) - (nconc exact wildcard))) + (when (or (equal type minor) + (and minor + (string-match (concat "^" type "$") minor))) + (push attrs result))) + (nreverse result))) (defun mailcap-unescape-mime-test (test type-info) (let (save-pos save-chr subst) @@ -705,7 +709,7 @@ to supply to the test." (push (list otest result) mailcap-viewer-test-cache) result)))) -(defun mailcap-add-mailcap-entry (major minor info &optional after) +(defun mailcap-add-mailcap-entry (major minor info) (let ((old-major (assoc major mailcap-mime-data))) (if (null old-major) ; New major area (push (cons major (list (cons minor info))) mailcap-mime-data) @@ -714,22 +718,16 @@ to supply to the test." ((or (null cur-minor) ; New minor area, or (assq 'test info)) ; Has a test, insert at beginning (setcdr old-major - (if after ; Or after, if specified. - (nconc (cdr old-major) - (list (cons minor info))) - (cons (cons minor info) (cdr old-major))))) + (cons (cons minor info) (cdr old-major)))) ((and (not (assq 'test info)) ; No test info, replace completely (not (assq 'test cur-minor)) (equal (assq 'viewer info) ; Keep alternative viewer (assq 'viewer cur-minor))) - (unless after - (setcdr cur-minor info))) + (setcdr cur-minor info)) (t (setcdr old-major - (if after - (nconc (cdr old-major) (list (cons minor info))) - (setcdr old-major - (cons (cons minor info) (cdr old-major))))))))))) + (setcdr old-major + (cons (cons minor info) (cdr old-major)))))))))) (defun mailcap-add (type viewer &optional test) "Add VIEWER as a handler for TYPE. @@ -812,7 +810,7 @@ If NO-DECODE is non-nil, don't decode STRING." (setq passed (list viewer)) ;; None found, so heuristically select some applicable viewer ;; from `mailcap-mime-data'. - (mailcap-parse-mailcaps) + (mailcap-parse-mailcaps nil t) (setq major (split-string (car ctl) "/")) (setq minor (cadr major) major (car major)) @@ -824,11 +822,16 @@ If NO-DECODE is non-nil, don't decode STRING." (dolist (entry viewers) (when (mailcap-viewer-passes-test entry info) (push entry passed))) - ;; The data is in "logical" order; entries from ~/.mailcap - ;; are first, so we don't need to do any sorting if the - ;; user wants ~/.mailcap to be preferred. - (unless mailcap-prefer-mailcap-viewers - (setq passed (sort passed 'mailcap-viewer-lessp))) + (setq passed (sort (nreverse passed) 'mailcap-viewer-lessp)) + ;; When we want to prefer entries from the user's + ;; ~/.mailcap file, then we filter out the system entries + ;; and see whether we have anything left. + (when mailcap-prefer-mailcap-viewers + (when-let ((user-entry + (seq-find (lambda (elem) + (eq (cdr (assq 'source elem)) 'user)) + passed))) + (setq passed (list user-entry)))) (setq viewer (car passed)))) (when (and (stringp (cdr (assq 'viewer viewer))) passed) commit 7d46b934ab60fdd58c46391636663ff85594c40b Author: Mauro Aranda Date: Mon Oct 7 03:59:43 2019 +0200 Only complete words inside of the string widget * lisp/wid-edit.el ('string widget): Peek the word that ispell-complete-word will try to complete, and only offer completions when the word is inside of the field (bug#11046). diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index a5999c0de8..4d1a609809 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -58,6 +58,10 @@ (require 'cl-lib) (eval-when-compile (require 'subr-x)) ; when-let +;; The `string' widget completion uses this. +(declare-function ispell-get-word "ispell" + (following &optional extra-otherchars)) + ;;; Compatibility. (defun widget-event-point (event) @@ -3074,7 +3078,12 @@ as the value." "A string." :tag "String" :format "%{%t%}: %v" - :complete-function 'ispell-complete-word + :complete (lambda (widget) + (require 'ispell) + (let ((start (save-excursion (nth 1 (ispell-get-word nil))))) + (if (< start (widget-field-start widget)) + (message "No word to complete inside field") + (ispell-complete-word)))) :prompt-history 'widget-string-prompt-value-history) (define-widget 'regexp 'string commit 821c96c1b0421e8cf6ae0133402918e4ebc1466f Author: Basil L. Contovounesios Date: Mon Oct 7 03:02:07 2019 +0100 ; * doc/misc/eww.texi (Advanced): Fix recent typo. diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi index d0a4c9a790..168a9bfa74 100644 --- a/doc/misc/eww.texi +++ b/doc/misc/eww.texi @@ -227,9 +227,9 @@ package. You can list existing cookies with @kbd{C} @vindex shr-cookie-policy Many @acronym{HTML} pages have images embedded in them, and EWW will -download most these by default. When fetching images, cookies can be -sent and received, and these can be used to track users. To control -when to send cookies when retrieving these images, the +download most of these by default. When fetching images, cookies can +be sent and received, and these can be used to track users. To +control when to send cookies when retrieving these images, the @code{shr-cookie-policy} variable can be used. The default value, @code{same-origin}, means that EWW will only send cookies when fetching images that originate from the same source as the commit 22af213f804d1405a5266a9d0e0e51a69daabef7 Author: Mauro Aranda Date: Mon Oct 7 03:36:09 2019 +0200 Fix message when no completions available for editable field * lisp/wid-edit.el (widget-completions-at-point): Detect here if point is not in an editable field. (widget-complete): And here say there are no completions available (bug#11562). diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 916d41af25..a5999c0de8 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -1166,7 +1166,7 @@ When not inside a field, signal an error." (plist-get completion-extra-properties :predicate)))) (t - (error "Not in an editable field"))))) + (error "No completions available for this field"))))) ;; We may want to use widget completion in buffers where the major mode ;; hasn't added widget-completions-at-point to completion-at-point-functions, ;; so it's not really obsolete (yet). @@ -1174,8 +1174,9 @@ When not inside a field, signal an error." (defun widget-completions-at-point () (let ((field (widget-field-find (point)))) - (when field - (widget-apply field :completions-function)))) + (if field + (widget-apply field :completions-function) + (error "Not in an editable field")))) ;;; Setting up the buffer. commit 785dda9406e2bb2950cc23db42329c8fd8fb3868 Author: Juri Linkov Date: Mon Oct 7 02:00:24 2019 +0300 Allow using last_tab_bar_item on no-x builds. * src/frame.h (struct frame): Remove HAVE_WINDOW_SYSTEM around last_tab_bar_item. diff --git a/src/frame.h b/src/frame.h index 1b21cc6284..f408f12394 100644 --- a/src/frame.h +++ b/src/frame.h @@ -220,10 +220,8 @@ struct frame /* Cache of realized faces. */ struct face_cache *face_cache; -#if defined (HAVE_WINDOW_SYSTEM) /* Tab-bar item index of the item on which a mouse button was pressed. */ int last_tab_bar_item; -#endif #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) /* Tool-bar item index of the item on which a mouse button was pressed. */ commit 01465915c93d11fe26c189386d7103cf4904bf6a Author: Juri Linkov Date: Mon Oct 7 00:53:34 2019 +0300 Implement tab-close-other bound to C-x 6 1 by analogy with C-x 5 1. * lisp/tab-bar.el (tab-close-other): New command bound to C-x 6 1. * doc/emacs/frames.texi (Tab Bars): Document it. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 869b77d86b..169eebab3e 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1307,6 +1307,11 @@ Switch to another tab. If you repeat this command, it cycles through all the tabs on the selected frame. With a positive numeric argument N, it switches to the next Nth tab; with a negative argument −N, it switches back to the previous Nth tab. + +@item C-x 6 1 +@kindex C-x 6 1 +@findex tab-close-other +Close all tabs on the selected frame, except the selected one. @end table @node Dialog Boxes diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 27ae274eaa..1c1acaafa4 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -560,6 +560,17 @@ TO-INDEX counts from 1." (tab-bar-tabs))))) (tab-bar-close-tab (1+ (tab-bar--tab-index-by-name name)))) +(defun tab-close-other () + "Close all tabs on the selected frame, except the selected one." + (interactive) + (let* ((tabs (tab-bar-tabs)) + (current-index (tab-bar--current-tab-index tabs))) + (when current-index + (set-frame-parameter nil 'tabs (list (nth current-index tabs))) + (if tab-bar-mode + (force-mode-line-update) + (message "Deleted all other tabs"))))) + ;;; Short aliases @@ -819,6 +830,7 @@ Like \\[find-file-other-frame] (which see), but creates a new tab." (switch-to-buffer-other-tab value)))) (define-key ctl-x-6-map "2" 'tab-new) +(define-key ctl-x-6-map "1" 'tab-close-other) (define-key ctl-x-6-map "0" 'tab-close) (define-key ctl-x-6-map "o" 'tab-next) (define-key ctl-x-6-map "b" 'switch-to-buffer-other-tab) commit d24a19779028f1fe940b43eb72e6c68d2d835bd7 Author: Juri Linkov Date: Mon Oct 7 00:08:10 2019 +0300 Use tabs in EWW (bug#37592) * lisp/net/eww.el (eww-open-in-new-buffer): Call tab-new when tab-bar-mode is enabled. (eww-browse-url): Add docstring. Call tab-new when tab-bar-mode is enabled. * lisp/net/shr.el (shr-map): Bind [C-down-mouse-1] to shr-mouse-browse-url-new-window. (shr-mouse-browse-url-new-window): New command. (shr-browse-url): Add optional arg new-window. * doc/misc/eww.texi (Basics): Mention opening tabs on M-RET. diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi index b8821cbc29..d0a4c9a790 100644 --- a/doc/misc/eww.texi +++ b/doc/misc/eww.texi @@ -105,7 +105,10 @@ web page hit @kbd{g} (@code{eww-reload}). Pressing @kbd{w} @kindex M-RET The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the URL at point in a new EWW buffer, akin to opening a link in a new -``tab'' in other browsers. +``tab'' in other browsers. When @code{global-tab-line-mode} is +enabled, this buffer is displayed in the tab on the window tab line. +When @code{tab-bar-mode} is enabled, a new tab is created on the frame +tab bar. @findex eww-readable @kindex R diff --git a/etc/NEWS b/etc/NEWS index 208db12519..906dc912d6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1185,6 +1185,10 @@ document. Invoking the command with a prefix argument will cause it to create a new EWW buffer for the URL instead of reusing the default one. ++++ +*** Clicking with the Ctrl key or 'C-u RET' on a link opens a new tab +when tab-bar-mode is enabled. + +++ *** The 'd' ('eww-download') command now falls back to current page's URL. If this command is invoked with no URL at point, it now downloads the diff --git a/lisp/net/eww.el b/lisp/net/eww.el index fb495a9858..0756c6088b 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -369,6 +369,9 @@ engine used." (interactive) (let ((url (eww-suggested-uris))) (if (null url) (user-error "No link at point") + (when tab-bar-mode + (let ((tab-bar-new-tab-choice t)) + (tab-new))) ;; clone useful to keep history, but ;; should not clone from non-eww buffer (with-current-buffer @@ -878,7 +881,22 @@ the like." ;;;###autoload (defun eww-browse-url (url &optional new-window) + "Ask the EWW browser to load URL. + +Interactively, if the variable `browse-url-new-window-flag' is non-nil, +loads the document in a new buffer tab on the window tab-line. A non-nil +prefix argument reverses the effect of `browse-url-new-window-flag'. + +If `tab-bar-mode' is enabled, then whenever a document would +otherwise be loaded in a new buffer, it is loaded in a new tab +in the tab-bar on an existing frame. + +Non-interactively, this uses the optional second argument NEW-WINDOW +instead of `browse-url-new-window-flag'." (when new-window + (when tab-bar-mode + (let ((tab-bar-new-tab-choice t)) + (tab-new))) (pop-to-buffer-same-window (generate-new-buffer (format "*eww-%s*" (url-host (url-generic-parse-url diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 628cc17a5b..f3d5de9fb6 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -201,6 +201,7 @@ and other things: (define-key map [?\M-\t] 'shr-previous-link) (define-key map [follow-link] 'mouse-face) (define-key map [mouse-2] 'shr-browse-url) + (define-key map [C-down-mouse-1] 'shr-mouse-browse-url-new-window) (define-key map "I" 'shr-insert-image) (define-key map "w" 'shr-maybe-probe-and-copy-url) (define-key map "u" 'shr-maybe-probe-and-copy-url) @@ -967,7 +968,13 @@ size, and full-buffer size." (mouse-set-point ev) (shr-browse-url)) -(defun shr-browse-url (&optional external mouse-event) +(defun shr-mouse-browse-url-new-window (ev) + "Browse the URL under the mouse cursor in a new window." + (interactive "e") + (mouse-set-point ev) + (shr-browse-url nil nil t)) + +(defun shr-browse-url (&optional external mouse-event new-window) "Browse the URL at point using `browse-url'. If EXTERNAL is non-nil (interactively, the prefix argument), browse the URL using `browse-url-secondary-browser-function'. @@ -987,7 +994,9 @@ the mouse click event." (progn (funcall browse-url-secondary-browser-function url) (shr--blink-link)) - (browse-url url)))))) + (browse-url url (if new-window + (not browse-url-new-window-flag) + browse-url-new-window-flag))))))) (defun shr-save-contents (directory) "Save the contents from URL in a file." commit 47cf2a37e7f7d2df3cc05b657b1b4ad8307c7c64 Author: Stefan Monnier Date: Sun Oct 6 16:00:21 2019 -0400 * eieio-core.el (eieio--full-class-object): New function. Rather than explicitly call eieio-class-un-autoload, the autoloading is now performed on-demand if you use eieio--full-class-object. * lisp/emacs-lisp/eieio-core.el (eieio-class-un-autoload): Remove. (eieio--full-class-object): New function, to replace it. (eieio-oref, eieio--class-precedence-list): * lisp/emacs-lisp/eieio-base.el (eieio-persistent-convert-list-to-object): Use it instead of eieio-class-un-autoload. * lisp/emacs-lisp/eieio.el (eieio-class-parents, child-of-class-p): Load the class if needed. diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el index 534613811d..fc78b3e098 100644 --- a/lisp/emacs-lisp/eieio-base.el +++ b/lisp/emacs-lisp/eieio-base.el @@ -277,8 +277,7 @@ identified, and needing more object creation." (progn ;; If OBJCLASS is an eieio autoload object, then we need to ;; load it. - (eieio-class-un-autoload objclass) - (eieio--class-object objclass)))) + (eieio--full-class-object objclass)))) (while slots (let ((initarg (car slots)) diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index 620b47e68d..09aed101a3 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -125,7 +125,8 @@ Currently under control of this var: (defsubst eieio--class-object (class) "Return the class object." (if (symbolp class) - ;; Keep the symbol if class-v is nil, for better error messages. + ;; Return the symbol if the class object doesn't exist, + ;; for better error messages. (or (cl--find-class class) class) class)) @@ -217,10 +218,6 @@ It creates an autoload function for CNAME's constructor." (make-obsolete-variable cname (format "use \\='%s instead" cname) "25.1")) - ;; Store the new class vector definition into the symbol. We need to - ;; do this first so that we can call defmethod for the accessor. - ;; The vector will be updated by the following while loop and will not - ;; need to be stored a second time. (setf (cl--find-class cname) newc) ;; Create an autoload on top of our constructor function. @@ -230,9 +227,17 @@ It creates an autoload function for CNAME's constructor." (autoload (intern (format "%s-child-p" cname)) filename "" nil nil) (autoload (intern (format "%s-list-p" cname)) filename "" nil nil))))) -(defsubst eieio-class-un-autoload (cname) - "If class CNAME is in an autoload state, load its file." - (autoload-do-load (symbol-function cname))) ; cname +(defun eieio--full-class-object (class) + "Like `eieio--class-object' but loads the class if needed." + (let ((c (eieio--class-object class))) + (and (not (symbolp c)) + ;; If the default-object-cache slot is nil, the class object + ;; is still a "dummy" setup by eieio-defclass-autoload. + (not (eieio--class-default-object-cache c)) + ;; FIXME: We rely on the autoload setup for the "standard" + ;; constructor, here! + (autoload-do-load (symbol-function (eieio--class-name c)))) + c)) (cl-deftype list-of (elem-type) `(and list @@ -730,9 +735,7 @@ Argument FN is the function calling this verifier." (cl-check-type obj (or eieio-object class)) (let* ((class (cond ((symbolp obj) (error "eieio-oref called on a class: %s" obj) - (let ((c (cl--find-class obj))) - (if (eieio--class-p c) (eieio-class-un-autoload obj)) - c)) + (eieio--full-class-object obj)) (t (eieio--object-class obj)))) (c (eieio--slot-name-index class slot))) (if (not c) @@ -1013,16 +1016,15 @@ The order, in which the parents are returned depends on the method invocation orders of the involved classes." (if (or (null class) (eq class eieio-default-superclass)) nil - (unless (eieio--class-default-object-cache class) - (eieio-class-un-autoload (eieio--class-name class))) - (cl-case (eieio--class-method-invocation-order class) - (:depth-first - (eieio--class-precedence-dfs class)) - (:breadth-first - (eieio--class-precedence-bfs class)) - (:c3 - (eieio--class-precedence-c3 class)))) - ) + (let ((class (eieio--full-class-object class))) + (cl-case (eieio--class-method-invocation-order class) + (:depth-first + (eieio--class-precedence-dfs class)) + (:breadth-first + (eieio--class-precedence-bfs class)) + (:c3 + (eieio--class-precedence-c3 class)))))) + (define-obsolete-function-alias 'class-precedence-list 'eieio--class-precedence-list "24.4") diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 4b899cdc64..9c3420176f 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -425,10 +425,11 @@ If EXTRA, include that in the string returned to represent the symbol." 'object-class-name 'eieio-object-class-name "24.4") (defun eieio-class-parents (class) + ;; FIXME: What does "(overload of variable)" mean here? "Return parent classes to CLASS. (overload of variable). The CLOS function `class-direct-superclasses' is aliased to this function." - (eieio--class-parents (eieio--class-object class))) + (eieio--class-parents (eieio--full-class-object class))) (define-obsolete-function-alias 'class-parents #'eieio-class-parents "24.4") @@ -468,7 +469,7 @@ The CLOS function `class-direct-subclasses' is aliased to this function." (defun child-of-class-p (child class) "Return non-nil if CHILD class is a subclass of CLASS." - (setq child (eieio--class-object child)) + (setq child (eieio--full-class-object child)) (cl-check-type child eieio--class) ;; `eieio-default-superclass' is never mentioned in eieio--class-parents, ;; so we have to special case it here. commit dc8108e10910352ab97c8200b23672072c374a91 Author: Stefan Kangas Date: Wed Aug 21 03:38:49 2019 +0200 Support changing font size using mouse wheel * lisp/mwheel.el (mouse-wheel-mode): Support changing font size (text scaling) using mouse wheel. (Bug#28182) (mouse-wheel-scroll-amount): Bind the Ctrl modifier to text scaling. (mwheel-installed-text-scale-bindings): New variable. (mouse-wheel--remove-bindings): New helper function for 'mouse-wheel-mode'. * doc/emacs/frames.texi (Mouse Commands): Document this feature. * etc/NEWS: Announce it. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index ba1424aa2a..869b77d86b 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -201,10 +201,12 @@ deactivating the mark. @xref{Shift Selection}. @vindex mouse-wheel-progressive-speed Some mice have a ``wheel'' which can be used for scrolling. Emacs supports scrolling windows with the mouse wheel, by default, on most -graphical displays. To toggle this feature, use @kbd{M-x -mouse-wheel-mode}. The variables @code{mouse-wheel-follow-mouse} and -@code{mouse-wheel-scroll-amount} determine where and by how much -buffers are scrolled. The variable +graphical displays. There is also support for increasing or +decreasing the height of the default face, by default bound to +scrolling with the @key{Ctrl} modifier. To toggle this feature, use +@kbd{M-x mouse-wheel-mode}. The variables +@code{mouse-wheel-follow-mouse} and @code{mouse-wheel-scroll-amount} +determine where and by how much buffers are scrolled. The variable @code{mouse-wheel-progressive-speed} determines whether the scroll speed is linked to how fast you move the wheel. diff --git a/etc/NEWS b/etc/NEWS index 4a32300268..208db12519 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2309,6 +2309,18 @@ bool vector. ** 'regexp-quote' may return its argument string. If the argument needs no quoting, it can be returned instead of a copy. ++++ +** Mouse scroll up and down with control key modifier changes font size. +Previously, the control key modifier was used to scroll up or down by +an amount which was close to near a full screen. This is now instead +available by scrolling with the meta modifier key. + +To get the old behaviour back, customize the variable +'mouse-wheel-scroll-amount', or add the following to your init file: + +(customize-set-variable 'mouse-wheel-scroll-amount + '(5 ((shift) . 1) ((control) . nil))) + * Lisp Changes in Emacs 27.1 diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 4862406fa1..9b67e71886 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -84,17 +84,22 @@ set to the event sent when clicking on the mouse wheel button." :group 'mouse :type 'number) -(defcustom mouse-wheel-scroll-amount '(5 ((shift) . 1) ((control) . nil)) +(defcustom mouse-wheel-scroll-amount + '(5 ((shift) . 1) ((meta) . nil) ((control) . text-scale)) "Amount to scroll windows by when spinning the mouse wheel. This is an alist mapping the modifier key to the amount to scroll when the wheel is moved with the modifier key depressed. -Elements of the list have the form (MODIFIERS . AMOUNT) or just AMOUNT if -MODIFIERS is nil. +Elements of the list have the form (MODIFIER . AMOUNT) or just AMOUNT if +MODIFIER is nil. AMOUNT should be the number of lines to scroll, or nil for near full screen. It can also be a floating point number, specifying the fraction of a full screen to scroll. A near full screen is `next-screen-context-lines' -less than a full screen." +less than a full screen. + +If AMOUNT is the symbol text-scale, this means that with +MODIFIER, the mouse wheel will change the face height instead of +scrolling." :group 'mouse :type '(cons (choice :tag "Normal" @@ -105,20 +110,22 @@ less than a full screen." (repeat (choice :tag "modifier" (const alt) (const control) (const hyper) (const meta) (const shift) (const super))) - (choice :tag "scroll amount" - (const :tag "Full screen" :value nil) - (integer :tag "Specific # of lines") - (float :tag "Fraction of window")))) + (choice :tag "action" + (const :tag "Scroll full screen" :value nil) + (integer :tag "Scroll specific # of lines") + (float :tag "Scroll fraction of window")))) (repeat (cons (repeat (choice :tag "modifier" (const alt) (const control) (const hyper) (const meta) (const shift) (const super))) - (choice :tag "scroll amount" - (const :tag "Full screen" :value nil) - (integer :tag "Specific # of lines") - (float :tag "Fraction of window"))))) - :set 'mouse-wheel-change-button) + (choice :tag "action" + (const :tag "Scroll full screen" :value nil) + (integer :tag "Scroll specific # of lines") + (float :tag "Scroll fraction of window") + (const :tag "Change face size" :value text-scale))))) + :set 'mouse-wheel-change-button + :version "27.1") (defcustom mouse-wheel-progressive-speed t "If non-nil, the faster the user moves the wheel, the faster the scrolling. @@ -316,6 +323,15 @@ non-Windows systems." (put 'mwheel-scroll 'scroll-command t) (defvar mwheel-installed-bindings nil) +(defvar mwheel-installed-text-scale-bindings nil) + +(defun mouse-wheel--remove-bindings (bindings funs) + "Remove key BINDINGS if they're bound to any function in FUNS. +BINDINGS is a list of key bindings, FUNS is a list of functions. +This is a helper function for `mouse-wheel-mode'." + (dolist (key bindings) + (when (memq (lookup-key (current-global-map) key) funs) + (global-unset-key key)))) (define-minor-mode mouse-wheel-mode "Toggle mouse wheel support (Mouse Wheel mode)." @@ -328,17 +344,32 @@ non-Windows systems." :global t :group 'mouse ;; Remove previous bindings, if any. - (while mwheel-installed-bindings - (let ((key (pop mwheel-installed-bindings))) - (when (eq (lookup-key (current-global-map) key) 'mwheel-scroll) - (global-unset-key key)))) + (mouse-wheel--remove-bindings mwheel-installed-bindings + '(mwheel-scroll)) + (mouse-wheel--remove-bindings mwheel-installed-text-scale-bindings + '(text-scale-increase + text-scale-decrease)) + (setq mwheel-installed-bindings nil) + (setq mwheel-installed-text-scale-bindings nil) ;; Setup bindings as needed. (when mouse-wheel-mode - (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event mouse-wheel-right-event mouse-wheel-left-event)) - (dolist (key (mapcar (lambda (amt) `[(,@(if (consp amt) (car amt)) ,event)]) - mouse-wheel-scroll-amount)) - (global-set-key key 'mwheel-scroll) - (push key mwheel-installed-bindings))))) + (dolist (binding mouse-wheel-scroll-amount) + (cond + ;; Bindings for changing font size. + ((and (consp binding) (eq (cdr binding) 'text-scale)) + (let ((increase-key `[,(list (caar binding) mouse-wheel-down-event)]) + (decrease-key `[,(list (caar binding) mouse-wheel-up-event)])) + (global-set-key increase-key 'text-scale-increase) + (global-set-key decrease-key 'text-scale-decrease) + (push increase-key mwheel-installed-text-scale-bindings) + (push decrease-key mwheel-installed-text-scale-bindings))) + ;; Bindings for scrolling. + (t + (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event + mouse-wheel-right-event mouse-wheel-left-event)) + (let ((key `[(,@(if (consp binding) (car binding)) ,event)])) + (global-set-key key 'mwheel-scroll) + (push key mwheel-installed-bindings)))))))) ;;; Compatibility entry point ;; preloaded ;;;###autoload commit 8de2e69f021b5b2920a07d82c9869bb394171d41 Author: Juanma Barranquero Date: Sun Oct 6 20:53:18 2019 +0200 Set alternate faces for some line numbers (bug#27734) * lisp/faces.el (line-number-major-tick, line-number-minor-tick): New faces. * lisp/cus-start.el (display-line-numbers-major-tick) (display-line-numbers-minor-tick): Add customization info. * lisp/frame.el: Add `display-line-numbers-major-tick' and `display-line-numbers-minor-tick' to list of variables which should trigger redisplay of the current buffer. * src/xdisp.c (syms_of_xdisp) : Defvar new options. (syms_of_xdisp) : Defsym new faces. (maybe_produce_line_number): Use new faces for line numbers that are multiple of `display-line-numbers-major-tick' and `display-line-numbers-minor-tick'. * etc/NEWS (value): Announce new feature. * doc/emacs/display.texi (Display Custom): Describe it. Wording by Robert Pluim diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 84363d0f0d..406feb8c12 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1871,7 +1871,12 @@ The line numbers are displayed in a special face @code{line-number}. The current line number is displayed in a different face, @code{line-number-current-line}, so you can make the current line's number have a distinct appearance, which will help locating the line -showing point. +showing point. Additional faces @code{line-number-major-tick} and +@code{line-number-minor-tick} can be used to highlight the line numbers +of lines which are a multiple of certain numbers. Customize +@code{display-line-numbers-major-tick} and +@code{display-line-numbers-minor-tick} respectively to set those +numbers. @vindex visible-bell If the variable @code{visible-bell} is non-@code{nil}, Emacs attempts diff --git a/etc/NEWS b/etc/NEWS index beb15776ef..4a32300268 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -558,6 +558,13 @@ network connection information (in addition to the host name). *** When called interactively with a prefix arg 'C-u', 'desktop-read' now prompts the user for the directory containing the desktop file. ++++ +** display-line-numbers-mode +*** New faces 'line-number-major-tick' and 'line-number-minor-tick', +and customizable variables 'display-line-numbers-major-tick' and +'display-line-numbers-minor-tick' can be used to highlight the line +numbers of lines multiple of certain numbers. + +++ ** winner *** A new variable, 'winner-boring-buffers-regexp', has been added. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index e61c1954a1..89a96a9f51 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -655,6 +655,20 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Count lines from beginning of narrowed region" :value nil)) "26.1") + (display-line-numbers-major-tick + display-line-numbers + (choice + (const :tag "No line" 0) + (integer :tag "Multiples of" + :value 10)) + "27.1") + (display-line-numbers-minor-tick + display-line-numbers + (choice + (const :tag "No line" 0) + (integer :tag "Multiples of" + :value 5)) + "27.1") (display-fill-column-indicator display-fill-column-indicator diff --git a/lisp/faces.el b/lisp/faces.el index 9c5ffe1e59..58b6349ccf 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -2390,6 +2390,40 @@ unwanted effects." :group 'basic-faces :group 'display-line-numbers) +(defface line-number-major-tick + '((t :inherit line-number)) + "Face for highlighting \"major ticks\" (as in a ruler). +When `display-line-numbers-major-tick' is positive, highlight +the line numbers of lines which are a multiple of its value. +This face is used when `display-line-numbers' is non-nil. + +If you customize the font of this face, make sure it is a +monospaced font, otherwise line numbers will not line up, +and text lines might move horizontally as you move through +the buffer. Similarly, making this face's font different +from that of the `line-number' face could produce such +unwanted effects." + :version "27.1" + :group 'basic-faces + :group 'display-line-numbers) + +(defface line-number-minor-tick + '((t :inherit line-number)) + "Face for highlighting \"minor ticks\" (as in a ruler). +When `display-line-numbers-minor-tick' is positive, highlight +the line numbers of lines which are a multiple of its value. +This face is used when `display-line-numbers' is non-nil. + +If you customize the font of this face, make sure it is a +monospaced font, otherwise line numbers will not line up, +and text lines might move horizontally as you move through +the buffer. Similarly, making this face's font different +from that of the `line-number' face could produce such +unwanted effects." + :version "27.1" + :group 'basic-faces + :group 'display-line-numbers) + ;; Definition stolen from display-line-numbers. (defface fill-column-indicator '((t :inherit shadow :weight normal :slant normal diff --git a/lisp/frame.el b/lisp/frame.el index 0c68fc378b..51b3b621ff 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2724,6 +2724,8 @@ See also `toggle-frame-maximized'." display-line-numbers-width display-line-numbers-current-absolute display-line-numbers-widen + display-line-numbers-major-tick + display-line-numbers-minor-tick display-fill-column-indicator display-fill-column-indicator-column display-fill-column-indicator-character diff --git a/src/xdisp.c b/src/xdisp.c index 8aa38c8034..1f3a8136f8 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -22664,6 +22664,14 @@ maybe_produce_line_number (struct it *it) empty lines beyond EOB. */ && it->what != IT_EOB) tem_it.face_id = current_lnum_face_id; + else if (display_line_numbers_major_tick > 0 + && (lnum_to_display % display_line_numbers_major_tick == 0)) + tem_it.face_id = merge_faces (it->w, Qline_number_major_tick, + 0, DEFAULT_FACE_ID); + else if (display_line_numbers_minor_tick > 0 + && (lnum_to_display % display_line_numbers_minor_tick == 0)) + tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick, + 0, DEFAULT_FACE_ID); else tem_it.face_id = lnum_face_id; if (beyond_zv @@ -34125,6 +34133,8 @@ be let-bound around code that needs to disable messages temporarily. */); /* Names of the faces used to display line numbers. */ DEFSYM (Qline_number, "line-number"); DEFSYM (Qline_number_current_line, "line-number-current-line"); + DEFSYM (Qline_number_major_tick, "line-number-major-tick"); + DEFSYM (Qline_number_minor_tick, "line-number-minor-tick"); /* Name of a text property which disables line-number display. */ DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable"); @@ -34760,6 +34770,20 @@ if the font in fill-column-indicator face does not support Unicode characters. DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character"); Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character); + DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick, + doc: /* If an integer N > 0, highlight line number of every Nth line. +The line number is shown with the `line-number-major-tick' face. +Otherwise, no special highlighting is done every Nth line. +Note that major ticks take precedence over minor ticks. */); + display_line_numbers_major_tick = 0; + + DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick, + doc: /* If an integer N > 0, highlight line number of every Nth line. +The line number is shown with the `line-number-minor-tick' face. +Otherwise, no special highlighting is done every Nth line. +Note that major ticks take precedence over minor ticks. */); + display_line_numbers_minor_tick = 0; + DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay, doc: /* Non-nil means don't eval Lisp during redisplay. */); inhibit_eval_during_redisplay = false; commit 29db34e3e0cd5be78b7ab4604050c0ba05835414 Author: Juri Linkov Date: Sun Oct 6 21:47:24 2019 +0300 Don't bind 'C-x 6' to '2C-mode-map' globally by default. * lisp/textmodes/two-column.el: Don't autoload global setting of "\C-x6" to 2C-command. * lisp/ldefs-boot.el: Update to remove setting "\C-x6" to 2C-command. * doc/emacs/commands.texi (Keys): * doc/emacs/text.texi (Two-Column): * doc/lispref/keymaps.texi (Prefix Keys): * doc/lispref/maps.texi (Standard Keymaps): Unbind 'C-x 6' from '2C-mode-map'. diff --git a/doc/emacs/commands.texi b/doc/emacs/commands.texi index 4773d7675b..17e0d20f35 100644 --- a/doc/emacs/commands.texi +++ b/doc/emacs/commands.texi @@ -118,13 +118,12 @@ C-k} is two key sequences, not one. By default, the prefix keys in Emacs are @kbd{C-c}, @kbd{C-h}, @kbd{C-x}, @kbd{C-x @key{RET}}, @kbd{C-x @@}, @kbd{C-x a}, @kbd{C-x n}, @kbd{C-x r}, @kbd{C-x v}, @kbd{C-x 4}, @kbd{C-x 5}, @kbd{C-x 6}, -@key{ESC}, @kbd{M-g}, and @kbd{M-o}. (@key{F1} and @key{F2} are -aliases for @kbd{C-h} and @kbd{C-x 6}.) This list is not cast in -stone; if you customize Emacs, you can make new prefix keys. You -could even eliminate some of the standard ones, though this is not -recommended for most users; for example, if you remove the prefix -definition of @kbd{C-x 4}, then @kbd{C-x 4 C-f} becomes an invalid key -sequence. @xref{Key Bindings}. +@key{ESC}, @kbd{M-g}, @kbd{M-o} and @key{F2}. (@key{F1} is an alias +for @kbd{C-h}.) This list is not cast in stone; if you customize +Emacs, you can make new prefix keys. You could even eliminate some of +the standard ones, though this is not recommended for most users; for +example, if you remove the prefix definition of @kbd{C-x 4}, then +@kbd{C-x 4 C-f} becomes an invalid key sequence. @xref{Key Bindings}. Typing the help character (@kbd{C-h} or @key{F1}) after a prefix key displays a list of the commands starting with that prefix. The sole diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 974f79d523..a837b6580d 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -2870,9 +2870,8 @@ of text. It uses two side-by-side windows, each showing its own buffer. There are three ways to enter two-column mode: @table @asis -@item @kbd{@key{F2} 2} or @kbd{C-x 6 2} +@item @kbd{@key{F2} 2} @kindex F2 2 -@kindex C-x 6 2 @findex 2C-two-columns Enter two-column mode with the current buffer on the left, and on the right, a buffer whose name is based on the current buffer's name @@ -2883,9 +2882,8 @@ changed. This command is appropriate when the current buffer is empty or contains just one column and you want to add another column. -@item @kbd{@key{F2} s} or @kbd{C-x 6 s} +@item @kbd{@key{F2} s} @kindex F2 s -@kindex C-x 6 s @findex 2C-split Split the current buffer, which contains two-column text, into two buffers, and display them side by side (@code{2C-split}). The current @@ -2898,21 +2896,19 @@ This command is appropriate when you have a buffer that already contains two-column text, and you wish to separate the columns temporarily. @item @kbd{@key{F2} b @var{buffer} @key{RET}} -@itemx @kbd{C-x 6 b @var{buffer} @key{RET}} @kindex F2 b -@kindex C-x 6 b @findex 2C-associate-buffer Enter two-column mode using the current buffer as the left-hand buffer, and using buffer @var{buffer} as the right-hand buffer (@code{2C-associate-buffer}). @end table - @kbd{@key{F2} s} or @kbd{C-x 6 s} looks for a column separator, which -is a string that appears on each line between the two columns. You can -specify the width of the separator with a numeric argument to -@kbd{@key{F2} s}; that many characters, before point, constitute the -separator string. By default, the width is 1, so the column separator -is the character before point. + @kbd{@key{F2} s} looks for a column separator, which is a string +that appears on each line between the two columns. You can specify +the width of the separator with a numeric argument to @kbd{@key{F2} +s}; that many characters, before point, constitute the separator +string. By default, the width is 1, so the column separator is the +character before point. When a line has the separator at the proper place, @kbd{@key{F2} s} puts the text after the separator into the right-hand buffer, and @@ -2924,25 +2920,22 @@ mode: write it in the left-hand buffer, and put an empty line in the right-hand buffer.) @kindex F2 RET -@kindex C-x 6 RET @findex 2C-newline - The command @kbd{@key{F2} @key{RET}} or @kbd{C-x 6 @key{RET}} -(@code{2C-newline}) inserts a newline in each of the two buffers at -corresponding positions. This is the easiest way to add a new line to -the two-column text while editing it in split buffers. + The command @kbd{@key{F2} @key{RET}} (@code{2C-newline}) inserts +a newline in each of the two buffers at corresponding positions. +This is the easiest way to add a new line to the two-column text while +editing it in split buffers. @kindex F2 1 -@kindex C-x 6 1 @findex 2C-merge When you have edited both buffers as you wish, merge them with -@kbd{@key{F2} 1} or @kbd{C-x 6 1} (@code{2C-merge}). This copies the +@kbd{@key{F2} 1} (@code{2C-merge}). This copies the text from the right-hand buffer as a second column in the other buffer. To go back to two-column editing, use @kbd{@key{F2} s}. @kindex F2 d -@kindex C-x 6 d @findex 2C-dissociate - Use @kbd{@key{F2} d} or @kbd{C-x 6 d} to dissociate the two buffers, -leaving each as it stands (@code{2C-dissociate}). If the other buffer, -the one not current when you type @kbd{@key{F2} d}, is empty, -@kbd{@key{F2} d} kills it. + Use @kbd{@key{F2} d} to dissociate the two buffers, leaving each as +it stands (@code{2C-dissociate}). If the other buffer, the one not +current when you type @kbd{@key{F2} d}, is empty, @kbd{@key{F2} d} +kills it. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index b8eed0a501..58f4a6687d 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -545,8 +545,8 @@ key. @item @cindex @kbd{C-x 6} -@vindex 2C-mode-map -@code{2C-mode-map} is the global keymap used for the @kbd{C-x 6} prefix +@vindex ctl-x-6-map +@code{ctl-x-6-map} is the global keymap used for the @kbd{C-x 6} prefix key. @item diff --git a/doc/lispref/maps.texi b/doc/lispref/maps.texi index bcf8f175e0..1ee4816b0c 100644 --- a/doc/lispref/maps.texi +++ b/doc/lispref/maps.texi @@ -21,7 +21,7 @@ keymaps, @pxref{Keymaps}. @c Don't add xrefs to things covered in {Keymaps}. @table @code @item 2C-mode-map -A sparse keymap for subcommands of the prefix @kbd{C-x 6}.@* +A sparse keymap for subcommands of the prefix @key{F2}.@* @xref{Two-Column,, Two-Column Editing, emacs, The GNU Emacs Manual}. @item abbrev-map @@ -42,6 +42,9 @@ A sparse keymap for subcommands of the prefix @kbd{C-x 4}. @item ctl-x-5-map A sparse keymap for subcommands of the prefix @kbd{C-x 5}. +@item ctl-x-6-map +A sparse keymap for subcommands of the prefix @kbd{C-x 6}. + @item ctl-x-map A full keymap for @kbd{C-x} commands. diff --git a/etc/NEWS b/etc/NEWS index 0edbec6894..beb15776ef 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2106,6 +2106,11 @@ immediately. Type 'M-x so-long-commentary' for full documentation. * Incompatible Lisp Changes in Emacs 27.1 +--- +** Two-column mode provides its C-x 6 prefix map only after loading +two-column.el. Its prefix key F2 is still available globally +along with C-x 6 used by the tab commands globally. + --- ** Incomplete destructive splicing support has been removed. Support for Common Lisp style destructive splicing (",.") was diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index ea111f2d3f..5c20c0526d 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -34138,7 +34138,6 @@ resumed later. ;;;;;; 0 0)) ;;; Generated autoloads from textmodes/two-column.el (autoload '2C-command "two-column" () t 'keymap) - (global-set-key "\C-x6" '2C-command) (global-set-key [f2] '2C-command) (autoload '2C-two-columns "two-column" "\ diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el index e1ebf1a02a..5bc70d0bd5 100644 --- a/lisp/textmodes/two-column.el +++ b/lisp/textmodes/two-column.el @@ -184,7 +184,9 @@ minus this value." ;; This one is for historical reasons and simple keyboards, it is not ;; at all mnemonic. All usual sequences containing 2 were used, and ;; f2 could not be set up in a standard way under Emacs 18. -;;;###autoload (global-set-key "\C-x6" '2C-command) +;; This prefix is bound only after loading this package +;; to not conflict with the C-x 6 prefix used by tab commands. +(global-set-key "\C-x6" '2C-command) ;;;###autoload (global-set-key [f2] '2C-command) commit ef9124aaa005d5409b194ec60e3315d8a6625760 Author: Stefan Monnier Date: Sun Oct 6 13:48:28 2019 -0400 * lisp/emacs-lisp/package.el (package--get-deps): Rewrite. Avoid inf-recursion with dependency cycles. Remove unused `only` arg. Prune duplicates early rather than late. (package--removable-packages): Simplify code accordingly. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 188f398a56..169bcda69f 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -1844,21 +1844,17 @@ if it is still empty." (package--save-selected-packages (package--find-non-dependencies))) (memq pkg package-selected-packages)) -(defun package--get-deps (pkg &optional only) - (let* ((pkg-desc (cadr (assq pkg package-alist))) - (direct-deps (cl-loop for p in (package-desc-reqs pkg-desc) - for name = (car p) - when (assq name package-alist) - collect name)) - (indirect-deps (unless (eq only 'direct) - (delete-dups - (cl-loop for p in direct-deps - append (package--get-deps p)))))) - (cl-case only - (direct direct-deps) - (separate (list direct-deps indirect-deps)) - (indirect indirect-deps) - (t (delete-dups (append direct-deps indirect-deps)))))) +(defun package--get-deps (pkgs) + (let ((seen '())) + (while pkgs + (let ((pkg (pop pkgs))) + (if (memq pkg seen) + nil ;; Done already! + (let ((pkg-desc (cadr (assq pkg package-alist)))) + (when pkg-desc + (push pkg seen) + (setq pkgs (append (package-desc-reqs pkg-desc) pkgs))))))) + seen)) (defun package--user-installed-p (package) "Return non-nil if PACKAGE is a user-installed package. @@ -1873,10 +1869,7 @@ control over." "Return a list of names of packages no longer needed. These are packages which are neither contained in `package-selected-packages' nor a dependency of one that is." - (let ((needed (cl-loop for p in package-selected-packages - if (assq p package-alist) - ;; `p' and its dependencies are needed. - append (cons p (package--get-deps p))))) + (let ((needed (package--get-deps package-selected-packages))) (cl-loop for p in (mapcar #'car package-alist) unless (or (memq p needed) ;; Do not auto-remove external packages. commit 4638b5ce0ae80568ac3278a5d1ae67086bd7f616 Merge: ad76020af8 8ad41af3a1 Author: Eli Zaretskii Date: Sun Oct 6 19:54:58 2019 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 8ad41af3a1a651e11c270b9bccc838aed5d0e0e7 Author: Paul Eggert Date: Sun Oct 6 09:53:53 2019 -0700 Port file-acl errno checking to non-GNU Problem reported privately for FreeBSD 12 by Ashish Shukla. * src/fileio.c (Ffile_acl): Treat EINVAL etc. like ENOTSUP if acl_get_file fails, to port to FreeBSD 12 and other non-GNU platforms. diff --git a/src/fileio.c b/src/fileio.c index 45186d6940..781a71bcf3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3248,7 +3248,7 @@ Return nil if file does not exist. */) acl_t acl = acl_get_file (SSDATA (ENCODE_FILE (absname)), ACL_TYPE_EXTENDED); if (acl == NULL) { - if (errno == ENOENT || errno == ENOTDIR || errno == ENOTSUP) + if (errno == ENOENT || errno == ENOTDIR || acl_errno_valid (errno)) return Qnil; report_file_error ("Getting ACLs", absname); } commit ad76020af8498d148984daf4de545d5d610d0589 Author: Eli Zaretskii Date: Sun Oct 6 19:53:18 2019 +0300 Support mouse clicks on tab bar on TTY frames This for now doesn't work on GPM. * src/xdisp.c (display_tab_bar): Make the loop over tab-bar items more efficient. (tab_bar_item_info, tool_bar_item_info): Correct data type for CHARPOS. (tty_get_tab_bar_item, tty_handle_tab_bar_click): New functions. (note_mouse_highlight): Handle help-echo of tab-bar tabs on TTY frames. * src/w32inevt.c (do_mouse_event): Call tty_handle_tab_bar_click to process mouse clicks on the tab bar. * src/termchar.h (tty_handle_tab_bar_click): Add prototype. * src/w32console.c (w32con_set_terminal_modes): Disable Quick Edit mode on entry, to make sure mouse events get reported to us. diff --git a/src/termchar.h b/src/termchar.h index 796453d3cc..11c964b2b6 100644 --- a/src/termchar.h +++ b/src/termchar.h @@ -231,4 +231,8 @@ extern struct tty_display_info *tty_list; #define CURTTY() FRAME_TTY (SELECTED_FRAME()) +struct input_event; +extern bool tty_handle_tab_bar_click (struct frame *, int, int, bool, + struct input_event *); + #endif /* EMACS_TERMCHAR_H */ diff --git a/src/w32console.c b/src/w32console.c index 8575c930a8..c50bb67cd2 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -503,7 +503,14 @@ w32con_set_terminal_modes (struct terminal *t) SetConsoleActiveScreenBuffer (cur_screen); - SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); + /* If Quick Edit is enabled for the console, it will get in the way + of receiving mouse events, so we disable it. But leave the + Insert Mode as it was set by the user. */ + DWORD new_console_mode + = ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_EXTENDED_FLAGS; + if ((prev_console_mode & ENABLE_INSERT_MODE) != 0) + new_console_mode |= ENABLE_INSERT_MODE; + SetConsoleMode (keyboard_handle, new_console_mode); /* Initialize input mode: interrupt_input off, no flow control, allow 8 bit character input, standard quit char. */ diff --git a/src/w32inevt.c b/src/w32inevt.c index 0a1321c6d8..1a901d4e0a 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -559,8 +559,6 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, if (event->dwButtonState == button_state) return 0; - emacs_ev->kind = MOUSE_CLICK_EVENT; - /* Find out what button has changed state since the last button event. */ but_change = button_state ^ event->dwButtonState; @@ -576,15 +574,24 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, } button_state = event->dwButtonState; - emacs_ev->modifiers = - w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) - | ((event->dwButtonState & mask) ? down_modifier : up_modifier); + emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0); + emacs_ev->timestamp = GetTickCount (); + + int x = event->dwMousePosition.X; + int y = event->dwMousePosition.Y; + struct frame *f = get_frame (); + if (tty_handle_tab_bar_click (f, x, y, (button_state & mask) != 0, + emacs_ev)) + return 0; /* tty_handle_tab_bar_click adds the event to queue */ - XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); - XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); - XSETFRAME (emacs_ev->frame_or_window, get_frame ()); + emacs_ev->modifiers |= ((button_state & mask) + ? down_modifier : up_modifier); + + emacs_ev->kind = MOUSE_CLICK_EVENT; + XSETFASTINT (emacs_ev->x, x); + XSETFASTINT (emacs_ev->y, y); + XSETFRAME (emacs_ev->frame_or_window, f); emacs_ev->arg = Qnil; - emacs_ev->timestamp = GetTickCount (); return 1; } diff --git a/src/xdisp.c b/src/xdisp.c index f5dedc218e..8aa38c8034 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12746,12 +12746,12 @@ display_tab_bar (struct window *w) /* Display all items of the tab bar. */ items = it.f->tab_bar_items; - for (i = 0; i < it.f->n_tab_bar_items; ++i) + int j; + for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS) { - Lisp_Object string; + Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION); /* Stop at nil string. */ - string = AREF (items, i * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_CAPTION); if (NILP (string)) break; @@ -13180,7 +13180,7 @@ tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx, bool *close_p) { Lisp_Object prop; - int charpos; + ptrdiff_t charpos; /* This function can be called asynchronously, which means we must exclude any possibility that Fget_text_property signals an @@ -13256,7 +13256,7 @@ get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph, void handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, - int modifiers) + int modifiers) { Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); struct window *w = XWINDOW (f->tab_bar_window); @@ -13420,6 +13420,96 @@ note_tab_bar_highlight (struct frame *f, int x, int y) #endif /* HAVE_WINDOW_SYSTEM */ +/* Find the tab-bar item at X coordinate and return its information. */ +static Lisp_Object +tty_get_tab_bar_item (struct frame *f, int x, int *idx, ptrdiff_t *end) +{ + ptrdiff_t clen = 0; + Lisp_Object caption; + + int i, j; + for (i = 0, j = 0; i < f->n_tab_bar_items; i++, j += TAB_BAR_ITEM_NSLOTS) + { + caption = AREF (f->tab_bar_items, j + TAB_BAR_ITEM_CAPTION); + if (NILP (caption)) + return Qnil; + clen += SCHARS (caption); + if (x < clen) + break; + } + if (i < f->n_tab_bar_items) + { + *idx = i; + *end = clen; + return caption; + } + else + return Qnil; +} + +/* Handle a mouse click at X/Y on the tab bar of TTY frame F. If the + click was on the tab bar and was handled, populate the EVENT + structure, store it in keyboard queue, and return true; otherwise + return false. MODIFIERS are event modifiers for generating the tab + release event. */ +bool +tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, + struct input_event *event) +{ + /* Did they click on the tab bar? */ + if (y < FRAME_MENU_BAR_LINES (f) + || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)) + return false; + + /* Find the tab-bar item where the X,Y coordinates belong. */ + int prop_idx; + ptrdiff_t clen; + Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &clen); + + if (NILP (caption)) + return false; + + if (NILP (AREF (f->tab_bar_items, + prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P))) + return false; + + if (down_p) + f->last_tab_bar_item = prop_idx; + else + { + /* Generate a TAB_BAR_EVENT event. */ + Lisp_Object frame; + Lisp_Object key = AREF (f->tab_bar_items, + prop_idx * TAB_BAR_ITEM_NSLOTS + + TAB_BAR_ITEM_KEY); + /* Kludge alert: we assume the last two characters of a tab + label are " x", and treat clicks on those 2 characters as a + Close Tab command. */ + eassert (STRINGP (caption)); + int lastc = SSDATA (caption)[SCHARS (caption) - 1]; + bool close_p = false; + if ((x == clen - 1 || (clen > 1 && x == clen - 2)) && lastc == 'x') + close_p = true; + + event->code = 0; + XSETFRAME (frame, f); + event->kind = TAB_BAR_EVENT; + event->frame_or_window = frame; + event->arg = frame; + kbd_buffer_store_event (event); + + event->kind = TAB_BAR_EVENT; + event->frame_or_window = frame; + event->arg = key; + if (close_p) + event->modifiers |= ctrl_modifier; + kbd_buffer_store_event (event); + f->last_tab_bar_item = -1; + } + + return true; +} + /*********************************************************************** @@ -14065,7 +14155,7 @@ static bool tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx) { Lisp_Object prop; - int charpos; + ptrdiff_t charpos; /* This function can be called asynchronously, which means we must exclude any possibility that Fget_text_property signals an @@ -32711,9 +32801,30 @@ note_mouse_highlight (struct frame *f, int x, int y) && part != ON_TAB_LINE)) clear_mouse_face (hlinfo); - /* Reset help_echo_string. It will get recomputed below. */ + /* Reset help_echo_string. It will get recomputed below. */ help_echo_string = Qnil; + /* Handle tab-bar highlight on mouse-capable TTY frames. */ + if (!FRAME_WINDOW_P (f) + && (y >= FRAME_MENU_BAR_LINES (f) + && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))) + { + int prop_idx; + ptrdiff_t ignore; + Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore); + + if (!NILP (caption)) + { + help_echo_object = help_echo_window = Qnil; + help_echo_pos = -1; + help_echo_string = AREF (f->tab_bar_items, + prop_idx * TAB_BAR_ITEM_NSLOTS + + TAB_BAR_ITEM_HELP); + if (NILP (help_echo_string)) + help_echo_string = caption; + } + } + #ifdef HAVE_WINDOW_SYSTEM /* If the cursor is on the internal border of FRAME and FRAME's internal border is draggable, provide some visual feedback. */