Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Making Cue Scripts with Perl

by starX (Chaplain)
on Dec 17, 2012 at 18:19 UTC ( [id://1009211]=CUFP: print w/replies, xml ) Need Help??

For those of you who aren't familiar with Shakespearean stage-craft, one of the particularly interesting staging conditions of Elizabethan London is that individual actors didn't have copies of the whole play: they had only their own parts, with a few cue words written out for them. As more theatre companies are experimenting with re-creating Shakespeare's staging conditions, more are turning to this form of script distribution under the premise that it forces actors to listen to each other, and allows for some interesting discoveries in rehearsal.

While creating cue scripts is a lot easier with a word processor than it was writing it out by hand 400 years ago, I wrote this script to make generating cue scripts even easier. It's functionality is currently limited to processing files from the MIT Shakespeare, but it supports creating a cue script that includes multiple parts (as many as the end user specifies) because doubling is one of Shakespeare's original staging conditions, too:

#!/usr/bin/perl # # cueScriptGen # # Generate a cue script from an MIT Shakespeare File # # # Released under the GPL 2.0 and all that jazz. # # This is just a prototype. A more polished version will need further # testing and development. # # Last Revised 12 Dec. 2012 8 PM use strict; use warnings; # The user must give us at least one character name (but may give us # any number of them), followed by a script file. If they don't, # print a simple error and exit. if (@ARGV < 2) { die "usage is \"cueScriptGen character_1 [character_2 &c] file_name\ +"\n"; } # We should edit this to either accept a file name or a URL. # If we force a URL, we can explore transformations based on # alternative methods of formatting. # Whatever the file is, it will be the LAST thing in our # argument list, so pop it off so we have a list of nothing # but characters. my $mit_shakes = pop @ARGV; # Initialize variables. my $cue_line = ""; my $prev_cue_line = ""; my $act = ""; my $scene = ""; my $new_act = "false"; my $new_scene = "false"; my $line = ""; my $title_of_play = ""; # Open a file or quit with a basic warning if you can't. open PLAY, $mit_shakes || die "Could not open file: $!\n"; # Step 0.5: Print basic html header info from the file, and # them some heading info so the reader knows what they're # looking at. until ($line =~ m/<\/head>/) { if ($line =~ m/<title>(.*)<\/title>/) { $title_of_play = $1; } print "$line\n"; $line = <PLAY>; } print "</head>\n<body>\n"; print "<h1>$title_of_play</h1>\n"; print '<h2>Cue Script for '; # This boolean will tell us if we're on the # first item in the list, which should not # be preceeded by a comma and a space when # printing the list of characters. my $i = 0; foreach (@ARGV) { if ($i == 0) { print "$_"; $i = 1; } else { print ", $_"; } } print ". </h2>\n"; # Traverse the file until EOF while (<PLAY>) { $line = $_; # print "</head>\n"; # Step 1: Find a speech block that contains a character that we're l +ooking for. # We need to do this for every character left in our arguument list. + foreach (@ARGV) { my $character = $_; if ($line =~ m/^<a name="speech\d+"><b>$character<\/b>/i) { # Print the act heading if we haven't yet. if ($new_act eq "true") { print "$act\n"; $new_act = "false"; } # Print the scene headin if we haven't yet. if ($new_scene eq "true") { print "$scene\n"; $new_scene = "false"; } # Step 2: We've found a line of text that matches a block of tex +t for the # character we're looking for, so first we need to print their c +ue line. # See step 1.5 (below) for details. If the cue line is less than + three # words long, print the line that came before it, too. $cue_line =~ m/^<a name="\d+\.\d+\.\d+">(.*)</; my @cue_words = split /\s/, $1; my $cue_words = @cue_words; if ($cue_words < 2) { print "<b>Cue:</b> $prev_cue_line\n$cue_line\n\n"; } else { #print "<b>Cue:</b> $cue_line\n\n"; } # Step 3: Print the entire speech block for the character; you k +now you're # at the end of the block when you reach the closing blockquote while ($line !~ m/<\/blockquote>/) { print "$line\n"; # We still need to keep track of the cue line, just in case the cu +e script # is for an actor who plays two roles with back to back lines. $prev_cue_line = $cue_line; $cue_line = $line; # Read the next line of the file. $line = <PLAY>; } # Step 4: Print the closing blockquote. print "</blockquote>\n"; } # Step 1.5: We need to keep track of each line of text as we go, s +o if the # line was not a speech heading, see if it's a line of text. If it + is, keep it elsif ($line =~ m/^<a name="\d\.\d+\.\d+"/) { $prev_cue_line = $cue_line; $cue_line = $line; } # Step 1.6: We should also print act headings. elsif ($line =~ m/.*<h3>ACT \w+.*/) { $act = $line; $new_act = "true"; } # Step 1.7: We should also print scene headings. elsif ($line =~ m/.*<h3>SCENE \w+.*/) { $scene = $line; $new_scene = "true"; } } } # Last piece of cleanup, close off our HTML elements print "\n</body>\n</html>\n";

Please feel free to comment and make suggestions for improvements.

Replies are listed 'Best First'.
Re: Making Cue Scripts with Perl
by jwkrahn (Abbot) on Dec 17, 2012 at 21:19 UTC
    open PLAY, $mit_shakes || die "Could not open file: $!\n";

    You are testing whether $mit_shakes is true or false, not whether open succeeded or failed.    You need to either use parentheses:

    open( PLAY, $mit_shakes ) || die "Could not open file: $!\n";

    Or use the low precedence or operator:

    open PLAY, $mit_shakes or die "Could not open file: $!\n";


    until ($line =~ m/<\/head>/) { if ($line =~ m/<title>(.*)<\/title>/) { $title_of_play = $1; } print "$line\n"; $line = <PLAY>; }

    That is usually written as:

    while ( my $line = <PLAY> ) { last if $line =~ m/<\/head>/; if ( $line =~ m/<title>(.*)<\/title>/ ) { $title_of_play = $1; } print "$line\n"; }


    my $i = 0; foreach (@ARGV) { if ($i == 0) { print "$_"; $i = 1; } else { print ", $_"; } } print ". </h2>\n";

    That is usually written as:

    print join ', ', @ARGV, "</h2>\n";


    while (<PLAY>) { $line = $_;

    That is usually written as:

    while ( my $line = <PLAY> ) {


    foreach (@ARGV) { my $character = $_;

    That is usually written as:

    foreach my $character ( @ARGV ) {
Re: Making Cue Scripts with Perl
by GrandFather (Saint) on Dec 17, 2012 at 22:14 UTC

    Don't initialise all your variables in a great bolus at the top of your code. You wipe out half the advantage of using strictures if you do so. Instead declare and initialise variables to have as small a scope as makes sense. Always initialise variables with their first value when they are declared unless the declaration must be outside a loop.

    my $i = 0; foreach (@ARGV) { if ($i == 0) { print "$_"; $i = 1; } else { print ", $_"; } }

    is much better written:

    print join ', ', @ARGV;

    New acts and scenes are better managed by:

    my $new_act; my $new_scene; while (<$playIn>) { my $line = $_; ... # Print the act heading if we haven't yet. if ($new_act) { print "$new_act\n"; $new_act = undef; } # Print the scene headin if we haven't yet. if ($new_scene) { print "$new_scene\n"; $new_scene = undef; } ... # Step 1.6: We should also print act headings. elsif ($line =~ m/.*<h3>ACT \w+.*/) { $new_act = $line; } # Step 1.7: We should also print scene headings. elsif ($line =~ m/.*<h3>SCENE \w+.*/) { $new_scene = $line; } }

    Don't use manifest constants ("true" and "false") for boolean values. They are prone to error and obscure the flow of the code by adding code. if ($new_scene) is easy to read an understand - anything more is harder to read, understand and get right.

    Use three parameter open and lexical file handles:

    open my $playIn, '<', $mit_shakes or die "Could not open '$mit_shakes' +: $!\n";

    Note that your open (open PLAY, $mit_shakes || die "Could not open file: $!\n";) is broken. Replace || with or for it to work as you expect.

    True laziness is hard work
Re: Making Cue Scripts with Perl
by girarde (Hermit) on Dec 20, 2012 at 23:07 UTC
    When posting at great length, <readmore> tags are appreciated.

    An interesting topic. It's not just Shakespeare that has had cue scripts; I've done a few shows that had them just to save on paper.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://1009211]
Approved by herveus
Front-paged by herveus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-03-19 02:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found