@@ -160,55 +160,31 @@ is a zero-based file offset, assuming ‘utf-8-unix’ coding."
160160 (string-to-number (match-string 3 line)))))
161161 (concat (match-string 1 line) " :" (match-string 1 line)))))
162162
163- (defun clang-format--vc-diff-get -diff-lines (file -orig file-new )
163+ (defun clang-format--vc-diff-compute -diff-and-get- lines (buf -orig buf-cur )
164164 " Return all line regions that contain diffs between FILE-ORIG and
165165FILE-NEW. If there is no diff ‘nil’ is returned. Otherwise the
166166return is a ‘list’ of lines in the format ‘--lines=<start>:<end>’
167167which can be passed directly to ‘clang-format’."
168168 ; ; Use temporary buffer for output of diff.
169169 (with-temp-buffer
170- (let ((status (call-process
171- " diff"
172- nil
173- (current-buffer )
174- nil
175- ; ; Binary diff has different behaviors that we
176- ; ; aren't interested in.
177- " -a"
178- ; ; Get minimal diff (copy diff config for git-clang-format).
179- " -U0"
180- file-orig
181- file-new))
182- (stderr (concat (if (zerop (buffer-size )) " " " : " )
170+ (diff-no-select buf-orig buf-cur " -a -U0" t (current-buffer ))
171+ (let ((diff-lines '()))
172+ ; ; Iterate through all lines in diff buffer and collect all
173+ ; ; lines in current buffer that have a diff.
174+ (goto-char (point-min ))
175+ (while (not (eobp ))
176+ (let ((diff-line (clang-format--vc-diff-match-diff-line
183177 (buffer-substring-no-properties
184- (point-min ) (line-end-position ))))
185- (diff-lines '()))
186- (cond
187- ((stringp status)
188- (error " (diff killed by signal %s%s ) " status stderr))
189- ; ; Return of 0 indicates no diff.
190- ((= status 0 ) nil )
191- ; ; Return of 1 indicates found diffs and no error.
192- ((= status 1 )
193- ; ; Iterate through all lines in diff buffer and collect all
194- ; ; lines in current buffer that have a diff.
195- (goto-char (point-min ))
196- (while (not (eobp ))
197- (let ((diff-line (clang-format--vc-diff-match-diff-line
198- (buffer-substring-no-properties
199- (line-beginning-position )
200- (line-end-position )))))
201- (when diff-line
202- ; ; Create list line regions with diffs to pass to
203- ; ; clang-format.
204- (push (concat " --lines=" diff-line) diff-lines)))
205- (forward-line 1 ))
206- (reverse diff-lines))
207- ; ; Any return != 0 && != 1 indicates some level of error.
208- (t
209- (error " (diff returned unsuccessfully %s%s ) " status stderr))))))
210-
211- (defun clang-format--vc-diff-get-vc-head-file (tmpfile-vc-head )
178+ (line-beginning-position )
179+ (line-end-position )))))
180+ (when diff-line
181+ ; ; Create list line regions with diffs to pass to
182+ ; ; clang-format.
183+ (push (concat " --lines=" diff-line) diff-lines)))
184+ (forward-line 1 ))
185+ (reverse diff-lines))))
186+
187+ (defun clang-format--vc-diff-get-diff-lines ()
212188 " Stores the contents of ‘buffer-file-name’ at vc revision HEAD into
213189‘tmpfile-vc-head’. If the current buffer is either not a file or not
214190in a vc repo, this results in an error. Currently git is the only
@@ -217,39 +193,44 @@ supported vc."
217193 (unless (buffer-file-name )
218194 (error " Buffer is not visiting a file " ))
219195
220- (let ((base-dir (vc-root-dir ))
196+ (let ((inp-buf (current-buffer ))
197+ (base-dir (vc-root-dir ))
221198 (backend (vc-backend (buffer-file-name ))))
222- ; ; We need to be able to find version control (git) root.
223- (unless base-dir
224- (error " File not known to git " ))
225- (cond
226- ((string-equal backend " Git" )
227- ; ; Get the filename relative to git root.
228- (let ((vc-file-name (substring
229- (expand-file-name (buffer-file-name ))
230- (string-width (expand-file-name base-dir))
231- nil )))
232- (let ((status (call-process
233- " git"
234- nil
235- `(:file , tmpfile-vc-head)
236- nil
237- " show" (concat " HEAD:" vc-file-name)))
238- (stderr (with-temp-buffer
239- (unless (zerop (cadr (insert-file-contents tmpfile-vc-head)))
240- (insert " : " ))
241- (buffer-substring-no-properties
242- (point-min ) (line-end-position )))))
243- (when (stringp status)
244- (error " (git show HEAD:%s killed by signal %s%s ) "
245- vc-file-name status stderr))
246- (unless (zerop status)
247- (error " (git show HEAD:%s returned unsuccessfully %s%s ) "
248- vc-file-name status stderr)))))
249- (t
250- (error
251- " Version control %s isn't supported, currently supported backends: git"
252- backend)))))
199+ (with-temp-buffer
200+ ; ; We need to be able to find version control (git) root.
201+ (unless base-dir
202+ (error " File not known to version control system " ))
203+ (cond
204+ ((string-equal backend " Git" )
205+ ; ; Get the filename relative to git root.
206+ (let ((vc-file-name (substring
207+ (expand-file-name (buffer-file-name inp-buf))
208+ (string-width (expand-file-name base-dir))
209+ nil )))
210+ (let ((status (call-process
211+ " git"
212+ nil
213+ (current-buffer )
214+ nil
215+ " show" (concat " HEAD:" vc-file-name)))
216+ (stderr (concat (if (zerop (buffer-size )) " " " : " )
217+ (buffer-substring-no-properties
218+ (point-min ) (line-end-position )))))
219+ (when (stringp status)
220+ (error " (git show HEAD:%s killed by signal %s%s ) "
221+ vc-file-name status stderr))
222+ (unless (zerop status)
223+ (error " (git show HEAD:%s returned unsuccessfully %s%s ) "
224+ vc-file-name status stderr)))))
225+ (t
226+ (error
227+ " Version control %s isn't supported, currently supported backends: git"
228+ backend)))
229+ ; ; Collect all lines where inp-buf (buffer we call
230+ ; ; clang-format-vc-diff on) differs from latest version of the
231+ ; ; backing file in the version control system.
232+ (clang-format--vc-diff-compute-diff-and-get-lines
233+ (current-buffer ) inp-buf))))
253234
254235
255236(defun clang-format--region-impl (start end &optional style assume-file-name lines )
@@ -323,7 +304,6 @@ specific locations for reformatting (i.e diff locations)."
323304 (delete-file temp-file)
324305 (when (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
325306
326-
327307;;;### autoload
328308(defun clang-format-vc-diff (&optional style assume-file-name )
329309 " The same as ‘clang-format-buffer’ but only operates on the vc
@@ -332,35 +312,15 @@ diffs from HEAD in the buffer. If no STYLE is given uses
332312file. If no ASSUME-FILE-NAME is given uses the function
333313‘buffer-file-name’."
334314 (interactive )
335- (let ((tmpfile-vc-head nil )
336- (tmpfile-curbuf nil ))
337- (unwind-protect
338- (progn
339- (setq tmpfile-vc-head
340- (make-temp-file " clang-format-vc-tmp-head-content" ))
341- (clang-format--vc-diff-get-vc-head-file tmpfile-vc-head)
342- ; ; Move the current buffer to a temporary file to take a
343- ; ; diff. Even if current-buffer is backed by a file, we
344- ; ; want to diff the buffer contents which might not be
345- ; ; saved.
346- (setq tmpfile-curbuf (make-temp-file " clang-format-vc-tmp" ))
347- (write-region nil nil tmpfile-curbuf nil 'nomessage )
348- ; ; Get a list of lines with a diff.
349- (let ((diff-lines
350- (clang-format--vc-diff-get-diff-lines
351- tmpfile-vc-head tmpfile-curbuf)))
352- ; ; If we have any diffs, format them.
353- (when diff-lines
354- (clang-format--region-impl
355- (point-min )
356- (point-max )
357- style
358- assume-file-name
359- diff-lines))))
360- (progn
361- ; ; Cleanup temporary files we created.
362- (when tmpfile-vc-head (delete-file tmpfile-vc-head))
363- (when tmpfile-curbuf (delete-file tmpfile-curbuf))))))
315+ (let ((diff-lines (clang-format--vc-diff-get-diff-lines)))
316+ ; ; If we have any diffs, format them.
317+ (when diff-lines
318+ (clang-format--region-impl
319+ (point-min )
320+ (point-max )
321+ style
322+ assume-file-name
323+ diff-lines))))
364324
365325
366326;;;### autoload
0 commit comments