1 #! /bin/env python 2 # Time-stamp: <2001-06-04 00:16:20 cymbala> 3 # 4 info = {} 5 info['PATHS'] = ['PY_PATH', 'CSS_PATH'] 6 info['PY_NAME'] = 'rjc_css.py' 7 info['CSS_NAMES'] = ['works.css'] 8 info['PY_PATH'] = '~/bin' 9 info['CSS_PATH'] = '~/Db/Homepage' 10 # 11 info['DEBUG'] = 't' 12 info['DEBUG'] = None 13 14 info['PY_DESCRIPTION'] = """ This Python script looks at a cascading style sheet and outputs a condensed list of class attributes that will be handled by the CSS. """ 19 20 # ------------------------------------------------------- 21 # Rationale: 22 # What values of class attribute (for standard HTML elements) are 23 # defined for the cascading-style-sheet used at: 24 # http://www.marxists.org/archive/lenin/works/index.htm 25 # CSS: 26 # http://www.marxists.org/archive/css/works.css 27 # 2001.05.26 28 # ------------------------------------------------------- 29 30 import os 31 import re 32 import sys 33 import string 34 import fileinput 35 36 class Program: 37 def printer(self, text): 38 """This will display information and can write to a log.""" 39 # 40 # Standard-error. Note newline _not_ printed here. 41 sys.stdout.write(text) 42 # 43 # Log file: 44 # ... pending ... 45 46 pass 47 48 def __init__(self, info): 49 """This happens during class instantiation.""" 50 # 51 self.info = info 52 # 53 self.comment = None 54 self.comment_Previous = None 55 # 56 self.last_line_type = None 57 self.last_line_type_Previous = None 58 # 59 self.line_type = {} 60 self.line_type['COMMENT'] = 'COMMENT' 61 self.line_type['COMMENT_NOT'] = 'COMMENT_NOT' 62 # 63 self.indentation = {} 64 self.indentation['a'] = ' ' 65 self.indentation['b'] = 2 * self.indentation['a'] 66 67 68 # Expand "~" to home subdirectory. 69 for type in self.info['PATHS']: 70 if type == 'PY_PATH' or type == 'CSS_PATH': 71 if string.find(self.info[type], '~') > -1: 72 self.info[type] = os.path.expanduser( 73 self.info[type]) 74 pass 75 pass 76 else: 77 raise 'Unknown type: ' + type 78 79 if self.info['DEBUG']: 80 self.printer('PATH: ' + type + ': ' + self.info[type] + '\n') 81 pass 82 83 pass 84 85 # Input file(s) (must expand '~' first): 86 if sys.argv[1:] == []: 87 foo = [] 88 for name in self.info['CSS_NAMES']: 89 foo.append(os.path.join(self.info['CSS_PATH'], name)) 90 pass 91 92 sys.argv[1:] = foo 93 pass 94 95 # Some compiled regular expressions. 96 self.re_compiled = {} 97 self.re_compiled['COMMENT_START'] = re.compile(r'/\*') 98 self.re_compiled['COMMENT_END'] = re.compile(r'\*/') 99 100 pass 101 102 def append_to_comment(self, appendage): 103 """Add appendage to the comment.""" 104 # 105 self.last_line_type = self.line_type['COMMENT'] 106 if self.comment == None: 107 self.comment = appendage 108 pass 109 else: 110 self.comment = self.comment + appendage 111 pass 112 pass 113 114 def parse_css(self, line): 115 """This looks at each line in CSS.""" 116 # 117 # Preparation. 118 self.comment_on_one = None 119 match_obj_start = self.re_compiled['COMMENT_START'].search(line) 120 match_obj_end = self.re_compiled['COMMENT_END'].search(line) 121 122 # Blank lines. 123 if string.strip(line) == '': 124 return 125 126 # PREVIOUS things. 127 self.comment_Previous = self.comment 128 self.last_line_type_Previous = self.last_line_type 129 130 # Comment? 131 if not match_obj_start == None: 132 # 133 if not match_obj_end == None: 134 self.comment_on_one = 't' 135 self.comment_on_one = 't' 136 self.comment_on_one = 't' 137 self.comment_on_one = 't' 138 self.comment_on_one = 't' 139 # 140 if self.info['DEBUG']: 141 self.printer( 142 ' ~~Entire comment on one line~~ ' 143 + '\n') 144 pass 145 self.append_to_comment(line[match_obj_start.start(0): 146 match_obj_end.end(0)]) 147 # 148 pass 149 else: 150 if self.info['DEBUG']: 151 self.printer( 152 ' ~~Comment begins here, ends on another line~~ ' 153 + '\n') 154 pass 155 self.append_to_comment(line) 156 # 157 pass 158 pass 159 elif not match_obj_end == None: 160 if self.info['DEBUG']: 161 self.printer( 162 ' ~~End of a comment that started on some other line~~ ' 163 + '\n') 164 pass 165 self.append_to_comment(line[:match_obj_end.end(0)]) 166 # 167 pass 168 else: 169 # Is this a comment that spans more than two lines? 170 if not self.comment == None: 171 # 172 if self.info['DEBUG']: 173 self.printer( 174 ' ~~Middle of long comment~~ ' + 175 '\n') 176 pass 177 self.append_to_comment(line) 178 pass 179 pass 180 181 # Found end of a comment: 182 if not match_obj_end == None: 183 if self.info['DEBUG']: 184 self.printer( 185 'END-OF-COMMENT: ' + self.comment + 186 '\n') 187 pass 188 # 189 # COMMENT ACTION. 190 if self.last_line_type_Previous == self.line_type['COMMENT_NOT']: 191 self.printer('\n') 192 pass 193 self.printer(self.comment + '\n') 194 self.comment = None 195 pass 196 197 # Change in comment, so ignore (handled above already). 198 if (not self.comment_Previous == self.comment) and \ (not self.comment_Previous == None): 200 return 201 elif self.comment_on_one: 202 return 203 204 # 205 # EVERYTHING ELSE (not blank line or comment)... 206 # ... print just the first line ... 207 # 208 209 # LAST. 210 if self.last_line_type_Previous == self.line_type['COMMENT']: 211 self.printer(self.indentation['a'] + line) 212 pass 213 # 214 self.last_line_type = self.line_type['COMMENT_NOT'] 215 216 pass 217 218 def MAIN(self): 219 """This reads the CSS and finds stuff.""" 220 # 221 for line in fileinput.input(): 222 self.parse_css(line) 223 pass 224 225 pass 226 227 def __call__(self): 228 """This executes when "class_instance()" is executed.""" 229 # 230 # Arguments: 231 if self.info['DEBUG']: 232 self.printer('sys.argv[1:]: ' + str(sys.argv[1:]) + '\n') 233 pass 234 235 # MAIN # 236 self.MAIN() 237 238 pass 239 240 # ------------------------ 241 # END OF CLASS DEFINITION. 242 pass 243 244 # ------------------------------------------------------- 245 # MAIN # 246 # 247 spam = Program(info) 248 spam() 249 250 # ------------------------------------------------------- 251 # 252 # My favorite way to execute this script: 253 # - 254 # - Ensure CPython mode available (Debian GNU/Linux: 255 # ``apt-get install python-elisp''). 256 # - Open .py file in GNU Emacs. 257 # - Execute with: "C-c C-c" (two Ctrl-c) 258 # - ...output appears in "*Python Output*" buffer. 259 # - 260 ### 261 262 # Local Variables: 263 # eval: (standard-display-european t) 264 # End: 265 # Local variables: 266 # py-indent-offset: 4 267 # End: |