Geant4_10
G4UItcsh.cc
Go to the documentation of this file.
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 // $Id: G4UItcsh.cc 66892 2013-01-17 10:57:59Z gunter $
28 //
29 
30 #ifndef WIN32
31 
32 #include "G4Types.hh"
33 #include "G4StateManager.hh"
34 #include "G4UIcommandStatus.hh"
35 #include "G4UItcsh.hh"
36 #include <ctype.h>
37 #include <sstream>
38 #include <fstream>
39 #include <stdlib.h>
40 
41 // ASCII character code
42 static const char AsciiCtrA = '\001';
43 static const char AsciiCtrB = '\002';
44 static const char AsciiCtrC = '\003';
45 static const char AsciiCtrD = '\004';
46 static const char AsciiCtrE = '\005';
47 static const char AsciiCtrF = '\006';
48 static const char AsciiCtrK = '\013';
49 static const char AsciiCtrL = '\014';
50 static const char AsciiCtrN = '\016';
51 static const char AsciiCtrP = '\020';
52 static const char AsciiCtrQ = '\021';
53 static const char AsciiCtrS = '\023';
54 static const char AsciiCtrZ = '\032';
55 static const char AsciiTAB = '\011';
56 static const char AsciiBS = '\010';
57 static const char AsciiDEL = '\177';
58 static const char AsciiESC = '\033';
59 
60 static const int AsciiPrintableMin = 32;
61 
62 // history file
63 static const G4String historyFileName= "/.g4_hist";
64 
66 G4UItcsh::G4UItcsh(const G4String& prompt, G4int maxhist)
67  : G4VUIshell(prompt),
68  commandLine(""), cursorPosition(1),
69  commandHistory(maxhist), maxHistory(maxhist),
70  currentHistoryNo(1), relativeHistoryIndex(0)
72 {
73  // get current terminal mode
74  tcgetattr(0, &tios);
75 
76  // read a shell history file
77  const char* path = getenv("HOME");
78  if( path == NULL ) return;
79 
80  G4String homedir= path;
81  G4String fname= homedir + historyFileName;
82 
83  std::ifstream histfile;
84  enum { BUFSIZE= 1024 }; char linebuf[BUFSIZE];
85 
86  histfile.open(fname, std::ios::in);
87  while (histfile.good()) {
88  if(histfile.eof()) break;
89 
90  histfile.getline(linebuf, BUFSIZE);
91  G4String aline= linebuf;
92  aline.strip(G4String::both);
93  if(aline.size() != 0) StoreHistory(linebuf);
94  }
95  histfile.close();
96 }
97 
101 {
102  // store a shell history
103  const char* path = getenv("HOME");
104  if( path == NULL ) return;
105 
106  G4String homedir= path;
107  G4String fname= homedir + historyFileName;
108 
109  std::ofstream histfile;
110  histfile.open(fname, std::ios::out);
111 
112  G4int n0hist= 1;
114 
115  for (G4int i=n0hist; i<= currentHistoryNo; i++) {
116  histfile << RestoreHistory(i) << G4endl;
117  }
118 
119  histfile.close();
120 }
121 
123 void G4UItcsh::MakePrompt(const char* msg)
125 {
126  if(promptSetting.length()<=1) {
128  return;
129  }
130 
131  promptString="";
132  size_t i;
133  for(i=0; i<promptSetting.length()-1; i++){
134  if(promptSetting[i]=='%'){
135  switch (promptSetting[i+1]) {
136  case 's': // current application status
137  {
138  G4String stateStr;
139  if(msg)
140  { stateStr = msg; }
141  else
142  {
144  stateStr= statM-> GetStateString(statM->GetCurrentState());
145  }
146  promptString.append(stateStr);
147  i++;
148  }
149  break;
150  case '/': // current working directory
152  i++;
153  break;
154  case 'h': // history#
155  {
156  std::ostringstream os;
157  os << currentHistoryNo;
158  promptString.append(os.str());
159  i++;
160  }
161  break;
162  default:
163  break;
164  }
165  } else {
167  }
168  }
169 
170  // append last chaacter
171  if(i == promptSetting.length()-1)
173 }
174 
175 
179 {
180  RestoreTerm();
181 }
182 
183 
184 // --------------------------------------------------------------------
185 // commad line operations
186 // --------------------------------------------------------------------
190 {
191  commandLine= "";
192  cursorPosition= 1;
193 }
194 
198 {
199  if( ! (cc >= AsciiPrintableMin && isprint(cc)) ) return;
200 
201  // display...
202  G4cout << cc;
203  size_t i;
204  for(i=cursorPosition-1; i<commandLine.length() ;i++)
205  G4cout << commandLine[i];
206  for(i=cursorPosition-1; i<commandLine.length() ;i++)
207  G4cout << AsciiBS;
208  G4cout << std::flush;
209 
210  // command line string...
211  if(IsCursorLast()) { // add
212  commandLine+= cc;
213  } else { // insert
214  commandLine.insert(cursorPosition-1, G4String(cc));
215  }
216  cursorPosition++;
217 }
218 
222 {
223  if(cursorPosition==1) return;
224 
225  // display...
226  if(IsCursorLast()) {
227  G4cout << AsciiBS << ' ' << AsciiBS << std::flush;
228  } else {
229  G4cout << AsciiBS;
230  size_t i;
231  for(i=cursorPosition-2; i< commandLine.length()-1 ;i++){
232  G4cout << commandLine[i+1];
233  }
234  G4cout << ' ';
235  for(i=cursorPosition-2; i< commandLine.length() ;i++){
236  G4cout << AsciiBS;
237  }
238  G4cout << std::flush;
239  }
240 
241  // command line string...
242  commandLine.erase(cursorPosition-2, 1);
243 
244  cursorPosition--;
245 }
246 
250 {
251  if(IsCursorLast()) return;
252 
253  // display...
254  size_t i;
255  for(i=cursorPosition-1; i< commandLine.length()-1 ;i++){
256  G4cout << commandLine[i+1];
257  }
258  G4cout << ' ';
259  for(i=cursorPosition-1; i< commandLine.length() ;i++){
260  G4cout << AsciiBS;
261  }
262  G4cout << std::flush;
263 
264  // command lin string...
265  commandLine.erase(cursorPosition-1, 1);
266 }
267 
271 {
272  // display...
273  G4int i;
274  for(i= cursorPosition; i>=2; i--) G4cout << AsciiBS;
275  for(i=1; i<=G4int(commandLine.length()); i++) G4cout << ' ';
276  for(i=1; i<=G4int(commandLine.length()); i++) G4cout << AsciiBS;
277  G4cout << std::flush;
278 
279  // command line string...
280  commandLine.erase();
281  cursorPosition= 1;
282 }
283 
287 {
288  if(IsCursorLast()) return;
289 
290  // display...
291  G4int i;
292  for(i=cursorPosition; i<=G4int(commandLine.length()); i++) G4cout << ' ';
293  for(i=commandLine.length(); i>=cursorPosition; i--) G4cout << AsciiBS;
294  G4cout << std::flush;
295 
296  // command line string...
297  commandLine.erase(cursorPosition-1,
298  commandLine.length()-cursorPosition+1);
299 }
300 
304 {
305  if(! clearString.empty() ) {
306  G4cout << clearString;
307 
308  G4cout << promptString << commandLine << std::flush;
309  // reset cursur position
310  for(G4int i=commandLine.length()+1; i>=cursorPosition+1; i--)
311  G4cout << AsciiBS << std::flush;
312  }
313 }
314 
318 {
319  if(IsCursorLast()) return;
320 
321  G4cout << commandLine[(size_t)(cursorPosition-1)] << std::flush;
322  cursorPosition++;
323 }
324 
328 {
329  if(cursorPosition==1) return;
330 
331  cursorPosition--;
332  G4cout << AsciiBS << std::flush;
333 }
334 
338 {
339  for(G4int i=cursorPosition; i>1; i--){
340  G4cout << AsciiBS;
341  }
342  G4cout << std::flush;
343  cursorPosition=1;
344 }
345 
349 {
350  for(size_t i=cursorPosition-1; i<commandLine.length(); i++){
351  G4cout << commandLine[i];
352  }
353  G4cout << std::flush;
354  cursorPosition=commandLine.length()+1;
355 }
356 
360 {
361  G4int nhmax= currentHistoryNo-1 >= maxHistory ?
363 
364  // retain current input
366 
367  if(relativeHistoryIndex>=-nhmax+1 && relativeHistoryIndex<=0) {
368  ClearLine();
371 
372  G4cout << commandLine << std::flush;
373  cursorPosition= commandLine.length()+1;
374  }
375 }
376 
380 {
381  G4int nhmax= currentHistoryNo-1 >= maxHistory ?
383 
384  if(relativeHistoryIndex>=-nhmax && relativeHistoryIndex<=-1) {
385  ClearLine();
387 
390 
391  G4cout << commandLine << std::flush;
392  cursorPosition= commandLine.length()+1;
393  }
394 }
395 
396 
400 {
401  G4cout << G4endl;
402 
403  // input string
405  // target token is last token
406  G4int jhead= input.last(' ');
407  if(jhead != G4int(G4String::npos)) {
408  input.remove(0, jhead);
409  input= input.strip(G4String::leading);
410  }
411  //G4cout << "@@@@ input=" << input << G4endl;
412 
413  // command tree of "user specified directory"
414  G4String vpath = currentCommandDir;
415  G4String vcmd = "";
416 
417  if( !input.empty() ) {
418  G4int len= input.length();
419  G4int indx=-1;
420  for(G4int i=len-1; i>=0; i--) {
421  if(input[(size_t)i]=='/') {
422  indx= i;
423  break;
424  }
425  }
426  // get abs. path
427  if(indx != -1) vpath= GetAbsCommandDirPath(input(0,indx+1));
428  if(!(indx==0 && len==1)) vcmd= input(indx+1,len-indx-1); // care for "/"
429  }
430 
431  // list matched dirs/commands
432  //G4cout << "@@@ vpath=" << vpath <<":vcmd=" << vcmd << G4endl;
433  ListCommand(vpath, vpath+vcmd);
434 
435  G4cout << promptString << commandLine << std::flush;
436 }
437 
441 {
442  // inputting string
444  // target token is last token
445  G4int jhead= input.last(' ');
446  if(jhead != G4int(G4String::npos)) {
447  input.remove(0, jhead);
448  input= input.strip(G4String::leading);
449  }
450 
451  // tail string
452  size_t thead = input.find_last_of('/');
453  G4String strtail = input;
454  if (thead != G4String::npos) strtail = input(thead+1, input.size()-thead-1);
455 
456  // command tree of "user specified directory"
458  G4String vcmd;
459 
460  G4int len= input.length();
461  if(!input.empty()) {
462  G4int indx= -1;
463  for(G4int i=len-1; i>=0; i--) {
464  if(input(i)=='/') {
465  indx= i;
466  break;
467  }
468  }
469  // get abs. path
470  if(indx != -1) vpath= GetAbsCommandDirPath(input(0,indx+1));
471  if(!(indx==0 && len==1)) vcmd= input(indx+1,len-indx-1); // care for "/"
472  }
473 
474  G4UIcommandTree* atree= GetCommandTree(vpath); // get command tree
475  if(atree == NULL) return;
476 
477  // list matched directories/commands
478  G4String stream, strtmp;
479  G4String inputpath= vpath+vcmd;
480  G4int nMatch= 0;
481 
482  int Ndir= atree-> GetTreeEntry();
483  int Ncmd= atree-> GetCommandEntry();
484 
485  // directory ...
486  for(G4int idir=1; idir<=Ndir; idir++) {
487  G4String fpdir= atree-> GetTree(idir)-> GetPathName();
488  // matching test
489  if( fpdir.index(inputpath, 0) == 0) {
490  if(nMatch==0) {
491  stream= GetCommandPathTail(fpdir);
492  } else {
493  strtmp= GetCommandPathTail(fpdir);
494  stream= GetFirstMatchedString(stream, strtmp);
495  }
496  nMatch++;
497  }
498  }
499 
500  // command ...
501  for(G4int icmd=1; icmd<=Ncmd; icmd++){
502  G4String fpcmd= atree-> GetPathName() +
503  atree-> GetCommand(icmd) -> GetCommandName();
504  // matching test
505  if( fpcmd.index(inputpath, 0) ==0) {
506  if(nMatch==0) {
507  stream= GetCommandPathTail(fpcmd) + " ";
508  } else {
509  strtmp= GetCommandPathTail(fpcmd) + " ";
510  stream= GetFirstMatchedString(stream, strtmp);
511  }
512  nMatch++;
513  }
514  }
515 
516  // display...
517  input= commandLine;
518  // target token is last token
519  jhead= input.last(' ');
520  if(jhead == G4int(G4String::npos)) jhead=0;
521  else jhead++;
522 
523  G4int jt = jhead;
524 
525  G4String dspstr;
526  G4int i;
527  for(i=jt; i<=G4int(input.length())-1; i++) dspstr+= G4String(AsciiBS);
528  for(i=jt; i<=G4int(input.length())-1; i++) dspstr+= G4String(' ');
529  for(i=jt; i<=G4int(input.length())-1; i++) dspstr+= G4String(AsciiBS);
530 
531  dspstr+= (vpath + stream);
532  if (nMatch == 0) dspstr+= strtail;
533  G4cout << dspstr << std::flush;
534 
535  // command line string
536  input.remove(jt);
537  input+= (vpath + stream);
538  if (nMatch==0) input+= strtail;
539 
540  commandLine= input;
541  cursorPosition= commandLine.length()+1;
542 }
543 
544 // --------------------------------------------------------------------
545 // commad line
546 // --------------------------------------------------------------------
550 {
552 
553  char cc;
554  do{ // input loop
555  G4cin.get(cc);
556 
557  // treatment for special character
558  switch(cc){
559  case AsciiCtrA: // ... move cursor to the top
560  MoveCursorTop();
561  break;
562  case AsciiCtrB: // ... backward cursor
563  BackwardCursor();
564  break;
565  case AsciiCtrD: // ... delete/exit/show matched list
566  if(commandLine.length()!=0 && IsCursorLast()) ListMatchedCommand();
567  else if (commandLine.empty()) {
568  return G4String("exit");
569  } else DeleteCharacter();
570  break;
571  case AsciiCtrE: // ... move cursor to the end
572  MoveCursorEnd();
573  break;
574  case AsciiCtrF: // ... forward cursor
575  ForwardCursor();
576  break;
577  case AsciiCtrK: // ... clear after the cursor
579  break;
580  case AsciiCtrL: // ... clear screen
581  // ClearScreen();
582  break;
583  case AsciiCtrN: // ... next command
584  NextCommand();
585  break;
586  case AsciiCtrP: // ... previous command
587  PreviousCommand();
588  break;
589  case AsciiTAB: // ... command completion
590  if( (!commandLine.empty()) && IsCursorLast()) CompleteCommand();
591  break;
592  case AsciiDEL: // ... backspace
594  break;
595  case AsciiBS: // ... backspace
597  break;
598  case AsciiCtrC: // ... kill prompt
599  break;
600  case AsciiCtrQ: // ... restarts suspeded output
601  break;
602  case AsciiCtrS: // ... suspend output
603  break;
604  case AsciiCtrZ: // ... suspend
605  break;
606  default:
607  break;
608  }
609 
610  // treatment for ESC. character
611  if( cc == AsciiESC) { // ESC
612  G4cin.get(cc);
613  if (cc == '[' || cc == 'O') { // care for another termcap, such as konsole
614  G4cin.get(cc);
615  switch(cc) {
616  case 'A': // [UP]
617  cc = 'P' - '@';
618  PreviousCommand(); // ... show previous commad
619  break;
620  case 'B': // [DOWN]
621  cc = 'N' - '@';
622  NextCommand(); // ... show next commad
623  break;
624  case 'C': // [RIGHT]
625  cc = 'F' - '@';
626  ForwardCursor(); // ... forward cursor
627  break;
628  case 'D': // [LEFT]
629  cc = 'B' - '@';
630  BackwardCursor(); // ... backward cursor
631  break;
632  default: // who knows !?
633  cc = 0;
634  break;
635  }
636  }
637  }
638 
639  // insert character to command line and display
640  InsertCharacter(cc);
641 
642  } while( cc != '\n');
643 
644  return commandLine;
645 }
646 
650 {
652 
653  MakePrompt(msg); // update
655 
656  G4cout << promptString << std::flush;
657 
658  G4String newCommand= ReadLine(); // read line...
659  // multi-line
660  while( (newCommand.length() > 0) &&
661  ( newCommand[newCommand.length()-1] == '_') ) {
662  newCommand.remove(newCommand.length()-1);
663  G4cout << G4endl;
664  promptString= "? ";
665  G4cout << promptString << std::flush;
666  G4String newLine= ReadLine();
667  newCommand.append(newLine);
668  }
669 
670  // update history...
671  G4bool isMeaningfull= FALSE; // check NULL command
672  for (size_t i=0; i<newCommand.length(); i++) {
673  if(newCommand[i] != ' ') {
674  isMeaningfull= TRUE;
675  break;
676  }
677  }
678  if( !newCommand.empty() && isMeaningfull) StoreHistory(newCommand);
679 
680  // reset terminal
681  RestoreTerm();
682 
683  G4cout << G4endl;
684  return newCommand;
685 }
686 
689  const G4String& str2) const
691 {
692  int nlen1= str1.length();
693  int nlen2= str2.length();
694 
695  int nmin = nlen1<nlen2 ? nlen1 : nlen2;
696 
697  G4String strMatched;
698  for(size_t i=0; G4int(i)<nmin; i++){
699  if(str1[i]==str2[i]) {
700  strMatched+= str1[i];
701  } else {
702  break;
703  }
704  }
705 
706  return strMatched;
707 }
708 
709 // --------------------------------------------------------------------
710 // history
711 // --------------------------------------------------------------------
715 {
717  if(i==0) i=maxHistory;
718 
719  commandHistory[i-1]= aCommand; // 0-offset
721 }
722 
726 {
727  if(histNo>= currentHistoryNo) return "";
728 
729  G4int index= histNo%maxHistory;
730  if(index==0) index= maxHistory;
731 
732  return commandHistory[index-1]; // 0-offset
733 }
734 
735 // --------------------------------------------------------------------
736 // terminal mode
737 // --------------------------------------------------------------------
741 {
742  termios tiosbuf= tios;
743 
744  tiosbuf.c_iflag &= ~(BRKINT | ISTRIP);
745  tiosbuf.c_iflag |= (IGNBRK | IGNPAR);
746  tiosbuf.c_lflag &= ~(ICANON | IEXTEN | ECHO);
747  tiosbuf.c_cc[VMIN] = 1;
748  tiosbuf.c_cc[VTIME] = 0;
749 
750  tcsetattr(0, TCSAFLUSH, &tiosbuf);
751 }
752 
753 
757 {
758  tcsetattr(0, TCSAFLUSH, &tios);
759 }
760 
761 #endif
762 
virtual G4String GetCommandLineString(const char *msg=0)
Definition: G4UItcsh.cc:648
G4String GetCommandPathTail(const G4String &apath) const
Definition: G4VUIshell.cc:193
G4String promptString
Definition: G4VUIshell.hh:62
G4bool IsCursorLast() const
Definition: G4UItcsh.hh:134
Int_t index
Definition: macro.C:9
G4String & remove(str_size)
G4String strip(G4int strip_Type=trailing, char c=' ')
ifstream in
Definition: comparison.C:7
void ClearLine()
Definition: G4UItcsh.cc:269
G4int relativeHistoryIndex
Definition: G4UItcsh.hh:109
virtual void ListCommand(const G4String &input, const G4String &candidate="") const
Definition: G4VUIshell.cc:231
void InsertCharacter(char cc)
Definition: G4UItcsh.cc:196
void BackspaceCharacter()
Definition: G4UItcsh.cc:220
int G4int
Definition: G4Types.hh:78
void BackwardCursor()
Definition: G4UItcsh.cc:326
G4String commandLineBuf
Definition: G4UItcsh.hh:77
void SetTermToInputMode()
Definition: G4UItcsh.cc:739
std::vector< G4String > commandHistory
Definition: G4UItcsh.hh:106
G4String GetFirstMatchedString(const G4String &str1, const G4String &str2) const
Definition: G4UItcsh.cc:688
G4String RestoreHistory(G4int index)
Definition: G4UItcsh.cc:724
G4String GetAbsCommandDirPath(const G4String &apath) const
Definition: G4VUIshell.cc:147
~G4UItcsh()
Definition: G4UItcsh.cc:99
virtual void MakePrompt(const char *msg=0)
Definition: G4UItcsh.cc:123
static G4StateManager * GetStateManager()
#define G4cin
Definition: G4ios.hh:60
G4GLOB_DLL std::ostream G4cout
str_size index(const char *, G4int pos=0) const
virtual void ResetTerminal()
Definition: G4UItcsh.cc:177
bool G4bool
Definition: G4Types.hh:79
void ClearScreen()
Definition: G4UItcsh.cc:302
void ForwardCursor()
Definition: G4UItcsh.cc:316
#define FALSE
Definition: globals.hh:52
void CompleteCommand()
Definition: G4UItcsh.cc:439
void DeleteCharacter()
Definition: G4UItcsh.cc:248
#define TRUE
Definition: globals.hh:55
G4UItcsh(const G4String &prompt="%s> ", G4int maxhist=100)
Definition: G4UItcsh.cc:66
G4ApplicationState GetCurrentState() const
G4String commandLine
Definition: G4UItcsh.hh:75
G4UIcommandTree * GetCommandTree(const G4String &dir) const
Definition: G4VUIshell.cc:118
void ListMatchedCommand()
Definition: G4UItcsh.cc:398
G4String ReadLine()
Definition: G4UItcsh.cc:548
G4int currentHistoryNo
Definition: G4UItcsh.hh:108
termios tios
Definition: G4UItcsh.hh:116
G4int last(char) const
void MoveCursorTop()
Definition: G4UItcsh.cc:336
void RestoreTerm()
Definition: G4UItcsh.cc:755
void PreviousCommand()
Definition: G4UItcsh.cc:358
G4String & append(const G4String &)
void NextCommand()
Definition: G4UItcsh.cc:378
G4String currentCommandDir
Definition: G4VUIshell.hh:73
const XML_Char int len
Definition: expat.h:262
#define G4endl
Definition: G4ios.hh:61
string fname
Definition: test.py:308
void InitializeCommandLine()
Definition: G4UItcsh.cc:188
G4String clearString
Definition: G4UItcsh.hh:117
void MoveCursorEnd()
Definition: G4UItcsh.cc:347
void StoreHistory(G4String aCommand)
Definition: G4UItcsh.cc:713
G4String promptSetting
Definition: G4VUIshell.hh:61
#define BUFSIZE
Definition: liblist.c:41
G4int cursorPosition
Definition: G4UItcsh.hh:76
G4int maxHistory
Definition: G4UItcsh.hh:107
void ClearAfterCursor()
Definition: G4UItcsh.cc:285