master
parent
c12f709140
commit
065811d203
|
@ -0,0 +1,320 @@
|
|||
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.
|
||||
|
||||
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.
|
||||
|
||||
I am not a published writer and not an authority on script formatting. I got what I know out of a book.
|
||||
|
||||
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.
|
||||
|
||||
Thank you Joey for having me here.
|
||||
|
||||
###Headings:
|
||||
Most headings should begin with a transition. The list of valid commands is:
|
||||
.fi => FADE IN: a gradual transition from a solid color to an image
|
||||
.fo => FADE OUT.
|
||||
.ftb => FADE TO BLACK.
|
||||
.ftw => FADE TO WHITE.
|
||||
.ct => CUT TO: indicates an instantaneous shift from one shot to the next
|
||||
.shot => lack of an explicit transition assumes a cut
|
||||
.hct => HARD CUT TO: describes a jarring transition
|
||||
.qct => QUICK CUT TO: describes a cut sooner than expected
|
||||
.tct => TIME CUT TO: emphasizes time passing
|
||||
.mct => MATCH CUT TO: image in first shot visually or thematically matches image in second
|
||||
.dt => DISSOLVE TO: gradual transition from image to another implies passage of time.
|
||||
.rdt => RIPPLE DISSOLVE TO: indicates transition into daydream or imagination
|
||||
.wt => WIPE TO: new image slides over top of last one
|
||||
|
||||
Example transition:
|
||||
|
||||
.fi (or any transition command) <= Writes a transition line, except .shot which omits it.
|
||||
type shot heading here <= this line will be capitalized
|
||||
First direction. <= these lines are not capitalized.
|
||||
Second direction.
|
||||
Third direction, etc...
|
||||
|
||||
Direction without a shot heading:
|
||||
.dir
|
||||
First direction.
|
||||
Second direction.
|
||||
Third direction, etc...
|
||||
|
||||
Some items aren't implemented in dialogue yet:
|
||||
1) you must watch that you don't leave a " -- " dangling on a line by itself,
|
||||
instead, carry the last word onto the line with a dash
|
||||
2) observe lyrical line endings in dialogue by indenting wrapped lines by two spaces
|
||||
3) you must watch that the four line limit for parenthetical direction is not exceeded
|
||||
|
||||
Example dialogue:
|
||||
|
||||
.d
|
||||
char name <= this line will be capitalized
|
||||
this is what he's saying <= Dialogue
|
||||
raises hand to wave <= Parenthetical direction
|
||||
this is more of what he's saying <= Dialogue
|
||||
this is going to be in parenthesis <= Parenthetical direction
|
||||
this is more of what he's saying, etc... <= Dialogue
|
||||
|
||||
.note
|
||||
Allows you to add a temporary note to a script without getting an error.
|
||||
All notes need to be removed eventually because they are a format violation.
|
||||
|
||||
|
||||
|
||||
###name this file screenplay.pm and pop it in your Plugin folder. Then you need to add the plugin to your Ikiwiki setup file.
|
||||
|
||||
#!/usr/bin/perl
|
||||
# Screenplay markup language
|
||||
package IkiWiki::Plugin::screenplay;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use IkiWiki 3.00;
|
||||
use Text::Format;
|
||||
use Log::Log4perl qw(:easy);
|
||||
Log::Log4perl->easy_init($INFO);
|
||||
#Log::Log4perl->easy_init($ERROR);
|
||||
|
||||
sub import {
|
||||
hook(type => "getsetup", id => "screenplay", call => \&getsetup);
|
||||
hook(type => "htmlize", id => "screenplay", call => \&htmlize, longname => "Screenplay");
|
||||
}
|
||||
|
||||
sub getsetup () {
|
||||
return
|
||||
plugin => {
|
||||
safe => 1,
|
||||
rebuild => 1, # format plugin
|
||||
section => "format",
|
||||
},
|
||||
}
|
||||
|
||||
sub htmlize (@) {
|
||||
#set up variables and fill with defaults
|
||||
my %params=@_;
|
||||
my $content = $params{content};
|
||||
my @lines = split(/\r\n|\r|\n/, $content);
|
||||
my @chunk;
|
||||
my @formatted;
|
||||
my $current_line = shift(@lines);
|
||||
my $current_command = "";
|
||||
my $current_chunk = "";
|
||||
|
||||
while (scalar(@lines) > 0) {
|
||||
until ( &dot_command($current_line) || scalar(@lines) == 0 ) {
|
||||
#skip spaces; mark bad lines
|
||||
unless ( &blank_line($current_line) ) {
|
||||
push(@formatted, "<br />");
|
||||
push(@formatted, &no_command($current_line));
|
||||
}
|
||||
$current_line = shift(@lines);
|
||||
}
|
||||
|
||||
#Exit while loop if we're out of lines
|
||||
last if (scalar(@lines) == 0);
|
||||
|
||||
#set command for chunk
|
||||
$current_command = $current_line;
|
||||
$current_line = shift(@lines);
|
||||
|
||||
#get chunk, i.e. all text up to next blank line or a dot command.
|
||||
until (substr($current_line,0,1) eq '.' || $current_line =~ m// || $current_line =~ m/^\s*$/) {
|
||||
push(@chunk,$current_line);
|
||||
$current_line = shift(@lines);
|
||||
last unless defined $current_line;
|
||||
}
|
||||
|
||||
#Start with a blank line unless unneeded.
|
||||
if (scalar(@formatted) > 0 ) {
|
||||
push(@formatted, "<br />");
|
||||
}
|
||||
|
||||
#remaining lines are not commands.
|
||||
if (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
if ($current_command eq ".shot") {
|
||||
push(@formatted, &indent(&chunk(uc($current_chunk),57),17));
|
||||
while (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, "<br />");
|
||||
push(@formatted, &indent(&chunk($current_chunk,57),17));
|
||||
}
|
||||
|
||||
} elsif ($current_command eq ".note") {
|
||||
push(@formatted, "NOTE:<br />");
|
||||
push(@formatted, &chunk($current_chunk,75));
|
||||
while (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, "<br />");
|
||||
push(@formatted, &chunk($current_chunk,75));
|
||||
}
|
||||
|
||||
} elsif ($current_command eq ".dir") {
|
||||
push(@formatted, &indent(&chunk($current_chunk,57),17));
|
||||
while (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, "<br />");
|
||||
push(@formatted, &indent(&chunk($current_chunk,57),17));
|
||||
}
|
||||
|
||||
} elsif ($current_command eq ".d") {
|
||||
push(@formatted, &indent(&chunk(uc($current_chunk),32),41));
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk($current_chunk,34),27));
|
||||
while (scalar(@chunk) / 2 >= 1 ) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk($current_chunk,34),27));
|
||||
}
|
||||
|
||||
} elsif ($current_command eq ".pd") {
|
||||
push(@formatted, &indent(&chunk(uc($current_chunk),32),41));
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk($current_chunk,34),27));
|
||||
while (scalar(@chunk) / 2 >= 1 ) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk(&pd($current_chunk),19),34));
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &indent(&chunk($current_chunk,34),27));
|
||||
}
|
||||
|
||||
} elsif ($current_command =~ m/^\.(fi|fo|ct|hct|qct|tct|mct|dt|rdt)$/) {
|
||||
if ($current_command eq ".fi") {
|
||||
push(@formatted, &indent(&chunk(uc("FADE IN:"),20),17));
|
||||
} elsif ($current_command eq ".fo") {
|
||||
push(@formatted, &indent(&chunk(uc("FADE OUT:"),20),60));
|
||||
} elsif ($current_command eq ".ct") {
|
||||
push(@formatted, &indent(&chunk(uc("CUT TO:"),20),60));
|
||||
} elsif ($current_command eq ".hct") {
|
||||
push(@formatted, &indent(&chunk(uc("HARD CUT TO:"),20),60));
|
||||
} elsif ($current_command eq ".qct") {
|
||||
push(@formatted, &indent(&chunk(uc("QUICK CUT TO:"),20),60));
|
||||
} elsif ($current_command eq ".tct") {
|
||||
push(@formatted, &indent(&chunk(uc("TIME CUT TO:"),20),60));
|
||||
} elsif ($current_command eq ".mct") {
|
||||
push(@formatted, &indent(&chunk(uc("MATCH CUT TO:"),20),60));
|
||||
} elsif ($current_command eq ".dt") {
|
||||
push(@formatted, &indent(&chunk(uc("DISSOLVE TO:"),20),60));
|
||||
} elsif ($current_command eq ".rdt") {
|
||||
push(@formatted, &indent(&chunk(uc("RIPPLE DISSOLVE TO:"),20),60));
|
||||
} elsif ($current_command eq ".wt") {
|
||||
push(@formatted, &indent(&chunk(uc("WIPE TO:"),20),60));
|
||||
}
|
||||
push(@formatted, &indent(&chunk(uc($current_chunk),57),17));
|
||||
while (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, "<br />");
|
||||
push(@formatted, &indent(&chunk($current_chunk,57),17));
|
||||
}
|
||||
|
||||
}
|
||||
#mark the rest of the chunk as 'no command'
|
||||
if (scalar(@chunk)) {
|
||||
$current_chunk = shift(@chunk);
|
||||
push(@formatted, &no_command($current_chunk));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
my @content;
|
||||
my $i = 0;
|
||||
$current_line = "";
|
||||
while (scalar(@formatted)) {
|
||||
$i++;
|
||||
$current_line = shift(@formatted);
|
||||
if ( $i % 60 == 0 ) {
|
||||
push(@content, &indent($i/60 . ".<br />",72) );
|
||||
}
|
||||
push(@content, $current_line);
|
||||
}
|
||||
$content = join("\r\n",@content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub blank_line {
|
||||
my $line = shift(@_);
|
||||
my $ret = 0;
|
||||
|
||||
if ($line =~ m// || $line =~ m/^\s*$/) {
|
||||
$ret = 1;
|
||||
} else {
|
||||
$ret = 0;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub chunk () {
|
||||
my $unchunked = shift(@_);
|
||||
my $columns = shift(@_);
|
||||
my $text = new Text::Format;
|
||||
$text->rightFill(1);
|
||||
$text->columns($columns);
|
||||
$text->firstIndent(0);
|
||||
$text->tabstop(0);
|
||||
$text->extraSpace(1);
|
||||
my @chunked = split /\n/, $text->format($unchunked);
|
||||
my @formatted;
|
||||
foreach (@chunked) {
|
||||
push(@formatted, $_ . "<br />");
|
||||
}
|
||||
return @formatted;
|
||||
}
|
||||
|
||||
sub dot_command {
|
||||
my $line = shift(@_);
|
||||
my $ret = 0;
|
||||
|
||||
if ($line =~ m/^\.(ct|dir|dt|d|fi|fo|hct|mct|note|pd|qct|rdt|shot|tct)$/) {
|
||||
$ret = 1;
|
||||
} else {
|
||||
$ret = 0;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub indent () {
|
||||
my @unindented = @_;
|
||||
my $spaces = pop @unindented;
|
||||
my @indented;
|
||||
foreach (@unindented) {
|
||||
push(@indented, " " x $spaces . $_);
|
||||
}
|
||||
return @indented;
|
||||
}
|
||||
|
||||
sub no_command () {
|
||||
my $line = shift(@_);
|
||||
my $text = new Text::Format;
|
||||
$text->rightFill(1);
|
||||
$text->columns(68);
|
||||
$text->firstIndent(0);
|
||||
$text->tabstop(0);
|
||||
$text->extraSpace(1);
|
||||
my @chunked = split /\n/, $text->format($line);
|
||||
my @formatted;
|
||||
push(@formatted, ("NO COMMAND: "));
|
||||
foreach (@chunked) {
|
||||
push(@formatted, ( $_ . "<br />" ));
|
||||
}
|
||||
return @formatted;
|
||||
}
|
||||
|
||||
sub pd () {
|
||||
my @chunk = @_;
|
||||
# add '(' to top item
|
||||
my $line = "(" . shift(@chunk);
|
||||
unshift(@chunk, $line);
|
||||
|
||||
# add ')' to bottom item
|
||||
$line = pop(@chunk) . ")";
|
||||
push(@chunk, $line);
|
||||
|
||||
return @chunk;
|
||||
}
|
||||
|
||||
1
|
||||
|
Loading…
Reference in New Issue