Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.postscript > #3009 > unrolled thread
| Started by | luser droog <luser.droog@gmail.com> |
|---|---|
| First post | 2017-03-21 22:44 -0700 |
| Last post | 2017-04-07 22:43 -0400 |
| Articles | 13 — 4 participants |
Back to article view | Back to comp.lang.postscript
html generator luser droog <luser.droog@gmail.com> - 2017-03-21 22:44 -0700
Re: html generator Carlos <angus@quovadis.com.ar> - 2017-03-22 22:02 +0100
Re: html generator tlvp <mPiOsUcB.EtLlLvEp@att.net> - 2017-03-22 18:24 -0400
Re: html generator luser droog <luser.droog@gmail.com> - 2017-03-22 16:45 -0700
Re: html generator JohnF <john@please.see.sig.for.email.com> - 2017-03-23 05:18 +0000
Re: html generator tlvp <mPiOsUcB.EtLlLvEp@att.net> - 2017-03-23 19:33 -0400
Re: html generator Carlos <angus@quovadis.com.ar> - 2017-03-23 07:56 +0100
Re: html generator luser droog <luser.droog@gmail.com> - 2017-03-22 16:44 -0700
functional ps? was: Re: html generator luser droog <luser.droog@gmail.com> - 2017-03-31 23:48 -0700
Re: functional ps? was: Re: html generator Carlos <angus@quovadis.com.ar> - 2017-04-01 23:33 +0200
Re: functional ps? was: Re: html generator luser droog <luser.droog@gmail.com> - 2017-04-03 08:10 -0700
Re: functional ps? was: Re: html generator luser droog <luser.droog@gmail.com> - 2017-04-07 07:07 -0700
Re: functional ps? was: Re: html generator tlvp <mPiOsUcB.EtLlLvEp@att.net> - 2017-04-07 22:43 -0400
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-03-21 22:44 -0700 |
| Subject | html generator |
| Message-ID | <3f057c06-9f44-4f91-9912-361bd7667bbe@googlegroups.com> |
A friend and I are working on a webpage builder. As part of
our design process I wrote up a draft in postscript, knowing
that I could knock one out fairly quickly.
So this is what I came up with, for the curious or the bored.
As I described the behavior to my friend, he replied "Oh, so
it's object-oriented postscript; that's frightening."
It's meant to describe a control panel that will be "compiled"
into html/js.
$ cat page.ps && echo ----snip---- && gsnd -q page.ps
%@
/main {
(<html>) =
(<head>) =
( <script>)=
( </script>)=
(</head>)=
(<body>)=
process-layout
(</body>)=
(</html>) =
quit
} def
%% Content
/wireless <<
/Type /controls cvx
/afterburner { (Afterburner) [(Auto)(Enable)(Disable)] select }
/ap_isolation { (AP Isolation) check }
/authentication { (Authentication) [(Auto)(Shared Key)] select }
>> def
/do-thing {
dup type /arraytype eq {
{ do-thing } forall
}{
dup /Type get exec
} ifelse
} def
/controls {
( <table>)=
{
1 index /Type eq {
pop pop
}{
exec
} ifelse
} forall
( </table>)=
} def
/select {
( <tr>)=
( <td>) =only exch =only (</td>)=
( <td>) =
0 1 2 index length 1 sub { % /id [] 0
12 { ( ) print } repeat
3 copy get % /id [] 0 /id (Auto)
=only % /id [] 0 /id
( <input type=radio name=) =only =only
( value=) =only =only (>)=
} for
pop pop
( </td>) =
( </tr>)=
} def
/check {
pop pop
} def
%% Layout
/menu null def
/submenu null def
/panels [
wireless
] def
/help null def
/layout [
{ [
//menu
//submenu
//panels
//help
] table }
] def
/process-layout { layout { exec } forall } def
/table {
( <table>)=
{
%(==1==)=
dup type /nulltype ne {
( <tr><td>)=
do-thing
( </tr></td>)=
}{
pop
} ifelse
} forall
( </table>)=
} def
main
----snip----
<html>
<head>
<script>
</script>
</head>
<body>
<table>
<tr><td>
<table>
<tr>
<td>Afterburner</td>
<td>
Auto <input type=radio name=afterburner value=0>
Enable <input type=radio name=afterburner value=1>
Disable <input type=radio name=afterburner value=2>
</td>
</tr>
<tr>
<td>Authentication</td>
<td>
Auto <input type=radio name=authentication value=0>
Shared Key <input type=radio name=authentication value=1>
</td>
</tr>
</table>
</tr></td>
</table>
</body>
</html>
[toc] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2017-03-22 22:02 +0100 |
| Message-ID | <20170322220232.3c641ccb@samara.DOMA> |
| In reply to | #3009 |
[luser droog <luser.droog@gmail.com>, 2017-03-21 22:44]
> A friend and I are working on a webpage builder. As part of
> our design process I wrote up a draft in postscript, knowing
> that I could knock one out fairly quickly.
>
> So this is what I came up with, for the curious or the bored.
> As I described the behavior to my friend, he replied "Oh, so
> it's object-oriented postscript; that's frightening."
>
> It's meant to describe a control panel that will be "compiled"
> into html/js.
Nice.
[...]
> /wireless <<
> /Type /controls cvx
> /afterburner { (Afterburner) [(Auto)(Enable)(Disable)] select }
> /ap_isolation { (AP Isolation) check }
> /authentication { (Authentication) [(Auto)(Shared Key)] select }
> >> def
[...]
> /controls {
> ( <table>)=
> {
> 1 index /Type eq {
> pop pop
> }{
> exec
> } ifelse
> } forall
> ( </table>)=
> } def
[...]
> <table>
> <tr>
> <td>Afterburner</td>
> <td>
> Auto <input type=radio name=afterburner value=0>
> Enable <input type=radio name=afterburner value=1>
> Disable <input type=radio name=afterburner value=2>
> </td>
> </tr>
> <tr>
> <td>Authentication</td>
> <td>
> Auto <input type=radio name=authentication value=0>
> Shared Key <input type=radio name=authentication value=1>
> </td>
> </tr>
> </table>
How did you ensure the order? (?)
Btw, isn't it a shame Adobe made characters < / > syntax? An opportunity for a
real nice DSL for XML/HTML was lost...
--
[toc] | [prev] | [next] | [standalone]
| From | tlvp <mPiOsUcB.EtLlLvEp@att.net> |
|---|---|
| Date | 2017-03-22 18:24 -0400 |
| Message-ID | <1guv442cevupk.1aj58z9fiqhpq.dlg@40tude.net> |
| In reply to | #3010 |
On Wed, 22 Mar 2017 22:02:32 +0100, Carlos wrote: > ... real nice DSL ... "DSL" = ? Digital subscriber line? dynamic software link? dual substitution language? double sense loser? deft sign loop? -- Help! Tnx. Cheers, -- tlvp -- Avant de repondre, jeter la poubelle, SVP.
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-03-22 16:45 -0700 |
| Message-ID | <83f1a227-e919-42da-b8cd-ab7152bb5826@googlegroups.com> |
| In reply to | #3011 |
On Wednesday, March 22, 2017 at 5:24:25 PM UTC-5, tlvp wrote: > On Wed, 22 Mar 2017 22:02:32 +0100, Carlos wrote: > > > ... real nice DSL ... > > "DSL" = ? Digital subscriber line? dynamic software link? dual substitution > language? double sense loser? deft sign loop? -- Help! Tnx. Cheers, -- tlvp Domain Specific Language, I'm sure. What used to be called "little languages" in the 80s.
[toc] | [prev] | [next] | [standalone]
| From | JohnF <john@please.see.sig.for.email.com> |
|---|---|
| Date | 2017-03-23 05:18 +0000 |
| Message-ID | <oavlqr$3jh$1@reader1.panix.com> |
| In reply to | #3013 |
luser droog <luser.droog@gmail.com> wrote: > On Wednesday, March 22, 2017 at 5:24:25 PM UTC-5, tlvp wrote: >> On Wed, 22 Mar 2017 22:02:32 +0100, Carlos wrote: >> >> > ... real nice DSL ... >> >> "DSL" = ? Digital subscriber line? dynamic software link? >> dual substitution language? double sense loser? deft sign >> loop? -- Help! Tnx. Cheers, -- tlvp > > Domain Specific Language, I'm sure. What used to be called > "little languages" in the 80s. Called "little languages" at least as recently as 1998, e.g., https://www.goodreads.com/book/show/758073.HPL -- John Forkosh ( mailto: j@f.com where j=john and f=forkosh )
[toc] | [prev] | [next] | [standalone]
| From | tlvp <mPiOsUcB.EtLlLvEp@att.net> |
|---|---|
| Date | 2017-03-23 19:33 -0400 |
| Message-ID | <fw56tibzhdgh$.1j2kq0q46b5qm$.dlg@40tude.net> |
| In reply to | #3013 |
On Wed, 22 Mar 2017 16:45:30 -0700 (PDT), luser droog wrote: > Domain Specific Language, I'm sure. Thanks. That particular acronym's new to me. > ... What used to be called "little languages" > in the 80s. I'd never have guessed that :-) . So thanks again. Cheers, -- tlvp -- Avant de repondre, jeter la poubelle, SVP.
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2017-03-23 07:56 +0100 |
| Message-ID | <20170323075600.08dd167b@samara.DOMA> |
| In reply to | #3011 |
[tlvp <mPiOsUcB.EtLlLvEp@att.net>, 2017-03-22 18:24] > On Wed, 22 Mar 2017 22:02:32 +0100, Carlos wrote: > > > ... real nice DSL ... > > "DSL" = ? Digital subscriber line? dynamic software link? dual substitution > language? double sense loser? deft sign loop? -- Help! Tnx. Cheers, -- tlvp Domain specific language, as luser-droog mentioned. It'd be nice if one could name functions <p> or <html>, with the code resembling the html document structure. --
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-03-22 16:44 -0700 |
| Message-ID | <bc8ed7c6-182a-41a9-9235-c1934468d178@googlegroups.com> |
| In reply to | #3010 |
On Wednesday, March 22, 2017 at 4:02:33 PM UTC-5, Carlos wrote:
> [luser droog <luser.droog@gmail.com>, 2017-03-21 22:44]
> > A friend and I are working on a webpage builder. As part of
> > our design process I wrote up a draft in postscript, knowing
> > that I could knock one out fairly quickly.
> >
> > So this is what I came up with, for the curious or the bored.
> > As I described the behavior to my friend, he replied "Oh, so
> > it's object-oriented postscript; that's frightening."
> >
> > It's meant to describe a control panel that will be "compiled"
> > into html/js.
>
> Nice.
>
> [...]
> > /wireless <<
> > /Type /controls cvx
> > /afterburner { (Afterburner) [(Auto)(Enable)(Disable)] select }
> > /ap_isolation { (AP Isolation) check }
> > /authentication { (Authentication) [(Auto)(Shared Key)] select }
> > >> def
> [...]
> > /controls {
> > ( <table>)=
> > {
> > 1 index /Type eq {
> > pop pop
> > }{
> > exec
> > } ifelse
> > } forall
> > ( </table>)=
> > } def
> [...]
> > <table>
> > <tr>
> > <td>Afterburner</td>
> > <td>
> > Auto <input type=radio name=afterburner value=0>
> > Enable <input type=radio name=afterburner value=1>
> > Disable <input type=radio name=afterburner value=2>
> > </td>
> > </tr>
> > <tr>
> > <td>Authentication</td>
> > <td>
> > Auto <input type=radio name=authentication value=0>
> > Shared Key <input type=radio name=authentication value=1>
> > </td>
> > </tr>
> > </table>
>
> How did you ensure the order? (?)
Here, with luck. In the current version, we're generating the postscript
from a sort-of config script with awk. And all dicts contain an array of
the keys in order.
> Btw, isn't it a shame Adobe made characters < / > syntax? An opportunity for a
> real nice DSL for XML/HTML was lost...
That hadn't occurred to me as a problem. I do wish there were a way to add more
punctuation chars to the delimiter set.
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-03-31 23:48 -0700 |
| Subject | functional ps? was: Re: html generator |
| Message-ID | <cc855de4-c705-4805-b9d8-f9bbc0d29d3c@googlegroups.com> |
| In reply to | #3009 |
On Wednesday, March 22, 2017 at 12:44:24 AM UTC-5, luser droog wrote:
> A friend and I are working on a webpage builder. As part of
> our design process I wrote up a draft in postscript, knowing
> that I could knock one out fairly quickly.
>
> So this is what I came up with, for the curious or the bored.
> As I described the behavior to my friend, he replied "Oh, so
> it's object-oriented postscript; that's frightening."
>
Subsequent iterations and conversations have steered the project
somewhat away from the object-orientation paradigm (although of
course that will be important in the js of the resulting page)
towards being more 'functional'. So the following is a grab-bag
of stuff which is my attempt to rewrite some postscript without
following my usual style.
Any comments (positive or negative) appreciated.
$ cat toolbox.ps
/toolbox-main {
4 5 6 {a b c} BEGIN
a = b = c =
0 1 9 { spaces == } for
END
quit
} def
% Defining Local Variables
% eg.
% /pythagorean-distance { { x0 y0 x1 y1 } BEGIN
% x0 x1 sub dup mul
% y0 y1 sub dup mul add sqrt
% END } def
%
/BEGIN { reverse dup dict-for-names begin { exch def } forall } def
/END { end } def
/dict-for-names { length dict } def
/reverse { % a
[ exch % [ a
dup { % [ ... a i
1 index exch get exch % [ ... a[i] a
} backwards-for-loop pop % [ a[n-1]..a[0]
] % [...]
} def
/forwards { 0 1 2 index length 1 sub } def
/backwards { length 1 sub -1 0 } def
/forward-for-loop { % a proc
exch forwards % proc a 0 1 n-1
5 -1 roll % a 0 1 n-1 proc
for
} def
/backward-for-loop { % a proc
exch backwards % proc a n-1 -1 0
5 -1 roll % a n-1 -1 0 proc
for
} def
/spaces { [ exch {( )} repeat ] join } def
% array-of-strings join string
% array-of-arrays join array
% string* n join string
% array* n join array
%
/join {
dup is_integer { array astore } if
join-elements
} def
/join-elements { % a
dup element-lengths-sum % a n
1 index new-same-type-as-first % a a'
exch put-by-intervals % a'
} def
/element-lengths-sum { % a
0 exch { length add } forall % n
} def
/type-constructor <<
/arraytype {array}
/stringtype {string}
/nulltype {string}
>> def
/new-same-type-as-first { % n a
%pstack/ =
first type % n a[0]
%pstack/ =
type-constructor exch get exec % a a'
} def
/first { dup length 0 eq { pop null }{ 0 get } ifelse } def
/put-by-intervals { % a' a
0 exch { % a' pos a[i]
put-element-and-update-position % a' pos a[i]
} forall % a' pos'
pop % a'
} def
/put-element-and-update-position { % a' pos a[i]
3 copy putinterval % a' pos a[i]
length add % a' pos'
} def
/is_integer { type /integertype eq } def
/is_array { type /arraytype eq } def
/is_dict { type /dicttype eq } def
/is_null { type /nulltype eq } def
/is_zero { dup is_integer { 0 eq }{ false } ifelse } def
/main where { pop }{ toolbox-main } ifelse
[toc] | [prev] | [next] | [standalone]
| From | Carlos <angus@quovadis.com.ar> |
|---|---|
| Date | 2017-04-01 23:33 +0200 |
| Subject | Re: functional ps? was: Re: html generator |
| Message-ID | <20170401233324.3184776f@samara.DOMA> |
| In reply to | #3031 |
[luser droog <luser.droog@gmail.com>, 2017-03-31 23:48]
[...]
> Subsequent iterations and conversations have steered the project
> somewhat away from the object-orientation paradigm (although of
> course that will be important in the js of the resulting page)
> towards being more 'functional'. So the following is a grab-bag
> of stuff which is my attempt to rewrite some postscript without
> following my usual style.
>
> Any comments (positive or negative) appreciated.
>
>
> $ cat toolbox.ps
>
> /toolbox-main {
> 4 5 6 {a b c} BEGIN
I find this unnecessary. What's the advantage over << /a 4 /b 5 /c 6 >> begin?
For assigning parameters, I prefer your idiom ({ c b a } { exch def } forall),
or a better abstraction, maybe something like
/pythagorean-distance { x0 y0 x1 y1 } {
...
} defn
[...]
> /backward-for-loop { % a proc
> exch backwards % proc a n-1 -1 0
> 5 -1 roll % a n-1 -1 0 proc
> for
> } def
I had to change this to:
/backwards-for-loop { % a proc
exch backwards % proc a n-1 -1 0
4 -1 roll % a n-1 -1 0 proc
for
} def
[...]
> % array-of-strings join string
> % array-of-arrays join array
> % string* n join string
> % array* n join array
> %
> /join {
> dup is_integer { array astore } if
> join-elements
> } def
I like this implementation, it's well factored and easy to follow. I never seem
to be able to do that, I always put everything in one function.
>
> /join-elements { % a
> dup element-lengths-sum % a n
> 1 index new-same-type-as-first % a a'
> exch put-by-intervals % a'
> } def
>
> /element-lengths-sum { % a
> 0 exch { length add } forall % n
> } def
>
> /type-constructor <<
> /arraytype {array}
> /stringtype {string}
> /nulltype {string}
> >> def
>
>
> /new-same-type-as-first { % n a
> %pstack/ =
> first type % n a[0]
> %pstack/ =
> type-constructor exch get exec % a a'
> } def
>
> /first { dup length 0 eq { pop null }{ 0 get } ifelse } def
>
> /put-by-intervals { % a' a
> 0 exch { % a' pos a[i]
> put-element-and-update-position % a' pos a[i]
> } forall % a' pos'
> pop % a'
> } def
>
> /put-element-and-update-position { % a' pos a[i]
> 3 copy putinterval % a' pos a[i]
> length add % a' pos'
> } def
>
> /is_integer { type /integertype eq } def
> /is_array { type /arraytype eq } def
> /is_dict { type /dicttype eq } def
> /is_null { type /nulltype eq } def
> /is_zero { dup is_integer { 0 eq }{ false } ifelse } def
>
> /main where { pop }{ toolbox-main } ifelse
--
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-04-03 08:10 -0700 |
| Subject | Re: functional ps? was: Re: html generator |
| Message-ID | <95b16b8e-99be-45ec-bd69-f782c47d5abe@googlegroups.com> |
| In reply to | #3032 |
On Saturday, April 1, 2017 at 4:33:25 PM UTC-5, Carlos wrote:
> [luser droog <luser.droog@gmail.com>, 2017-03-31 23:48]
> [...]
> > Subsequent iterations and conversations have steered the project
> > somewhat away from the object-orientation paradigm (although of
> > course that will be important in the js of the resulting page)
> > towards being more 'functional'. So the following is a grab-bag
> > of stuff which is my attempt to rewrite some postscript without
> > following my usual style.
> >
> > Any comments (positive or negative) appreciated.
> >
> >
> > $ cat toolbox.ps
> >
> > /toolbox-main {
> > 4 5 6 {a b c} BEGIN
>
> I find this unnecessary. What's the advantage over << /a 4 /b 5 /c 6 >> begin?
> For assigning parameters, I prefer your idiom ({ c b a } { exch def } forall),
> or a better abstraction, maybe something like
>
> /pythagorean-distance { x0 y0 x1 y1 } {
> ...
> } defn
That's really cool. My friend loves it. Another factor in this
project is my friend doesn't want to learn "too much postscript".
So all of my idioms need to be wrapped up as functions.
> [...]
>
> > /backward-for-loop { % a proc
> > exch backwards % proc a n-1 -1 0
> > 5 -1 roll % a n-1 -1 0 proc
> > for
> > } def
>
> I had to change this to:
>
> /backwards-for-loop { % a proc
> exch backwards % proc a n-1 -1 0
> 4 -1 roll % a n-1 -1 0 proc
> for
> } def
The bug there was in /backwards. It should leave a copy of the array
for the loop to work on.
> [...]
>
> > % array-of-strings join string
> > % array-of-arrays join array
> > % string* n join string
> > % array* n join array
> > %
> > /join {
> > dup is_integer { array astore } if
> > join-elements
> > } def
>
> I like this implementation, it's well factored and easy to follow. I never seem
> to be able to do that, I always put everything in one function.
>
That's what I'm working on here. Trying to write short functions, and
totally top-down. Pass off work to sub functions that aren't written
yet but will have a smaller task to perform.
It's a tough slog.
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-04-07 07:07 -0700 |
| Subject | Re: functional ps? was: Re: html generator |
| Message-ID | <3a1bbbef-8fa9-47f8-b951-4031a7bee25a@googlegroups.com> |
| In reply to | #3036 |
On Monday, April 3, 2017 at 10:10:32 AM UTC-5, luser droog wrote:
> On Saturday, April 1, 2017 at 4:33:25 PM UTC-5, Carlos wrote:
> > [luser droog <luser.droog@gmail.com>, 2017-03-31 23:48]
> > [...]
> > > Subsequent iterations and conversations have steered the project
> > > somewhat away from the object-orientation paradigm (although of
> > > course that will be important in the js of the resulting page)
> > > towards being more 'functional'. So the following is a grab-bag
> > > of stuff which is my attempt to rewrite some postscript without
> > > following my usual style.
> > >
> > > Any comments (positive or negative) appreciated.
> > >
> > >
> > > $ cat toolbox.ps
> > >
> > > /toolbox-main {
> > > 4 5 6 {a b c} BEGIN
> >
> > I find this unnecessary. What's the advantage over << /a 4 /b 5 /c 6 >> begin?
> > For assigning parameters, I prefer your idiom ({ c b a } { exch def } forall),
> > or a better abstraction, maybe something like
> >
> > /pythagorean-distance { x0 y0 x1 y1 } {
> > ...
> > } defn
>
> That's really cool. My friend loves it. Another factor in this
> project is my friend doesn't want to learn "too much postscript".
> So all of my idioms need to be wrapped up as functions.
>
Here's my next version.
cat sample/skippy/v1-josh-toolbox.ps
%(../debug.ps/db5.ps)run traceon currentfile cvx debug
/toolbox-main {
4 5 6 {a b c} BEGIN
a = b = c =
0 1 9 { spaces == } for
END
(o/data.ps) run
global_welcome { exch =only ( ) print == } map-children
% pstack/ =
[ 65 66 67 ] chars-to-string ==
(p) (text) [(align=right)] tag ==
{ {{false} {(nope!)=}} {{true} {(it's true!)=}} } cond
(hello, %%%%) [/R 2 /D 2] sprintf ==
quit
} def
% Define Local Variables
% eg.
% /pythagorean-distance { x0 y0 x1 y1 } {
% x0 x1 sub dup mul
% y0 y1 sub dup mul add sqrt
% } function def
%
/BEGIN { reverse dup length dict begin { exch def } forall } def
/END { end } def
% {a r g s} {body} -> {{a r g s}BEGIN body END}
/function {
{BEGIN} exch combine
{END} combine
curry
} def
% Predicates
/is_integer { type /integertype eq } def
/is_array { type /arraytype eq } def
/is_dict { type /dicttype eq } def
/is_null { type /nulltype eq } def
/is_zero { dup is_integer { 0 eq }{ false } ifelse } def
% Generating arrays and strings and procs
%
/spaces { [ exch {( )} repeat ] join } def
% array-of-strings join string
% array-of-arrays join array
% string* n join string
% array* n join array
% If n=0 or array length is 0, result is a string
/join {
dup is_integer { array astore } if
join-elements
} def
/curry { [ 3 1 roll expand ] cvx } def
/combine { 2 join cvx } def
% Mapping functions over complex structures
%
% /name value proc result
% ordered_dict proc -> array_of_results
/map-in-name-order { % dict proc
1 index /name_order get % dict proc array
3 -1 roll % proc array dict
{ 1 index get } curry % proc array {.dict. 1 index get}
3 -1 roll combine % array {.dict. 1 index get .proc.}
forall
} def
/map-children {
exch /children get exch map-in-name-order
} def
% Extracting data from the tree
%
/children-array {
{ exch pop } map-children
} def
% Conversions
/as-string { 128 string cvs } def
/as-array { [ exch expand ] } def
/as-dict { << exch expand >> } def
/chars-to-string { dup length string exch put-elements pop } def
/reverse { % a
[ exch % [ a
{ % [ ... a i
%pstack/ =
1 index exch get exch % [ ... a[i] a
} backward-for-loop pop % [ a[n-1]..a[0]
] % [...]
} def
/forward-for-loop { % a proc
exch forwards % proc a 0 1 n-1
5 -1 roll % a 0 1 n-1 proc
for
} def
/backward-for-loop { % a proc
exch backwards % proc a n-1 -1 0
5 -1 roll % a n-1 -1 0 proc
%pstack/ =
for
} def
/forwards { 0 1 2 index length 1 sub } def
/backwards { dup length 1 sub -1 0 } def
/join-elements { % a
dup element-lengths-sum % a n
1 index new-same-type-as-first % a a'
exch put-by-intervals % a'
} def
/element-lengths-sum { % a
0 exch { length add } forall % n
} def
/type-constructors <<
/arraytype {array}
/stringtype {string}
/nulltype {string}
>> def
/new-same-type-as-first { % n a
type-constructors begin
first type exec
end
} def
/put-by-intervals { % a' a
0 exch { % a' pos a[i]
putinterval-and-update-position % a' pos'
} forall % a' pos'
pop % a'
} def
/putinterval-and-update-position { % a' pos a[i]
3 copy putinterval % a' pos a[i]
length add % a' pos'
} def
/put-elements { % dst src
{ % dst src i
2 copy get % dst src i src[i]
3 index 3 1 roll % dst src dst i src[i]
put % dst src
} forward-for-loop % dst src
} def
/expand { {} forall } def
/first { dup length 0 eq { pop null }{ 0 get } ifelse } def
/rest { 1 1 index length 1 sub getinterval } def
% wrap
% (p) (text) -> (<p>text</p>)
/simple-tag {tag text}{
/start (<) tag (>) 3 join def
/final (</) tag (>) 3 join def
start text final 3 join
} function def
/tag {
% pstack/ =
dup is_array { tag-with-stuff }{ simple-tag } ifelse
} def
/tag-with-stuff {tag text stuff}{
% pstack/ =
/start [ (<) tag
stuff { ( ) exch } forall
(>) ] join def
/final (</) tag (>) 3 join def
start text final 3 join
} function def
% [ [{test}{body}]* ]
/cond {
dup length 0 gt {
{ % [test body]
aload pop test-case
} forall
} if
} def
/test-case {
[ 3 1 roll
/exec cvx exch
{exit} combine
/if cvx
% pstack/ =
] cvx exec
} def
% (format %) [4] -> (format 4)
/sprintf {fmt args} {
[ fmt (%) { % ... str match
search { % post match pre
3 1 roll % pre post match
args shift as-string % pre post match remainder args[0]
% pstack/ =
4 1 roll /args exch def % pre str(args[0]) post match
}{ % str
exit
} ifelse
} loop ] join
} function def
/shift {
dup rest
exch first
% pstack/ =
} def
%/main where { pop }{ toolbox-main } ifelse
[toc] | [prev] | [next] | [standalone]
| From | tlvp <mPiOsUcB.EtLlLvEp@att.net> |
|---|---|
| Date | 2017-04-07 22:43 -0400 |
| Subject | Re: functional ps? was: Re: html generator |
| Message-ID | <i8qb4djjxy2k$.u2b3x2reweef$.dlg@40tude.net> |
| In reply to | #3036 |
On Mon, 3 Apr 2017 08:10:30 -0700 (PDT), luser droog wrote: > That's what I'm working on here. Trying to write short functions, and > totally top-down. Pass off work to sub functions that aren't written > yet but will have a smaller task to perform. > > It's a tough slog. I think that's what the Creator must have said around day # 3 :-) . Cheers, -- tlvp -- Avant de repondre, jeter la poubelle, SVP.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.postscript
csiph-web