• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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