> On Dec 13, 2020, at 7:15 AM, Damjan Marion via lists.fd.io 
> <dmarion=me....@lists.fd.io> wrote:
> 
> 
> Hi,
> 
> I was playing a bit with clang-format as replacement to gnu indent which we 
> use today[1].
> 
> While it is impossible to render exact same result like gnu indent, good 
> thing is that clang-format can be used only on lines which are changed in the 
> diff so no major reformat is needed. My patch deos exactly that.

I have an emacs function that can be used to do this (reformat only changed 
lines) on file save as well. I've included it below.. It does count on 
"clang-format.el" already being installed. The first couple of items are for 
hooking before-save, and only do the reformat if CLANG is specified in the 
standard VPP trailer comment (instead of INDENT or ON).

Thanks,
Chris.

        (defun vpp-maybe-format-buffer ()
          "Reformat buffer if contains VPP magic"
          (when (save-excursion
                  (goto-char (point-min))
                  (re-search-forward "coding-style-patch-verification: 
\\(ON\\|INDENT\\|CLANG\\)" nil t))
            (cond
             ((string= "CLANG" (match-string 1)) (clang-format-vc-diff) t)
             ;; ((string= "ON" (match-string 1)) (vpp-format-buffer) t)
             ;; ((string= "INDENT" (match-string 1)) (vpp-format-buffer) t)
             (t t))))

        (defun vpp-maybe-format-buffer-on-save ()
          (add-hook 'before-save-hook 'vpp-maybe-format-buffer nil t))
        (add-hook 'c-mode-hook 'vpp-maybe-format-buffer-on-save)
        (add-hook 'c++-mode-hook 'vpp-maybe-format-buffer-on-save)

        (defvar diffu-new-lines-re "^@@.*\\+\\([0-9]+\\)\\(,\\([0-9]+\\)\\)?")

        (defun clang-format-args-from-diff-buffer (&optional buffer)
          (let ((use-buf (or buffer (current-buffer)))
                lines)
            (with-current-buffer use-buf
              (save-excursion
                (goto-char (point-max))
                (while (re-search-backward diffu-new-lines-re nil 'noerror)
                  (let ((start (string-to-number (match-string 1)))
                        (count (string-to-number (or (match-string 3) "1"))))
                    (unless (= count 0)
                      (setq lines (cons (format "--lines=%d:%d" start (+ start 
count -1)) lines)))))))
            lines))

        (defun clang-format-vc-diff ()
          "Reformat only the changed lines from VC in the buffer"
          (interactive)
          (let* ((code-buffer (current-buffer))
                 (cursor (clang-format--bufferpos-to-filepos (point) 'exact 
'utf-8-unix))
                 ;; vc-working-revision has some bizarre cache bug, it
                 ;; returns the revision that was HEAD the first time it is
                 ;; checked in a buffer. If that buffer is saved, and checked
                 ;; the next call to vc-working-revision is not updated, one
                 ;; must reload the file. So instead invoke the backend 
directly.
                 (head-revision (vc-call-backend (vc-backend buffer-file-name)
                                                 'working-revision
                                                 buffer-file-name))
                 (temp-buffer (generate-new-buffer " *clang-format-temp*"))
                 (temp-file (make-temp-file "clang-format"))
                 diff-line-args
                 head-temp-file)
            (unwind-protect
                (if (not head-revision)
                    (progn
                      (message "(clang-format-vc-diff: %s not revision 
controlled, formatting whole buffer"
                               buffer-file-name)
                      (clang-format-buffer))
                  ;; Get the HEAD revision into a temp file
                  (let ((head-temp-buf (vc-find-revision buffer-file-name 
head-revision)))
                    (setq head-temp-file (buffer-file-name head-temp-buf))
                    (kill-buffer head-temp-buf))
                  ;; Get the diff of buffer from the HEAD revision
                  (let ((status (call-process-region
                                 nil nil (executable-find "diff")
                                 nil `(,temp-buffer ,temp-file) nil
                                 "-u0"
                                 head-temp-file
                                 "-"))
                        (stderr (with-temp-buffer
                                  (unless (zerop (cadr (insert-file-contents 
temp-file)))
                                    (insert ": "))
                                  (buffer-substring-no-properties
                                   (point-min) (line-end-position)))))
                    (cond
                     ((stringp status)
                      (error "(clang-format-vc-diff diff killed by signal 
%s%s)" status stderr))
                     ((zerop status)
                      (message "(clang-format-vc-diff no diff"))
                     ((not (= 1 status))
                       (error "(clang-format-vc-diff diff failed with code 
%d%s)" status stderr))))
                  (setq diff-line-args (clang-format-args-from-diff-buffer 
temp-buffer))
                  ;; empty the temp buffer, and delete the temp file
                  (with-current-buffer temp-buffer (erase-buffer))
                  ;; Get xml-replacements into now-empty temp-buffer
                  (if (not diff-line-args)
                      (message "(clang-format-vc-diff no differences to 
format)")
                    (let ((status (apply #'call-process-region
                                         nil nil clang-format-executable
                                         nil `(,temp-buffer ,temp-file) nil
                                         `("-output-replacements-xml"
                                           "-assume-filename" 
,(file-name-nondirectory buffer-file-name)
                                           "-fallback-style" 
,clang-format-fallback-style
                                           "-cursor" ,(number-to-string cursor)
                                           ,@diff-line-args)))
                          (stderr (with-temp-buffer
                                    (unless (zerop (cadr (insert-file-contents 
temp-file)))
                                      (insert ": "))
                                    (buffer-substring-no-properties
                                     (point-min) (line-end-position)))))
                      (cond
                       ((stringp status)
                        (error "(clang-format killed by signal %s%s)" status 
stderr))
                       ((not (zerop status))
                        (error "(clang-format failed with code %d%s)" status 
stderr)))
                      (if (= 0 (buffer-size temp-buffer))
                          (message "(vpp-clang-diff-format-buffer no formatting 
changes")
                        (cl-destructuring-bind (replacements cursor 
incomplete-format)
                            (with-current-buffer temp-buffer
                              (clang-format--extract (car (xml-parse-region))))
                          (save-excursion
                            (dolist (rpl replacements)
                              (apply #'clang-format--replace rpl)))
                          (when cursor
                            (goto-char (clang-format--filepos-to-bufferpos 
cursor 'exact
                                                                           
'utf-8-unix)))
                          (if incomplete-format
                              (message "(clang-format: incomplete (syntax 
errors)%s)" stderr)
                            (message "(clang-format: success%s)" stderr)))))))
              (ignore-errors (kill-buffer temp-buffer))
              (ignore-errors (delete-file temp-file))
              (ignore-errors (delete-file head-temp-file)))))

Attachment: signature.asc
Description: Message signed with OpenPGP

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#18322): https://lists.fd.io/g/vpp-dev/message/18322
Mute This Topic: https://lists.fd.io/mt/78925374/21656
Group Owner: vpp-dev+ow...@lists.fd.io
Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to