Skip to content

Instantly share code, notes, and snippets.

@reedobrien
Last active August 29, 2015 14:19
Show Gist options
  • Save reedobrien/4df4e0240dd9f2a92fa1 to your computer and use it in GitHub Desktop.
Save reedobrien/4df4e0240dd9f2a92fa1 to your computer and use it in GitHub Desktop.
# This is a copy of the clang-format vim-integration script, refactored to work
# with yapf.
# Questions and/or suggestions? I'm @pignacio in github.
# This script is hosted at http://gist.github.com/pignacio/f93218bbafa2aa94610c
# I'm not sure if this works properly in windows/mac. Only tested in linux.
#
# This file is a minimal yapf vim-integration. To install:
# - Change 'binary' if yapf is not on the path (see below).
# - Add to your .vimrc:
#
# map <C-I> :%pyf <path-to-this-file>/yapf_format.py<CR>
# imap <C-I> <ESC>:pyf <path-to-this-file>/yapf_format.py<CR>i
# vmap <C-I> :pyf <path-to-this-file>/yapf_format.py<CR>
#
# The first line enables yapf_format for NORMAL mode, the second line adds
# support for INSERT mode, and the third for VISUAL. Change "C-I" to another
# binding if you need yapf_format on a different key (C-I stands for Ctrl+i).
#
# With this integration you can press the bound key and yapf will format the
# whole file in NORMAL mode, the current line in INSERT mode or the selected
# region in VISUAL mode.
#
# It operates on the current, potentially unsaved buffer and does not create
# or save any files. To revert a formatting, just undo.
import difflib
import subprocess
import sys
import vim
# Change this to the full path if yapf is not on the path.
binary = 'yapf'
# Change this to format according to other formatting styles.
style = 'pep8'
def main():
# Get the current text.
buf = vim.current.buffer
text = '\n'.join(buf)
# Determine range to format.
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
if cursor < 0:
print 'Couldn\'t determine cursor position. Is your file empty?'
return
# Avoid flashing an ugly, ugly cmd prompt on Windows when invoking yapf.
startupinfo = None
if sys.platform.startswith('win32'):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
# Call formatter.
command = '{} --lines {} --style "{}"'.format(binary, lines, style)
with open('/tmp/yapf-calls', 'a') as fout:
fout.write(str(command) + '\n')
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
startupinfo=startupinfo,
shell=True)
stdout, stderr = p.communicate(input=text)
# If successful, replace buffer contents.
if stderr:
print stderr
if not stdout:
print('No output from yapf (crashed?).\n' +
'Please report to github.com/google/yapf.')
else:
lines = stdout.rstrip('\n').split('\n')
sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
for op in reversed(sequence.get_opcodes()):
if op[0] is not 'equal':
vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment