aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Vilcans <martin@librador.com>2012-02-07 22:26:14 +0100
committerMartin Vilcans <martin@librador.com>2012-02-07 22:37:00 +0100
commitef1635819c057f634cb776b9c57c7d1348b88c26 (patch)
treeecd54b21df4f006dfd07687a7b81f2d5ec9c1769
parent45ae626de30f9676aa6a16f868644f2054e65074 (diff)
downloadscreenplain-ef1635819c057f634cb776b9c57c7d1348b88c26.tar.gz
Added scene numbers
-rw-r--r--screenplain/export/html.py7
-rw-r--r--screenplain/parsers/spmd.py30
-rw-r--r--screenplain/types.py8
-rw-r--r--tests/files/scene-numbers.spmd7
-rw-r--r--tests/files/scene-numbers.spmd.html4
-rw-r--r--tests/files_test.py6
-rw-r--r--tests/spmd_test.py16
7 files changed, 60 insertions, 18 deletions
diff --git a/screenplain/export/html.py b/screenplain/export/html.py
index d1f3820..881233c 100644
--- a/screenplain/export/html.py
+++ b/screenplain/export/html.py
@@ -81,8 +81,15 @@ def _write_dialog_block(dialog, out):
def format_slug(slug, out):
+ num = slug.scene_number
with tags(out, 'h2'):
+ if num:
+ with tags(out, 'span class="scnuml"'):
+ out.write(to_html(slug.scene_number))
out.write(to_html(slug.line))
+ if num:
+ with tags(out, 'span class="scnumr"'):
+ out.write(to_html(slug.scene_number))
def format_action(para, out):
diff --git a/screenplain/parsers/spmd.py b/screenplain/parsers/spmd.py
index 7df7ce3..89a457c 100644
--- a/screenplain/parsers/spmd.py
+++ b/screenplain/parsers/spmd.py
@@ -10,15 +10,10 @@ from screenplain.types import (
)
from screenplain.richstring import parse_emphasis
-slug_prefixes = (
- 'INT. ',
- 'EXT. ',
- 'INT./EXT. ',
- 'INT/EXT. ',
- 'INT ',
- 'EXT ',
- 'INT/EXT ',
- 'I/E ',
+slug_regexes = (
+ re.compile(r'^(INT|EXT|EST)[ .]'),
+ re.compile(r'^(INT\.?/EXT\.?)[ .]'),
+ re.compile(r'^I/E[ .]'),
)
TWOSPACE = ' ' * 2
@@ -26,6 +21,7 @@ TWOSPACE = ' ' * 2
centered_re = re.compile(r'\s*>\s*(.*?)\s*<\s*$')
dual_dialog_re = re.compile(r'^(.+?)(\s*\^)$')
slug_re = re.compile(r'(?:(\.)\s*)?(\S.*?)\s*$')
+scene_number_re = re.compile(r'(.*?)\s*(?:#([^#]+)#)\s*$')
transition_re = re.compile(r'(>?)\s*(.+?)(:?)$')
@@ -62,17 +58,19 @@ class InputParagraph(object):
match = slug_re.match(self.lines[0])
if not match:
- return
+ return None
period, text = match.groups()
- if period:
- return Slug(_to_rich(text.upper()))
-
- upper = text.upper()
- if not any(upper.startswith(s) for s in slug_prefixes):
+ text = text.upper()
+ if not period and not any(regex.match(text) for regex in slug_regexes):
return None
- return Slug(_to_rich(upper))
+ match = scene_number_re.match(text)
+ if match:
+ text, scene_number = match.groups()
+ return Slug(_to_rich(text), _to_rich(scene_number))
+ else:
+ return Slug(_to_rich(text))
def as_centered_action(self):
if not all(centered_re.match(line) for line in self.lines):
diff --git a/screenplain/types.py b/screenplain/types.py
index 7ef6cc9..fb21c1b 100644
--- a/screenplain/types.py
+++ b/screenplain/types.py
@@ -9,8 +9,14 @@ class Slug(object):
indent = ''
top_margin = 1
- def __init__(self, line):
+ def __init__(self, line, scene_number=None):
+ """Creates a scene heading (slug).
+ The line parameter is a RichString with the slugline.
+ The scene_number parameter is an optional RichString.
+
+ """
self.line = line
+ self.scene_number = scene_number
@property
def lines(self):
diff --git a/tests/files/scene-numbers.spmd b/tests/files/scene-numbers.spmd
new file mode 100644
index 0000000..51064d2
--- /dev/null
+++ b/tests/files/scene-numbers.spmd
@@ -0,0 +1,7 @@
+INT. SOMEWHERE - DAY #1#
+
+Bla bla
+
+INT. SOMEWHERE ELSE - NIGHT #2#
+
+Bla bla
diff --git a/tests/files/scene-numbers.spmd.html b/tests/files/scene-numbers.spmd.html
new file mode 100644
index 0000000..8179c79
--- /dev/null
+++ b/tests/files/scene-numbers.spmd.html
@@ -0,0 +1,4 @@
+<h2><span class="scnuml">1</span>INT. SOMEWHERE - DAY<span class="scnumr">1</span></h2>
+<div class="action"><p>Bla bla</p></div>
+<h2><span class="scnuml">2</span>INT. SOMEWHERE ELSE - NIGHT<span class="scnumr">2</span></h2>
+<div class="action"><p>Bla bla</p></div>
diff --git a/tests/files_test.py b/tests/files_test.py
index af478fb..1637dda 100644
--- a/tests/files_test.py
+++ b/tests/files_test.py
@@ -58,3 +58,9 @@ class ParseTests(unittest2.TestCase):
actual, expected = self.convert(
'simple.spmd', 'simple.html', 'simple.spmd.html', '--bare')
self.assertMultiLineEqual(expected, actual)
+
+ def test_scene_numbers(self):
+ actual, expected = self.convert(
+ 'scene-numbers.spmd', 'scene-numbers.html',
+ 'scene-numbers.spmd.html', '--bare')
+ self.assertMultiLineEqual(expected, actual)
diff --git a/tests/spmd_test.py b/tests/spmd_test.py
index 9f03076..b317b56 100644
--- a/tests/spmd_test.py
+++ b/tests/spmd_test.py
@@ -5,7 +5,7 @@
import unittest2
from screenplain.parsers.spmd import parse
from screenplain.types import Slug, Action, Dialog, DualDialog, Transition
-from screenplain.richstring import plain, empty_string
+from screenplain.richstring import plain, italic, empty_string
class ParseTests(unittest2.TestCase):
@@ -62,6 +62,20 @@ class ParseTests(unittest2.TestCase):
self.assertEquals(Slug, type(paras[0]))
self.assertEquals(plain('SNIPER SCOPE POV'), paras[0].line)
+ def test_scene_number_is_parsed(self):
+ paras = parse(['EXT SOMEWHERE - DAY #42#'])
+ self.assertEquals(plain('EXT SOMEWHERE - DAY'), paras[0].line)
+ self.assertEquals(plain('42'), paras[0].scene_number)
+
+ def test_only_last_two_hashes_in_slug_used_for_scene_number(self):
+ paras = parse(['INT ROOM #237 #42#'])
+ self.assertEquals(plain('42'), paras[0].scene_number)
+ self.assertEquals(plain('INT ROOM #237'), paras[0].line)
+
+ def test_scene_number_can_be_styled(self):
+ paras = parse(['.SOMEWHERE #*HELLO*#'])
+ self.assertEquals(italic('HELLO'), paras[0].scene_number)
+
# A Character element is any line entirely in caps, with one empty
# line before it and without an empty line after it.
def test_all_caps_is_character(self):