Created
September 16, 2012 23:21
-
-
Save westurner/3734801 to your computer and use it in GitHub Desktop.
ReStructuredText Heading Shift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
A utility for modifying ReStructuredText headings by the | |
specified shift offset. | |
For example:: | |
========== | |
Title | |
========== | |
Heading 1 | |
========= | |
Heading 2 | |
--------- | |
Heading 3 | |
~~~~~~~~~ | |
Shifted by 1:: | |
Title | |
====== | |
Heading 1 | |
---------- | |
Heading 2 | |
~~~~~~~~~~ | |
Heading 3 | |
''''''''' | |
""" | |
import re | |
import optparse | |
RE_TITLE = re.compile(r'^([\=|\-|\~]+)\n(.*)\n^([\=|\-|\~]+)\n', re.MULTILINE) | |
RE_HEADING = re.compile(r'^(?:[\=|\-|\~]?)(?:[\n]?)(.*)\n^([\=|\-|\~]+)\n', | |
re.MULTILINE) | |
STANDARD_HEADINGS = { | |
0: '==', | |
1: '=', | |
2: '-', | |
3: '~', | |
4: "'", | |
5: '"', | |
6: '`', | |
7: '^', | |
8: '_', | |
9: '*', | |
10: '+', | |
11: '#', | |
12: '<', | |
13: '>'} | |
def restructuredtext_shift(input_file, shiftby): | |
""" | |
Shift the headings of a restructuredtext document | |
:param input_file: ReStructuredText file to read | |
:type input_file: str | |
:param shiftby: offset to shift headings by | |
:type shiftby: signed int | |
""" | |
shiftfactor = shiftby | |
f = open(input_file,'r+') | |
lines = f.read() | |
depthcount = 0 | |
headings = {} | |
sections = [] | |
# Special case for title | |
title_obj = RE_TITLE.search(lines) | |
(overline, title, underline) = title_obj.groups() | |
#if len(overline) == len(underline): | |
headings[overline[0]*2] = 0 | |
print 0, title | |
#sections.append((0, '\n'.join([overline, title, underline]))) | |
# Extract section headings and existing section heading numbering | |
for g in RE_HEADING.finditer(lines): | |
(text, line) = g.groups() | |
underline_char = line[0] | |
depth = headings.get(underline_char) | |
if not depth: | |
depthcount += 1 | |
headings[underline_char] = depthcount | |
heading_level = headings[underline_char] | |
sections.append( | |
(heading_level, underline_char, '\n'.join((text, line)))) | |
print heading_level, heading_level * ' ', text | |
STD_HEADINGS = STANDARD_HEADINGS.values() | |
# Expand headings with elements from STD_HEADINGS | |
for char in sorted(headings.keys()): | |
STD_HEADINGS.remove(char) | |
for n in xrange(len(STD_HEADINGS)): | |
dest = depthcount + ((((shiftby > 0) and 1 or -1)) * n) | |
headings[STD_HEADINGS[n]] = dest | |
headings_by_n = dict( | |
(x[1], x[0]) for x in headings.items(), | |
) | |
#output = copy.copy(lines) | |
output = lines | |
# Perform underline replacements | |
for section in sections: | |
(level, char, text) = section | |
newlevel = level + shiftby | |
newchar = headings_by_n[newlevel] | |
section, underline = text.split('\n',1) | |
newtext = '\n'.join((section, underline.replace(char, newchar))) | |
output = output.replace(text, newtext, 1) | |
return output | |
def main(): | |
prs = optparse.OptionParser() | |
prs.add_option('-i','--input-file',dest='input_file',action='store', | |
help='ReStructuredText file to reindent') | |
prs.add_option('-s','--shiftby',dest='shiftby',action='store', | |
help='Degrees to shift ReStructuredText headings by (eg 1, -1)') | |
(opts,args) = prs.parse_args() | |
if not (opts.input_file and opts.shiftby): | |
raise Exception("Must specify both --input-file and --shiftby") | |
exit(0) | |
print restructuredtext_shift(opts.input_file, int(opts.shiftby)) | |
if __name__=="__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is now in
westurner/rst-tools
: