Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // 28 29 #include "G4VBasicShell.hh" 30 31 #include "G4StateManager.hh" 32 #include "G4UIcommand.hh" 33 #include "G4UIcommandStatus.hh" 34 #include "G4UIcommandTree.hh" 35 #include "G4UImanager.hh" 36 37 #include <sstream> 38 #include <vector> 39 40 G4VBasicShell::G4VBasicShell() : currentDirectory("/") {} 41 42 G4VBasicShell::~G4VBasicShell() = default; 43 44 G4String G4VBasicShell::ModifyToFullPathCommand(const char* aCommandLine) const 45 { 46 const G4String& rawCommandLine = aCommandLine; 47 if (rawCommandLine.empty() || rawCommandLine[0] == '\0') return rawCommandLine; 48 const G4String& commandLine = G4StrUtil::strip_copy(rawCommandLine); 49 G4String commandString; 50 G4String parameterString; 51 size_t i = commandLine.find(' '); 52 if (i != std::string::npos) { 53 commandString = commandLine.substr(0, i); 54 parameterString = " "; 55 parameterString += commandLine.substr(i + 1, commandLine.length() - (i + 1)); 56 } 57 else { 58 commandString = commandLine; 59 } 60 61 G4String fullPathCommandLine = ModifyPath(commandString) + parameterString; 62 return fullPathCommandLine; 63 } 64 65 G4String G4VBasicShell::GetCurrentWorkingDirectory() const { return currentDirectory; } 66 67 G4bool G4VBasicShell::ChangeDirectory(const char* newDir) 68 { 69 const G4String& newPrefix = G4StrUtil::strip_copy(newDir); 70 71 G4String newDirectory = ModifyPath(newPrefix); 72 if (newDirectory.back() != '/') { 73 newDirectory += "/"; 74 } 75 if (FindDirectory(newDirectory.c_str()) == nullptr) { 76 return false; 77 } 78 currentDirectory = std::move(newDirectory); 79 return true; 80 } 81 82 G4UIcommandTree* G4VBasicShell::FindDirectory(const char* dirName) const 83 { 84 G4String theDir = G4StrUtil::strip_copy(dirName); 85 86 G4String targetDir = ModifyPath(theDir); 87 if (targetDir.back() != '/') { 88 targetDir += "/"; 89 } 90 G4UIcommandTree* comTree = G4UImanager::GetUIpointer()->GetTree(); 91 if (targetDir == "/") { 92 return comTree; 93 } 94 size_t idx = 1; 95 while (idx < targetDir.length() - 1) { 96 size_t i = targetDir.find('/', idx); 97 comTree = comTree->GetTree(targetDir.substr(0, i + 1).c_str()); 98 if (comTree == nullptr) { 99 return nullptr; 100 } 101 idx = i + 1; 102 } 103 return comTree; 104 } 105 106 G4UIcommand* G4VBasicShell::FindCommand(const char* commandName) const 107 { 108 const G4String& commandLine = G4StrUtil::strip_copy(commandName); 109 110 G4String commandString; 111 std::size_t i = commandLine.find(' '); 112 if (i != std::string::npos) { 113 commandString = commandLine.substr(0, i); 114 } 115 else { 116 commandString = commandLine; 117 } 118 119 const G4String& targetCom = ModifyPath(commandString); 120 return G4UImanager::GetUIpointer()->GetTree()->FindPath(targetCom); 121 } 122 123 G4String G4VBasicShell::ModifyPath(const G4String& tempPath) const 124 { 125 if (tempPath.length() == 0) return tempPath; 126 127 G4String newPath = ""; 128 129 // temporal full path 130 if (tempPath[0] == '/') 131 newPath = tempPath; 132 else 133 newPath = currentDirectory + tempPath; 134 135 // body of path... 136 while (true) { 137 size_t idx = newPath.find("/./"); 138 if (idx == G4String::npos) break; 139 newPath.erase(idx, 2); 140 } 141 142 while (true) { 143 size_t idx = newPath.find("/../"); 144 if (idx == G4String::npos) break; 145 if (idx == 0) { 146 newPath.erase(1, 3); 147 continue; 148 } 149 size_t idx2 = newPath.find_last_of('/', idx - 1); 150 if (idx2 != G4String::npos) newPath.erase(idx2, idx - idx2 + 3); 151 } 152 153 // end of path... 154 if (newPath.size() >= 3) { 155 if (newPath.substr(newPath.size() - 3, 3) == "/..") { 156 if (newPath.size() == 3) { 157 newPath = "/"; 158 } 159 else { 160 size_t idx = newPath.find_last_of('/', newPath.size() - 4); 161 if (idx != G4String::npos) newPath.erase(idx + 1); 162 } 163 } 164 } 165 166 if (newPath.size() >= 2) { 167 if (newPath.substr(newPath.size() - 2, 2) == "/.") newPath.erase(newPath.size() - 1, 1); 168 } 169 170 // truncate "/////" to "/" 171 while (true) { 172 size_t idx = newPath.find("//"); 173 if (idx == G4String::npos) break; 174 newPath.erase(idx, 1); 175 } 176 177 return newPath; 178 } 179 //////////////////////////////////////////// 180 // Method used for command completion ////// 181 //////////////////////////////////////////// 182 G4String G4VBasicShell::Complete(const G4String& commandName) 183 { 184 const G4String& rawCommandLine = commandName; 185 const G4String& commandLine = G4StrUtil::strip_copy(rawCommandLine); 186 187 std::size_t i = commandLine.find(' '); 188 if (i != std::string::npos) 189 return rawCommandLine; // Already entering parameters, 190 // assume command path is correct. 191 G4String commandString = commandLine; 192 G4String targetCom = ModifyPath(commandString); 193 G4UIcommandTree* tree = G4UImanager::GetUIpointer()->GetTree(); 194 G4String value = FindMatchingPath(tree, targetCom); 195 if (value.empty()) return rawCommandLine; 196 return value; 197 } 198 199 G4String G4VBasicShell::FindMatchingPath(G4UIcommandTree* aTree, const G4String& aCommandPath) 200 { 201 return aTree->CompleteCommandPath(aCommandPath); 202 } 203 204 //////////////////////////////////////////// 205 // Method involving an interactive G4cout // 206 //////////////////////////////////////////// 207 /***************************************************************************/ 208 void G4VBasicShell::ExecuteCommand(const G4String& aCommand) 209 /***************************************************************************/ 210 // Should be put in G4VBasicShell. 211 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 212 { 213 if (aCommand.length() < 2) return; 214 G4UImanager* UI = G4UImanager::GetUIpointer(); 215 if (UI == nullptr) return; 216 G4int commandStatus = UI->ApplyCommand(aCommand); 217 switch (commandStatus) { 218 case fCommandSucceeded: 219 break; 220 case fCommandNotFound: 221 G4cerr << "command not found: " 222 << "\"" << aCommand << "\"" << G4endl; 223 break; 224 case fIllegalApplicationState: 225 G4cerr << "illegal application state -- command refused:" 226 << "\"" << aCommand << "\"" << G4endl; 227 break; 228 case fParameterOutOfRange: 229 case fParameterUnreadable: 230 case fParameterOutOfCandidates: 231 default: 232 G4cerr << "command refused (" << commandStatus << "):" 233 << "\"" << aCommand << "\"" << G4endl; 234 } 235 } 236 /***************************************************************************/ 237 void G4VBasicShell::ApplyShellCommand( 238 const G4String& a_string, G4bool& exitSession, G4bool& exitPause) 239 /***************************************************************************/ 240 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 241 { 242 G4UImanager* UI = G4UImanager::GetUIpointer(); 243 if (UI == nullptr) return; 244 245 G4String command = G4StrUtil::lstrip_copy(a_string); 246 247 if (command[0] == '#') { 248 G4cout << command << G4endl; 249 } 250 else if (command == "ls" || command.substr(0, 3) == "ls ") { 251 ListDirectory(command); 252 } 253 else if (command == "pwd") { 254 G4cout << "Current Working Directory : " << GetCurrentWorkingDirectory() << G4endl; 255 } 256 else if (command == "cd" || command.substr(0, 3) == "cd ") { 257 ChangeDirectoryCommand(command); 258 } 259 else if (command == "help" || command.substr(0, 5) == "help ") { 260 TerminalHelp(command); 261 } 262 else if (command[0] == '?') { 263 ShowCurrent(command); 264 } 265 else if (command == "hist" || command == "history") { 266 G4int nh = UI->GetNumberOfHistory(); 267 for (G4int i = 0; i < nh; i++) { 268 G4cout << i << ": " << UI->GetPreviousCommand(i) << G4endl; 269 } 270 } 271 else if (command[0] == '!') { 272 G4String ss = command.substr(1, command.length() - 1); 273 G4int vl; 274 const char* tt = ss; 275 std::istringstream is(tt); 276 is >> vl; 277 G4int nh = UI->GetNumberOfHistory(); 278 if (vl >= 0 && vl < nh) { 279 G4String prev = UI->GetPreviousCommand(vl); 280 G4cout << prev << G4endl; 281 ExecuteCommand(ModifyToFullPathCommand(prev)); 282 } 283 else { 284 G4cerr << "history " << vl << " is not found." << G4endl; 285 } 286 } 287 else if (command == "exit") { 288 if (!exitPause) { // In a secondary loop. 289 G4cout << "You are now processing RUN." << G4endl; 290 G4cout << "Please abort it using \"/run/abort\" command first" << G4endl; 291 G4cout << " and use \"continue\" command until the application" << G4endl; 292 G4cout << " becomes to Idle." << G4endl; 293 } 294 else { 295 exitSession = true; 296 } 297 } 298 else if (command == "cont" || command == "continue") { 299 exitPause = true; 300 } 301 else { 302 ExecuteCommand(ModifyToFullPathCommand(a_string)); 303 } 304 } 305 306 void G4VBasicShell::ShowCurrent(const G4String& newCommand) const 307 { 308 G4UImanager* UI = G4UImanager::GetUIpointer(); 309 if (UI == nullptr) return; 310 G4String comString = newCommand.substr(1, newCommand.length() - 1); 311 G4String theCommand = ModifyToFullPathCommand(comString); 312 G4String curV = UI->GetCurrentValues(theCommand); 313 if (! curV.empty()) { 314 G4cout << "Current value(s) of the parameter(s) : " << curV << G4endl; 315 } 316 } 317 318 void G4VBasicShell::ChangeDirectoryCommand(const G4String& newCommand) 319 { 320 G4String prefix; 321 if (newCommand.length() <= 3) { 322 prefix = "/"; 323 } 324 else { 325 const G4String& aNewPrefix = newCommand.substr(3, newCommand.length() - 3); 326 prefix = G4StrUtil::strip_copy(aNewPrefix); 327 } 328 if (! ChangeDirectory(prefix)) { 329 G4cout << "directory <" << prefix << "> not found." << G4endl; 330 } 331 } 332 333 void G4VBasicShell::ListDirectory(const G4String& newCommand) const 334 { 335 G4String targetDir; 336 if (newCommand.length() <= 3) { 337 targetDir = GetCurrentWorkingDirectory(); 338 } 339 else { 340 const G4String& newPrefix = newCommand.substr(3, newCommand.length() - 3); 341 targetDir = G4StrUtil::strip_copy(newPrefix); 342 } 343 G4UIcommandTree* commandTree = FindDirectory(targetDir); 344 if (commandTree == nullptr) { 345 G4cout << "Directory <" << targetDir << "> is not found." << G4endl; 346 } 347 else { 348 commandTree->ListCurrent(); 349 } 350 } 351 void G4VBasicShell::TerminalHelp(const G4String& newCommand) 352 { 353 G4UImanager* UI = G4UImanager::GetUIpointer(); 354 if (UI == nullptr) return; 355 G4UIcommandTree* treeTop = UI->GetTree(); 356 size_t i = newCommand.find(' '); 357 if (i != std::string::npos) { 358 G4String newValue = newCommand.substr(i + 1, newCommand.length() - (i + 1)); 359 G4StrUtil::strip(newValue); 360 G4String targetCom = ModifyToFullPathCommand(newValue); 361 G4UIcommand* theCommand = treeTop->FindPath(targetCom); 362 if (theCommand != nullptr) { 363 theCommand->List(); 364 return; 365 } 366 367 G4cout << "Command <" << newValue << " is not found." << G4endl; 368 return; 369 } 370 371 G4UIcommandTree* floor[10]; 372 floor[0] = treeTop; 373 size_t iFloor = 0; 374 size_t prefixIndex = 1; 375 G4String prefix = GetCurrentWorkingDirectory(); 376 while (prefixIndex < prefix.length() - 1) { 377 size_t ii = prefix.find('/', prefixIndex); 378 floor[iFloor + 1] = floor[iFloor]->GetTree(G4String(prefix.substr(0, ii + 1))); 379 prefixIndex = ii + 1; 380 iFloor++; 381 } 382 floor[iFloor]->ListCurrentWithNum(); 383 // 1998 Oct 2 non-number input 384 while (true) { 385 // G4cout << G4endl << "Type the number ( 0:end, -n:n level back ) : "<<std::flush; 386 G4cout << G4endl << "Type the number ( 0:end, -n:n level back ) : " << G4endl; 387 G4int j; 388 if (! GetHelpChoice(j)) { 389 G4cout << G4endl << "Not a number, once more" << G4endl; 390 continue; 391 } 392 if (j < 0) { 393 if (iFloor < (size_t)-j) 394 iFloor = 0; 395 else 396 iFloor += j; 397 // iFloor += j; 398 // if( iFloor < 0 ) iFloor = 0; 399 floor[iFloor]->ListCurrentWithNum(); 400 continue; 401 } 402 if (j == 0) { 403 break; 404 } 405 if (j > 0) { 406 G4int n_tree = floor[iFloor]->GetTreeEntry(); 407 if (j > n_tree) { 408 if (j <= n_tree + floor[iFloor]->GetCommandEntry()) { 409 floor[iFloor]->GetCommand(j - n_tree)->List(); 410 } 411 } 412 else { 413 floor[iFloor + 1] = floor[iFloor]->GetTree(j); 414 iFloor++; 415 floor[iFloor]->ListCurrentWithNum(); 416 } 417 } 418 } 419 G4cout << "Exit from HELP." << G4endl << G4endl; 420 // G4cout << G4endl; 421 ExitHelp(); 422 } 423