1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-19 06:07:42 +02:00

Change tokenization of header comment lines & translate strings ...

... allowing (_ "...") for single strings, and allowing a sequence of such
inside outer ( ) for choice controls, but still accepting the old syntax too
This commit is contained in:
Paul Licameli 2018-02-27 18:32:59 -05:00
parent 0879949904
commit ba8e6bd465
2 changed files with 126 additions and 52 deletions

View File

@ -329,7 +329,7 @@ bool NyquistEffect::DefineParams( ShuttleParams & S )
} }
else if (ctrl.type == NYQ_CTRL_CHOICE) else if (ctrl.type == NYQ_CTRL_CHOICE)
{ {
wxArrayString choices = ParseChoice(ctrl); const wxArrayString &choices = ctrl.choices;
int x=d; int x=d;
//parms.WriteEnum(ctrl.var, (int) d, choices); //parms.WriteEnum(ctrl.var, (int) d, choices);
S.DefineEnum( x, static_cast<const wxChar*>( ctrl.var.c_str() ), 0, choices ); S.DefineEnum( x, static_cast<const wxChar*>( ctrl.var.c_str() ), 0, choices );
@ -378,7 +378,7 @@ bool NyquistEffect::GetAutomationParameters(CommandParameters & parms)
} }
else if (ctrl.type == NYQ_CTRL_CHOICE) else if (ctrl.type == NYQ_CTRL_CHOICE)
{ {
wxArrayString choices = ParseChoice(ctrl); const wxArrayString &choices = ctrl.choices;
parms.WriteEnum(ctrl.var, (int) d, choices); parms.WriteEnum(ctrl.var, (int) d, choices);
} }
else if (ctrl.type == NYQ_CTRL_STRING) else if (ctrl.type == NYQ_CTRL_STRING)
@ -428,7 +428,7 @@ bool NyquistEffect::SetAutomationParameters(CommandParameters & parms)
else if (ctrl.type == NYQ_CTRL_CHOICE) else if (ctrl.type == NYQ_CTRL_CHOICE)
{ {
int val; int val;
wxArrayString choices = ParseChoice(ctrl); const wxArrayString &choices = ctrl.choices;
good = parms.ReadEnum(ctrl.var, &val, choices) && good = parms.ReadEnum(ctrl.var, &val, choices) &&
val != wxNOT_FOUND; val != wxNOT_FOUND;
} }
@ -468,7 +468,7 @@ bool NyquistEffect::SetAutomationParameters(CommandParameters & parms)
else if (ctrl.type == NYQ_CTRL_CHOICE) else if (ctrl.type == NYQ_CTRL_CHOICE)
{ {
int val {0}; int val {0};
wxArrayString choices = ParseChoice(ctrl); const wxArrayString &choices = ctrl.choices;
parms.ReadEnum(ctrl.var, &val, choices); parms.ReadEnum(ctrl.var, &val, choices);
ctrl.val = (double) val; ctrl.val = (double) val;
} }
@ -1469,13 +1469,25 @@ wxString NyquistEffect::EscapeString(const wxString & inStr)
return str; return str;
} }
wxArrayString NyquistEffect::ParseChoice(const NyqControl & ctrl) wxArrayString NyquistEffect::ParseChoice(const wxString & text)
{ {
wxArrayString choices = wxStringTokenize(ctrl.label, wxT(",")); wxArrayString choices;
if (text[0] == wxT('(')) {
for (size_t i = 0, cnt = choices.GetCount();i < cnt; i++) // New style: expecting a Lisp-like list of strings
{ Tokenize(text, choices, 1, 1);
choices[i] = choices[i].Trim(true).Trim(false); for (auto &choice : choices)
choice = UnQuote(choice);
}
else {
// Old style: expecting a comma-separated list of
// un-internationalized names, ignoring leading and trailing spaces
// on each; and the whole may be quoted
choices = wxStringTokenize(
text[0] == wxT('"') ? text.Mid(1, text.Length() - 2) : text,
wxT(",")
);
for (auto &choice : choices)
choice = choice.Trim(true).Trim(false);
} }
return choices; return choices;
@ -1508,15 +1520,27 @@ void NyquistEffect::Stop()
mStop = true; mStop = true;
} }
wxString NyquistEffect::UnQuote(const wxString &s) wxString NyquistEffect::UnQuote(
const wxString &s, bool allowParens, bool translate)
{ {
wxString out;
int len = s.Length(); int len = s.Length();
if (len >= 2 && s[0] == wxT('\"') && s[len - 1] == wxT('\"')) { if (len >= 2 && s[0] == wxT('\"') && s[len - 1] == wxT('\"')) {
return s.Mid(1, len - 2); auto unquoted = s.Mid(1, len - 2);
return translate ? GetCustomTranslation( unquoted ) : unquoted;
} }
else if (allowParens &&
len >= 2 && s[0] == wxT('(') && s[len - 1] == wxT(')')) {
wxArrayString tokens;
Tokenize(s, tokens, 1, 1);
if (tokens.size() > 1)
// Assume the first token was _ -- we don't check that
// And the second is the string, which is internationalized
return UnQuote( tokens[1], false, true );
else
return {};
}
else
// If string was not quoted, assume no translation exists
return s; return s;
} }
@ -1540,51 +1564,83 @@ double NyquistEffect::GetCtrlValue(const wxString &s)
return Internat::CompatibleToDouble(s); return Internat::CompatibleToDouble(s);
} }
void NyquistEffect::Parse(const wxString &line) void NyquistEffect::Tokenize(
const wxString &line, wxArrayString &tokens,
size_t trimStart, size_t trimEnd)
{ {
wxArrayString tokens;
int i;
int len = line.Length();
bool sl = false; bool sl = false;
bool q = false; bool q = false;
wxString tok = wxT(""); wxString tok = wxT("");
int paren = 0;
for (i = 1; i < len; i++) { auto endToken = [&]{
wxChar c = line[i]; if (!tok.empty()) {
tokens.push_back(tok);
if (c == wxT('\\')) {
sl = true;
}
else if (c == wxT('"')) {
q = !q;
}
else {
if ((!q && !sl && c == wxT(' ')) || c == wxT('\t')) {
tokens.Add(tok);
tok = wxT(""); tok = wxT("");
} }
else if (sl && c == wxT('n')) { };
tok += wxT('\n');
for (auto c :
make_iterator_range(line.begin() + trimStart, line.end() - trimEnd)) {
if (q && c == wxT('\\')) {
// begin escaped character, only within quotes
sl = true;
continue;
} }
else { else if (sl && c == wxT('n'))
c = wxT('\n');
if (!sl && !paren && c == wxT('"')) {
if (!q)
// finish previous token; begin token, including the delimiter
endToken(), q = true, tok += c;
else
// end token, including the delimiter
tok += c, q = false, endToken();
}
else if (!q && !paren && (c == wxT(' ') || c == wxT('\t')))
// Separate tokens; don't accumulate this character
endToken();
else if (!q && c == wxT('(')) {
if (++paren == 1)
// finish previous token; begin list, including the delimiter
endToken(), tok += c;
else
// defer tokenizing of nested list to a later pass over the token
tok += c; tok += c;
} }
else if (!q && c == wxT(')')) {
if (--paren == 0)
// finish list, including the delimiter
tok += c, endToken();
else if (paren < 0)
// forgive unbalanced right paren
paren = 0, endToken();
else
// nested list; deferred tokenizing
tok += c;
}
else
tok += c;
sl = false; sl = false;
} }
}
if (tok != wxT("")) { // Finish -- this just forgives unbalanced open quotes or left parens
tokens.Add(tok); endToken();
} }
len = tokens.GetCount(); void NyquistEffect::Parse(const wxString &line)
{
wxArrayString tokens;
Tokenize(line, tokens, 1, 0);
int len = tokens.size();
if (len < 1) { if (len < 1) {
return; return;
} }
// Consistency decission is for "plug-in" as the correct spelling // Consistency decision is for "plug-in" as the correct spelling
// "plugin" (deprecated) is allowed as an undocumented convenience. // "plugin" (deprecated) is allowed as an undocumented convenience.
if (len == 2 && tokens[0] == wxT("nyquist") && if (len == 2 && tokens[0] == wxT("nyquist") &&
(tokens[1] == wxT("plug-in") || tokens[1] == wxT("plugin"))) { (tokens[1] == wxT("plug-in") || tokens[1] == wxT("plugin"))) {
@ -1665,9 +1721,7 @@ void NyquistEffect::Parse(const wxString &line)
if (len >= 2 && tokens[0] == wxT("name")) { if (len >= 2 && tokens[0] == wxT("name")) {
mName = UnQuote(tokens[1]); mName = UnQuote(tokens[1]);
if (mName.EndsWith(wxT("..."))) if (mName.EndsWith(wxT("...")))
{
mName = mName.RemoveLast(3); mName = mName.RemoveLast(3);
}
return; return;
} }
@ -1739,14 +1793,16 @@ void NyquistEffect::Parse(const wxString &line)
// TODO: Document. // TODO: Document.
// Page name in Audacity development manual // Page name in Audacity development manual
if (len >= 2 && tokens[0] == wxT("manpage")) { if (len >= 2 && tokens[0] == wxT("manpage")) {
mManPage = UnQuote(tokens[1]); // do not translate
mManPage = UnQuote(tokens[1], false, false);
return; return;
} }
// TODO: Document. // TODO: Document.
// Local Help file // Local Help file
if (len >= 2 && tokens[0] == wxT("helpfile")) { if (len >= 2 && tokens[0] == wxT("helpfile")) {
mHelpFile = UnQuote(tokens[1]); // do not translate
mHelpFile = UnQuote(tokens[1], false, false);
return; return;
} }
@ -1763,18 +1819,31 @@ void NyquistEffect::Parse(const wxString &line)
NyqControl ctrl; NyqControl ctrl;
ctrl.var = tokens[1]; ctrl.var = tokens[1];
ctrl.name = tokens[2]; ctrl.name = UnQuote( tokens[2] );
// 3 is type, below
ctrl.label = tokens[4]; ctrl.label = tokens[4];
// valStr may or may not be a quoted string
ctrl.valStr = tokens[5]; ctrl.valStr = tokens[5];
ctrl.val = GetCtrlValue(ctrl.valStr); ctrl.val = GetCtrlValue(ctrl.valStr);
if (ctrl.valStr[0] == wxT('(') || ctrl.valStr[0] == wxT('"'))
ctrl.valStr = UnQuote( ctrl.valStr );
// 6 is minimum, below
// 7 is maximum, below
if (tokens[3] == wxT("string")) { if (tokens[3] == wxT("string")) {
ctrl.type = NYQ_CTRL_STRING; ctrl.type = NYQ_CTRL_STRING;
ctrl.label = UnQuote( ctrl.label );
} }
else if (tokens[3] == wxT("choice")) { else if (tokens[3] == wxT("choice")) {
ctrl.type = NYQ_CTRL_CHOICE; ctrl.type = NYQ_CTRL_CHOICE;
ctrl.choices = ParseChoice(ctrl.label);
ctrl.label = wxT("");
} }
else { else {
ctrl.label = UnQuote( ctrl.label );
if (len < 8) { if (len < 8) {
return; return;
} }
@ -2124,7 +2193,7 @@ bool NyquistEffect::TransferDataToEffectWindow()
if (ctrl.type == NYQ_CTRL_CHOICE) if (ctrl.type == NYQ_CTRL_CHOICE)
{ {
wxArrayString choices = ParseChoice(ctrl); const wxArrayString &choices = ctrl.choices;
int val = (int)ctrl.val; int val = (int)ctrl.val;
if (val < 0 || val >= (int)choices.GetCount()) if (val < 0 || val >= (int)choices.GetCount())
@ -2288,7 +2357,7 @@ void NyquistEffect::BuildEffectWindow(ShuttleGui & S)
{ {
S.AddSpace(10, 10); S.AddSpace(10, 10);
wxArrayString choices = wxStringTokenize(ctrl.label, wxT(",")); const wxArrayString &choices = ctrl.choices;
S.Id(ID_Choice + i).AddChoice( {}, wxT(""), &choices); S.Id(ID_Choice + i).AddChoice( {}, wxT(""), &choices);
} }
else else

View File

@ -56,6 +56,7 @@ public:
wxString var; wxString var;
wxString name; wxString name;
wxString label; wxString label;
wxArrayString choices;
wxString valStr; wxString valStr;
wxString lowStr; wxString lowStr;
wxString highStr; wxString highStr;
@ -141,7 +142,7 @@ private:
static wxString NyquistToWxString(const char *nyqString); static wxString NyquistToWxString(const char *nyqString);
wxString EscapeString(const wxString & inStr); wxString EscapeString(const wxString & inStr);
wxArrayString ParseChoice(const NyqControl & ctrl); static wxArrayString ParseChoice(const wxString & text);
static int StaticGetCallback(float *buffer, int channel, static int StaticGetCallback(float *buffer, int channel,
long start, long len, long totlen, long start, long len, long totlen,
@ -162,9 +163,13 @@ private:
void ParseFile(); void ParseFile();
bool ParseCommand(const wxString & cmd); bool ParseCommand(const wxString & cmd);
bool ParseProgram(wxInputStream & stream); bool ParseProgram(wxInputStream & stream);
static void Tokenize(
const wxString &line, wxArrayString &tokens,
size_t trimStart, size_t trimEnd);
void Parse(const wxString &line); void Parse(const wxString &line);
wxString UnQuote(const wxString &s); static wxString UnQuote(const wxString &s,
bool allowParens = true, bool translate = true);
double GetCtrlValue(const wxString &s); double GetCtrlValue(const wxString &s);
void OnLoad(wxCommandEvent & evt); void OnLoad(wxCommandEvent & evt);