1#!/usr/bin/env python 2 3# Convert Tim-style text to html or qml 4# 5# The Rules: 6# - Lines with all upper case words to h2 or h3 capwords depending on next line underlining (first to h1/title though) 7# (must be 3 chars or more) 8# (todo: relax to not all upper case... no need to capwords if not) 9# - Other text to p, blank lines break a p 10# - Lines beginning with "- " (NB space) to ul/li (bulleted) 11# - Lines beginning with "-?" (no space) to ul/li (?) with <br> at end of first line 12# - Words delim <xxx> to <i>xxx</i> 13# "$ " at start of line indicates one line of code (add <br> too) 14 15import sys 16import string 17import re 18 19def line_of_dashes(n): 20 r="" 21 for i in xrange(n): 22 r+="-" 23 return r 24 25def line_of_equals(n): 26 r="" 27 for i in xrange(n): 28 r+="=" 29 return r 30 31class TextToMarkup: 32 33 def __init__(self,m,s): 34 self.startup=1 # True 35 self.scope_p=0 # False 36 self.scope_ul=0 # False 37 self.scope_li=0 # False 38 self.done_title=0 # False 39 self.skipnextline=0 # False 40 self.mode=m 41 self.stringify=s 42 43 def dispose(self,l): 44 if self.stringify: 45 self.output.write("\"") # Actually, they should all have been "-ed anyway 46 for c in l: 47 if c=="\"": 48 self.output.write("\\\"") 49 else: 50 self.output.write(c) 51 self.output.write("\\n\"\n") 52 else: 53 self.output.write(l+"\n") 54 55 def process_word(self,w): 56 r="" 57 if len(w)<3: # Special case allows "<" or "<>" without turning italic 58 for i in xrange(len(w)): 59 if w[i]=="<": 60 r+="<" 61 elif w[i]==">": 62 r+=">" 63 else: 64 r+=w[i] 65 else: 66 for i in xrange(len(w)): 67 if w[i]=="<": 68 r+="<i>" 69 elif w[i]==">": 70 r+="</i>" 71 elif w[i]=='"': 72 r+=""" 73 elif w[i]=="&": 74 r+="&" 75 else: 76 r+=w[i] 77 return r 78 79 def process_paragraph_text(self,txt): 80 81 is_code=0 # False 82 specialbreak=0 # False 83 r=" " 84 85 if txt[0]=="-": 86 if txt[1]==" ": 87 txt=txt[2:] 88 else: 89 specialbreak=1 # True 90 if self.scope_ul and self.scope_li: 91 r+="</li>" 92 self.scope_li=0 # False 93 if not self.scope_ul: 94 r+="<ul>" 95 self.scope_ul=1 # True 96 if not self.scope_li: 97 r+="<li>" 98 self.scope_li=1 # True 99 100 elif txt[0]=="$": 101 is_code=1 # True 102 r+="<code>" 103 txt=txt[2:] 104 105 for w in txt.split(): 106 r+=self.process_word(w) 107 r+=" " 108 if is_code: 109 r+="</code>" 110 if specialbreak: 111 r+="<br>" 112 return r 113 114 def process(self,in_stream,out_stream): 115 self.output=out_stream 116 self.input=in_stream 117 118 if self.mode=="html": 119 self.dispose("<html>") 120 121 while 1: # True 122 123 if self.startup: 124 self.currline_raw=in_stream.readline() 125 self.nextline_raw=in_stream.readline() 126 self.startup=0 # False 127 else: 128 self.currline_raw=self.nextline_raw 129 self.nextline_raw=in_stream.readline() 130 131 if not self.currline_raw: 132 break 133 134 if self.skipnextline: 135 self.skipnextline=0 # False 136 continue 137 138 # Should track last line too 139 self.currline=self.currline_raw.strip() 140 self.nextline=self.nextline_raw.strip() 141 142 if len(self.currline)>2 and self.nextline==line_of_equals(len(self.currline)): 143 if self.done_title: 144 self.dispose("<h2>"+string.capwords(self.currline)+"</h2>") 145 self.skipnextline=1 # True 146 continue 147 else: 148 if (self.mode=="html"): 149 self.dispose("<head>") 150 self.dispose("<!--- AUTOMATICALLY GENERATED FILE : DO NOT EDIT --->") 151 self.dispose("<title>"+string.capwords(self.currline)+"</title>") 152 self.dispose("</head>") 153 self.dispose("<body>") 154 elif (self.mode=="qml"): 155 self.dispose("<qt title='"+string.capwords(self.currline)+"'>") 156 self.dispose("<h1>"+string.capwords(self.currline)+"</h1>") 157 self.done_title=1 # True 158 self.skipnextline=1 # True 159 continue 160 elif len(self.currline)>2 and self.nextline==line_of_dashes(len(self.currline)): 161 self.dispose("<h3>"+string.capwords(self.currline)+"</h3>") 162 self.skipnextline=1 # True 163 continue 164 elif self.scope_p: 165 if (len(self.currline)): 166 self.dispose(self.process_paragraph_text(self.currline)) 167 else: 168 if self.scope_li: 169 self.dispose("</li>") 170 self.scope_li=0 # False 171 if self.scope_ul: 172 self.dispose("</ul>") 173 self.scope_ul=0 # False 174 self.dispose("</p>") 175 self.scope_p=0 # False 176 elif len(self.currline): 177 self.dispose("<p>") 178 self.dispose(self.process_paragraph_text(self.currline)) 179 self.scope_p=1 # True 180 else: 181 self.dispose("") 182 183 if self.mode=="html": 184 self.dispose("</body>") 185 self.dispose("</html>") 186 187######################################### 188 189if __name__=='__main__': 190 191 mode=None 192 stringify=0 # False 193 for i in xrange(1,len(sys.argv)): 194 if sys.argv[i]=="-qml": 195 mode="qml" 196 if sys.argv[i]=="-html": 197 mode="html" 198 elif sys.argv[i]=="-s": 199 stringify=1 # True 200 201 t2m=TextToMarkup(mode,stringify) # "html" and "qml" are alternatives. Should be stringify option. 202 t2m.process(sys.stdin,sys.stdout) 203 204