Rosetta Code/Run examples: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) (→{{header|Perl 6}}: Substantial upgrades to configurability and capability) |
Thundergnat (talk | contribs) (→{{header|Perl 6}}: More switches & updates, roughed in multi-language code, will now run Perl & Python as well as Perl6) |
||
Line 263: | Line 263: | ||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |
||
{{works with|Rakudo|2018.03}} |
{{works with|Rakudo|2018.03}} |
||
This is a fairly comprehensive task code runner. It is set up to work for Perl 6 |
This is a fairly comprehensive task code runner. It is set up to work for Perl 6 by default, but has basic configurations to run Perl and Python tasks as well. It can be easily tweaked to work with other languages by adding a load-lang('whatever'){} routine similar to the Perl6, Perl and Python ones. (And ensuring that the appropriate compiler is installed and accessible.) There is so much variation to the task requirements and calling conventions that it would be problematic to make a general purpose, language agnostic code runner so some configuration is necessary to make it work with other languages. |
||
By default, this will download the Perl 6 section of any (every) task that has a Perl 6 example, extract the code blocks and attempt to run them. Many tasks require files or user interaction to proceed, others are not complete runnable code blocks (example code fragments), some tasks run forever. To try to deal with and compensate for this, this implementation can load a %resource hash that will: supply input files where necessary, skip unrunnable code fragments, limit long and/or infinite running blocks, supply user interaction code where possible, and skip blocks where user interaction is unavoidable. |
By default, this will download the Perl 6 section of any (every) task that has a Perl 6 example, extract the code blocks and attempt to run them. Many tasks require files or user interaction to proceed, others are not complete runnable code blocks (example code fragments), some tasks run forever. To try to deal with and compensate for this, this implementation can load a %resource hash that will: supply input files where necessary, skip unrunnable code fragments, limit long and/or infinite running blocks, supply user interaction code where possible, and skip blocks where user interaction is unavoidable. |
||
Line 284: | Line 284: | ||
my %*SUB-MAIN-OPTS = :named-anywhere; |
my %*SUB-MAIN-OPTS = :named-anywhere; |
||
unit sub MAIN( |
|||
unit sub MAIN( Str $run = '', Bool :f(:$force), Bool :l(:$local), Bool :r(:$remote) ); |
|||
Str $run = '', # Task or file name |
|||
Str :$lang = 'perl6', # Language, default perl6 - should be same as in the <lang *> tags |
|||
Int :$skip = 0, # Skip # to continue partially into a list |
|||
Bool :f(:$force), # Override any task-skip parameter in %resource hash |
|||
Bool :l(:$local), # Only use task code from local cache |
|||
Bool :r(:$remote), # Only use code from remote server (refresh local cache) |
|||
Bool :q(:$quiet), # Less verbose, don't display source code |
|||
Bool :d(:$deps), # Load dependencies if necessary |
|||
Bool :p(:$pause), # pause after each task |
|||
⚫ | |||
die 'You can select local or remote, but not both...' if $local && $remote; |
die 'You can select local or remote, but not both...' if $local && $remote; |
||
Line 290: | Line 300: | ||
my $client = HTTP::UserAgent.new; |
my $client = HTTP::UserAgent.new; |
||
my $url = 'http://rosettacode.org/mw'; |
my $url = 'http://rosettacode.org/mw'; |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
my %c = ( # text colors |
my %c = ( # text colors |
||
Line 310: | Line 309: | ||
); |
); |
||
my $view = 'xdg-open'; # image viewer, this will open default under Linux |
my $view = 'xdg-open'; # image viewer, this will open default under Linux |
||
my % |
my %l = load-lang($lang); # load languge paramters |
||
my %resource = load-resources($lang); |
|||
my $get-tasks = True; |
my $get-tasks = True; |
||
Line 320: | Line 320: | ||
if $run { |
if $run { |
||
if $run.IO.e and $run.IO.f { |
if $run.IO.e and $run.IO.f {# is it a file? |
||
@tasks = $run.IO.lines; |
@tasks = $run.IO.lines; # yep, treat each line as a task name |
||
} else { # must be a single task name |
|||
⚫ | |||
@tasks = ($run); |
@tasks = ($run); # treat it so |
||
} |
} |
||
$get-tasks = False; |
$get-tasks = False; # don't need to retreive task names from web |
||
} |
} |
||
if $get-tasks { # load tasks from web if no cache is not found, older than one day or forced |
|||
if $get-tasks { |
|||
if |
if !"%l<language>.tasks".IO.e or ("%l<language>.tasks".IO.modified - now) > 86400 or $remote { |
||
@tasks = mediawiki-query( |
@tasks = mediawiki-query( # get tasks from web |
||
$url, 'pages', |
$url, 'pages', |
||
:generator<categorymembers>, |
:generator<categorymembers>, |
||
Line 340: | Line 340: | ||
"%l<exe>.tasks".IO.spurt: @tasks.sort.join("\n"); |
"%l<exe>.tasks".IO.spurt: @tasks.sort.join("\n"); |
||
} else { |
} else { |
||
@tasks = "%l<language>.tasks".IO.slurp; |
@tasks = "%l<language>.tasks".IO.slurp; # load tasks from file |
||
} |
} |
||
} |
} |
||
⚫ | |||
for @tasks -> $title { |
for @tasks -> $title { |
||
# If you want to resume partially into automatic |
|||
# downloads, adjust $skip to skip that many tasks |
|||
my $skip = 0; |
|||
next if $++ < $skip; |
next if $++ < $skip; |
||
next unless $title ~~ /\S/; # filter blank lines (from files) |
|||
⚫ | |||
say $skip + ++$, ") $title"; |
|||
say $skip + ++$, " $title"; |
|||
my $name = $title.subst(/<-[-0..9A..Za..z]>/, '_', :g); |
my $name = $title.subst(/<-[-0..9A..Za..z]>/, '_', :g); |
||
Line 359: | Line 357: | ||
my $entry; |
my $entry; |
||
if $remote or (($modified - now) > 86400 * 7) { |
if $remote or !"$taskdir/name.txt".IO.e or (($modified - now) > 86400 * 7) { |
||
my $page = $client.get("{ $url }/index.php?title={ uri-escape $title }&action=raw").content; |
my $page = $client.get("{ $url }/index.php?title={ uri-escape $title }&action=raw").content; |
||
uh-oh("Whoops, can't find page: $url/$title :check spelling.") and next if $page.elems == 0; |
|||
say "Getting code from: http://rosettacode.org/wiki/{ $title.subst(' ', '_', :g) }#%l<language>"; |
say "Getting code from: http://rosettacode.org/wiki/{ $title.subst(' ', '_', :g) }#%l<language>"; |
||
my $header = %l<header>; # can't interpolate hash into regex |
my $header = %l<header>; # can't interpolate hash into regex |
||
$entry = $page.comb(/'=={{header|' $header '}}==' .+? [<?before \n'=='<-[={]>*'{{header'> || $] /).Str // |
$entry = $page.comb(/'=={{header|' $header '}}==' .+? [<?before \n'=='<-[={]>*'{{header'> || $] /).Str // |
||
uh-oh("No code found\nMay be bad markup"); |
|||
my $lang = %l<language>; # can't interpolate hash into regex |
my $lang = %l<language>; # can't interpolate hash into regex |
||
Line 387: | Line 386: | ||
unless @blocks { |
unless @blocks { |
||
uh-oh("No code found\nMay be bad markup") unless %resource{"$name"}<skip> ~~ /'ok to skip'/; |
|||
say "Skipping $name: ", %resource{"$name"}<skip>, "\n" if %resource{"$name"}<skip> |
say "Skipping $name: ", %resource{"$name"}<skip>, "\n" if %resource{"$name"}<skip> |
||
} |
} |
||
Line 406: | Line 405: | ||
run-it($taskdir, "$name$n"); |
run-it($taskdir, "$name$n"); |
||
} |
} |
||
say '=' x 79; |
say %c<delim>, '=' x 79, %c<clr>; |
||
pause if $pause; |
|||
} |
} |
||
Line 428: | Line 428: | ||
copy "$current/rc/resources/{$fn}", "./{$fn}" |
copy "$current/rc/resources/{$fn}", "./{$fn}" |
||
} |
} |
||
dump-code ("$code%l<ext>"); |
dump-code ("$code%l<ext>") unless $quiet; |
||
check- |
check-dependencies("$code%l<ext>", $lang) if $deps; |
||
my @cmd = %resource{$code}<cmd> ?? |%resource{$code}<cmd> !! "%l<exe> $code%l<ext>\n"; |
my @cmd = %resource{$code}<cmd> ?? |%resource{$code}<cmd> !! "%l<exe> $code%l<ext>\n"; |
||
for @cmd -> $cmd { |
for @cmd -> $cmd { |
||
Line 437: | Line 437: | ||
chdir $current; |
chdir $current; |
||
say "\nDone $code"; |
say "\nDone $code"; |
||
} |
|||
sub pause { |
|||
prompt "Press enter to procede: >"; |
|||
# or |
|||
⚫ | |||
} |
} |
||
Line 449: | Line 455: | ||
sub clear { "\r" ~ ' ' x 100 ~ "\r" } |
sub clear { "\r" ~ ' ' x 100 ~ "\r" } |
||
sub |
sub uh-oh ($err) { put %c<warn>, "{'#' x 79}\n\n $err \n\n{'#' x 79}", %c<clr> } |
||
multi check-dependencies ($fn, 'perl6') { |
|||
sub uh-oh ($err) { put %c<warn>, "{'#' x 79}\n\n$err;\n\n{'#' x 79}", %c<clr> } |
|||
sub check-modules ($fn) { |
|||
my @use = $fn.IO.slurp.comb(/<?after $$ 'use '> \N+? <?before \h* ';'>/); |
my @use = $fn.IO.slurp.comb(/<?after $$ 'use '> \N+? <?before \h* ';'>/); |
||
if +@use { |
if +@use { |
||
Line 464: | Line 468: | ||
} |
} |
||
multi check-dependencies ($fn, $unknown) { |
|||
sub load-resources { () } # load resources for finer control |
|||
note "Sorry, don't know how to handle dependancies for $unknown language." |
|||
</lang> |
|||
}; |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
) } |
|||
multi load-lang ('perl') { ( |
|||
language => 'Perl', |
|||
exe => 'perl', |
|||
ext => '.pl', |
|||
dir => 'perl', |
|||
header => 'Perl', |
|||
tag => rx/<?after '<lang ' 'perl' '>' > .*? <?before '</' 'lang>'>/, |
|||
) } |
|||
multi load-lang ('python') { ( |
|||
language => 'Python', |
|||
exe => 'python', |
|||
ext => '.py', |
|||
dir => 'python', |
|||
header => 'Python', |
|||
tag => rx/<?after '<lang ' 'python' '>' > .*? <?before '</' 'lang>'>/, |
|||
) } |
|||
multi load-lang ($unknown) { die "Sorry, don't know how to handle $unknown language." }; |
|||
multi load-resources ($unknown) { () };</lang> |
|||
{{out}} with command line: '''perl6 RC-run.p6 "Determine if a string is numeric"''' |
{{out}} with command line: '''perl6 RC-run.p6 -q "Determine if a string is numeric"''' |
||
<pre>Retrieving tasks |
<pre>Retrieving tasks |
||
1 Determine if a string is numeric |
1 Determine if a string is numeric |
||
Line 501: | Line 539: | ||
===============================================================================</pre> |
===============================================================================</pre> |
||
Or, if the full %resource hash is loaded it will automatically feed input parameters to tasks that require them:<br> |
Or, if the full %resource hash is loaded it will automatically feed input parameters to tasks that require them:<br> |
||
'''perl6 RC-run.p6 Lucky_and_even_lucky_numbers''' |
'''perl6 RC-run.p6 Lucky_and_even_lucky_numbers''' -q |
||
<pre>Retrieving tasks |
<pre>Retrieving tasks |
||
1 Lucky_and_even_lucky_numbers |
1 Lucky_and_even_lucky_numbers |