Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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
64/////////////////////////////////////////////////////////
65G4UItcsh::G4UItcsh(const G4String& prompt, G4int maxhist)
66 : G4VUIshell(prompt),
67 commandLine(""), cursorPosition(1),
68 commandHistory(maxhist), maxHistory(maxhist),
69 currentHistoryNo(1), relativeHistoryIndex(0)
70/////////////////////////////////////////////////////////
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;
80 G4String fname= homedir + historyFileName;
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
96/////////////////////
98/////////////////////
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
120//////////////////////////////////////////
121void G4UItcsh::MakePrompt(const char* msg)
122//////////////////////////////////////////
123{
124 if(promptSetting.length()<=1) {
126 return;
127 }
128
129 promptString="";
130 G4int i;
131 for(i=0; i<(G4int)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 == G4int(promptSetting.length()-1))
171}
172
173
174//////////////////////////////
176//////////////////////////////
177{
178 RestoreTerm();
179}
180
181
182// --------------------------------------------------------------------
183// commad line operations
184// --------------------------------------------------------------------
185//////////////////////////////////////
187//////////////////////////////////////
188{
189 commandLine= "";
191}
192
193///////////////////////////////////////
195///////////////////////////////////////
196{
197 if( ! (cc >= AsciiPrintableMin && isprint(cc)) ) return;
198
199 // display...
200 G4cout << cc;
201 std::size_t i;
202 for(i=cursorPosition-1; i<commandLine.length(); ++i)
203 G4cout << commandLine[(G4int)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
217///////////////////////////////////
219///////////////////////////////////
220{
221 if(cursorPosition==1) return;
222
223 // display...
224 if(IsCursorLast()) {
225 G4cout << AsciiBS << ' ' << AsciiBS << std::flush;
226 } else {
227 G4cout << AsciiBS;
228 std::size_t i;
229 for(i=cursorPosition-2; i< commandLine.length()-1; ++i){
230 G4cout << commandLine[G4int(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
245////////////////////////////////
247////////////////////////////////
248{
249 if(IsCursorLast()) return;
250
251 // display...
252 std::size_t i;
253 for(i=cursorPosition-1; i< commandLine.length()-1; ++i){
254 G4cout << commandLine[G4int(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
266//////////////////////////
268//////////////////////////
269{
270 // display...
271 std::size_t i;
272 for(i= cursorPosition; i>=2; i--) G4cout << AsciiBS;
273 for(i=1; i<=commandLine.length(); ++i) G4cout << ' ';
274 for(i=1; i<=commandLine.length(); ++i) G4cout << AsciiBS;
275 G4cout << std::flush;
276
277 // command line string...
278 commandLine.erase();
280}
281
282/////////////////////////////////
284/////////////////////////////////
285{
286 if(IsCursorLast()) return;
287
288 // display...
289 for(std::size_t i=cursorPosition; i<=commandLine.length(); ++i) G4cout << ' ';
290 for(G4int j=(G4int)commandLine.length(); j>=cursorPosition; --j) G4cout << AsciiBS;
291 G4cout << std::flush;
292
293 // command line string...
295 commandLine.length()-cursorPosition+1);
296}
297
298////////////////////////////
300////////////////////////////
301{
302 if(! clearString.empty() ) {
304
305 G4cout << promptString << commandLine << std::flush;
306 // reset cursur position
307 for(G4int i=G4int(commandLine.length()+1); i>=cursorPosition+1; --i)
308 G4cout << AsciiBS << std::flush;
309 }
310}
311
312//////////////////////////////
314//////////////////////////////
315{
316 if(IsCursorLast()) return;
317
318 G4cout << commandLine[cursorPosition-1] << std::flush;
320}
321
322///////////////////////////////
324///////////////////////////////
325{
326 if(cursorPosition==1) return;
327
329 G4cout << AsciiBS << std::flush;
330}
331
332//////////////////////////////
334//////////////////////////////
335{
336 for(G4int i=cursorPosition; i>1; --i){
337 G4cout << AsciiBS;
338 }
339 G4cout << std::flush;
341}
342
343//////////////////////////////
345//////////////////////////////
346{
347 for(G4int i=cursorPosition-1; i<(G4int)commandLine.length(); ++i){
348 G4cout << commandLine[i];
349 }
350 G4cout << std::flush;
351 cursorPosition=G4int(commandLine.length()+1);
352}
353
354////////////////////////////////
356////////////////////////////////
357{
358 G4int nhmax= currentHistoryNo-1 >= maxHistory ?
360
361 // retain current input
363
364 if(relativeHistoryIndex>=-nhmax+1 && relativeHistoryIndex<=0) {
365 ClearLine();
368
369 G4cout << commandLine << std::flush;
370 cursorPosition= G4int(commandLine.length()+1);
371 }
372}
373
374////////////////////////////
376////////////////////////////
377{
378 G4int nhmax= currentHistoryNo-1 >= maxHistory ?
380
381 if(relativeHistoryIndex>=-nhmax && relativeHistoryIndex<=-1) {
382 ClearLine();
384
387
388 G4cout << commandLine << std::flush;
389 cursorPosition= G4int(commandLine.length()+1);
390 }
391}
392
393
394///////////////////////////////////
396///////////////////////////////////
397{
398 G4cout << G4endl;
399
400 // input string
402 // target token is last token
403 auto jhead= input.rfind(' ');
404 if(jhead != G4String::npos) {
405 input.erase(0, jhead);
406 G4StrUtil::lstrip(input);
407 }
408
409 // command tree of "user specified directory"
411 G4String vcmd = "";
412
413 if( !input.empty() ) {
414 G4int len= (G4int)input.length();
415 G4int indx=-1;
416 for(G4int i=len-1; i>=0; --i) {
417 if(input[i]=='/') {
418 indx= (G4int)i;
419 break;
420 }
421 }
422 // get abs. path
423 if(indx != -1) vpath= GetAbsCommandDirPath(input.substr(0,indx+1));
424 if(!(indx==0 && len==1)) vcmd= input.substr(indx+1,len-indx-1); // care for "/"
425 }
426
427 // list matched dirs/commands
428 //G4cout << "@@@ vpath=" << vpath <<":vcmd=" << vcmd << G4endl;
429 ListCommand(vpath, vpath+vcmd);
430
431 G4cout << promptString << commandLine << std::flush;
432}
433
434////////////////////////////////
436////////////////////////////////
437{
438 // inputting string
440
441 // target token is last token
442 auto jhead= input.rfind(' ');
443 if(jhead != G4String::npos) {
444 input.erase(0, jhead);
445 G4StrUtil::lstrip(input);
446 }
447
448 // tail string
449 std::size_t thead = input.find_last_of('/');
450 G4String strtail = input;
451 if (thead != G4String::npos) strtail = input.substr(thead+1, input.size()-thead-1);
452
453 // command tree of "user specified directory"
455 G4String vcmd;
456
457 G4int len= (G4int)input.length();
458 if(!input.empty()) {
459 G4int indx= -1;
460 for(G4int i=len-1; i>=0; --i) {
461 if(input[i]=='/') {
462 indx= i;
463 break;
464 }
465 }
466 // get abs. path
467 if(indx != -1) vpath= GetAbsCommandDirPath(input.substr(0,indx+1));
468 if(!(indx==0 && len==1)) vcmd= input.substr(indx+1,len-indx-1); // care for "/"
469 }
470
471 G4UIcommandTree* atree= GetCommandTree(vpath); // get command tree
472 if(atree == NULL) return;
473
474 // list matched directories/commands
475 G4String stream, strtmp;
476 G4String inputpath= vpath+vcmd;
477 G4int nMatch= 0;
478
479 G4int Ndir= atree-> GetTreeEntry();
480 G4int Ncmd= atree-> GetCommandEntry();
481
482 // directory ...
483 for(G4int idir=1; idir<=Ndir; idir++) {
484 G4String fpdir= atree-> GetTree(idir)-> GetPathName();
485 // matching test
486 if( fpdir.find(inputpath, 0) == 0) {
487 if(nMatch==0) {
488 stream= GetCommandPathTail(fpdir);
489 } else {
490 strtmp= GetCommandPathTail(fpdir);
491 stream= GetFirstMatchedString(stream, strtmp);
492 }
493 nMatch++;
494 }
495 }
496
497 // command ...
498 for(G4int icmd=1; icmd<=Ncmd; icmd++){
499 G4String fpcmd= atree-> GetPathName() +
500 atree-> GetCommand(icmd) -> GetCommandName();
501 // matching test
502 if( fpcmd.find(inputpath, 0) ==0) {
503 if(nMatch==0) {
504 stream= GetCommandPathTail(fpcmd) + " ";
505 } else {
506 strtmp= GetCommandPathTail(fpcmd) + " ";
507 stream= GetFirstMatchedString(stream, strtmp);
508 }
509 nMatch++;
510 }
511 }
512
513 // display...
514 input= commandLine;
515 // target token is last token
516 jhead= input.rfind(' ');
517 if(jhead == G4String::npos) jhead=0;
518 else jhead++;
519
520 std::size_t jt = jhead;
521
522 G4String dspstr;
523 std::size_t i;
524 for(i=jt; i<=input.length()-1; ++i) dspstr+= AsciiBS;
525 for(i=jt; i<=input.length()-1; ++i) dspstr+= ' ';
526 for(i=jt; i<=input.length()-1; ++i) dspstr+= AsciiBS;
527
528 dspstr+= (vpath + stream);
529 if (nMatch == 0) dspstr+= strtail;
530 G4cout << dspstr << std::flush;
531
532 // command line string
533 input.erase(jt);
534 input+= (vpath + stream);
535 if (nMatch==0) input+= strtail;
536
537 commandLine= input;
538 cursorPosition= G4int(commandLine.length()+1);
539}
540
541// --------------------------------------------------------------------
542// commad line
543// --------------------------------------------------------------------
544/////////////////////////////
546/////////////////////////////
547{
549
550 char cc;
551 do{ // input loop
552 G4cin.get(cc);
553
554 // treatment for special character
555 switch(cc){
556 case AsciiCtrA: // ... move cursor to the top
558 break;
559 case AsciiCtrB: // ... backward cursor
561 break;
562 case AsciiCtrD: // ... delete/exit/show matched list
563 if(commandLine.length()!=0 && IsCursorLast()) ListMatchedCommand();
564 else if (commandLine.empty()) {
565 return G4String("exit");
566 } else DeleteCharacter();
567 break;
568 case AsciiCtrE: // ... move cursor to the end
570 break;
571 case AsciiCtrF: // ... forward cursor
573 break;
574 case AsciiCtrK: // ... clear after the cursor
576 break;
577 case AsciiCtrL: // ... clear screen
578 // ClearScreen();
579 break;
580 case AsciiCtrN: // ... next command
581 NextCommand();
582 break;
583 case AsciiCtrP: // ... previous command
585 break;
586 case AsciiTAB: // ... command completion
587 if( (!commandLine.empty()) && IsCursorLast()) CompleteCommand();
588 break;
589 case AsciiDEL: // ... backspace
591 break;
592 case AsciiBS: // ... backspace
594 break;
595 case AsciiCtrC: // ... kill prompt
596 break;
597 case AsciiCtrQ: // ... restarts suspeded output
598 break;
599 case AsciiCtrS: // ... suspend output
600 break;
601 case AsciiCtrZ: // ... suspend
602 break;
603 default:
604 break;
605 }
606
607 // treatment for ESC. character
608 if( cc == AsciiESC) { // ESC
609 G4cin.get(cc);
610 if (cc == '[' || cc == 'O') { // care for another termcap, such as konsole
611 G4cin.get(cc);
612 switch(cc) {
613 case 'A': // [UP]
614 cc = 'P' - '@';
615 PreviousCommand(); // ... show previous commad
616 break;
617 case 'B': // [DOWN]
618 cc = 'N' - '@';
619 NextCommand(); // ... show next commad
620 break;
621 case 'C': // [RIGHT]
622 cc = 'F' - '@';
623 ForwardCursor(); // ... forward cursor
624 break;
625 case 'D': // [LEFT]
626 cc = 'B' - '@';
627 BackwardCursor(); // ... backward cursor
628 break;
629 default: // who knows !?
630 cc = 0;
631 break;
632 }
633 }
634 }
635
636 // insert character to command line and display
637 InsertCharacter(cc);
638
639 } while( cc != '\n');
640
641 return commandLine;
642}
643
644////////////////////////////////////////////////////////
646////////////////////////////////////////////////////////
647{
649
650 MakePrompt(msg); // update
652
653 G4cout << promptString << std::flush;
654
655 G4String newCommand= ReadLine(); // read line...
656 // multi-line
657 while( (newCommand.length() > 0) &&
658 ( newCommand[G4int(newCommand.length()-1)] == '_') ) {
659 newCommand.erase(newCommand.length()-1);
660 G4cout << G4endl;
661 promptString= "? ";
662 G4cout << promptString << std::flush;
663 G4String newLine= ReadLine();
664 newCommand.append(newLine);
665 }
666
667 // update history...
668 G4bool isMeaningfull= FALSE; // check NULL command
669 for (G4int i=0; i<(G4int)newCommand.length(); ++i) {
670 if(newCommand[i] != ' ') {
671 isMeaningfull= TRUE;
672 break;
673 }
674 }
675 if( !newCommand.empty() && isMeaningfull) StoreHistory(newCommand);
676
677 // reset terminal
678 RestoreTerm();
679
680 G4cout << G4endl;
681 return newCommand;
682}
683
684////////////////////////////////////////////////////////////////////
686 const G4String& str2) const
687////////////////////////////////////////////////////////////////////
688{
689 std::size_t nlen1= str1.length();
690 std::size_t nlen2= str2.length();
691
692 std::size_t nmin = nlen1<nlen2 ? nlen1 : nlen2;
693
694 G4String strMatched;
695 for(G4int i=0; i<(G4int)nmin; ++i){
696 if(str1[i]==str2[i]) {
697 strMatched+= str1[i];
698 } else {
699 break;
700 }
701 }
702
703 return strMatched;
704}
705
706// --------------------------------------------------------------------
707// history
708// --------------------------------------------------------------------
709//////////////////////////////////////////////
711//////////////////////////////////////////////
712{
714 if(i==0) i=maxHistory;
715
716 commandHistory[i-1]= aCommand; // 0-offset
718}
719
720///////////////////////////////////////////////
722///////////////////////////////////////////////
723{
724 if(histNo>= currentHistoryNo) return "";
725
726 G4int index= histNo%maxHistory;
727 if(index==0) index= maxHistory;
728
729 return commandHistory[index-1]; // 0-offset
730}
731
732// --------------------------------------------------------------------
733// terminal mode
734// --------------------------------------------------------------------
735///////////////////////////////////
737///////////////////////////////////
738{
739 termios tiosbuf= tios;
740
741 tiosbuf.c_iflag &= ~(BRKINT | ISTRIP);
742 tiosbuf.c_iflag |= (IGNBRK | IGNPAR);
743 tiosbuf.c_lflag &= ~(ICANON | IEXTEN | ECHO);
744 tiosbuf.c_cc[VMIN] = 1;
745 tiosbuf.c_cc[VTIME] = 0;
746
747 tcsetattr(0, TCSAFLUSH, &tiosbuf);
748}
749
750
751////////////////////////////
753////////////////////////////
754{
755 tcsetattr(0, TCSAFLUSH, &tios);
756}
757
758#endif
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4cin
Definition: G4ios.hh:56
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()
void MoveCursorTop()
Definition: G4UItcsh.cc:333
void InsertCharacter(char cc)
Definition: G4UItcsh.cc:194
virtual void ResetTerminal()
Definition: G4UItcsh.cc:175
void PreviousCommand()
Definition: G4UItcsh.cc:355
virtual void MakePrompt(const char *msg=0)
Definition: G4UItcsh.cc:121
G4String GetFirstMatchedString(const G4String &str1, const G4String &str2) const
Definition: G4UItcsh.cc:685
void CompleteCommand()
Definition: G4UItcsh.cc:435
void NextCommand()
Definition: G4UItcsh.cc:375
G4String RestoreHistory(G4int index)
Definition: G4UItcsh.cc:721
void RestoreTerm()
Definition: G4UItcsh.cc:752
void ForwardCursor()
Definition: G4UItcsh.cc:313
G4String ReadLine()
Definition: G4UItcsh.cc:545
G4int cursorPosition
Definition: G4UItcsh.hh:75
void MoveCursorEnd()
Definition: G4UItcsh.cc:344
G4int currentHistoryNo
Definition: G4UItcsh.hh:107
void DeleteCharacter()
Definition: G4UItcsh.cc:246
termios tios
Definition: G4UItcsh.hh:115
void SetTermToInputMode()
Definition: G4UItcsh.cc:736
void ListMatchedCommand()
Definition: G4UItcsh.cc:395
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:645
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:323
void ClearAfterCursor()
Definition: G4UItcsh.cc:283
void ClearScreen()
Definition: G4UItcsh.cc:299
void StoreHistory(G4String aCommand)
Definition: G4UItcsh.cc:710
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 TRUE
Definition: globals.hh:41
#define FALSE
Definition: globals.hh:38
G4String strip_copy(G4String str, char ch=' ')
Return copy of string with leading and trailing characters removed.
void lstrip(G4String &str, char ch=' ')
Remove leading characters from string.
G4String lstrip_copy(G4String str, char ch=' ')
Return copy of string with leading characters removed.