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; // $"
255 ^"\"" ++ this ++ "\""
258 ^this.collect({ arg char;
259 if(char == from,{to},{char})
263 insert { arg index, string;
264 ^this.keep(index) ++ string ++ this.drop(index)
267 wrapExtend { arg size;
268 ^this.dup(size div: this.size).join
275 padLeft { arg size, string = " ";
276 ^string.wrapExtend(max(0, size - this.size)) ++ this
279 padRight { arg size, string = " ";
280 ^this ++ string.wrapExtend(max(0, size - this.size))
283 underlined { arg char = $-;
284 ^this ++ "\n" ++ String.fill(this.size, char)
288 ^this.as(Array).scramble.as(String)
292 ^this.as(Array).rotate(n).as(String)
295 compile { ^thisProcess.interpreter.compile(this); }
296 interpret { ^thisProcess.interpreter.interpret(this); }
297 interpretPrint { ^thisProcess.interpreter.interpretPrint(this); }
302 prCat { arg aString; _ArrayCat }
304 printOn { arg stream;
307 storeOn { arg stream;
308 stream.putAll(this.asCompileString);
311 inspectorClass { ^StringInspector }
316 _String_StandardizePath
317 ^this.primitiveFailed
321 ^this.primitiveFailed
324 var sep = thisProcess.platform.pathSeparator;
325 if(this.last != sep, {
331 withoutTrailingSlash {
332 var sep = thisProcess.platform.pathSeparator;
333 if(this.last == sep,{
334 ^this.copyRange(0, this.size-2)
342 sep = thisProcess.platform.pathSeparator;
344 if(first == sep){^this};
345 if(first == $~){^this.standardizePath};
346 ^File.getcwd ++ sep ++ this;
349 pathMatch { _StringPathMatch ^this.primitiveFailed } // glob
351 ^thisProcess.interpreter.executeFile(this);
353 loadPaths { |warn=true|
354 var paths = this.pathMatch;
355 if(warn and:{paths.isEmpty}) { ("no files found for this path:" + this.quote).warn };
356 ^paths.collect({ arg path;
357 thisProcess.interpreter.executeFile(path);
361 var path = thisProcess.nowExecutingPath;
362 if(path.isNil) { Error("can't load relative to an unsaved file").throw};
363 if(path.basename == this) { Error("should not load a file from itself").throw };
364 ^(path.dirname ++ thisProcess.platform.pathSeparator ++ this).loadPaths
368 caller = thisMethod.getBackTrace.caller.functionDef;
369 if(caller == Interpreter.findMethod(\interpretPrintCmdLine), {
370 path = thisProcess.nowExecutingPath;
372 path = caller.filenameSymbol.asString;
374 if(this[0] == thisProcess.platform.pathSeparator, {^this});
375 if(path.isNil) { Error("can't resolve relative to an unsaved file").throw};
376 ^(path.dirname ++ thisProcess.platform.pathSeparator ++ this)
379 if(Quarks.isInstalled(this).not) {
380 Quarks.install(this);
381 "... the class library may have to be recompiled.".postln;
382 // maybe check later whether there are .sc files included.
386 if(Quarks.isInstalled(this)) {
387 Quarks.uninstall(this);
388 "... the class library may have to be recompiled.".postln;
393 ^this.primitiveFailed
397 ^this.primitiveFailed
400 this.reverseDo({ arg char, i;
402 ^[this.copyFromStart(this.size - 2 - i), this.copyToEnd(this.size - i)]
410 var pathSeparator = thisProcess.platform.pathSeparator;
412 if (path.respondsTo(\fullPath)) {
413 ^PathName(this +/+ path.fullPath)
416 if (this.last == pathSeparator or: { path.first == pathSeparator }) {
420 ^this ++ pathSeparator ++ path
423 asRelativePath { |relativeTo|
424 ^PathName(this).asRelativePath(relativeTo)
427 // changed because there is no need to create a separate object
428 // when String already knows how to make an absolute path
429 ^this.absolutePath; // was ^PathName(this).asAbsolutePath
432 // runs a unix command and returns the result code.
433 systemCmd { _String_System ^this.primitiveFailed }
435 gethostbyname { _GetHostByName ^this.primitiveFailed }
437 // gets value of environment variable
440 ^this.primitiveFailed
442 // sets value of environment variable
443 // value may be nil to unset the variable
446 ^this.primitiveFailed
453 codegen_UGenCtorArg { arg stream;
454 stream << this.asCompileString;
456 ugenCodeString { arg ugenIndex, isDecl, inputNames=#[], inputStrings=#[];
458 ^this.primitiveFailed
461 asSecs { |maxDays = 365| // assume a timeString of ddd:hh:mm:ss.sss. see asTimeString.
462 var time = 0, sign = 1, str = this;
463 var limits = [inf, 60, 60, 24, maxDays];
464 var scaling = [0.001, 1.0, 60.0, 3600.0, 86400.0];
465 var padding = [3, 2, 2, 2, 3];
467 if (this.first == $-) {
472 str.split($:).reverseDo { |num, i|
473 num = num.padRight(padding[i], "0").asInteger;
474 if (num > limits[i]) {
475 ("asSecs: number greater than allowed:" + this).warn;
479 ("asSecs: negative numbers within slots not supported:" + this).warn;
482 time = time + (num * scaling[i]);
487 speak { arg channel = 0, force = false;
488 var speech = GUI.current.speech;
489 if( speech.initialized.not, { speech.init });
490 speech.channels[ channel ].speak( this, force );
494 ^this.collect(_.toLower)
497 ^this.collect(_.toUpper)