diff --git a/hitags.py b/hitags.py index 6a43b34..f741c35 100755 --- a/hitags.py +++ b/hitags.py @@ -9,27 +9,31 @@ input_filename = '' preprocessor='clang -fdirectives-only -E {input_} -o {output}' tags_filename = 'vim.tags' polution_directory = './' +action = 'hi' def print2(s): print(s, file=sys.stderr) def usage(name, x): - print2("Usage: {0} ".format(name)) + print2("Usage: {0} ".format(name)) print2("\t-h") - print2("\t-i ") - print2("\t-p ") - print2("\t-t ") + print2("\t-i : input") + print2("\t-p : preprocessor (e.g.: 'clang -fdirectives-only -E {input_} -o {output}')") + print2("\t-t : polution directory") + print2("\t---") + print2("\thi") + print2("\tsig") exit(x) def opts(args): - global input_filename, preprocessor, polution_directory + global input_filename, preprocessor, polution_directory, action try: i = args.index("--help") if "--help" in args else -1 if i != -1: usage(args[0], 1) else: - for idx, arg in enumerate(args[1:]): + for idx, arg in enumerate(args[1:]): # this is terrible if arg in ("-h", "--help"): usage(args[0], 0) elif arg == "-i": @@ -38,6 +42,10 @@ def opts(args): preprocessor = args[idx + 2] elif arg == "-t": polution_directory = args[idx + 2] + elif arg == "hi": + action = "hi" + elif arg == "sig": + action = "sig" except IndexError: usage(args[0], 1) if input_filename == '': @@ -79,7 +87,7 @@ targets = [ 'type': 'u', 'out': hi('Type') }, - { + { 'type': 'g', 'out': hi('Type') }, @@ -92,15 +100,16 @@ targets = [ 'out': hi('Identifier') }, ] -PATTERN_INDEX = 1 - 1 -TYPE_INDEX = 4 - 1 +NAME_INDEX = (1) - 1 +PATTERN_INDEX = (3) - 1 +TYPE_INDEX = (4) - 1 def do_ignore(row): IGNORE_IF_BEGINS_WITH = '!_' for i in IGNORE_IF_BEGINS_WITH: if row[0][0] == i: return True - if row[PATTERN_INDEX].find('operator') != -1: + if row[NAME_INDEX].find('operator') != -1: return True return False @@ -131,7 +140,7 @@ def file2tags(filename, flags): def tags2hi(filename): output = set() - print2(filename) + #print2(filename) try: with open(filename) as f: csv_reader = csv.reader(f, delimiter='\t') @@ -141,14 +150,41 @@ def tags2hi(filename): for t in targets: try: if t['type'] == row[TYPE_INDEX]: - output.add(render(t, re.escape(row[PATTERN_INDEX]))) + output.add(render(t, re.escape(row[NAME_INDEX]))) except: - print2(row) + #print2(row) + pass except FileNotFoundError as e: print2(sys.argv[0] + ": No such file or directory '{0}'.".format(filename)) exit(1) return output +def pattern2signature(name, pattern): + start = pattern.find(name) + if pattern.find(')') != -1: + end = pattern.find(')') + 1 + else: + end = pattern.find('$') + return pattern[start : end] + +has_signature = ['f', 'p'] + +def tags2sigs(filename): + output = dict() + #print2(filename) + with open(filename) as f: + csv_reader = csv.reader(f, delimiter='\t') + for row in csv_reader: + if do_ignore(row): + continue + if row[TYPE_INDEX] in has_signature: + signature = pattern2signature(row[NAME_INDEX], row[PATTERN_INDEX]) + if row[NAME_INDEX] in output: + output[row[NAME_INDEX]].append(signature) + else: + output[row[NAME_INDEX]] = [signature] + return output + def main(argv): global input_filename opts(argv) @@ -162,9 +198,12 @@ def main(argv): if language != '': input_filename = preprocessfile(input_filename) flags += ' --language-force={0} '.format(language) - output = tags2hi(file2tags(input_filename, flags)) - output = sorted(output) - output = '\n'.join(output) + if action == 'hi': + output = tags2hi(file2tags(input_filename, flags)) + output = sorted(output) + output = '\n'.join(output) + elif action == 'sig': + output = "let signatures = " + str(tags2sigs(file2tags(input_filename, flags))) print(output) if __name__ == '__main__': diff --git a/hitags.vim b/hitags.vim index 1455ecf..8c0a96c 100644 --- a/hitags.vim +++ b/hitags.vim @@ -11,28 +11,83 @@ " otherwise you are responsible for creating your own let s:polution_directory = expand('~/.vim/plugin/HiTags/') -" Compiler to use for preprocessing C/C++, so headers are respected -" Either use "clang" or "gcc" or something compatible, -" alternatively you will have to edit s:preprocessor -let s:preprocessor_executable = "clang" +" Compiler_Collection_based_Preprocessing: +if 0 + " Compiler to use for preprocessing C/C++, so headers are respected + " Either use "clang" or "gcc" or something compatible, + " alternatively you will have to edit s:preprocessor + let s:preprocessor_executable = "clang" + "let s:preprocessor_executable = "gcc" + let s:preprocessor = s:preprocessor_executable . ' -fdirectives-only -E {input_} -o {output}' +endif + +" Stand_alone_preprocessor: +" The only implementation i know is fcpp (https://github.com/bagder/fcpp.git) +" However, it has the major advantage that it will only warn on missing +" headers and not error. Meaning a tool chain using '-I' doesn't break +" everything. +let s:preprocessor = "fcpp -LL {input_} {output}" " --- --------------------------- --- " --- Don't Touch --- " --- Unless --- " --- You know What You Are Doing --- " --- --------------------------- --- -let s:preprocessor = s:preprocessor_executable . ' -fdirectives-only -E {input_} -o {output}' let s:tags_filename = 'tags' let s:tags_file = expand(s:polution_directory) . s:tags_filename let s:tags_scriptname = 'tags.vim' let s:tags_script = expand(s:polution_directory) . 'tags.vim' +let s:sigs_script = expand(s:polution_directory) . 'sigs.vim' " let s:generator_script = expand('~/.vim/plugin/HiTags/hitags.py') -let s:generation_command = 'python ' . s:generator_script . +let s:generation_command = + \ 'python ' . s:generator_script . \ ' -i ' . '"' . expand('%:p') . '"' . \ ' -p ' . '"' . s:preprocessor . '"' . \ ' -t ' . '"' . s:polution_directory . '"' . - \ ' > ' . '"' . s:tags_script . '"' + \ ' hi ' . + \ ' > ' . '"' . s:tags_script . '"' . + \ ';' . + \ 'python ' . s:generator_script . + \ ' -i ' . '"' . expand('%:p') . '"' . + \ ' -p ' . '"' . s:preprocessor . '"' . + \ ' -t ' . '"' . s:polution_directory . '"' . + \ ' sig ' . + \ ' > ' . '"' . s:sigs_script . '"' + +" --- Signature stuff --- +function! SigDebug() + echo s:generation_command +endfunction + + +function! SigInit() + let g:signatures = {} + + autocmd TextChangedI * call SigPopup() +endfunction + +call SigInit() + +function! SigPopup() + let key = matchstr(getline('.')[:col('.')-2], '\k\+$') + if has_key(g:signatures, key) + call popup_atcursor(g:signatures[key], #{} ) + endif +endfunction + +function! Sig() + execute 'source ' . s:sigs_script +endfunction + +if exists('g:sigs_events') + for e in g:sigs_events + execute "autocmd " . e . " * Sig" + endfor +endif + +command! Sig :call Sig() +" --- --- --- function! HiTagsUpdate() let pid = system(s:generation_command)