aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Vilcans <martin@librador.com>2011-08-09 23:31:46 +0200
committerMartin Vilcans <martin@librador.com>2011-08-09 23:31:46 +0200
commita5c079fd7d7ebecc071974f5d538457a2beb9fea (patch)
treeb39f347c22eba7a4d39dc36bd3f01517e19b5bec
parentf55044504fadac6dbc089756f2c1a8a00f9e0622 (diff)
downloadscreenplain-a5c079fd7d7ebecc071974f5d538457a2beb9fea.tar.gz
Added first version of code
-rw-r--r--screenplain/__init__.py1
-rw-r--r--screenplain/export/__init__.py0
-rw-r--r--screenplain/export/pdf.py24
-rw-r--r--screenplain/export/text.py12
-rw-r--r--screenplain/main.py15
-rw-r--r--screenplain/parse.py120
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