I decided to write a small script to make writing HTML interactive stories less tedious:

import doctest
import re
import sys

import tkinter
import tkinter.filedialog

<html lang="en">
  <div align="center">

HTML_END = """

SEPARATOR = '\n---\n\n'

def link_to_self(word):
    Generates an html link to the given word.

    >>> link_to_self("spam")
    '<a href="Spam.html">spam</a>'
    return '<a href="{}.html">{}</a>'.format(word.capitalize(),word)

def inside_square_brackets(text):
    Returns all the text inside square brackets.

    >>> inside_square_brackets('Some nice [brackets]')
    return re.findall('\[.*?\]',text)

def insert_links(text):
    Insert links from square brackets.

    >>> insert_links("A [cake]?")
    'A <a href="Cake.html">cake</a>?'
    for link in inside_square_brackets(text):
        text = text.replace(link,link_to_self(link.replace('[','').replace(']','')))
    return text

def html_page(title,page):
    Generates an html page with title and text.
    return HTML_START.format(title.capitalize(),title.capitalize()) + insert_links(page) + HTML_END

def create_html_file(filename,text):
    with open(filename+'.html','w+') as f:

def gen_interactive_story(titles_and_texts):
    for title,text in titles_and_texts:

def parse_stories_and_titles(text):
    Spits out tuples (title,text) from a text containg paragraphs
    separated by the SEPARATOR.
    chunks = text.split(SEPARATOR)
    lines_from_chunks = [chunk.splitlines() for chunk in chunks]
    return [(line[0].capitalize(),''.join(line[1:]))
                for line in lines_from_chunks]

def find_txt_file(lst):
    Returns the first '.txt' file in a list.

    >>> find_txt_file(['a.txt','b.foo','c.py'])
    txts = [i for i in lst if '.txt' in i]
    if txts: return txts[0]

def contains_txt_file(lst):
    return bool(find_txt_file(lst))

def parse_and_generate_stories(filename):
    with open(filename) as f:
        titles_and_texts = parse_stories_and_titles(f.read())

def ask_filename():
    root = tkinter.Tk()
    return tkinter.filedialog.askopenfilenames()[0]

def _test():

def main():
    if contains_txt_file(sys.argv):
        filename = find_txt_file(sys.argv)
        filename = ask_filename()

if __name__ == "__main__":

To simplify testing, I include a properly written story:

a scary choice

It was an extremely [dark] night and around me I could only 
see a [cave] and a [wood].



I mean, extremely dark, even without moon. But I could not lose time,
it was time to make [a scary choice].



The cave was frightening, but I decided to go in nonetheless,
what is life without risk?



The wood was emitting scary and creepy sounds but I decided 
to enter it because it seemed less scary than the wood.

1 Answer 1


for starters, have it output valid html....so don't put a div and an h1 into your head...
also align is not a valid attribute. you should run your markup output through a validator

  • \$\begingroup\$ I recommend that you don't say to not output valid HTML.. what if the OP is unfamiliar with HTML? You could explain why doing that is bad practice, and you could even point to some online resources for extended reference. \$\endgroup\$
    – SirPython
    Mar 11, 2015 at 21:01
  • \$\begingroup\$ you could have done that too. i thought i was pretty clear. if @reticality feels like i need to explain more, i'm more than happy to \$\endgroup\$
    – albert
    Mar 11, 2015 at 21:10
  • \$\begingroup\$ I am curios about the benefit of valid html, so long as the html correctly shows up in mozilla and chrome, why should it also be 'correct'? \$\endgroup\$
    – Caridorc
    Mar 11, 2015 at 21:53
  • 1
    \$\begingroup\$ there are more browser engines than those fyi, and valid markup ensures the browser will render them correctly \$\endgroup\$
    – albert
    Mar 11, 2015 at 22:05
  • 1
    \$\begingroup\$ @albert I was just recommending something that could improve your post and could help not only Caridorc, but could also help future readers. \$\endgroup\$
    – SirPython
    Mar 11, 2015 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.