2013-03-20 17:53:23 +08:00
|
|
|
# This file is a minimal clang-format vim-integration. To install:
|
|
|
|
# - Change 'binary' if clang-format is not on the path (see below).
|
|
|
|
# - Add to your .vimrc:
|
|
|
|
#
|
[clang-format] update comments in clang-format.py for python3 compatibility
Summary:
D23319 introduced python3 compatibility to clang-format.py, this is however not reflected by the documentation in the comments at the beginning of the file, which show how to use the script with python2 in .vimrc. While the actual mapping a user might want to use may well differ from my suggestion, I think it's nice to show the python2 and python3 version, such that a user can pick from the suggestions instead of googeling the python3 replacement for `:pyf` which they might not be familiar with.
EDIT: picking reviewers according to https://llvm.org/docs/Phabricator.html#finding-potential-reviewers
Reviewers: klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Subscribers: ilya-biryukov, cfe-commits, llvm-commits, ychen
Patch By: pseyfert
Tags: #clang-tools-extra, #llvm, #clang
Differential Revision: https://reviews.llvm.org/D38446
2019-11-08 21:15:45 +08:00
|
|
|
# if has('python')
|
|
|
|
# map <C-I> :pyf <path-to-this-file>/clang-format.py<cr>
|
|
|
|
# imap <C-I> <c-o>:pyf <path-to-this-file>/clang-format.py<cr>
|
|
|
|
# elseif has('python3')
|
|
|
|
# map <C-I> :py3f <path-to-this-file>/clang-format.py<cr>
|
|
|
|
# imap <C-I> <c-o>:py3f <path-to-this-file>/clang-format.py<cr>
|
|
|
|
# endif
|
2013-03-20 17:53:23 +08:00
|
|
|
#
|
[clang-format] update comments in clang-format.py for python3 compatibility
Summary:
D23319 introduced python3 compatibility to clang-format.py, this is however not reflected by the documentation in the comments at the beginning of the file, which show how to use the script with python2 in .vimrc. While the actual mapping a user might want to use may well differ from my suggestion, I think it's nice to show the python2 and python3 version, such that a user can pick from the suggestions instead of googeling the python3 replacement for `:pyf` which they might not be familiar with.
EDIT: picking reviewers according to https://llvm.org/docs/Phabricator.html#finding-potential-reviewers
Reviewers: klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Subscribers: ilya-biryukov, cfe-commits, llvm-commits, ychen
Patch By: pseyfert
Tags: #clang-tools-extra, #llvm, #clang
Differential Revision: https://reviews.llvm.org/D38446
2019-11-08 21:15:45 +08:00
|
|
|
# The if-elseif-endif conditional should pick either the python3 or python2
|
|
|
|
# integration depending on your vim setup.
|
|
|
|
#
|
|
|
|
# The first mapping enables clang-format for NORMAL and VISUAL mode, the second
|
|
|
|
# mapping adds support for INSERT mode. Change "C-I" to another binding if you
|
2013-03-20 17:53:23 +08:00
|
|
|
# need clang-format on a different key (C-I stands for Ctrl+i).
|
|
|
|
#
|
|
|
|
# With this integration you can press the bound key and clang-format will
|
|
|
|
# format the current line in NORMAL and INSERT mode or the selected region in
|
|
|
|
# VISUAL mode. The line or region is extended to the next bigger syntactic
|
|
|
|
# entity.
|
|
|
|
#
|
2015-07-11 14:46:26 +08:00
|
|
|
# You can also pass in the variable "l:lines" to choose the range for
|
|
|
|
# formatting. This variable can either contain "<start line>:<end line>" or
|
|
|
|
# "all" to format the full file. So, to format the full file, write a function
|
|
|
|
# like:
|
|
|
|
# :function FormatFile()
|
|
|
|
# : let l:lines="all"
|
[clang-format] update comments in clang-format.py for python3 compatibility
Summary:
D23319 introduced python3 compatibility to clang-format.py, this is however not reflected by the documentation in the comments at the beginning of the file, which show how to use the script with python2 in .vimrc. While the actual mapping a user might want to use may well differ from my suggestion, I think it's nice to show the python2 and python3 version, such that a user can pick from the suggestions instead of googeling the python3 replacement for `:pyf` which they might not be familiar with.
EDIT: picking reviewers according to https://llvm.org/docs/Phabricator.html#finding-potential-reviewers
Reviewers: klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Subscribers: ilya-biryukov, cfe-commits, llvm-commits, ychen
Patch By: pseyfert
Tags: #clang-tools-extra, #llvm, #clang
Differential Revision: https://reviews.llvm.org/D38446
2019-11-08 21:15:45 +08:00
|
|
|
# : if has('python')
|
|
|
|
# : pyf <path-to-this-file>/clang-format.py
|
|
|
|
# : elseif has('python3')
|
|
|
|
# : py3f <path-to-this-file>/clang-format.py
|
|
|
|
# : endif
|
2015-07-11 14:46:26 +08:00
|
|
|
# :endfunction
|
|
|
|
#
|
2013-03-20 17:53:23 +08:00
|
|
|
# It operates on the current, potentially unsaved buffer and does not create
|
|
|
|
# or save any files. To revert a formatting, just undo.
|
2018-12-19 00:07:37 +08:00
|
|
|
from __future__ import absolute_import, division, print_function
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2013-07-21 18:45:33 +08:00
|
|
|
import difflib
|
2013-05-21 20:21:39 +08:00
|
|
|
import json
|
2016-12-10 08:54:13 +08:00
|
|
|
import platform
|
2013-03-20 17:53:23 +08:00
|
|
|
import subprocess
|
2013-06-10 22:16:26 +08:00
|
|
|
import sys
|
2013-05-21 20:21:39 +08:00
|
|
|
import vim
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2014-11-03 05:27:59 +08:00
|
|
|
# set g:clang_format_path to the path to clang-format if it is not on the path
|
2013-03-20 17:53:23 +08:00
|
|
|
# Change this to the full path if clang-format is not on the path.
|
|
|
|
binary = 'clang-format'
|
2014-11-04 18:40:26 +08:00
|
|
|
if vim.eval('exists("g:clang_format_path")') == "1":
|
2014-11-03 05:27:59 +08:00
|
|
|
binary = vim.eval('g:clang_format_path')
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2013-09-02 15:42:02 +08:00
|
|
|
# Change this to format according to other formatting styles. See the output of
|
|
|
|
# 'clang-format --help' for a list of supported styles. The default looks for
|
2013-09-10 23:41:12 +08:00
|
|
|
# a '.clang-format' or '_clang-format' file to indicate the style that should be
|
|
|
|
# used.
|
2019-05-17 15:22:55 +08:00
|
|
|
style = None
|
2015-04-17 15:59:19 +08:00
|
|
|
fallback_style = None
|
2015-04-16 16:26:37 +08:00
|
|
|
if vim.eval('exists("g:clang_format_fallback_style")') == "1":
|
|
|
|
fallback_style = vim.eval('g:clang_format_fallback_style')
|
2013-04-09 23:23:04 +08:00
|
|
|
|
2016-12-10 08:54:13 +08:00
|
|
|
def get_buffer(encoding):
|
|
|
|
if platform.python_version_tuple()[0] == '3':
|
|
|
|
return vim.current.buffer
|
|
|
|
return [ line.decode(encoding) for line in vim.current.buffer ]
|
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
def main():
|
|
|
|
# Get the current text.
|
2016-08-31 21:36:36 +08:00
|
|
|
encoding = vim.eval("&encoding")
|
2016-12-10 08:54:13 +08:00
|
|
|
buf = get_buffer(encoding)
|
[clang-format] update trailing newline treatment in clang-format.py
Summary:
The current clang-format.py does not handle trailing newlines at the end of a file correctly.
Trailing empty lines get removed except one.
As far as I understand this is because clang-format gets fed from stdin and writes to stdout when called from clang-format.py.
In a "normal" file (with no trailing empty lines) the string that gets passed to clang-format does not contain a trailing '\n' after the '\n'.join from python.
The clang-format binary does not add a trailing newline to input from stdin, but (if there are multiple trailing '\n', all except one get removed).
When reading back this means that we see in python from a "normal" file a string with no trailing '\n'. From a file with (potentially multiple) empty line(s) at the end, we get a string with one trailing '\n' back in python. In the former case all is fine, in the latter case split('\n') makes one empty line at the end of the file out of the clang-format output. Desired would be instead that the **file** ends with a newline, but not with an empty line.
For the case that a user specifies a range to format (and wants to keep trailing empty lines) I did **not** try to fix this by simply removing all trailing newlines from the clang-format output. Instead, I add a '\n' to the unformatted file content (i.e. newline-terminate what is passed to clang-format) and then strip off the last newline from the output (which itself is now for sure the newline termination of the clang-format output).
(Should this get approved, I'll need someone to help me land this.)
Reviewers: klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Patch By: pseyfert
Subscribers: cfe-commits, llvm-commits
Tags: #clang-format, #clang
Differential Revision: https://reviews.llvm.org/D70864
update trailing newline treatment in clang-format.py
2019-12-07 01:24:30 +08:00
|
|
|
# Join the buffer into a single string with a terminating newline
|
|
|
|
text = '\n'.join(buf) + '\n'
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
# Determine range to format.
|
2015-07-11 14:46:26 +08:00
|
|
|
if vim.eval('exists("l:lines")') == '1':
|
2017-08-22 22:28:01 +08:00
|
|
|
lines = ['-lines', vim.eval('l:lines')]
|
2017-06-19 15:30:04 +08:00
|
|
|
elif vim.eval('exists("l:formatdiff")') == '1':
|
|
|
|
with open(vim.current.buffer.name, 'r') as f:
|
|
|
|
ondisk = f.read().splitlines();
|
|
|
|
sequence = difflib.SequenceMatcher(None, ondisk, vim.current.buffer)
|
|
|
|
lines = []
|
|
|
|
for op in reversed(sequence.get_opcodes()):
|
|
|
|
if op[0] not in ['equal', 'delete']:
|
|
|
|
lines += ['-lines', '%s:%s' % (op[3] + 1, op[4])]
|
|
|
|
if lines == []:
|
|
|
|
return
|
2015-07-11 14:46:26 +08:00
|
|
|
else:
|
2017-06-19 15:30:04 +08:00
|
|
|
lines = ['-lines', '%s:%s' % (vim.current.range.start + 1,
|
|
|
|
vim.current.range.end + 1)]
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2014-05-22 19:37:05 +08:00
|
|
|
# Determine the cursor position.
|
|
|
|
cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
|
|
|
|
if cursor < 0:
|
2016-08-31 21:36:36 +08:00
|
|
|
print('Couldn\'t determine cursor position. Is your file empty?')
|
2014-05-22 19:37:05 +08:00
|
|
|
return
|
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
# Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
|
|
|
|
startupinfo = None
|
|
|
|
if sys.platform.startswith('win32'):
|
|
|
|
startupinfo = subprocess.STARTUPINFO()
|
|
|
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
|
|
|
startupinfo.wShowWindow = subprocess.SW_HIDE
|
2013-06-10 22:16:26 +08:00
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
# Call formatter.
|
2019-05-17 15:22:55 +08:00
|
|
|
command = [binary, '-cursor', str(cursor)]
|
2017-09-05 21:58:53 +08:00
|
|
|
if lines != ['-lines', 'all']:
|
2017-06-19 15:30:04 +08:00
|
|
|
command += lines
|
2019-05-17 15:22:55 +08:00
|
|
|
if style:
|
|
|
|
command.extend(['-style', style])
|
2015-04-16 16:26:37 +08:00
|
|
|
if fallback_style:
|
|
|
|
command.extend(['-fallback-style', fallback_style])
|
2014-03-11 06:12:14 +08:00
|
|
|
if vim.current.buffer.name:
|
|
|
|
command.extend(['-assume-filename', vim.current.buffer.name])
|
|
|
|
p = subprocess.Popen(command,
|
|
|
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
|
|
stdin=subprocess.PIPE, startupinfo=startupinfo)
|
2016-08-31 21:36:36 +08:00
|
|
|
stdout, stderr = p.communicate(input=text.encode(encoding))
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
# If successful, replace buffer contents.
|
|
|
|
if stderr:
|
2016-08-31 21:36:36 +08:00
|
|
|
print(stderr)
|
2013-03-20 17:53:23 +08:00
|
|
|
|
2014-03-11 06:12:14 +08:00
|
|
|
if not stdout:
|
2016-08-31 21:36:36 +08:00
|
|
|
print(
|
|
|
|
'No output from clang-format (crashed?).\n'
|
|
|
|
'Please report to bugs.llvm.org.'
|
|
|
|
)
|
2014-03-11 06:12:14 +08:00
|
|
|
else:
|
2016-08-31 21:36:36 +08:00
|
|
|
lines = stdout.decode(encoding).split('\n')
|
2014-03-11 06:12:14 +08:00
|
|
|
output = json.loads(lines[0])
|
[clang-format] update trailing newline treatment in clang-format.py
Summary:
The current clang-format.py does not handle trailing newlines at the end of a file correctly.
Trailing empty lines get removed except one.
As far as I understand this is because clang-format gets fed from stdin and writes to stdout when called from clang-format.py.
In a "normal" file (with no trailing empty lines) the string that gets passed to clang-format does not contain a trailing '\n' after the '\n'.join from python.
The clang-format binary does not add a trailing newline to input from stdin, but (if there are multiple trailing '\n', all except one get removed).
When reading back this means that we see in python from a "normal" file a string with no trailing '\n'. From a file with (potentially multiple) empty line(s) at the end, we get a string with one trailing '\n' back in python. In the former case all is fine, in the latter case split('\n') makes one empty line at the end of the file out of the clang-format output. Desired would be instead that the **file** ends with a newline, but not with an empty line.
For the case that a user specifies a range to format (and wants to keep trailing empty lines) I did **not** try to fix this by simply removing all trailing newlines from the clang-format output. Instead, I add a '\n' to the unformatted file content (i.e. newline-terminate what is passed to clang-format) and then strip off the last newline from the output (which itself is now for sure the newline termination of the clang-format output).
(Should this get approved, I'll need someone to help me land this.)
Reviewers: klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Patch By: pseyfert
Subscribers: cfe-commits, llvm-commits
Tags: #clang-format, #clang
Differential Revision: https://reviews.llvm.org/D70864
update trailing newline treatment in clang-format.py
2019-12-07 01:24:30 +08:00
|
|
|
# Strip off the trailing newline (added above).
|
|
|
|
# This maintains trailing empty lines present in the buffer if
|
|
|
|
# the -lines specification requests them to remain unchanged.
|
|
|
|
lines = lines[1:-1]
|
2016-10-27 21:46:49 +08:00
|
|
|
sequence = difflib.SequenceMatcher(None, buf, lines)
|
2014-03-11 06:12:14 +08:00
|
|
|
for op in reversed(sequence.get_opcodes()):
|
2019-12-07 01:36:56 +08:00
|
|
|
if op[0] != 'equal':
|
2014-03-11 06:12:14 +08:00
|
|
|
vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
|
2015-06-05 05:23:07 +08:00
|
|
|
if output.get('IncompleteFormat'):
|
2016-08-31 21:36:36 +08:00
|
|
|
print('clang-format: incomplete (syntax errors)')
|
2014-03-11 06:12:14 +08:00
|
|
|
vim.command('goto %d' % (output['Cursor'] + 1))
|
|
|
|
|
|
|
|
main()
|