Permalink
Browse files

Embed rst2ctags in tool directory for convenience.

  • Loading branch information...
drmikehenry authored and jszakmeister committed Feb 19, 2013
1 parent e1665fc commit a28e39c57856e4a01f79dcec76372f44d6c1cfa2
View
@@ -1452,7 +1452,8 @@ distributions. Compiled binaries may be found at
http://ctags.sourceforge.net/
Added support for reStructuredText using rst2ctags. rst2ctags can be found
-at https://bitbucket.org/bernh/rst2ctags
+at https://bitbucket.org/bernh/rst2ctags, and a copy has been embedded
+in $VIMFILES/tool/rst2ctags.
------------------------------------------------------------------------------
TCOMMENT *notes_tcomment*
View
@@ -0,0 +1,19 @@
+Copyright (c) 2009 Bernhard Leiner <bleiner@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
@@ -0,0 +1,6 @@
+TODO
+====
+
+- check compatibility with the tagbar and taglist-plus vim plugins
+- add proper testsuite
+- think about special sphinx support
Binary file not shown.
@@ -0,0 +1,93 @@
+*********
+rst2ctags
+*********
+
+Goals
+=====
+
+rst2ctags was started with two milestones in mind:
+
+1. Generating a *tags* file from one ore more `rst`_ files.
+
+ Instead of adding rst support to ctags in the usual way by writing a
+ new language parser in C, I decided to use the available docutils
+ Python package for the hard part - the parsing.
+
+2. Integration into `Vim`_ via the `taglist`_ plugin.
+
+Usage
+=====
+
+Generate plain tags file
+------------------------
+
+The basic command line usage is compatible with `ctags`_::
+
+ rst2ctags [options] [file(s)]
+
+ CTAGS-Specific Options
+ ----------------------
+ -f <FILE> Write tags to specified file (default: "tags"). Value
+ of "-" writes tags to stdout.
+ -R Recurse into directories supplied on command line
+ --sort=[yes|no] Should tags be sorted by name? Default is "no", which
+ will sort by line number.
+ --taglist Compatibility mode in order to be used as main ctags
+ executable for the taglist Vim plugin.
+
+Integration into Vim
+--------------------
+
+As mentioned above, integration into Vim is possible by using the
+taglist plugin. Please add the following line to your ``.vimrc``
+to configure taglist to use rst2ctags instead of the ctags executable::
+
+ let Tlist_Ctags_Cmd = '/path/to/rst2ctags --taglist'
+ let tlist_rst_settings = 'rst;s:sections;i:images'
+
+If called with the ``--taglist`` option, rst2ctags is interface
+compatible with ctags (at least as far as the usage by taglist in
+concerned) and will transparently call the ctags executable for other
+languages than rst.
+
+Screenshot
+~~~~~~~~~~
+
+*sections* and *images* from the currently loaded file (the rst version
+of this html page) are shown in the taglist window on the left.
+
+.. image:: rst2ctags.png
+ :width: 540px
+
+Download
+========
+
+The `complete repository
+<http://bitbucket.org/bernh/rst2ctags/>`_ is hosted on bitbucket and can
+be cloned by::
+
+ hg clone https://bernh@bitbucket.org/bernh/rst2ctags/
+
+
+Or download the
+`lastest version <http://bitbucket.org/bernh/rst2ctags/get/tip.zip>`_.
+
+Future
+======
+
+I consider *rst2ctags* feature complete and won't spend much work in
+improvments since I don't use vanilla Vim that much any more. Please
+have a look at `pida-rst-plugin`_ which can be considered as successor
+project.
+
+Anyway, if you have any feature requests or bug reports, please create
+`a new issue <http://bitbucket.org/bernh/rst2ctags/issues/>`_.
+
+
+.. _`Vim`: http://www.vim.org/
+.. _`rst`: http://docutils.sourceforge.net/rst.html
+.. _`taglist`: http://vim-taglist.sourceforge.net/
+.. _`ctags`: http://ctags.sourceforge.net/
+.. _`rst2ctags`: http://bernh.net/projects/rst2ctags/
+.. _`pida-rst-plugin`: http://bernh.net/projects/pida-rst-plugin/
+
View
@@ -0,0 +1,192 @@
+#! /usr/bin/env python
+
+"""
+Copyright 2009-2011 Bernhard Leiner <bleiner@gmail.com>
+
+This software may be used and distributed according to the terms of the
+MIT license, incorporated herein by reference.
+"""
+
+import os
+import sys
+from optparse import OptionParser
+
+from docutils import nodes
+from docutils.core import publish_doctree
+
+__version__ = "1.0"
+
+class Tag(object):
+
+ SRO = "|" # scope resolution operator
+
+ def __init__(self, tagid, tagfile, tagaddress, tagtype, linenr,
+ level = 0, parent = None):
+ self.tagid = tagid
+ self.tagfile = tagfile
+ self.tagaddress = tagaddress
+ self.tagtype = tagtype
+ self.linenr = linenr
+ self.level = level
+ if level == 0:
+ self.scope = None
+ elif level == 1:
+ self.scope = parent.tagid if parent else None
+ elif level > 1:
+ self.scope = (Tag.SRO.join((parent.scope, parent.tagid))
+ if (parent and parent.scope and parent.tagid)
+ else None)
+ self.parent = parent
+
+ def __str__(self):
+ base_info = "{0}\t{1}\t{2}\t{3}".format \
+ (self.tagid, self.tagfile, self.tagaddress, self.tagtype)
+ # add line info
+ line_info = "\tline:{0:d}".format(self.linenr)
+ # add full scope information
+ scope_info = ("\tsection:{0}".format(self.scope) if self.scope
+ else "")
+
+ return base_info + line_info + scope_info + "\n"
+
+
+class CTagsWriter(object):
+ """rst2ctags specific docutils writer class.
+ """
+
+ URL = "http://bernh.net/rst2ctags"
+ VERSION = "rst2ctags v{0}".format(__version__)
+
+ metadata = \
+ ("!_TAG_FILE_FORMAT\t2\t/extended format/\n"
+ "!_TAG_FILE_SORTED\t{sort}\t/0=unsorted, 1=sorted, 2=foldcase/\n"
+ "!_TAG_PROGRAM_NAME\trst2ctags\t//\n"
+ "!_TAG_PROGRAM_AUTHOR\tBernhard Leiner\t/bleiner@gmail.com/\n"
+ "!_TAG_PROGRAM_URL\t{url}\t//\n"
+ "!_TAG_PROGRAM_VERSION\t{version}\t//\n")
+
+ def __init__(self):
+ self.tags = []
+
+ def nodewalker(self, node, level, parent):
+ """Translates the doctree into a list of tags and appends it to
+ :attr:`tags`.
+ """
+ tag = None
+ new_parent = False
+ if isinstance(node, nodes.section):
+ tagtype = "s"
+ tagfile = os.path.relpath(node.source)
+ tagid = \
+ str(node.astext().partition(node.child_text_separator)[0])
+ tagaddress = '/^{0}$/;"'.format(tagid)
+ taglinenr = node.line - 1
+ # increase level for next found section
+ level += 1
+ new_parent = True
+ tag = Tag(tagid, tagfile, tagaddress, tagtype, taglinenr, level, parent)
+ elif (isinstance(node, nodes.image) or
+ isinstance(node, nodes.figure)):
+ tagtype = "i"
+ tagfile = os.path.relpath(node.source) if node.source \
+ else os.path.relpath(node.parent.source)
+ taglinenr = node.line - 1 if node.line else node.parent.line - 1
+ if isinstance(node, nodes.image):
+ tagid = node.attributes['uri']
+ tagaddress = '/^{0}$/;"'.format(node.rawsource.split('\n')[0])
+ if isinstance(node, nodes.figure):
+ tagid = node.children[0].attributes['uri']
+ tagaddress = '/^{0}$/;"'.format(node.children[0].rawsource.split('\n')[0])
+ tag = Tag(tagid, tagfile, tagaddress, tagtype, taglinenr, level)
+
+ if tag:
+ self.tags.append(tag)
+
+ if new_parent:
+ parent = tag
+
+ if len(node.children) and not isinstance(node, nodes.figure):
+ for child in node:
+ self.nodewalker(child, level, parent)
+
+
+ def write(self, f, sort, metadata):
+ if sort == "yes": # sort by tag name
+ self.tags.sort(key = lambda t: t.tagid)
+ else: # sort by file and line number
+ self.tags.sort(key = lambda t: (t.tagfile, t.linenr))
+
+ if metadata:
+ sort = "1" if sort == "yes" else "0"
+ f.write(self.metadata.format(sort=sort, url = CTagsWriter.URL,
+ version = CTagsWriter.VERSION))
+ for tag in self.tags:
+ f.write(str(tag))
+
+
+def get_rst_files(source_args, recurse):
+ """Return an iterable containing all source files.
+ """
+
+ rst_ext = ".rst"
+ source_files = []
+
+ def is_rst_file(f):
+ return os.path.splitext(f)[1] == rst_ext
+
+ if not recurse:
+ # treat all source args as files
+ source_files = [f for f in source_args if is_rst_file(f)]
+ else:
+ # source_args may be a mixture of files and directories
+ cwd = os.getcwd()
+ if cwd not in source_args:
+ source_args.append(cwd)
+ source_files = [f for f in source_args
+ if os.path.isfile(f) and is_rst_file(f)]
+ for source_dir in (d for d in source_args if os.path.isdir(d)):
+ for dirpath, _, filenames in os.walk(source_dir):
+ source_files.extend(os.path.join(dirpath, f)
+ for f in filenames if is_rst_file(f))
+ # return unique sources
+ return set(os.path.abspath(f) for f in source_files)
+
+
+
+def main():
+ parser = OptionParser(usage = "usage: %prog [options] file(s)",
+ version = "%prog {0}".format(__version__))
+ parser.add_option \
+ ("-f", "--file", metavar = "FILE", dest = "tagfile",
+ default = "tags",
+ help = 'Write tags into FILE (default: "tags"). Value of '
+ '"-" writes tags to stdout.')
+ parser.add_option \
+ ("-R", "--recurse", dest = "recurse", action = "store_true",
+ default = False,
+ help = "Recurse into directories supplied on command line")
+ parser.add_option \
+ ("--sort", metavar = "[yes|no]", dest = "sort", default = "no",
+ help = 'Should tags be sorted by name? Default is "no", which '
+ 'will sort by line number.')
+ options, args = parser.parse_args()
+
+ if len(args) == 0:
+ parser.error('No files specified. Try "--help"')
+
+ writer = CTagsWriter()
+ for rstfile in get_rst_files(args, options.recurse):
+ with open(rstfile) as f:
+ rstdata = f.read()
+ doctree = publish_doctree(rstdata, source_path = rstfile)
+ writer.nodewalker(doctree, -1, None)
+
+ if options.tagfile == "-":
+ writer.write(sys.stdout, options.sort, False)
+ else:
+ with open(options.tagfile, "w") as f:
+ writer.write(f, options.sort, True)
+
+
+if __name__ == "__main__":
+ main()
@@ -0,0 +1,72 @@
+*****
+Titel
+*****
+
+Section 1
+=========
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a massa vel sem
+eleifend aliquam. Proin at laoreet nibh.
+
+.. image:: rst2ctags1.png
+ :width: 540px
+
+Subsection 1
+------------
+
+Praesent luctus dictum orci eget volutpat. Etiam ac nisl at dui accumsan
+pretium. Pellentesque lectus massa, egestas at vulputate nec, facilisis et mi.
+
+* Sed adipiscing aliquet sollicitudin.
+* Aliquam erat volutpat.
+* Etiam vel est sed metus lacinia cursus id in felis.
+
+In placerat rhoncus risus, in bibendum elit aliquam et.
+
+Subsection 2
+------------
+
+Donec pretium, massa at dictum consectetur, lacus dolor interdum arcu, et
+ullamcorper turpis libero sed tortor. Cras fermentum, velit ut convallis
+porttitor, enim odio interdum turpis, quis gravida erat ante sit amet mi.
+Curabitur sollicitudin magna cursus neque interdum vitae eleifend mi blandit.
+
+.. figure:: rst2ctags2.png
+
+Section 2
+=========
+
+Suspendisse consequat nibh non eros accumsan gravida. Maecenas id lectus est,
+vel imperdiet ligula. Donec id lacus tellus.
+
+Section 3
+=========
+
+Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
+Curae; Sed nec suscipit lorem.
+
+Subsection 3
+------------
+
+Subsubsection 1
+~~~~~~~~~~~~~~~
+
+Morbi sed leo lectus. Vivamus magna eros, euismod quis semper eget, porta at
+leo. Quisque auctor, nisl at vestibulum consequat, diam lectus feugiat dui, nec
+consequat lorem velit a purus.
+
+Subsubsection 2
+~~~~~~~~~~~~~~~
+
+Morbi sed leo lectus. Vivamus magna eros, euismod quis semper eget, porta at
+leo. Quisque auctor, nisl at vestibulum consequat, diam lectus feugiat dui, nec
+consequat lorem velit a purus.
+
+.. image:: ../doc/rst2ctags.png
+ :width: 540px
+
+Subsection 4
+------------
+
+Sed in sem id sapien elementum pretium quis ac odio. Etiam tempor felis eget
+risus gravida faucibus euismod tortor ullamcorper.
Oops, something went wrong.

0 comments on commit a28e39c

Please sign in to comment.