From f06333af1b154659d5c464d3cbe878ad0ecc3d7c Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Wed, 20 Sep 2017 10:49:12 +0200 Subject: [PATCH] word input enclosed in single quotes may contain blanks; coord name(unit) now considered a word, not a string --- pub/CHANGELOG | 7 +++++++ pub/ftest/oz.f2t | 2 +- pub/ftest/r_of_i.f2t | 6 ++++-- pub/lib/coord.cpp | 2 +- pub/readplus/macro.cpp | 25 +++++++++++++++---------- pub/trivia/string_ops.cpp | 35 ++++++++++++++++++++++++++++++++++- pub/trivia/string_ops.hpp | 32 ++++++++++++++++---------------- 7 files changed, 78 insertions(+), 31 deletions(-) diff --git a/pub/CHANGELOG b/pub/CHANGELOG index 1dfce038..7540401e 100644 --- a/pub/CHANGELOG +++ b/pub/CHANGELOG @@ -1,3 +1,10 @@ +Release + +- UI changes: + - word input enclosed in single quotes may contain blanks + - coord name(unit) now considered a word, not a string + - commands oz+ and or+ now ask for coord name and unit + Release 2.4.0g of 11aug17: - Support error bars in Load_96 and in fe2 diff --git a/pub/ftest/oz.f2t b/pub/ftest/oz.f2t index ac64e68c..2575b5a9 100755 --- a/pub/ftest/oz.f2t +++ b/pub/ftest/oz.f2t @@ -1,6 +1,6 @@ #!/usr/bin/env frida fm 7 3 h -oz+ "myz()" 100*j +oz+ myz() 100*j mz- 0 exit_unless(z0[,2]==200,"failed") exit(0) \ No newline at end of file diff --git a/pub/ftest/r_of_i.f2t b/pub/ftest/r_of_i.f2t index 357fa219..f56fa91b 100755 --- a/pub/ftest/r_of_i.f2t +++ b/pub/ftest/r_of_i.f2t @@ -1,6 +1,8 @@ #!/usr/bin/env frida fm 1 1 h -or+ "my_r()" 77 +or+ my_r() 77 +or+ 'coord name with blanks(unit with blanks)' 88 oy r0[1+i] -exit_unless(y==77,"result_wrong") +exit_unless(y==77,"r0_to_y_wrong") +exit_unless(r1==88,"r1_wrong") exit(0) \ No newline at end of file diff --git a/pub/lib/coord.cpp b/pub/lib/coord.cpp index 13161e19..622bfb55 100644 --- a/pub/lib/coord.cpp +++ b/pub/lib/coord.cpp @@ -56,7 +56,7 @@ void CCoord::ask_and_set(const string& quest) prompt += " [" + str_std() + "]"; prompt += " ? "; for (;;) { - string resp = NMacro::readln(prompt); + string resp = NMacro::readwd(prompt); if (resp == "\\q") { throw S("user escape to main menu"); } else if (resp == "") { diff --git a/pub/readplus/macro.cpp b/pub/readplus/macro.cpp index 33f45932..a755b498 100644 --- a/pub/readplus/macro.cpp +++ b/pub/readplus/macro.cpp @@ -26,15 +26,15 @@ using std::cout; namespace NMacro { // internals, used only in this file: -std::deque<string> stack; + std::deque<string> stack; // the following are only called indirectly through macros: -void metacmd_incl(string r); + void metacmd_incl(string r); // auxiliary: -string wordexp_cpp_unique(const string& s); -string string_extract_quoted(string* in); -bool is_separator(char c); + string wordexp_cpp_unique(const string& s); + string string_extract_quoted(string* in); + bool is_separator(char c); } @@ -79,6 +79,15 @@ string NMacro::readln(const string& prompt, ifstream* F, int* lineno) string NMacro::readwd(const string& prompt) { string in = readln(prompt); + if (in[0] == '\'') { // string enclosed in quotes, may contain spaces + string::size_type j = triv::pos_closing(in); + if (j+1 < in.length()) { + if (!is_separator(in[j+1])) + throw "closing quote followed by non-space character"; + push_remainder(in.substr(j+2)); + } + return in.substr(1, j-1); + } string::size_type j = in.find_first_of(" \t"); if (j != string::npos) { push_remainder(in.substr(j)); @@ -128,14 +137,10 @@ string NMacro::exemac(const string& in) //************************************************************************************************** -//! Push _rem_ back on the input stack. +//! Left-trims the argument, and puts it back on the input stack. void NMacro::push_remainder(const string& rem) { - if (rem == "") - return; // nothing to do - if (!is_separator(rem[0])) - throw "missing separator at beginning of [" + rem + "]"; string::size_type j = rem.find_first_not_of(" \t"); if (j != string::npos) stack.push_front(rem.substr(j)); diff --git a/pub/trivia/string_ops.cpp b/pub/trivia/string_ops.cpp index 85b0808b..b730295d 100644 --- a/pub/trivia/string_ops.cpp +++ b/pub/trivia/string_ops.cpp @@ -85,7 +85,7 @@ void triv::string_extract_word(const string& in, string* out1, string* out2) { string::size_type j0 = 0, j1, j2, jf = in.size(); - // handle special case "`" + // handle special case "`" // TODO: check if needed; reimplement using pos_closing if (in[0] == '`') { j1 = in.find_first_of('`', 1); if (j1 == string::npos) { @@ -151,3 +151,36 @@ vector<string> triv::split(const string& in, const string& delimiters) } return out; } + +//! For string starting with a delimiter, return position of matching delimiter. +//! INCOMPLETE. Currently only supports '. +//! Has unit test 003 (StrOpsTest, PosClosing). + +std::string::size_type triv::pos_closing(const std::string& in) +{ + char opener = in[0]; + char closer = 0; + switch (opener) { + case '\'': + closer = '\''; break; + /* NOT YET SUPPORTED: + case '"': + closer = '"'; break; + case '(': + closer = ')'; break; + case '[': + closer = ']'; break; + case '{': + closer = '}'; break; + */ + default: + throw "BUG: pos_closing("+in+"): arg does not start with supported delimiter"; + } + for (string::size_type j=1; j<in.length(); ++j) { + if (in[j-1]=='\\') + continue; + if (in[j]==closer) + return j; + } + throw string("Unmatched ")+opener+" in "+in; +} diff --git a/pub/trivia/string_ops.hpp b/pub/trivia/string_ops.hpp index 27dc76f0..40ac1e37 100644 --- a/pub/trivia/string_ops.hpp +++ b/pub/trivia/string_ops.hpp @@ -12,25 +12,25 @@ #include <string> #include <vector> -namespace triv -{ +namespace triv { -bool str2vec(std::string inp, std::vector<double>* V, size_t nmax = 0, bool force = true); -void string_extract_word(const std::string& in, std::string* out1, std::string* out2); -void string_extract_line(const std::string& in, std::string* out1, std::string* out2); -std::vector<std::string> split(const std::string& in, const std::string& delimiters = " \t"); -std::string strip(const std::string& str, const char* sepSet = " \n"); + bool str2vec(std::string inp, std::vector<double>* V, size_t nmax = 0, bool force = true); + void string_extract_word(const std::string& in, std::string* out1, std::string* out2); + void string_extract_line(const std::string& in, std::string* out1, std::string* out2); + std::vector<std::string> split(const std::string& in, const std::string& delimiters = " \t"); + std::string strip(const std::string& str, const char* sepSet = " \n"); + std::string::size_type pos_closing(const std::string& str); -template <class T> std::string join(const std::vector<T>& v, const std::string& separator) -{ - std::ostringstream result; - for (auto i = v.begin(); i != v.end(); i++) { - if (i != v.begin()) - result << separator; - result << *i; + template <class T> std::string join(const std::vector<T>& v, const std::string& separator) + { + std::ostringstream result; + for (auto i = v.begin(); i != v.end(); i++) { + if (i != v.begin()) + result << separator; + result << *i; + } + return result.str(); } - return result.str(); -} } #endif // STRING_OPS_H -- GitLab