vim: add tool from compile_commands.json
Comming from https://github.com/whatacold/texttoolkit fork https://raw.githubusercontent.com/cerg2010cerg2010/texttoolkit/master/cdg.py
This commit is contained in:
parent
d303604a24
commit
617574713a
116
.vim/plugin/cdg.py
Executable file
116
.vim/plugin/cdg.py
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
'''A simple compilation database generator, or cdg in short.
|
||||||
|
|
||||||
|
It works by parsing the output of the GNU make command.'''
|
||||||
|
|
||||||
|
file_name_regex = re.compile(r"[\w./+\-]+\.(s|cc?|cpp|cxx)\b",
|
||||||
|
re.IGNORECASE)
|
||||||
|
enter_dir_regex = re.compile(r"^\s*make(?:\[\d+\])?: Entering directory [`\'\"](?P<dir>.*)[`\'\"]\s*$",
|
||||||
|
re.MULTILINE)
|
||||||
|
leave_dir_regex = re.compile(r"^\s*make(?:\[\d+\])?: Leaving directory .*$",
|
||||||
|
re.MULTILINE)
|
||||||
|
compilers_regex = re.compile(r'\b(g?cc|[gc]\+\+|clang\+?\+?|icecc|s?ccache)\s')
|
||||||
|
|
||||||
|
|
||||||
|
def parse(make_output):
|
||||||
|
'''Parse the make output into a list of objects.
|
||||||
|
|
||||||
|
Per https://clang.llvm.org/docs/JSONCompilationDatabase.html
|
||||||
|
'''
|
||||||
|
result = []
|
||||||
|
pwd = ""
|
||||||
|
path_stack = []
|
||||||
|
for line in make_output.replace('\r', '').split('\n'):
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
enter_dir_match = enter_dir_regex.match(line)
|
||||||
|
if enter_dir_match:
|
||||||
|
pwd = enter_dir_match.group('dir')
|
||||||
|
path_stack.append(pwd)
|
||||||
|
# logger.debug("stack after append: {}".format(path_stack))
|
||||||
|
continue
|
||||||
|
elif leave_dir_regex.match(line):
|
||||||
|
# logger.debug("stack before pop: {}".format(path_stack))
|
||||||
|
path_stack.pop()
|
||||||
|
if path_stack:
|
||||||
|
pwd = path_stack[-1]
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = compilers_regex.search(line)
|
||||||
|
if not match:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# look backward and discard anything before delimiters
|
||||||
|
i = match.start()
|
||||||
|
while i > 0:
|
||||||
|
j = i - 1
|
||||||
|
if line[j] in (' ', '\t', '\n', ';', '&'):
|
||||||
|
break
|
||||||
|
i -= 1
|
||||||
|
line = line[i:]
|
||||||
|
|
||||||
|
file_match = file_name_regex.search(line)
|
||||||
|
# logger.debug(line, file_match)
|
||||||
|
if not file_match:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# To workaround that there is no "entering directory..."
|
||||||
|
if not pwd:
|
||||||
|
pwd = "/path/to/your/project/"
|
||||||
|
path_stack.append(pwd)
|
||||||
|
|
||||||
|
# Special handling for projects like Redis,
|
||||||
|
# which has output like "printf xxx; cc xxx"
|
||||||
|
command = line
|
||||||
|
ri = command.rfind(';')
|
||||||
|
if -1 != ri:
|
||||||
|
command = command[:ri]
|
||||||
|
ri = command.rfind('&&')
|
||||||
|
if -1 != ri:
|
||||||
|
command = command[:ri]
|
||||||
|
|
||||||
|
result.append({
|
||||||
|
"directory": pwd.strip(),
|
||||||
|
"file": file_match.group(0).strip(),
|
||||||
|
"command": command.strip(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print('''Usage: {} [compilation-db-file]
|
||||||
|
|
||||||
|
[compilation-db-file] is optional, which is `compile_commands.json` by default.
|
||||||
|
Specify it if you want to write to another file, and specify `-` for stdout.
|
||||||
|
|
||||||
|
This CLI program takes GNU make output from stdin from a pipe,
|
||||||
|
parse it, and write the json string to a file.
|
||||||
|
'''.format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
make_output = sys.stdin.read().strip()
|
||||||
|
if not make_output:
|
||||||
|
usage()
|
||||||
|
|
||||||
|
db = json.dumps(parse(make_output),
|
||||||
|
indent=2) + '\n'
|
||||||
|
file_name = 'compile_commands.json' if len(sys.argv) == 1 else sys.argv[1]
|
||||||
|
if '-' != file_name:
|
||||||
|
with open(file_name, "w") as f:
|
||||||
|
f.write(db)
|
||||||
|
else:
|
||||||
|
sys.stdout.write(db)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -116,12 +116,15 @@ func! MenuCB(id, result)
|
|||||||
execute "!compiledb -n" g:build_cmd
|
execute "!compiledb -n" g:build_cmd
|
||||||
elseif a:result == 8 "https://github.com/rizsotto/scan-build
|
elseif a:result == 8 "https://github.com/rizsotto/scan-build
|
||||||
execute "!analyze-build"
|
execute "!analyze-build"
|
||||||
|
elseif a:result == 9
|
||||||
|
execute "!make clean > /dev/null && make -nw | python ~/.vim/plugin/cdg.py "
|
||||||
|
elseif a:result == 10
|
||||||
|
echo "Add -DCMAKE_EXPORT_COMPILE_COMMANDS=ON to cmake. On modify build option with ccmake"
|
||||||
endif
|
endif
|
||||||
"Add -DCMAKE_EXPORT_COMPILE_COMMANDS=ON with cmake build
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
command! ShowMenuCodeDb
|
command! ShowMenuCodeDb
|
||||||
\ :call popup_menu(['tag/csope', 'tag/cscope Kernel', 'Autotags update', 'Autotags add dependancy','simple compile_commands', 'bear', "compiledb", "analyse build"], #{
|
\ :call popup_menu(['tag/csope', 'tag/cscope Kernel', 'Autotags update', 'Autotags add dependancy','simple compile_commands', 'bear', "compiledb", "analyse build", "rebuild with make parsing", "cmake option"], #{
|
||||||
\ title: "Code database for ".g:build_cmd,
|
\ title: "Code database for ".g:build_cmd,
|
||||||
\ callback: 'MenuCB', highlight: 'Question', padding: [1,1,0,1]} )
|
\ callback: 'MenuCB', highlight: 'Question', padding: [1,1,0,1]} )
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user