Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.postscript > #3009 > unrolled thread

html generator

Started byluser droog <luser.droog@gmail.com>
First post2017-03-21 22:44 -0700
Last post2017-04-07 22:43 -0400
Articles 13 — 4 participants

Back to article view | Back to comp.lang.postscript


Contents

  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

#3009 — html generator

Fromluser droog <luser.droog@gmail.com>
Date2017-03-21 22:44 -0700
Subjecthtml 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]


#3010

FromCarlos <angus@quovadis.com.ar>
Date2017-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]


#3011

Fromtlvp <mPiOsUcB.EtLlLvEp@att.net>
Date2017-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]


#3013

Fromluser droog <luser.droog@gmail.com>
Date2017-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]


#3014

FromJohnF <john@please.see.sig.for.email.com>
Date2017-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]


#3016

Fromtlvp <mPiOsUcB.EtLlLvEp@att.net>
Date2017-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]


#3015

FromCarlos <angus@quovadis.com.ar>
Date2017-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]


#3012

Fromluser droog <luser.droog@gmail.com>
Date2017-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]


#3031 — functional ps? was: Re: html generator

Fromluser droog <luser.droog@gmail.com>
Date2017-03-31 23:48 -0700
Subjectfunctional 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]


#3032 — Re: functional ps? was: Re: html generator

FromCarlos <angus@quovadis.com.ar>
Date2017-04-01 23:33 +0200
SubjectRe: 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]


#3036 — Re: functional ps? was: Re: html generator

Fromluser droog <luser.droog@gmail.com>
Date2017-04-03 08:10 -0700
SubjectRe: 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]


#3039 — Re: functional ps? was: Re: html generator

Fromluser droog <luser.droog@gmail.com>
Date2017-04-07 07:07 -0700
SubjectRe: 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]


#3040 — Re: functional ps? was: Re: html generator

Fromtlvp <mPiOsUcB.EtLlLvEp@att.net>
Date2017-04-07 22:43 -0400
SubjectRe: 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