|
# -*- coding: utf-8 -*- |
|
import os |
|
|
|
|
|
def doctree_resolved(app, doctree, docname): |
|
|
|
filename = os.path.join(app.confdir, app.config.ctags_filename) |
|
|
|
# load existent ctag |
|
ctags = load_ctag(filename) |
|
|
|
# purge old ctag entries |
|
#TODO: remove entries by using 'docname' |
|
|
|
# build domain related references |
|
domains_db = get_current_doc_references(app, docname) |
|
|
|
# process reference targets |
|
ctags = update_ctags(app, doctree, docname, ctags, domains_db) |
|
|
|
# write to tags file |
|
save_ctags(filename, ctags) |
|
|
|
#app.info('updating ctag file: {filename}.'.format(filename=filename)) |
|
|
|
|
|
def load_ctag(filename): |
|
ctags = {} |
|
if os.path.exists(filename): |
|
for line in open(filename, 'rt'): |
|
try: |
|
idx, src, line = line.strip().split('\t') |
|
ctags[idx] = (src, line) |
|
except ValueError: |
|
pass #skip broken line |
|
|
|
return ctags |
|
|
|
|
|
def get_current_doc_references(app, current_docname): |
|
refs = {} |
|
for domainname, domain in app.env.domains.iteritems(): |
|
for name, dispname, type, docname, anch, prio in domain.get_objects(): |
|
if docname == current_docname: |
|
# overwrite if name already exist by another domain... |
|
refs[name] = [domainname, type, dispname, anch, prio] |
|
return refs |
|
|
|
|
|
def update_ctags(app, doctree, docname, ctags, domains_db): |
|
def node_filter(node): |
|
try: |
|
return bool(node['ids']) |
|
except: |
|
return False |
|
|
|
for node in doctree.traverse(node_filter): |
|
for id in node['ids']: |
|
if id in domains_db: |
|
ctags[id] = node_to_db_entry( |
|
node, app.srcdir, app.config.ctags_relpath) |
|
|
|
# document xref |
|
idx = '/' + docname |
|
ctags[idx] = node_to_db_entry( |
|
doctree.next_node(), app.srcdir, app.config.ctags_relpath) |
|
|
|
return ctags |
|
|
|
|
|
def node_to_db_entry(node, basedir, use_relpath=True): |
|
path = node.source |
|
if use_relpath: |
|
path = os.path.relpath(path, basedir) |
|
|
|
return (path, str(node.line)) |
|
|
|
|
|
def save_ctags(filename, ctags): |
|
with open(filename, 'wt') as f: |
|
for idx in sorted(ctags.keys()): |
|
f.write(idx + '\t') |
|
f.write('\t'.join(ctags[idx])) |
|
f.write('\n') |
|
|
|
|
|
def setup(app): |
|
app.add_config_value('ctags_filename', 'tags', False) |
|
app.add_config_value('ctags_relpath', True, False) |
|
app.connect('doctree-resolved', doctree_resolved) |