#!@PYTHON@ # yodl2texinfo-post.py # # (c) 1998,1999 Jan Nieuwenhuizen program_name = 'yodl2texinfo-post' version = '@TOPLEVEL_VERSION@' simple_nodes = 0 backup = 0 ## urg:: ## this hack (File: texinfo, Node: Pointer Validation) ## ## @set nodename Node 1 ## @node @value{nodename}, Node 2, Top, Top ## ## together with --commands-in-node-names, still doesn't work: ## ## out/topinfo.texinfo:906: Node `@value{nodename}' previously defined at line 48. ## urg_value = 1 not_in_node_set = '[,:\.?!\\\'`{}]' not_in_node = '.*[,:\.?!\\\'`{}].*' import os import sys import getopt from string import * import regex import regsub import time def program_id (): return program_name + ' version ' + version; def identify (): sys.stdout.write (program_id () + '\n') def help (): sys.stdout.write ("Usage: %s [OPTION]... [FILE]...\n" "Resolve yodl tags, autogenerate nodes and menus.\n\n" + "Options:\n" + " -h, --help print this help\n" + " -k, --keep keep backup of Yodl output\n" + " -s, --simple-nodes don't put next,prev,up references in nodes\n" % (program_name) ) sys.exit (0) identify () (options, files) = getopt.getopt ( sys.argv[1:], 'hks', ['help','keep','simple-nodes']) for opt in options: o = opt[0] a = opt[1] if o == '--help' or o == '-h': help () elif o == '--keep' or o == '-k': backup = 1 elif o == '--simple-nodes' or o == '-s': simple_nodes = 1 else: print o raise getopt.error def gulp_file (f): try: i = open (f) i.seek (0, 2) n = i.tell () i.seek (0,0) except: sys.stderr.write ('can\'t open file %s\n ' % f) return '' s = i.read (n) if len (s) <= 0: sys.stderr.write ('gulped empty file: %s\n'% f) return s class Node: def __init__ (this, pos, name): this.pos = pos this.name = name this.description = '' this.prev = '' this.next = '' this.top = '' class Menu (Node): def __init__ (this, pos, name): Node.__init__ (this, pos, name) this.node_list = [] TAB_POS = 34 class Pre_texinfo_file (Menu): def __init__ (this, filename): Menu.__init__ (this, 0, 'Top') this.filename = filename this.node_list = [] this.s = '' this.offset = 0 this.last = Node (0, '') this.prefix = '' this.default = Node (0,'') this.default.top = '(dir)' this.node_dict = {} this.xref_list = [] def gulp (this): this.s = gulp_file (this.filename) def new_menu (this, pos, name): m = Menu (pos, name) if this.default.name: m.name = this.default.name if this.default.description: m.description = this.default.description m.name = this.prefix + m.name return m def new_node (this, pos, name): n = Node (pos, name) if this.default.name: n.name = this.default.name if this.default.description: n.description = this.default.description n.name = this.prefix + n.name while this.node_dict.has_key (n.name): n.name = n.name + 'i' this.node_dict[n.name] = 0 n.top = this.default.top n.prev = this.last.name this.last.next = n.name this.last = n return n def eat_tag (this): i = regex.search ('@TAGSTART@', this.s) j = 0 if i < 0: return 0 j = regex.search ('@TAGEND@', this.s[i:]) if j < 0: raise 'huh?' j = i + j + len ('@TAGEND@') tag = this.s[i + len ('@TAGSTART@'):j - len ('@TAGEND@')] k = regex.search (' ', tag[1:]) + 1 tag_name = tag[1:k] tag_string = tag[k:len (tag) - 1] while tag_string[:1] == ' ': tag_string = tag_string[1:] # # urg, commas in titles... # but even more urg, makeinfo (3.12) chokes on # various other characters in node names too # if urg_value: tag_string = regsub.gsub (not_in_node_set, '-', tag_string) tag_string = regsub.gsub ('--', '-', tag_string) # brr tag_string = regsub.gsub ('--', '-', tag_string) tag_string = regsub.gsub ('@code', '', tag_string) tag_string = regsub.gsub ('@emph', '', tag_string) tag_string = regsub.gsub ('@strong', '', tag_string) if tag_name == 'menu': this.default.top = 'Top' n = this.new_node (i, tag_string) m = this.new_menu (i, tag_string) this.default.top = tag_string this.default.name = '' this.default.description = '' m.node_list.append (n) this.node_list.append (m) elif tag_name == 'node': n = this.new_node (i, tag_string) this.default.name = '' this.default.description = '' if not len (this.node_list): # m = Menu (i, 'Toplevel') m = this.new_menu (i, 'Toplevel') this.node_list.append (m) this.node_list[len (this.node_list)-1].node_list.append (n) elif tag_name == 'node_description': this.default.description = tag_string elif tag_name == 'node_name': this.default.name = tag_string elif tag_name == 'node_prefix': this.prefix = tag_string elif tag_name == 'ref': ## urg, prefix is broken ref = '@ref{' + this.prefix + tag_string + '}' this.s = this.s[:i] + ref + this.s[j:] this.xref_list.append (this.prefix + tag_string) ## urg return 1 else: sys.stderr.write ("unknown tag: `" + tag + "', skipping\n") this.s = this.s[:i] + this.s[j:] return 1 def plug (this): if backup: os.rename (this.filename, this.filename + '~') fd = open (this.filename, 'w') fd.write (this.s) fd.close () def create_node (this, n): node = '@node ' set = '' if not urg_value and regex.match (not_in_node, n.name) != -1: set = set + "@set nodename " + n.name + "\n" node = node + "@value{nodename}" else: node = node + n.name if not simple_nodes: if not urg_value and regex.match (not_in_node, n.next) != -1: set = set + "@set nextname " + n.next + "\n" node = node + ", @value{nextname}" else: node = node + ", " + n.next if not urg_value and regex.match (not_in_node, n.prev) != -1: set = set + "@set prevname " + n.prev + "\n" node = node + ", @value{prevname}" else: node = node + ", " + n.prev if not urg_value and regex.match (not_in_node, n.top) != -1: set = set + "@set topname " + n.top + "\n" node = node + ", @value{topname}" else: node = node + ", " + n.top node = set + node + "\n" if n.name == 'Top': node = node + "@top\n" this.s = this.s[:n.pos + this.offset] + node + this.s[n.pos + this.offset:] this.offset = this.offset + len (node) def create_menu (this, m): if len (m.node_list) < 2: return menu = "@menu\n" for n in m.node_list[1:]: d = n.description if not d: d = n.name if not urg_value and regex.match (not_in_node, n.name) != -1: menu = menu + "@set nodename " + n.name + "\n" menu = menu + "* @value{nodename}::" menu = menu + ' ' * (TAB_POS - len (n.name)) + d + "\n" else: menu = menu + ljust ('* ' + n.name + '::', TAB_POS) + d + "\n" menu = menu + "@end menu\n" this.s = this.s[:m.pos + this.offset] + menu + this.s[m.pos + this.offset:] m.node_list[0].pos = m.node_list[0].pos - len (menu) this.offset = this.offset + len (menu) def create_nodes (this, m): for n in m.node_list: this.create_node (n) def parse (this): i = 1 while i: i = this.eat_tag () def nodes_and_menus (this): this.default.top = '(dir)' n = this.new_node (0, 'Top') m = Menu (0, 'Top') m.node_list.append (n) this.node_list.insert (0, m) n.pos = this.offset this.create_menu (this) n.pos = - this.offset this.create_nodes (m) for m in this.node_list[1:]: this.create_menu (m) this.create_nodes (m) def xrefs (this): this.prefix = '' this.default.top = 'Top' m = Menu (len (this.s), 'Missing nodes') this.default.top = 'Missing nodes' first_b = 1 for i in this.xref_list: if not this.node_dict.has_key (i): if first_b: this.default.top = 'Top' n = this.new_node (len (this.s), 'Missing nodes') m.node_list.append (n) this.default.top = 'Missing nodes' first_b = 0 sys.stderr.write (this.filename + ": warning: xref to nonexistent node: `" + i + "'\n") n = this.new_node (len (this.s), i) m.node_list.append (n) if len (m.node_list) > 1: this.node_list.append (m) this.default.top = 'Top' def post (this): this.gulp () this.parse () this.xrefs () this.nodes_and_menus () this.s = regsub.gsub ('^\n\n', '\n', this.s) this.s = '\n' + this.s infotitle = '' basename = os.path.basename (os.path.splitext (this.filename)[0]) infoname = basename + ".info" if len (this.node_list) > 1: infotitle = this.node_list[1].name else: infotitle = basename # this.s = '@settitle %s\n' % this.node_list[1].name + this.s # this.s = '@setfilename %s\n' % infoname + this.s # this.s = '\\input texinfo @c -*-texinfo-*-\n' + this.s this.s = r"""\input texinfo @c -*-texinfo-*- @setfilename %s @settitle %s """ % (infoname, infotitle) + this.s this.s = this.s + "\n@bye" this.plug () for f in files: t = Pre_texinfo_file (f) t.post ()