#!/usr/bin/env python3

import sys
import re

def usage():
    print('usage: html_gen [FILE]')
    sys.exit(1)

def get_lines():
    with open(sys.argv[1]) as f:
        lines = [line for line in f]

        for line in lines:
            yield line

class Parser():
    def __init__(self):
        self.written_text = ''
        self.remaining_text = ''
        self.markup = { 'h1': '^[#]{1}(\s*)',
                        'h2': '^[#]{2}(\s*)',
                        'h3': '^[#]{3}(\s*)',
                        'h4': '^[#]{4}(\s*)',
                        'h5': '^[#]{5}(\s*)',
                        'h6': '^[#]{6}(\s*)',
                        'hr': '^-{3}',
                        'a': '((\[https?:\/{2}.+?\.(com|org|edu|net)\])(\(.+?\)))'
                      }
        self.header = False
        self.in_paragraph = False
        self.previous_line = None

    def get_tags(self):
        ''' Return the available markup symbols '''

        for tag in sorted(self.markup)[::-1]:
            yield tag

    def generate_paragraph(self, text):
        ''' Check if a line starts or ends a paragraph

        A paragraph is currently determined by blank lines separating
        a block of text.
        '''

        if self.previous_line == '' and text != '' and not self.header:
            self.in_paragraph = True
            return_text = "<p>" + text
        elif self.previous_line != '' and text == '' and self.in_paragraph:
            self.in_paragraph = False
            return_text = "</p>\n"
        else:
            return_text = text

        self.previous_line = text

        return return_text

    def generate_tag(self, line):
        ''' Generate a tag

        Parameters:
          line: the line to generate HTML from
        '''

        self.header = False

        text = self.parse_line(line.replace('\n', ''))
        text = self.generate_paragraph(text)

        return text

    def parse_line(self, text):
        ''' Parse a line recursively for markup symbols

        Parameters:
          text: a textual line
        Returns: the generated HTML
        '''

        self.written_text = text
        self.remaining_text = ''

        for key in self.get_tags():
            if re.search(self.markup[key], text) and key == 'hr':
                self.written_text = '<hr>'
                break
            elif re.search(self.markup[key], text) and key != 'a':
                r = re.search(self.markup[key], text)
                self.remaining_text = text[r.span()[1]:]
                self.written_text = ''.join(['<', key, '>', self.parse_line(self.remaining_text),
                                       '</', key, '>\n'])
                self.remaining_text = ''
                self.header = True
                break
            elif re.search(self.markup['a'], text):
                rng = re.search(self.markup['a'], text)
                link_name = rng.groups()[1].replace('[', '').replace(']', '')
                link_title = rng.groups()[3].replace('(', '').replace(')', '')

                # Check where the link is within the line
                if rng.start(0) > 0:
                    self.written_text = ''.join([text[:rng.start(0)], "<a href='",
                                                 link_name, "'>", link_title, "</a>"])
                else:
                    self.written_text = ''.join(["<a href='", link_name, "'>",
                                                 link_title, "</a>"])

                self.remaining_text = text[rng.end(len(rng.groups())):]

        if self.remaining_text == '':
            return self.written_text

        return self.written_text + self.parse_line(self.remaining_text)

def write_html():
    ''' Writes the HTML '''

    html = '<!doctype HTML>\n<html>\n<head></head>\n<body>\n' + \
           str(convert_text_to_html()) + '\n</body>\n</html>'

    with open('output.html', 'w') as out:
        out.write(html)

def convert_text_to_html():
    ''' Converts the text source into HTML markup '''

    parser = Parser()
    html = ''

    with open(sys.argv[1]) as f:
        for line in get_lines():
            html += parser.generate_tag(line)

    return html

if __name__ == '__main__':

    if len(sys.argv) == 1:
        usage()

    write_html()

@@ -2220,18 +2220,23 @@
         
-if
+match =
  re.sear
@@ -2257,28 +2257,66 @@
 %5Bkey%5D, text)
- and
+%0A%0A            if match:%0A                if
  key == 'hr'
@@ -2325,32 +2325,36 @@
                 
+   
+ 
 self.written_tex
@@ -2384,135 +2384,29 @@
     
-break%0A            elif re.search(self.markup%5Bkey%5D, text) and key != 'a':%0A                r = re.search(self.markup%5Bkey%5D, text)%0A
+elif key != 'a':%0A    
     
@@ -2444,17 +2444,21 @@
  = text%5B
-r
+match
 .span()%5B
@@ -2462,16 +2462,20 @@
 ()%5B1%5D:%5D%0A
+    
         
@@ -2603,16 +2603,26 @@
         
+          
 '%3C/', ke
@@ -2643,42 +2643,8 @@
     
-         self.remaining_text = ''%0A
     
@@ -2648,27 +2648,24 @@
             
-   
 self.header 
@@ -2691,122 +2691,29 @@
     
-break%0A            elif re.search(self.markup%5B'a'%5D, text):%0A                rng = re.search(self.markup%5B'a'%5D, text)%0A
+elif key == 'a':%0A    
     
@@ -2732,27 +2732,29 @@
 link_name = 
-rng
+match
 .groups()%5B1%5D
@@ -2796,32 +2796,36 @@
                 
+    
 link_title = rng
@@ -2821,19 +2821,21 @@
 title = 
-rng
+match
 .groups(
@@ -2890,16 +2890,20 @@
         
+    
 # Check 
@@ -2956,14 +2956,20 @@
     
+   
+ 
 if 
-rng
+match
 .sta
@@ -2979,16 +2979,20 @@
 0) %3E 0:%0A
+    
         
@@ -3038,19 +3038,21 @@
 (%5Btext%5B:
-rng
+match
 .start(0
@@ -3068,16 +3068,20 @@
 ref='%22,%0A
+    
         
@@ -3167,38 +3167,46 @@
                 
+  
+  
 else:%0A
+    
                 
@@ -3309,32 +3309,36 @@
                 
+    
 link_title, %22%3C/a
@@ -3343,16 +3343,20 @@
 /a%3E%22%5D)%0A%0A
+    
         
@@ -3390,19 +3390,21 @@
  = text%5B
-rng
+match
 .end(len
@@ -3408,11 +3408,13 @@
 len(
-rng
+match
 .gro
@@ -3424,16 +3424,39 @@
 ())):%5D%0A%0A
+                break%0A%0A
         

Remove duplicate code in Parser's parse_line()