16d528ed9Sopenharmony_ci# Copyright 2014 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci# found in the LICENSE file.
46d528ed9Sopenharmony_ci#
56d528ed9Sopenharmony_ci# Based on clang-format.py.
66d528ed9Sopenharmony_ci#
76d528ed9Sopenharmony_ci# This file is a minimal gn format vim-integration. To install:
86d528ed9Sopenharmony_ci# - Change 'binary' if gn is not on the path (see below).
96d528ed9Sopenharmony_ci# - Add to your .vimrc:
106d528ed9Sopenharmony_ci#
116d528ed9Sopenharmony_ci#   map <F1> :pyxf <path-to-this-file>/gn-format.py<CR>
126d528ed9Sopenharmony_ci#
136d528ed9Sopenharmony_ci# gn format currently formats only a complete file so visual ranges, etc. won't
146d528ed9Sopenharmony_ci# be used. It operates on the current, potentially unsaved buffer and does not
156d528ed9Sopenharmony_ci# create or save any files. To revert a formatting, just undo.
166d528ed9Sopenharmony_ci
176d528ed9Sopenharmony_cifrom __future__ import print_function
186d528ed9Sopenharmony_ciimport difflib
196d528ed9Sopenharmony_ciimport subprocess
206d528ed9Sopenharmony_ciimport sys
216d528ed9Sopenharmony_ciimport vim
226d528ed9Sopenharmony_ci
236d528ed9Sopenharmony_ci# Change this to the full path if gn is not on the path.
246d528ed9Sopenharmony_cibinary = 'gn'
256d528ed9Sopenharmony_ciif vim.eval('exists("g:gn_path")') == "1":
266d528ed9Sopenharmony_ci  binary = vim.eval('g:gn_path')
276d528ed9Sopenharmony_ci
286d528ed9Sopenharmony_cidef main():
296d528ed9Sopenharmony_ci  # Get the current text.
306d528ed9Sopenharmony_ci  buf = vim.current.buffer
316d528ed9Sopenharmony_ci  text = '\n'.join(buf)
326d528ed9Sopenharmony_ci
336d528ed9Sopenharmony_ci  is_win = sys.platform.startswith('win32')
346d528ed9Sopenharmony_ci  # Avoid flashing an ugly cmd prompt on Windows when invoking gn.
356d528ed9Sopenharmony_ci  startupinfo = None
366d528ed9Sopenharmony_ci  if is_win:
376d528ed9Sopenharmony_ci    startupinfo = subprocess.STARTUPINFO()
386d528ed9Sopenharmony_ci    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
396d528ed9Sopenharmony_ci    startupinfo.wShowWindow = subprocess.SW_HIDE
406d528ed9Sopenharmony_ci
416d528ed9Sopenharmony_ci  # Call formatter. Needs shell=True on Windows due to gn.bat in depot_tools.
426d528ed9Sopenharmony_ci  p = subprocess.Popen([binary, 'format', '--stdin'],
436d528ed9Sopenharmony_ci                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
446d528ed9Sopenharmony_ci                       stdin=subprocess.PIPE, startupinfo=startupinfo,
456d528ed9Sopenharmony_ci                       shell=is_win, universal_newlines=True)
466d528ed9Sopenharmony_ci  stdout, stderr = p.communicate(input=text)
476d528ed9Sopenharmony_ci  if p.returncode != 0:
486d528ed9Sopenharmony_ci    print('Formatting failed, please report to gn-dev@chromium.org.')
496d528ed9Sopenharmony_ci    print(stdout, stderr)
506d528ed9Sopenharmony_ci  else:
516d528ed9Sopenharmony_ci    # Otherwise, replace current buffer.
526d528ed9Sopenharmony_ci    lines = stdout.split('\n')
536d528ed9Sopenharmony_ci    # Last line should have trailing \n, but we don't want to insert a blank
546d528ed9Sopenharmony_ci    # line at the end of the buffer, so remove that.
556d528ed9Sopenharmony_ci    if lines[-1] == '':
566d528ed9Sopenharmony_ci      lines = lines[:-1]
576d528ed9Sopenharmony_ci    sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
586d528ed9Sopenharmony_ci    for op in reversed(sequence.get_opcodes()):
596d528ed9Sopenharmony_ci      if op[0] != 'equal':
606d528ed9Sopenharmony_ci        vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
616d528ed9Sopenharmony_ci
626d528ed9Sopenharmony_cimain()
63