1 This plugin works for me. It follows the standard for a movie screenplay pretty closely, I am not aware of any errors in format. Please let me know if you find any.
3 Right now all it does is display your pages properly in a web browser. What I would like to add is the ability to output a file that could easily be printed once the screenplay is finished. We keep all the scenes we work on in one folder and eventually we will want to print a script out of that folder. It would be great if an up to date PDF or TXT script could be put in the folder when a scene is saved. I will do it, it just isn't a priority yet.
5 I am not a published writer and not an authority on script formatting. I got what I know out of a book.
7 Briefly, you type a command on a line, like ".d", then on the next line (for the dialog command) you type a person's name. Then you hit return again and write the words he is supposed to speak out all on one line. When you save your document this simple text will become a properly formatted script.
9 Thank you Joey for having me here.
12 Most headings should begin with a transition. The list of valid commands is:
13 .fi => FADE IN: a gradual transition from a solid color to an image
15 .ftb => FADE TO BLACK.
16 .ftw => FADE TO WHITE.
17 .ct => CUT TO: indicates an instantaneous shift from one shot to the next
18 .shot => lack of an explicit transition assumes a cut
19 .hct => HARD CUT TO: describes a jarring transition
20 .qct => QUICK CUT TO: describes a cut sooner than expected
21 .tct => TIME CUT TO: emphasizes time passing
22 .mct => MATCH CUT TO: image in first shot visually or thematically matches image in second
23 .dt => DISSOLVE TO: gradual transition from image to another implies passage of time.
24 .rdt => RIPPLE DISSOLVE TO: indicates transition into daydream or imagination
25 .wt => WIPE TO: new image slides over top of last one
29 .fi (or any transition command) <= Writes a transition line, except .shot which omits it.
30 type shot heading here <= this line will be capitalized
31 First direction. <= these lines are not capitalized.
33 Third direction, etc...
35 Direction without a shot heading:
39 Third direction, etc...
41 Some items aren't implemented in dialogue yet:
42 1) you must watch that you don't leave a " -- " dangling on a line by itself,
43 instead, carry the last word onto the line with a dash
44 2) observe lyrical line endings in dialogue by indenting wrapped lines by two spaces
45 3) you must watch that the four line limit for parenthetical direction is not exceeded
50 char name <= this line will be capitalized
51 this is what he's saying <= Dialogue
52 raises hand to wave <= Parenthetical direction
53 this is more of what he's saying <= Dialogue
54 this is going to be in parenthesis <= Parenthetical direction
55 this is more of what he's saying, etc... <= Dialogue
58 Allows you to add a temporary note to a script without getting an error.
59 All notes need to be removed eventually because they are a format violation.
63 ###name this file screenplay.pm and pop it in your Plugin folder. Then you need to add the plugin to your Ikiwiki setup file.
66 # Screenplay markup language
67 package IkiWiki::Plugin::screenplay;
73 use Log::Log4perl qw(:easy);
74 Log::Log4perl->easy_init($INFO);
75 #Log::Log4perl->easy_init($ERROR);
78 hook(type => "getsetup", id => "screenplay", call => \&getsetup);
79 hook(type => "htmlize", id => "screenplay", call => \&htmlize, longname => "Screenplay");
86 rebuild => 1, # format plugin
92 #set up variables and fill with defaults
94 my $content = $params{content};
95 my @lines = split(/\r\n|\r|\n/, $content);
98 my $current_line = shift(@lines);
99 my $current_command = "";
100 my $current_chunk = "";
102 while (scalar(@lines) > 0) {
103 until ( &dot_command($current_line) || scalar(@lines) == 0 ) {
104 #skip spaces; mark bad lines
105 unless ( &blank_line($current_line) ) {
106 push(@formatted, "<br />");
107 push(@formatted, &no_command($current_line));
109 $current_line = shift(@lines);
112 #Exit while loop if we're out of lines
113 last if (scalar(@lines) == 0);
115 #set command for chunk
116 $current_command = $current_line;
117 $current_line = shift(@lines);
119 #get chunk, i.e. all text up to next blank line or a dot command.
120 until (substr($current_line,0,1) eq '.' || $current_line =~ m// || $current_line =~ m/^\s*$/) {
121 push(@chunk,$current_line);
122 $current_line = shift(@lines);
123 last unless defined $current_line;
126 #Start with a blank line unless unneeded.
127 if (scalar(@formatted) > 0 ) {
128 push(@formatted, "<br />");
131 #remaining lines are not commands.
132 if (scalar(@chunk)) {
133 $current_chunk = shift(@chunk);
134 if ($current_command eq ".shot") {
135 push(@formatted, &indent(&chunk(uc($current_chunk),57),17));
136 while (scalar(@chunk)) {
137 $current_chunk = shift(@chunk);
138 push(@formatted, "<br />");
139 push(@formatted, &indent(&chunk($current_chunk,57),17));
142 } elsif ($current_command eq ".note") {
143 push(@formatted, "NOTE:<br />");
144 push(@formatted, &chunk($current_chunk,75));
145 while (scalar(@chunk)) {
146 $current_chunk = shift(@chunk);
147 push(@formatted, "<br />");
148 push(@formatted, &chunk($current_chunk,75));
151 } elsif ($current_command eq ".dir") {
152 push(@formatted, &indent(&chunk($current_chunk,57),17));
153 while (scalar(@chunk)) {
154 $current_chunk = shift(@chunk);
155 push(@formatted, "<br />");
156 push(@formatted, &indent(&chunk($current_chunk,57),17));
159 } elsif ($current_command eq ".d") {
160 push(@formatted, &indent(&chunk(uc($current_chunk),32),41));
161 $current_chunk = shift(@chunk);
162 push(@formatted, &indent(&chunk($current_chunk,34),27));
163 while (scalar(@chunk) / 2 >= 1 ) {
164 $current_chunk = shift(@chunk);
165 push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
166 $current_chunk = shift(@chunk);
167 push(@formatted, &indent(&chunk($current_chunk,34),27));
170 } elsif ($current_command eq ".pd") {
171 push(@formatted, &indent(&chunk(uc($current_chunk),32),41));
172 $current_chunk = shift(@chunk);
173 push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
174 $current_chunk = shift(@chunk);
175 push(@formatted, &indent(&chunk($current_chunk,34),27));
176 while (scalar(@chunk) / 2 >= 1 ) {
177 $current_chunk = shift(@chunk);
178 push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
179 $current_chunk = shift(@chunk);
180 push(@formatted, &indent(&chunk($current_chunk,34),27));
183 } elsif ($current_command =~ m/^\.(fi|fo|ct|hct|qct|tct|mct|dt|rdt)$/) {
184 if ($current_command eq ".fi") {
185 push(@formatted, &indent(&chunk(uc("FADE IN:"),20),17));
186 } elsif ($current_command eq ".fo") {
187 push(@formatted, &indent(&chunk(uc("FADE OUT:"),20),60));
188 } elsif ($current_command eq ".ct") {
189 push(@formatted, &indent(&chunk(uc("CUT TO:"),20),60));
190 } elsif ($current_command eq ".hct") {
191 push(@formatted, &indent(&chunk(uc("HARD CUT TO:"),20),60));
192 } elsif ($current_command eq ".qct") {
193 push(@formatted, &indent(&chunk(uc("QUICK CUT TO:"),20),60));
194 } elsif ($current_command eq ".tct") {
195 push(@formatted, &indent(&chunk(uc("TIME CUT TO:"),20),60));
196 } elsif ($current_command eq ".mct") {
197 push(@formatted, &indent(&chunk(uc("MATCH CUT TO:"),20),60));
198 } elsif ($current_command eq ".dt") {
199 push(@formatted, &indent(&chunk(uc("DISSOLVE TO:"),20),60));
200 } elsif ($current_command eq ".rdt") {
201 push(@formatted, &indent(&chunk(uc("RIPPLE DISSOLVE TO:"),20),60));
202 } elsif ($current_command eq ".wt") {
203 push(@formatted, &indent(&chunk(uc("WIPE TO:"),20),60));
205 push(@formatted, &indent(&chunk(uc($current_chunk),57),17));
206 while (scalar(@chunk)) {
207 $current_chunk = shift(@chunk);
208 push(@formatted, "<br />");
209 push(@formatted, &indent(&chunk($current_chunk,57),17));
213 #mark the rest of the chunk as 'no command'
214 if (scalar(@chunk)) {
215 $current_chunk = shift(@chunk);
216 push(@formatted, &no_command($current_chunk));
224 while (scalar(@formatted)) {
226 $current_line = shift(@formatted);
227 if ( $i % 60 == 0 ) {
228 push(@content, &indent($i/60 . ".<br />",72) );
230 push(@content, $current_line);
232 $content = join("\r\n",@content);
237 my $line = shift(@_);
240 if ($line =~ m// || $line =~ m/^\s*$/) {
250 my $unchunked = shift(@_);
251 my $columns = shift(@_);
252 my $text = new Text::Format;
254 $text->columns($columns);
255 $text->firstIndent(0);
257 $text->extraSpace(1);
258 my @chunked = split /\n/, $text->format($unchunked);
261 push(@formatted, $_ . "<br />");
267 my $line = shift(@_);
270 if ($line =~ m/^\.(ct|dir|dt|d|fi|fo|hct|mct|note|pd|qct|rdt|shot|tct)$/) {
281 my $spaces = pop @unindented;
283 foreach (@unindented) {
284 push(@indented, " " x $spaces . $_);
290 my $line = shift(@_);
291 my $text = new Text::Format;
294 $text->firstIndent(0);
296 $text->extraSpace(1);
297 my @chunked = split /\n/, $text->format($line);
299 push(@formatted, ("NO COMMAND: "));
301 push(@formatted, ( $_ . "<br />" ));
308 # add '(' to top item
309 my $line = "(" . shift(@chunk);
310 unshift(@chunk, $line);
312 # add ')' to bottom item
313 $line = pop(@chunk) . ")";