NB. pretty printers
NB.    pp filename     - pretty print file
NB.    ppf filename    - pretty print form definition only
NB. built from project: ~Source\main\pp\pp
NB. global definitions

script_z_ '~system\main\convert.ijs'
script_z_ '~system\main\files.ijs'
script_z_ '~system\main\strings.ijs'

coclass 'jpp'

j=. 'break. case. catch. catchd. catcht. continue. do. else. elseif. end.'
CONTROLS=: ;: j,' fcase. for. if. return. select. try. while. whilst.'
CONTROLX=: 0 0 0 0 0 0 0 0 0 _1, 0 1 1 0 1 1 1 1
CONTROLN=: ;: 'case. catch. catchd. catcht. do. else. elseif. end. fcase.'

FORMEND=: 'rem form end;';,')'
CONTS=: ';xywh';';cc';';cn'
expand=: #^:_1
lastones=: > (}. , 0:)  
tolist=: }.@;@:(LF&,@,@":&.>) 
findcontrols=: (1: e. (CONTS"_ (1: e. E.) &> <)) &>
maskinside=: +./\ *. +./\.
notquotes=: (+: ~:/\)@(''''&=)
notcomments=: ([: +./\. (=&' ') +: [: +./\ 'NB.'&E. > ~:/\@(''''&=))
notqc=: (notquotes *. notcomments) f.
debq=: #~ (+. 1: |. (> </\))@(notquotes <: ' '&~:)

NOUNDEFINE=: <@;: '0 : 0' , 'noun : 0' , '0 define' ,: 'noun define'
commentline=: 3 : 0
line=. y.
if. 'NB. '-:4{.line do.
  if. (,'=') -: ~. 4}.line do.
    line=. 'NB. ',57#'='
  elseif. (,'-') -: ~. 4}.line do.
    line=. 'NB. ',57#'-'
  end.
end.
line
)
dltab=: (TAB&= i. 0:) }. ]
indent1=: 3 : 0
tok=. y.
f=. 'for_'&-: @ (4&{.) *. ('.'&=) @ {:
x=. I. f &> tok
tok=. (<'for.') x} tok
+/ (CONTROLX,0) {~ CONTROLS i. tok
)
masknouns=: 3 : 0
tok=: ;: @ (#~ notqc) each y.
bgn=: masknoun1 &> tok
end=: tok=<;:')'
end=: 2 }. ; (1 0,bgn) < @ (</\) ;. 1 [ 0 1,end
if. (+/bgn) ~: +/end do.
  wdinfo 'Could not match noun begin and end definition'
  0 #~ #tok
else.
  ~: /\. bgn +. end
end.
)
masknoun1=: 3 : 0
1 e. NOUNDEFINE 1&e.@E. &> <y.
)
spacing=: 3 : 0
msk=. notcomments y.
in=. 0
bgn=. 0
txt=. debq msk#y.
com=. (-.msk)#y.

if. #txt do.
  tok=. ;: :: 0: txt
  if. tok -: 0 do. return. end.
  if. #tok do.
    in=. indent1 tok
    bgn=. ({.tok) e. CONTROLN
    if. 1=#tok do.
      txt=. ;tok
    else.
      txt=. spacing1 dlb txt
    end.
  else.
    txt=. ''
  end.
else.
  com=. dlb com
end.

in;bgn;<<txt,com
)
f=. #~ (=&' ') *: 1: |. notquotes *. '=:'&E. +. '=.'&E.
noblankbefore=: f f. ^: _

f=. #~ 1: + [: j. (1: |. =&' ') < _1: |. notquotes *. '=:'&E. +. '=.'&E.
blankafter=: f f. ^: _
spacing1=: blankafter @ noblankbefore

pp=: 3 : 0
0 2 pp y.
:
files=. boxxopen y.
res=. (#files) $ 0
for_f. files do.
  s=. x. pprun f
  if. s = _1 do. return. end.
  res=. s f_index } res
end.
res
)
pprun=: 4 : 0
old=. fread y.
dat=. pprun1 old;x.;y.
if. L. dat do.
  'lin msg'=. dat
  msg=. msg, ' in file:',LF,LF, > y.
  (0 >. lin - 10) open_jijs_ >y.
  if. lin do.
    pos=. 1 0 + (+/\LF = toJ old) i. lin + 0 1
    smsetselect_jijs_ pos
  end.
  wdinfo 'pp';msg
  _1 return.
end.
if. dat -: old do.
  0
else.
  1 [ dat fwrites y.
end.
)
pprun1=: 3 : 0
'old opt file'=. y.
'iftab tabwid'=. opt
dat=. old -. 26{a.

if. 0 = #dat do. return. end.

if. iftab do. spc=. TAB else. spc=. tabwid#' ' end.
dat=. toJ dat
dat=. dat,LF -. _1{.dat
dat=. <;._2 dat
dat=. dtb each dat
dat=. dltab each dat

ndx=. I. masknouns dat
noun=. ndx { dat
dat=. a: ndx} dat
dat=. commentline each dat
indat=. spacing each dat
if. (<0) e. indat do.
  lin=. indat i. <0
  txt=. lin pick dat
  cnt=. +/'''' = txt {.~ ('NB.' E. txt) i. 1
  if. 2 | cnt do.
    msg=. 'Mismatched quotes'
  else.
    msg=. 'Could not parse line'
  end.
  lin;msg
  return.
end.

'in begin dat'=. |: > indat
if. 0 ~: +/ in do.
  ins=. +/\ in

  if. _1 e. ins do.
    lin=. ins i. _1
    msg=. 'Unmatched end of control block'
  else.
    msk=. (dat = <,')') *. ins > 0
    if. 1 e. msk do.
      lin=. msk i. 1
      msg=. 'Unmatched start of control block'
    else.
      lin=. 0
      msg=. 'Mismatched control words'
    end.
  end.
  lin ; msg return.

else.
  in=. _1 |. +/\ in
  in=. 0 >. in - begin
  cmt=. 'NB.'&-: @ (3&{.)
  in=. in * -. cmt &> dat
  dat=. in (([ # spc"_),])each dat
end.
dat=. noun ndx } dat
dat=. toHOST ; ,&LF each dat

)

ppf=: 3 : 0
y=. boxopen y.
if. 1<#y do. ppf &> y return. end.

old=. 'b' fread y.
if. old -: _1 do. wdinfo 'Unable to read form' return. end.

new=. ppform old
if. 0 = new -: old do.
  new=. tolist new
  <new fwrites y.
else.
  a:
end.
)
ppform=: 3 : 0
hit=. 1, }. (1: e. '0 : 0'&E.) &> y.
dat=. hit <;.1 y.

forms=. I. (1: e. FORMEND&E.) &> dat
if. 0 e. #forms do. y. return. end.

; (ppform1 each forms { dat) forms} dat
)

ppform1=: 3 : 0

dat=. deb each y.
dat=. dat -. a:

end=. dat {.~ (FORMEND E. dat) i. 1
msk=. maskinside findcontrols ';',each end

head=. (msk i. 1) {. dat
tail=. (1 + msk i: 1) }. dat
form=. msk # end

head, a:, (ppcc form), a:, tail
)
ppcc=: 3 : 0
dat=. (, ';'"_ -. {:) each y.
blk=. ';', ; dat
msk=. ';xywh' E. blk
if. 0 = {.msk do.
  wdinfo 'Child controls do not start with xywh command.'
  dat return.
end.

blk=. (}:msk) <@(5&}.);.1 }.blk

ndx=. blk i.&> ';'
pos=. <@('xywh '&,) "1 ": 0 ". ndx {.&> blk
def=. (1+ndx) }.each blk

if. 0 e. 'cc'&-: @ (2&{.) &> def do.
  wdinfo 'xywh command not followed by cc command'
  dat return.
end.

def=. 3 }. each def
ind=. def i.&> ' '
max=. 1 + >./ ind
nam=. ind max&{. @ {. each def
def=. (1+ind) }. each def
ind=. (def i.&> ' ') <. def i.&> ';'
max=. 1 + >./ ind
typ=. ind {. each def
grp=. 0, }. typ = <'groupbox'
f=. (max&{. @ {.) , }.
def=. nam ,each ind f each def
new=. pos ,each ';cc '&, each def
dat=. (grp{'';LF) ,each new
)