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 /***********************************************************************/
29 string Engine::findMothursPath(){
32 string envPath = getenv("PATH");
33 string mothurPath = "";
35 //delimiting path char
37 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
43 //break apart path variable by ':'
45 mout->splitAtChar(envPath, dirs, delim);
47 //get path related to mothur
48 for (int i = 0; i < dirs.size(); i++) {
49 //to lower so we can find it
50 string tempLower = "";
51 for (int j = 0; j < dirs[i].length(); j++) { tempLower += tolower(dirs[i][j]); }
53 //is this mothurs path?
54 if (tempLower.find("mothur") != -1) { mothurPath = dirs[i]; break; }
57 if (mothurPath != "") {
58 //add mothur so it looks like what argv would look like
59 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
60 mothurPath += "/mothur";
62 mothurPath += "\\mothur";
65 //okay mothur is not in the path, so the folder mothur is in must be in the path
66 //lets find out which one
68 //get path related to mothur
69 for (int i = 0; i < dirs.size(); i++) {
71 //is this mothurs path?
73 string tempIn = dirs[i];
74 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
79 mout->openInputFile(tempIn, in, "");
82 if (in) { in.close(); mothurPath = tempIn; break; }
90 mout->errorOut(e, "Engine", "findMothursPath");
94 /***********************************************************************/
96 InteractEngine::InteractEngine(string path){
99 string temppath = path.substr(0, (path.find_last_of("othur")-5));
101 //this will happen if you set the path variable to contain mothur's exe location
102 if (temppath == "") { path = findMothursPath(); }
107 /***********************************************************************/
109 InteractEngine::~InteractEngine(){}
111 /***********************************************************************/
112 //This function allows the user to input commands one line at a time until they quit.
113 //If the command is garbage it does nothing.
114 bool InteractEngine::getInput(){
117 string commandName = "";
119 int quitCommandCalled = 0;
121 while(quitCommandCalled != 1){
126 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
127 MPI_Comm_size(MPI_COMM_WORLD, &processors);
133 mout->mothurOutEndLine();
135 input = getCommand();
136 mout->mothurOutEndLine();
138 if (mout->control_pressed) { input = "quit()"; }
140 //allow user to omit the () on the quit command
141 if (input == "quit") { input = "quit()"; }
146 for(int i = 1; i < processors; i++) {
147 int length = input.length();
148 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
149 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
154 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
156 char* tempBuf = new char[length];
157 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
160 if (input.length() > length) { input = input.substr(0, length); }
167 CommandOptionParser parser(input);
168 commandName = parser.getCommandString();
170 options = parser.getOptionString();
172 if (commandName != "") {
173 mout->executing = true;
176 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
178 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
179 //cout << pid << " is in execute " << commandName << endl;
181 //executes valid command
182 mout->runParse = true;
184 mout->clearAllGroups();
185 mout->Treenames.clear();
186 mout->saveNextLabel = "";
187 mout->printedHeaders = false;
188 mout->commandInputsConvertError = false;
189 mout->currentBinLabels.clear();
190 mout->binLabelsInFile.clear();
192 Command* command = cFactory->getCommand(commandName, options);
193 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
194 else { quitCommandCalled = command->execute(); }
196 //if we aborted command
197 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
199 mout->control_pressed = 0;
200 mout->executing = false;
206 mout->mothurOut("Invalid.");
207 mout->mothurOutEndLine();
212 catch(exception& e) {
213 mout->errorOut(e, "InteractEngine", "getInput");
217 /***********************************************************************/
218 string Engine::getCommand() {
221 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
223 char* nextCommand = NULL;
224 nextCommand = readline("mothur > ");
226 if(nextCommand != NULL) { add_history(nextCommand); }
227 else{ //^D causes null string and we want it to quit mothur
228 nextCommand = strdup("quit");
229 mout->mothurOut(nextCommand);
232 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
235 string nextCommand = "";
236 mout->mothurOut("mothur > ");
237 getline(cin, nextCommand);
238 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
243 string nextCommand = "";
245 mout->mothurOut("mothur > ");
246 getline(cin, nextCommand);
247 mout->mothurOutJustToLog(toString(nextCommand));
254 catch(exception& e) {
255 mout->errorOut(e, "Engine", "getCommand");
259 /***********************************************************************/
260 //This function opens the batchfile to be used by BatchEngine::getInput.
261 BatchEngine::BatchEngine(string path, string batchFileName){
264 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
266 string temppath = path.substr(0, (path.find_last_of("othur")-5));
268 //this will happen if you set the path variable to contain mothur's exe location
269 if (temppath == "") { path = findMothursPath(); }
274 catch(exception& e) {
275 mout->errorOut(e, "BatchEngine", "BatchEngine");
280 /***********************************************************************/
282 BatchEngine::~BatchEngine(){ }
284 /***********************************************************************/
285 //This Function allows the user to run a batchfile containing several commands on Dotur
286 bool BatchEngine::getInput(){
288 //check if this is a valid batchfile
289 if (openedBatch == 1) {
290 mout->mothurOut("unable to open batchfile");
291 mout->mothurOutEndLine();
296 string commandName = "";
299 //CommandFactory cFactory;
300 int quitCommandCalled = 0;
302 while(quitCommandCalled != 1){
307 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
308 MPI_Comm_size(MPI_COMM_WORLD, &processors);
314 input = getNextCommand(inputBatchFile);
319 for(int i = 1; i < processors; i++) {
320 int length = input.length();
321 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
322 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
327 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
329 char* tempBuf = new char[length];
330 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
333 if (input.length() > length) { input = input.substr(0, length); }
342 if (input[0] != '#') {
344 mout->mothurOutEndLine();
345 mout->mothurOut("mothur > " + input);
346 mout->mothurOutEndLine();
348 if (mout->control_pressed) { input = "quit()"; }
350 //allow user to omit the () on the quit command
351 if (input == "quit") { input = "quit()"; }
353 CommandOptionParser parser(input);
354 commandName = parser.getCommandString();
355 options = parser.getOptionString();
357 if (commandName != "") {
358 mout->executing = true;
361 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
363 //cout << pid << " is here " << commandName << '\t' << count << endl;
364 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
366 //executes valid command
367 mout->runParse = true;
369 mout->clearAllGroups();
370 mout->Treenames.clear();
371 mout->saveNextLabel = "";
372 mout->printedHeaders = false;
373 mout->commandInputsConvertError = false;
374 mout->currentBinLabels.clear();
375 mout->binLabelsInFile.clear();
378 Command* command = cFactory->getCommand(commandName, options);
379 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
380 else { quitCommandCalled = command->execute(); }
382 //if we aborted command
383 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
385 mout->control_pressed = 0;
386 mout->executing = false;
392 mout->mothurOut("Invalid.");
393 mout->mothurOutEndLine();
397 mout->gobble(inputBatchFile);
400 inputBatchFile.close();
403 catch(exception& e) {
404 mout->errorOut(e, "BatchEngine", "getInput");
408 /***********************************************************************/
409 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
412 string nextcommand = "";
414 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
415 else { nextcommand = mout->getline(inputBatchFile); }
419 catch(exception& e) {
420 mout->errorOut(e, "BatchEngine", "getNextCommand");
425 /***********************************************************************/
426 /***********************************************************************/
427 //This function opens the batchfile to be used by BatchEngine::getInput.
428 ScriptEngine::ScriptEngine(string path, string commandString){
432 listOfCommands = commandString.substr(1, (commandString.length()-1));
434 string temppath = path.substr(0, (path.find_last_of("othur")-5));
436 //this will happen if you set the path variable to contain mothur's exe location
437 if (temppath == "") { path = findMothursPath(); }
442 catch(exception& e) {
443 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
448 /***********************************************************************/
450 ScriptEngine::~ScriptEngine(){ }
452 /***********************************************************************/
453 //This Function allows the user to run a batchfile containing several commands on mothur
454 bool ScriptEngine::getInput(){
458 string commandName = "";
462 //CommandFactory cFactory;
463 int quitCommandCalled = 0;
465 while(quitCommandCalled != 1){
470 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
471 MPI_Comm_size(MPI_COMM_WORLD, &processors);
477 input = getNextCommand(listOfCommands);
479 if (input == "") { input = "quit()"; }
482 if ((input.find("quit") != string::npos) || (input.find("set.logfile") != string::npos)) {}
483 else if ((input.find("get.current") != string::npos) && (!mout->hasCurrentFiles())) {}
484 else { mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine(); }
486 mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine();
491 for(int i = 1; i < processors; i++) {
492 int length = input.length();
493 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
494 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
499 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
501 char* tempBuf = new char[length];
502 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
505 if (input.length() > length) { input = input.substr(0, length); }
513 if (mout->control_pressed) { input = "quit()"; }
515 //allow user to omit the () on the quit command
516 if (input == "quit") { input = "quit()"; }
518 CommandOptionParser parser(input);
519 commandName = parser.getCommandString();
520 options = parser.getOptionString();
522 if (commandName != "") {
523 mout->executing = true;
525 int pid, numProcesses;
527 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
528 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses);
530 //cout << pid << " is here " << commandName << endl;
531 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
532 //cout << pid << " is in execute" << endl;
534 //executes valid command
535 mout->runParse = true;
537 mout->clearAllGroups();
538 mout->Treenames.clear();
539 mout->saveNextLabel = "";
540 mout->printedHeaders = false;
541 mout->commandInputsConvertError = false;
542 mout->currentBinLabels.clear();
543 mout->binLabelsInFile.clear();
545 Command* command = cFactory->getCommand(commandName, options);
546 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
547 else { quitCommandCalled = command->execute(); }
549 //if we aborted command
550 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
552 mout->control_pressed = 0;
553 mout->executing = false;
556 //cout << pid << " is done in execute" << endl;
560 mout->mothurOut("Invalid.");
561 mout->mothurOutEndLine();
569 catch(exception& e) {
570 mout->errorOut(e, "ScriptEngine", "getInput");
574 /***********************************************************************/
575 string ScriptEngine::getNextCommand(string& commandString) {
578 string nextcommand = "";
580 bool ignoreSemiColons = false;
582 //go through string until you reach ; or end
583 while (count < commandString.length()) {
585 //you want to ignore any ; until you reach the next '
586 if ((commandString[count] == '\'') && (!ignoreSemiColons)) { ignoreSemiColons = true; }
587 else if ((commandString[count] == '\'') && (ignoreSemiColons)) { ignoreSemiColons = false; }
589 if ((commandString[count] == ';') && (!ignoreSemiColons)) { break; }
590 else { nextcommand += commandString[count]; }
595 //if you are not at the end
596 if (count != commandString.length()) { commandString = commandString.substr(count+1, commandString.length()); }
597 else { commandString = ""; }
600 //get rid of spaces in between commands if any
601 if (commandString.length() > 0) {
602 while (commandString[0] == ' ') {
603 commandString = commandString.substr(1,commandString.length());
604 if (commandString.length() == 0) { break; }
610 catch(exception& e) {
611 mout->errorOut(e, "ScriptEngine", "getNextCommand");
615 /***********************************************************************/