clang-format: Add capability to format the diff on save in vim.
authorDaniel Jasper <djasper@google.com>
Mon, 19 Jun 2017 07:30:04 +0000 (07:30 +0000)
committerDaniel Jasper <djasper@google.com>
Mon, 19 Jun 2017 07:30:04 +0000 (07:30 +0000)
With this patch, one can configure a BufWrite hook that will make the
clang-format integration compute a diff of the current buffer with the file
that's on disk and format all changed lines. This should create a
zero-overhead auto-format solution that doesn't require the file to
already be clang-format clean to avoid spurious diffs.

Review: https://reviews.llvm.org/D32429

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305665 91177308-0d34-0410-b5e6-96231b3b80d8

docs/ClangFormat.rst
tools/clang-format/clang-format.py

index ed0e58e452d3006c2212296b268119ebbacafdfb..902afcd08ed5fa05cd9d1408ede0bed0aae64077 100644 (file)
@@ -120,6 +120,18 @@ entity.
 It operates on the current, potentially unsaved buffer and does not create
 or save any files. To revert a formatting, just undo.
 
+An alternative option is to format changes when saving a file and thus to
+have a zero-effort integration into the coding workflow. To do this, add this to
+your `.vimrc`:
+
+.. code-block:: vim
+
+  function! Formatonsave()
+    let l:formatdiff = 1
+    pyf ~/llvm/tools/clang/tools/clang-format/clang-format.py
+  endfunction
+  autocmd BufWritePre *.h,*.cc,*.cpp call Formatonsave()
+
 
 Emacs Integration
 =================
index ae8a6ebf74e9215662c39ceb5c695627bf958a42..2412566346f247e470473a63a54e4bfa5b61af77 100644 (file)
@@ -63,8 +63,19 @@ def main():
   # Determine range to format.
   if vim.eval('exists("l:lines")') == '1':
     lines = vim.eval('l:lines')
+  elif vim.eval('exists("l:formatdiff")') == '1':
+    with open(vim.current.buffer.name, 'r') as f:
+      ondisk = f.read().splitlines();
+    sequence = difflib.SequenceMatcher(None, ondisk, vim.current.buffer)
+    lines = []
+    for op in reversed(sequence.get_opcodes()):
+      if op[0] not in ['equal', 'delete']:
+        lines += ['-lines', '%s:%s' % (op[3] + 1, op[4])]
+    if lines == []:
+      return
   else:
-    lines = '%s:%s' % (vim.current.range.start + 1, vim.current.range.end + 1)
+    lines = ['-lines', '%s:%s' % (vim.current.range.start + 1,
+                                  vim.current.range.end + 1)]
 
   # Determine the cursor position.
   cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
@@ -82,7 +93,7 @@ def main():
   # Call formatter.
   command = [binary, '-style', style, '-cursor', str(cursor)]
   if lines != 'all':
-    command.extend(['-lines', lines])
+    command += lines
   if fallback_style:
     command.extend(['-fallback-style', fallback_style])
   if vim.current.buffer.name: