[clang] [clang-format] New clang-format-indent-mode for Emacs (PR #78904)

via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 21 08:27:44 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: Amy Grinn (amygrinn)

<details>
<summary>Changes</summary>

This Emacs minor mode merges functionality from existing indentation functions such as 'c-indent-line' or 'treesit-indent' with the external clang-format utility.

On non-blank lines (lines with something other than whitespace), clang format will be used. Some replacements are filtered out if they affect text beyond the end of the current line.

This is useful, for example, for applying .clang-format rules such as IfMacros or AlignConsecutive* as you type.

Best,

Amy

---
Full diff: https://github.com/llvm/llvm-project/pull/78904.diff


1 Files Affected:

- (modified) clang/tools/clang-format/clang-format.el (+53) 


``````````diff
diff --git a/clang/tools/clang-format/clang-format.el b/clang/tools/clang-format/clang-format.el
index f43bf063c62970..510ceb7ef93bb3 100644
--- a/clang/tools/clang-format/clang-format.el
+++ b/clang/tools/clang-format/clang-format.el
@@ -28,6 +28,13 @@
 ;;
 ;;   (global-set-key [C-M-tab] 'clang-format-region)
 
+;; clang-format.el comes with a local minor mode
+;; `clang-format-indent-mode'.  This mode advises the existing
+;; indentation function using the `clang-format-executable'. This can
+;; be turned on automatically using a mode hook:
+;;
+;;   (add-hook 'c-mode-common-hook 'clang-format-indent-mode)
+
 ;;; Code:
 
 (require 'cl-lib)
@@ -217,5 +224,51 @@ the function `buffer-file-name'."
 ;;;###autoload
 (defalias 'clang-format 'clang-format-region)
 
+(defun clang-format--indent-line (&rest _)
+  "Indent current line using clang-format, if not on a blank line.
+
+Returns nil on blank lines. Discards replacements which
+affect text beyond the end of the line."
+  (when (save-excursion
+          (beginning-of-line)
+          (not (looking-at-p "[ \t]*$")))
+    (prog1 t
+      ;; Remove trailing whitespace
+      (save-excursion
+        (end-of-line)
+        (delete-char (- (skip-chars-backward " \t"))))
+      ;; Discard replacements which affect text beyond end of line
+      (let* ((next-char (clang-format--bufferpos-to-filepos
+                         (save-excursion
+                           (end-of-line)
+                           (skip-chars-forward " \t\r\n")
+                           (point))
+                         'exact 'utf-8-unix))
+             (advice `(lambda (offset length &rest _)
+                        (< (+ offset length) ,next-char))))
+        (advice-add #'clang-format--replace :before-while advice)
+        (unwind-protect
+            (let ((inhibit-message t))
+              (clang-format-region (line-beginning-position)
+                                   (line-end-position)))
+          (advice-remove #'clang-format--replace advice)))
+      (when (< (current-column) (current-indentation))
+        (back-to-indentation)))))
+
+;;;###autoload
+(define-minor-mode clang-format-indent-mode
+  "Use clang-format to control indentation on contentful lines.
+
+Clang format indent mode is a buffer-local minor mode. When
+enabled, indentation for lines that do not solely consist of
+whitespace will be determined by running the buffer through the
+`clang-format-executable' program. On empty lines, the existing
+indentation function will be used."
+  :global nil :group 'tools
+  (if clang-format-indent-mode
+      (advice-add indent-line-function :before-until
+                  #'clang-format--indent-line)
+    (advice-remove indent-line-function #'clang-format--indent-line)))
+
 (provide 'clang-format)
 ;;; clang-format.el ends here

``````````

</details>


https://github.com/llvm/llvm-project/pull/78904


More information about the cfe-commits mailing list