Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/interfaces/core/src/G4VUIshell.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 "G4VUIshell.hh"
 30 
 31 #include "G4StateManager.hh"
 32 #include "G4UIArrayString.hh"
 33 #include "G4UIcommand.hh"
 34 #include "G4UIcommandStatus.hh"
 35 #include "G4UIcommandTree.hh"
 36 #include "G4UImanager.hh"
 37 
 38 // terminal color string
 39 static const G4String strESC(1, '\033');
 40 static const G4String TermColorString[8] = {strESC + "[30m", strESC + "[31m", strESC + "[32m",
 41   strESC + "[33m", strESC + "[34m", strESC + "[35m", strESC + "[36m", strESC + "[37m"};
 42 
 43 ///////////////////////////////////////////////////////////////////
 44 G4VUIshell::G4VUIshell(const G4String& prompt)
 45   : promptSetting(prompt),
 46     promptString(""),
 47     nColumn(80),
 48     lsColorFlag(false),
 49     directoryColor(BLACK),
 50     commandColor(BLACK),
 51     currentCommandDir("/")
 52 ///////////////////////////////////////////////////////////////////
 53 {}
 54 
 55 /////////////////////////
 56 G4VUIshell::~G4VUIshell() = default;
 57 /////////////////////////
 58 
 59 ////////////////////////////////////////////
 60 void G4VUIshell::MakePrompt(const char* msg)
 61 ////////////////////////////////////////////
 62 {
 63   if (promptSetting.length() <= 1) {
 64     promptString = promptSetting;
 65     return;
 66   }
 67 
 68   promptString = "";
 69   G4int i;
 70   for (i = 0; i < (G4int)promptSetting.length() - 1; ++i) {
 71     if (promptSetting[i] == '%') {
 72       switch (promptSetting[i + 1]) {
 73         case 's':  // current application status
 74         {
 75           G4String stateStr;
 76           if (msg != nullptr) {
 77             stateStr = msg;
 78           }
 79           else {
 80             G4StateManager* statM = G4StateManager::GetStateManager();
 81             stateStr = statM->GetStateString(statM->GetCurrentState());
 82           }
 83           promptString.append(stateStr);
 84           i++;
 85         } break;
 86         case '/':  // current working directory
 87           promptString.append(currentCommandDir);
 88           i++;
 89           break;
 90         default:
 91           promptString += promptSetting[i];
 92           break;
 93       }
 94     }
 95     else {
 96       promptString += promptSetting[i];
 97     }
 98   }
 99 
100   // append last chaacter
101   if (i == G4int(promptSetting.length()) - 1) promptString += promptSetting[i];
102 }
103 
104 ////////////////////////////////
105 void G4VUIshell::ResetTerminal()
106 ////////////////////////////////
107 {}
108 
109 // --------------------------------------------------------------------
110 //      G4command operations
111 // --------------------------------------------------------------------
112 ////////////////////////////////////////////////////////////////////////
113 G4UIcommandTree* G4VUIshell::GetCommandTree(const G4String& input) const
114 ////////////////////////////////////////////////////////////////////////
115 {
116   G4UImanager* UI = G4UImanager::GetUIpointer();
117 
118   G4UIcommandTree* cmdTree = UI->GetTree();  // root tree
119 
120   G4String absPath = GetAbsCommandDirPath(G4StrUtil::strip_copy(input));
121 
122   // parsing absolute path ...
123   if (absPath.length() == 0) return nullptr;
124   if (absPath[G4int(absPath.length() - 1)] != '/') return nullptr;  // error??
125   if (absPath == "/") return cmdTree;
126 
127   for (std::size_t indx = 1; indx < absPath.length() - 1;) {
128     std::size_t jslash = absPath.find('/', indx);  // search index begin with "/"
129     if (jslash != G4String::npos) {
130       if (cmdTree != nullptr) cmdTree = cmdTree->GetTree(G4String(absPath.substr(0, jslash + 1)));
131     }
132     indx = jslash + 1;
133   }
134 
135   if (cmdTree == nullptr) return nullptr;
136   return cmdTree;
137 }
138 
139 //////////////////////////////////////////////////////////////////////
140 G4String G4VUIshell::GetAbsCommandDirPath(const G4String& apath) const
141 //////////////////////////////////////////////////////////////////////
142 {
143   if (apath.empty()) return apath;  // null string
144 
145   // if "apath" does not start with "/",
146   //   then it is treared as relative path
147   G4String bpath = apath;
148   if (apath[(std::size_t)0] != '/') bpath = currentCommandDir + apath;
149 
150   // parsing...
151   G4String absPath = "/";
152   for (std::size_t indx = 1; indx <= bpath.length() - 1;) {
153     std::size_t jslash = bpath.find('/', indx);  // search index begin with "/"
154     if (indx == jslash) {  // skip first '///'
155       ++indx;
156       continue;
157     }
158     if (jslash != G4String::npos) {
159       if (bpath.substr(indx, jslash - indx) == "..") {  // directory up
160         if (absPath == "/") {
161           indx = jslash + 1;
162           continue;
163         }
164         if (absPath.length() >= 2) {
165           absPath.erase(absPath.length() - 1);  // remove last  "/"
166           auto jpre = absPath.rfind('/');
167           if (jpre != G4String::npos) absPath.erase(jpre + 1);
168         }
169       }
170       else if (bpath.substr(indx, jslash - indx) == ".") {  // nothing to do
171       }
172       else {  // add
173         if (jslash != indx || bpath[(G4int)indx] != '/')  // truncate "////"
174           absPath += bpath.substr(indx, jslash - indx + 1);
175         // better to be check directory existence. (it costs!)
176       }
177       indx = jslash + 1;
178     }
179     else {  // directory ONLY (ignore non-"/" terminated string)
180       break;
181     }
182   }
183 
184   return absPath;
185 }
186 
187 ////////////////////////////////////////////////////////////////////
188 G4String G4VUIshell::GetCommandPathTail(const G4String& apath) const
189 ////////////////////////////////////////////////////////////////////
190 {  // xxx/xxx/zzz -> zzz, trancate /// -> /
191   if (apath.empty()) return apath;
192 
193   auto lstr = (G4int)apath.length();
194 
195   // for trancating "/"
196   G4bool Qsla = false;
197   if (apath[lstr - 1] == '/') Qsla = true;
198 
199   // searching last '/' from tail
200   G4int indx = -1;
201   for (G4int i = lstr - 1; i >= 0; --i) {
202     if (Qsla && apath[i] != '/') Qsla = false;  // break "/" flag!!
203     if (apath[i] == '/' && ! Qsla) {
204       indx = i;
205       break;
206     }
207   }
208 
209   if (indx == -1) return apath;  // not found
210 
211   if (indx == 0 && lstr == 1) {  // "/"
212     G4String nullStr;
213     return nullStr;
214   }
215   // G4String newPath= apath(indx+1,lstr-indx-1);
216   G4String newPath = apath;
217   newPath = newPath.substr(indx + 1, lstr - indx - 1);
218   return newPath;
219 }
220 
221 // --------------------------------------------------------------------
222 //      shell commands
223 // --------------------------------------------------------------------
224 /////////////////////////////////////////////////////////////
225 void G4VUIshell::ListCommand(const G4String& dir, const G4String& candidate) const
226 /////////////////////////////////////////////////////////////
227 {
228   // specified directpry
229   G4String input = G4StrUtil::strip_copy(dir);
230 
231   // command tree of "user specified directory"
232   G4String vpath = currentCommandDir;
233   G4String vcmd;
234 
235   auto len = (G4int)input.length();
236   if (! input.empty()) {
237     G4int indx = -1;
238     for (G4int i = len - 1; i >= 0; --i) {  // search last '/'
239       if (input[i] == '/') {
240         indx = i;
241         break;
242       }
243     }
244     // get abs. path
245     if (indx != -1) vpath = GetAbsCommandDirPath(input.substr(0, indx + 1));
246     if (indx != 0 || len != 1) vcmd = input.substr(indx + 1, len - indx - 1);  // care for "/"
247   }
248 
249   // check "vcmd" is directory?
250   const G4String& inputpath = vpath + vcmd;
251   if (! vcmd.empty()) {
252     const G4String& tmpstr = inputpath + "/";
253     if (GetCommandTree(tmpstr) != nullptr) {
254       vpath = tmpstr;
255       vcmd = "";
256     }
257   }
258 
259   // check "vpath" directory exists?
260   G4UIcommandTree* atree = GetCommandTree(vpath);
261   if (atree == nullptr) {
262     G4cout << "<" << input << ">: No such directory" << G4endl;
263     return;
264   }
265 
266   // list matched directories/commands
267   G4String stream;
268   G4bool isMatch = false;
269 
270   G4int Ndir = atree->GetTreeEntry();
271   G4int Ncmd = atree->GetCommandEntry();
272   if (Ndir == 0 && Ncmd == 0) return;  // no contents
273 
274   // directory ...
275   for (G4int idir = 1; idir <= Ndir; idir++) {
276     if (idir == 1 && lsColorFlag) stream += TermColorString[directoryColor];
277     G4String fpdir = atree->GetTree(idir)->GetPathName();
278     // matching test
279     if (candidate.empty()) {  // list all
280       if (vcmd.empty() || fpdir == inputpath) {
281         stream += GetCommandPathTail(fpdir);
282         stream += "  ";
283         isMatch = true;
284       }
285     }
286     else {  // list only matched with candidate
287       if (fpdir.find(candidate, 0) == 0) {
288         stream += GetCommandPathTail(fpdir);
289         stream += "  ";
290       }
291     }
292   }
293 
294   // command ...
295   for (G4int icmd = 1; icmd <= Ncmd; icmd++) {
296     if (icmd == 1 && lsColorFlag) stream += TermColorString[commandColor];
297     G4String fpcmd = atree->GetPathName() + atree->GetCommand(icmd)->GetCommandName();
298     // matching test
299     if (candidate.empty()) {  // list all
300       if (vcmd.empty() || fpcmd == inputpath) {
301         stream += GetCommandPathTail(fpcmd);
302         stream += "*  ";
303         isMatch = true;
304       }
305     }
306     else {  // list only matched with candidate
307       if (fpcmd.find(candidate, 0) == 0) {
308         stream += GetCommandPathTail(fpcmd);
309         stream += "*  ";
310       }
311     }
312   }
313 
314   // waring : not matched
315   if (! isMatch && candidate.empty())
316     G4cout << "<" << input << ">: No such directory or command" << std::flush;
317 
318   // display
319   G4UIArrayString arrayString(stream);
320   arrayString.Show(nColumn);
321 }
322