5 * Created by Pat Schloss on 8/15/08.
6 * Copyright 2008 Patrick D. Schloss. All rights reserved.
8 * There's a TON of duplicated code between InteractEngine and BatchEngine
9 * I couldn't figure out how to transition between ifstream (batch) and cin (interact)
10 * Fix later, don't have time now.
17 /***********************************************************************/
20 cFactory = CommandFactory::getInstance();
21 mout = MothurOut::getInstance();
24 mout->errorOut(e, "Engine", "Engine");
28 /***********************************************************************/
30 /***********************************************************************/
32 InteractEngine::InteractEngine(string path){
35 string temppath = path.substr(0, (path.find_last_of("othur")-5));
37 //this will happen if you set the path variable to contain mothur's exe location
38 if (temppath == "") { path = mout->findProgramPath("mothur"); }
43 /***********************************************************************/
45 InteractEngine::~InteractEngine(){}
47 /***********************************************************************/
48 //This function allows the user to input commands one line at a time until they quit.
49 //If the command is garbage it does nothing.
50 bool InteractEngine::getInput(){
53 string commandName = "";
55 int quitCommandCalled = 0;
57 while(quitCommandCalled != 1){
62 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
63 MPI_Comm_size(MPI_COMM_WORLD, &processors);
69 if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'. I changed them to '_' to avoid problems in your downstream analysis.\n"); }
71 mout->mothurOutEndLine();
74 mout->mothurOutEndLine();
76 if (mout->control_pressed) { input = "quit()"; }
78 //allow user to omit the () on the quit command
79 if (input == "quit") { input = "quit()"; }
84 for(int i = 1; i < processors; i++) {
85 int length = input.length();
86 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
87 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
92 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
94 char* tempBuf = new char[length];
95 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
98 if (input.length() > length) { input = input.substr(0, length); }
105 CommandOptionParser parser(input);
106 commandName = parser.getCommandString();
108 options = parser.getOptionString();
110 if (commandName != "") {
111 mout->executing = true;
114 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
116 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
117 //cout << pid << " is in execute " << commandName << endl;
119 //executes valid command
120 mout->changedSeqNames = false;
121 mout->runParse = true;
123 mout->clearAllGroups();
124 mout->Treenames.clear();
125 mout->saveNextLabel = "";
126 mout->printedHeaders = false;
127 mout->commandInputsConvertError = false;
128 mout->currentBinLabels.clear();
129 mout->binLabelsInFile.clear();
131 Command* command = cFactory->getCommand(commandName, options);
132 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
133 else { quitCommandCalled = command->execute(); }
135 //if we aborted command
136 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
138 mout->control_pressed = 0;
139 mout->executing = false;
145 mout->mothurOut("Invalid.");
146 mout->mothurOutEndLine();
151 catch(exception& e) {
152 mout->errorOut(e, "InteractEngine", "getInput");
156 /***********************************************************************/
157 string Engine::getCommand() {
160 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
162 char* nextCommand = NULL;
163 nextCommand = readline("mothur > ");
165 if(nextCommand != NULL) { add_history(nextCommand); }
166 else{ //^D causes null string and we want it to quit mothur
167 nextCommand = strdup("quit");
168 mout->mothurOut(nextCommand);
171 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
174 string nextCommand = "";
175 mout->mothurOut("mothur > ");
176 getline(cin, nextCommand);
177 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
182 string nextCommand = "";
184 mout->mothurOut("mothur > ");
185 getline(cin, nextCommand);
186 mout->mothurOutJustToLog(toString(nextCommand));
193 catch(exception& e) {
194 mout->errorOut(e, "Engine", "getCommand");
198 /***********************************************************************/
199 //This function opens the batchfile to be used by BatchEngine::getInput.
200 BatchEngine::BatchEngine(string path, string batchFileName){
203 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
205 string temppath = path.substr(0, (path.find_last_of("othur")-5));
207 //this will happen if you set the path variable to contain mothur's exe location
208 if (temppath == "") { path = mout->findProgramPath("mothur"); }
213 catch(exception& e) {
214 mout->errorOut(e, "BatchEngine", "BatchEngine");
219 /***********************************************************************/
221 BatchEngine::~BatchEngine(){ }
223 /***********************************************************************/
224 //This Function allows the user to run a batchfile containing several commands on Dotur
225 bool BatchEngine::getInput(){
227 //check if this is a valid batchfile
228 if (openedBatch == 1) {
229 mout->mothurOut("unable to open batchfile");
230 mout->mothurOutEndLine();
235 string commandName = "";
238 //CommandFactory cFactory;
239 int quitCommandCalled = 0;
241 while(quitCommandCalled != 1){
246 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
247 MPI_Comm_size(MPI_COMM_WORLD, &processors);
253 input = getNextCommand(inputBatchFile);
258 for(int i = 1; i < processors; i++) {
259 int length = input.length();
260 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
261 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
266 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
268 char* tempBuf = new char[length];
269 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
272 if (input.length() > length) { input = input.substr(0, length); }
281 if (input[0] != '#') {
282 if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'. I changed them to '_' to avoid problems in your downstream analysis.\n"); }
283 mout->mothurOutEndLine();
284 mout->mothurOut("mothur > " + input);
285 mout->mothurOutEndLine();
287 if (mout->control_pressed) { input = "quit()"; }
289 //allow user to omit the () on the quit command
290 if (input == "quit") { input = "quit()"; }
292 CommandOptionParser parser(input);
293 commandName = parser.getCommandString();
294 options = parser.getOptionString();
296 if (commandName != "") {
297 mout->executing = true;
300 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
302 //cout << pid << " is here " << commandName << '\t' << count << endl;
303 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
305 //executes valid command
306 mout->changedSeqNames = false;
307 mout->runParse = true;
309 mout->clearAllGroups();
310 mout->Treenames.clear();
311 mout->saveNextLabel = "";
312 mout->printedHeaders = false;
313 mout->commandInputsConvertError = false;
314 mout->currentBinLabels.clear();
315 mout->binLabelsInFile.clear();
318 Command* command = cFactory->getCommand(commandName, options);
319 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
320 else { quitCommandCalled = command->execute(); }
322 //if we aborted command
323 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
325 mout->control_pressed = 0;
326 mout->executing = false;
332 mout->mothurOut("Invalid.");
333 mout->mothurOutEndLine();
337 mout->gobble(inputBatchFile);
340 inputBatchFile.close();
343 catch(exception& e) {
344 mout->errorOut(e, "BatchEngine", "getInput");
348 /***********************************************************************/
349 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
352 string nextcommand = "";
354 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
355 else { nextcommand = mout->getline(inputBatchFile); }
359 catch(exception& e) {
360 mout->errorOut(e, "BatchEngine", "getNextCommand");
365 /***********************************************************************/
366 /***********************************************************************/
367 //This function opens the batchfile to be used by BatchEngine::getInput.
368 ScriptEngine::ScriptEngine(string path, string commandString){
372 listOfCommands = commandString.substr(1, (commandString.length()-1));
374 string temppath = path.substr(0, (path.find_last_of("othur")-5));
376 //this will happen if you set the path variable to contain mothur's exe location
377 if (temppath == "") { path = mout->findProgramPath("mothur"); }
382 catch(exception& e) {
383 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
388 /***********************************************************************/
390 ScriptEngine::~ScriptEngine(){ }
392 /***********************************************************************/
393 //This Function allows the user to run a batchfile containing several commands on mothur
394 bool ScriptEngine::getInput(){
398 string commandName = "";
402 //CommandFactory cFactory;
403 int quitCommandCalled = 0;
405 while(quitCommandCalled != 1){
410 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
411 MPI_Comm_size(MPI_COMM_WORLD, &processors);
417 input = getNextCommand(listOfCommands);
419 if (input == "") { input = "quit()"; }
421 if (mout->changedSeqNames) { mout->mothurOut("[WARNING]: your sequence names contained ':'. I changed them to '_' to avoid problems in your downstream analysis.\n"); }
424 if ((input.find("quit") != string::npos) || (input.find("set.logfile") != string::npos)) {}
425 else if ((input.find("get.current") != string::npos) && (!mout->hasCurrentFiles())) {}
426 else { mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine(); }
428 mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine();
433 for(int i = 1; i < processors; i++) {
434 int length = input.length();
435 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
436 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
441 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
443 char* tempBuf = new char[length];
444 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
447 if (input.length() > length) { input = input.substr(0, length); }
455 if (mout->control_pressed) { input = "quit()"; }
457 //allow user to omit the () on the quit command
458 if (input == "quit") { input = "quit()"; }
460 CommandOptionParser parser(input);
461 commandName = parser.getCommandString();
462 options = parser.getOptionString();
464 if (commandName != "") {
465 mout->executing = true;
467 int pid, numProcesses;
469 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
470 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses);
472 //cout << pid << " is here " << commandName << endl;
473 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
474 //cout << pid << " is in execute" << endl;
476 //executes valid command
477 mout->changedSeqNames = false;
478 mout->runParse = true;
480 mout->clearAllGroups();
481 mout->Treenames.clear();
482 mout->saveNextLabel = "";
483 mout->printedHeaders = false;
484 mout->commandInputsConvertError = false;
485 mout->currentBinLabels.clear();
486 mout->binLabelsInFile.clear();
488 Command* command = cFactory->getCommand(commandName, options);
489 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
490 else { quitCommandCalled = command->execute(); }
492 //if we aborted command
493 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
495 mout->control_pressed = 0;
496 mout->executing = false;
499 //cout << pid << " is done in execute" << endl;
503 mout->mothurOut("Invalid.");
504 mout->mothurOutEndLine();
512 catch(exception& e) {
513 mout->errorOut(e, "ScriptEngine", "getInput");
517 /***********************************************************************/
518 string ScriptEngine::getNextCommand(string& commandString) {
521 string nextcommand = "";
523 bool ignoreSemiColons = false;
525 //go through string until you reach ; or end
526 while (count < commandString.length()) {
528 //you want to ignore any ; until you reach the next '
529 if ((commandString[count] == '\'') && (!ignoreSemiColons)) { ignoreSemiColons = true; }
530 else if ((commandString[count] == '\'') && (ignoreSemiColons)) { ignoreSemiColons = false; }
532 if ((commandString[count] == ';') && (!ignoreSemiColons)) { break; }
533 else { nextcommand += commandString[count]; }
538 //if you are not at the end
539 if (count != commandString.length()) { commandString = commandString.substr(count+1, commandString.length()); }
540 else { commandString = ""; }
543 //get rid of spaces in between commands if any
544 if (commandString.length() > 0) {
545 while (commandString[0] == ' ') {
546 commandString = commandString.substr(1,commandString.length());
547 if (commandString.length() == 0) { break; }
553 catch(exception& e) {
554 mout->errorOut(e, "ScriptEngine", "getNextCommand");
558 /***********************************************************************/