xref: /minix3/external/bsd/llvm/dist/clang/tools/clang-format/clang-format.py (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc# This file is a minimal clang-format vim-integration. To install:
2f4a2713aSLionel Sambuc# - Change 'binary' if clang-format is not on the path (see below).
3f4a2713aSLionel Sambuc# - Add to your .vimrc:
4f4a2713aSLionel Sambuc#
5*0a6a1f1dSLionel Sambuc#   map <C-I> :pyf <path-to-this-file>/clang-format.py<cr>
6*0a6a1f1dSLionel Sambuc#   imap <C-I> <c-o>:pyf <path-to-this-file>/clang-format.py<cr>
7f4a2713aSLionel Sambuc#
8f4a2713aSLionel Sambuc# The first line enables clang-format for NORMAL and VISUAL mode, the second
9f4a2713aSLionel Sambuc# line adds support for INSERT mode. Change "C-I" to another binding if you
10f4a2713aSLionel Sambuc# need clang-format on a different key (C-I stands for Ctrl+i).
11f4a2713aSLionel Sambuc#
12f4a2713aSLionel Sambuc# With this integration you can press the bound key and clang-format will
13f4a2713aSLionel Sambuc# format the current line in NORMAL and INSERT mode or the selected region in
14f4a2713aSLionel Sambuc# VISUAL mode. The line or region is extended to the next bigger syntactic
15f4a2713aSLionel Sambuc# entity.
16f4a2713aSLionel Sambuc#
17f4a2713aSLionel Sambuc# It operates on the current, potentially unsaved buffer and does not create
18f4a2713aSLionel Sambuc# or save any files. To revert a formatting, just undo.
19f4a2713aSLionel Sambuc
20f4a2713aSLionel Sambucimport difflib
21f4a2713aSLionel Sambucimport json
22f4a2713aSLionel Sambucimport subprocess
23f4a2713aSLionel Sambucimport sys
24f4a2713aSLionel Sambucimport vim
25f4a2713aSLionel Sambuc
26*0a6a1f1dSLionel Sambuc# set g:clang_format_path to the path to clang-format if it is not on the path
27f4a2713aSLionel Sambuc# Change this to the full path if clang-format is not on the path.
28f4a2713aSLionel Sambucbinary = 'clang-format'
29*0a6a1f1dSLionel Sambucif vim.eval('exists("g:clang_format_path")') == "1":
30*0a6a1f1dSLionel Sambuc  binary = vim.eval('g:clang_format_path')
31f4a2713aSLionel Sambuc
32f4a2713aSLionel Sambuc# Change this to format according to other formatting styles. See the output of
33f4a2713aSLionel Sambuc# 'clang-format --help' for a list of supported styles. The default looks for
34f4a2713aSLionel Sambuc# a '.clang-format' or '_clang-format' file to indicate the style that should be
35f4a2713aSLionel Sambuc# used.
36f4a2713aSLionel Sambucstyle = 'file'
37f4a2713aSLionel Sambuc
38*0a6a1f1dSLionel Sambucdef main():
39f4a2713aSLionel Sambuc  # Get the current text.
40f4a2713aSLionel Sambuc  buf = vim.current.buffer
41f4a2713aSLionel Sambuc  text = '\n'.join(buf)
42f4a2713aSLionel Sambuc
43f4a2713aSLionel Sambuc  # Determine range to format.
44f4a2713aSLionel Sambuc  lines = '%s:%s' % (vim.current.range.start + 1, vim.current.range.end + 1)
45f4a2713aSLionel Sambuc
46*0a6a1f1dSLionel Sambuc  # Determine the cursor position.
47*0a6a1f1dSLionel Sambuc  cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
48*0a6a1f1dSLionel Sambuc  if cursor < 0:
49*0a6a1f1dSLionel Sambuc    print 'Couldn\'t determine cursor position. Is your file empty?'
50*0a6a1f1dSLionel Sambuc    return
51*0a6a1f1dSLionel Sambuc
52f4a2713aSLionel Sambuc  # Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
53f4a2713aSLionel Sambuc  startupinfo = None
54f4a2713aSLionel Sambuc  if sys.platform.startswith('win32'):
55f4a2713aSLionel Sambuc    startupinfo = subprocess.STARTUPINFO()
56f4a2713aSLionel Sambuc    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
57f4a2713aSLionel Sambuc    startupinfo.wShowWindow = subprocess.SW_HIDE
58f4a2713aSLionel Sambuc
59f4a2713aSLionel Sambuc  # Call formatter.
60f4a2713aSLionel Sambuc  command = [binary, '-lines', lines, '-style', style, '-cursor', str(cursor)]
61f4a2713aSLionel Sambuc  if vim.current.buffer.name:
62f4a2713aSLionel Sambuc    command.extend(['-assume-filename', vim.current.buffer.name])
63f4a2713aSLionel Sambuc  p = subprocess.Popen(command,
64f4a2713aSLionel Sambuc                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
65f4a2713aSLionel Sambuc                       stdin=subprocess.PIPE, startupinfo=startupinfo)
66f4a2713aSLionel Sambuc  stdout, stderr = p.communicate(input=text)
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc  # If successful, replace buffer contents.
69f4a2713aSLionel Sambuc  if stderr:
70*0a6a1f1dSLionel Sambuc    print stderr
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc  if not stdout:
73f4a2713aSLionel Sambuc    print ('No output from clang-format (crashed?).\n' +
74f4a2713aSLionel Sambuc        'Please report to bugs.llvm.org.')
75f4a2713aSLionel Sambuc  else:
76f4a2713aSLionel Sambuc    lines = stdout.split('\n')
77f4a2713aSLionel Sambuc    output = json.loads(lines[0])
78f4a2713aSLionel Sambuc    lines = lines[1:]
79f4a2713aSLionel Sambuc    sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
80f4a2713aSLionel Sambuc    for op in reversed(sequence.get_opcodes()):
81f4a2713aSLionel Sambuc      if op[0] is not 'equal':
82f4a2713aSLionel Sambuc        vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
83f4a2713aSLionel Sambuc    vim.command('goto %d' % (output['Cursor'] + 1))
84*0a6a1f1dSLionel Sambuc
85*0a6a1f1dSLionel Sambucmain()
86