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