parts/django/docs/_ext/literals_to_xrefs.py
changeset 69 c6bca38c1cbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parts/django/docs/_ext/literals_to_xrefs.py	Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,171 @@
+"""
+Runs through a reST file looking for old-style literals, and helps replace them
+with new-style references.
+"""
+
+import re
+import sys
+import shelve
+
+refre = re.compile(r'``([^`\s]+?)``')
+
+ROLES = (
+    'attr',
+    'class',
+    "djadmin",
+    'data',
+    'exc',
+    'file',
+    'func',
+    'lookup',
+    'meth',
+    'mod' ,
+    "djadminopt",
+    "ref",
+    "setting",
+    "term",
+    "tfilter",
+    "ttag",
+    
+    # special
+    "skip"
+)
+
+ALWAYS_SKIP = [
+    "NULL",
+    "True",
+    "False",
+]
+
+def fixliterals(fname):
+    data = open(fname).read()
+    
+    last = 0
+    new = []
+    storage = shelve.open("/tmp/literals_to_xref.shelve")
+    lastvalues = storage.get("lastvalues", {})
+    
+    for m in refre.finditer(data):
+        
+        new.append(data[last:m.start()])
+        last = m.end()
+        
+        line_start = data.rfind("\n", 0, m.start())
+        line_end = data.find("\n", m.end())
+        prev_start = data.rfind("\n", 0, line_start)
+        next_end = data.find("\n", line_end + 1)
+        
+        # Skip always-skip stuff
+        if m.group(1) in ALWAYS_SKIP:
+            new.append(m.group(0))
+            continue
+            
+        # skip when the next line is a title
+        next_line = data[m.end():next_end].strip()
+        if next_line[0] in "!-/:-@[-`{-~" and all(c == next_line[0] for c in next_line):
+            new.append(m.group(0))
+            continue
+        
+        sys.stdout.write("\n"+"-"*80+"\n")
+        sys.stdout.write(data[prev_start+1:m.start()])
+        sys.stdout.write(colorize(m.group(0), fg="red"))
+        sys.stdout.write(data[m.end():next_end])
+        sys.stdout.write("\n\n")
+        
+        replace_type = None
+        while replace_type is None:
+            replace_type = raw_input(
+                colorize("Replace role: ", fg="yellow")
+            ).strip().lower()
+            if replace_type and replace_type not in ROLES:
+                replace_type = None
+        
+        if replace_type == "":
+            new.append(m.group(0))
+            continue
+            
+        if replace_type == "skip":
+            new.append(m.group(0))
+            ALWAYS_SKIP.append(m.group(1))
+            continue
+        
+        default = lastvalues.get(m.group(1), m.group(1))
+        if default.endswith("()") and replace_type in ("class", "func", "meth"):
+            default = default[:-2]        
+        replace_value = raw_input(
+            colorize("Text <target> [", fg="yellow") + default + colorize("]: ", fg="yellow")
+        ).strip()
+        if not replace_value: 
+            replace_value = default
+        new.append(":%s:`%s`" % (replace_type, replace_value))
+        lastvalues[m.group(1)] = replace_value
+    
+    new.append(data[last:])
+    open(fname, "w").write("".join(new))
+    
+    storage["lastvalues"] = lastvalues
+    storage.close()
+    
+#
+# The following is taken from django.utils.termcolors and is copied here to
+# avoid the dependancy.
+#
+
+
+def colorize(text='', opts=(), **kwargs):
+    """
+    Returns your text, enclosed in ANSI graphics codes.
+
+    Depends on the keyword arguments 'fg' and 'bg', and the contents of
+    the opts tuple/list.
+
+    Returns the RESET code if no parameters are given.
+
+    Valid colors:
+        'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
+
+    Valid options:
+        'bold'
+        'underscore'
+        'blink'
+        'reverse'
+        'conceal'
+        'noreset' - string will not be auto-terminated with the RESET code
+
+    Examples:
+        colorize('hello', fg='red', bg='blue', opts=('blink',))
+        colorize()
+        colorize('goodbye', opts=('underscore',))
+        print colorize('first line', fg='red', opts=('noreset',))
+        print 'this should be red too'
+        print colorize('and so should this')
+        print 'this should not be red'
+    """
+    color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
+    foreground = dict([(color_names[x], '3%s' % x) for x in range(8)])
+    background = dict([(color_names[x], '4%s' % x) for x in range(8)])
+
+    RESET = '0'
+    opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}
+
+    text = str(text)
+    code_list = []
+    if text == '' and len(opts) == 1 and opts[0] == 'reset':
+        return '\x1b[%sm' % RESET
+    for k, v in kwargs.iteritems():
+        if k == 'fg':
+            code_list.append(foreground[v])
+        elif k == 'bg':
+            code_list.append(background[v])
+    for o in opts:
+        if o in opt_dict:
+            code_list.append(opt_dict[o])
+    if 'noreset' not in opts:
+        text = text + '\x1b[%sm' % RESET
+    return ('\x1b[%sm' % ';'.join(code_list)) + text
+
+if __name__ == '__main__':
+    try:
+        fixliterals(sys.argv[1])
+    except (KeyboardInterrupt, SystemExit):
+        print
\ No newline at end of file