Changeset View
Changeset View
Standalone View
Standalone View
include-fixer/tool/clang-include-fixer.py
Show All 13 Lines | |||||
# | # | ||||
# It operates on the current, potentially unsaved buffer and does not create | # It operates on the current, potentially unsaved buffer and does not create | ||||
# or save any files. To revert a fix, just undo. | # or save any files. To revert a fix, just undo. | ||||
import argparse | import argparse | ||||
import difflib | import difflib | ||||
import subprocess | import subprocess | ||||
import vim | import vim | ||||
import json | |||||
bkramer: We cannot rely on python-yaml being available, I don't want users to install python modules… | |||||
# set g:clang_include_fixer_path to the path to clang-include-fixer if it is not | # set g:clang_include_fixer_path to the path to clang-include-fixer if it is not | ||||
# on the path. | # on the path. | ||||
# Change this to the full path if clang-include-fixer is not on the path. | # Change this to the full path if clang-include-fixer is not on the path. | ||||
binary = 'clang-include-fixer' | binary = 'clang-include-fixer' | ||||
if vim.eval('exists("g:clang_include_fixer_path")') == "1": | if vim.eval('exists("g:clang_include_fixer_path")') == "1": | ||||
binary = vim.eval('g:clang_include_fixer_path') | binary = vim.eval('g:clang_include_fixer_path') | ||||
Show All 14 Lines | |||||
def execute(command, text): | def execute(command, text): | ||||
p = subprocess.Popen(command, | p = subprocess.Popen(command, | ||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, | stdout=subprocess.PIPE, stderr=subprocess.PIPE, | ||||
stdin=subprocess.PIPE) | stdin=subprocess.PIPE) | ||||
return p.communicate(input=text) | return p.communicate(input=text) | ||||
def InsertHeaderToVimBuffer(header, text): | def InsertHeaderToVimBuffer(header, text): | ||||
command = [binary, "-stdin", "-insert-header="+header, | command = [binary, "-stdin", "-insert-header="+json.dumps(header), | ||||
vim.current.buffer.name] | vim.current.buffer.name] | ||||
stdout, stderr = execute(command, text) | stdout, stderr = execute(command, text) | ||||
if stdout: | if stdout: | ||||
lines = stdout.splitlines() | lines = stdout.splitlines() | ||||
sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines) | sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines) | ||||
for op in reversed(sequence.get_opcodes()): | for op in reversed(sequence.get_opcodes()): | ||||
if op[0] is not 'equal': | if op[0] is not 'equal': | ||||
vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]] | vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]] | ||||
Show All 11 Lines | def main(): | ||||
# Get the current text. | # Get the current text. | ||||
buf = vim.current.buffer | buf = vim.current.buffer | ||||
text = '\n'.join(buf) | text = '\n'.join(buf) | ||||
# Run command to get all headers. | # Run command to get all headers. | ||||
command = [binary, "-stdin", "-output-headers", "-db="+args.db, | command = [binary, "-stdin", "-output-headers", "-db="+args.db, | ||||
"-input="+args.input, vim.current.buffer.name] | "-input="+args.input, vim.current.buffer.name] | ||||
stdout, stderr = execute(command, text) | stdout, stderr = execute(command, text) | ||||
lines = stdout.splitlines() | if stderr: | ||||
if len(lines) < 2: | print >> sys.stderr, "Error while running clang-include-fixer: " + stderr | ||||
print "No header is included.\n" | return | ||||
include_fixer_context = json.loads(stdout) | |||||
symbol = include_fixer_context["SymbolIdentifier"] | |||||
headers = include_fixer_context["Headers"] | |||||
if not symbol: | |||||
print "The file is fine, no need to add a header.\n" | |||||
return; | |||||
if not headers: | |||||
print "Couldn't find a header for {0}.\n".format(symbol) | |||||
return | return | ||||
# The first line is the symbol name. | # The first line is the symbol name. | ||||
symbol = lines[0] | |||||
# If there is only one suggested header, insert it directly. | # If there is only one suggested header, insert it directly. | ||||
if len(lines) == 2 or maximum_suggested_headers == 1: | if len(headers) == 1 or maximum_suggested_headers == 1: | ||||
InsertHeaderToVimBuffer(lines[1], text) | InsertHeaderToVimBuffer({"SymbolIdentifier": symbol, | ||||
print "Added #include {0} for {1}.\n".format(lines[1], symbol) | "Headers":[headers[0]]}, text) | ||||
print "Added #include {0} for {1}.\n".format(headers[0], symbol) | |||||
return | return | ||||
choices_message = "" | choices_message = "" | ||||
index = 1; | index = 1; | ||||
for header in lines[1:1+maximum_suggested_headers]: | for header in headers[0:maximum_suggested_headers]: | ||||
choices_message += "&{0} {1}\n".format(index, header) | choices_message += "&{0} {1}\n".format(index, header) | ||||
index += 1 | index += 1 | ||||
select = ShowDialog("choose a header file for {0}.".format(symbol), | select = ShowDialog("choose a header file for {0}.".format(symbol), | ||||
choices_message) | choices_message) | ||||
# Insert a selected header. | # Insert a selected header. | ||||
InsertHeaderToVimBuffer(lines[select], text) | InsertHeaderToVimBuffer({"SymbolIdentifier": symbol, | ||||
print "Added #include {0} for {1}.\n".format(lines[select], symbol) | "Headers":[headers[select-1]]}, text) | ||||
print "Added #include {0} for {1}.\n".format(headers[select-1], symbol) | |||||
return; | return; | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
main() | main() |
We cannot rely on python-yaml being available, I don't want users to install python modules just to run include-fixer. Can we restrict ourselves to the JSON subset of YAML here?