commit fd4ee361395060c8afa95393245ac8d51655ae54 (HEAD, refs/remotes/origin/master) Author: Yuan Fu Date: Mon Apr 6 09:56:15 2020 +0200 Unify and improve gdb-mi source buffer display logic Unify the behavior of source buffer display for gdb-mi. Before this change, stepping and other gdb command handlers use 'gud-display-line', and 'gdb-goto-breakpoint' uses 'gdb-display-source-buffer'. Now whenever gdb-mi code tries to open a source buffer, 'gdb-display-source-buffer' is used. Also, simplify the logic in 'gdb-display-source-buffer' and add a feature to limit the maximum number of source windows. * doc/emacs/building.texi (GDB User Interface Layout): Explain source file display in GDB. * etc/NEWS (gdb-mi): Add news about source display. * lisp/progmodes/gdb-mi.el (gdb-source-window): Remove variable, change to 'gdb-source-window-list'. (gdb-source-window-list): New variable. (gdb-display-source-buffer-action, gdb-max-source-window-count): New options. (gdb-init-1, gdb-setup-windows, gdb-load-window-configuration, gdb-restore-windows): Use 'gdb-source-window' rather than 'gdb-source-window-list'. (gdb-save-window-configuration): Use 'gdb-source-window' rather than 'gdb-source-window-list'. And consider any buffer that is not a command or function buffer as a source buffer. (gdb-display-source-buffer): Use new logic. (gdb-goto-breakpoint): Remove 'display-buffer' call and don't set 'gdb-source-buffer' anymore. * lisp/progmodes/gud.el (gud-display-line): If used by gdb-mi, use 'gdb-display-source-buffer' rather than 'display-buffer'. Don't set 'gdb-source-buffer' anymore. diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 8a05680c74..77a0e807c2 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -1022,6 +1022,14 @@ is the relevant buffer type, such as @samp{breakpoints}. You can do the same with the menu bar, with the @samp{GDB-Windows} and @samp{GDB-Frames} sub-menus of the @samp{GUD} menu. +@vindex gdb-max-source-window-count +@vindex gdb-display-source-buffer-action +By default, GDB uses at most one window to display the source file. +You can make it use more windows by customizing +@code{gdb-max-source-window-count}. You can also customize +@code{gdb-display-source-buffer-action} to control how GDB displays +source files. + When you finish debugging, kill the GUD interaction buffer with @kbd{C-x k}, which will also kill all the buffers associated with the session. However you need not do this if, after editing and diff --git a/etc/NEWS b/etc/NEWS index 81a70e9a97..1af368caa6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -233,6 +233,12 @@ will remember the window configuration before GDB started and restore it after GDB quits. A toggle button is also provided under 'Gud -- GDB-Windows'. ++++ +*** gdb-mi now has a better logic for displaying source buffers +Now GDB only uses one source window to display source file by default. +Customize 'gdb-max-source-window-count' to use more than one window. +Control source file display by 'gdb-display-source-buffer-action'. + ** Gravatar --- diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 07506834f1..ba586981de 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -224,7 +224,9 @@ Only used for files that Emacs can't find.") (defvar gdb-source-file-list nil "List of source files for the current executable.") (defvar gdb-first-done-or-error t) -(defvar gdb-source-window nil) +(defvar gdb-source-window-list nil + "List of windows used for displaying source files. +Sorted in most-recently-visited-first order.") (defvar gdb-inferior-status nil) (defvar gdb-continuation nil) (defvar gdb-supports-non-stop nil) @@ -645,6 +647,21 @@ Note that this variable only takes effect when variable :group 'gdb :version "28.1") +(defcustom gdb-display-source-buffer-action '(nil . ((inhibit-same-window . t))) + "`display-buffer' action used when GDB displays a source buffer." + :type 'list + :group 'gdb + :version "28.1") + +(defcustom gdb-max-source-window-count 1 + "Maximum number of source windows to use. +Until there are such number of source windows on screen, GDB +tries to open a new window when visiting a new source file; after +that GDB starts to reuse existing source windows." + :type 'number + :group 'gdb + :version "28.1") + (defvar gdbmi-debug-mode nil "When non-nil, print the messages sent/received from GDB/MI in *Messages*.") @@ -984,7 +1001,7 @@ detailed description of this mode. gdb-first-done-or-error t gdb-buffer-fringe-width (car (window-fringes)) gdb-debug-log nil - gdb-source-window nil + gdb-source-window-list nil gdb-inferior-status nil gdb-continuation nil gdb-buf-publisher '() @@ -2070,17 +2087,36 @@ is running." ;; GDB frame (after up, down etc). If no GDB frame is visible but the last ;; visited breakpoint is, use that window. (defun gdb-display-source-buffer (buffer) - (let* ((last-window (if gud-last-last-frame - (get-buffer-window - (gud-find-file (car gud-last-last-frame))))) - (source-window (or last-window - (if (and gdb-source-window - (window-live-p gdb-source-window)) - gdb-source-window)))) - (when source-window - (setq gdb-source-window source-window) - (set-window-buffer source-window buffer)) - source-window)) + "Find a window to display BUFFER. +Always find a window to display buffer, and return it." + ;; This function doesn't take care of setting up source window(s) at startup, + ;; that's handled by `gdb-setup-windows' (if `gdb-many-windows' is non-nil). + ;; If `buffer' is already shown in a window, use that window. + (or (get-buffer-window buffer) + (progn + ;; First, update the window list. + (setq gdb-source-window-list + (cl-remove-duplicates + (cl-remove-if-not + (lambda (win) + (and (window-live-p win) + (eq (window-frame win) + (selected-frame)))) + gdb-source-window-list))) + ;; Should we create a new window or reuse one? + (if (> gdb-max-source-window-count + (length gdb-source-window-list)) + ;; Create a new window, push it to window list and return it. + (car (push (display-buffer buffer gdb-display-source-buffer-action) + gdb-source-window-list)) + ;; Reuse a window, we use the oldest window and put that to + ;; the front of the window list. + (let ((last-win (car (last gdb-source-window-list))) + (rest (butlast gdb-source-window-list))) + (set-window-buffer last-win buffer) + (setq gdb-source-window-list + (cons last-win rest)) + last-win))))) (defun gdbmi-start-with (str offset match) @@ -4071,9 +4107,7 @@ DOC is an optional documentation string." (let* ((buffer (find-file-noselect (if (file-exists-p file) file (cdr (assoc bptno gdb-location-alist))))) - (window (or (gdb-display-source-buffer buffer) - (display-buffer buffer)))) - (setq gdb-source-window window) + (window (gdb-display-source-buffer buffer))) (with-current-buffer buffer (goto-char (point-min)) (forward-line (1- (string-to-number line))) @@ -4722,7 +4756,7 @@ file\" where the GDB session starts (see `gdb-main-file')." (select-window win2) (set-window-buffer win2 (or (gdb-get-source-buffer) (list-buffers-noselect))) - (setq gdb-source-window (selected-window)) + (setq gdb-source-window-list (list (selected-window))) (let ((win4 (split-window-right))) (gdb-set-window-buffer (gdb-get-buffer-create 'gdb-inferior-io) nil win4)) @@ -4798,7 +4832,8 @@ You can later restore this configuration from that file by (error "Unrecognized gdb buffer mode: %s" major-mode))) ;; Command buffer. ((derived-mode-p 'gud-mode) 'command) - ((equal (selected-window) gdb-source-window) 'source))) + ;; Consider everything else as source buffer. + (t 'source))) (with-window-non-dedicated nil (set-window-buffer nil placeholder) (set-window-prev-buffers (selected-window) nil) @@ -4841,7 +4876,7 @@ FILE should be a window configuration file saved by (pcase buffer-type ('source (when source-buffer (set-window-buffer nil source-buffer) - (setq gdb-source-window (selected-window)))) + (push (selected-window) gdb-source-window-list))) ('command (switch-to-buffer gud-comint-buffer)) (_ (let ((buffer (gdb-get-buffer-create buffer-type))) (with-window-non-dedicated nil @@ -4882,7 +4917,7 @@ This arrangement depends on the values of variable (if gud-last-last-frame (gud-find-file (car gud-last-last-frame)) (gud-find-file gdb-main-file))) - (setq gdb-source-window win))))) + (setq gdb-source-window-list (list win)))))) ;; Called from `gud-sentinel' in gud.el: (defun gdb-reset () diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 567f452b93..eb43e8b7e4 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -2826,9 +2826,13 @@ Obeying it means displaying in another window the specified file and line." (buffer (with-current-buffer gud-comint-buffer (gud-find-file true-file))) - (window (and buffer - (or (get-buffer-window buffer) - (display-buffer buffer '(nil (inhibit-same-window . t)))))) + (window + (when buffer + (if (eq gud-minor-mode 'gdbmi) + (gdb-display-source-buffer buffer) + ;; Gud still has the old behavior. + (or (get-buffer-window buffer) + (display-buffer buffer '(nil (inhibit-same-window . t))))))) (pos)) (when buffer (with-current-buffer buffer @@ -2858,9 +2862,7 @@ Obeying it means displaying in another window the specified file and line." (widen) (goto-char pos)))) (when window - (set-window-point window gud-overlay-arrow-position) - (if (eq gud-minor-mode 'gdbmi) - (setq gdb-source-window window)))))) + (set-window-point window gud-overlay-arrow-position))))) ;; The gud-call function must do the right thing whether its invoking ;; keystroke is from the GUD buffer itself (via major-mode binding) commit 981cea9b624f61de3bc84226d19303ff3f8cbd8b Author: Martin Rudalics Date: Mon Apr 6 09:46:24 2020 +0200 Fix problems when dragging frames with the mouse Re-implement 'mouse-drag-frame' via two new functions - 'mouse-drag-frame-resize' and 'mouse-drag-frame-move'. This is needed because with some toolkits the notifications for frame movement and resizing arrive asynchronously, breaking any calculations using intermediate frame sizes and positions. * lisp/mouse.el (mouse-drag-mode-line, mouse-drag-left-edge) (mouse-drag-top-left-corner, mouse-drag-top-edge) (mouse-drag-top-right-corner, mouse-drag-right-edge) (mouse-drag-bottom-right-corner, mouse-drag-bottom-edge) (mouse-drag-bottom-left-corner): Call 'mouse-drag-frame-resize' instead of 'mouse-drag-frame'. (mouse-drag-frame): Split into two new functions - 'mouse-drag-frame-move' and 'mouse-drag-frame-resize'. (mouse-drag-frame-resize, mouse-drag-frame-move): New functions to implement functionality of the removed 'mouse-drag-frame'. diff --git a/lisp/mouse.el b/lisp/mouse.el index e58a2e6da1..9703d957d5 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -552,7 +552,7 @@ frame instead." (not (eq (window-frame minibuffer-window) frame)))) ;; Drag frame when the window is on the bottom of its frame and ;; there is no minibuffer window below. - (mouse-drag-frame start-event 'move))))) + (mouse-drag-frame-move start-event))))) (defun mouse-drag-header-line (start-event) "Change the height of a window by dragging on its header line. @@ -569,7 +569,7 @@ the frame instead." (mouse-drag-line start-event 'header) (let ((frame (window-frame window))) (when (frame-parameter frame 'drag-with-header-line) - (mouse-drag-frame start-event 'move)))))) + (mouse-drag-frame-move start-event)))))) (defun mouse-drag-vertical-line (start-event) "Change the width of a window by dragging on a vertical line. @@ -577,46 +577,7 @@ START-EVENT is the starting mouse event of the drag action." (interactive "e") (mouse-drag-line start-event 'vertical)) -(defun mouse-resize-frame (frame x-diff y-diff &optional x-move y-move) - "Helper function for `mouse-drag-frame'." - (let* ((frame-x-y (frame-position frame)) - (frame-x (car frame-x-y)) - (frame-y (cdr frame-x-y)) - alist) - (if (> x-diff 0) - (when x-move - (setq x-diff (min x-diff frame-x)) - (setq x-move (- frame-x x-diff))) - (let* ((min-width (frame-windows-min-size frame t nil t)) - (min-diff (max 0 (- (frame-inner-width frame) min-width)))) - (setq x-diff (max x-diff (- min-diff))) - (when x-move - (setq x-move (+ frame-x (- x-diff)))))) - - (if (> y-diff 0) - (when y-move - (setq y-diff (min y-diff frame-y)) - (setq y-move (- frame-y y-diff))) - (let* ((min-height (frame-windows-min-size frame nil nil t)) - (min-diff (max 0 (- (frame-inner-height frame) min-height)))) - (setq y-diff (max y-diff (- min-diff))) - (when y-move - (setq y-move (+ frame-y (- y-diff)))))) - - (unless (zerop x-diff) - (when x-move - (push `(left . ,x-move) alist)) - (push `(width . (text-pixels . ,(+ (frame-text-width frame) x-diff))) - alist)) - (unless (zerop y-diff) - (when y-move - (push `(top . ,y-move) alist)) - (push `(height . (text-pixels . ,(+ (frame-text-height frame) y-diff))) - alist)) - (when alist - (modify-frame-parameters frame alist)))) - -(defun mouse-drag-frame (start-event part) +(defun mouse-drag-frame-resize (start-event part) "Drag a frame or one of its edges with the mouse. START-EVENT is the starting mouse event of the drag action. Its position window denotes the frame that will be dragged. @@ -635,9 +596,144 @@ frame with the mouse." (frame (if (window-live-p window) (window-frame window) window)) - (width (frame-native-width frame)) - (height (frame-native-height frame)) - ;; PARENT is the parent frame of FRAME or, if FRAME is a + ;; Initial "first" frame position and size. While dragging we + ;; base all calculations against that size and position. + (first-pos (frame-position frame)) + (first-left (car first-pos)) + (first-top (cdr first-pos)) + (first-width (frame-text-width frame)) + (first-height (frame-text-height frame)) + ;; Don't let FRAME become less large than the size needed to + ;; fit all of its windows. + (min-text-width + (+ (frame-windows-min-size frame t nil t) + (- (frame-inner-width frame) first-width))) + (min-text-height + (+ (frame-windows-min-size frame nil nil t) + (- (frame-inner-height frame) first-height))) + ;; PARENT is the parent frame of FRAME or, if FRAME is a + ;; top-level frame, FRAME's workarea. + (parent (frame-parent frame)) + (parent-edges + (if parent + (frame-edges parent) + (let* ((attributes + (car (display-monitor-attributes-list))) + (workarea (assq 'workarea attributes))) + (and workarea + `(,(nth 1 workarea) ,(nth 2 workarea) + ,(+ (nth 1 workarea) (nth 3 workarea)) + ,(+ (nth 2 workarea) (nth 4 workarea))))))) + (parent-left (and parent-edges (nth 0 parent-edges))) + (parent-top (and parent-edges (nth 1 parent-edges))) + (parent-right (and parent-edges (nth 2 parent-edges))) + (parent-bottom (and parent-edges (nth 3 parent-edges))) + ;; Drag types. drag-left/drag-right and drag-top/drag-bottom + ;; are mutually exclusive. + (drag-left (memq part '(bottom-left left top-left))) + (drag-top (memq part '(top-left top top-right))) + (drag-right (memq part '(top-right right bottom-right))) + (drag-bottom (memq part '(bottom-right bottom bottom-left))) + ;; Initial "first" mouse position. While dragging we base all + ;; calculations against that position. + (first-x-y (mouse-absolute-pixel-position)) + (first-x (car first-x-y)) + (first-y (cdr first-x-y)) + (exitfun nil) + (move + (lambda (event) + (interactive "e") + (when (consp event) + (let* ((last-x-y (mouse-absolute-pixel-position)) + (last-x (car last-x-y)) + (last-y (cdr last-x-y)) + (left (- last-x first-x)) + (top (- last-y first-y)) + alist) + ;; We never want to warp the mouse position here. When + ;; moving the mouse leftward or upward, then with a wide + ;; border the calculated left or top position of the + ;; frame could drop to a value less than zero depending + ;; on where precisely the mouse within the border. We + ;; guard against this by never allowing the frame to + ;; move to a position less than zero here. No such + ;; precautions are used for the right and bottom borders + ;; so with a large internal border parts of that border + ;; may disappear. + (when (and drag-left (>= last-x parent-left) + (>= (- first-width left) min-text-width)) + (push `(left . ,(max (+ first-left left) 0)) alist) + (push `(width . (text-pixels . ,(- first-width left))) + alist)) + (when (and drag-top (>= last-y parent-top) + (>= (- first-height top) min-text-height)) + (push `(top . ,(max 0 (+ first-top top))) alist) + (push `(height . (text-pixels . ,(- first-height top))) + alist)) + (when (and drag-right (<= last-x parent-right) + (>= (+ first-width left) min-text-width)) + (push `(width . (text-pixels . ,(+ first-width left))) + alist)) + (when (and drag-bottom (<= last-y parent-bottom) + (>= (+ first-height top) min-text-height)) + (push `(height . (text-pixels . ,(+ first-height top))) + alist)) + (modify-frame-parameters frame alist))))) + (old-track-mouse track-mouse)) + ;; Start tracking. The special value 'dragging' signals the + ;; display engine to freeze the mouse pointer shape for as long + ;; as we drag. + (setq track-mouse 'dragging) + ;; Loop reading events and sampling the position of the mouse. + (setq exitfun + (set-transient-map + (let ((map (make-sparse-keymap))) + (define-key map [switch-frame] #'ignore) + (define-key map [select-window] #'ignore) + (define-key map [scroll-bar-movement] #'ignore) + (define-key map [mouse-movement] move) + ;; Swallow drag-mouse-1 events to avoid selecting some other window. + (define-key map [drag-mouse-1] + (lambda () (interactive) (funcall exitfun))) + ;; Some of the events will of course end up looked up + ;; with a mode-line, header-line or vertical-line prefix ... + (define-key map [mode-line] map) + (define-key map [header-line] map) + (define-key map [vertical-line] map) + ;; ... and some maybe even with a right- or bottom-divider + ;; prefix. + (define-key map [right-divider] map) + (define-key map [bottom-divider] map) + map) + t (lambda () (setq track-mouse old-track-mouse)))))) + +(defun mouse-drag-frame-move (start-event) + "Drag a frame or one of its edges with the mouse. +START-EVENT is the starting mouse event of the drag action. Its +position window denotes the frame that will be dragged. + +PART specifies the part that has been dragged and must be one of +the symbols `left', `top', `right', `bottom', `top-left', +`top-right', `bottom-left', `bottom-right' to drag an internal +border or edge. If PART equals `move', this means to move the +frame with the mouse." + ;; Give temporary modes such as isearch a chance to turn off. + (run-hooks 'mouse-leave-buffer-hook) + (let* ((echo-keystrokes 0) + (start (event-start start-event)) + (window (posn-window start)) + ;; FRAME is the frame to drag. + (frame (if (window-live-p window) + (window-frame window) + window)) + (native-width (frame-native-width frame)) + (native-height (frame-native-height frame)) + ;; Initial "first" frame position and size. While dragging we + ;; base all calculations against that size and position. + (first-pos (frame-position frame)) + (first-left (car first-pos)) + (first-top (cdr first-pos)) + ;; PARENT is the parent frame of FRAME or, if FRAME is a ;; top-level frame, FRAME's workarea. (parent (frame-parent frame)) (parent-edges @@ -654,19 +750,16 @@ frame with the mouse." (parent-top (and parent-edges (nth 1 parent-edges))) (parent-right (and parent-edges (nth 2 parent-edges))) (parent-bottom (and parent-edges (nth 3 parent-edges))) - ;; `pos-x' and `pos-y' record the x- and y-coordinates of the - ;; last sampled mouse position. Note that we sample absolute - ;; mouse positions to avoid that moving the mouse from one - ;; frame into another gets into our way. `last-x' and `last-y' - ;; records the x- and y-coordinates of the previously sampled - ;; position. The differences between `last-x' and `pos-x' as - ;; well as `last-y' and `pos-y' determine the amount the mouse - ;; has been dragged between the last two samples. - pos-x-y pos-x pos-y - (last-x-y (mouse-absolute-pixel-position)) - (last-x (car last-x-y)) - (last-y (cdr last-x-y)) - ;; `snap-x' and `snap-y' record the x- and y-coordinates of the + ;; Initial "first" mouse position. While dragging we base all + ;; calculations against that position. + (first-x-y (mouse-absolute-pixel-position)) + (first-x (car first-x-y)) + (first-y (cdr first-x-y)) + ;; `snap-width' (maybe also a yet to be provided `snap-height') + ;; could become floats to handle proportionality wrt PARENT. + ;; We don't do any checks on this parameter so far. + (snap-width (frame-parameter frame 'snap-width)) + ;; `snap-x' and `snap-y' record the x- and y-coordinates of the ;; mouse position when FRAME snapped. As soon as the ;; difference between `pos-x' and `snap-x' (or `pos-y' and ;; `snap-y') exceeds the value of FRAME's `snap-width' @@ -678,176 +771,141 @@ frame with the mouse." (lambda (event) (interactive "e") (when (consp event) - (setq pos-x-y (mouse-absolute-pixel-position)) - (setq pos-x (car pos-x-y)) - (setq pos-y (cdr pos-x-y)) - (cond - ((eq part 'left) - (mouse-resize-frame frame (- last-x pos-x) 0 t)) - ((eq part 'top) - (mouse-resize-frame frame 0 (- last-y pos-y) nil t)) - ((eq part 'right) - (mouse-resize-frame frame (- pos-x last-x) 0)) - ((eq part 'bottom) - (mouse-resize-frame frame 0 (- pos-y last-y))) - ((eq part 'top-left) - (mouse-resize-frame - frame (- last-x pos-x) (- last-y pos-y) t t)) - ((eq part 'top-right) - (mouse-resize-frame - frame (- pos-x last-x) (- last-y pos-y) nil t)) - ((eq part 'bottom-left) - (mouse-resize-frame - frame (- last-x pos-x) (- pos-y last-y) t)) - ((eq part 'bottom-right) - (mouse-resize-frame - frame (- pos-x last-x) (- pos-y last-y))) - ((eq part 'move) - (let* ((old-position (frame-position frame)) - (old-left (car old-position)) - (old-top (cdr old-position)) - (left (+ old-left (- pos-x last-x))) - (top (+ old-top (- pos-y last-y))) - right bottom - ;; `snap-width' (maybe also a yet to be provided - ;; `snap-height') could become floats to handle - ;; proportionality wrt PARENT. We don't do any - ;; checks on this parameter so far. - (snap-width (frame-parameter frame 'snap-width))) - ;; Docking and constraining. - (when (and (numberp snap-width) parent-edges) + (let* ((last-x-y (mouse-absolute-pixel-position)) + (last-x (car last-x-y)) + (last-y (cdr last-x-y)) + (left (- last-x first-x)) + (top (- last-y first-y)) + right bottom) + (setq left (+ first-left left)) + (setq top (+ first-top top)) + ;; Docking and constraining. + (when (and (numberp snap-width) parent-edges) + (cond + ;; Docking at the left parent edge. + ((< last-x first-x) (cond - ;; Docking at the left parent edge. - ((< pos-x last-x) - (cond - ((and (> left parent-left) - (<= (- left parent-left) snap-width)) - ;; Snap when the mouse moved leftward and - ;; FRAME's left edge would end up within - ;; `snap-width' pixels from PARENT's left edge. - (setq snap-x pos-x) - (setq left parent-left)) - ((and (<= left parent-left) - (<= (- parent-left left) snap-width) - snap-x (<= (- snap-x pos-x) snap-width)) - ;; Stay snapped when the mouse moved leftward - ;; but not more than `snap-width' pixels from - ;; the time FRAME snapped. - (setq left parent-left)) - (t - ;; Unsnap when the mouse moved more than - ;; `snap-width' pixels leftward from the time - ;; FRAME snapped. - (setq snap-x nil)))) - ((> pos-x last-x) - (setq right (+ left width)) - (cond - ((and (< right parent-right) - (<= (- parent-right right) snap-width)) - ;; Snap when the mouse moved rightward and - ;; FRAME's right edge would end up within - ;; `snap-width' pixels from PARENT's right edge. - (setq snap-x pos-x) - (setq left (- parent-right width))) - ((and (>= right parent-right) - (<= (- right parent-right) snap-width) - snap-x (<= (- pos-x snap-x) snap-width)) - ;; Stay snapped when the mouse moved rightward - ;; but not more more than `snap-width' pixels - ;; from the time FRAME snapped. - (setq left (- parent-right width))) - (t - ;; Unsnap when the mouse moved rightward more - ;; than `snap-width' pixels from the time FRAME - ;; snapped. - (setq snap-x nil))))) - + ((and (> left parent-left) + (<= (- left parent-left) snap-width)) + ;; Snap when the mouse moved leftward and FRAME's + ;; left edge would end up within `snap-width' + ;; pixels from PARENT's left edge. + (setq snap-x last-x) + (setq left parent-left)) + ((and (<= left parent-left) + (<= (- parent-left left) snap-width) + snap-x (<= (- snap-x last-x) snap-width)) + ;; Stay snapped when the mouse moved leftward but + ;; not more than `snap-width' pixels from the time + ;; FRAME snapped. + (setq left parent-left)) + (t + ;; Unsnap when the mouse moved more than + ;; `snap-width' pixels leftward from the time + ;; FRAME snapped. + (setq snap-x nil)))) + ((> last-x first-x) + (setq right (+ left native-width)) (cond - ((< pos-y last-y) - (cond - ((and (> top parent-top) - (<= (- top parent-top) snap-width)) - ;; Snap when the mouse moved upward and FRAME's - ;; top edge would end up within `snap-width' - ;; pixels from PARENT's top edge. - (setq snap-y pos-y) - (setq top parent-top)) - ((and (<= top parent-top) - (<= (- parent-top top) snap-width) - snap-y (<= (- snap-y pos-y) snap-width)) - ;; Stay snapped when the mouse moved upward but - ;; not more more than `snap-width' pixels from - ;; the time FRAME snapped. - (setq top parent-top)) - (t - ;; Unsnap when the mouse moved upward more than - ;; `snap-width' pixels from the time FRAME - ;; snapped. - (setq snap-y nil)))) - ((> pos-y last-y) - (setq bottom (+ top height)) - (cond - ((and (< bottom parent-bottom) - (<= (- parent-bottom bottom) snap-width)) - ;; Snap when the mouse moved downward and - ;; FRAME's bottom edge would end up within - ;; `snap-width' pixels from PARENT's bottom - ;; edge. - (setq snap-y pos-y) - (setq top (- parent-bottom height))) - ((and (>= bottom parent-bottom) - (<= (- bottom parent-bottom) snap-width) - snap-y (<= (- pos-y snap-y) snap-width)) - ;; Stay snapped when the mouse moved downward - ;; but not more more than `snap-width' pixels - ;; from the time FRAME snapped. - (setq top (- parent-bottom height))) - (t - ;; Unsnap when the mouse moved downward more - ;; than `snap-width' pixels from the time FRAME - ;; snapped. - (setq snap-y nil)))))) - - ;; If requested, constrain FRAME's draggable areas to - ;; PARENT's edges. The `top-visible' parameter should - ;; be set when FRAME has a draggable header-line. If - ;; set to a number, it ascertains that the top of - ;; FRAME is always constrained to the top of PARENT - ;; and that at least as many pixels of FRAME as - ;; specified by that number are visible on each of the - ;; three remaining sides of PARENT. - ;; - ;; The `bottom-visible' parameter should be set when - ;; FRAME has a draggable mode-line. If set to a - ;; number, it ascertains that the bottom of FRAME is - ;; always constrained to the bottom of PARENT and that - ;; at least as many pixels of FRAME as specified by - ;; that number are visible on each of the three - ;; remaining sides of PARENT. - (let ((par (frame-parameter frame 'top-visible)) - bottom-visible) - (unless par - (setq par (frame-parameter frame 'bottom-visible)) - (setq bottom-visible t)) - (when (and (numberp par) parent-edges) - (setq left - (max (min (- parent-right par) left) - (+ (- parent-left width) par))) - (setq top - (if bottom-visible - (min (max top (- parent-top (- height par))) - (- parent-bottom height)) - (min (max top parent-top) - (- parent-bottom par)))))) - - ;; Use `modify-frame-parameters' since `left' and - ;; `top' may want to move FRAME out of its PARENT. - (modify-frame-parameters - frame - `((left . (+ ,left)) (top . (+ ,top))))))) - (setq last-x pos-x) - (setq last-y pos-y)))) - (old-track-mouse track-mouse)) + ((and (< right parent-right) + (<= (- parent-right right) snap-width)) + ;; Snap when the mouse moved rightward and FRAME's + ;; right edge would end up within `snap-width' + ;; pixels from PARENT's right edge. + (setq snap-x last-x) + (setq left (- parent-right native-width))) + ((and (>= right parent-right) + (<= (- right parent-right) snap-width) + snap-x (<= (- last-x snap-x) snap-width)) + ;; Stay snapped when the mouse moved rightward but + ;; not more more than `snap-width' pixels from the + ;; time FRAME snapped. + (setq left (- parent-right native-width))) + (t + ;; Unsnap when the mouse moved rightward more than + ;; `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-x nil))))) + (cond + ((< last-y first-y) + (cond + ((and (> top parent-top) + (<= (- top parent-top) snap-width)) + ;; Snap when the mouse moved upward and FRAME's + ;; top edge would end up within `snap-width' + ;; pixels from PARENT's top edge. + (setq snap-y last-y) + (setq top parent-top)) + ((and (<= top parent-top) + (<= (- parent-top top) snap-width) + snap-y (<= (- snap-y last-y) snap-width)) + ;; Stay snapped when the mouse moved upward but + ;; not more more than `snap-width' pixels from the + ;; time FRAME snapped. + (setq top parent-top)) + (t + ;; Unsnap when the mouse moved upward more than + ;; `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-y nil)))) + ((> last-y first-y) + (setq bottom (+ top native-height)) + (cond + ((and (< bottom parent-bottom) + (<= (- parent-bottom bottom) snap-width)) + ;; Snap when the mouse moved downward and FRAME's + ;; bottom edge would end up within `snap-width' + ;; pixels from PARENT's bottom edge. + (setq snap-y last-y) + (setq top (- parent-bottom native-height))) + ((and (>= bottom parent-bottom) + (<= (- bottom parent-bottom) snap-width) + snap-y (<= (- last-y snap-y) snap-width)) + ;; Stay snapped when the mouse moved downward but + ;; not more more than `snap-width' pixels from the + ;; time FRAME snapped. + (setq top (- parent-bottom native-height))) + (t + ;; Unsnap when the mouse moved downward more than + ;; `snap-width' pixels from the time FRAME + ;; snapped. + (setq snap-y nil)))))) + + ;; If requested, constrain FRAME's draggable areas to + ;; PARENT's edges. The `top-visible' parameter should + ;; be set when FRAME has a draggable header-line. If + ;; set to a number, it ascertains that the top of FRAME + ;; is always constrained to the top of PARENT and that + ;; at least as many pixels of FRAME as specified by that + ;; number are visible on each of the three remaining + ;; sides of PARENT. + ;; + ;; The `bottom-visible' parameter should be set when + ;; FRAME has a draggable mode-line. If set to a number, + ;; it ascertains that the bottom of FRAME is always + ;; constrained to the bottom of PARENT and that at least + ;; as many pixels of FRAME as specified by that number + ;; are visible on each of the three remaining sides of + ;; PARENT. + (let ((par (frame-parameter frame 'top-visible)) + bottom-visible) + (unless par + (setq par (frame-parameter frame 'bottom-visible)) + (setq bottom-visible t)) + (when (and (numberp par) parent-edges) + (setq left + (max (min (- parent-right par) left) + (+ (- parent-left native-width) par))) + (setq top + (if bottom-visible + (min (max top (- parent-top (- native-height par))) + (- parent-bottom native-height)) + (min (max top parent-top) + (- parent-bottom par)))))) + ;; Use `modify-frame-parameters' since `left' and `top' + ;; may want to move FRAME out of its PARENT. + (modify-frame-parameters frame `((left . (+ ,left)) (top . (+ ,top)))))))) + (old-track-mouse track-mouse)) ;; Start tracking. The special value 'dragging' signals the ;; display engine to freeze the mouse pointer shape for as long ;; as we drag. @@ -879,49 +937,49 @@ frame with the mouse." "Drag left edge of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'left)) + (mouse-drag-frame-resize start-event 'left)) (defun mouse-drag-top-left-corner (start-event) "Drag top left corner of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'top-left)) + (mouse-drag-frame-resize start-event 'top-left)) (defun mouse-drag-top-edge (start-event) "Drag top edge of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'top)) + (mouse-drag-frame-resize start-event 'top)) (defun mouse-drag-top-right-corner (start-event) "Drag top right corner of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'top-right)) + (mouse-drag-frame-resize start-event 'top-right)) (defun mouse-drag-right-edge (start-event) "Drag right edge of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'right)) + (mouse-drag-frame-resize start-event 'right)) (defun mouse-drag-bottom-right-corner (start-event) "Drag bottom right corner of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'bottom-right)) + (mouse-drag-frame-resize start-event 'bottom-right)) (defun mouse-drag-bottom-edge (start-event) "Drag bottom edge of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'bottom)) + (mouse-drag-frame-resize start-event 'bottom)) (defun mouse-drag-bottom-left-corner (start-event) "Drag bottom left corner of a frame with the mouse. START-EVENT is the starting mouse event of the drag action." (interactive "e") - (mouse-drag-frame start-event 'bottom-left)) + (mouse-drag-frame-resize start-event 'bottom-left)) (defcustom mouse-select-region-move-to-beginning nil "Effect of selecting a region extending backward from double click. commit 24c3fa96077a5fec6d8ba65d7c49ff1a731be32f Author: Paul Eggert Date: Sun Apr 5 10:45:09 2020 -0700 * src/coding.c (code_convert_string): Fix type mismatches. diff --git a/src/coding.c b/src/coding.c index 97a6eb949a..49c1e625d5 100644 --- a/src/coding.c +++ b/src/coding.c @@ -9524,8 +9524,8 @@ code_convert_string (Lisp_Object string, Lisp_Object coding_system, return (nocopy ? string : (encodep - ? make_unibyte_string (SDATA (string), bytes) - : make_multibyte_string (SDATA (string), bytes, bytes))); + ? make_unibyte_string (SSDATA (string), bytes) + : make_multibyte_string (SSDATA (string), bytes, bytes))); } else if (BUFFERP (dst_object)) { commit 507f26d532aaf9db4622c42eec1f89466fb5c724 Author: Eli Zaretskii Date: Sun Apr 5 19:51:09 2020 +0300 Fix a recent change in bignum.c * src/bignum.c (check_int_nonnegative): Fix a recent change. Reported by Glenn Morris . diff --git a/src/bignum.c b/src/bignum.c index 859896cdcf..669df4d9ee 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -465,5 +465,5 @@ int check_int_nonnegative (Lisp_Object x) { CHECK_INTEGER (x); - return Fnatnump (x) ? check_integer_range (x, 0, INT_MAX) : 0; + return NILP (Fnatnump (x)) ? 0 : check_integer_range (x, 0, INT_MAX); } commit c40b72389e4a807cb1231eb9341fadbd1eca88c5 Author: Michael Albinus Date: Sun Apr 5 18:29:10 2020 +0200 Fix thinko in tramp-cache.el * lisp/net/tramp-cache.el (tramp-set-connection-property) (tramp-flush-connection-property) (tramp-flush-connection-properties): Use `tramp-file-name-p'. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 93eeb16f54..09e30f000f 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -339,7 +339,7 @@ Return VALUE." (when-let ((hash (tramp-get-hash-table key))) (puthash property value hash)) (setq tramp-cache-data-changed - (or tramp-cache-data-changed (tramp-tramp-file-p key))) + (or tramp-cache-data-changed (tramp-file-name-p key))) (tramp-message key 7 "%s %s" property value) value) @@ -368,7 +368,7 @@ PROPERTY is set persistent when KEY is a `tramp-file-name' structure." (when-let ((hash (tramp-get-hash-table key))) (remhash property hash)) (setq tramp-cache-data-changed - (or tramp-cache-data-changed (tramp-tramp-file-p key))) + (or tramp-cache-data-changed (tramp-file-name-p key))) (tramp-message key 7 "%s" property)) ;;;###tramp-autoload @@ -388,7 +388,7 @@ used to cache connection properties of the local machine." (when-let ((hash (gethash key tramp-cache-data))) (hash-table-keys hash))) (setq tramp-cache-data-changed - (or tramp-cache-data-changed (tramp-tramp-file-p key))) + (or tramp-cache-data-changed (tramp-file-name-p key))) (remhash key tramp-cache-data)) ;;;###tramp-autoload commit 333f63d53706de9d1a1dbc04ed62f9dc0e9698db Merge: 0e18fdd1b6 6de20c7eab Author: Glenn Morris Date: Sun Apr 5 07:50:15 2020 -0700 Merge from origin/emacs-27 6de20c7eab (origin/emacs-27) Fix syntax error in man page. f8607d3c03 Handle filling of indented ChangeLog function entries 7e78f0d1b2 Fix void-variable n-reb in re-builder (Bug#40409) 452d776a5d Fix small bug in copy_string_contents. fa823653ff Fix invocations of gpg from Gnus d4f51d0a2e Don't draw GTK's internal border and tab bar on top of eac... 38731d504e ; * src/buffer.c (syms_of_buffer) : Doc... 44ac9e48bb Tweak htmlfontify's generated output commit 0e18fdd1b6e86b8b9704e3a73204f94682ee9450 Merge: 94b6b0b5c5 b2f2d0d2c4 Author: Glenn Morris Date: Sun Apr 5 07:50:15 2020 -0700 ; Merge from origin/emacs-27 The following commit was skipped: b2f2d0d2c4 (emacs-27) ; Auto-commit of loaddefs files. commit 94b6b0b5c5544d46a89915c94a83e2f4a224d044 Merge: a32c55bd9f ac3da1dd96 Author: Glenn Morris Date: Sun Apr 5 07:50:15 2020 -0700 Merge from origin/emacs-27 ac3da1dd96 Handle project--files-in-directory finding no files better 650a664ccd Let imenu to work on the menu bar when its list is a singl... commit a32c55bd9f3aa06b74adc9630b55689972c52356 Author: Stefan Monnier Date: Sun Apr 5 09:54:53 2020 -0400 * lisp/emacs-lisp/cl-macs.el (cl-defstruct): Avoid known cl-defsubst breakage diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 7f5d197b53..45a308ebca 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2970,14 +2970,26 @@ Supported keywords for slots are: (pcase-dolist (`(,cname ,args ,doc) constrs) (let* ((anames (cl--arglist-args args)) (make (cl-mapcar (function (lambda (s d) (if (memq s anames) s d))) - slots defaults))) - (push `(,cldefsym ,cname + slots defaults)) + ;; `cl-defsubst' is fundamentally broken: it substitutes + ;; its arguments into the body's `sexp' much too naively + ;; when inlinling, which results in various problems. + ;; For example it generates broken code if your + ;; argument's name happens to be the same as some + ;; function used within the body. + ;; E.g. (cl-defsubst sm-foo (list) (list list)) + ;; will expand `(sm-foo 1)' to `(1 1)' rather than to `(list t)'! + ;; Try to catch this known case! + (con-fun (or type #'record)) + (unsafe-cl-defsubst + (or (memq con-fun args) (assq con-fun args)))) + (push `(,(if unsafe-cl-defsubst 'cl-defun cldefsym) ,cname (&cl-defs (nil ,@descs) ,@args) ,(if (stringp doc) doc (format "Constructor for objects of type `%s'." name)) ,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs))) '((declare (side-effect-free t)))) - (,(or type #'record) ,@make)) + (,con-fun ,@make)) forms))) (if print-auto (nconc print-func (list '(princ ")" cl-s) t))) ;; Don't bother adding to cl-custom-print-functions since it's not used commit 4ed39549e3f9dbfeb2aea0e2674a7701dbc0e5ea Author: Mattias Engdegård Date: Fri Apr 3 16:01:01 2020 +0200 Avoid expensive recoding for ASCII identity cases (bug#40407) Optimise for the common case of encoding or decoding an ASCII-only string using an ASCII-compatible coding, for file names in particular. * src/coding.c (string_ascii_p): New function. (code_convert_string): Return the input string for ASCII-only inputs and ASCII-compatible codings. * test/src/coding-tests.el (coding-nocopy-ascii): New test. diff --git a/src/coding.c b/src/coding.c index 1049f1b755..97a6eb949a 100644 --- a/src/coding.c +++ b/src/coding.c @@ -9471,6 +9471,17 @@ not fully specified.) */) return code_convert_region (start, end, coding_system, destination, 1, 0); } +/* Whether a string only contains chars in the 0..127 range. */ +static bool +string_ascii_p (Lisp_Object str) +{ + ptrdiff_t nbytes = SBYTES (str); + for (ptrdiff_t i = 0; i < nbytes; i++) + if (SREF (str, i) > 127) + return false; + return true; +} + Lisp_Object code_convert_string (Lisp_Object string, Lisp_Object coding_system, Lisp_Object dst_object, bool encodep, bool nocopy, @@ -9502,7 +9513,21 @@ code_convert_string (Lisp_Object string, Lisp_Object coding_system, chars = SCHARS (string); bytes = SBYTES (string); - if (BUFFERP (dst_object)) + if (EQ (dst_object, Qt)) + { + /* Fast path for ASCII-only input and an ASCII-compatible coding: + act as identity. */ + Lisp_Object attrs = CODING_ID_ATTRS (coding.id); + if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)) + && (STRING_MULTIBYTE (string) + ? (chars == bytes) : string_ascii_p (string))) + return (nocopy + ? string + : (encodep + ? make_unibyte_string (SDATA (string), bytes) + : make_multibyte_string (SDATA (string), bytes, bytes))); + } + else if (BUFFERP (dst_object)) { struct buffer *buf = XBUFFER (dst_object); ptrdiff_t buf_pt = BUF_PT (buf); diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el index 110ff12696..93e6709d44 100644 --- a/test/src/coding-tests.el +++ b/test/src/coding-tests.el @@ -383,6 +383,17 @@ (should-not (eq (encode-coding-string s nil nil) s)) (should (eq (encode-coding-string s nil t) s)))) +(ert-deftest coding-nocopy-ascii () + "Check that the NOCOPY parameter works for ASCII-only strings." + (let* ((uni (apply #'string (number-sequence 0 127))) + (multi (string-to-multibyte uni))) + (dolist (s (list uni multi)) + (dolist (coding '(us-ascii iso-latin-1 utf-8)) + (should-not (eq (decode-coding-string s coding nil) s)) + (should-not (eq (encode-coding-string s coding nil) s)) + (should (eq (decode-coding-string s coding t) s)) + (should (eq (encode-coding-string s coding t) s)))))) + ;; Local Variables: ;; byte-compile-warnings: (not obsolete) ;; End: commit c7ac76603f291d432586abd2eeb75e1ca6e54863 Author: Mattias Engdegård Date: Sun Apr 5 15:13:44 2020 +0200 Suppress relint diagnostics in rx-tests.el * test/lisp/emacs-lisp/rx-tests.el (rx-char-any, rx-any): Suppress relint complaints; these regexps are intentionally bad. diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el index 0fece4004b..0e6f27836e 100644 --- a/test/lisp/emacs-lisp/rx-tests.el +++ b/test/lisp/emacs-lisp/rx-tests.el @@ -63,6 +63,7 @@ (ert-deftest rx-char-any () "Test character alternatives with `]' and `-' (Bug#25123)." (should (equal + ;; relint suppression: Range .<-]. overlaps previous .]-{ (rx string-start (1+ (char (?\] . ?\{) (?< . ?\]) (?- . ?:))) string-end) "\\`[.-:<-{-]+\\'"))) @@ -127,6 +128,10 @@ "[[:lower:][:upper:]-][^[:lower:][:upper:]-]")) (should (equal (rx (any "]" lower upper) (not (any "]" lower upper))) "[][:lower:][:upper:]][^][:lower:][:upper:]]")) + ;; relint suppression: Duplicated character .-. + ;; relint suppression: Single-character range .f-f + ;; relint suppression: Range .--/. overlaps previous .- + ;; relint suppression: Range .\*--. overlaps previous .--/ (should (equal (rx (any "-a" "c-" "f-f" "--/*--")) "[*-/acf]")) (should (equal (rx (any "]-a" ?-) (not (any "]-a" ?-))) @@ -140,6 +145,7 @@ "\\`a\\`[^z-a]")) (should (equal (rx (any "") (not (any ""))) "\\`a\\`[^z-a]")) + ;; relint suppression: Duplicated class .space. (should (equal (rx (any space ?a digit space)) "[a[:space:][:digit:]]")) (should (equal (rx (not "\n") (not ?\n) (not (any "\n")) (not-char ?\n) commit 962562cde45071f74a37854a299e88470a4ecd49 Author: Mattias Engdegård Date: Sun Apr 5 11:27:36 2020 +0200 Fix inverted NOCOPY encode/decode parameter (bug#40407) In {encode,decode}-coding-string, the NOCOPY parameter had the opposite effect to what was intended and documented. This 18 year old bug (introduced in 4031e2bf0a) only affected calls with CODING-SYSTEM being nil. * src/coding.c (code_convert_string): Correct use of NOCOPY. * test/src/coding-tests.el (coding-nocopy-trivial): New test. diff --git a/src/coding.c b/src/coding.c index f0fc37dbdf..1049f1b755 100644 --- a/src/coding.c +++ b/src/coding.c @@ -9485,7 +9485,7 @@ code_convert_string (Lisp_Object string, Lisp_Object coding_system, if (! norecord) Vlast_coding_system_used = Qno_conversion; if (NILP (dst_object)) - return (nocopy ? Fcopy_sequence (string) : string); + return nocopy ? string : Fcopy_sequence (string); } if (NILP (coding_system)) diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el index 094a1fad8f..110ff12696 100644 --- a/test/src/coding-tests.el +++ b/test/src/coding-tests.el @@ -375,6 +375,14 @@ (with-temp-buffer (insert-file-contents (car file)))))) (insert (format "%s: %s\n" (car file) result))))))) +(ert-deftest coding-nocopy-trivial () + "Check that the NOCOPY parameter works for the trivial coding system." + (let ((s "abc")) + (should-not (eq (decode-coding-string s nil nil) s)) + (should (eq (decode-coding-string s nil t) s)) + (should-not (eq (encode-coding-string s nil nil) s)) + (should (eq (encode-coding-string s nil t) s)))) + ;; Local Variables: ;; byte-compile-warnings: (not obsolete) ;; End: commit 6de20c7eab0dd8360e78d744dbf62aecc7f78281 Author: Philipp Stephani Date: Sun Apr 5 10:19:31 2020 +0200 Fix syntax error in man page. * doc/man/emacs.1.in: Fix syntax of --script argument. The Info manual states that --script has to be followed by a space, and the syntax with the equals sign doesn't actually work. diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in index e1190cf460..5a164e98cd 100644 --- a/doc/man/emacs.1.in +++ b/doc/man/emacs.1.in @@ -171,7 +171,7 @@ The editor will send messages to stderr. You must use \-l and \-f options to specify files to execute and functions to call. .TP -.BI \-\-script= "file" +.BI \-\-script " file" Run .I file as an Emacs Lisp script. commit f8607d3c03544afbe32c6bd324c287db305e569e Author: Noam Postavsky Date: Sat Apr 4 12:28:23 2020 -0400 Handle filling of indented ChangeLog function entries * lisp/vc/log-edit.el (log-edit-fill-entry): Relax regexp a bit to recognize function entries with leading blanks. * test/lisp/vc/log-edit-tests.el: New test. diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index d5d46147cf..906f9a9420 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -529,7 +529,7 @@ according to `fill-column'." (and (< beg end) (re-search-forward (concat "\\(?1:" change-log-unindented-file-names-re - "\\)\\|^\\(?1:\\)(") + "\\)\\|^\\(?1:\\)[[:blank:]]*(") end t) (copy-marker (match-end 1))) ;; Fill prose between log entries. diff --git a/test/lisp/vc/log-edit-tests.el b/test/lisp/vc/log-edit-tests.el index bb3f658232..86a40a97b1 100644 --- a/test/lisp/vc/log-edit-tests.el +++ b/test/lisp/vc/log-edit-tests.el @@ -74,6 +74,31 @@ couple of sentences. Long enough to be filled for several lines. \(fun9): Etc.")))) +(ert-deftest log-edit-fill-entry-indented-func-entries () + ;; Indenting function entries is a typical mistake caused by using a + ;; misconfigured or non-ChangeLog specific fill function. + (with-temp-buffer + (insert "\ +* dir/file.ext (fun1): + (fun2): + (fun3): +* file2.txt (fun4): + (fun5): + (fun6): + (fun7): Some prose. + (fun8): A longer description of a complicated change.\ + Spread over a couple of sentences.\ + Long enough to be filled for several lines. + (fun9): Etc.") + (goto-char (point-min)) + (let ((fill-column 72)) (log-edit-fill-entry)) + (should (equal (buffer-string) "\ +* dir/file.ext (fun1, fun2, fun3): +* file2.txt (fun4, fun5, fun6, fun7): Some prose. +\(fun8): A longer description of a complicated change. Spread over a +couple of sentences. Long enough to be filled for several lines. +\(fun9): Etc.")))) + (ert-deftest log-edit-fill-entry-trailing-prose () (with-temp-buffer (insert "\ commit 7e78f0d1b26557b1af95c542cc95cff131c18ec8 Author: Noam Postavsky Date: Sat Apr 4 12:00:41 2020 -0400 Fix void-variable n-reb in re-builder (Bug#40409) * lisp/emacs-lisp/re-builder.el (reb-while): Take the current value of the counter instead of its name. (reb-mark-non-matching-parenthesis): Bind n-reb to 0 at the start and don't wrongly treat it as dynamicly bound. diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el index 580e91483d..0e1618e010 100644 --- a/lisp/emacs-lisp/re-builder.el +++ b/lisp/emacs-lisp/re-builder.el @@ -767,22 +767,21 @@ If SUBEXP is non-nil mark only the corresponding sub-expressions." (reb-mark-non-matching-parenthesis)) nil))) -(defsubst reb-while (limit counter where) - (let ((count (symbol-value counter))) - (if (= count limit) - (progn - (message "Reached (while limit=%s, where=%s)" limit where) - nil) - (set counter (1+ count))))) +(defsubst reb-while (limit current where) + (if (< current limit) + (1+ current) + (message "Reached (while limit=%s, where=%s)" limit where) + nil)) (defun reb-mark-non-matching-parenthesis (bound) ;; We have a small string, check the whole of it, but wait until ;; everything else is fontified. (when (>= bound (point-max)) - (let (left-pars + (let ((n-reb 0) + left-pars faces-here) (goto-char (point-min)) - (while (and (reb-while 100 'n-reb "mark-par") + (while (and (setq n-reb (reb-while 100 n-reb "mark-par")) (not (eobp))) (skip-chars-forward "^()") (unless (eobp) commit 452d776a5da3f25ec1ce3a632c5df8db80b507ef Author: Philipp Stephani Date: Fri Apr 3 21:49:59 2020 +0200 Fix small bug in copy_string_contents. * src/emacs-module.c (module_copy_string_contents): Fix incorrect variable use. In this branch 'lisp_str_utf8' is always nil, so it makes little sense to add it as error data. diff --git a/src/emacs-module.c b/src/emacs-module.c index d56d03203b..911b82b8a1 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -637,7 +637,7 @@ module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer, /* Since we set HANDLE-8-BIT and HANDLE-OVER-UNI to nil, the return value can be nil, and we have to check for that. */ - CHECK_TYPE (!NILP (lisp_str_utf8), Qunicode_string_p, lisp_str_utf8); + CHECK_TYPE (!NILP (lisp_str_utf8), Qunicode_string_p, lisp_str); ptrdiff_t raw_size = SBYTES (lisp_str_utf8); ptrdiff_t required_buf_size = raw_size + 1; commit fa823653ffb0e3e893d30daa5abf68e909934e2e Author: Eli Zaretskii Date: Fri Apr 3 14:29:49 2020 +0300 Fix invocations of gpg from Gnus * lisp/epg-config.el (epg-config--make-gpg-configuration): Bind coding-system-for-read/write to 'undecided', to countermand possible values of 'no-conversion' or somesuch by the callers. (Bug#40248) diff --git a/lisp/epg-config.el b/lisp/epg-config.el index 74ab65113e..daa9a5abd1 100644 --- a/lisp/epg-config.el +++ b/lisp/epg-config.el @@ -183,10 +183,18 @@ version requirement is met." (defun epg-config--make-gpg-configuration (program) (let (config groups type args) (with-temp-buffer - (apply #'call-process program nil (list t nil) nil - (append (if epg-gpg-home-directory - (list "--homedir" epg-gpg-home-directory)) - '("--with-colons" "--list-config"))) + ;; The caller might have bound coding-system-for-* to something + ;; like 'no-conversion, but the below needs to call PROGRAM + ;; expecting human-readable text in both directions (since we + ;; are going to parse the output as text), so let Emacs guess + ;; the encoding of that text by its usual encoding-detection + ;; machinery. + (let ((coding-system-for-read 'undecided) + (coding-system-for-write 'undecided)) + (apply #'call-process program nil (list t nil) nil + (append (if epg-gpg-home-directory + (list "--homedir" epg-gpg-home-directory)) + '("--with-colons" "--list-config")))) (goto-char (point-min)) (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t) (setq type (intern (match-string 1)) commit d4f51d0a2ef0dbba7a798cd7b8b0a791f723bda5 Author: Martin Rudalics Date: Fri Apr 3 10:31:35 2020 +0200 Don't draw GTK's internal border and tab bar on top of each other * src/xterm.c (x_clear_under_internal_border): For GTK builds have 'margin' count in the height of the tab bar to avoid that tab bar and internal border are drawn on top of each other. diff --git a/src/xterm.c b/src/xterm.c index 2ba3c00940..bda976fcbb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1291,11 +1291,7 @@ x_clear_under_internal_border (struct frame *f) int border = FRAME_INTERNAL_BORDER_WIDTH (f); int width = FRAME_PIXEL_WIDTH (f); int height = FRAME_PIXEL_HEIGHT (f); -#ifdef USE_GTK - int margin = 0; -#else int margin = FRAME_TOP_MARGIN_HEIGHT (f); -#endif int face_id = !NILP (Vface_remapping_alist) ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID) commit 38731d504eb4675ff1c8a82f96cb90beced941d3 Author: Eli Zaretskii Date: Fri Apr 3 09:58:20 2020 +0300 ; * src/buffer.c (syms_of_buffer) : Doc fix. diff --git a/src/buffer.c b/src/buffer.c index 5c65d4d4d1..92ed405b6f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -6234,10 +6234,10 @@ Lisp programs may give this variable certain special values: DEFVAR_LISP ("inhibit-read-only", Vinhibit_read_only, doc: /* Non-nil means disregard read-only status of buffers or characters. -If the value is t, disregard `buffer-read-only' and all `read-only' -text properties. If the value is a list, disregard `buffer-read-only' -and disregard a `read-only' text property if the property value -is a member of the list. */); +A non-nil value that is a list means disregard `buffer-read-only' status, +and disregard a `read-only' text property if the property value is a +member of the list. Any other non-nil value means disregard `buffer-read-only' +and all `read-only' text properties. */); Vinhibit_read_only = Qnil; DEFVAR_PER_BUFFER ("cursor-type", &BVAR (current_buffer, cursor_type), Qnil, commit 44ac9e48bbdb9e8546a7cb330ae8875cf093b505 Author: Amin Bandali Date: Thu Apr 2 18:42:41 2020 -0400 Tweak htmlfontify's generated output * lisp/htmlfontify.el (hfy-default-header): declare the character encoding for the generated HTML file. This helps browsers display UTF-8 characters like the copyright symbol correctly. (hfy-sprintf-stylesheet): apply the default style to all of the text consistently, so that unstyled bits (which are not wrapped in span tags and are directly part of the surrounding pre tag's "innerHTML") have a look consistent with the rest of the document. diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el index 152c70a64e..c0012427ae 100644 --- a/lisp/htmlfontify.el +++ b/lisp/htmlfontify.el @@ -628,6 +628,7 @@ STYLE is the inline CSS stylesheet (or tag referring to an external sheet)." \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"> + %s %s