diff options
author | Martin Vilcans <martin@librador.com> | 2011-08-09 23:31:46 +0200 |
---|---|---|
committer | Martin Vilcans <martin@librador.com> | 2011-08-09 23:31:46 +0200 |
commit | a5c079fd7d7ebecc071974f5d538457a2beb9fea (patch) | |
tree | b39f347c22eba7a4d39dc36bd3f01517e19b5bec | |
parent | f55044504fadac6dbc089756f2c1a8a00f9e0622 (diff) | |
download | screenplain-a5c079fd7d7ebecc071974f5d538457a2beb9fea.tar.gz |
Added first version of code
-rw-r--r-- | screenplain/__init__.py | 1 | ||||
-rw-r--r-- | screenplain/export/__init__.py | 0 | ||||
-rw-r--r-- | screenplain/export/pdf.py | 24 | ||||
-rw-r--r-- | screenplain/export/text.py | 12 | ||||
-rw-r--r-- | screenplain/main.py | 15 | ||||
-rw-r--r-- | screenplain/parse.py | 120 |
6 files changed, 172 insertions, 0 deletions
diff --git a/screenplain/__init__.py b/screenplain/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/screenplain/__init__.py @@ -0,0 +1 @@ + diff --git a/screenplain/export/__init__.py b/screenplain/export/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/screenplain/export/__init__.py diff --git a/screenplain/export/pdf.py b/screenplain/export/pdf.py new file mode 100644 index 0000000..b25a0e3 --- /dev/null +++ b/screenplain/export/pdf.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +import fileinput +from reportlab.pdfgen import canvas +from reportlab.lib import pagesizes + +from screenplain.parse import parse, get_pages + +def to_pdf(input): + # pagesizes.letter, pagesizes.A4 + page_width, page_height = pagesizes.A4 + c = canvas.Canvas('out.pdf', pagesize=pagesizes.A4) + c.setFont('Courier', 12) + + paragraphs = parse(input) + for page_no, page in enumerate(get_pages(paragraphs), 1): + if page_no != 1: + c.showPage() + c.setFont('Courier', 12) + for line_no, line in enumerate(page): + c.drawString(0, page_height - 12 - 12 * line_no, line) + c.save() + +if __name__ == '__main__': + to_pdf(fileinput.input()) diff --git a/screenplain/export/text.py b/screenplain/export/text.py new file mode 100644 index 0000000..49a1f23 --- /dev/null +++ b/screenplain/export/text.py @@ -0,0 +1,12 @@ +import sys +from screenplain.parse import parse, get_pages + +def to_text(input): + out = sys.stdout + paragraphs = parse(input) + for page_no, page in enumerate(get_pages(paragraphs), 1): + if page_no != 1: + out.write('\f') + for line in page: + out.write(line) + out.write('\n') diff --git a/screenplain/main.py b/screenplain/main.py new file mode 100644 index 0000000..948914c --- /dev/null +++ b/screenplain/main.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +# Run with: +# PYTHONPATH=. python screenplain/main.py filename.txt + +import fileinput +import sys + +if __name__ == '__main__': + if False: + from screenplain.export.text import to_text + to_text(fileinput.input()) + else: + from screenplain.export.pdf import to_pdf + to_pdf(fileinput.input()) diff --git a/screenplain/parse.py b/screenplain/parse.py new file mode 100644 index 0000000..c4cadb5 --- /dev/null +++ b/screenplain/parse.py @@ -0,0 +1,120 @@ +import itertools +import textwrap + +# Numbers from http://www.emacswiki.org/emacs/ScreenPlay +# According to http://johnaugust.com/2004/how-many-lines-per-page +lines_per_page = 56 + +class _ParentheticalFlipFlop(object): + def __init__(self): + self.inside = False + + def __call__(self, text): + stripped = text.strip() + starts = stripped.startswith('(') + ends = stripped.endswith(')') + + if self.inside: + if ends: + self.inside = False + return True + else: + if starts and not ends: + self.inside = True + return starts + +class Slug(object): + indent = '' + top_margin = 1 + + def __init__(self, lines): + self.lines = [self.indent + line.strip() for line in lines] + + def format(self): + return self.lines + +class Dialog(object): + indent_character = ' ' * 22 + indent_dialog = ' ' * 10 + indent_parenthetical_first = ' ' * 16 + indent_parenthetical_subsequent = ' ' * 17 + + fill_parenthetical = 45 + fill_dialog = 45 + + top_margin = 1 + + def __init__(self, lines): + self.character = lines[0] + flipflop = _ParentheticalFlipFlop() + self.blocks = [ + (paren, ' '.join(t.strip() for t in lines)) + for paren, lines in itertools.groupby(lines[1:], flipflop)] + + def format(self): + yield self.indent_character + self.character + + for parenthetical, text in self.blocks: + if parenthetical: + lines = textwrap.wrap( + text, + width=self.fill_parenthetical, + initial_indent=self.indent_parenthetical_first, + subsequent_indent=self.indent_parenthetical_subsequent + ) + else: + lines = textwrap.wrap( + text, + width=self.fill_dialog, + initial_indent=self.indent_dialog, + subsequent_indent=self.indent_dialog + ) + for line in lines: + yield line + +class Action(object): + indent = '' + fill = 68 + top_margin = 1 + + def __init__(self, lines): + self.text = ' '.join(line.strip() for line in lines) + + def format(self): + for line in textwrap.wrap(self.text, width=self.fill): + yield self.indent + line + +def is_blank(string): + return string == '' or string.isspace() + +def create_paragraph(line_list): + if line_list[0].isupper(): + if len(line_list) == 1: + return Slug(line_list) + else: + return Dialog(line_list) + else: + return Action(line_list) + +def parse(source): + """Reads raw text input and generates paragraph objects.""" + for blank, lines in itertools.groupby( + (line.rstrip() for line in source), is_blank + ): + if not blank: + yield create_paragraph(list(lines)) + +def get_pages(paragraphs): + """Generates one list of lines per page.""" + lines_on_page = [] + for paragraph in paragraphs: + top_margin = paragraph.top_margin if lines_on_page else 0 + para_lines = list(paragraph.format()) + + if len(lines_on_page) + top_margin + len(para_lines) > lines_per_page: + yield lines_on_page + lines_on_page = [] + else: + lines_on_page += [''] * top_margin + lines_on_page += para_lines + yield lines_on_page |