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