/[svn]/linuxsampler/trunk/src/shell/lscp.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/shell/lscp.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2515 by schoenebeck, Wed Feb 5 20:45:18 2014 UTC revision 2516 by schoenebeck, Thu Feb 6 21:11:23 2014 UTC
# Line 30  using namespace LinuxSampler; Line 30  using namespace LinuxSampler;
30  static LSCPClient g_client;  static LSCPClient g_client;
31  static KeyboardReader g_keyboardReader;  static KeyboardReader g_keyboardReader;
32  static Condition g_todo;  static Condition g_todo;
33    static String g_goodPortion;
34    static String g_badPortion;
35    static String g_suggestedPortion;
36    
37  static void printUsage() {  static void printUsage() {
38      cout << "lscp - The LinuxSampler Control Protocol (LSCP) Shell." << endl;      cout << "lscp - The LinuxSampler Control Protocol (LSCP) Shell." << endl;
# Line 40  static void printUsage() { Line 43  static void printUsage() {
43      cout << endl;      cout << endl;
44      cout << "   -p  TCP port number of LSCP server (default " << LSCP_DEFAULT_PORT << ")." << endl;      cout << "   -p  TCP port number of LSCP server (default " << LSCP_DEFAULT_PORT << ")." << endl;
45      cout << endl;      cout << endl;
46        cout << "   --no-auto-correct  Don't perform auto correction of obvious syntax errors." << endl;
47        cout << endl;
48  }  }
49    
50  // Called by the network reading thread, whenever new data arrived from the  // Called by the network reading thread, whenever new data arrived from the
# Line 53  static void onNewKeyboardInputAvailable( Line 58  static void onNewKeyboardInputAvailable(
58      g_todo.Set(true);      g_todo.Set(true);
59  }  }
60    
61    static void autoComplete() {
62        if (g_suggestedPortion.empty()) return;
63        String s;
64        // let the server delete mistaken characters first
65        for (int i = 0; i < g_badPortion.size(); ++i) s += '\b';
66        // now add the suggested, correct characters
67        s += g_suggestedPortion;
68        g_suggestedPortion.clear();
69        g_client.send(s);
70    }
71    
72  int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
73      String host = LSCP_DEFAULT_HOST;      String host = LSCP_DEFAULT_HOST;
74      int port    = LSCP_DEFAULT_PORT;      int port    = LSCP_DEFAULT_PORT;
75        bool autoCorrect = true;
76    
77      // parse command line arguments      // parse command line arguments
78      for (int i = 0; i < argc; ++i) {      for (int i = 0; i < argc; ++i) {
# Line 76  int main(int argc, char *argv[]) { Line 93  int main(int argc, char *argv[]) {
93                  cerr << "Error: invalid port argument \"" << argv[i] << "\"\n";                  cerr << "Error: invalid port argument \"" << argv[i] << "\"\n";
94                  return -1;                  return -1;
95              }              }
96            } else if (s == "--no-auto-correct") {
97                autoCorrect = false;
98          } else if (s[0] == '-') { // invalid / unknown command line argument ...          } else if (s[0] == '-') { // invalid / unknown command line argument ...
99              printUsage();              printUsage();
100              return -1;              return -1;
# Line 86  int main(int argc, char *argv[]) { Line 105  int main(int argc, char *argv[]) {
105      // receiving incoming network data from the sampler's LSCP server      // receiving incoming network data from the sampler's LSCP server
106      g_client.setCallback(onLSCPClientNewInputAvailable);      g_client.setCallback(onLSCPClientNewInputAvailable);
107      if (!g_client.connect(host, port)) return -1;      if (!g_client.connect(host, port)) return -1;
108      String sResponse = g_client.sendCommandSync("SET SHELL INTERACT 1");      String sResponse = g_client.sendCommandSync(
109            (autoCorrect) ? "SET SHELL AUTO_CORRECT 1" : "SET SHELL AUTO_CORRECT 0"
110        );
111        sResponse = g_client.sendCommandSync("SET SHELL INTERACT 1");
112      if (sResponse.substr(0, 2) != "OK") {      if (sResponse.substr(0, 2) != "OK") {
113          cerr << "Error: sampler too old, it does not support shell instructions\n";          cerr << "Error: sampler too old, it does not support shell instructions\n";
114          return -1;          return -1;
# Line 116  int main(int argc, char *argv[]) { Line 138  int main(int argc, char *argv[]) {
138                  if (res >= 1) {                                      if (res >= 1) {                    
139                      String s = line.substr(n);                      String s = line.substr(n);
140    
141                      String key = LSCP_SHK_GOOD_FRONT;                      // extract portion that is already syntactically correct
142                      size_t i = s.find(key);                      size_t iGood = s.find(LSCP_SHK_GOOD_FRONT);
143                      String sGood = s.substr(0, i);                      String sGood = s.substr(0, iGood);
144                      String sBad  = s.substr(i + key.length());                      if (sGood.find(LSCP_SHK_CURSOR) != string::npos)
145                      //printf("line '%s' good='%s' bad='%s'\n", line.c_str(), sGood.c_str(), sBad.c_str());                          sGood.erase(sGood.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker
146    
147                      CCursor cursor = CCursor::now();                      // extract portion that was written syntactically incorrect
148                      cursor.toColumn(0);                      String sBad = s.substr(iGood + strlen(LSCP_SHK_GOOD_FRONT));
149                      cursor.clearLine();                      if (sBad.find(LSCP_SHK_CURSOR) != string::npos)
150                            sBad.erase(sBad.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker
151                        if (sBad.find(LSCP_SHK_SUGGEST_BACK) != string::npos)
152                            sBad.erase(sBad.find(LSCP_SHK_SUGGEST_BACK)); // erase auto suggestion portion
153    
154                        // extract portion that is suggested for auto completion
155                        String sSuggest;
156                        if (s.find(LSCP_SHK_SUGGEST_BACK) != string::npos) {
157                            sSuggest = s.substr(s.find(LSCP_SHK_SUGGEST_BACK) + strlen(LSCP_SHK_SUGGEST_BACK));
158                            if (sSuggest.find(LSCP_SHK_CURSOR) != string::npos)
159                                sSuggest.erase(sSuggest.find(LSCP_SHK_CURSOR), strlen(LSCP_SHK_CURSOR)); // erase cursor marker
160                        }
161    
162                        // extract current cursor position
163                        int cursorColumn = sGood.size();
164                        String sCursor = s;
165                        if (sCursor.find(LSCP_SHK_GOOD_FRONT) != string::npos)
166                            sCursor.erase(sCursor.find(LSCP_SHK_GOOD_FRONT), strlen(LSCP_SHK_GOOD_FRONT)); // erase good/bad marker
167                        if (sCursor.find(LSCP_SHK_SUGGEST_BACK) != string::npos)
168                            sCursor.erase(sCursor.find(LSCP_SHK_SUGGEST_BACK), strlen(LSCP_SHK_SUGGEST_BACK)); // erase suggestion marker
169                        if (sCursor.find(LSCP_SHK_CURSOR) != string::npos)
170                            cursorColumn = sCursor.find(LSCP_SHK_CURSOR);
171    
172                        // store those informations globally for the auto-completion
173                        // feature
174                        g_goodPortion      = sGood;
175                        g_badPortion       = sBad;
176                        g_suggestedPortion = sSuggest;
177    
178                        //printf("line '%s' good='%s' bad='%s' suggested='%s' cursor=%d\n", line.c_str(), sGood.c_str(), sBad.c_str(), sSuggest.c_str(), cursorColumn);
179    
180                        CCursor cursor = CCursor::now().toColumn(0).clearLine();
181    
182                      CFmt cfmt;                      CFmt cfmt;
183                      if (code == LSCP_SHU_COMPLETE) cfmt.bold().green();                      if (code == LSCP_SHU_COMPLETE) cfmt.bold().green();
# Line 132  int main(int argc, char *argv[]) { Line 185  int main(int argc, char *argv[]) {
185                      cout << sGood << flush;                      cout << sGood << flush;
186                      cfmt.reset().red();                      cfmt.reset().red();
187                      cout << sBad << flush;                      cout << sBad << flush;
188                        cfmt.bold().yellow();
189                        cout << sSuggest << flush;
190    
191                        cursor.toColumn(cursorColumn);
192                  }                  }
193              } else if (line.substr(0,2) == "OK") { // single-line response expected ...              } else if (line.substr(0,2) == "OK") { // single-line response expected ...
194                  cout << endl << flush;                  cout << endl << flush;
# Line 177  int main(int argc, char *argv[]) { Line 234  int main(int argc, char *argv[]) {
234              if (c == KBD_BACKSPACE) {              if (c == KBD_BACKSPACE) {
235                  cout << "\b \b" << flush;                  cout << "\b \b" << flush;
236                  c = '\b';                  c = '\b';
237                } else if (c == '\t') { // auto completion ...
238                    autoComplete();
239                    continue; // don't send tab character to LSCP server
240              } else if (c != '\n') { // don't apply RETURN stroke yet, since the typed command might still be corrected by the sampler              } else if (c != '\n') { // don't apply RETURN stroke yet, since the typed command might still be corrected by the sampler
241                  cout << c << flush;                  cout << c << flush;
242              }              }

Legend:
Removed from v.2515  
changed lines
  Added in v.2516

  ViewVC Help
Powered by ViewVC