@@ -157,6 +157,22 @@ is a zero-based file offset, assuming ‘utf-8-unix’ coding."
157157 (with-demoted-errors " failed to remove file: %S"
158158 (delete-file (pop , bind-files-to-delete )))))))
159159
160+
161+ (defun clang-format--vc-diff-match-diff-line (line )
162+ ; ; We are matching something like:
163+ ; ; "@@ -80 +80 @@" or "@@ -80,2 +80,2 @@"
164+ ; ; Return as "<LineStart>:<LineEnd>"
165+ (when (string-match " ^@@\s -[0-9,]+\s \\ +\\ ([0-9]+\\ )\\ (,\\ ([0-9]+\\ )\\ )?\s @@$" line)
166+ ; ; If we have multi-line diff
167+ (if (match-string 3 line)
168+ (concat (match-string 1 line)
169+ " :"
170+ (number-to-string
171+ (+ (string-to-number (match-string 1 line))
172+ (string-to-number (match-string 3 line)))))
173+ (concat (match-string 1 line) " :" (match-string 1 line)))))
174+
175+
160176(defun clang-format--vc-diff-get-diff-lines (file-orig file-new )
161177 " Return all line regions that contain diffs between FILE-ORIG and
162178FILE-NEW. If there is no diff ‘nil’ is returned. Otherwise the
@@ -175,32 +191,35 @@ which can be passed directly to ‘clang-format’."
175191 ; ; Binary diff has different behaviors that we
176192 ; ; aren't interested in.
177193 " -a"
178- ; ; Print new lines in file-new formatted as
179- ; ; "--lines=<StartDiff:EndDiff> "
180- " --changed-group-format=%(N=0?:--lines=%dF:%dM )"
181- ; ; Don't print anything for unchanged lines
182- " --unchanged-group-format="
194+ ; ; Get minimal diff (copy diff config for git-clang-format).
195+ " -U0"
183196 file-orig
184197 file-new))
185198 (stderr (concat (if (zerop (buffer-size )) " " " : " )
186199 (buffer-substring-no-properties
187- (point-min ) (line-end-position )))))
200+ (point-min ) (line-end-position ))))
201+ (diff-lines '()))
188202 (cond
189203 ((stringp status)
190204 (error " (diff killed by signal %s%s ) " status stderr))
191205 ; ; Return of 0 indicates no diff.
192206 ((= status 0 ) nil )
193207 ; ; Return of 1 indicates found diffs and no error.
194208 ((= status 1 )
195- ; ; We had our diff command printout all diffs as
196- ; ; "--lines=S0:E0 --lines=S1:E1 ... --lines=SN:EN " so just
197- ; ; split the output into a list to pass to clang-format.
198- (split-string
199- (buffer-substring-no-properties (point-min ) (point-max ))
200- ; ; All whitespace (practically only spaces).
201- " [ \f\t\n\r\v ]"
202- ; ; Don't create empty entries.
203- t ))
209+ ; ; Iterate through all lines in diff buffer and collect all
210+ ; ; lines in current buffer that have a diff.
211+ (goto-char (point-min ))
212+ (while (not (eobp ))
213+ (let ((diff-line (clang-format--vc-diff-match-diff-line
214+ (buffer-substring-no-properties
215+ (line-beginning-position )
216+ (line-end-position )))))
217+ (when diff-line
218+ ; ; Create list line regions with diffs to pass to
219+ ; ; clang-format.
220+ (push (concat " --lines=" diff-line) diff-lines)))
221+ (forward-line 1 ))
222+ (reverse diff-lines))
204223 ; ; Any return != 0 && != 1 indicates some level of error.
205224 (t
206225 (error " (diff returned unsuccessfully %s%s ) " status stderr))))))
0 commit comments