#!/usr/bin/env python # Python-Loesung von Markus Korn """USAGE: footnotes.py [-a] [--test] [< input.txt] --test Self-test using text SAMPLE in script source -a Number footnotes in order of appearance in text """ SAMPLE = '''A great brown fox [13] jumped of a pile of lorem ipsum [4], [7]. He met with a silver penguin, browsing the Linux Kernel Mailinglist [3]. They debated other the question whether to start a C-program with "main (int argc, char **argv)" or with "main (int argc, char *argv[])". Square brackets annoyed them [9999]. Multiple references may exist to same targets [4]. @footnote: [13] Al Fabetus: "On characters and animals", 1888, self published. [4] Lorem Ipsum, Web Link [9999] Annoying Link. [7] B. Fox: "More on Blind Text". [3] Linux Kernel Maintainers: LKML ''' import re, sys, operator TEXT, FOOTNOTE = 0, re.MULTILINE def sortdict_bykey(dct): x = sorted(dct.keys()) for i in x: yield dct[i] class SortedItems(object): def __init__(self, mode, part, nr_map=None): self.mode = mode self.part = part self.map = nr_map or {} self.count = 0 def __call__(self, match): x = int(match.group(1)) try: return "[%s]" %self.map[x] except KeyError: if not self.mode and self.part == TEXT: return "[0]" self.count += 1 self.map[x] = self.count return "[%s]" %self.count def sort_part(part, text, nr_map, mode): sort_func = SortedItems(mode, part, nr_map or None) r = re.compile(r"%s\[(\d+)\]" %(part and "^" or ""), part) if nr_map is None or part == TEXT: return r.sub(sort_func, text), sort_func.map elif part == FOOTNOTE: cache = {} for line in text.splitlines(): nr, t = re.match(r"^\[(\d+)\](.*)", line).groups() neu = nr_map[int(nr)] cache[neu] = "[%s]%s" %(neu, t) return "\n".join(sortdict_bykey(cache)), nr_map def main(s, usebody=False): RE_FOOTSPLIT = re.compile(r'(\n*@footnote:[^\[]*)', re.MULTILINE) FOOTSPLIT = RE_FOOTSPLIT.search(s).group(1) body, footnote = s.split(FOOTSPLIT) if usebody: body, nr_map = sort_part(TEXT, body, None, usebody) footnote, _ = sort_part(FOOTNOTE, footnote, nr_map, usebody) else: footnote, nr_map = sort_part(FOOTNOTE, footnote, None, usebody) body, _ = sort_part(TEXT, body, nr_map, usebody) return body + FOOTSPLIT + footnote.rstrip("\n") if __name__ == '__main__': if '--test' in sys.argv[1:]: print main(SAMPLE, usebody='-a' in sys.argv[1:]) else: print main(sys.stdin.read(), usebody='-a' in sys.argv[1:])