# This software carries the following license: # # Modified BSD license # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Steinar Knutsen """GuideHTML 1.2 Tool for generating HTML from files with syntax inspired by AmigaGuide. @TITLE @EM @STRONG @TT @BR @LINK @NAME @P @H @BLOCKQUOTE @ADDRESS @DL { ... } (In other words, every second element becomes
and
, respectively.) @UL { ... } @OL { ... } @TIME Inserts time of generation. The timespec is sent to strftime(). @CONCAT Concatenates the two input elements with no space between them. @INCLUDE Inserts the contents of named file as a text unit. { ... } groups text elements into a new text element. More or less everything is whitespace and case insensitive. It is not necessary to write the entire tag names, only enough to identify a tag unambiguisly is necessary. """ import shlex, sys, time, string from DCLMatcher import DCLMatcher def strip_apo(word): if len(word) >= 2: if word[0] == '"' and word[-1] == '"': return word[1:-1] elif word[0] == "'" and word[-1] == "'": return word[1:-1] else: return word else: return word class message: pass EndCurly = message() commenters = '' wordchars = ("!#$%&()*+,-./0123456789:;<=>?" "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz" "|~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿" "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ") class converter(shlex.shlex): def __init__(self, stream=sys.stdin, outstream = sys.stdout, tags = None): self.outstream = outstream if not tags: self.tags = DCLMatcher({ "TITLE": self.__title, "EM": self.__em, "STRONG": self.__strong, "TT": self.__tt, "BR": self.__br, "LINK": self.__link, "NAME": self.__name, "P": self.__p, "H": self.__h, "BLOCKQUOTE": self.__blockquote, "ADDRESS": self.__address, "DL": self.__dl, "UL": self.__ul, "OL": self.__ol, "TIME": self.__time, "CONCAT": self.__concat, "INCLUDE": self.__include }) else: self.tags = tags shlex.shlex.__init__(self, stream) self.wordchars = wordchars self.commenters = commenters def close(self): # Trigs the parsing of the input. logical = self.get_logical() document = [] while len(logical) > 0: document.append(logical) logical = self.get_logical() self.outstream.write(string.join(document, ' ')) def get_logical(self): token = self.get_token() if token == '{': return self.grouper() elif token == '@': return self.alpha() elif token == '}': return EndCurly else: return strip_apo(token) def alpha(self): # Tag look-up and unpleasant stuff like that. command = self.get_logical() # This will and should explode confronted with unknown tags. return self.tags[command]() def grouper(self): # Token grouping. tokens = [] logical = self.get_logical() while logical != EndCurly: tokens.append(logical) logical = self.get_logical() return string.join(tokens, ' ') def __title(self): return "%s\n" % self.get_logical() def __em(self): return "%s" % self.get_logical() def __strong(self): return "%s" % self.get_logical() def __tt(self): return "%s" % self.get_logical() def __br(self): return "
" def __link(self): url = self.get_logical() text = self.get_logical() return '%s' % (url, text) def __name(self): name = self.get_logical() text = self.get_logical() return '%s' % (url, text) def __p(self): return "\n

\n%s\n" % self.get_logical() def __h(self): lvl = self.get_logical() header = self.get_logical() return "\n%s\n" % (lvl, header, lvl) def __blockquote(self): return "\n

\n%s\n
\n" % self.get_logical() def __address(self): return "\n
\n%s\n
\n" % self.get_logical() # Variable element number tags, dl, ul, ol. def isBeginCurly(self): if self.get_token() != '{': raise "{ expected at line %s" % self.lineno def __dl(self): sys.stdout.flush() self.isBeginCurly() dl = ['\n
'] item = self.get_logical() while item != EndCurly: assert item != '' definition = self.get_logical() dl.append("
%s" % item) dl.append("
%s" % definition) item = self.get_logical() dl.append('
\n') return string.join(dl, '\n') def __ul(self): self.isBeginCurly() ul = ['\n
    '] item = self.get_logical() while item != EndCurly: assert item != '' ul.append("
  • %s" % item) item = self.get_logical() ul.append('
\n') return string.join(ul, '\n') def __ol(self): self.isBeginCurly() ol = ['\n
    '] item = self.get_logical() while item != EndCurly: assert item != '' ol.append("
  1. %s" % item) item = self.get_logical() ol.append('
\n') return string.join(ol, '\n') def __time(self): return time.strftime(self.get_logical(), time.localtime(time.time())) def __concat(self): return self.get_logical() + self.get_logical() def __include(self): file = open(self.get_logical()) text = file.read(-1) file.close() return text if __name__ == '__main__': html = converter() html.close()