Skip to content

Instantly share code, notes, and snippets.

@shimizukawa
Created November 30, 2012 03:38
Show Gist options
  • Save shimizukawa/4173639 to your computer and use it in GitHub Desktop.
Save shimizukawa/4173639 to your computer and use it in GitHub Desktop.
ctags file generator for sphinx
# -*- 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)
/chapter1 chapter1.rst 3
/chapter2 chapter2.rst 1
/chapter3 chapter3.rst 3
/index index.rst 5
/test test.rst 2
chap2 chapter2.rst 5
foo index.rst 20
spam chapter1.rst 9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment