20 from __future__
import print_function
31 binary =
'clang-include-fixer'
32 if vim.eval(
'exists("g:clang_include_fixer_path")') ==
"1":
33 binary = vim.eval(
'g:clang_include_fixer_path')
35 maximum_suggested_headers = 3
36 if vim.eval(
'exists("g:clang_include_fixer_maximum_suggested_headers")') ==
"1":
37 maximum_suggested_headers = max(
39 vim.eval(
'g:clang_include_fixer_maximum_suggested_headers'))
42 if vim.eval(
'exists("g:clang_include_fixer_increment_num")') ==
"1":
45 vim.eval(
'g:clang_include_fixer_increment_num'))
47 jump_to_include =
False
48 if vim.eval(
'exists("g:clang_include_fixer_jump_to_include")') ==
"1":
49 jump_to_include = vim.eval(
'g:clang_include_fixer_jump_to_include') !=
"0"
52 if vim.eval(
'exists("g:clang_include_fixer_query_mode")') ==
"1":
53 query_mode = vim.eval(
'g:clang_include_fixer_query_mode') !=
"0"
57 eval_message = message +
'\n'
58 for idx, header
in enumerate(headers[0:maximum_suggested_headers]):
59 eval_message +=
"({0}). {1}\n".format(idx + 1, header)
60 eval_message +=
"Enter (q) to quit;"
61 if maximum_suggested_headers < len(headers):
62 eval_message +=
" (m) to show {0} more candidates.".format(
63 min(increment_num, len(headers) - maximum_suggested_headers))
65 eval_message +=
"\nSelect (default 1): "
66 res = vim.eval(
"input('{0}')".format(eval_message))
71 raise Exception(
' Insertion cancelled...')
74 headers, maximum_suggested_headers + increment_num)
78 if idx <= 0
or idx > len(headers):
83 print(
"Invalid option: {}".format(res), file=sys.stderr)
85 return headers[idx - 1]
91 if sys.platform.startswith(
'win32'):
92 startupinfo = subprocess.STARTUPINFO()
93 startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
94 startupinfo.wShowWindow = subprocess.SW_HIDE
96 p = subprocess.Popen(command,
97 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
98 stdin=subprocess.PIPE, startupinfo=startupinfo)
99 return p.communicate(input=text.encode(
'utf-8'))
103 command = [binary,
"-stdin",
"-insert-header=" + json.dumps(header),
104 vim.current.buffer.name]
105 stdout, stderr =
execute(command, text)
107 raise Exception(stderr)
109 lines = stdout.splitlines()
110 sequence = difflib.SequenceMatcher(
None, vim.current.buffer, lines)
112 for op
in reversed(sequence.get_opcodes()):
114 vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
115 if op[0] ==
'insert':
119 if jump_to_include
and line_num:
120 vim.current.window.cursor = (line_num, 0)
126 line = vim.eval(
"line(\".\")")
128 col = int(vim.eval(
"col(\".\")")) - 1
129 line_text = vim.eval(
"getline({0})".format(line))
130 if len(line_text) == 0:
return ""
131 symbol_pos_begin = col
132 p = re.compile(
'[a-zA-Z0-9:_]')
133 while symbol_pos_begin >= 0
and p.match(line_text[symbol_pos_begin]):
134 symbol_pos_begin -= 1
137 while symbol_pos_end < len(line_text)
and p.match(line_text[symbol_pos_end]):
139 return line_text[symbol_pos_begin+1:symbol_pos_end]
143 parser = argparse.ArgumentParser(
144 description=
'Vim integration for clang-include-fixer')
145 parser.add_argument(
'-db', default=
'yaml',
146 help=
'clang-include-fixer input format.')
147 parser.add_argument(
'-input', default=
'',
148 help=
'String to initialize the database.')
154 args, _ = parser.parse_known_args()
157 buf = vim.current.buffer
158 text =
'\n'.
join(buf)
163 print(
"Skip querying empty symbol.")
166 "-db=" + args.db,
"-input=" + args.input,
167 vim.current.buffer.name]
170 command = [binary,
"-stdin",
"-output-headers",
"-db=" + args.db,
171 "-input=" + args.input, vim.current.buffer.name]
172 stdout, stderr =
execute(command, text)
174 print(
"Error while running clang-include-fixer: {}".format(stderr),
178 include_fixer_context = json.loads(stdout)
179 query_symbol_infos = include_fixer_context[
"QuerySymbolInfos"]
180 if not query_symbol_infos:
181 print(
"The file is fine, no need to add a header.")
183 symbol = query_symbol_infos[0][
"RawIdentifier"]
185 header_infos = include_fixer_context[
"HeaderInfos"]
190 for header_info
in header_infos:
191 header = header_info[
"Header"]
192 if header
not in seen:
194 unique_headers.append(header)
196 if not unique_headers:
197 print(
"Couldn't find a header for {0}.".format(symbol))
201 selected = unique_headers[0]
202 inserted_header_infos = header_infos
203 if len(unique_headers) > 1:
205 "choose a header file for {0}.".format(symbol),
206 unique_headers, maximum_suggested_headers)
207 inserted_header_infos = [
208 header
for header
in header_infos
if header[
"Header"] == selected]
209 include_fixer_context[
"HeaderInfos"] = inserted_header_infos
212 print(
"Added #include {0} for {1}.".format(selected, symbol))
213 except Exception
as error:
214 print(error, file=sys.stderr)
218 if __name__ ==
'__main__':