1 String[char] : RawArray {
2 classvar <>unixCmdActions;
5 unixCmdActions = IdentityDictionary.new;
10 unixCmdActions[pid].value(res, pid);
11 unixCmdActions.removeAt(pid);
15 arg postOutput = true;
20 // runs a unix command and sends stdout to the post window
22 arg action, postOutput = true;
24 pid = this.prUnixCmd(postOutput);
26 unixCmdActions.put(pid, action);
31 // Like unixCmd but gets the result into a string
33 var pipe, lines, line;
35 pipe = Pipe.new(this, "r");
38 while({line.notNil}, {lines = lines ++ line ++ "\n"; line = pipe.getLine; });
57 ^Array.fill(this.size, { |i| this[i].ascii })
71 _String_GetResourceDirPath
79 compare { arg aString, ignoreCase=false; _StringCompare }
80 < { arg aString; ^this.compare(aString, true) < 0 }
81 > { arg aString; ^this.compare(aString, true) > 0 }
82 <= { arg aString; ^this.compare(aString, true) <= 0 }
83 >= { arg aString; ^this.compare(aString, true) >= 0 }
84 == { arg aString; ^this.compare(aString, true) == 0 }
85 != { arg aString; ^this.compare(aString, true) != 0 }
88 // no sense doing collect as per superclass collection
89 performBinaryOpOnSimpleNumber { arg aSelector, aNumber;
90 ^aNumber.asString.perform(aSelector, this);
92 performBinaryOpOnComplex { arg aSelector, aComplex;
93 ^aComplex.asString.perform(aSelector, this);
98 asCompileString { _String_AsCompileString; }
103 postcln { "// ".post; this.postln; }
104 postc { "// ".post; this.post; }
106 postf { arg ... items; ^this.prFormat( items.collect(_.asString) ).post }
107 format { arg ... items; ^this.prFormat( items.collect(_.asString) ) }
108 prFormat { arg items; _String_Format ^this.primitiveFailed }
109 matchRegexp { arg string, start = 0, end; _String_Regexp ^this.primitiveFailed }
111 fformat { arg ... args;
112 var str, resArgs, val, func;
113 var suffixes, sig = false;
117 val = args.removeAt(0);
118 func = Post.formats[char];
120 resArgs = resArgs.add(val);
123 resArgs = resArgs.add(func.value(val))
129 if(char == $%) { sig = true };
131 ^str.format(*resArgs)
134 die { arg ... culprits;
135 if(culprits.notEmpty,{
136 ("\n\nFATAL ERROR: ").postln;
137 culprits.do({ arg c; if(c.isString,{c.postln},{c.dump}) });
141 error { "ERROR:\n".post; this.postln; }
142 warn { "WARNING:\n".post; this.postln }
143 inform { ^this.postln }
144 ++ { arg anObject; ^this prCat: anObject.asString; }
145 + { arg anObject; ^this prCat: " " prCat: anObject.asString; }
146 catArgs { arg ... items; ^this.catList(items) }
147 scatArgs { arg ... items; ^this.scatList(items) }
148 ccatArgs { arg ... items; ^this.ccatList(items) }
150 // concatenate this with a list as a string
151 var string = this.copy;
152 list.do({ arg item, i;
153 string = string ++ item;
158 var string = this.copy;
159 list.do({ arg item, i;
160 string = string prCat: " " ++ item;
165 var string = this.copy;
166 list.do({ arg item, i;
167 string = string prCat: ", " ++ item;
171 split { arg separator=$/;
174 separator=separator.ascii;
177 if(let.ascii != separator ,{
180 array=array.add(word);
187 containsStringAt { arg index, string;
188 ^compare( this[index..index + string.size-1], string, false) == 0
191 icontainsStringAt { arg index, string;
192 ^compare( this[index..index + string.size-1], string, true) == 0
196 contains { arg string, offset = 0;
197 ^this.find(string, false, offset).notNil
199 containsi { arg string, offset = 0;
200 ^this.find(string, true, offset).notNil
203 findRegexp { arg regexp, offset = 0;
205 ^this.primitiveFailed
208 findAllRegexp { arg string, offset = 0;
209 var indices = [], i=[];
211 i = this.findRegexp(string, offset);
212 i.notNil and: {i.size != 0}
214 indices = indices.add(i);
215 offset = i[0][0] + 1;
220 find { arg string, ignoreCase = false, offset = 0;
222 ^this.primitiveFailed
224 findBackwards { arg string, ignoreCase = false, offset = 0x7FFFFFFE;
225 _String_FindBackwards
226 ^this.primitiveFailed
228 endsWith { arg string;
229 ^this.contains(string, this.size - string.size)
231 beginsWith { arg string;
232 ^this.containsStringAt(0, string)
234 findAll { arg string, ignoreCase = false, offset=0;
237 i = this.find(string, ignoreCase, offset);
240 indices = indices.add(i);
245 replace { arg find, replace;
246 ^super.replace(find, replace).join
250 escapeChar { arg charToEscape; // $"
251 ^this.class.streamContents({ arg st;
253 if(char == charToEscape,{
261 ^"\"" ++ this ++ "\""
264 ^this.collect({ arg char;
265 if(char == from,{to},{char})
269 insert { arg index, string;
270 ^this.keep(index) ++ string ++ this.drop(index)
273 wrapExtend { arg size;
274 ^this.dup(size div: this.size).join
281 padLeft { arg size, string = " ";
282 ^string.wrapExtend(max(0, size - this.size)) ++ this
285 padRight { arg size, string = " ";
286 ^this ++ string.wrapExtend(max(0, size - this.size))
289 underlined { arg char = $-;
290 ^this ++ "\n" ++ String.fill(this.size, char)
294 ^this.as(Array).scramble.as(String)
298 ^this.as(Array).rotate(n).as(String)
301 compile { ^thisProcess.interpreter.compile(this); }
302 interpret { ^thisProcess.interpreter.interpret(this); }
303 interpretPrint { ^thisProcess.interpreter.interpretPrint(this); }
308 prCat { arg aString; _ArrayCat }
310 printOn { arg stream;
313 storeOn { arg stream;
314 stream.putAll(this.asCompileString);
317 inspectorClass { ^StringInspector }
322 _String_StandardizePath
323 ^this.primitiveFailed
326 var sep = thisProcess.platform.pathSeparator;
327 if(this.last != sep, {
333 withoutTrailingSlash {
334 var sep = thisProcess.platform.pathSeparator;
335 if(this.last == sep,{
336 ^this.copyRange(0, this.size-2)
344 sep = thisProcess.platform.pathSeparator;
346 if(first == sep){^this};
347 if(first == $~){^this.standardizePath};
348 ^File.getcwd ++ sep ++ this;
351 pathMatch { _StringPathMatch ^this.primitiveFailed } // glob
353 ^thisProcess.interpreter.executeFile(this);
355 loadPaths { |warn=true|
356 var paths = this.pathMatch;
357 if(warn and:{paths.isEmpty}) { ("no files found for this path:" + this.quote).warn };
358 ^paths.collect({ arg path;
359 thisProcess.interpreter.executeFile(path);
363 var path = thisProcess.nowExecutingPath;
364 if(path.isNil) { Error("can't load relative to an unsaved file").throw};
365 if(path.basename == this) { Error("should not load a file from itself").throw };
366 ^(path.dirname ++ thisProcess.platform.pathSeparator ++ this).loadPaths
369 var path = thisProcess.nowExecutingPath;
370 if(this[0] == thisProcess.platform.pathSeparator, {^this});
371 if(path.isNil) { Error("can't resolve relative to an unsaved file").throw};
372 ^(path.dirname ++ thisProcess.platform.pathSeparator ++ this)
375 if(Quarks.isInstalled(this).not) {
376 Quarks.install(this);
377 "... the class library may have to be recompiled.".postln;
378 // maybe check later whether there are .sc files included.
382 if(Quarks.isInstalled(this)) {
383 Quarks.uninstall(this);
384 "... the class library may have to be recompiled.".postln;
389 ^this.primitiveFailed
393 ^this.primitiveFailed
396 this.reverseDo({ arg char, i;
398 ^[this.copyFromStart(this.size - 2 - i), this.copyToEnd(this.size - i)]
406 var pathSeparator = thisProcess.platform.pathSeparator;
408 if (path.respondsTo(\fullPath)) {
409 ^PathName(this +/+ path.fullPath)
412 if (this.last == pathSeparator or: { path.first == pathSeparator }) {
416 ^this ++ pathSeparator ++ path
419 asRelativePath { |relativeTo|
420 ^PathName(this).asRelativePath(relativeTo)
423 // changed because there is no need to create a separate object
424 // when String already knows how to make an absolute path
425 ^this.absolutePath; // was ^PathName(this).asAbsolutePath
428 // runs a unix command and returns the result code.
429 systemCmd { _String_System ^this.primitiveFailed }
431 gethostbyname { _GetHostByName ^this.primitiveFailed }
433 // gets value of environment variable
436 ^this.primitiveFailed
438 // sets value of environment variable
439 // value may be nil to unset the variable
442 ^this.primitiveFailed
449 codegen_UGenCtorArg { arg stream;
450 stream << this.asCompileString;
452 ugenCodeString { arg ugenIndex, isDecl, inputNames=#[], inputStrings=#[];
454 ^this.primitiveFailed
457 asSecs { |maxDays = 365| // assume a timeString of ddd:hh:mm:ss.sss. see asTimeString.
458 var time = 0, sign = 1, str = this;
459 var limits = [inf, 60, 60, 24, maxDays];
460 var scaling = [0.001, 1.0, 60.0, 3600.0, 86400.0];
461 var padding = [3, 2, 2, 2, 3];
463 if (this.first == $-) {
468 str.split($:).reverseDo { |num, i|
469 num = num.padRight(padding[i], "0").asInteger;
470 if (num > limits[i]) {
471 ("asSecs: number greater than allowed:" + this).warn;
475 ("asSecs: negative numbers within slots not supported:" + this).warn;
478 time = time + (num * scaling[i]);
483 speak { arg channel = 0, force = false;
484 var speech = GUI.current.speech;
485 if( speech.initialized.not, { speech.init });
486 speech.channels[ channel ].speak( this, force );
490 ^this.collect(_.toLower)
493 ^this.collect(_.toUpper)