From 617574713a44ebbd4c40a018d625d89c34ddb51e Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Sun, 31 Jul 2022 00:19:27 +0200 Subject: [PATCH] vim: add tool from compile_commands.json Comming from https://github.com/whatacold/texttoolkit fork https://raw.githubusercontent.com/cerg2010cerg2010/texttoolkit/master/cdg.py --- .vim/plugin/cdg.py | 116 ++++++++++++++++++++++++++++++++++++ .vim/plugin/cscope_plus.vim | 7 ++- 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100755 .vim/plugin/cdg.py diff --git a/.vim/plugin/cdg.py b/.vim/plugin/cdg.py new file mode 100755 index 0000000..84ff973 --- /dev/null +++ b/.vim/plugin/cdg.py @@ -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.*)[`\'\"]\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() diff --git a/.vim/plugin/cscope_plus.vim b/.vim/plugin/cscope_plus.vim index 3ce3c7b..2e7773d 100644 --- a/.vim/plugin/cscope_plus.vim +++ b/.vim/plugin/cscope_plus.vim @@ -116,12 +116,15 @@ func! MenuCB(id, result) execute "!compiledb -n" g:build_cmd elseif a:result == 8 "https://github.com/rizsotto/scan-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 - "Add -DCMAKE_EXPORT_COMPILE_COMMANDS=ON with cmake build endfunc 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, \ callback: 'MenuCB', highlight: 'Question', padding: [1,1,0,1]} )