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