Skip to main content
added 174 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat "\\(^\\)" ;; Optional, don't capture, ignore. "\\(?:diff[[;; Git uses:blank "diff ..." & "index ..." ;; Subversion uses:]]+ "Index .*\n\\)?.." & "===...".   ;;  ;; So use any non-blank line start except for '-' & '+'. "\\(?:index[[[^\\-\\+[:blank:]]+.*\n\\)+?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point))))))))   
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position))) ) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-at-point-file-line-to-point current-filename-relative current-line current-column)) ) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found) ) ) ) ) ) ) 
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat "\\(^\\)" ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point))))))))   
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position))) ) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-at-point-file-line-to-point current-filename-relative current-line current-column)) ) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found) ) ) ) ) ) ) 
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat "\\(^\\)" ;; Optional, don't capture, ignore. ;; Git uses: "diff ..." & "index ..." ;; Subversion uses: "Index ..." & "===...".   ;;  ;; So use any non-blank line start except for '-' & '+'. "\\(?:[^\\-\\+[:blank:]]+.*\n\\)+?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point)))))))) 
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position)))) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-at-point-file-line-to-point current-filename-relative current-line current-column))) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found))))))) 
added 33 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat  "\\(^\\)"  ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point)))))))) 
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point)))))))) 
(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) "This can be used to navigate to a point in a diff buffer. Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat  "\\(^\\)"  ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?" ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point)))))))) 
deleted 60 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133

Edit: this is now a package: diff-at-point


(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict) " This "This can be used to navigate to a point in a diff buffer,. given Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement.  CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'.  When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk.  " (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. )  nil t 1 ) ) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for (in lines). (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat  ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?"  ;; Prefix '+++ '.  "^"  "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n"  "@@[[:blank:]]+.*[[:blank:]]@@"  ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1 ) (match-beginning 0) (point-max) ) ) ) ) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@" ) current-filename-diff-point-max t 1 ) ) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties  (match-beginning 4)  (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties  (match-beginning 5)  (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines)) ) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and  (eq fallback-point-end nil)  (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point) ) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or  (eq fallback-delta-lines nil)  (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil) ) ) ) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or  (eq fallback-delta-lines nil)  (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil) ) ) ) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column)) ) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)) ) ) (forward-line) ) ) ) ) ) ) ) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (if fallback-point-end (progn   (goto-char (or fallback-point-end current-filename-diff-point-max))   (forward-line -1)   (forward-char) ) ;; Last hunk, no end. (goto-char current-filename-diff-point-max) ) ) ;; fallback-point-end (point) ) ) ) ) ) ) ) 
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position))) ) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-at-point-file-line-to-point current-filename-relative current-line current-column)) ) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found) ) ) ) ) ) ) 
(defun diff-file-line-to-point (current-filename-relative current-line current-column &optional strict) " This can be used to navigate to a point in a diff buffer, given the file, line and column in the original (non-diff) file. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement. When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk.  " (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. )  nil t 1 ) ) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for (in lines). (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat ;; Prefix '+++ '.  "^"  "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n"  "@@[[:blank:]]+.*[[:blank:]]@@"  ;; May have trailing text which can be safely ignored. ) nil t 1 ) (match-beginning 0) (point-max) ) ) ) ) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@" ) current-filename-diff-point-max t 1 ) ) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties (match-beginning 4) (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties (match-beginning 5) (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines)) ) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and (eq fallback-point-end nil) (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point) ) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil) ) ) ) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or (eq fallback-delta-lines nil) (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil) ) ) ) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column)) ) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)) ) ) (forward-line) ) ) ) ) ) ) ) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (if fallback-point-end (progn   (goto-char fallback-point-end)   (forward-line -1)   (forward-char) ) ;; Last hunk, no end. (goto-char current-filename-diff-point-max) ) ) ;; fallback-point-end (point) ) ) ) ) ) ) ) 
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position))) ) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-file-line-to-point current-filename-relative current-line current-column)) ) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found) ) ) ) ) ) ) 

Edit: this is now a package: diff-at-point


(defun diff-at-point-file-line-to-point (current-filename-relative current-line current-column &optional strict)  "This can be used to navigate to a point in a diff buffer.  Given the file, line and column in the original (non-diff) file, this returns the point in the diff buffer or nil if it can't be found. This can be used to implement a utility to open a diff buffer, then navigate to the point the user was viewing. However this function doesn't make any change the the buffer state, that's up to the caller to implement.  CURRENT-FILENAME-RELATIVE the filename to look-up in the diff. Typically this is the filename of the current buffer, relative to the repository root. Arguments CURRENT-LINE & CURRENT-COLUMN define the location in the file. Typically this is taken from the current `point'.  When STRICT is enabled, only return a result if the line exists in the diff, otherwise return a point in the closest hunk." (save-excursion (if (not (re-search-forward (concat ;; Prefix '+++ '. "^" "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+" ;; Optional 'b/'. "\\(\\|b/\\)" (regexp-quote current-filename-relative) ;; Optional ' (some text)' ;; Subversion quirk. "\\(\\|[[:blank:]]+.*\\)\n" "@@[[:blank:]]+.*[[:blank:]]@@" ;; may have trailing text, ignore this. ) nil t 1)) (error "Unable to find filename in diff: %S" current-filename-relative) (beginning-of-line) (let ( ;; Next file or end of document. (point-found nil) ;; Fallback point closest to the hunk, ;; used if 'current-line' isn't inside the hunk in the diff. ;; ;; The fallback uses either the beginning or end of the hunk. (fallback-point-begin nil) (fallback-point-end nil) (fallback-point-is-begin nil) ;; The distance of the fallback point to the line we're looking for. (fallback-delta-lines nil) ;; Find the next hunk or file max, to restrict the search. (current-filename-diff-point-max (save-excursion (if (re-search-forward (concat  ;; Optional, don't capture, ignore. "\\(?:diff[[:blank:]]+.*\n\\)?" "\\(?:index[[:blank:]]+.*\n\\)?"  ;; Prefix '+++ '. "\\-\\-\\-[[:blank:]]+.*\n" "\\+\\+\\+[[:blank:]]+.*\n" ;; May have trailing text which can be safely ignored. "@@[[:blank:]]+.*[[:blank:]]@@") nil t 1) (match-beginning 0) (point-max))))) ;; Now search for the current hunk. (save-excursion (while (and (eq point-found nil) (re-search-forward (concat "^\\(@@\\)[[:blank:]]+" ;; Previous (ignore). "\\-" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+" ;; Current (use). "\\+" "\\([[:digit:]]+\\)\\,\\([[:digit:]]+\\)" "[[:blank:]]+@@") current-filename-diff-point-max t 1)) (let* ( (diff-hunk-point (match-beginning 1)) (diff-hunk-begin (string-to-number (buffer-substring-no-properties  (match-beginning 4)  (match-end 4)))) (diff-hunk-lines (string-to-number (buffer-substring-no-properties  (match-beginning 5)  (match-end 5)))) (diff-hunk-end (+ diff-hunk-begin diff-hunk-lines))) ;; We have something like this: ;; @@ -1,4 +1,5 @@ ;; string-to-number ;; (message "%S %S" diff-hunk-begin diff-hunk-end) ;; If the last hunk was set as the fallback, use this chink as the ;; end of that fallback. (when (and  (eq fallback-point-end nil)  (not (eq fallback-point-begin nil))) (setq fallback-point-end diff-hunk-point)) ;; Scan down the the line... (cond ((< current-line diff-hunk-begin) (let ((delta (- diff-hunk-begin current-line))) (when (or  (eq fallback-delta-lines nil)  (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin t) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) ((>= current-line diff-hunk-end) (let ((delta (- current-line diff-hunk-end))) (when (or  (eq fallback-delta-lines nil)  (> fallback-delta-lines delta)) (setq fallback-point-begin diff-hunk-point) (setq fallback-point-is-begin nil) (setq fallback-delta-lines delta) ;; Set next iteration. (setq fallback-point-end nil)))) (t (let ((diff-line-current diff-hunk-begin)) (forward-line) ;; Avoid eternal loop (for mal-formed diffs). (while (eq point-found nil) (let ((c (char-after (point)))) (cond ((memq c '(?\s ?+)) (when (eq diff-line-current current-line) (setq point-found (+ 1 (point) current-column))) (setq diff-line-current (+ 1 diff-line-current))) ((eq c ?-) nil) (t (error "Malformed diff, unexpected character %S" c)))) (forward-line)))))))) ;; May be nil, return either way. (if strict point-found (or point-found ;; Use the beginning or end of the hunk. (save-excursion (if fallback-point-is-begin (progn (goto-char fallback-point-begin) (forward-line 1) (forward-char) ) (progn (goto-char (or fallback-point-end current-filename-diff-point-max)) (forward-line -1) (forward-char))) ;; fallback-point-end (point)))))))) 
(defun vc-root-diff-fullscreen-and-jump-to-point (&optional branch) " Open a diff of the repository in the current frame. Jumping to the file, then line if possible. " (interactive) (let ( (pop-up-windows nil) (current-filename (buffer-file-name)) (current-line (line-number-at-pos)) (current-column (- (point) (line-beginning-position))) ) (when (if branch (vc-root-version-diff nil branch nil) (vc-root-diff nil)) (when current-filename (let* ( (current-filename-relative (file-relative-name current-filename default-directory)) (point-found (diff-at-point-file-line-to-point current-filename-relative current-line current-column)) ) ;; Go to the file in the diff which we were previously viewing. (when point-found (goto-char point-found) ) ) ) ) ) ) 
added 20 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
added 1803 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
deleted 483 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
deleted 14 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
deleted 14 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
deleted 268 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
added 49 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
added 59 characters in body
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading
Source Link
ideasman42
  • 9.5k
  • 2
  • 38
  • 133
Loading