Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // 26 // 27 // 27 // 28 28 29 #include "G4VUIshell.hh" 29 #include "G4VUIshell.hh" 30 30 31 #include "G4StateManager.hh" 31 #include "G4StateManager.hh" 32 #include "G4UIArrayString.hh" 32 #include "G4UIArrayString.hh" 33 #include "G4UIcommand.hh" 33 #include "G4UIcommand.hh" 34 #include "G4UIcommandStatus.hh" 34 #include "G4UIcommandStatus.hh" 35 #include "G4UIcommandTree.hh" 35 #include "G4UIcommandTree.hh" 36 #include "G4UImanager.hh" 36 #include "G4UImanager.hh" 37 37 38 // terminal color string 38 // terminal color string 39 static const G4String strESC(1, '\033'); 39 static const G4String strESC(1, '\033'); 40 static const G4String TermColorString[8] = {st 40 static const G4String TermColorString[8] = {strESC + "[30m", strESC + "[31m", strESC + "[32m", 41 strESC + "[33m", strESC + "[34m", strESC + " 41 strESC + "[33m", strESC + "[34m", strESC + "[35m", strESC + "[36m", strESC + "[37m"}; 42 42 43 ////////////////////////////////////////////// 43 /////////////////////////////////////////////////////////////////// 44 G4VUIshell::G4VUIshell(const G4String& prompt) 44 G4VUIshell::G4VUIshell(const G4String& prompt) 45 : promptSetting(prompt), 45 : promptSetting(prompt), 46 promptString(""), 46 promptString(""), 47 nColumn(80), 47 nColumn(80), 48 lsColorFlag(false), 48 lsColorFlag(false), 49 directoryColor(BLACK), 49 directoryColor(BLACK), 50 commandColor(BLACK), 50 commandColor(BLACK), 51 currentCommandDir("/") 51 currentCommandDir("/") 52 ////////////////////////////////////////////// 52 /////////////////////////////////////////////////////////////////// 53 {} 53 {} 54 54 55 ///////////////////////// 55 ///////////////////////// 56 G4VUIshell::~G4VUIshell() = default; 56 G4VUIshell::~G4VUIshell() = default; 57 ///////////////////////// 57 ///////////////////////// 58 58 59 //////////////////////////////////////////// 59 //////////////////////////////////////////// 60 void G4VUIshell::MakePrompt(const char* msg) 60 void G4VUIshell::MakePrompt(const char* msg) 61 //////////////////////////////////////////// 61 //////////////////////////////////////////// 62 { 62 { 63 if (promptSetting.length() <= 1) { 63 if (promptSetting.length() <= 1) { 64 promptString = promptSetting; 64 promptString = promptSetting; 65 return; 65 return; 66 } 66 } 67 67 68 promptString = ""; 68 promptString = ""; 69 G4int i; 69 G4int i; 70 for (i = 0; i < (G4int)promptSetting.length( 70 for (i = 0; i < (G4int)promptSetting.length() - 1; ++i) { 71 if (promptSetting[i] == '%') { 71 if (promptSetting[i] == '%') { 72 switch (promptSetting[i + 1]) { 72 switch (promptSetting[i + 1]) { 73 case 's': // current application stat 73 case 's': // current application status 74 { 74 { 75 G4String stateStr; 75 G4String stateStr; 76 if (msg != nullptr) { 76 if (msg != nullptr) { 77 stateStr = msg; 77 stateStr = msg; 78 } 78 } 79 else { 79 else { 80 G4StateManager* statM = G4StateMan 80 G4StateManager* statM = G4StateManager::GetStateManager(); 81 stateStr = statM->GetStateString(s 81 stateStr = statM->GetStateString(statM->GetCurrentState()); 82 } 82 } 83 promptString.append(stateStr); 83 promptString.append(stateStr); 84 i++; 84 i++; 85 } break; 85 } break; 86 case '/': // current working director 86 case '/': // current working directory 87 promptString.append(currentCommandDi 87 promptString.append(currentCommandDir); 88 i++; 88 i++; 89 break; 89 break; 90 default: 90 default: 91 promptString += promptSetting[i]; 91 promptString += promptSetting[i]; 92 break; 92 break; 93 } 93 } 94 } 94 } 95 else { 95 else { 96 promptString += promptSetting[i]; 96 promptString += promptSetting[i]; 97 } 97 } 98 } 98 } 99 99 100 // append last chaacter 100 // append last chaacter 101 if (i == G4int(promptSetting.length()) - 1) 101 if (i == G4int(promptSetting.length()) - 1) promptString += promptSetting[i]; 102 } 102 } 103 103 104 //////////////////////////////// 104 //////////////////////////////// 105 void G4VUIshell::ResetTerminal() 105 void G4VUIshell::ResetTerminal() 106 //////////////////////////////// 106 //////////////////////////////// 107 {} 107 {} 108 108 109 // ------------------------------------------- 109 // -------------------------------------------------------------------- 110 // G4command operations 110 // G4command operations 111 // ------------------------------------------- 111 // -------------------------------------------------------------------- 112 ////////////////////////////////////////////// 112 //////////////////////////////////////////////////////////////////////// 113 G4UIcommandTree* G4VUIshell::GetCommandTree(co 113 G4UIcommandTree* G4VUIshell::GetCommandTree(const G4String& input) const 114 ////////////////////////////////////////////// 114 //////////////////////////////////////////////////////////////////////// 115 { 115 { 116 G4UImanager* UI = G4UImanager::GetUIpointer( 116 G4UImanager* UI = G4UImanager::GetUIpointer(); 117 117 118 G4UIcommandTree* cmdTree = UI->GetTree(); / 118 G4UIcommandTree* cmdTree = UI->GetTree(); // root tree 119 119 120 G4String absPath = GetAbsCommandDirPath(G4St 120 G4String absPath = GetAbsCommandDirPath(G4StrUtil::strip_copy(input)); 121 121 122 // parsing absolute path ... 122 // parsing absolute path ... 123 if (absPath.length() == 0) return nullptr; 123 if (absPath.length() == 0) return nullptr; 124 if (absPath[G4int(absPath.length() - 1)] != 124 if (absPath[G4int(absPath.length() - 1)] != '/') return nullptr; // error?? 125 if (absPath == "/") return cmdTree; 125 if (absPath == "/") return cmdTree; 126 126 127 for (std::size_t indx = 1; indx < absPath.le 127 for (std::size_t indx = 1; indx < absPath.length() - 1;) { 128 std::size_t jslash = absPath.find('/', ind 128 std::size_t jslash = absPath.find('/', indx); // search index begin with "/" 129 if (jslash != G4String::npos) { 129 if (jslash != G4String::npos) { 130 if (cmdTree != nullptr) cmdTree = cmdTre 130 if (cmdTree != nullptr) cmdTree = cmdTree->GetTree(G4String(absPath.substr(0, jslash + 1))); 131 } 131 } 132 indx = jslash + 1; 132 indx = jslash + 1; 133 } 133 } 134 134 135 if (cmdTree == nullptr) return nullptr; 135 if (cmdTree == nullptr) return nullptr; 136 return cmdTree; 136 return cmdTree; 137 } 137 } 138 138 139 ////////////////////////////////////////////// 139 ////////////////////////////////////////////////////////////////////// 140 G4String G4VUIshell::GetAbsCommandDirPath(cons 140 G4String G4VUIshell::GetAbsCommandDirPath(const G4String& apath) const 141 ////////////////////////////////////////////// 141 ////////////////////////////////////////////////////////////////////// 142 { 142 { 143 if (apath.empty()) return apath; // null st 143 if (apath.empty()) return apath; // null string 144 144 145 // if "apath" does not start with "/", 145 // if "apath" does not start with "/", 146 // then it is treared as relative path 146 // then it is treared as relative path 147 G4String bpath = apath; 147 G4String bpath = apath; 148 if (apath[(std::size_t)0] != '/') bpath = cu 148 if (apath[(std::size_t)0] != '/') bpath = currentCommandDir + apath; 149 149 150 // parsing... 150 // parsing... 151 G4String absPath = "/"; 151 G4String absPath = "/"; 152 for (std::size_t indx = 1; indx <= bpath.len 152 for (std::size_t indx = 1; indx <= bpath.length() - 1;) { 153 std::size_t jslash = bpath.find('/', indx) 153 std::size_t jslash = bpath.find('/', indx); // search index begin with "/" 154 if (indx == jslash) { // skip first '///' 154 if (indx == jslash) { // skip first '///' 155 ++indx; 155 ++indx; 156 continue; 156 continue; 157 } 157 } 158 if (jslash != G4String::npos) { 158 if (jslash != G4String::npos) { 159 if (bpath.substr(indx, jslash - indx) == 159 if (bpath.substr(indx, jslash - indx) == "..") { // directory up 160 if (absPath == "/") { 160 if (absPath == "/") { 161 indx = jslash + 1; 161 indx = jslash + 1; 162 continue; 162 continue; 163 } 163 } 164 if (absPath.length() >= 2) { 164 if (absPath.length() >= 2) { 165 absPath.erase(absPath.length() - 1); 165 absPath.erase(absPath.length() - 1); // remove last "/" 166 auto jpre = absPath.rfind('/'); 166 auto jpre = absPath.rfind('/'); 167 if (jpre != G4String::npos) absPath. 167 if (jpre != G4String::npos) absPath.erase(jpre + 1); 168 } 168 } 169 } 169 } 170 else if (bpath.substr(indx, jslash - ind 170 else if (bpath.substr(indx, jslash - indx) == ".") { // nothing to do 171 } 171 } 172 else { // add 172 else { // add 173 if (jslash != indx || bpath[(G4int)ind 173 if (jslash != indx || bpath[(G4int)indx] != '/') // truncate "////" 174 absPath += bpath.substr(indx, jslash 174 absPath += bpath.substr(indx, jslash - indx + 1); 175 // better to be check directory existe 175 // better to be check directory existence. (it costs!) 176 } 176 } 177 indx = jslash + 1; 177 indx = jslash + 1; 178 } 178 } 179 else { // directory ONLY (ignore non-"/" 179 else { // directory ONLY (ignore non-"/" terminated string) 180 break; 180 break; 181 } 181 } 182 } 182 } 183 183 184 return absPath; 184 return absPath; 185 } 185 } 186 186 187 ////////////////////////////////////////////// 187 //////////////////////////////////////////////////////////////////// 188 G4String G4VUIshell::GetCommandPathTail(const 188 G4String G4VUIshell::GetCommandPathTail(const G4String& apath) const 189 ////////////////////////////////////////////// 189 //////////////////////////////////////////////////////////////////// 190 { // xxx/xxx/zzz -> zzz, trancate /// -> / 190 { // xxx/xxx/zzz -> zzz, trancate /// -> / 191 if (apath.empty()) return apath; 191 if (apath.empty()) return apath; 192 192 193 auto lstr = (G4int)apath.length(); 193 auto lstr = (G4int)apath.length(); 194 194 195 // for trancating "/" 195 // for trancating "/" 196 G4bool Qsla = false; 196 G4bool Qsla = false; 197 if (apath[lstr - 1] == '/') Qsla = true; 197 if (apath[lstr - 1] == '/') Qsla = true; 198 198 199 // searching last '/' from tail 199 // searching last '/' from tail 200 G4int indx = -1; 200 G4int indx = -1; 201 for (G4int i = lstr - 1; i >= 0; --i) { 201 for (G4int i = lstr - 1; i >= 0; --i) { 202 if (Qsla && apath[i] != '/') Qsla = false; 202 if (Qsla && apath[i] != '/') Qsla = false; // break "/" flag!! 203 if (apath[i] == '/' && ! Qsla) { 203 if (apath[i] == '/' && ! Qsla) { 204 indx = i; 204 indx = i; 205 break; 205 break; 206 } 206 } 207 } 207 } 208 208 209 if (indx == -1) return apath; // not found 209 if (indx == -1) return apath; // not found 210 210 211 if (indx == 0 && lstr == 1) { // "/" 211 if (indx == 0 && lstr == 1) { // "/" 212 G4String nullStr; 212 G4String nullStr; 213 return nullStr; 213 return nullStr; 214 } 214 } 215 // G4String newPath= apath(indx+1,lstr-indx- 215 // G4String newPath= apath(indx+1,lstr-indx-1); 216 G4String newPath = apath; 216 G4String newPath = apath; 217 newPath = newPath.substr(indx + 1, lstr - in 217 newPath = newPath.substr(indx + 1, lstr - indx - 1); 218 return newPath; 218 return newPath; 219 } 219 } 220 220 221 // ------------------------------------------- 221 // -------------------------------------------------------------------- 222 // shell commands 222 // shell commands 223 // ------------------------------------------- 223 // -------------------------------------------------------------------- 224 ////////////////////////////////////////////// 224 ///////////////////////////////////////////////////////////// 225 void G4VUIshell::ListCommand(const G4String& d 225 void G4VUIshell::ListCommand(const G4String& dir, const G4String& candidate) const 226 ////////////////////////////////////////////// 226 ///////////////////////////////////////////////////////////// 227 { 227 { 228 // specified directpry 228 // specified directpry 229 G4String input = G4StrUtil::strip_copy(dir); 229 G4String input = G4StrUtil::strip_copy(dir); 230 230 231 // command tree of "user specified directory 231 // command tree of "user specified directory" 232 G4String vpath = currentCommandDir; 232 G4String vpath = currentCommandDir; 233 G4String vcmd; 233 G4String vcmd; 234 234 235 auto len = (G4int)input.length(); 235 auto len = (G4int)input.length(); 236 if (! input.empty()) { 236 if (! input.empty()) { 237 G4int indx = -1; 237 G4int indx = -1; 238 for (G4int i = len - 1; i >= 0; --i) { // 238 for (G4int i = len - 1; i >= 0; --i) { // search last '/' 239 if (input[i] == '/') { 239 if (input[i] == '/') { 240 indx = i; 240 indx = i; 241 break; 241 break; 242 } 242 } 243 } 243 } 244 // get abs. path 244 // get abs. path 245 if (indx != -1) vpath = GetAbsCommandDirPa 245 if (indx != -1) vpath = GetAbsCommandDirPath(input.substr(0, indx + 1)); 246 if (indx != 0 || len != 1) vcmd = input.su 246 if (indx != 0 || len != 1) vcmd = input.substr(indx + 1, len - indx - 1); // care for "/" 247 } 247 } 248 248 249 // check "vcmd" is directory? 249 // check "vcmd" is directory? 250 const G4String& inputpath = vpath + vcmd; << 250 G4String inputpath = vpath + vcmd; 251 if (! vcmd.empty()) { 251 if (! vcmd.empty()) { 252 const G4String& tmpstr = inputpath + "/"; << 252 G4String tmpstr = inputpath + "/"; 253 if (GetCommandTree(tmpstr) != nullptr) { 253 if (GetCommandTree(tmpstr) != nullptr) { 254 vpath = tmpstr; 254 vpath = tmpstr; 255 vcmd = ""; 255 vcmd = ""; 256 } 256 } 257 } 257 } 258 258 259 // check "vpath" directory exists? 259 // check "vpath" directory exists? 260 G4UIcommandTree* atree = GetCommandTree(vpat 260 G4UIcommandTree* atree = GetCommandTree(vpath); 261 if (atree == nullptr) { 261 if (atree == nullptr) { 262 G4cout << "<" << input << ">: No such dire 262 G4cout << "<" << input << ">: No such directory" << G4endl; 263 return; 263 return; 264 } 264 } 265 265 266 // list matched directories/commands 266 // list matched directories/commands 267 G4String stream; 267 G4String stream; 268 G4bool isMatch = false; 268 G4bool isMatch = false; 269 269 270 G4int Ndir = atree->GetTreeEntry(); 270 G4int Ndir = atree->GetTreeEntry(); 271 G4int Ncmd = atree->GetCommandEntry(); 271 G4int Ncmd = atree->GetCommandEntry(); 272 if (Ndir == 0 && Ncmd == 0) return; // no c 272 if (Ndir == 0 && Ncmd == 0) return; // no contents 273 273 274 // directory ... 274 // directory ... 275 for (G4int idir = 1; idir <= Ndir; idir++) { 275 for (G4int idir = 1; idir <= Ndir; idir++) { 276 if (idir == 1 && lsColorFlag) stream += Te 276 if (idir == 1 && lsColorFlag) stream += TermColorString[directoryColor]; 277 G4String fpdir = atree->GetTree(idir)->Get 277 G4String fpdir = atree->GetTree(idir)->GetPathName(); 278 // matching test 278 // matching test 279 if (candidate.empty()) { // list all 279 if (candidate.empty()) { // list all 280 if (vcmd.empty() || fpdir == inputpath) 280 if (vcmd.empty() || fpdir == inputpath) { 281 stream += GetCommandPathTail(fpdir); 281 stream += GetCommandPathTail(fpdir); 282 stream += " "; 282 stream += " "; 283 isMatch = true; 283 isMatch = true; 284 } 284 } 285 } 285 } 286 else { // list only matched with candidat 286 else { // list only matched with candidate 287 if (fpdir.find(candidate, 0) == 0) { 287 if (fpdir.find(candidate, 0) == 0) { 288 stream += GetCommandPathTail(fpdir); 288 stream += GetCommandPathTail(fpdir); 289 stream += " "; 289 stream += " "; 290 } 290 } 291 } 291 } 292 } 292 } 293 293 294 // command ... 294 // command ... 295 for (G4int icmd = 1; icmd <= Ncmd; icmd++) { 295 for (G4int icmd = 1; icmd <= Ncmd; icmd++) { 296 if (icmd == 1 && lsColorFlag) stream += Te 296 if (icmd == 1 && lsColorFlag) stream += TermColorString[commandColor]; 297 G4String fpcmd = atree->GetPathName() + at 297 G4String fpcmd = atree->GetPathName() + atree->GetCommand(icmd)->GetCommandName(); 298 // matching test 298 // matching test 299 if (candidate.empty()) { // list all 299 if (candidate.empty()) { // list all 300 if (vcmd.empty() || fpcmd == inputpath) 300 if (vcmd.empty() || fpcmd == inputpath) { 301 stream += GetCommandPathTail(fpcmd); 301 stream += GetCommandPathTail(fpcmd); 302 stream += "* "; 302 stream += "* "; 303 isMatch = true; 303 isMatch = true; 304 } 304 } 305 } 305 } 306 else { // list only matched with candidat 306 else { // list only matched with candidate 307 if (fpcmd.find(candidate, 0) == 0) { 307 if (fpcmd.find(candidate, 0) == 0) { 308 stream += GetCommandPathTail(fpcmd); 308 stream += GetCommandPathTail(fpcmd); 309 stream += "* "; 309 stream += "* "; 310 } 310 } 311 } 311 } 312 } 312 } 313 313 314 // waring : not matched 314 // waring : not matched 315 if (! isMatch && candidate.empty()) 315 if (! isMatch && candidate.empty()) 316 G4cout << "<" << input << ">: No such dire 316 G4cout << "<" << input << ">: No such directory or command" << std::flush; 317 317 318 // display 318 // display 319 G4UIArrayString arrayString(stream); 319 G4UIArrayString arrayString(stream); 320 arrayString.Show(nColumn); 320 arrayString.Show(nColumn); 321 } 321 } 322 322