1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4# 5# Based on clang-format.py. 6# 7# This file is a minimal gn format vim-integration. To install: 8# - Change 'binary' if gn is not on the path (see below). 9# - Add to your .vimrc: 10# 11# map <F1> :pyxf <path-to-this-file>/gn-format.py<CR> 12# 13# gn format currently formats only a complete file so visual ranges, etc. won't 14# be used. It operates on the current, potentially unsaved buffer and does not 15# create or save any files. To revert a formatting, just undo. 16 17from __future__ import print_function 18import difflib 19import subprocess 20import sys 21import vim 22 23# Change this to the full path if gn is not on the path. 24binary = 'gn' 25if vim.eval('exists("g:gn_path")') == "1": 26 binary = vim.eval('g:gn_path') 27 28def main(): 29 # Get the current text. 30 buf = vim.current.buffer 31 text = '\n'.join(buf) 32 33 is_win = sys.platform.startswith('win32') 34 # Avoid flashing an ugly cmd prompt on Windows when invoking gn. 35 startupinfo = None 36 if is_win: 37 startupinfo = subprocess.STARTUPINFO() 38 startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 39 startupinfo.wShowWindow = subprocess.SW_HIDE 40 41 # Call formatter. Needs shell=True on Windows due to gn.bat in depot_tools. 42 p = subprocess.Popen([binary, 'format', '--stdin'], 43 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 44 stdin=subprocess.PIPE, startupinfo=startupinfo, 45 shell=is_win, universal_newlines=True) 46 stdout, stderr = p.communicate(input=text) 47 if p.returncode != 0: 48 print('Formatting failed, please report to gn-dev@chromium.org.') 49 print(stdout, stderr) 50 else: 51 # Otherwise, replace current buffer. 52 lines = stdout.split('\n') 53 # Last line should have trailing \n, but we don't want to insert a blank 54 # line at the end of the buffer, so remove that. 55 if lines[-1] == '': 56 lines = lines[:-1] 57 sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines) 58 for op in reversed(sequence.get_opcodes()): 59 if op[0] != 'equal': 60 vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]] 61 62main() 63