[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[sc-users] Re: string formatting notation
Sorry to prolong this, but there was a mistake in the preprocessor...
corrected here.
hjh
(
var
convertFStrings = { |code|
var stream = CollStream(code), out = String.new, ch, closeQuote;
while {
ch = stream.next;
ch.notNil
} {
case
{ ch == $f and: { stream.peek == $" } } {
stream.next; // swallow quote
out = out ++ parseFString.(stream);
}
{ ch == $" or: { ch == $' } } { // scan a whole normal string/symbol
literal, with escapes
closeQuote = ch;
out = out ++ ch;
while {
ch = stream.next;
ch.notNil and: { ch != closeQuote }
} {
if(ch == $\\) {
out = out ++ ch ++ stream.next; // escape, esp. for quotes
} {
out = out ++ ch;
}
};
if(ch.notNil) { out = out ++ ch };
}
{
out = out ++ ch;
};
};
out;
},
parseFString = { |stream|
// assumes 'f"' is already scanned; return: code converted to
"str".format(...)
var start = stream.pos, list = List.new, formatStr = String.new, out, ch;
while {
ch = stream.next;
ch.notNil and: { ch != $" }
} {
if(ch == ${ and: { stream.peek == ${ }) {
stream.next; // swallow second brace
parseOneExpression.(stream, list);
formatStr = formatStr ++ "%";
} {
formatStr = formatStr ++ ch;
};
};
if(ch.isNil) {
Error("open-ended f-string: %".format(stream.collection[start .. start +
20])).throw;
};
if(list.size >= 1) { // .format only if there's something to format
out = CollStream.new;
out << $" << formatStr << $" << ".format(";
list.do { |expr, i|
if(i > 0) { out << ", " };
out << expr;
};
out << ")";
out.collection
} {
// -1 -- we need the opening quote, and don't include .next char
stream.collection[start - 1.. stream.pos - 1]
}
},
parseOneExpression = { |stream, list|
// assumes '{{' is already scanned; result: item added to list
var start = stream.pos, out = String.new, ch;
while {
ch = stream.next;
ch.notNil and: { ch != $} or: { stream.peek != $} } }
} {
// check for nested f-string
if(ch == $f and: { stream.peek == $" }) {
stream.next; // swallow quote
out = out ++ parseFString.(stream);
} {
out = out ++ ch;
};
};
if(ch.isNil) {
Error("open-ended string interpolation argument: %".format(
stream.collection[start .. start + 20]
)).throw;
};
list.add(out);
stream.next; // scan second brace
stream
};
// some tests
c = CollStream("abc}}xyz");
l = List.new;
parseOneExpression.(c, l);
l.debug("list, expected [ \"abc\" ]");
c.collection[c.pos..c.pos+5].debug("stream state, expected \"xyz\"");
c = CollStream("abc = {{abc}}\"; xyz");
parseFString.(c).debug("parseFString test");
c = "var abc = 10.rand; f\"abc = {{abc ++ f\"nested string
{{xyz}}\"}}\".postln;";
convertFStrings.(c).debug("nested conversion");
c = "\"normal \\\"string\\\" ending with f\".postln";
convertFStrings.(c).debug("escaped \"quotes\" and closing f");
c = "'abcdef\"xyz'";
convertFStrings.(c).debug("weird symbol");
try {
convertFStrings.("f\"{{abc}xyz\"")
} { |error|
if(error.errorString.beginsWith("ERROR: open-ended string interpolation
argument")) {
"open-ended string interpolation argument detected OK".debug;
} {
error.throw;
}
};
try {
convertFStrings.("f\"{{abc}}xyz; 123")
} { |error|
if(error.errorString.beginsWith("ERROR: open-ended f-string")) {
"open-ended f-string detected OK".debug;
} {
error.throw;
}
};
thisProcess.interpreter.preProcessor = convertFStrings;
)
--
Sent from: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html
_______________________________________________
sc-users mailing list
info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: https://listarc.bham.ac.uk/marchives/sc-users/
search: https://listarc.bham.ac.uk/lists/sc-users/search/