CodeBrowser

Contains the CodeBrowser code without the test cases.

1. CodeBrowser

References:

ref==>ref

Functions:

1. CodeBrowser.AddFooter (9 lines)

     ∇ {html}←AddFooter parms
[1]    html←''
[2]    :If ~0∊⍴parms.footer
[3]        html←⊂'<footer>'
[4]        html,←⊂'<hr>'
[5]        html,←⊂'<p>',(ExchangeHtmlSpecialChars parms.footer),'</p>'
[6]        html,←⊂'</footer>'
[7]    :EndIf
[8]   ⍝Done
     ∇

2. CodeBrowser.AddMainMenu (14 lines)

     ∇ {hasMainMenu}←AddMainMenu(parms collect);html;refs
[1]    refs←{1<⍴,⍵:↑⍵ ⋄ ⍉⍪⊃⍵}⊃,/parms GetSubNamespaces¨parms.refs
[2]    refs←({(⍵⍳⍵)=⍳≢⍵}refs[;2])⌿refs        ⍝ Get rid of (additional) refs
[3]    hasMainMenu←0
[4]    html←1 AddMainMenu_ refs collect
[5]    :If 1≥+/∨/¨'<li>'∘⍷¨html
[6]        html←''
[7]    :EndIf
[8]    :If 0≠≢html
[9]        html←('<nav id="main">' '<p>Namespace structure:</p>'),html,(⊂'</nav>')
[10]       WriteHTML html
[11]       hasMainMenu←1
[12]   :EndIf
[13]  ⍝Done
     ∇

3. CodeBrowser.AddMainMenu_ (17 lines)

     ∇ html←level AddMainMenu_(refs collect);i;buff;noOf
[1]    html←⊂'<ol>'
[2]    i←1
[3]    :Repeat
[4]        :If ~0∊⍴refs
[5]            html,←{'<li>'('<a href="#',(collect.remove RemoveLevels⍕⍵),'">',((⊃{⍺,'.',⍵}/⍕¨level),'. ',⍕⍵),'</a>')}refs[i;2]
[6]            :If 0<noOf←{+/∧\1↓⍵[;1]>⊃⍵}(i-1)↓refs
[7]                html,←(level,1)AddMainMenu_(noOf↑i↓refs)collect
[8]                i←i+noOf+1
[9]            :Else
[10]               i+←1
[11]           :EndIf
[12]       :EndIf
[13]       (¯1↑level)←1+¯1↑level
[14]   :Until i>1⊃⍴refs
[15]   html,←⊂'</ol>'
[16]  ⍝Done
     ∇

4. CodeBrowser.AddParameters (17 lines)

     ∇ html←AddParameters parms;mat;toc;header;row
[1]    html←''
[2]    :If parms.showParms
[3]        mat←parms.∆List
[4]        toc←mat[;1]~¨' '
[5]        mat⌿⍨←~toc∊⊂'refs'      ⍝ Strictly speaking these are not parameters
[6]        row←toc⍳⊂'info'
[7]        mat[row;2]←⊂Max 2⊃mat[row;]
[8]        row←toc⍳⊂'caption'
[9]        mat[row;2]←⊂Max 2⊃mat[row;]
[10]       row←toc⍳⊂'footer'
[11]       mat[row;2]←⊂Max 2⊃mat[row;]
[12]       html←({{'<tr>',⍵,'</tr>'}⊃,/{'<td>',(⍕⍵),'</td>'}¨⍵}¨↓mat)
[13]       header←⊂'<tr><th>Name</th><th>Setting</th></tr>'
[14]       html←('<div id="parameters">' '<hr>' '<h2 class="center">Parameters</h2>' '<table id="parms">'),header,(⊂'<tbody>'),html,'</tbody>' '</table>' '</div>'
[15]   :EndIf
[16]  ⍝Done
     ∇

5. CodeBrowser.CollectAplObjects (6 lines)

     ∇ {r}←level CollectAplObjects(parms collect);buff;ref;For;level
[1]    r←⍬
[2]    :For ref :In parms.refs
[3]        level CollectAplObjects_ ref parms collect
[4]    :EndFor
[5]   ⍝Done
     ∇

6. CodeBrowser.CollectAplObjects_ (11 lines)

     ∇ {r}←level CollectAplObjects_(ref parms collect);EndIf;lists;refs
[1]    r←⍬
[2]    lists←level CreateToc ref parms collect
[3]    level CollectAplObjects__ lists ref parms collect
[4]    :If 0≠≢lists.containers
[5]    :AndIf parms.recursive
[6]        refs←ref.⍎¨lists.containers
[7]    :AndIf 0<≢refs←(0<≢¨⍕¨refs)/refs
[8]        ((⊂level),¨⍳⍴lists.containers){⍺ CollectAplObjects_ ⍵ parms collect}¨refs
[9]    :EndIf
[10]  ⍝Done
     ∇

7. CodeBrowser.CollectAplObjects__ (17 lines)

     ∇ {r}←level CollectAplObjects__(lists ref parms collect);i;html;names;k;name;captions
[1]    r←⍬
[2]    ReportRefs ref
[3]    html←''
[4]    captions←'Functions:' 'Operators:' 'Scripts:' 'Variables:'
[5]    :For i :In ⍳≢lists.(fns opr scripts variables)
[6]        :If 0≠≢names←i⊃lists.(fns opr scripts variables)
[7]            html,←⊂'<p class="type">',(i⊃captions),'</p>'
[8]            :For k :In ⍳⍴names
[9]                name←k⊃names
[10]               html,←level CollectFnsAndOprAndScriptsAndVars ref name parms k collect
[11]           :EndFor
[12]       :EndIf
[13]   :EndFor
[14]   html,←⊂'<div id="',(GetBookmark_ID parms),'"></div>'
[15]   IncrementBookMarkCounter parms
[16]   r←WriteHTML html
     ∇

8. CodeBrowser.CollectFnsAndOpr (20 lines)

     ∇ r←level CollectFnsAndOpr(ref name parms collect i);body;no;caption;target
[1]    r←''
[2]    :If ¯3≠≡body←(⎕UCS 13)A.Split ref.⎕VR name
[3]        body←ExchangeHtmlSpecialChars body
[4]        r,←⊂'<div class="bookmarktarget" ',(collect MakeID(⍕ref),'.',name),'>'
[5]        r,←⊂'<div id="',(GetBookmark_ID parms),'" class="code_block">'
[6]        caption←MakeBreadCrumb collect.remove RemoveLevels⍕ref
[7]        r,←⊂'<button title="Hide" class="accordion expanded">Hide</button>'
[8]        target←'bookmark_',¯5↑'00000',⍕parms.bookmarkCounter-1
[9]        r,←⊂'<button title="Brings previous object to the top" onClick="jump2bookmark(''',target,''')">Previous</button>'
[10]       target←'bookmark_',¯5↑'00000',⍕parms.bookmarkCounter+1
[11]       r,←⊂'<button title="Brings next object to the top" onClick="jump2bookmark(''',target,''')">Next</button>'
[12]       r,←⊂'<p class="caption">',(⍕i),'. ',caption,'.',name,' (',(⍕¯1+≢body),' lines)</p>'
[13]       r,←⊂'<div class="accordion-content">'
[14]       (1⊃body)←'<pre><code>',1⊃body
[15]       r,←body,⊂'</code></pre>'
[16]       r,←'</div>' '</div>' '</div>'
[17]       IncrementBookMarkCounter parms
[18]   :EndIf
[19]  ⍝Done
     ∇

9. CodeBrowser.CollectFnsAndOprAndScriptsAndVars (11 lines)

     ∇ r←level CollectFnsAndOprAndScriptsAndVars(ref name parms i collect);body;no;caption
[1]    r←''
[2]    :Select ⊃ref.⎕NC name
[3]    :Case 9
[4]        r←level CollectScript ref name parms collect i
[5]    :Case 2
[6]        r←level CollectVariable ref name parms collect i
[7]    :Else
[8]        r←level CollectFnsAndOpr ref name parms collect i
[9]    :EndSelect
[10]  ⍝DoneColl
     ∇

10. CodeBrowser.CollectScript (22 lines)

     ∇ r←level CollectScript(ref name parms collect i);body;no;caption;target
[1]    r←''
[2]    :If 2=≡body←ref.⎕SRC ref.⍎name
[3]        body←(,¨'<>&')⎕R'\&lt;' '\&gt;' '\&amp;'⍠('Greedy' 0)⊣body
[4]        no←⍕2+level
[5]        r,←⊂'<div class="bookmarktarget" ',(collect MakeID(⍕ref),'.',name),'>'
[6]        r,←⊂'<div id="',(GetBookmark_ID parms),'" class="code_block">'
[7]        caption←MakeBreadCrumb collect.remove RemoveLevels⍕ref
[8]        r,←⊂'<button title="Hide" class="accordion expanded">Hide</button>'
[9]        target←'bookmark_',¯5↑'00000',⍕parms.bookmarkCounter-1
[10]       r,←⊂'<button title="Brings previous object to the top" onClick="jump2bookmark(''',target,''')">Previous</button>'
[11]       target←'bookmark_',¯5↑'00000',⍕parms.bookmarkCounter+1
[12]       r,←⊂'<button title="Brings next object to the top" onClick="jump2bookmark(''',target,''')">Next</button>'
[13]       r,←⊂'<p class="caption">',(⍕i),'. ',caption,'.',name,' (',(⍕≢body),' lines)</p>'
[14]       r,←⊂'<div class="accordion-content">'
[15]       body←({(3+⍴,⍕⍵){⍺↑'[',(⍕⍵),']'}¨¯1+⍳⍵}⍴body),¨body
[16]       (1⊃body)←'<pre><code>',1⊃body
[17]       r,←body,⊂'</code></pre>'
[18]       r,←'</div>' '</div>' '</div>'
[19]       IncrementBookMarkCounter parms
[20]   :EndIf
[21]  ⍝Done
     ∇

11. CodeBrowser.CollectVariable (14 lines)

     ∇ r←level CollectVariable(ref name parms collect i);no;info;caption
[1]    r←''
[2]    no←⍕2+level
[3]    r,←⊂'<div ',(collect MakeID(⍕ref),'.',name),'>'
[4]    caption←MakeBreadCrumb collect.remove RemoveLevels⍕ref
[5]    r,←⊂'<p class="caption">',(⍕i),'. ',caption,'.',name,'</p>'
[6]    r,←⊂'</div>'
[7]    :Trap 6
[8]        info←'Rank: ',(⍕⍴⍴ref.⍎name),'; Shape: ',({0∊⍴⍵:'⍬' ⋄ ⍕⍵}⍴ref.⍎name),'; Depth: ',(⍕≡ref.⍎name),'; Data Representation: ',⍕⎕DR ref.⍎name
[9]        r,←⊂'<pre><code>',info,'</code></pre>'
[10]   :Else  ⍝ This may well fail because the variable is now hidden (CodeBrowser on CodeBrowser)
[11]       r←''
[12]   :EndTrap
[13]  ⍝Done
     ∇

12. CodeBrowser.CompressCSS (29 lines)

     ∇ CompressCSS←{
[1]   ⍝ Takes CSS and compresses it to a single line.
[2]   ⍝ Along the way it...
[3]   ⍝ * removes all comments
[4]   ⍝ * removes any spaces around `;:{}`
[5]   ⍝ * replaces <TAB> chars by spaces
[6]   ⍝ * removes multiple spaces
[7]   ⍝ Note that this method can have desastrous results when performed on non-valid CSS!\\
[8]   ⍝ Throws an error in case something is not right with the CSS.
[9]        css←⍵
[10]       css←{(1↓⊃,/(⎕UCS 13),¨⍵)}⍣(1≠≡css)⊣css
[11]       start←'/*'⍷css
[12]       end←'*/'⍷css
[13]       mask←~{⍵∨≠\⍵}css='"'
[14]       0=≡/+/¨mask∘/¨start end:'Cannot compress CSS: number of occurrences of /* and */ are different'⎕SIGNAL 11
[15]       0≠≢(∪⊃-/+\¨start end)~0 1:'Cannot compress CSS: Invalid nested comments'⎕SIGNAL 11
[16]       start∧←mask
[17]       end∧←mask
[18]       bool←~{⍵∨≠\⍵}start∨end
[19]       bool[1+⍸end]←0
[20]       css←bool/css
[21]       css←A.DMB css~⎕TC
[22]       ((css=⎕UCS 9)/css)←' '
[23]       mask←~{⍵∨≠\⍵}css='"'
[24]       b1←mask\mask/⊃∨/' :' ' ;' ' {' ' }'⍷¨⊂css
[25]       b2←mask\mask/⊃∨/': ' '; ' '{ ' '} '⍷¨⊂css
[26]       b←~b1∨0,¯1↓b2
[27]       '<style>',(b/css),'</style>'
[28]   }
     ∇

13. CodeBrowser.CreateHtml (32 lines)

     ∇ filename←CreateHtml parms;collect;WriteHTML;info
[1]    parms.bookmarkCounter←1
[2]    WriteHTML←parms.filename∘{0=≢⍵:r←⍬ ⋄ (⊂⍵)⎕NPUT ⍺ 2}
[3]    WriteHeader parms
[4]    WriteHTML'<h1>',(ExchangeHtmlSpecialChars parms.caption),'</h1>'
[5]    :If 0≠≢parms.info
[6]        info←ExchangeHtmlSpecialChars⍣(~parms.infoIsHTML)⊣parms.info
[7]        :If 0 1∊⍨≡info
[8]        :AndIf ~(⎕UCS 13)∊info
[9]            WriteHTML(⊂'<div id="info">'),({'<p>',⍵,'</p>'}¨⊆info),⊂'</div>'
[10]       :Else
[11]           info←(⎕UCS 13)A.Split⍣((⎕UCS 13)∊info)⊣info
[12]           WriteHTML(⊂'<div id="info">'),({({'<p>',⍵,'</p>'}⍵)}¨info),⊂'</div>'
[13]       :EndIf
[14]   :EndIf
[15]   collect←⎕NS''
[16]   collect.namespaces←⍬
[17]   collect.remove←⌊/{+/'.'=⍵}¨namespaces
[18]   :If parms.recursive
[19]       collect.hasMainMenu←AddMainMenu parms collect
[20]   :Else
[21]       collect.hasMainMenu←0
[22]   :EndIf
[23]   WriteHTML'<div id="',(GetBookmark_ID parms),'"></div>'
[24]   parms.bookmarkCounter+←1
[25]   1 CollectAplObjects parms collect
[26]   WriteHTML AddFooter parms
[27]   WriteHTML AddParameters parms
[28]   WriteHTML InjectJavaScriptLate ⍬
[29]   WriteHTML('</body>' '</html>')
[30]   filename←parms.filename
[31]  ⍝Done
     ∇

14. CodeBrowser.CreateOrReplaceFile (25 lines)

     ∇ {r}←CreateOrReplaceFile parms;errCounter;tno
[1]    r←⍬
[2]    :If ⎕NEXISTS parms.filename
[3]        :Trap 19
[4]            ⎕NDELETE parms.filename
[5]        :Case 19
[6]            ⎕NUNTIE((A.DTB↓⎕NNAMES)⍳⊂parms.filename)⊃⎕NNUMS
[7]            ⎕NDELETE parms.filename
[8]        :EndTrap
[9]    :EndIf
[10]   errCounter←0
[11]   :Repeat
[12]       :Trap 22
[13]           ⍝ This causes sometimes an error that goes away
[14]           ⍝ after a short delay. DropBox?!
[15]           tno←parms.filename ⎕NCREATE 0
[16]       :Else
[17]           tno←0
[18]           ⎕DL 0.2
[19]           errCounter←errCounter+1
[20]       :EndTrap
[21]   :Until (tno<0)∨5<errCounter ⍝ Try max 5 times.
[22]   'Unable to create the HTML file'⎕SIGNAL 22/⍨tno=0
[23]   ⎕NUNTIE tno
[24]  ⍝Done
     ∇

15. CodeBrowser.CreateParms (57 lines)

     ∇ r←CreateParms path
[1]   ⍝ If `path` is not empty it is assumed that this points to the CodeBrowser home directory of a user command folder.
[2]   ⍝ | Name             | Description | Options/flag |
[3]   ⍝ |:-----------------|:------------|:-------------|
[4]   ⍝ | `backgroundColorPrint` | Set this to 0 if you don't want background color when printing. | --- |
[5]   ⍝ | `caption`        | Defaults to the list of namespaces specified by the user. | `-caption |
[6]   ⍝ | `cssfilename`    | Location of the CSS file. | --- |
[7]   ⍝ | `filename`       | If not set this defaults to a temp file name. | `-filename` |
[8]   ⍝ | `footer`         | No default. Text string added to the bottom of the HTML file. | `-footer` |
[9]   ⍝ | `ignore`         | Use this to ignore, say, a help system etc.<<br>>Text vector with comma-separated fully qualified namespace names. | `-ignore` |
[10]  ⍝ | `ignoreEmpty`    | Boolean that defaults to 1 menaing that empty containers are ignored. | --- |
[11]  ⍝ | `ignoreTatinPkgs`| Boolean that decided whether #._tatin (or ⎕SE._tatin) should be ignored |
[12]  ⍝ | `info`           | If not empty this is shown under the caption with ID="info". | `-info` |
[13]  ⍝ | `infoIsHTML`     | Boolean that defaults to 0, meaning that any `<` becomes `&lt;`.<<br>>Typically used for HTML that was generated by the `MarkAPL` class. |
[14]  ⍝ | `lang`           | Specifies the language; defaults to "en". | `-lang` |
[15]  ⍝ | `lines`          | Number of lines to be displayed. Defaults to no restriction |
[16]  ⍝ | `linkcssfile`    | Boolean that defaults to 0 menaing that contents of `cssfile` is embedded. | --- |
[17]  ⍝ | `namespaces`     | Will be becomes the namespaces to be scanned. Is read-only.| --- |
[18]  ⍝ | `printFontSize`  | Base font size in pt. | `-pfs` |
[19]  ⍝ | `processFunctions`   | Boolean that defaults to 1. | `-obj=f` |
[20]  ⍝ | `processGuiInstances | Boolean that defaults to 0. | `-obj=g` |
[21]  ⍝ | `processOperators`   | Boolean that defaults to 1. | `-obj=o` |
[22]  ⍝ | `processScripts` | Boolean that defaults to 1. Regards classes, interfaces and scripted namespaces. | `-obj=s` |
[23]  ⍝ | `processVars`    | Boolean that defaults to 1. | `-obj=v` |
[24]  ⍝ | `recursive`      | Boolean that defaults to 1, meaning that sub-namespaces will be scanned as well. | `-r=1` |
[25]  ⍝ | `showParms`      | Boolean that defaults to 0. Specify 1 to append a table with parameters. | `-p` |
[26]  ⍝ | `twoSidedPrint`  | Boolean that defaults to 0. If 1 the left margin is always larger than the right one.| `-twosided` |
[27]  ⍝ | `version`        | Text vector with version number and version data. Is read-only| --- |
[28]  ⍝ | `viewInBrowser`  | Boolean that defaults to 0. Specify 1 for displaying the HTML in your default browser. | `-view` |
[29]   r←⎕NS''
[30]   r.backgroundColorPrint←1
[31]   r.caption←¯1
[32]   r.cssfilename←GetCssFilename path
[33]   r.filename←''
[34]   r.footer←''
[35]   r.ignore←''
[36]   r.ignoreEmpty←1
[37]   r.ignoreTatinPkgs←1
[38]   r.info←''
[39]   r.infoIsHTML←0
[40]   r.lang←'en'
[41]   r.lines←¯1
[42]   r.linkcssfile←0
[43]   r.namespaces←''
[44]   r.printFontSize←8
[45]   r.processFunctions←1
[46]   r.processGuiInstances←0
[47]   r.processOperators←1
[48]   r.processScripts←1
[49]   r.processVars←1
[50]   r.recursive←1
[51]   r.showParms←0
[52]   r.twoSidedPrint←0
[53]   r.version←{(1⊃⍵),' ',(2⊃⍵),' from ',(3⊃⍵)}Version
[54]   r.viewInBrowser←0
[55]   r.⎕FX'r←∆List' 'r←{⍵,[1.5]⍎¨⍵}↓⎕nl 2' 'r←(~(r[;1]~¨'' '')∊''refs'' ''bookmarkCounter'')⌿r'
[56]   ⍝Done
     ∇

16. CodeBrowser.CreateToc (42 lines)

     ∇ lists←level CreateToc(ref parms collect);lists;width;caption;flag;html;buff
[1]    lists←⎕NS''                ⍝ All lists: functions, operators, non-scripted namespaces (containers)
[2]    lists.(fns opr scripts variables containers)←⊂''
[3]    :If collect.hasMainMenu
[4]        caption←(FormatLevel level),MakeBreadCrumb collect.remove RemoveLevels⍕ref
[5]        html←⊂caption{'<h3 id="',(collect.remove RemoveLevels ⍵),'">',⍺,'</h3>'}⍕ref
[6]    :Else
[7]        html←''
[8]    :EndIf
[9]    flag←1
[10]   :If 0<≢↓ref.⎕NL 2 3 4 9
[11]       width←⍕6⌈⌈0.8×⌈/≢¨↓ref.⎕NL 9,GetNameClasses parms
[12]       (buff flag)←HandleContainers ref width flag lists parms collect
[13]       html,←buff
[14]       :If parms.processFunctions
[15]       :AndIf 0≠≢lists.fns←' '~¨⍨↓ref.⎕NL 3
[16]       :AndIf 0≠≢lists.fns←(3.3≠⊃∘ref.⎕NC¨⊂¨lists.fns)/lists.fns
[17]           (html flag)←html OpenNavSub flag
[18]           html,←CreateToc_ ref parms lists.fns'Function'collect width
[19]       :EndIf
[20]       :If parms.processOperators
[21]       :AndIf 0≠≢lists.opr←' '~¨⍨↓ref.⎕NL 4
[22]       :AndIf 0≠≢lists.opr←(4.3≠⊃∘ref.⎕NC¨⊂¨lists.opr)/lists.opr
[23]           (html flag)←html OpenNavSub flag
[24]           html,←CreateToc_ ref parms lists.opr'Operator'collect width
[25]       :EndIf
[26]       :If parms.processScripts
[27]       :AndIf 0≠≢lists.scripts←ListScriptsIn ref
[28]       :AndIf 0≠≢lists.scripts←(~(ref.{0∊⍴⊃,/⍵:⍵ ⋄ ⍎¨⍵}lists.scripts)∊parms.ignore)/lists.scripts
[29]           (html flag)←html OpenNavSub flag
[30]           html,←CreateToc_ ref parms lists.scripts'Script'collect width
[31]       :EndIf
[32]       :If parms.processVars
[33]       :AndIf 0≠≢lists.variables←' '~¨⍨↓ref.⎕NL 2
[34]           (html flag)←html OpenNavSub flag
[35]           html,←CreateToc_ ref parms lists.variables'Variable'collect width
[36]       :EndIf
[37]       html,←(~flag)/⊂'</nav>'
[38]   :EndIf
[39]  ⍝ Collapsible: html,←⊂'</div>'
[40]   {}WriteHTML html
[41]  ⍝Done
     ∇

17. CodeBrowser.CreateToc_ (8 lines)

     ∇ html←CreateToc_(ref parms list title collect width)
[1]    html←''
[2]    html,←⊂'<div class="toclist">'
[3]    html,←⊂'<p><b>',title,(((1<⍴list)/'s'),': ',⍕⊃⍴list),'</b></p>'
[4]    html,←⊂'<div>'
[5]    html,←(ref{'<div style="width:',width,'em;"><a ',(collect MakeBookmarkRef(⍕⍺),'.',{⍵↓⍨⍵⍳' '}⍵),'>',⍵}¨{(⍕¨⍳⍴⍵),¨'. '∘,¨⍵}list),¨⊂'</a></div>'
[6]    html,←'</div>' '</div>'
[7]   ⍝Done
     ∇

18. CodeBrowser.ExchangeHtmlSpecialChars (4 lines)

     ∇ ExchangeHtmlSpecialChars←{
[1]        11::(,¨'<>&')⎕R'\&lt;' '\&gt;' '\&amp;'⍠('Greedy' 0)⊣↓⎕FMT ⍵
[2]        (,¨'<>&')⎕R'\&lt;' '\&gt;' '\&amp;'⍠('Greedy' 0)⊣⍵
[3]    }
     ∇

19. CodeBrowser.FormatDate (5 lines)

     ∇ FormatDate←{
[1]        date←⍵
[2]        ' '=1↑0⍴date:date
[3]        10↑A.FormatDateTime date
[4]    }
     ∇

20. CodeBrowser.FormatLevel (3 lines)

     ∇ FormatLevel←{
[1]        (⊃{⍺,'.',⍵}/⍕¨⍵),'. '
[2]    }
     ∇

21. CodeBrowser.GetBookmark_ID (4 lines)

     ∇ r←GetBookmark_ID parms
[1]   ⍝ Returns an ID that can be used as a bookmark ID.
[2]    r←'bookmark_',¯5↑'00000',⍕parms.bookmarkCounter
[3]   ⍝Done
     ∇

22. CodeBrowser.GetCSS (15 lines)

     ∇ css←GetCSS parms;against;bool;row;replaceBy
[1]    css←⊃F.NGET(1⊃,parms.cssfilename)1
[2]    against←'font-size: ',(⍕parms.printFontSize),'pt;'
[3]    css←'font-size: *8pt;'⎕R against⊣css
[4]    css←{'-webkit-print-color-adjust: *exact;'⎕R''⊣⍵}⍣(⊃~parms.backgroundColorPrint)⊣css
[5]    :If 0≠parms.twoSidedPrint
[6]        against←'@page :left {margin: 20mm 20mm 20mm 10mm;}'
[7]        css←'@page :left *{margin: *20mm *20mm *20mm *20mm;}'⎕R against⊣css
[8]    :EndIf
[9]    :If 0<+/bool←∨/¨'.accordion-content'∘⍷¨css
[10]       row←⍸bool
[11]       replaceBy←'max-height: ',(⍕parms.lines),'em;'
[12]       css[row]←replaceBy∘{replaceBy←⍺ ⋄ 'max-height: {0,}([1-9][0-9]){1,2}em;'⎕R replaceBy⍠('Greedy' 0)⊣⍵}¨css[row]
[13]   :EndIf
[14]  ⍝Done
     ∇

23. CodeBrowser.GetCodeMirrorLib (27 lines)

     ∇ GetCodeMirrorLib←{
[1]        ⍝ NOT SUPPORTED (yet)
[2]        parms←⍵
[3]        0=parms.codeMirrorLib:''
[4]        r←''
[5]        r,←⊂'<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/codemirror.js"></script>'
[6]        r,←⊂'<link  href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/codemirror.css" rel="stylesheet">'
[7]        r,←⊂'<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.33.0/mode/apl/apl.js"></script>'
[8]        r,←⊂'<style>'
[9]        r,←⊂'.CodeMirror{height:auto; border: 1px solid #eee;}'
[10]       r,←⊂'</style>'
[11]       r,←⊂'     <script>'
[12]       r,←⊂'(function(){'
[13]       r,←⊂'nodes=document.getElementsByTagName(''code'')'
[14]       r,←⊂'Array.from(nodes).forEach(node=>{'
[15]       r,←⊂'    if(node.parentNode.tagName===''PRE''){'
[16]       r,←⊂'        let pre=node.parentNode;'
[17]       r,←⊂'        let ta=document.createElement("TEXTAREA");'
[18]       r,←⊂'        ta.value=node.innerText;'
[19]       r,←⊂'        pre.parentNode.replaceChild(ta,pre);'
[20]       r,←⊂'        CodeMirror.fromTextArea(ta);'
[21]       r,←⊂'    }'
[22]       r,←⊂'})'
[23]       r,←⊂'})();'
[24]       r,←⊂'</script>'
[25]       r
[26]   }
     ∇

24. CodeBrowser.GetCssFilename (14 lines)

     ∇ r←GetCssFilename path;F
[1]    F←##.FilesAndDirs
[2]    :If 0=≢path
[3]        :If 9=##.⎕NC'CiderConfig'
[4]            r←##.CiderConfig.HOME,'/Files/codebrowser_styles.css'
[5]        :ElseIf 9=##.⎕NC'TatinVars'
[6]            r←##.TatinVars.HOME,'/Files/codebrowser_styles.css'
[7]        :Else
[8]            r←HOME,'/codebrowser_styles.css'
[9]        :EndIf
[10]   :Else
[11]       ((path∊'/\')/path)←F.CurrentSep
[12]       r←path,F.CurrentSep,'codebrowser_styles.css'
[13]   :EndIf
     ∇

25. CodeBrowser.GetNameClasses (3 lines)

     ∇ r←GetNameClasses parms
[1]    r←parms.(processVars processFunctions processOperators processScripts)/2 3 4 9
[2]   ⍝Done
     ∇

26. CodeBrowser.GetSubNamespaces (39 lines)

     ∇ r←{y}GetSubNamespaces ref;list;level;bool
[1]    level←0
[2]    :If 0=⎕NC'y'
[3]        ⎕SHADOW'parms'
[4]        parms←CreateParms''
[5]    :ElseIf 326=⎕DR y
[6]        ⎕SHADOW'parms'
[7]        parms←y
[8]    :Else
[9]        level←y
[10]   :EndIf
[11]   r←⊂level ref
[12]   :If 0≠≢list←' '~¨⍨↓ref.⎕NL 9.1 9.2                                 ⍝ All namespaces
[13]   :AndIf 0≠≢list←(ref.{((⍕⎕THIS),'.',⍵)≡⍕⍎⍵}¨list)/list              ⍝ We are not interested in refs pointing elsewhere
[14]       list←ref.⍎¨list                                                ⍝ Make them refs
[15]       list~←ref,{0∊⍴⊃,/⍵:⍵ ⋄ ⍎¨⍵}MassageNameLists parms.ignore       ⍝ Remove any self references and those to be ignored
[16]   :AndIf 0≠≢list
[17]       :If parms.ignoreTatinPkgs
[18]       :AndIf 0<≢parms.namespaces
[19]       :AndIf ∧/parms.namespaces≢¨⊂'_tatin'
[20]           list←(~(⍕¨list)∊'#._tatin' '⎕SE._tatin')/list              ⍝ Remove Tatin packages
[21]       :EndIf
[22]   :AndIf 0≠≢list
[23]   :AndIf 0≠≢list←(~'['∊¨⍕¨list)/list                                 ⍝ Remove unnamed namespaces and instances
[24]   :AndIf 0≠≢list←({16::1 ⋄ 0⊣⎕SRC ⍵}¨list)/list                      ⍝ Remove scripted ones
[25]       :If 0∊bool←'Namespace'∘≡¨ref.{⍵ ⎕WG'Type'}¨list
[26]           :If parms.processGuiInstances
[27]               bool∨←(~bool)\ref.{⍵ ⎕WG'KeepOnClose'}¨(~bool)/list
[28]           :EndIf
[29]           list←bool/list
[30]       :EndIf
[31]   :AndIf 0≠≢list
[32]       :If parms.ignoreEmpty
[33]           list←({0≠≢⍵.⎕NL⍳16}¨list)/list
[34]       :EndIf
[35]   :AndIf 0≠≢list
[36]       r←((⊂level,ref),⊃,/(1+level)GetSubNamespaces¨list)~⊂''
[37]   :EndIf
[38]  ⍝Done
     ∇

27. CodeBrowser.HandleContainers (27 lines)

     ∇ (html flag)←HandleContainers(ref width flag lists parms collect);html;these;recursiveMsg
[1]    html←''
[2]    :If 0<≢lists.containers←' '~¨⍨↓ref.⎕NL 9
[3]    :AndIf 0<≢lists.containers←({16::1 ⋄ 0⊣⎕SRC ⍵}¨ref.⍎¨lists.containers)/lists.containers
[4]    :AndIf 0<≢lists.containers←(~(ref.⍎¨lists.containers)∊parms.ignore)/lists.containers
[5]    :AndIf 0<≢lists.containers←(ref≠ref.⍎¨lists.containers)/lists.containers
[6]    :AndIf 0<≢lists.containers←((~'['∊¨⍕¨ref.⍎¨lists.containers))/lists.containers
[7]    :AndIf 0<≢lists.containers←(~(these←ref.⍎¨lists.containers)∊collect.namespaces)/lists.containers
[8]        lists←RemoveGuiInstances lists ref parms
[9]    :AndIf 0<≢lists.containers
[10]       lists←RemoveEmptyContainers lists ref parms
[11]   :AndIf 0<≢lists.containers
[12]       lists←RemoveTatinPackages lists ref parms
[13]   :AndIf 0<≢lists.containers
[14]       collect.namespaces,←these
[15]       flag←{0⊣html,←⊂'<nav class="sub">'}⍣1⊣1
[16]       html,←⊂'<div class="toclist">'
[17]       recursiveMsg←(~collect.hasMainMenu)/' (not scanned)'
[18]       html,←⊂'<p><b>Sub namespace',((1<⍴lists.containers)/'s'),': ',(⍕⊃⍴lists.containers),'</b>',recursiveMsg,'</p>'
[19]       html,←⊂'<div>'
[20]       :If parms.recursive
[21]           html,←⊃,/ref{(no name)←⍵ ⋄ ⊂'<div style="width:',width,'em;"><a ',(collect MakeBookmarkRef(⍕⍺),'.',name),'>',(⍕no),'. ',name,'</a></div>'}¨(⍳≢lists.containers),¨⊂¨lists.containers
[22]       :Else
[23]           html,←lists.containers{('<div style="width:',width,'em;">'),(⍕⍵),'. ',⍺,'</div>'}¨⍳≢lists.containers
[24]       :EndIf
[25]       html,←'</div>' '</div>'
[26]   :EndIf
     ∇

28. CodeBrowser.HandleParms (50 lines)

     ∇ (msg en)←HandleParms(parms namespaces);DE
[1]   ⍝ Returns either `'' 0` or an error message in `msg` and 11 in `en`.
[2]    DE←11 ⍝ DOMAIN ERROR
[3]    msg←en←⍬
[4]    namespaces←'⎕se'⎕R'⎕SE'⊣namespaces
[5]    :If ~∧/((,¨namespaces)∊,¨'#' '⎕SE')∨⊃¨9=⎕NC¨namespaces
[6]        msg←'No namespace(s) specified'
[7]        en←DE
[8]        :Return
[9]    :EndIf
[10]   :Trap 0
[11]       parms.refs←⍎¨namespaces
[12]   :Else
[13]       msg←'Something went wrong - check the namespace list'
[14]       en←DE
[15]       :Return
[16]   :EndTrap
[17]   :If 1≥|≡parms.cssfilename
[18]       parms.cssfilename←A.DMB parms.cssfilename
[19]       :If ∨/' ,'∊parms.cssfilename
[20]           ((' '=parms.cssfilename)/parms.cssfilename)←','
[21]           parms.cssfilename←','A.Split parms.cssfilename
[22]       :EndIf
[23]       parms.cssfilename←⊆parms.cssfilename
[24]   :EndIf
[25]   parms.filename{~0∊⍴⍺:⍺ ⋄ (¯4↓F.GetTempFilename''),'.html'}←⍬
[26]   parms.caption{~(⊂⍺)∊¯1 '':⍺ ⋄ 1=⍴,⍵:⍕⍵ ⋄ ⊃,/{⍺,', ',⍵}/⍵}←namespaces
[27]   CreateOrReplaceFile parms
[28]   :Trap 0
[29]       parms.ignore←{0∊⍴⊃,/⍵:⍵ ⋄ ⍎¨⍵}MassageNameLists parms.ignore
[30]   :Else
[31]       msg←'Something went wrong - check -ignore'
[32]       en←DE
[33]   :EndTrap
[34]   :If '⋄'∊parms.info
[35]       parms.info←'⋄'A.Split parms.info
[36]   :EndIf
[37]   :If ~(⊂parms.infoIsHTML)∊0 1
[38]       msg←'"infoIsHTML" is not a Boolean'
[39]       en←DE
[40]   :EndIf
[41]   :If ~(⊂parms.processGuiInstances)∊0 1
[42]       msg←'"processGuiInstances" is not a Boolean'
[43]       en←DE
[44]   :EndIf
[45]   :If ~(≡parms.info)∊0 1 2
[46]       msg←'"info" is neither a text vector nor a vector of text vectors'
[47]       en←DE
[48]   :EndIf
[49]  ⍝Done
     ∇

29. CodeBrowser.IncrementBookMarkCounter (3 lines)

     ∇ {parms}←IncrementBookMarkCounter parms
[1]    parms.bookmarkCounter+←1
[2]   ⍝Done
     ∇

30. CodeBrowser.Init (4 lines)

     ∇ {r}←Init dummy
[1]    r←⍬
[2]    A←##.APLTreeUtils2 ⋄ F←##.FilesAndDirs
[3]   ⍝Done
     ∇

31. CodeBrowser.InitializeUserCommand (13 lines)

     ∇ {r}←InitializeUserCommand dummy
[1]   ⍝ Propagate refs depending on circumstances
[2]    r←⍬
[3]    :If 0=⎕NC'A'                                   ⍝ It's a Tatin package then
[4]        :If '⎕'=⊃⊃⎕XSI
[5]            A←⎕SE._CodeBrowser.APLSource.APLTreeUtils2
[6]            F←⎕SE._CodeBrowser.APLSource.FilesAndDirs
[7]        :Else
[8]            A←##.APLTreeUtils2
[9]            F←##.FilesAndDirs
[10]       :EndIf
[11]   :EndIf
[12]  ⍝Done
     ∇

32. CodeBrowser.InjectJavaScriptEarly (9 lines)

     ∇ html←InjectJavaScriptEarly dummy
[1]   ⍝ This code needs to go into the <head>er of the HTML page.
[2]    html←''
[3]    html,←⊂'<script>'
[4]    html,←⊂'function jump2bookmark(id){'
[5]    html,←⊂'    var obj = document.getElementById(id);'
[6]    html,←⊂'    obj.scrollIntoView({behavior: "smooth", block: "start"});'
[7]    html,←⊂'}'
[8]    html,←⊂'</script>'
     ∇

33. CodeBrowser.InjectJavaScriptLate (40 lines)

     ∇ html←InjectJavaScriptLate dummy
[1]   ⍝ The transition does not work well on large objects (several hundred lines) at all.
[2]   ⍝ May be one day CSS gets better options for this, or we implement a pure JavaScript solution?!
[3]   ⍝ This code needs to go to the bottom of the HTML page!
[4]    html←''
[5]    html,←⊂'<script>'
[6]    html,←⊂'var acc = document.getElementsByClassName("accordion");'
[7]    html,←⊂'var i;'
[8]    html,←⊂'for (i = 0; i < acc.length; i++) {'
[9]    html,←⊂'    acc[i].addEventListener("click", function() {'
[10]   ⍝ html,←⊂'debugger;'
[11]   html,←⊂'         var content = lastSibling(this);'
[12]   html,←⊂'         if (this.classList.contains("expanded")) {'
[13]  ⍝ We need to collapse it:
[14]   html,←⊂'               this.classList.add("collapsed");'
[15]   html,←⊂'               this.classList.remove("expanded");'
[16]   ⍝html,←⊂'               content.style.transition = "max-height 1s ease-in 0s";'
[17]   html,←⊂'               content.style.maxHeight = 0;'
[18]   html,←⊂'               this.innerHTML = "Show"'                 ⍝ "↕"'
[19]   html,←⊂'               this.setAttribute("title", "Show the code block");'
[20]   html,←⊂'           } else {'
[21]  ⍝ We need to expanded it:
[22]   ⍝html,←⊂'               content.style.transition = "max-height 0.2s ease-out 0s";'
[23]   html,←⊂'               content.style.maxHeight = content.scrollHeight + "px";'
[24]   html,←⊂'               this.classList.add("expanded");'
[25]   html,←⊂'               this.classList.remove("collapsed");'
[26]   html,←⊂'               this.innerHTML = "Hide"'
[27]   html,←⊂'               this.setAttribute("title", "Hide the code block");'
[28]   html,←⊂'         } '
[29]   html,←⊂'    });'
[30]   html,←⊂'}'
[31]   html,←⊂'function lastSibling(node){'
[32]   html,←⊂'   var tempObj=node.parentNode.lastChild;'
[33]   html,←⊂'   while(tempObj.nodeType!=1 && tempObj.previousSibling!=null){'
[34]   html,←⊂'   tempObj=tempObj.previousSibling;'
[35]   html,←⊂'   }'
[36]   html,←⊂'   return (tempObj.nodeType==1)?tempObj:false;'
[37]   html,←⊂'}'
[38]   html,←⊂'</script>'
[39]  ⍝Done
     ∇

34. CodeBrowser.Install (4 lines)

     ∇ Install
[1]   ⍝ Checks whether the packages required by CodeBrowser are already installed in the standard folder for
[2]   ⍝ packages required by any Dyalog user command.
[3]    ∘∘∘
     ∇

35. CodeBrowser.ListScriptsIn (7 lines)

     ∇ ListScriptsIn←{
[1]        l1←ref{0∊≢⍵:⍵ ⋄ ⍵/⍨⍺.{((⍕⎕THIS),'.',⍵)≡⍕⍎⍵}¨⍵}' '~¨⍨↓ref.⎕NL 9.4 9.5   ⍝ Class and interfaces
[2]        l2←ref{0∊≢⍵:⍵ ⋄ ⍵/⍨⍺.{((⍕⎕THIS),'.',⍵)≡⍕⍎⍵}¨⍵}' '~¨⍨↓ref.⎕NL 9.1       ⍝ All namespaces
[3]        l2←(ref.{0::0 ⋄ 1⊣⍴⎕SRC⍎⍵}¨l2)/l2
[4]        0∊⍴l2:l1
[5]        {⍵[⍋↑⍵]}l1,l2
[6]    }
     ∇

36. CodeBrowser.MakeBookmarkRef (4 lines)

     ∇ r←collect MakeBookmarkRef path
[1]    path←collect.remove RemoveLevels path
[2]    r←'href="#',path,'"'
[3]   ⍝Done
     ∇

37. CodeBrowser.MakeBreadCrumb (7 lines)

     ∇ MakeBreadCrumb←{
[1]        parts←'.'A.Split ⍵
[2]        urls←{(⍳⍴⍵)↑¨⊂⍵}parts
[3]        top←{'<a href="#',(⊃{⍺,'.',⍵}/⍵),'">'}¨urls
[4]        r←top,¨parts
[5]        ¯1↓⊃,/r,¨⊂'</a>.'
[6]    }
     ∇

38. CodeBrowser.MakeID (4 lines)

     ∇ r←collect MakeID ref
[1]    ref←collect.remove RemoveLevels ref
[2]    r←'id="',ref,'"'
[3]    ⍝Done
     ∇

39. CodeBrowser.MassageNameLists (9 lines)

     ∇ MassageNameLists←{
[1]   ⍝ (⊂'#.abc') ←→ MassageNameLists '#.abc'
[2]   ⍝ ('#.abc' '#.x' '#.y') ←→ MassageNameLists '#.abc  #.x , #.y'
[3]   ⍝ ('#.abc' '#.x' '#.y') ←→ MassageNameLists #.abc  #.x #.y'
[4]        1<|≡⍵:⍕¨⍵
[5]        r←⍕,⍵
[6]        ((','=r)/r)←' '
[7]        ' 'A.Split A.DMB r
[8]    }
     ∇

40. CodeBrowser.Max (5 lines)

     ∇ Max←{
[1]        ⍺←80
[2]        ⍺>⍴⍵:⍵
[3]        (⍺⍴⍵),'...'
[4]    }
     ∇

41. CodeBrowser.MoreHelp (3 lines)

     ∇ r←MoreHelp dummy
[1]    {}⎕SE.UCMD']ADOC ⎕se._CodeBrowser'
[2]    r←'Watch your default browser'
     ∇

42. CodeBrowser.OpenInDefaultBrowser (6 lines)

     ∇ OpenInDefaultBrowser←{
[1]        6::0
[2]        ⎕USING←'' 'System' 'System.Diagnostics,System.dll'
[3]        proc←Process.Start,⊂⍵
[4]        1:proc←proc     ⍝ was a NEW process started = True?
[5]    }
     ∇

43. CodeBrowser.OpenNavSub (5 lines)

     ∇ (html flag)←html OpenNavSub flag
[1]    :If flag
[2]        html,←⊂'<nav class="sub">'
[3]        flag←0
[4]    :EndIf
     ∇

44. CodeBrowser.Public (2 lines)

     ∇ r←Public
[1]    r←'Run' 'CreateParms' 'Selfie' 'MoreHelp'
     ∇

45. CodeBrowser.RemoveEmptyContainers (8 lines)

     ∇ lists←RemoveEmptyContainers(lists ref parms);bool;list
[1]   ⍝ Remove all empty containers unless parms.ignoreEmpty is 0.
[2]    :If parms.ignoreEmpty
[3]        list←ref.⍎¨lists.containers
[4]        :If 0∊bool←{~0∊⍴⍵.⎕NL⍳16}¨list
[5]            lists.containers←bool/lists.containers
[6]        :EndIf
[7]    :EndIf
     ∇

46. CodeBrowser.RemoveGuiInstances (11 lines)

     ∇ lists←RemoveGuiInstances(lists ref parms);bool;list
[1]   ⍝ Remove all GUI instances unless parms.processGuiInstances is 1.
[2]   ⍝ Even then everything that does not carry `KeepOnClose←` is
[3]   ⍝ removed
[4]    list←ref.⍎¨lists.containers
[5]    :If 0∊bool←'Namespace'∘≡¨list ⎕WG¨⊂'Type'
[6]        :If parms.processGuiInstances
[7]            bool∨←(~bool)\ref.{⍵ ⎕WG'KeepOnclose'}¨(~bool)/list
[8]        :EndIf
[9]        lists.containers←bool/lists.containers
[10]   :EndIf
     ∇

47. CodeBrowser.RemoveLevels (8 lines)

     ∇ RemoveLevels←{
[1]        noOf←⍺
[2]        path←⍵
[3]        (,'#')≡,path:path
[4]        buff←+\'.'=⍵
[5]        path←(+/∧\noOf>buff)↓path
[6]        ('.'=1⍴path)↓path
[7]    }
     ∇

48. CodeBrowser.RemoveRefs (6 lines)

     ∇ list←parent RemoveRefs list;bool
[1]   ⍝ Remove scripts that are just references.
[2]    :If 0<+/bool←9=parent.⎕NC list        ⍝ Only those are potentially refs
[3]        bool←bool∧bool\parent.{((⍕⎕THIS),'.',⍵)≡⍕⍎⍵}¨↓bool⌿list
[4]        list←bool⌿list
[5]    :EndIf
     ∇

49. CodeBrowser.RemoveTatinPackages (6 lines)

     ∇ lists←RemoveTatinPackages(lists ref parms);bool
[1]   ⍝ Remove all Tatin packages except when the user asks for them explicitly
[2]    :If parms.ignoreTatinPkgs
[3]    :AndIf 0=+/'⎕SE._tatin' '#._tatin'∊parms.namespaces
[4]        lists.containers←(~lists.containers≡¨⊂'_tatin')/lists.containers
[5]    :EndIf
     ∇

50. CodeBrowser.ReportRefs (11 lines)

     ∇ {r}←ReportRefs ref;html;list
[1]    r←⍬
[2]    :If 0≠≢list←' '~¨⍨↓ref.⎕NL 9.1
[3]    :AndIf 0≠≢list←(ref.{∊'['∊is←⍕⍎⍵:0 ⋄ ((⍕⎕THIS),'.',⍵)≢is}¨list)/list
[4]        html←⊂'<p class="type">References:</p>'
[5]        html,←⊂'<table class="refs">'
[6]        html,←'<tr>'∘,¨(ref.{'<td>',⍵,'</td><td>==></td><td>',({0::⍵ ⋄ ⍕⍎}⍵),'</td>'}¨list),¨⊂'</tr>'
[7]        html,←⊂'</table>'
[8]        {}WriteHTML html
[9]    :EndIf
[10]  ⍝Done
     ∇

51. CodeBrowser.Run (21 lines)

     ∇ filename←{parms}Run namespaces;refs
[1]   ⍝ Collects the code and variables in the (non-scripted) namespaces listed in `namespaces` and
[2]   ⍝ compiles an HTML page with the code in it.\\
[3]   ⍝ `namespaces` must be a text vector with fully qualified namespace name(s). You can use either
[4]   ⍝ a space or a comma as separator.\\
[5]   ⍝ `parms` is optional. If provided it must be a parameter space, typically created with `CreateParms`.\\
[6]   ⍝ Returns the name of the file the HTML is written to.\\
[7]   ⍝ The HTML page contains the CSS and JavaScript needed and is therefore fully self-contained.
[8]   ⍝ You should not attempt to view it in an outdated browser like IE9.
[9]    ⎕IO←1 ⋄ ⎕ML←1
[10]   Init ⍬
[11]   namespaces←MassageNameLists namespaces
[12]   parms←{0<⎕NC ⍵:⍎⍵ ⋄ CreateParms''}'parms'
[13]   parms.namespaces←namespaces
[14]   ⎕SIGNAL/HandleParms parms namespaces
[15]   filename←CreateHtml parms
[16]   :If parms.viewInBrowser
[17]       {}A.GoToWebPage filename
[18]   :EndIf
[19]   parms.cssfilename←{0=≢⍵:⍵ ⋄ 0 1∊⍨≡⍵:⍵ ⋄ ⊃{⍺,', ',⍵}/⍵}parms.cssfilename
[20]  ⍝Done
     ∇

52. CodeBrowser.Selfie (12 lines)

     ∇ r←Selfie dummy;parms
[1]   ⍝ Create an HTML document of CodeBrowser itself.
[2]    parms←CreateParms''
[3]    parms.caption←'CodeBrowser'
[4]    parms.info←'Contains the CodeBrowser code without the test cases.'
[5]    parms.showParms←1
[6]    parms.footer←'Created by ',⎕AN,' on ',A.FormatDateTime ⎕TS
[7]    parms.twoSidedPrint←1
[8]    parms.filename←F.GetTempPath,'/',⎕AN,'_CodeBrowser_CodeReview.html'
[9]    parms.viewInBrowser←1
[10]   r←parms Run(⍕⎕THIS)
[11]  ⍝Done
     ∇

53. CodeBrowser.Version (3 lines)

     ∇ r←Version
[1]   ⍝ See also `History`
[2]    r←'CodeBrowser' '2.0.0+81' '2022-01-17'
     ∇

54. CodeBrowser.WriteHeader (22 lines)

     ∇ {r}←WriteHeader parms;html;thisCssFile;filename
[1]    html←⊂'<!DOCTYPE html>'
[2]    html,←⊂'<html lang="',parms.lang,'">'
[3]    html,←⊂'<head>'
[4]    html,←⊂'<meta http-equiv="X-UA-Compatible" content="IE=edge" />'
[5]    html,←⊂'<meta charset="utf-8">'
[6]    html,←⊂'<title>',(ExchangeHtmlSpecialChars parms.caption),'</title>'
[7]    :If parms.linkcssfile
[8]        :For thisCssFile :In parms.cssfilename
[9]            filename←F.EnforceSlash'expand'F.NormalizePath thisCssFile
[10]           filename←':/'⎕R'|/'⊣filename
[11]           html,←⊂'<link href="file://',filename,'" rel="stylesheet">'
[12]       :EndFor
[13]   :Else
[14]       html,←⊂CompressCSS GetCSS parms
[15]   :EndIf
[16]   html,←InjectJavaScriptEarly ⍬
[17]   ⍝html,←GetCodeMirrorLib parms  ⍝ Not implemented yet   ⍝TODO⍝
[18]   html,←⊂'</head>'
[19]   html,←⊂'<body>'
[20]   r←WriteHTML html
[21]  ⍝Done
     ∇

Variables:

1. CodeBrowser.ADOC_Doc

Rank: 1; Shape: 83; Depth: 2; Data Representation: 326

2. CodeBrowser.History

Rank: 1; Shape: 18; Depth: 2; Data Representation: 326

3. CodeBrowser.buff (0 lines)


4. CodeBrowser.caption (0 lines)


5. CodeBrowser.dummy

Rank: 0; Shape: ⍬; Depth: 0; Data Representation: 83

6. CodeBrowser.flag (0 lines)


7. CodeBrowser.html

Rank: 1; Shape: 1473; Depth: 2; Data Representation: 326

9. CodeBrowser.level

Rank: 0; Shape: ⍬; Depth: 0; Data Representation: 83

10. CodeBrowser.namespaces

Rank: 1; Shape: 1; Depth: 2; Data Representation: 326

11. CodeBrowser.r

Rank: 1; Shape: 3; Depth: 2; Data Representation: 326

12. CodeBrowser.width (0 lines)


1.1. CodeBrowser.API

Functions:

1. CodeBrowser.API.CreateParms (1 lines)

     ∇ CreateParms←{⍺←⊣ ⋄ ⍺ ##.CreateParms ⍵}
     ∇

2. CodeBrowser.API.MoreHelp (1 lines)

     ∇ MoreHelp←{⍺←⊣ ⋄ ⍺ ##.MoreHelp ⍵}
     ∇

3. CodeBrowser.API.Run (1 lines)

     ∇ Run←{⍺←⊣ ⋄ ⍺ ##.Run ⍵}
     ∇

4. CodeBrowser.API.Selfie (1 lines)

     ∇ Selfie←{⍺←⊣ ⋄ ⍺ ##.Selfie ⍵}
     ∇

1.2. CodeBrowser.Admin

Functions:

1. CodeBrowser.Admin.CreateAPI (20 lines)

     ∇ {r}←{tellLink}CreateAPI flag;list1;list2
[1]   ⍝ Creates cover functions for all API functions in ##.API from ##.Public.\\
[2]   ⍝ If ⍺←1 then Link will be told.
[3]   ⍝ Without ⍺ the user will be asked whether Link should be told.
[4]    r←⍬
[5]    tellLink←{0<⎕NC ⍵:⍎⍵ ⋄ ¯1}'tellLink'
[6]    :If 0=##.⎕NC'API'
[7]        'API'##.⎕NS''
[8]    :EndIf
[9]    :If flag
[10]       :If 0<≢list1←↓##.API.⎕NL⍳16
[11]           ⎕SE.Link.Expunge¨(⊂(⍕⎕THIS),'.##.API.'),¨list1
[12]       :EndIf
[13]       list2←##.Public~'Methods' 'Public' 'GoToGitHub'
[14]       ##.API.{⍎⍵,'←{⍺←⊣ ⋄ ⍺ ##.',⍵,' ⍵}'}¨list2
[15]       :If (,1)≡,tellLink
[16]       :OrIf 1 ##.U.YesOrNo'Tell Link?'
[17]           r,←⎕SE.Link.Add¨##.API.((⊂(⍕⎕THIS),'.'),¨↓⎕NL 3)
[18]       :EndIf
[19]   :EndIf
     ∇

2. CodeBrowser.Admin.ImportCode (9 lines)

     ∇ {success}←ImportCode path;list
[1]   ⍝ Takes a path and imports everyting found. Traps any errors but prints errors to the session for them.
[2]   ⍝ Returns a scalar 0 in case their is nothing to import, otherwise a vector with 1 for success and 0
[3]   ⍝ otherwise for every item found.
[4]    success←0
[5]    :If 0<≢list←⊃⎕NINFO⍠('Wildcard' 1)('Recurse' 2)⊣path
[6]        success←{0::0,0/⎕←'Error fixing ',⍵,':',⍕⎕EN ⋄ 1⊣2 ⎕FIX'file://',⍵}¨list
[7]    :EndIf
[8]   ⍝Done
     ∇

1.3. CodeBrowser.GUI

Functions:

1. CodeBrowser.GUI.AddPosnAndSize (1 lines)

     ∇ AddPosnAndSize←{+⌿↑⍵.(Posn Size)}
     ∇

2. CodeBrowser.GUI.CheckInput (51 lines)

     ∇ (success msg)←CheckInput n;list;bool
[1]    success←0
[2]    msg←''
[3]   
[4]    :If 0∊⍴∊list←PolishNamespaceList n.namespaces.Text
[5]        ShowInStatusbar'Nothing to scan?!'
[6]        →SetFocusTo n.Scan n.namespaces
[7]    :EndIf
[8]    bool←list∊,¨'#' '⎕SE'
[9]    :If 1∊bool←~{(⍵∊,¨'#' '⎕SE')∨9.1=⎕NC∘⊂¨⍵}list
[10]       ShowInStatusbar'Scan: not a namespace: ',⊃{⍺,',',⍵}/bool/list
[11]       →SetFocusTo n.Scan n.namespaces
[12]   :EndIf
[13]   n.namespaces.Text←⊃{⍺,', ',⍵}/list
[14]  
[15]   :If ~0∊⍴list←n.toBeIgnored.Text
[16]       ((list=',')/list)←' '
[17]       list←##.A.DMB list
[18]       list←∪' '##.A.Split list
[19]       :If 1∊bool←~{((,'#')∘≡¨⍵)∨9=⎕NC¨⍵}list
[20]           ShowInStatusbar'To be ignored: not a namespace: ',⊃{⍺,',',⍵}/bool/list
[21]           →SetFocusTo n.Scan n.toBeIgnored
[22]       :EndIf
[23]       n.toBeIgnored.Text←⊃{⍺,',',⍵}/list
[24]   :EndIf
[25]  
[26]   :If ~0∊⍴n.filename.Text
[27]   :AndIf 0=##.F.IsFile n.filename.Text
[28]   :AndIf ~CreateNativeFile n.filename.Text
[29]       ShowInStatusbar'HTML filename is invalid (not pointing to a file)'
[30]       →SetFocusTo n.Parms n.filename
[31]   :EndIf
[32]  
[33]   :If ~0∊⍴n.cssFilename.Text
[34]   :AndIf 0=##.F.IsFile n.cssFilename.Text
[35]       ShowInStatusbar'CSS filename is invalid (not pointing to a file)'
[36]       →SetFocusTo n.Parms n.cssFilename
[37]   :EndIf
[38]  
[39]   :If 0=+/n.(processFns processOpr processScripts processVars).State
[40]       ShowInStatusbar'Nothing to be processed?!'
[41]       →SetFocusTo n.Parms n.processFns
[42]   :EndIf
[43]  
[44]   :If (0=n.lines.Value)∨n.lines.Value<¯1
[45]       ShowInStatusbar'"Lines" must be either a positive integer or ¯1'
[46]       →SetFocusTo n.Parms n.lines
[47]   :EndIf
[48]  
[49]   success←1
[50]  ⍝Done
     ∇

3. CodeBrowser.GUI.CopyGuiToParms (27 lines)

     ∇ {r}←CopyGuiToParms n
[1]    r←⍬
[2]    n.∆Parms.namespaces←n.namespaces.Text
[3]    n.∆Parms.ignore←n.toBeIgnored.Text
[4]    n.∆Parms.ignoreEmpty←n.ignoreEmptyNamespaces.State
[5]    n.∆Parms.ignoreTatinPkgs←n.ignoreTatinPkgs.State
[6]    n.∆Parms.recursive←n.recursive.State
[7]    n.∆Parms.processGuiInstances←n.processGuiInstances.State
[8]    n.∆Parms.filename←n.filename.Text
[9]    n.∆Parms.cssfilename←MassageCssFilename n.cssFilename.Text
[10]   n.∆Parms.linkcssfile←n.linkCssFile.State
[11]   n.∆Parms.lang←n.lang.Text
[12]   n.∆Parms.showParms←n.showParms.State
[13]   n.∆Parms.viewInBrowser←n.viewInBrowser.State
[14]   n.∆Parms.processFunctions←n.processFns.State
[15]   n.∆Parms.processOperators←n.processOpr.State
[16]   n.∆Parms.processScripts←n.processScripts.State
[17]   n.∆Parms.processVars←n.processVars.State
[18]   n.∆Parms.backgroundColorPrint←n.printBgrCol.State
[19]   n.∆Parms.twoSidedPrint←n.twoSidedPrint.State
[20]   n.∆Parms.printFontSize←⊃(//)⎕VFI n.fontSizeForPrint.Text
[21]   n.∆Parms.caption←n.caption.Text
[22]   n.∆Parms.footer←n.footer.Text
[23]   n.∆Parms.info←,n.info.Text
[24]   n.∆Parms.infoIsHTML←n.infoIsHtml.State
[25]   n.∆Parms.lines←n.lines.Value
[26]  ⍝Done
     ∇

4. CodeBrowser.GUI.CreateButtons (38 lines)

     ∇ n←CreateButtons n;∆
[1]    ∆←⊂'Button'
[2]    ∆,←⊂'Style' 'Push'
[3]    ∆,←⊂'Caption' '&Done'
[4]    ∆,←⊂'Size'(⍬ 120)
[5]    ∆,←⊂'TipObj'n.∆Tip
[6]    ∆,←⊂'Tip'('Create the HTML page, close the GUI and' 'print the HTML filename to the session')
[7]    ∆,←⊂'Attach'(4⍴'Bottom' 'Left')
[8]    n.OK←⍎'ok'n.∆Form.⎕WC ∆
[9]    n.∆Buttons←n.OK
[10]   n.OK.Posn[1]←n.∆Form.Size[1]-n.OK.Size[1]+(⌊0.5×n.∆vgap)+n.StatusMsg.##.Size[1]
[11]   n.OK.Posn[2]←n.∆hgap
[12]  
[13]   ∆←⊂'Button'
[14]   ∆,←⊂'Style' 'Push'
[15]   ∆,←⊂'Caption' 'Cancel'
[16]   ∆,←⊂'Size'(⍬ 120)
[17]   ∆,←⊂'Attach'(4⍴'Bottom' 'Left')
[18]   ∆,←⊂'TipObj'n.∆Tip
[19]   ∆,←⊂'Tip'('Close the GUI without taking any action')
[20]   n.Cancel←⍎'cancel'n.∆Form.⎕WC ∆
[21]   n.∆Buttons,←n.Cancel
[22]   n.Cancel.Posn[1]←n.OK.Posn[1]
[23]   n.Cancel.Posn[2]←n.∆hgap+2⊃AddPosnAndSize n.OK
[24]  
[25]   ∆←⊂'Button'
[26]   ∆,←⊂'Style' 'Push'
[27]   ∆,←⊂'Caption' '&Preview'
[28]   ∆,←⊂'Size'(⍬ 120)
[29]   ∆,←⊂'Attach'(4⍴'Bottom' 'Left')
[30]   ∆,←⊂'TipObj'n.∆Tip
[31]   ∆,←⊂'Tip'('Put what''s defined on display' 'with the default browser.')
[32]   n.Preview←⍎'preview'n.∆Form.⎕WC ∆
[33]   n.∆Buttons,←n.Preview
[34]   n.Preview.Posn[1]←n.OK.Posn[1]
[35]   n.Preview.Posn[2]←n.∆hgap+2⊃AddPosnAndSize n.Cancel
[36]   n.Preview.onSelect←'OnPreview'
[37]  ⍝Done
     ∇

5. CodeBrowser.GUI.CreateCaption (16 lines)

     ∇ n←n CreateCaption parent;∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'(n.(∆vgap ∆hgap))
[3]    ∆,←⊂'Caption' '&Caption:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'caption_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'(((⌈n.∆vgap÷2)+⊃↑+⌿⊃ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[10]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[11]   ∆,←⊂'Text'({¯1≡⍵:'' ⋄ ⍵}n.∆Parms.caption)
[12]   ∆,←⊂'TipObj'n.∆Tip
[13]   ∆,←⊂'Tip'('Specify the overall caption.' 'If you leave this empty it will default to' 'the names of all namespaces to be scanned.')
[14]   n.caption←⍎'caption'parent.⎕WC ∆
[15]  ⍝Done
     ∇

6. CodeBrowser.GUI.CreateCssFilename (38 lines)

     ∇ n←n CreateCssFilename(above parent);∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆hgap)
[3]    ∆,←⊂'Caption' '&CSS filename:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'cssfile_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'(((2+⌈n.∆vgap÷2)+⊃↑+⌿⊃ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[10]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[11]   ∆,←⊂'TipObj'n.∆Tip
[12]   ∆,←⊂'Tip'('The name of the CSS file to be used.' 'Change this only if you have created your own CSS file.')
[13]   ∆,←⊂'Text'n.∆Parms.cssfilename
[14]   n.cssFilename←⍎'cssfile'parent.⎕WC ∆
[15]  
[16]   ∆←⊂'Button'
[17]   ∆,←⊂'Style' 'Push'
[18]   ∆,←⊂'Caption' '...'
[19]   ∆,←⊂'Posn'((n.cssFilename.Posn[1])⍬)
[20]   ∆,←⊂'Size'((n.cssFilename.Size[1])⍬)
[21]   ∆,←⊂'TipObj'n.∆Tip
[22]   ∆,←⊂'Tip'('Browse for the CSS file to be used')
[23]   ∆,←⊂'Attach'('Top' 'Right' 'Top' 'Right')
[24]   n.selectDirCssFile←⍎'selectDirFilename'parent.⎕WC ∆
[25]   n.selectDirCssFile.onSelect←'OnBrowseForCssFile'
[26]   n.selectDirCssFile.Posn[2]←n.TabCtrl.Size[2]-n.∆hgap+n.selectDirCssFile.Size[2]
[27]   n.cssFilename.Size[2]-←2+n.selectDirCssFile.Size[2]
[28]  
[29]   ∆←⊂'Button'
[30]   ∆,←⊂'Style' 'Check'
[31]   ∆,←⊂'Caption' 'Link the CSS file rather than emebedd'
[32]   ∆,←⊂'Posn'((2+n.∆vgap+⊃↑+⌿⊃n.cssFilename.(Posn Size)),n.∆hgap)
[33]   ∆,←⊂'TipObj'n.∆Tip
[34]   ∆,←⊂'Tip'('Linking can be very useful for changing the CSS')
[35]   ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[36]   n.linkCssFile←⍎'linkCssFile'parent.⎕WC ∆
[37]  ⍝Done
     ∇

7. CodeBrowser.GUI.CreateFileBox (26 lines)

     ∇ n←CreateFileBox parms;n;∆;path
[1]   ⍝ Builds up a `FileBox` control which will remain invisible until it is `⎕DQ`ed.\\
[2]   ⍝ Returns an `n` namepsace.
[3]    n←⎕NS''
[4]    ∆←''
[5]    ∆,←⊂'Caption'parms.caption
[6]    ∆,←⊂'Style' 'Single'
[7]    ∆,←⊂'Filters'parms.filters
[8]    ∆,←⊂'FileMode'parms.fileMode
[9]    ∆,←⊂'Index'(parms.index-1)
[10]   path←parms.path
[11]   ((path='/')/path)←'\'
[12]   ∆,←⊂'Directory'path
[13]   :If 0∊⍴parms.file
[14]       ∆,←⊂'File'(↑,/1↓⎕NPARTS path)
[15]   :Else
[16]       ∆,←⊂'File'(↑,/1↓⎕NPARTS parms.file)
[17]   :EndIf
[18]   n.∆Form←parms.parent.⎕NEW'FileBox'∆
[19]   n.∆Form.⎕DF'[FileBox]'
[20]   n.∆Form.onFileBoxOK←'OnSelectOkButtonInFileBox'
[21]   n.∆Form.onFileBoxCancel←'OnSelectCancelButtonInFileBox'
[22]   n.∆parms←parms
[23]   n.∆result←''
[24]   n.∆Form.n←n
[25]  ⍝Done
     ∇

8. CodeBrowser.GUI.CreateFileBoxParms (11 lines)

     ∇ r←filename CreateFileBoxParms n
[1]   ⍝ Returns a parameter namespace with default settings:
[2]    r←⎕NS''
[3]    r.caption←''
[4]    r.file←filename
[5]    r.fileMode←'Read'
[6]    r.filters←⊂'*.*' 'All files (*.*)'
[7]    r.index←1
[8]    r.parent←n.∆Form
[9]    r.path←{0∊⍴⍵:##.F.PWD ⋄ ⍵}path
[10]  ⍝Done
     ∇

9. CodeBrowser.GUI.CreateFilename (33 lines)

     ∇ n←n CreateFilename parent;∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'(n.(∆vgap ∆hgap))
[3]    ∆,←⊂'Caption' '&HTML filename:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'filename_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'((2+⊃↑+⌿↑ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[10]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[11]   :If 0∊≢n.∆Parms.filename
[12]       ∆,←⊂'Text'('html'##.F.GetTempFilename2'')
[13]   :Else
[14]       ∆,←⊂'Text'n.∆Parms.filename
[15]   :EndIf
[16]   ∆,←⊂'TipObj'n.∆Tip
[17]   ∆,←⊂'Tip'('The name of the file the HTML will be saved in.' 'There is not default.')
[18]   n.filename←⍎'footer'parent.⎕WC ∆
[19]  
[20]   ∆←⊂'Button'
[21]   ∆,←⊂'Style' 'Push'
[22]   ∆,←⊂'Caption' '...'
[23]   ∆,←⊂'Posn'((n.filename.Posn[1])⍬)
[24]   ∆,←⊂'Size'((n.filename.Size[1])⍬)
[25]   ∆,←⊂'TipObj'n.∆Tip
[26]   ∆,←⊂'Tip'('Browse for the file the HTML is going to be written to.')
[27]   ∆,←⊂'Attach'('Top' 'Right' 'Top' 'Right')
[28]   n.selectDirFilename←⍎'selectDirFilename'parent.⎕WC ∆
[29]   n.selectDirFilename.onSelect←'OnBrowseForFilename'
[30]   n.selectDirFilename.Posn[2]←n.TabCtrl.Size[2]-n.∆hgap+n.selectDirFilename.Size[2]
[31]   n.filename.Size[2]-←2+n.selectDirFilename.Size[2]
[32]  ⍝Done
     ∇

10. CodeBrowser.GUI.CreateFonts (4 lines)

     ∇ n←CreateFonts n
[1]    n.∆APL_Font←⍎'APLFont'n.∆Form.⎕WC'Font'('PName' 'APL385 Unicode')('Size' 18)
[2]    n.∆STD_Font←⍎'STDFont'n.∆Form.⎕WC'Font'('PName' 'Verdana')('Size' 15)
[3]   ⍝Done
     ∇

11. CodeBrowser.GUI.CreateFooter (16 lines)

     ∇ n←n CreateFooter(parent above);∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆hgap)
[3]    ∆,←⊂'Caption' '&Footer:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'footer_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'((⊃+⌿↑ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[10]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[11]   ∆,←⊂'Text'n.∆Parms.footer
[12]   ∆,←⊂'TipObj'n.∆Tip
[13]   ∆,←⊂'Tip'('The footer may be a single line or several lines with ⋄ used as separators.' 'There is no default.')
[14]   n.footer←⍎'footer'parent.⎕WC ∆
[15]  ⍝Done
     ∇

12. CodeBrowser.GUI.CreateForm (14 lines)

     ∇ n←CreateForm n;∆;ref;∆Form
[1]    ∆←⊂'Form'
[2]    ∆,←⊂'Caption'({(1⊃⍵),' version ',(2⊃⍵),' from ',(3⊃⍵)}##.Version)
[3]    ∆,←⊂'Coord' 'Pixel'
[4]    ∆,←⊂'Posn'(300 280)
[5]    ∆,←⊂'Size'(565 900)
[6]    n.∆Form←⍎'gui'⎕WC ∆
[7]   
[8]    ref←⍎'SB'n.∆Form.⎕WC⊂'Statusbar'
[9]    n.StatusMsg←⍎'StatusMsg'ref.⎕WC'StatusField'('Coord' 'Prop')('Size'⍬ 99)
[10]   n←CreateFonts n
[11]   n.∆Form.FontObj←n.∆STD_Font
[12]   n.∆Tip←'MyTip'n.∆Form.⎕WC⊂'TipField'
[13]  ⍝Done
     ∇

13. CodeBrowser.GUI.CreateGUI (14 lines)

     ∇ n←CreateGUI n;∆;size
[1]    n←CreateForm n
[2]    n←CreateTabs n
[3]    n(CreateScanTabChildren)←parms.namespaces
[4]    n←CreateParmsTabChildren n
[5]    n←CreateButtons n
[6]    n←CreateTextTabChildren n
[7]    n.OK.onSelect←'OnOK'
[8]    n.Cancel.onSelect←1
[9]    n.∆Form.n←n
[10]   2 ⎕NQ n.Scan'Select'
[11]   n.namespaces.SelText←2⍴1+⍴,n.namespaces.Text
[12]   ⎕NQ n.namespaces'GotFocus'
[13]  ⍝Done
     ∇

14. CodeBrowser.GUI.CreateIgnoreGuiInstances (11 lines)

     ∇ n←n CreateIgnoreGuiInstances(parent above);∆
[1]    ∆←⊂'Button'
[2]    ∆,←⊂'Caption' 'Ignore &GUI instances'
[3]    ∆,←⊂'Style' 'Check'
[4]    ∆,←⊂'State'(~n.∆Parms.processGuiInstances)
[5]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'left')
[6]    ∆,←⊂'TipObj'n.∆Tip
[7]    ∆,←⊂'Tip'('GUI instances with' 'KeepOnClose←0' 'are ignored in any case')
[8]    ∆,←⊂'Posn'((⊃+⌿↑above.(Posn Size)),n.∆hgap+2)
[9]    n.processGuiInstances←⍎'processGuiInstances'parent.⎕WC ∆
[10]  ⍝Done
     ∇

15. CodeBrowser.GUI.CreateInfo (34 lines)

     ∇ n←n CreateInfo(parent above);∆;ref;tip
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆hgap)
[3]    ∆,←⊂'Caption' '&Info:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'info_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'((⊃+⌿↑ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Attach'('Top' 'Left' 'Bottom' 'Right')
[10]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[11]   ∆,←⊂'Text'n.∆Parms.info
[12]   ∆,←⊂'Style' 'Multi'
[13]   ∆,←⊂'TipObj'n.∆Tip
[14]   tip←⊂'"Info" goes right after the "Caption".'
[15]   tip,←⊂'There is no default, so if you leave this'
[16]   tip,←⊂'empty then there will be no "Info".'
[17]   ∆,←⊂'Tip'tip
[18]   n.info←⍎'info'parent.⎕WC ∆
[19]   n.info.onKeyPress←'OnKeyPressInInfo'
[20]  
[21]   ∆←⊂'Button'
[22]   ∆,←⊂'Style' 'Check'
[23]   ∆,←⊂'Caption' '"Info" is &HTML'
[24]   ∆,←⊂'TipObj'n.∆Tip
[25]   tip←⊂'Use this in case you want "Info" to be left alone (normally "<" etc. would be translated).'
[26]   tip,←⊂'This allows you to transform Markdown to HTML and then insert that HTML as "Info".'
[27]   ∆,←⊂'Tip'tip
[28]   ∆,←⊂'Posn'(((⌈n.∆vgap÷2)+⊃+⌿↑n.info.(Posn Size)),n.∆hgap)
[29]   ∆,←⊂'State'n.∆Parms.infoIsHTML
[30]   ∆,←⊂'Attach'(4⍴'Bottom' 'Left')
[31]   n.infoIsHtml←⍎'infoIsHtml'parent.⎕WC ∆
[32]   n.infoIsHtml.Posn[2]+←2
[33]  ⍝Done
     ∇

16. CodeBrowser.GUI.CreateLang (21 lines)

     ∇ n←n CreateLang(parent above);∆;list
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Caption' '&Language:'
[3]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆hgap)
[4]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[5]    n.lang_label←⍎'lang_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Combo'
[8]    ∆,←⊂'Style' 'DropEdit'
[9]    ∆,←⊂'Posn'((⊃+⌿↑n.lang_label.(Posn Size)),n.∆hgap)
[10]   ∆,←⊂'index' 1
[11]   ∆,←⊂'Size'(21 50)
[12]   list←'en' 'de' 'da' 'fr' 'it' 'es'
[13]   ∆,←⊂'Items'list
[14]   ∆,←⊂'TipObj'n.∆Tip
[15]   ∆,←⊂'Tip'('This two-character code is used for setting the "lang" attribute of the <html> tag.')
[16]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[17]   ∆,←⊂'SelItems'({b←(⍴⍵)⍴0 ⋄ b[1]←1 ⋄ b}list)
[18]   n.lang←⍎'lang'parent.⎕WC ∆
[19]   n.lang.onKeyPress←'OnKeyPressInLang'
[20]  ⍝Done
     ∇

17. CodeBrowser.GUI.CreateLines (17 lines)

     ∇ n←n CreateLines(parent sibling);∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Caption' '&L&ines:'
[3]    ∆,←⊂'Posn'(sibling.Posn[1],n.∆vgap+2⊃+⌿↑sibling.(Posn Size))
[4]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[5]    ref←⍎'lines_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'((⊃+⌿↑ref.(Posn Size)),ref.Posn[2])
[9]    ∆,←⊂'FieldType' 'Numeric'
[10]   ∆,←⊂'Size'(21 50)
[11]   ∆,←⊂'Value'n.∆Parms.lines
[12]   ∆,←⊂'TipObj'n.∆Tip
[13]   ∆,←⊂'Tip'('How many lines are displayed per object.' '¯1 means "all lines".')
[14]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[15]   n.lines←⍎'lines'parent.⎕WC ∆
[16]  ⍝Done
     ∇

18. CodeBrowser.GUI.CreateNamespaces (29 lines)

     ∇ n←n CreateNamespaces(parent namespaces);∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'n.(∆vgap ∆hgap)
[3]    ∆,←⊂'Caption' '&Namespace(s) to be scanned:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'ns_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'(((2+⌈n.∆vgap÷2)+⊃↑+⌿⊃ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Font'n.∆APL_Font
[10]   ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[11]   ∆,←⊂'Text'(⊃{⍺,', ',⍵}/{0∊≢⍵:'#' ⋄ ⍵}⊆⍕¨namespaces)
[12]   ∆,←⊂'Size'(⍬(n.ScanSubForm.Size[2]-2×n.∆hgap))
[13]   ∆,←⊂'FontObj'n.∆APL_Font
[14]   ∆,←⊂'TipObj'n.∆Tip
[15]   ∆,←⊂'Tip'('Specify all the namespaces to be scanned.' 'Use spaces or commata as separators.')
[16]   n.namespaces←⍎'namespaces'parent.⎕WC ∆
[17]   n.namespaces.Size[1]-←5
[18]  
[19]   ∆←⊂'Button'
[20]   ∆,←⊂'Style' 'Check'
[21]   ∆,←⊂'Caption' 'Process &recursively'
[22]   ∆,←⊂'Posn'((n.∆hgap+⊃+⌿↑n.namespaces.(Posn Size)),n.∆vgap)
[23]   ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[24]   ∆,←⊂'State'n.∆Parms.recursive
[25]   ∆,←⊂'TipObj'n.∆Tip
[26]  ⍝∆,←⊂'Tip'('')
[27]   n.recursive←⍎'recursive'parent.⎕WC ∆
[28]  ⍝Done
     ∇

19. CodeBrowser.GUI.CreateNativeFile (9 lines)

     ∇ success←CreateNativeFile filename;tno
[1]   ⍝ Tries to create native file with `filename` and returns 1 in case of success and 0 otherwise.
[2]    :Trap 22
[3]        tno←filename ⎕NCREATE 0
[4]        ⎕NUNTIE tno
[5]        success←1
[6]    :Case 22
[7]        success←0
[8]    :EndTrap
     ∇

20. CodeBrowser.GUI.CreateOtherParms (21 lines)

     ∇ n←n CreateOtherParms(parent above);∆;ref
[1]    ∆←⊂'Button'
[2]    ∆,←⊂'Style' 'Check'
[3]    ∆,←⊂'Caption' '&Show parameters at the end of the document'
[4]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆vgap)
[5]    ∆,←⊂'State'n.∆Parms.showParms
[6]    ∆,←⊂'TipObj'n.∆Tip
[7]    ∆,←⊂'Tip'('Use this for documenting the parameters.' 'When printed the parameter go onto a separate page.')
[8]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[9]    n.showParms←⍎'showParms'parent.⎕WC ∆
[10]  
[11]   ∆←⊂'Button'
[12]   ∆,←⊂'Style' 'Check'
[13]   ∆,←⊂'Caption' '&View resulting HTML page in default browser'
[14]   ∆,←⊂'Posn'((⊃+⌿↑n.showParms.(Posn Size)),n.∆hgap)
[15]   ∆,←⊂'State'n.∆Parms.viewInBrowser
[16]   ∆,←⊂'TipObj'n.∆Tip
[17]  ⍝ ∆,←⊂'Tip'('')
[18]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[19]   n.viewInBrowser←⍎'viewInBrowser'parent.⎕WC ∆
[20]  ⍝Done
     ∇

21. CodeBrowser.GUI.CreateParmsTabChildren (9 lines)

     ∇ n←CreateParmsTabChildren n;∆;ref
[1]    n(CreateFilename)←n.ParmsSubForm
[2]    n(CreateCssFilename)←n.filename n.ParmsSubForm
[3]    n(CreateToBeProcessed)←n.ParmsSubForm n.linkCssFile
[4]    n(CreatePrintParms)←n.processFns.## n.ParmsSubForm
[5]    n(CreateLang)←n.ParmsSubForm n.processFns.##
[6]    n(CreateLines)←n.ParmsSubForm n.lang_label
[7]    n(CreateOtherParms)←n.ParmsSubForm n.lines
[8]   ⍝Done
     ∇

22. CodeBrowser.GUI.CreatePrintParms (47 lines)

     ∇ n←n CreatePrintParms(sibling parent);∆;ref;ref2;list
[1]    ∆←⊂'Group'
[2]    ∆,←⊂'Caption' ' P&rint parameters'
[3]    ∆,←⊂'Posn'(sibling.Posn[1],n.∆hgap+2⊃+⌿↑sibling.(Posn Size))
[4]    ∆,←⊂'Size'(135 300)
[5]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[6]    ref←⍎'printParms_group'parent.⎕WC ∆
[7]   
[8]    ∆←⊂'Button'
[9]    ∆,←⊂'Style' 'Check'
[10]   ∆,←⊂'Caption' '&Use background colour for print'
[11]   ∆,←⊂'TipObj'n.∆Tip
[12]   ∆,←⊂'State'n.∆Parms.backgroundColorPrint
[13]   ∆,←⊂'Tip'('By default when printing background colours are ignored.' 'For some browsers that default behaviour can be overwritten.')
[14]   ∆,←⊂'Posn'(n.(2 1×∆vgap ∆hgap))
[15]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[16]   n.printBgrCol←⍎'printBgrCol'ref.⎕WC ∆
[17]  
[18]   ∆←⊂'Button'
[19]   ∆,←⊂'Style' 'Check'
[20]   ∆,←⊂'Caption' '&Two-sided print'
[21]   ∆,←⊂'State'n.∆Parms.twoSidedPrint
[22]   ∆,←⊂'TipObj'n.∆Tip
[23]   ∆,←⊂'Tip'('The left margin is different on odd and even pages then.')
[24]   ∆,←⊂'Posn'((⊃+⌿↑n.printBgrCol.(Posn Size)),n.∆hgap)
[25]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[26]   n.twoSidedPrint←⍎'twoSidedPrint'ref.⎕WC ∆
[27]  
[28]   ∆←⊂'Label'
[29]   ∆,←⊂'Caption' '&Font size to be used for print:'
[30]   ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑n.twoSidedPrint.(Posn Size)),n.∆hgap)
[31]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[32]   ref2←⍎'fontsize_label'ref.⎕WC ∆
[33]  
[34]   ∆←⊂'Combo'
[35]   ∆,←⊂'Style' 'Drop'
[36]   ∆,←⊂'Posn'(ref2.Posn[1],ref2.Size[2]+n.∆hgap)
[37]   ∆,←⊂'index' 1
[38]   ∆,←⊂'Size'(21 40)
[39]   list←'4' '5' '6' '7' '8' '9' '10' '11' '12' '16' '17' '18' '20' '22' '23' '24' '25' '27' '28' '29' '31'
[40]   ∆,←⊂'Items'list
[41]   ∆,←⊂'TipObj'n.∆Tip
[42]  ⍝∆,←⊂'Tip' ('')
[43]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[44]   ∆,←⊂'SelItems'(list{b←(⍴⍺)⍴0 ⋄ b[(⍎¨⍺)⍳⍵]←1 ⋄ b}n.∆Parms.printFontSize)
[45]   n.fontSizeForPrint←⍎'fontSizeForPrint'ref.⎕WC ∆
[46]  ⍝Done
     ∇

23. CodeBrowser.GUI.CreateScanTabChildren (6 lines)

     ∇ n←n CreateScanTabChildren namespaces
[1]    n(CreateNamespaces)←n.ScanSubForm namespaces
[2]    n(CreateToBeIgnored)←n.ScanSubForm n.recursive
[3]    n(CreateIgnoreGuiInstances)←n.ScanSubForm n.ignoreEmptyNamespaces
[4]    n(CreateTatinPackages)←n.ScanSubForm n.processGuiInstances
[5]   ⍝Done
     ∇

24. CodeBrowser.GUI.CreateSubForms (31 lines)

     ∇ n←CreateSubForms n;∆
[1]    ∆←⊂'SubForm'
[2]    ∆,←⊂'TabObj'n.Scan
[3]    ∆,←⊂'Coord' 'Prop'
[4]    ∆,←⊂'Posn'(0 0)
[5]    ∆,←⊂'Size'(100 100)
[6]    ∆,←⊂'EdgeStyle' 'Dialog'
[7]    ∆,←⊂'Attach'('Top' 'Left' 'Bottom' 'Right')
[8]    n.ScanSubForm←⍎'subformScan'n.TabCtrl.⎕WC ∆
[9]    n.ScanSubForm.Coord←'Pixel'
[10]  
[11]   ∆←⊂'SubForm'
[12]   ∆,←⊂'TabObj'n.Parms
[13]   ∆,←⊂'Coord' 'Prop'
[14]   ∆,←⊂'Posn'(0 0)
[15]   ∆,←⊂'Size'(100 100)
[16]   ∆,←⊂'EdgeStyle' 'Dialog'
[17]   ∆,←⊂'Attach'('Top' 'Left' 'Bottom' 'Right')
[18]   n.ParmsSubForm←⍎'subformParms'n.TabCtrl.⎕WC ∆
[19]   n.ParmsSubForm.Coord←'Pixel'
[20]  
[21]   ∆←⊂'SubForm'
[22]   ∆,←⊂'TabObj'n.Text
[23]   ∆,←⊂'Coord' 'Prop'
[24]   ∆,←⊂'Posn'(0 0)
[25]   ∆,←⊂'Size'(100 100)
[26]   ∆,←⊂'EdgeStyle' 'Dialog'
[27]   ∆,←⊂'Attach'('Top' 'Left' 'Bottom' 'Right')
[28]   n.TextSubForm←⍎'subformText'n.TabCtrl.⎕WC ∆
[29]   n.TextSubForm.Coord←'Pixel'
[30]  ⍝Done
     ∇

25. CodeBrowser.GUI.CreateTabControlAndChildren (19 lines)

     ∇ n←CreateTabControlAndChildren n;∆
[1]    ∆←⊂'TabControl'
[2]    ∆,←⊂'Size'(n.∆Form.Size-70 20)
[3]    ∆,←⊂'Posn'(0 10)
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Bottom' 'Right')
[5]    n.TabCtrl←⍎'tabctrl'n.∆Form.⎕WC ∆
[6]   
[7]    ∆←⊂'TabButton'
[8]    ∆,←⊂'Caption' 'Scan'
[9]    n.Scan←⍎'tabbtnScan'n.TabCtrl.⎕WC ∆
[10]  
[11]   ∆←⊂'TabButton'
[12]   ∆,←⊂'Caption' 'Parameters'
[13]   n.Parms←⍎'tabbtnParms'n.TabCtrl.⎕WC ∆
[14]  
[15]   ∆←⊂'TabButton'
[16]   ∆,←⊂'Caption' 'Text'
[17]   n.Text←⍎'tabbtnText'n.TabCtrl.⎕WC ∆
[18]  ⍝Done
     ∇

26. CodeBrowser.GUI.CreateTabs (4 lines)

     ∇ n←CreateTabs n;∆
[1]    n←CreateTabControlAndChildren n
[2]    n←CreateSubForms n
[3]   ⍝Done
     ∇

27. CodeBrowser.GUI.CreateTatinPackages (11 lines)

     ∇ n←n CreateTatinPackages(parent above);∆
[1]    ∆←⊂'Button'
[2]    ∆,←⊂'Style' 'Check'
[3]    ∆,←⊂'Caption' 'Ignore &Tatin packages'
[4]    ∆,←⊂'Posn'((⊃+⌿↑above.(Posn Size)),n.∆hgap)
[5]    ∆,←⊂'State'n.∆Parms.ignoreTatinPkgs
[6]    ∆,←⊂'TipObj'n.∆Tip
[7]    ∆,←⊂'Tip'('Ignores (⎕SE|#)._tatin')
[8]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[9]    n.ignoreTatinPkgs←⍎'ignoreTatinPkgs'parent.⎕WC ∆
[10]  ⍝Done
     ∇

28. CodeBrowser.GUI.CreateTextTabChildren (5 lines)

     ∇ n←CreateTextTabChildren n;∆;ref;list
[1]    n(CreateCaption)←n.TextSubForm
[2]    n(CreateFooter)←n.TextSubForm n.caption
[3]    n(CreateInfo)←n.TextSubForm n.footer
[4]   ⍝Done
     ∇

29. CodeBrowser.GUI.CreateToBeIgnored (27 lines)

     ∇ n←n CreateToBeIgnored(parent above);∆;ref
[1]    ∆←⊂'Label'
[2]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑above.(Posn Size)),n.∆hgap)
[3]    ∆,←⊂'Caption' 'To be ignored:'
[4]    ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Left')
[5]    ref←⍎'ignored_label'parent.⎕WC ∆
[6]   
[7]    ∆←⊂'Edit'
[8]    ∆,←⊂'Posn'(((2+⌈n.∆vgap÷2)+⊃↑+⌿⊃ref.(Posn Size)),n.∆hgap)
[9]    ∆,←⊂'Font'n.∆APL_Font
[10]   ∆,←⊂'Attach'('Top' 'Left' 'Top' 'Right')
[11]   ∆,←⊂'Size'(⍬(parent.Size[2]-2×n.∆hgap))
[12]   ∆,←⊂'FontObj'n.∆APL_Font
[13]   ∆,←⊂'TipObj'n.∆Tip
[14]   ∆,←⊂'Tip'('Specify everything inside the namespaces to be scanned that you want to be ignored.' 'Specify fully qualified names. Use spaces or commata as separators.')
[15]   n.toBeIgnored←⍎'tobeignored'parent.⎕WC ∆
[16]   n.toBeIgnored.Size[1]-←5
[17]  
[18]   ∆←⊂'Button'
[19]   ∆,←⊂'Caption' '&Ignore empty namespaces'
[20]   ∆,←⊂'Style' 'Check'
[21]   ∆,←⊂'State'n.∆Parms.ignoreEmpty
[22]   ∆,←⊂'Attach'('Top' 'Left' 'Top' 'left')
[23]   ∆,←⊂'Tip'('If this is not ticked empty namespaces will be listed')
[24]   ∆,←⊂'Posn'(((⌈n.∆vgap÷2)+⊃+⌿↑n.toBeIgnored.(Posn Size)),n.∆hgap+2)
[25]   n.ignoreEmptyNamespaces←⍎'ignoreEmpty'parent.⎕WC ∆
[26]  ⍝Done
     ∇

30. CodeBrowser.GUI.CreateToBeProcessed (50 lines)

     ∇ n←n CreateToBeProcessed(parent above);∆;ref
[1]    ∆←⊂'Group'
[2]    ∆,←⊂'Caption' ' &Process '
[3]    ∆,←⊂'Posn'((n.∆vgap+⊃+⌿↑n.linkCssFile.(Posn Size)),n.∆hgap)
[4]    ∆,←⊂'Size'(135 300)
[5]    ∆,←⊂'Attach'(4⍴'Top' 'Left')
[6]    ∆,←⊂'TipObj'n.∆Tip
[7]   ⍝ ∆,←⊂'Tip'('')
[8]    ref←⍎'process_group'parent.⎕WC ∆
[9]   
[10]   ∆←⊂'Button'
[11]   ∆,←⊂'Style' 'Check'
[12]   ∆,←⊂'Caption' '&Functions'
[13]   ∆,←⊂'Posn'n.(2 1×∆vgap ∆hgap)
[14]   ∆,←⊂'State'n.∆Parms.processFunctions
[15]   ∆,←⊂'TipObj'n.∆Tip
[16]  ⍝ ∆,←⊂'Tip'('')
[17]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[18]   n.processFns←⍎'processFns'ref.⎕WC ∆
[19]  
[20]   ∆←⊂'Button'
[21]   ∆,←⊂'Style' 'Check'
[22]   ∆,←⊂'Caption' '&Operators'
[23]   ∆,←⊂'Posn'((⊃+⌿↑n.processFns.(Posn Size)),n.∆hgap)
[24]   ∆,←⊂'State'n.∆Parms.processOperators
[25]   ∆,←⊂'TipObj'n.∆Tip
[26]  ⍝ ∆,←⊂'Tip'('')
[27]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[28]   n.processOpr←⍎'processOpr'ref.⎕WC ∆
[29]  
[30]   ∆←⊂'Button'
[31]   ∆,←⊂'Style' 'Check'
[32]   ∆,←⊂'Caption' '&Scripts (classes, namespaces, interfaces)'
[33]   ∆,←⊂'Posn'((⊃+⌿↑n.processOpr.(Posn Size)),n.∆hgap)
[34]   ∆,←⊂'State'n.∆Parms.processScripts
[35]   ∆,←⊂'TipObj'n.∆Tip
[36]  ⍝ ∆,←⊂'Tip'('')
[37]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[38]   n.processScripts←⍎'processScripts'ref.⎕WC ∆
[39]  
[40]   ∆←⊂'Button'
[41]   ∆,←⊂'Style' 'Check'
[42]   ∆,←⊂'Caption' '&Variables'
[43]   ∆,←⊂'Posn'((⊃+⌿↑n.processScripts.(Posn Size)),n.∆hgap)
[44]   ∆,←⊂'State'n.∆Parms.processVars
[45]   ∆,←⊂'TipObj'n.∆Tip
[46]  ⍝ ∆,←⊂'Tip'('')
[47]   ∆,←⊂'Attach'(4⍴'Top' 'Left')
[48]   n.processVars←⍎'processVars'ref.⎕WC ∆
[49]  ⍝Done
     ∇

31. CodeBrowser.GUI.DQ (3 lines)

     ∇ {r}←DQ ref
[1]    r←⎕DQ ref
[2]   ⍝Done
     ∇

32. CodeBrowser.GUI.GetRefTo_n (4 lines)

     ∇ GetRefTo_n←{
[1]        0<⍵.⎕NC'n':⍵.n
[2]        ∇ ⍵.##
[3]    }
     ∇

33. CodeBrowser.GUI.Init (3 lines)

     ∇ n←Init dummy
[1]    n←⎕NS''
[2]    n.(∆vgap ∆hgap)←15
     ∇

34. CodeBrowser.GUI.MassageCssFilename (6 lines)

     ∇ filename←MassageCssFilename filename
[1]   ⍝ Forces `filename` to be an absolute path.
[2]    :If (~':'∊filename)∧'//'≢2⍴filename  ⍝ Not absolute?
[3]        filename←'expand'##.F.NormalizePath filename
[4]    :EndIf
[5]   ⍝Done
     ∇

35. CodeBrowser.GUI.OnBrowseForCssFile (18 lines)

     ∇ OnBrowseForCssFile msg;n;parms;fb;res;path;filename;extension
[1]    n←GetRefTo_n⊃msg
[2]    (path filename extension)←⎕NPARTS n.cssFilename.Text
[3]    filename←filename,extension
[4]    parms←filename CreateFileBoxParms n
[5]    :If 0∊⍴path
[6]        parms.path←##.F.PWD
[7]    :Else
[8]        parms.path←path
[9]    :EndIf
[10]   parms.caption←'Read CSS file'
[11]   parms.filters←⊂'*.css' 'CSS file'
[12]   fb←CreateFileBox parms
[13]   res←DQ fb.∆Form
[14]   :If ~0∊⍴fb.∆result
[15]       n.cssFilename.Text←fb.∆result
[16]   :EndIf
[17]  ⍝Done
     ∇

36. CodeBrowser.GUI.OnBrowseForFilename (20 lines)

     ∇ OnBrowseForFilename msg;parms;fb;n;res;path;filename;extension
[1]    n←GetRefTo_n⊃msg
[2]    (path filename extension)←⎕NPARTS n.filename.Text
[3]    filename←filename,extension
[4]    parms←filename CreateFileBoxParms n
[5]    :If 0∊⍴path
[6]        parms.path←##.F.PWD
[7]    :Else
[8]        parms.path←path
[9]    :EndIf
[10]   parms←filename CreateFileBoxParms n
[11]   parms.caption←'Save HTML file'
[12]   parms.fileMode←'Write'
[13]   parms.filters←('*.HTML' 'HTML files')('*.HTM' 'HTML files')
[14]   fb←CreateFileBox parms
[15]   res←DQ fb.∆Form
[16]   :If ~0∊⍴fb.∆result
[17]       n.filename.Text←fb.∆result
[18]   :EndIf
[19]  ⍝Done
     ∇

37. CodeBrowser.GUI.OnKeyPressInInfo (6 lines)

     ∇ OnKeyPressInInfo←{
[1]        ⍵[4 5 6]≢0 9 2:1
[2]        ⍝ Suppress Ctrl+Tab: that should change the current tab
[3]        n←GetRefTo_n⊃⍵
[4]        0⊣⎕NQ n.TabCtrl.TabObj,1↓⍵
[5]    }
     ∇

38. CodeBrowser.GUI.OnKeyPressInLang (4 lines)

     ∇ OnKeyPressInLang←{
[1]        1≠⍴,3⊃⍵:1
[2]        2≥1+⍴,⍵[1].Text
[3]    }
     ∇

39. CodeBrowser.GUI.OnOK (11 lines)

     ∇ r←OnOK msg;n
[1]    n←GetRefTo_n⊃msg
[2]    (r msg)←CheckInput n
[3]    :If r
[4]        ShowInStatusbar'Processing...'
[5]        n.∆Parms←n.∆Parms
[6]        CopyGuiToParms n
[7]        {}n.∆Parms ##.Run n.∆Parms.namespaces
[8]        ⎕NQ n.∆Form'Close'
[9]    :EndIf
[10]  ⍝Done
     ∇

40. CodeBrowser.GUI.OnPreview (10 lines)

     ∇ OnPreview←{
[1]        n←GetRefTo_n⊃⍵
[2]        (r msg)←CheckInput n
[3]        0=r:0
[4]        _←CopyGuiToParms n
[5]        0=≢n.∆Parms.filename:0
[6]        _←n.∆Parms ##.Run n.∆Parms.namespaces
[7]        _←##.A.GoToWebPage⍣(⊃~n.∆Parms.viewInBrowser)⊣n.∆Parms.filename
[8]        0
[9]    }
     ∇

41. CodeBrowser.GUI.OnSelectCancelButtonInFileBox (5 lines)

     ∇ OnSelectCancelButtonInFileBox←{
[1]        n←GetRefTo_n⊃⍵
[2]        n.∆result←''
[3]        1
[4]    }
     ∇

42. CodeBrowser.GUI.OnSelectOkButtonInFileBox (5 lines)

     ∇ OnSelectOkButtonInFileBox←{
[1]        n←GetRefTo_n⊃⍵
[2]        n.∆result←n.∆Form.Directory,n.∆Form.File
[3]        1
[4]    }
     ∇

43. CodeBrowser.GUI.PolishNamespaceList (7 lines)

     ∇ PolishNamespaceList←{
[1]    ⍝ ⍵ is typically n.namespaces.Text
[2]        list←⍵
[3]        ((list=',')/list)←' '
[4]        list←∪' '##.A.Split ##.A.DMB list
[5]        '⎕se'⎕R'⎕SE'⊣list
[6]    }
     ∇

44. CodeBrowser.GUI.Run (19 lines)

     ∇ {r}←{parms}Run(namespaces homePath);∆;n
[1]   ⍝ `namespaces` can be one of:
[2]   ⍝ * Single ref
[3]   ⍝ * Vector of refs
[4]   ⍝ * Simple text vector
[5]   ⍝ * Vector of text vectors
[6]   ⍝ In case `homePath` is not empty it is assumed that `Run` is executed by the user command framework.
[7]    r←⍬
[8]    ##.Init ⍬
[9]    :If 0=⎕NC'parms'
[10]       parms←##.CreateParms homePath
[11]   :EndIf
[12]   parms.namespaces←namespaces
[13]   n←Init ⍬
[14]   n.∆Parms←parms
[15]   n←CreateGUI n
[16]   DQ n.∆Form
[17]   :Trap 0 ⋄ ⎕NQ n.∆Form'Close' ⋄ :EndTrap
[18]  ⍝Done
     ∇

45. CodeBrowser.GUI.SetFocusTo (5 lines)

     ∇ r←SetFocusTo(tab control)
[1]    r←0
[2]    ⎕NQ tab'Select'
[3]    ⎕NQ control'GotFocus'
[4]   ⍝Done
     ∇

46. CodeBrowser.GUI.ShowInStatusbar (3 lines)

     ∇ {r}←ShowInStatusbar msg
[1]    n.StatusMsg.Text←msg
[2]   ⍝Done
     ∇

Parameters

NameSetting
backgroundColorPrint1
caption CodeBrowser
cssfilename C:/T/Projects/UserCommands/CodeBrowser/Files/codebrowser_styles.css
filename C:\Users\kai\AppData\Local\Temp\/kai_CodeBrowser_CodeReview.html
footer Created by kai on 2022-01-18 09:27:16
ignore
ignoreEmpty 1
ignoreTatinPkgs 1
info Contains the CodeBrowser code without the test cases.
infoIsHTML 0
lang en
lines ¯1
linkcssfile 0
namespaces #.CodeBrowser.CodeBrowser
printFontSize 8
processFunctions 1
processGuiInstances 0
processOperators 1
processScripts 1
processVars 1
recursive 1
showParms 1
twoSidedPrint 1
version CodeBrowser 2.0.0+81 from 2022-01-17
viewInBrowser 1