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: