4 no warnings
qw(uninitialized redefine);
10 sub dige { slm(12, Digest::SHA::sha256_hex( encode_utf8(shift) ) ) };
13 !-d $_ && `mkdir -p $_` for qw'wormhole/digway G W';
16 use Mojolicious::Lite;
18 push @{app->static->paths}, '/home/s/styleshed/public';
19 app->secrets(["nothing"]);
20 # divert mojo log statements from our err channel
21 #app->log->path(($G->{c}->{ipd} || $G->{c}->{dir})."/mojo\.log")
22 # if $G->{c}->{dir} || $G->{c}->{ipd};
24 our $listen = "http://localhost:1422";
26 $_ = `cat listen`; chomp $_;
27 $listen = 'http://'.$_;
30 1 && saybl "Starting listens: $listen";
31 app->start('daemon', '--listen' => "$listen");
35 no warnings qw(uninitialized redefine);
36 my $poing = qr/\w+(?:\.\w+)?/;
38 my $nls = qr/[ \t]*(?! *\/\
/)/;
39 # < enj() should do this
40 my $jstring = sub { my ($s) = @_;
50 $C->{c
}->{s
} =~ s/^(\w+)(?: (-?\w+))?:(?: (%$nlp))?$/n $1 $2 \$s:$twolt'' $3/smg;
51 # blockquote til /^\s*$/g
52 # multi line, always \n$
53 # supposed to not babz anything in it...
54 # < stylehouse (the editor) must know this too
55 # or it'll expand tabs to 4 spaces
56 $C->{c
}->{s
} =~ s
{^(\s
*)($nlp)<<(''|"")($nlp?
)\n((?
:\
1$nlp\n)+)[ \t]*\n}{
57 # < allow empty lines with first line's indent
58 # would be easy if we were iterating lines
59 my $babin = $3 eq '""';
62 my $line = $ind.$fore."BlockQuote$4\n";
64 my ($reind) = $was =~ /^(\s+)/;
65 $was =~ s/^$reind//sgm;
67 my $C = {c
=>{s
=>$was}};
71 my $lines = [split /\n/, $was];
72 $lines->[-1] eq '' && pop @
$lines;
74 #die "not nl last: aft $line: $lines->[-1] ".wdump 3,[$was,$lines];
75 $lines = join "+\n", map {
76 $ind.$jstring->("$_\n")
78 $lines = $ind."var BlockQuote =\n$lines;";
79 my $dig = dig
($lines);
80 $hide->{$dig} = $lines;
84 #$o = $G->{h}->($A,$C,$G,$T,"readLines",<<'');
86 # # comment to // comment
87 $C->{c
}->{s
} =~ s/^(\s*)#/$1\/\
//gsm;
88 $C->{c
}->{s
} =~ s/( \{|}|;) #/$1 \/\
//gsm;
89 # =pod (.+) =cut comment
90 $C->{c
}->{s
} =~ s
/^(\s*)=\w+(.+?)^\s*=\w+\s*$/
91 join "\n",map{"$1\/\/ $_"} split"\n",$2;
94 # capital A is the more empiricle
95 $C->{c
}->{s
} =~ s/\bA&(\w+)\b/A\.c\.$1/g;
96 $C->{c
}->{s
} =~ s/\ba&(\w+)\b/A\.sc\.$1/g;
97 # and for $G->{h}->($A,$C,$G,$T,"somea","goof") -> $A->{some}->{sc}->{goof}
98 $C->{c
}->{s
} =~ s/\b(\w+)A&(\w+)\b/A\.$1\.c\.$2/g;
99 $C->{c
}->{s
} =~ s/\b(\w+)a&(\w+)\b/A\.$1\.sc\.$2/g;
101 # @Thing -> $A->{1}->{sc}->{Thing}
103 $C->{c
}->{s
} =~ s/(?<!\w)\@(\w+)\b/1s\&$1/g;
105 # '$A->{4}->("tv") jo eig notch'
106 # -> '$A->{4}->{y}->{tv} && $A->{4}->{y}->{tv}->{jo} && $A->{4}->{y}->{tv}->{jo}[0.1]' etc
107 # io but much simpler, single
108 # < could N many/gref with a sub
109 # < jsbab since so floody
110 # < going into $G->{h}->($A,$C,$G,$T,"things","uni/va/ve/la") etc
111 $C->{c
}->{s
} =~ s
{\b($poing)&tv
(( \
$?\w
+\b)+)}{
113 my @path = split ' ', $2;
114 my @expr = ("'$thing"."&tv @path'", $thing);
116 my $cv = s/(\d+)$// ?
$1 : 1;
117 $cv *= 0.1 while $cv >= 1;
118 my $t = s/^\$// ?
'['.$_.']' : '.'.$_;
119 push @expr, $thing.'.y', ($thing = $thing.'.y'.'.tv');
120 push @expr, "$thing$t", ($thing = "$thing$t"."[$cv]");
127 # $A->{3}->{sc}->{do} -> $A->{3}->{sc}->{do}
128 $C->{c
}->{s
} =~ s/\b(\d)(s|c)&(\w+)\b/"A[$1].".($2 eq 's' ? 'sc' : 'c').".$3"/smeg;
129 # make $G->{h}->($A,$C,$G,$T,"upA","thing") -> $A->{up}->{c}->{thing}
130 $C->{c
}->{s
} =~ s/\b(\w+)(a|A)&(\w+)\b/"A.$1.".($2 eq 'a' ? 'sc' : 'c').".$3"/smeg;
132 $C->{c
}->{s
} =~ s/\b([a-z]+)\.(\d)\b/$1.'['.$2.']'/gie;
134 # $v->{sc}->{do} -> $v->{sc}->{do}, etc
135 # < doing the above three paragraphs in this one:
136 # < $A->{up}->{c}->{s}->{sc}->{pi}...
137 $C->{c
}->{s
} =~ s
[\b(\w
+)(s
|c
|y
)&(\w
+)\b][
138 my $arm = ($2 eq 's' ?
'sc' : $2).".$3";
142 if ($on =~ /^(up)+(C)?$/) { # $A->{up}->{sc}->{do} -> $A->{up}->{sc}->{do}
143 # the other A aliases use $G->{h}->($A,$C,$G,$T,"upa","do")
144 $s .= '.up' while $on =~ s/^up//;
145 $s .= ".c\.s" if $on =~ s/^C//;
148 elsif ($on =~ /^\w\w+$/) { # $G->{h}->($A,$C,$G,$T,"oms","do") -> $om->{sc}->{do}
152 else { # $z->{sc}->{do} -> $z->{sc}->{do}
158 # capital C is the more universal (prefer $C->{sc}->{do})
159 $C->{c
}->{s
} =~ s/\bs&(\w+)\b/C\.sc\.$1/g;
160 $C->{c
}->{s
} =~ s/\bC&(\w+)\b/C\.sc\.$1/g;
161 $C->{c
}->{s
} =~ s/\bc&(\w+)\b/C\.c\.$1/g;
164 # recursive regex, but:
165 # imbalanced brackets cause an infinite loop
166 # < something off the net
167 # perldoc perlre "(??{ code })" onwards?
169 $brackin = qr/\{[^\}\{]*$brackin?[^\}\{]*\}/;
170 my $varguessbab = sub { my ($t,$s,$varcod,$nocall) = @_;
172 # talk is all the i is without the i
174 my $h = {path
=>[],vars
=>[],arks
=>[]};
175 my $defunc;$defunc = sub {
177 if ($s =~ s/^((\w+:)*)\{/\{/s) {
178 my $arkfor = $1; # not in $whole, can forget
179 $h->{bail
} = "not even" unless $s =~ /^$brackin/;
180 $s =~ s/^($brackin)(:(\S+)|) ?//;
186 $code =~ s/^\{|\}$//g;
187 if ($code =~ /^(\w+)(?::(.+))?$/) {
188 my $prerolled_function = $1;
189 # which will peel/parse
191 # < turn "la $inter " into "la ".$inter." "
193 push @
{$h->{vars
}}, '"'.$subtalk.'"';
194 my $now = "{$prerolled_function}";
195 $talk =~ s/\Q$whole\E/$now/;
199 $code = [split ";", $code];
200 # return last expression
201 if ($code->[-1] !~ /return/) {
202 my $expr = pop @
$code;
204 push @
$code, " return $expr"
206 $code = join ";", @
$code;
207 $code = "&acgts"."{ $code }";
208 push @
{$h->{vars
}}, $code;
209 # its var is a function, its talk is anything else about it
213 push @
{$h->{arks
}}, $name;
215 $talk =~ s/\Q$whole$withname\E/$now/s
216 || push @
$cod, "no replacing: $whole";
217 #push @$cod, "Would $name: $code\n"
218 # ." onward: ".slim(20,$s)."\n";
224 my $after_first_pathy_thing;
225 # since that redefines columns
226 # assume @things, #things, $things, anything:things are for var/ar unpack
228 my $firstpath = $h->{path
};
229 while ($s =~ s/^(\S+)\s*//) {
231 $firstpath = [@
{$h->{path
}}] if $island =~ /^[io]$/;
232 my $path = [split '/', $island];
235 # waving (and so we dont see :y)
236 # and this avoids latic:yon/... in paths...
237 $pa->{arkfor
} = $1 if @
$path == 1 && s/^((\w+:)+)(\*)?y(\w|$)/${3}y$4/;
239 $pa->{ark
} = $1 || 1 if s/:(\w*)$//;
241 if (s/\{(\S+)\}?$//) {
243 while ($pa->{gref
} =~ /\$(\w[\w\[\]\.]*)/g) {
244 push @
{$pa->{grefpara
} ||= []},$1;
245 push @
{$h->{vars
}}, $1;
247 s/^/*/ if /^$/; # implies globbing
251 $pa->{isdelete
} = 1 if s/^-|-$//;
252 $pa->{issark
} = 1 if s/^@//;
253 $pa->{isvar
} = 1 if s/^#//;
254 $pa->{isvar
} = 2 if s/^\$//;
255 $pa->{issark
} && $pa->{isvar
} < 2 && delete $pa->{isvar
};
258 # the notion of C always split/linking domain names etc
259 if ($pa->{t
} =~ /^\w+[\[\.]\w/) {
260 # A[1].$sc->{cee} named $cee
261 # < could be pointing to anything
262 # into datatype (date/time/style?) aspects
263 # to/through/with functions
264 # at such rhythms, intro such dimension
265 $varnamung = $pa->{t
};
266 my $name = $1 if $pa->{t
} =~ /^\w[\w\[\]\.]+?(\w+)$/;
267 !$name && die "Cant de-qualify name: $pa->{t} in $talk";
268 #1 && saybl "AHvo: $name ". substr($name,0,1) . " OPR " . substr($name,1,0);
269 $name = "\$$name" unless
270 substr($name,0,1) eq "\$";
271 $talk =~ s/\$?\Q$varnamung\E/$name/sg
272 || die "Cant find $pa->{t} in $talk";
276 $pa->{isvar
} && push @
{$h->{vars
}}, $varnamung || $pa->{t
};
277 $pa->{glob} = 1 if $pa->{t
} =~ /^\*/;
278 $pa->{word
} = 1 unless $pa->{isvar
} || $pa->{issark
} || $pa->{glob};
281 # not barewords or spacers :unless
282 # but anything @plumbed
283 $pa->{ark
} = $pa->{t
} if $pa->{ark
} eq '1';
284 !$after_first_pathy_thing
285 && ($pa->{ark
} || $pa->{issark
}) &&
286 push @
{$h->{arks
}}, $pa->{ark
} || $pa->{t
};
287 push @
{$h->{path
}}, $pa;
289 $after_first_pathy_thing = 1 if @
$path > 1;
293 return "Bailed: $h->{bail}" if $h->{bail
};
294 while (my ($t,$iv) = each %{$h }) { ref $iv eq 'HASH' || next;
295 while (my ($i,$n) = each %{$iv }) {
296 $n =~ /\W+/ && die "wobbyly $t varnameinterpretation: $n", $s;
298 @
{$h->{arks
}} = uniq @
{$h->{arks
}};
299 if (!@
{$h->{arks
}}) { # see $io->{realise}
300 # accept $pa->{t} as a possible name
301 for my $pa (@
{$h->{path
}}) {
303 next if $pa->{t
} =~ /\W/;
304 push @
{$h->{arks
}}, $pa->{t
}
307 @
{$h->{arks
}} = 's' if !@
{$h->{arks
}};
309 my $la = $firstpath->[-1];
310 # the test: i $d/@la/@dio la:{} ... puts s as the {}
311 #my $vork = '$d/@la/@dio';
312 #$talk =~ m{\Q$vork\E}
313 # && saybl "Found it: ".wdump 5,[$h,$la];
314 # maybe we should call it r if .../made:s {}
315 # probably about right.. unplumbed {}$ could mean grep that stuff?
316 # except for row generation, which is how anyway?
317 # < knowing better, realise() won't spit out doofs as s
318 if (($la->{glob} || $la->{word
}) && !$la->{ark
} && !$la->{issark
} && !grep {$_ eq 's'} @
{$h->{arks
}}) {
319 @
{$h->{arks
}} = grep { $_ ne $la->{t
} } @
{$h->{arks
}}; # remove word as nonark
320 push @
{$h->{arks
}}, 's';
323 # S does var setting, or each io can set ay
324 # but not each $ay->{sc}.$arks
327 push @
$cod, "var $sets = " unless $nocall;
328 $nocall->{sets
} = $sets if $nocall;
331 $talk = "$t $talk" if $nocall;
333 (my $vus = sjson
([$talk])) =~ s/^\[|\]$//g;
335 my $call = $nocall ?
"" : "io\.$t(";
336 push @
$cod, "$call$vus,[";
338 push @
$cod, join ',', @
{$h->{vars
}} if @
{$h->{vars
}};
340 push @
$cod, ']'.($nocall ?
"" : ");");
341 # undef (becomes $cod) if $ar->{testing_io_vars}
342 # else for hoisting up to the inside of the S {
344 # if not hoisting and returning an s column, set first one as ya
345 $ya = " var ya = ay\.sc\.s && ay\.sc\.s[0];"
346 if !$nocall && grep {$_ eq 's'} @
{$h->{arks
}};
348 push @
$varcod, ' var '.$_.' = '.$sets.'.sc.'.$_.';' for uniq @
{$h->{arks
}};
349 $cod = join '', @
$cod, $ya;
350 $ar->{ta
} and push @
{$ar->{ta
}}, [$talk,$cod];
353 return $varguessbab if $ar->{ta
};
354 $C->{c
}->{s
} =~ s
{(^\s
*|return )(i
|o
) ([\w\@\
{\
$\#
]+[^\n]*[^\n;]+)$}{
355 # unless testing, i/o doesn't set variables, only as S i/o
356 my $varcod = $ar->{testing_io_vars
} ?
undef : [];
357 "$1".$varguessbab->($2,$3,$varcod) }smeg
;
361 # each etc $data { into:
362 # while (my ($e,$tv) = each %$data) {
363 # while (my ($t,$c) = each %$tv) {
364 # so the value tv is for t-ing into
365 # DIY closing brackets
366 # avoids eaching nonref after first
367 # could replace with $G->{h}->($A,$C,$G,$T,"chew-ish") call if more spec
368 # and know indents to close
370 my ($ind,$in,$from) = @_;
371 my @in = split ',', $in;
372 @in = split '', $in[0] if @in == 1;
377 unshift @in, $v if @in;
380 my $s = "for (var $k in $from) {";
381 $s .= "\n var $v = $from\[$k];";
382 $s .= "\n if(typeof $v != 'object') { continue }"
388 @open = map { $ind.$_ } @open;
391 $C->{c
}->{s
} =~ s
/^(\s*)each (\w+(,\w+)*) (\S+) \{(\s*)$/
398 # (~hifnotc)?~com message: list, of, interestings
399 # < colouring or otherwise classifying by the source of the way
400 # eg everything from 4* looks kind of blue, etc
401 # more colour will jump in on top as aspects unfold, yadda
403 my $lnlp = qr/[^\n;]+/;
404 $C->{c
}->{s
} =~ s
{(; |^|\
{|and |return |= ) *~(?
:(\w
+)~)?
(\
$?
>?
[\w
]+(?
:$lnlp?
:)?
)(?
: ($lnlp)?
)?
(;|$)}{
410 $s = "'$s'" unless $s =~ s/^\$//;
411 $ope."G\&$c:$s,[$e];"
414 # chuck error: throw "Something", C
415 # throws new Error("Something"), its .tc=[C]
416 # also handles concatenated bits for "Something":
417 my $varbits = qr/[\w\[\]\.]+/;
418 my $concatbit = qr/\+(?:[\w\[\]\.]+|"[^\n"]+")/;
419 $C->{c
}->{s
} =~ s
{(^\s
*(?
!#)$nlp?)throw ("[^\n"]+?"$concatbit*)(, ?$nlp)?;?\s*$}{
424 my $guts = "new Error($msg)";
425 if ($tc =~ s/^, ?//) {
427 $guts = "{var er = $guts; er\.tc = [$tc]; throw er}";
431 $guts = "throw $guts;";
436 # rechuck error: throw e, "inn"
437 # pushes $e->{catches} $e->{stack} to $e->{stacks}[],
438 # chrome < 2012 restacks when rethrowing
440 $C->{c
}->{s
} =~ s
{(^\s
*(?
!#)$nlp?)throw ($varbits)(, ?$nlp)?;?\s*$}{
444 my $guts = "($var\.catches = $var\.catches || [])";
445 $tc = $tc =~ s/^, ?// ?
",tc:[$tc]" : "";
446 $guts .= ".push({stack:$var\.stack$tc}); throw $var;"; # "
450 #c n groundula, keywords, subs
452 # n thing -jod_33 s:var hue:'490deg'
453 # c/sc get wrapped with {}
455 # n thing -jod_33 s:string %hue:490deg,note:$note+btw
456 # and c/sc become $G->{h}->($A,$C,$G,$T,"peel") bits, $note+ becomes "+note+"
457 # and c $s:object,$up:ob will make json (wrapped with {})
458 # greediness of c/sc regarding % needs tuning
459 # be nice to have spaces in c, editor could easily step over all this
460 # < C like this, but fits after { or =
461 # < n:r yabbada to $r = $G->{h}->($A,$C,$G,$T,"n",['yabbada','W'])
462 # viz. this Babz decides when [t] means cW:t
463 # and sets a variable to the C created
464 # also u:thing so that $thing becomes that object in the mind
466 my $blankycsc = '"",{},{}';
467 $C->{c
}->{s
} =~ s
{(^\s
*|return )(n
|u
|m
|e
) (\
$)?
("[^\n"]+"|\w+\S*)(?: (\$)?([-\w]*))?(?: ([^\n]*?))?(?: (%)?([^\n]*?))?$}{
477 $t = '"'.$t.'"' if !$tvar;
478 $y = '"'.$y.'"' if !$yvar;
482 !$_ and s/^/{}/ && next;
483 if ($_ eq $c && /^\$\w+:\w+/) {
484 s/\$(\w+):(\w+)( )?/"$1:$2".(defined $3 ? ",":"")/seg;
489 s/\$([^\s\+]+)(\+|$)/"+$1+"/sg;
491 s/^(.*)$/"G\&"."peel,".$1." ";/smeg
498 my $guts = "G
&".$mode.":";
499 $guts .= "M
," if $mode eq 'm';
500 my $arg = "[$t,$y,$c";
501 $arg .= ",$sc" if $sc;
504 $arg =~ s/,\Q$blankycsc\E]$/]/ && $tvar;
510 $C->{c}->{s} =~ s/^(\s*)elsif ?\(/${1}else if (/sgm;
513 # < match until closing bracket, see $brackin
514 $C->{c}->{s} =~ s/(\w\S*) \|\|\=(?: ($nlp)(;)?|\s*)$/$1 = $1 || $2$3/gm;
517 $C->{c}->{s} =~ s/^($nls)([^\n]+?) and ($nlp)(;)?$/$1if ($2) {
521 # sub { my ($raw,$args) = @_; -> function(raw,args){
522 # sub { my ($A,$C,$G,$T,$sec,$lamp,$socket) = @_; -> function(A,C,G,T,s,e,c,lamp,socket){
523 # < (arfgunc) a way to write its args on it without having to read via toString parse
524 $C->{c}->{s} =~ s/(\W|^)&(acgt)?(\w+)?((?:,\w+)+?)?(,)?\{/;
526 my ($not,$acgt,$wordy,$commad,$wholimp) = ($1,$2,$3,$4,$5);
527 if (!$acgt && $wordy && ($commad || $wholimp)) {
528 # all,of,it is whole names, add comma to end if one \w+: &isparam,{
529 @args = split ',', $wordy.$commad
532 # acgt on the front or no commas
533 # means single letters until after commas
535 split('', ($acgt && 'ACGT').$wordy),
539 "${not}function
(".join(',',map{$_}grep{$_}@args)."){"
542 # $thing -> var thing
543 # doesn't see '$get # vardescript', see # -> //
544 $C->{c}->{s} =~ s/^($nls)\$(\w+)(;|\s*=|\s*\/\/|$)/
545 $1."var
$2".($3||';')/smeg;
547 # GONER thing$ -> var thing (would perl alright tho...)
549 $C->{c}->{s} =~ s/^($nls)(\w+)\$(?:;)?\s*(=|$)/
550 $1."var
$2".($3 eq '=' ? ' =' : ';')/smeg;
555 my $wsnotnl = qr/[ \t]/;
556 my $anS = qr/^$wsnotnl*S($wsnotnl*| \w[^\n]*)$/m;
557 my $GandS = "G
"."&"."S
";
558 if ($C->{c}->{s} =~ $anS) {
559 my @l = split /\n/, $C->{c}->{s};
564 $args =~ s/^\s+|\s+$//g;
565 # $G->{h}->($A,$C,$G,$T,"S
",s/num,t/nam,talk/json(d),params)
566 my $num = $1 if $args =~ s/^(\d+(?:\.\d+)?)\s*//;
567 my $nam; # maybe 'S 3 (title): i/o ....
568 # so then: } var sets; while(sets = $G->{h}->($A,$C,$G,$T,"S
",3,'title','i/o ...',[params]) { var one = $sets->{sc}->{one}); ...
569 my $sets; # name of $G->{h}->($A,$C,$G,$T,"S
") return ^
570 my $talkpara; # 'i/o ...',[params]
571 my $setting = []; # the (var one = $sets->{sc}->{one};)+
572 # talk,params pass through S, which iterates and sets vars inside
573 $args =~ s{^(?:(.*?):? )?(i|o) ([\w\@\{\$\#]+[^\n]*[^\n;]+)$}{
576 $talkpara = $varguessbab->($2,$3,$setting,$nocall);
577 $sets = $nocall->{sets};
581 # io-light, assume one eg $N may be returned from the call
582 # < projected to expand... unless io is the place that also sees
583 # up the A train to where N and M etc live.
584 # coming from or going to Osc
586 # title contains '$N' to while (N = ...)
588 if ($args =~ s/\$([^\s\+]+)(\+|$)/$1/sg) {
589 $1 && $sets && die "have dollarey
$1 in args
, also io
return sets
$sets";
593 $nam && $args && die "io set nam
='$nam', also args
: $args";
594 $nam = $args if $args;
595 $nam = $jstring->($nam) if $nam;
596 $num ||= "''" unless $num eq '0';
598 $args = join',',grep{length}$num,$nam,$talkpara;
600 my $call = join':',grep{length}$GandS,$args;
601 # conjoins while blocks
602 my $con = $firstS ? "" : "} ";
605 $con .= "var
$sets; ";
606 $call = "$sets = $call";
608 $con .= "while (".$call.") {";
611 #$setting = join ';', @$setting;
612 #$setting =~ s/;;/;/sg;
613 $con .= join '',@$setting;
622 $C->{c}->{s} = join "\n",@l;
624 # $G->{h}->($A,$C,$G,$T,"thing
",args,"with space
"); $e v
625 $C->{c}->{s} =~ s/($poing)\&(\$)?($poing)(?::([^\n;]+))(|\) ?\{ var.+$|\s*$|\s*$|;)/
626 my ($on,$var,$p,$e,$t) = ($1,$2,$3,$4,$5);
627 $t = "$1$t" if $e =~ s{(\) ?\{(?: var.+|))$}{};
628 $e = ",$e" if length $e;
629 ($on,my$in) = ("G\
.h
",'A,C,G,T,')
631 $p = "\"$p\"" unless $var;
632 my $s = $on."($in$p$e)$t";
633 $s = '$'.$s if $on !~ m{\.};
637 # $G->{h}->($A,$C,$G,$T,"thing
",args) && without space
638 $C->{c}->{s} =~ s/(G|$poing$poing)\&(\$)?($poing)(,[^\s;]+)?(;)?/
639 my $t = $2 ? "$3" : "'$3'";
640 my $h = $1 eq 'G' ? ".h
(A
,C
,G
,T
,$t" : "\
[$t\
](A
,C
,G
,T
";
643 # $G->{h}->($A,$C,$G,$T,"g
","be
",'jit') requires args...
644 $C->{c}->{s} =~ s/($poing)\&(\$)?($poing)(,[^\s;]+)(;)?/
645 my $t = $2 ? "$3" : "'$3'";
646 my $h = $1 eq 'G' ? ".h
(A
,C
,G
,T
,$t" : "\
[$t\
](A
,C
,G
,T
";
651 # delete returns the deleted
653 # delete $c->{per} -> $se = $c->{per}; delete $c->{per}
654 $C->{c}->{s} =~ s/ = delete ($poing[^\s;)]*)([\s;\)]*)/ = $1; delete $1$2/gsm;
657 # unhide blockquotation
658 %$hide && $C->{c}->{s} =~ s/HIDING:([0-9a-f]+)/$hide->{$1} || die "Cant find $1"/seg;
661 get '/' => sub { my ($c) = @_;
662 $c->reply->static("two\
.html
");
665 #c /peek/ - pull it into stylehouse
666 any '/peek/*t' => sub { my ($c) = @_;
667 my $resp = sub { my ($s) = @_; $c->render(text=>sjson($s)) };
669 my $t = $c->param('t');
670 # for a size or range:
671 my $line = $c->param('line') || 0;
672 # for directory, text,
675 $type = 'd' if $t =~ /\*/;
677 my ($f) = my @l = glob $t;
678 saybl "glob $t -> ".Dump(\@l);
681 # supplying ?-ambiguated $t matching many
682 $type = 'd' if @l > 1 || -d $f;
683 my $re = {type=>$type};
684 return $resp->({sc=>{%$re,lines=>[@l],
685 dige=>dige(join "\n",@l)}}) if $type eq 'd';
687 return $resp->({er=>'not found'}) if !-f $f;
689 my $size = $re->{sizekb} = 0.001 * (-s $f);
690 return $resp->({er=>'too big: '.$size.'kb'}) if $size > 420;
691 # < image or video...
692 return $resp->({er=>'not text'}) unless -T $f;
693 my $string = decode_utf8(read_file($f));
694 @l = split "\n", $string;
695 $re->{length} = 0+@l;
697 # how to chop that up
698 if ($line =~ s/<(\d+)$//) {
699 # only shallow indents, dige between
701 # always has a leading something
704 if (!/\S+/ || /^ {$indentlt}/) {
705 push @{$between[-1] ||= []}, $_;
713 1 && sayre "indgrep
$indentlt ".@l." < ".$re->{length};
714 @between = map { !@$_ ? '' : @$_."x
".dige(join("\n",@$_)) } @between;
715 $re->{dige} = dige(join "\n",
716 $between[0], map{ $l[$_], $between[$_+1]||'' } 0..@l-1
718 $re->{between} = \@between;
722 my $toline = $2 if $line =~ s/^(\d+)-(\d+)$/$1/;
723 $toline ||= $line + 100;
725 $toline = @l-1 if $toline > @l-1;
726 @l = @l[$line..$toline];
727 $re->{toline} = $line + @l;
728 $re->{dige} = dige(join "\n",@l);
731 return $resp->({sc=>{%$re,lines=>[@l]}})
734 #c /digwaypoll/ notifier, see 281 Sevo
736 my $poll = {tx=>[],ways=>{}};
737 $poll->{wayt} = {}; # pi/name -> pi-name
738 $poll->{wayd} = {}; # pi-name -> $C->{sc}->{dige}
739 get '/digwtf' => sub { my ($c) = @_;
740 $c->render(text => wdump($poll->{wayd}));
742 $poll->{doing} = sub { my ($o) = @_;
743 return if $o && $poll->{one} && $o ne $poll->{one};
745 while (my ($p,$i) = each %{$poll->{ways} }) {
747 $t = $poll->{wayt}->{"$p"} ||= do { $t =~ s/\W/-/sg; $t };
748 my $digway = "wormhole
/digway/$t";
749 my $dig = readlink $digway;
750 #1 && sayre "no $digway" if !$dig;
752 my $was = $poll->{wayd}->{"$t"};
753 next if $was && $dig eq $was;
754 $poll->{wayd}->{"$t"} = $dig;
759 # send many d=0 Lines as one message,
760 # so receiver can react immediately
761 for my $tx (@{$poll->{tx}}) {
762 my $s = join"", map{ $_ ."\n" }
763 map{ $_.'%dige:'.$tw->{$_} }
764 grep { !$tx->{ways}->{$_}
765 || $tx->{ways}->{$_} ne $tw->{$_}
768 1 && saygr "digwaypoll
: $s"
772 Mojo::IOLoop->timer(33,sub { $poll->{doing}($poll->{one} = rand()) });
774 websocket '/digwaypoll' => sub { my ($s) = @_;
777 1 && sayyl "Got digwaypolling
";
779 # complete picture (t/dige) at new listeners
781 push @{$poll->{tx}}, $tx;
783 my $addr = $tx->remote_address;
784 Mojo::IOLoop->stream($tx->connection)->timeout(300000);
785 $tx->max_websocket_size(512000);
787 $s->on(message => sub { my ($M,$m) = @_; #}
788 die "Not wordy
: $m" unless $m =~ /^([\w\-\/]+)(%\w+.*)?$/;
789 $tx->{ways}->{"$1"} ++ || $poll->{ways}->{"$1"} ++
792 $s->on(finish => sub { my ($M,$code,$reason) = @_;
793 @{$poll->{tx}} = grep { $_ ne $tx } @{$poll->{tx}};
794 while (my ($t,$i) = each %{$tx->{ways} }) {
795 -- $poll->{ways}->{"$t"} && next;
796 delete $poll->{ways}->{"$t"};
797 $t = delete $poll->{wayt}->{"$t"};
798 $t and delete $poll->{wayd}->{"$t"};
801 1 && sayre "digwaypoll Gone
: $addr $code $reason";
807 my $error = sub { my ($c,$s) = @_;
808 $c->render(text => sjson({er=>$s}), status => 400);
810 my $char_safety = sub { my ($c,$t) = @_;
811 return $error->($c,"illegal char
: '$1' in '$t'")
812 if $t =~ /([^\w\/-]+)/g;
815 # comes in /js/$t.$$version->{js}, code separated from W
816 any '/js/*W' => sub { my ($c) = @_;
817 my $t = $c->param('W');
818 my $version = $1 if $t =~ s/\.(\w+)\.js$//;
819 return $error->($c,"Know version
") unless $version;
820 return if $char_safety->($c,$t);
822 # must match the .1 dige
823 # < using the smaller .5, .2 to know that
825 my $cache = $G->{Wache} ||= {};
826 if ($cache->{$f} ne $version) {
827 return $error->($c,"No
1: $f") unless -f $f;
828 my $is = $cache->{$f} = dige(decode_utf8(read_file($f)));
829 return $error->($c,"dige mismatch
: is
$is")
830 unless $is eq $version;
833 return $error->($c,"No js
: $f") unless -f $f;
834 $c->render(text => decode_utf8(read_file($f)) );
836 any '/W/*W' => sub { my ($c) = @_;
837 my $t = $c->param('W');
838 my $s = $c->param('s');
839 my $patch = $c->param('patch') && die "know patch
";
840 my $cache = $G->{Wache} ||= {};
845 return if $char_safety->($c,$t);
847 # and you can't use the name ^[1-5]
849 my $species = $1 || $c->param('species') || '1';
850 # may be in t for unique of+t amongst @Search
851 $t =~ s/\/$species$//;
853 $species = "1.".$species if $species =~ /\D/;
854 my $f = "$t/$species";
862 # optional safety - must replace such dige
863 my $pa = $c->param('parent');
864 if ($pa && $pa ne $cache->{"$f"} ) {
865 $re->{er} = 'not ffwd';
866 # could give out tree since...
868 # $re->{dige} = $cache->{"$f"} ;
872 $re->{ok} = 'deleted';
875 # the whole name is directory
876 -d $t || `mkdir -p $t`;
878 $s = "$s\n" if $s !~ /\n$/;
880 my $enc = encode_utf8($s);
881 write_file("$f\
.1",$enc);
882 my $writ = -s "$f\
.1";
883 return $error->($c,"failed to
write $f\
.1 (journal
):"
884 ." length $writ != ".length($enc))
885 if $writ != length $enc;
888 # the .5 may be in the same request
889 my $five = $c->param('fivestring');
892 write_file("$ff\
.1",encode_utf8($five));
896 # < (notify nearby others, who )+
897 $re->{ok} = 'updated';
898 $re->{ok} = 'created' if $new;
904 $s = decode_utf8(read_file($f));
908 $re->{er} = 'not found';
909 $re->{suggest_species} = 1 if $fone ne $f && -f $fone
913 # it should have a dig
915 $f =~ m{^W/spot/} ? dig($s)
922 # if they know its hash, assume they don't need the string again
923 if (my $ha = $c->param('have')) {
924 delete $re->{s} if grep {$_ eq $dig} split "\t", $ha
926 # or if it was a write
927 delete $re->{s} if $nos;
929 $c->render(text=>sjson($re));
933 any '/ghost/*w' => sub { my ($c) = @_;
934 my $t = $c->param('w');
935 # / in t not meaning directory
936 (my $st = $t) =~ s/\W+/-/g;
937 my $se = $c->param('se') || '*';
938 my $s = $c->param('s');
939 my $patch = $c->param('patch') && die "know patch
";
940 my $cache = $G->{ghostache} ||= {};
941 my @opt = glob "G
/$se/$st";
942 die "multiple
@opt" if @opt > 1;
943 my $f = $opt[0] || '';
944 my ($cat) = $f =~ /^G\/([^\/]+)\//;
945 # < avoid some disking if $have
946 my $wig = "wormhole
/digway/$st";
947 my $digway = readlink($wig) || '';
955 # optional safety - must replace such dige
956 my $pa = $c->param('parent');
958 $re->{er} = "!se param
: writing G
/\$se/\
$t";
961 elsif ($pa && $pa ne $cache->{"$f"} ) {
962 if (!$cache->{"$f"} ) {
963 $re->{er} = "lookup first
";
967 $re->{er} = 'not ffwd';
969 # could give out tree since...
971 # $re->{dige} = $cache->{"$f"} ;
975 $re->{ok} = 'deleted';
978 # non-name is directory
979 (my $dir = $f) =~ s/\/[^\/]+$//;
980 -d $dir || `mkdir -p $dir`;
982 #$s = "$s\n" if $s !~ /\n$/;
984 write_file("$f\
.1",encode_utf8($s));
987 # < (notify nearby others, who )+
988 $re->{ok} = 'updated';
989 $re->{ok} = 'created' if $new;
992 my $mv = $c->param('gitmv');
996 sayre("no $m to move from
")
997 && last unless -f $m;
999 my $dif = `diff $f $m`;
1000 sayre("$f<-$mv not up to date
:\n".$dif)
1001 && last if $dif =~ /\S/;
1004 my $move = `git mv $m $f`;
1005 sayre("$f<-$mv git mv noise
:\n".$move)
1006 && last if $move =~ /\S/;
1014 $s = decode_utf8(read_file($f));
1015 $re->{ok} = 'found';
1018 $re->{er} = 'not found'
1023 $cache->{$f} = $dig;
1024 if ($dig ne $digway) {
1025 -l $wig && `unlink $wig`;
1029 die "no cat
: $f" if !$cat;
1030 $re->{se} = $cat;# if $cat ne $se;
1032 # they know string if:
1033 if (my $ha = $c->param('have')) {
1034 # they know its hash
1035 delete $re->{s} if grep {$_ eq $dig} split "\t", $ha
1041 $poll->{doing}() if $poll->{ways} && $poll->{ways}->{"$t"};
1045 $c->render(text=>sjson($re));
1048 #c /way/ $A->{4}->{sc}->{waythe} way!
1049 any '/JaBabz/*W' => sub { my ($c) = @_;
1050 my $t = $c->param('W');
1051 my $w = $c->param('s');
1053 my $dige = dige($w);
1054 my $cache = $G->{Babache} ||= {};
1055 $w = $cache->{"$dige"} ||= do {
1061 $c->render(text=>$w);
1065 # this line is compiled to JaBabz($C):
1074 for ('G/*','wormhole/way') {
1075 my @opt = glob "$_/$t";
1077 next if !$f || !-f $f;
1078 # $w->{t} will be pi/thing, t (on disk) is pi-thing
1079 $w = {t=>$ot,y=>{}};
1080 $w->{c}->{s} = decode_utf8(read_file($f));
1081 $w->{sc}->{dige} = slm(12, dig $w->{c}->{s});
1082 $w->{sc}->{of} = 'w';
1088 my $babv = readlink("wormhole
/digway/JaBabz
");
1089 $A->{sc}->{wayjs} = {} if !$A->{sc}->{babv} || $A->{sc}->{babv} ne $babv;
1090 $A->{sc}->{babv} = $babv;
1091 # swap s just read for s compiled against its t/dige
1092 $w->{c}->{s} = $A->{sc}->{wayjs}->{"$w->{t
}"}->{"$w->{sc
}->{dige
}"} ||= babz($w);
1095 get '/way/*way' => sub { my ($c) = @_;
1096 my $t = $c->param('way');
1098 $w || return $c->reply->not_found;
1100 $c->res->headers->append(Dige => $w->{sc}->{dige});
1102 my $have = $c->param('have');
1103 if ($have && $have eq $w->{sc}->{dige} ) {
1104 return $c->render(text => '')
1106 $c->render(text => $w->{c}->{s});
1108 get '/wayjs/#dige/#args/*way' => sub { my ($c) = @_;
1109 my $t = $c->param('way');
1111 # must be that version
1112 $w && $c->param('dige') eq $w->{sc}->{dige}
1113 || return $c->reply->not_found;
1114 # put in a global namespace
1115 my $name = join("__
",'w',$t,
1116 $c->param('dige'),$c->param('args'));
1118 my $s = "function
$name(A
,C
,G
,T
,"
1119 .$c->param('args').") {\n".$w->{c}->{s}."\n}\n";
1120 $c->render(text => $s);
1122 get '/wjs/*way' => sub { my ($c) = @_;
1123 my $wayish = $c->param('way');
1124 $wayish =~ s/\.js$//;
1125 my ($t,$args,$dige) = split "__
", $wayish;
1129 1 && saybl $c->param('way')." -> $t $args $dige";
1131 # must be that version
1133 1 && sayre "404 $t";
1134 return $c->reply->not_found
1136 if ($dige && $dige ne $w->{sc}->{dige}) {
1137 1 && sayre "moved
$t $dige -> $w->{sc
}->{dige
}";
1138 return $c->reply->not_found
1140 $dige = $w->{sc}->{dige};
1141 $w->{sc}->{args} = $args;
1143 # put in a global namespace
1144 my $name = join("__
",'w',$t,$args,$dige);
1147 my $s = "function
$name(A
,C
,G
,T
,$args) {\n".$w->{c}->{s}."\n}\n";
1149 $c->res->headers->append(sc => sjson($w->{sc}));
1150 $c->render(text => $s);