commit 6a788d2fc18c23dcfc5d0352649b2f690e9cbff7 (HEAD, refs/remotes/origin/master) Author: Noam Postavsky Date: Fri Jan 13 19:47:22 2017 -0500 Don't wait for frame to become visible * src/xterm.c (x_make_frame_visible): Remove code that waits for the frame to become visible. We have to deal with invisible frames anyway, the loop could sometimes before the frame turned visible, and for some window managers (e.g., XMonad, i3wm) it caused Emacs to get stuck in a busy loop (Bug#24091). diff --git a/src/xterm.c b/src/xterm.c index adc02e2768..db561c902a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10993,19 +10993,12 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg, /* Change of visibility. */ -/* This tries to wait until the frame is really visible. - However, if the window manager asks the user where to position - the frame, this will return before the user finishes doing that. - The frame will not actually be visible at that time, - but it will become visible later when the window manager - finishes with it. */ +/* This function sends the request to make the frame visible, but may + return before it the frame's visibility is changed. */ void x_make_frame_visible (struct frame *f) { - int original_top, original_left; - int tries = 0; - block_input (); x_set_bitmap_icon (f); @@ -11052,16 +11045,13 @@ x_make_frame_visible (struct frame *f) before we do anything else. We do this loop with input not blocked so that incoming events are handled. */ { - Lisp_Object frame; /* This must be before UNBLOCK_INPUT since events that arrive in response to the actions above will set it when they are handled. */ bool previously_visible = f->output_data.x->has_been_visible; - XSETFRAME (frame, f); - - original_left = f->left_pos; - original_top = f->top_pos; + int original_left = f->left_pos; + int original_top = f->top_pos; /* This must come after we set COUNT. */ unblock_input (); @@ -11105,46 +11095,6 @@ x_make_frame_visible (struct frame *f) unblock_input (); } - - /* Process X events until a MapNotify event has been seen. */ - while (!FRAME_VISIBLE_P (f)) - { - /* Force processing of queued events. */ - x_sync (f); - - /* If on another desktop, the deiconify/map may be ignored and the - frame never becomes visible. XMonad does this. - Prevent an endless loop. */ - if (FRAME_ICONIFIED_P (f) && ++tries > 100) - break; - - /* This hack is still in use at least for Cygwin. See - http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html. - - Machines that do polling rather than SIGIO have been - observed to go into a busy-wait here. So we'll fake an - alarm signal to let the handler know that there's something - to be read. We used to raise a real alarm, but it seems - that the handler isn't always enabled here. This is - probably a bug. */ - if (input_polling_used ()) - { - /* It could be confusing if a real alarm arrives while - processing the fake one. Turn it off and let the - handler reset it. */ - int old_poll_suppress_count = poll_suppress_count; - poll_suppress_count = 1; - poll_for_input_1 (); - poll_suppress_count = old_poll_suppress_count; - } - - if (XPending (FRAME_X_DISPLAY (f))) - { - XEvent xev; - XNextEvent (FRAME_X_DISPLAY (f), &xev); - x_dispatch_event (&xev, FRAME_X_DISPLAY (f)); - } - } } } commit e5e42cefd7f2eb47d2c8660a7a317e8b08d36a82 Author: Tino Calancha Date: Sat Jan 21 11:54:55 2017 +0900 diff-hunk-kill independent of point inside headers Make diff-apply-hunk and diff-hunk-kill independent of the point position in a diff header (Bug#17544). This change allows to apply hunks in order. It also makes possible to press M-k repeatedly to kill hunks in the order they appear in the buffer. See discussion on #Bug25105. * lisp/vc/diff-mode.el (diff-file-junk-re): Move definition before it's used. (diff--at-diff-header-p): New predicate; return non-nil when point is inside a hunk header, a file header, or within a line matching diff-file-junk-re. (diff-beginning-of-hunk): Use it. Check if the point is inside a diff header, in the middle of a hunk, or before the first hunk. (diff-apply-hunk): Call diff-beginning-of-hunk with non-nil arg before apply the hunk. (diff-hunk-kill, diff-file-kill): Call diff-beginning-of-hunk with non-nil arg after kill the hunks. (diff-post-command-hook): Call diff-beginning-of-hunk with non-nil argument. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 4e878c404c..b7ad8e8ebd 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -498,22 +498,55 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html") ;; The return value is used by easy-mmode-define-navigation. (goto-char (or end (point-max))))) +;; "index ", "old mode", "new mode", "new file mode" and +;; "deleted file mode" are output by git-diff. +(defconst diff-file-junk-re + "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file") + +;; If point is in a diff header, then return beginning +;; of hunk position otherwise return nil. +(defun diff--at-diff-header-p () + "Return non-nil if point is inside a diff header." + (let ((regexp-hunk diff-hunk-header-re) + (regexp-file diff-file-header-re) + (regexp-junk diff-file-junk-re) + (orig (point))) + (catch 'headerp + (save-excursion + (forward-line 0) + (when (looking-at regexp-hunk) ; Hunk header. + (throw 'headerp (point))) + (forward-line -1) + (when (re-search-forward regexp-file (point-at-eol 4) t) ; File header. + (forward-line 0) + (throw 'headerp (point))) + (goto-char orig) + (forward-line 0) + (when (looking-at regexp-junk) ; Git diff junk. + (while (and (looking-at regexp-junk) + (not (bobp))) + (forward-line -1)) + (re-search-forward regexp-file nil t) + (forward-line 0) + (throw 'headerp (point)))) nil))) + (defun diff-beginning-of-hunk (&optional try-harder) "Move back to the previous hunk beginning, and return its position. If point is in a file header rather than a hunk, advance to the next hunk if TRY-HARDER is non-nil; otherwise signal an error." (beginning-of-line) - (if (looking-at diff-hunk-header-re) + (if (looking-at diff-hunk-header-re) ; At hunk header. (point) - (forward-line 1) - (condition-case () - (re-search-backward diff-hunk-header-re) - (error - (unless try-harder - (error "Can't find the beginning of the hunk")) - (diff-beginning-of-file-and-junk) - (diff-hunk-next) - (point))))) + (let ((pos (diff--at-diff-header-p)) + (regexp diff-hunk-header-re)) + (cond (pos ; At junk diff header. + (if try-harder + (goto-char pos) + (error "Can't find the beginning of the hunk"))) + ((re-search-backward regexp nil t)) ; In the middle of a hunk. + ((re-search-forward regexp nil t) ; At first hunk header. + (forward-line 0)) + (t (error "Can't find the beginning of the hunk")))))) (defun diff-unified-hunk-p () (save-excursion @@ -632,12 +665,8 @@ If the prefix ARG is given, restrict the view to the current file instead." hunk-bounds)) (inhibit-read-only t)) (apply 'kill-region bounds) - (goto-char (car bounds)))) - -;; "index ", "old mode", "new mode", "new file mode" and -;; "deleted file mode" are output by git-diff. -(defconst diff-file-junk-re - "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file") + (goto-char (car bounds)) + (diff-beginning-of-hunk t))) (defun diff-beginning-of-file-and-junk () "Go to the beginning of file-related diff-info. @@ -690,7 +719,8 @@ data such as \"Index: ...\" and such." "Kill current file's hunks." (interactive) (let ((inhibit-read-only t)) - (apply 'kill-region (diff-bounds-of-file)))) + (apply 'kill-region (diff-bounds-of-file))) + (diff-beginning-of-hunk t)) (defun diff-kill-junk () "Kill spurious empty diffs." @@ -1274,7 +1304,7 @@ See `after-change-functions' for the meaning of BEG, END and LEN." ;; it's safer not to do it on big changes, e.g. when yanking a big ;; diff, or when the user edits the header, since we might then ;; screw up perfectly correct values. --Stef - (diff-beginning-of-hunk) + (diff-beginning-of-hunk t) (let* ((style (if (looking-at "\\*\\*\\*") 'context)) (start (line-beginning-position (if (eq style 'context) 3 2))) (mid (if (eq style 'context) @@ -1738,6 +1768,7 @@ the value of this variable when given an appropriate prefix argument). With a prefix argument, REVERSE the hunk." (interactive "P") + (diff-beginning-of-hunk t) (pcase-let ((`(,buf ,line-offset ,pos ,old ,new ,switched) ;; Sometimes we'd like to have the following behavior: if ;; REVERSE go to the new file, otherwise go to the old. commit 1508b538fd8f8c2e00aadcea42ac36013fad02e3 Author: Tino Calancha Date: Sat Jan 21 11:54:38 2017 +0900 ; Revert "Improve diff-mode navigation/manipulation" This reverts commit 2c8a7e50d24daf19ea7d86f1cfeaa98a41c56085. This change causes regressions: https://lists.gnu.org/archive/html/emacs-devel/2016-11/msg00738.html The following related commits are reverted as well: 61c6a10e3110490dadac4577cc540053341ff25c a283d655db88cdcc8cb53d8e2578e1cdf751c84b 6b6abe0dba6a9a2e5f78aac3814421886e7a184f e5ef59b87da5c2ddfa22f7342efe29b3eea6ed97 73349822cbd6e50526eda9c75453584d73dfca83 Fixes: debbugs:25105, 25400. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index b50b4a254f..4e878c404c 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -551,124 +551,26 @@ next hunk if TRY-HARDER is non-nil; otherwise signal an error." ;; Define diff-{hunk,file}-{prev,next} (easy-mmode-define-navigation - diff--internal-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view) + diff-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view + (when diff-auto-refine-mode + (unless (prog1 diff--auto-refine-data + (setq diff--auto-refine-data + (cons (current-buffer) (point-marker)))) + (run-at-time 0.0 nil + (lambda () + (when diff--auto-refine-data + (let ((buffer (car diff--auto-refine-data)) + (point (cdr diff--auto-refine-data))) + (setq diff--auto-refine-data nil) + (with-local-quit + (when (buffer-live-p buffer) + (with-current-buffer buffer + (save-excursion + (goto-char point) + (diff-refine-hunk)))))))))))) (easy-mmode-define-navigation - diff--internal-file diff-file-header-re "file" diff-end-of-file) - -(defun diff--wrap-navigation (skip-hunk-start - what orig - header-re goto-start-func count) - "Wrap diff-{hunk,file}-{next,prev} for more intuitive behavior. -Override the default diff-{hunk,file}-{next,prev} implementation -by skipping any lines that are associated with this hunk/file but -precede the hunk-start marker. For instance, a diff file could -contain - -diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el -index 923de9a..6b1c24f 100644 ---- a/lisp/vc/diff-mode.el -+++ b/lisp/vc/diff-mode.el -@@ -590,6 +590,22 @@ -....... - -If a point is on 'index', then the point is considered to be in -this first hunk. Move the point to the @@... marker before -executing the default diff-hunk-next/prev implementation to move -to the NEXT marker." - (if (not skip-hunk-start) - (funcall orig count) - - (let ((start (point))) - (funcall goto-start-func) - - ;; Trap the error. - (condition-case nil - (funcall orig count) - (error nil)) - - (when (not (looking-at header-re)) - (goto-char start) - (user-error (format "No %s" what))) - - ;; We successfully moved to the next/prev hunk/file. Apply the - ;; auto-refinement if needed - (when diff-auto-refine-mode - (unless (prog1 diff--auto-refine-data - (setq diff--auto-refine-data - (cons (current-buffer) (point-marker)))) - (run-at-time 0.0 nil - (lambda () - (when diff--auto-refine-data - (let ((buffer (car diff--auto-refine-data)) - (point (cdr diff--auto-refine-data))) - (setq diff--auto-refine-data nil) - (with-local-quit - (when (buffer-live-p buffer) - (with-current-buffer buffer - (save-excursion - (goto-char point) - (diff-refine-hunk)))))))))))))) - -;; These functions all take a skip-hunk-start argument which controls -;; whether we skip pre-hunk-start text or not. In interactive uses we -;; always want to do this, but the simple behavior is still necessary -;; to, for example, avoid an infinite loop: -;; -;; diff-hunk-next calls -;; diff--wrap-navigation calls -;; diff-bounds-of-hunk calls -;; diff-beginning-of-hunk calls -;; diff-hunk-next -;; -;; Here the outer diff-hunk-next has skip-hunk-start set to t, but the -;; inner one does not, which breaks the loop. -(defun diff-hunk-prev (&optional count skip-hunk-start) - "Go to the previous COUNT'th hunk." - (interactive (list (prefix-numeric-value current-prefix-arg) t)) - (diff--wrap-navigation - skip-hunk-start - "prev hunk" - 'diff--internal-hunk-prev - diff-hunk-header-re - (lambda () (goto-char (car (diff-bounds-of-hunk)))) - count)) - -(defun diff-hunk-next (&optional count skip-hunk-start) - "Go to the next COUNT'th hunk." - (interactive (list (prefix-numeric-value current-prefix-arg) t)) - (diff--wrap-navigation - skip-hunk-start - "next hunk" - 'diff--internal-hunk-next - diff-hunk-header-re - (lambda () (goto-char (car (diff-bounds-of-hunk)))) - count)) - -(defun diff-file-prev (&optional count skip-hunk-start) - "Go to the previous COUNT'th file." - (interactive (list (prefix-numeric-value current-prefix-arg) t)) - (diff--wrap-navigation - skip-hunk-start - "prev file" - 'diff--internal-file-prev - diff-file-header-re - (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next)) - count)) - -(defun diff-file-next (&optional count skip-hunk-start) - "Go to the next COUNT'th file." - (interactive (list (prefix-numeric-value current-prefix-arg) t)) - (diff--wrap-navigation - skip-hunk-start - "next file" - 'diff--internal-file-next - diff-file-header-re - (lambda () (goto-char (car (diff-bounds-of-file))) (diff--internal-hunk-next)) - count)) - - - + diff-file diff-file-header-re "file" diff-end-of-file) (defun diff-bounds-of-hunk () "Return the bounds of the diff hunk at point. @@ -679,13 +581,12 @@ point is in a file header, return the bounds of the next hunk." (let ((pos (point)) (beg (diff-beginning-of-hunk t)) (end (diff-end-of-hunk))) - (cond ((> end pos) + (cond ((>= end pos) (list beg end)) ;; If this hunk ends above POS, consider the next hunk. ((re-search-forward diff-hunk-header-re nil t) (list (match-beginning 0) (diff-end-of-hunk))) - ;; There's no next hunk, so just take the one we have. - (t (list beg end)))))) + (t (error "No hunk found")))))) (defun diff-bounds-of-file () "Return the bounds of the file segment at point. @@ -771,7 +672,7 @@ data such as \"Index: ...\" and such." (setq prevfile nextfile)) (if (and previndex (numberp prevfile) (< previndex prevfile)) (setq prevfile previndex)) - (if (numberp prevfile) + (if (and (numberp prevfile) (<= prevfile start)) (progn (goto-char prevfile) ;; Now skip backward over the leading junk we may have before the @@ -1764,9 +1665,8 @@ SRC and DST are the two variants of text as returned by `diff-hunk-text'. SWITCHED is non-nil if the patch is already applied. NOPROMPT, if non-nil, means not to prompt the user." (save-excursion - (let* ((hunk-bounds (diff-bounds-of-hunk)) - (other (diff-xor other-file diff-jump-to-old-file)) - (char-offset (- (point) (goto-char (car hunk-bounds)))) + (let* ((other (diff-xor other-file diff-jump-to-old-file)) + (char-offset (- (point) (diff-beginning-of-hunk t))) ;; Check that the hunk is well-formed. Otherwise diff-mode and ;; the user may disagree on what constitutes the hunk ;; (e.g. because an empty line truncates the hunk mid-course), @@ -1775,7 +1675,7 @@ NOPROMPT, if non-nil, means not to prompt the user." ;; Suppress check when NOPROMPT is non-nil (Bug#3033). (_ (unless noprompt (diff-sanity-check-hunk))) (hunk (buffer-substring - (point) (cadr hunk-bounds))) + (point) (save-excursion (diff-end-of-hunk) (point)))) (old (diff-hunk-text hunk reverse char-offset)) (new (diff-hunk-text hunk (not reverse) char-offset)) ;; Find the location specification. @@ -1883,15 +1783,8 @@ With a prefix argument, REVERSE the hunk." ;; Display BUF in a window (set-window-point (display-buffer buf) (+ (car pos) (cdr new))) (diff-hunk-status-msg line-offset (diff-xor switched reverse) nil) - - ;; Advance to the next hunk with skip-hunk-start set to t - ;; because we want the behavior of moving to the next logical - ;; hunk, not the original behavior where were would sometimes - ;; stay on the current hunk. This is the behavior we get when - ;; navigating through hunks interactively, and we want it when - ;; applying hunks too (see http://debbugs.gnu.org/17544). (when diff-advance-after-apply-hunk - (diff-hunk-next nil t)))))) + (diff-hunk-next)))))) (defun diff-test-hunk (&optional reverse) @@ -1972,15 +1865,14 @@ For use in `add-log-current-defun-function'." (defun diff-ignore-whitespace-hunk () "Re-diff the current hunk, ignoring whitespace differences." (interactive) - (let* ((hunk-bounds (diff-bounds-of-hunk)) - (char-offset (- (point) (goto-char (car hunk-bounds)))) + (let* ((char-offset (- (point) (diff-beginning-of-hunk t))) (opts (pcase (char-after) (?@ "-bu") (?* "-bc") (_ "-b"))) (line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)") (error "Can't find line number")) (string-to-number (match-string 1)))) (inhibit-read-only t) (hunk (delete-and-extract-region - (point) (cadr hunk-bounds))) + (point) (save-excursion (diff-end-of-hunk) (point)))) (lead (make-string (1- line-nb) ?\n)) ;Line nums start at 1. (file1 (make-temp-file "diff1")) (file2 (make-temp-file "diff2")) @@ -2076,14 +1968,16 @@ Return new point, if it was moved." (interactive) (require 'smerge-mode) (save-excursion - (let* ((hunk-bounds (diff-bounds-of-hunk)) - (style (progn (goto-char (car hunk-bounds)) - (diff-hunk-style))) ;Skips the hunk header as well. + (diff-beginning-of-hunk t) + (let* ((start (point)) + (style (diff-hunk-style)) ;Skips the hunk header as well. (beg (point)) - (end (cadr hunk-bounds)) (props-c '((diff-mode . fine) (face diff-refine-changed))) (props-r '((diff-mode . fine) (face diff-refine-removed))) - (props-a '((diff-mode . fine) (face diff-refine-added)))) + (props-a '((diff-mode . fine) (face diff-refine-added))) + ;; Be careful to go back to `start' so diff-end-of-hunk gets + ;; to read the hunk header's line info. + (end (progn (goto-char start) (diff-end-of-hunk) (point)))) (remove-overlays beg end 'diff-mode 'fine)