App-Mowyw
view release on metacpan or search on metacpan
lib/App/Mowyw.pm view on Meta::CPAN
|synatxfile
|syntax
|endsyntax
|bind
|for
|endfor
|ifvar
|endifvar
)/x ],
[ 'TAG_END', qr/\s*\]\]\]/],
[ 'TAG_END', qr/\s*\%\]/],
[ 'BRACES_START', qr/\{\{/],
[ 'BRACES_END', qr/\}\}/],
);
sub parse_all_in_dir {
my @todo = @_;
while (defined(my $fn = pop @todo)){
$fn .= '/' unless ($fn =~ m#/$#);
opendir my $DIR, $fn or die "Cannot opend directory '$fn' for reading: $!";
IW: while (my $f = readdir $DIR){
# ignore symbolic links and non-Readable files:
next IW if (-l $f);
# if we consider . and .., we loop infinetly.
# and while we are at ignoring, we can ignore a few
# other things as well ;-)
if (
$f eq '..'
or $f eq '.'
or $f eq '.svn'
or $f eq '.git'
or $f =~ m{(?:~|\.swp)$}){
next;
}
$f = $fn . $f;
if (-d $f){
push @todo, $f;
process_dir($f);
} else {
process_file($f);
}
}
closedir $DIR;
}
}
sub process_dir {
my $fn = shift;
my $new_fn = get_online_fn($fn);
mkdir $new_fn;
}
# strip leading and trailing whitespaces from a string
sub strip_ws {
my $s = shift;
$s =~ s/^\s+//g;
$s =~ s/\s+$//g;
return $s;
}
sub escape {
my $str = shift;
my %esc = (
"\\" => '\\\\',
"\t" => '\t',
"\n" => '\n',
);
my $re = join '|', map quotemeta, keys %esc;
$str =~ s/($re)/$esc{$1}/g;
return $str;
}
sub parse_error {
my $message = shift;
my @filenames = @{shift()};
my $token = shift;
my $str = "Parse error in file '$filenames[0]': $message\n";
if ($token) {
$str .= "in line $token->[3] near'" . escape($token->[0]) ."'\n";
}
for (@filenames[0..$#filenames]) {
$str .= " ...included from file '$_'\n";
}
confess $str;
exit 1;
}
# parse sub: anything is treated as normal text that does not start or end a
# command
# the second (optional) arg contains a hash of additional tokens that are
# treated as plain text
sub p_text {
my $tokens = shift;
my %a;
%a = %{$_[0]} if ($_[0]);
my $str = "";
my %allowed_tokens = (
KEYWORD => 1,
UNMATCHED => 1,
);
while ( $tokens
and $tokens->[0]
and $tokens->[0]->[0]
and ($allowed_tokens{$tokens->[0]->[0]}
or $a{$tokens->[0]->[0]})){
$str .= $tokens->[0]->[1];
shift @$tokens;
}
return $str;
}
# parse sub: parse an include statement.
# note that TAG_START and the keyword "include" are already stripped
sub p_include {
my $tokens = shift;
my $meta = shift;
# normally we'd expect an UNMATCHED token, but the user might choose
# a keyword as well as file name
my $fn = strip_ws(slurp_upto_token($tokens, 'TAG_END', $meta));
$fn = get_include_filename('include', $fn, $meta->{FILES}->[-1]);
# print Dumper $tokens;
my $m = my_dclone($meta);
unshift @{$m->{FILES}}, $fn;
return parse_file($fn, $m);
}
# parse sub: parse a system statement.
sub p_system {
my $tokens = shift;
my $meta = shift;
my $fn = strip_ws(slurp_upto_token($tokens, 'TAG_END', $meta));
print STDERR "Executing external command '$fn'\n" unless $config{quiet};
my $tmp = `$fn`;
return ($tmp);
}
# parse sub: parse a 'menu' statement.
lib/App/Mowyw.pm view on Meta::CPAN
for (keys %$meta){
if ($_ eq 'VARS'){
my %vs = %{$meta->{VARS}};
for my $v (keys %vs){
if (blessed $vs{$v}){
$result{VARS}{$v} = $vs{$v};
} else {
$result{VARS}{$v} = ref $vs{$v} ? dclone($vs{$v}) : $vs{$v};
}
}
} else {
$result{$_} = ref $meta->{$_} ? dclone($meta->{$_}) : $meta->{$_};
}
}
return \%result;
}
sub p_braces {
my $tokens = shift;
my $meta = shift;
my $str = "";
p_expect($tokens,"BRACES_START", $meta);
if ($meta->{CURRENT_ITEM}){
# print "using text inside braces\n";
$str .= parse_tokens($tokens, $meta);
} else {
# discard the text between opening {{ and closing }} braces
# print "discarding text inside braces\n";
parse_tokens($tokens, $meta);
}
p_expect($tokens, "BRACES_END", $meta);
return $str;
}
sub p_setvar {
my $tokens = shift;
my $meta = shift;
my $str = "";
while ($tokens->[0]->[0] ne "TAG_END"){
$str .= $tokens->[0]->[1];
shift @$tokens;
}
p_expect($tokens, "TAG_END", $meta);
$str = strip_ws($str);
$str =~ m#^(\S+)\s#;
my $name = $1;
my $value = $str;
$value =~ s/^\S+\s+//;
$meta->{VARS}->{$name} = $value;
return "";
}
sub p_readvar {
my ($tokens, $meta) = @_;
my $str = strip_ws(slurp_upto_token($tokens, 'TAG_END', $meta));
my ($name, $rest) = split m/\s+/, $str, 2;
my %options = parse_hash($rest, 'readvar', $meta);
my $c = resolve_var($name, $meta);
if (defined $options{escape} && lc $options{escape} eq 'html'){
return encode_entities($c);
}
return $c if defined $c;
return '';
}
sub p_syntaxfile {
my $tokens = shift;
my $meta = shift;
my $tag_content = shift @$tokens;
$tag_content = strip_ws($tag_content->[1]);
p_expect($tokens, "TAG_END", $meta);
my @t = split m/\s+/, $tag_content;
if (scalar @t != 2){
parse_error(
"Usage of syntaxfile tag: [[[syntaxfile <filename> <language>",
$meta->{FILES},
$tokens->[0],
);
}
}
sub p_syntax {
my $tokens = shift;
my $meta = shift;
my $lang = shift @$tokens;
$lang = strip_ws($lang->[1]);
p_expect($tokens, "TAG_END", $meta);
my $str = "";
while ($tokens->[0] and not ($tokens->[0]->[0] eq "TAG_START" and $tokens->[1]->[1] eq "endsyntax" and $tokens->[2]->[0] eq "TAG_END")){
$str .= $tokens->[0]->[1];
shift @$tokens;
}
p_expect($tokens, "TAG_START", $meta);
p_expect($tokens, "KEYWORD", $meta);
p_expect($tokens, "TAG_END", $meta);
return do_hilight($str, $lang, $meta);
}
sub do_hilight {
my ($str, $lang, $meta) = @_;
if ($lang eq 'escape'){
return encode_entities($str);
}
eval {
no warnings "all";
require Text::VimColor;
};
if ($@){
# require was not successfull
print STDERR " Not syntax hilighting, Text::VimColor not found\n" unless $config{quiet};
# encode at least some special chars "by hand"
return encode_entities($str);
} else {
print STDERR "." unless $config{quiet};
# any encoding will do if vim automatically detects it
my $vim_encoding = 'utf-8';
my $BOM = "\x{feff}";
my $syn = Text::VimColor->new(
filetype => $lang,
string => encode($vim_encoding, $BOM . $str),
);
$str = decode($vim_encoding, $syn->html);
$str =~ s/^$BOM//;
return $str;
}
}
# parse sub: expect a specific token, return its content or die if the
# expectation was not met.
sub p_expect {
my ($tokens, $expect, $meta) = splice @_, 0, 3;
parse_error("Unexpected End of File, expected $expect", $meta->{FILES}) unless (@$tokens);
confess("\$tokens not a array ref - this is most likely a programming error\n$internal_error_message") unless(ref($tokens) eq "ARRAY");
if ($tokens->[0]->[0] eq $expect){
my $e_val = shift;
if (not defined($e_val) or $e_val eq $tokens->[0]->[1]){
my $val = $tokens->[0]->[1];
shift @$tokens;
return $val;
} else {
parse_error("Expected '$e_val', got $tokens->[0][1]\n",
$meta->{FILES}, $tokens->[0]);
}
}
parse_error(
"Expected token $expect, got $tokens->[0]->[0]\n",
$meta->{FILES},
$tokens->[0],
);
}
sub lex_string {
my $text = shift;
my @tokens = lex($text, \@input_tokens);
# print Data::Dumper->Dump(\@tokens);
return @tokens;
}
sub parse_tokens {
my $tokens = shift;
( run in 0.656 second using v1.01-cache-2.11-cpan-5a3173703d6 )