Dept. of incomplete documentation: what if BufDelay* needs to be multichannel?
[supercollider.git] / SCClassLibrary / deprecated / Helper / uGenHelper.sc
blobfd728d0c6b9986ae1c6d6a3b52fff98c885ae7eb
1 /*
2 // Helper, ClassHelper, UGenHelper, TopicHelper
3 // (In this file: UGenHelper)
4 // ________________________________
5 //
6 // Classes to auto generate help files following style guides.
7 // See Helper source for more comments
8 // started on 04/11/07 - andreavalle
9 */
12 UGenHelper {
14         var <>class, <>path ;
15         classvar doctype, head, preface, examples, parents ;
17         *new { arg class, path ;
18                 this.deprecated;
19                 ^super.new.initUGenHelper( class, path )
20         }
22         initUGenHelper { arg aClass, aPath ;
23                 class = aClass ;
24                 path = aPath ;
25                 parents  = "" ;
26                 if ( path.isNil, {
27                         GUI.current.dialog.savePanel({ arg newPath ;
28                                  path = newPath ; {this.makeHelp}.defer })
29                         }, { this.makeHelp }) ;
30         }
32         createText {
33                 head = "
34 <head>
35 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">
36 <meta http-equiv=\"Content-Style-Type\" content=\"text/css\">
37 <title></title>
38 <meta name=\"Generator\" content=\"Cocoa HTML Writer\">
39 <meta name=\"CocoaVersion\" content=\"824.42\">
40 <style type=\"text/css\">
41 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
42 p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
43 p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
44 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #d40000}
45 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
46 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #007700}
47 span.s1 {font: 18.0px Helvetica}
48 span.s2 {color: #1200c4}
49 span.s3 {color: #1200c4}
50 span.s4 {color: #000000}
51 span.s5 {color: #1200c4}
52 span.Apple-tab-span {white-space:pre}
53 </style>
54 </head>
55 " ;
56                 preface = "
57 <p class=\"p1\"><span class=\"s1\"><b>SomeUGen<span class=\"Apple-tab-span\">   </span><span class=\"Apple-tab-span\">  </span><span class=\"Apple-tab-span\">  </span></b></span><b>explanation of the what SomeUGen does</b></p>
58 <p class=\"p2\"><b></b><br></p>
59 "                       .replace("SomeUGen", class.name.asString) ;
60                         doctype = "
61 <!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">
62 " ;
63                 examples = "
64 <p class=\"p4\">// what this example does</p>
65 <p class=\"p5\">x = { <span class=\"s3\">SomeUGen</span>.ar(<span class=\"s3\">XLine</span>.kr(2000, 200), 0, 0.5) }.play;</p>
66 <p class=\"p5\">x.free;</p>
67 <p class=\"p3\"><br></p>
68 <p class=\"p4\">// what this example does</p>
69 <p class=\"p5\">(</p>
70 <p class=\"p6\"><span class=\"s4\">x = </span><span class=\"s5\">SynthDef</span><span class=\"s4\">(</span>\\helpSomeUGen<span class=\"s4\">, {<span class=\"Apple-converted-space\"></span></span></p>
71 <p class=\"p5\"><span class=\"Apple-tab-span\"></span><span class=\"s3\">Out</span>.ar(0, <span class=\"s3\">SomeUGen</span>.ar(<span class=\"s3\">SinOsc</span>.ar(<span class=\"s3\">XLine</span>.kr(1, 1000, 9), 0, 200, 800), 0, 0.25));<span class=\"Apple-converted-space\"></span></p>
72 <p class=\"p5\">}).play;<span class=\"Apple-converted-space\"></span></p>
73 <p class=\"p5\">)</p>
74 <p class=\"p5\">x.free;</p>
75 "                       .replace("SomeUGen", class.name.asString) ;
76         }
79         makeHelp {
80                 var title = class.name.asString ;
81                 var classMethodBlock = this.createClassMethodBlock ;
82                 this.createText ;
83                 // see ClassHelper
84                 // write a html file in tmp
85                 File.new(path, "w")
86                         .write(doctype +
87                                  "<hmtl>\n"+
88                                  head+
89                                  "<body>\n"+
90                                  preface+
91                                  classMethodBlock +
92                                  examples+
93                                  "</body>"+
94                                  "</html>")
95                                 .close ;
96                 // and reopen thru class.openHelpFile
97                 // open works if the path is a place where SC looks for Help files
98                 class.openHelpFile
99         }
101         createClassMethodBlock {
102                 var arArgs, krArgs, irArgs ;
103                 var arBlock = "", krBlock = "", irBlock = "" ;
104                 var explanation = "
105 <p class=\"p2\"><br></p>
106 <p class=\"p1\">Here is a short prose explanation of what the UGen does, and any other relevant points.</p>
107 " ;
108                 var total, defaults, default ;
109                 var par ;
110                 var uGen, uGenParent = class ; // we need to get the args
111                 var uGenParentMethods = uGenParent.class.methods.collect(_.name) ;
112                 var arMethod, krMethod, irMethod ;
113                 if ( uGenParentMethods == nil, { uGenParentMethods = [] }) ;
114                 // in the following we crawl on the tree untile we find ar/kr/ir methods
115                 // this works fine for most UGen
116                 // but not for the ones not implementing *r methods
117                 // in that case a default generic string is returned
118                 // The aim being to generate a template, not such a bad solution
119                 while {
120                         ( uGenParentMethods.includes(\ar) or:
121                         uGenParentMethods.includes(\kr) or:
122                         uGenParentMethods.includes(\ir)).not
123                  }
124                         { uGen = uGenParent ;
125                                 // returns a "warning" but styled message
126                                 // if *r methods are not found
127                                 if (uGenParent == nil, {
128                                 ^"<p class=\"p1\"><b>"++
129                                 class.name.asString+
130                                 "-->no ar/kr/ir methods: sorry, you have to complete as required"+
131                                 explanation+"</p></b>"
132                                 } );
133                         uGenParent = uGenParent.superclass ;
134                          uGenParentMethods = uGenParent.class.methods.collect(_.name) ;
135                          if ( uGenParentMethods == nil, { uGenParentMethods = [] }) ;
136                          } ;
138                 arMethod = uGenParent.class.findMethod(\ar) ;
139                 krMethod = uGenParent.class.findMethod(\kr) ;
140                 irMethod = uGenParent.class.findMethod(\ir) ;
142                 defaults = arMethod ;
143                 if ( defaults.isNil, { defaults = krMethod }) ;
144                 if ( defaults.isNil, { defaults = irMethod }) ;
145                 defaults = defaults.argumentString ;
146                 defaults = defaults.split($,) ;
147                 arArgs = arMethod.argNames ;
148                 krArgs = krMethod.argNames ;
149                 irArgs = irMethod.argNames ;
150                 case
151                 { arArgs.size == 1 }{
152                 arBlock = "
153 <p class=\"p1\"><b>SomeUGen.ar".replace("SomeUGen", class.name.asString) }
155                 { arArgs.notNil} {
156                  arBlock = "
157 <p class=\"p1\"><b>SomeUGen.ar(".replace("SomeUGen", class.name.asString) ;
158                 arArgs = arArgs[1..] ;
159                 arArgs.do({ arg anArg ;
160                         arBlock = arBlock++anArg.asString++", "
161                 }) ;
162                 arBlock = arBlock[..arBlock.size-3]+")</b></p>" ;
163                 } ;
165                 case
166                 { krArgs.size == 1 }{
167                 krBlock = "
168 <p class=\"p1\"><b>SomeUGen.kr".replace("SomeUGen", class.name.asString) }
170                 { krArgs.notNil} {
171                 krBlock = "
172 <p class=\"p1\"><b>SomeUGen.kr(".replace("SomeUGen", class.name.asString) ;
173                 krArgs = krArgs[1..] ;
174                 krArgs.do({ arg anArg ;
175                         krBlock = krBlock++anArg.asString++", "
176                 }) ;
177                 krBlock = krBlock[..krBlock.size-3]+")</b></p>" ;
178                 } ;
180                 case
181                 { irArgs.size == 1 }{
182                 irBlock = "
183 <p class=\"p1\"><b>SomeUGen.ir".replace("SomeUGen", class.name.asString) ;}
185                 {irArgs.notNil} {
186                 irBlock = "
187 <p class=\"p1\"><b>SomeUGen.ir(".replace("SomeUGen", class.name.asString) ;
188                 irArgs = irArgs[1..] ;
189                 irArgs.do({ arg anArg ;
190                         irBlock = irBlock++anArg.asString++", "
191                 }) ;
192                 irBlock = irBlock[..irBlock.size-3]+")</b></p>" ;
193                 } ;
194                 par = if (arArgs.notNil, { arArgs }, { if (krArgs.notNil, { krArgs }, { irArgs } ) }) ;
195                 //par = if ( par.size == 1, { [] }, { par }) ;
196                 // all those replacements are tricky, indeed
197                 // could be implemented much better, probably
198                 par.do({ arg anArg, index ;
199                         default = defaults[index+1].asString ;
200                         default = if ( default.split($=).size == 1, { "nil" }, {
201                                  default.split($=)[1] });
202                         explanation = explanation +
204 <p class=\"p1\"><b>arg1</b> - explanation of arg1. Default value is defaultValue.</p>
205 "                               .replace("arg1", anArg.asString)
206                                 .replace("defaultValue", default) ;
208                 }) ;
209                 explanation = explanation +
211 <p class=\"p2\"><br></p>
212 <p class=\"p1\"><b>See also:</b> <a href=\"../UGens/Oscillators/SinOsc.html\"><span class=\"s2\">SinOsc</span></a> [other related UGens...]</p>
213 <p class=\"p2\"><br></p>
214 <p class=\"p3\"><br></p>
215 " ;
216                 total = arBlock+krBlock+irBlock+explanation ;
217                 ^total
218         }