Konsoleneingabeverfahren (Auto completion)
-
Hallo,
ich würde gern eine art autovervollständigungsroutine bei drücken von tab in meiner konsolenapplikation integrieren.
cin stellt sowas nicht zur verfügung oder? müsste ich da sozusagen eine selbstgetsrickte eingaberoutine basteln? sonderzeichen wie pfeiltasten lassen sich ja über getch() abfangen oder?
Hat jemand eventuell schon mal eine eingaberoutine geschrieben und mag sie posten? stell mir das nämlich ganz schön stressig vor, gerade so mit pfeil-links und dann zeichen einfügen und so...
oder auch pfeil nach oben für die letzten paar befehle, die müsste man dann auch irgendwo zwischenspeichern.....ich habe mir das so vorgestellt, dass die routine einfach bei drücken von tab den bisherigen string checkt und in einem <vector> nach möglichen kandidaten für eine vervollständigung schaut.
nun gut,
falls jemand was hat kann er es ja mal schicken, ansonsten muss ich halt selbst ran.....gruß
jOe
-
mc_ginley schrieb:
stell mir das nämlich ganz schön stressig vor, gerade so mit pfeil-links und dann zeichen einfügen und so...
naja, es hält sich in grenzen. ich hab in basic öfters sowas gemacht.
es war recht einfach zu implementieren, wenn ich zwei strings für die aktuele zeile genommen habe, einen string für das vor dem corsor und einen string für das nach dem cursor. ich nenne die strings mal left und right. dann sind die komischen tasten bald beherrschbar.
backspace: letztes zeichen von left löschen
del: erstes zeichen von right löschen
cursor-left: letzes von left löschen und vorn an right hängen
cursor-right: erstes von right löschen und hinten an left hängen
anderes zeichen: zeichen hinten an left hängenund wenn's einem spaß macht, kann man sich überlegen, ob right nicht besser anderesrum gespeichert werden sollte (war in basic ausgeschlossen). man kann für die tasten pos1 und end feine implementierunen machen. und so weiter.
-
...ja genau pos1 und ende! nicht zu vergesssen!
nun gut, aber wie siehts aus mit solchen einagben wie î oder á oder à? diese ganzen sonderzeichen die zwei tastendrücke benötigen müssten dann so richtig von hand implementiert werden? ich seh schon schweißperlen auf meiner stirn...
wie schauts mit ALT-GR + ziffernblock? setzt getch() sowas um, bzw liefer [ALT GR] +[7] auch "{"?gruß
jOe
-
mc_ginley schrieb:
...ja genau pos1 und ende! nicht zu vergesssen!
nun gut, aber wie siehts aus mit solchen einagben wie î oder á oder à? diese ganzen sonderzeichen die zwei tastendrücke benötigen müssten dann so richtig von hand implementiert werden? ich seh schon schweißperlen auf meiner stirn...
wie schauts mit ALT-GR + ziffernblock? setzt getch() sowas um, bzw liefer [ALT GR] +[7] auch "{"?gruß
jOeich schätze, getch macht das alles. probiers aus mit
for(;;) cout<<getch()<<'\n;
und sag mal bescheid, ob í und ì und î gehen. [altgr]+ziffernblock macht sicherlich jemand anderes.
-
... ja also ALT-GR funktioniert, auch die Geschichte mit dem â - PUUUHH.
Ich hab nur gerade das Problem das getch sich mit den Pfeiltasten nicht so verhält wie es soll.
Normalerweise soll getch() bei Pfeil oder Funktionstasten 0 oder 0xE0 (224) liefern. Bei den Funktionstasten klappt das auch, da kommt 0.
0xE0 bzw 224 erhalte ich aber nie! Somit kann ich auch [TAB] nicht abfangen (das worums ja eigentlich ging....
woran kann das denn liegen?gruß
jOe
-
..is ok, lag daran dass ich mein zeichen als char und nicht als int definiert hatte....
wie kann ich diesen integer wert nun an einen string anhängen?
-
mc_ginley schrieb:
woran kann das denn liegen?
ich tippe zuerst auf messfehler.
wobei ich nicht auf 224 warten würde, sondern nur gucken, was denn bei cursortasten geliefert wird. getch() mag gerne mal bei jedem compiler ein anderes mapping von taste zu zahlenkombination haben.
-
mc_ginley schrieb:
..is ok, lag daran dass ich mein zeichen als char und nicht als int definiert hatte....
denk noch drüber nach, ob bei dir
int getKey(){ int key=getch();//getch gibt doch keine munuszahlen, oder? if(key==0) key=256+getch(); return result; }
sich auf den code positiv auswürken würde.
-
... so ich poste mal das was ich zusammengeschrieben hab. falls mal jemand sowas braucht
bis jetzt keine groben bugs... ich lass mich aber gern eines besseren belehrenfeatures:
- multiline, eingabe kann über mehrere zeilen gehen, auch am konsolenbufferende (war das ein gefrickel!)
- entfernen/einfügen im string
- pos1, ende, links, rechtsmögliche verbesserungen:
- vector für die letzten eingaben ( für pfeil nach oben/unten)
- die cursor x-koordinate müsste man irgendwie mal klug berechnen und nicht durchiterieren ( beim berechnen treten bei perioden 0.333333 usw rundungsfehler auf deswegen hab ichs erst mal so gelöst)
- wie fügt man ein int an einen string an? ich habs mit stringstream "notgelöst", das lässt sich sicher besser machen....so, die vervollständigung macht dann Inpcomplete. Das sollte true zurückgeben wenn eine lösung gefunden wurde. das ist dann aber aufgabenspezifisch und kann sich ja jeder selber zusammenfrickeln....
char getlast( string* in ) { char ch; if ( in->length() == 0) return 0; ch = in->c_str()[in->length() - 1 ]; return ch; } char getfirst( string* in ) { char ch; if ( in->length() == 0) return 0; ch = in->c_str()[0]; return ch; } string cutlast( string in ) { string tmp; if ( in.length() == 0 ) return tmp; tmp.assign ( in.substr( 0, in.length()-1 ) ); return tmp; } string cutfirst( string in ) { string tmp; if ( in.length() == 0 ) return tmp; tmp.assign( in.substr( 1 ) ); return tmp; } ////////////////////////////////////////////////////////////////////////////////////////////// // setcursor // void setcursor ( DWORD dimx, DWORD dimy, DWORD x, DWORD y , UINT _pos ) { UINT ox,oy; /////////////////////////////////////////////////////////////////// // calculate y oy = y + (_pos + x)/dimx; /////////////////////////////////////////////////////////////////// // iterate x ox = x; for ( int i = 0; i < _pos; i++ ){ ox++; if ( ox == dimx ) ox = 0; } gotoxy(ox,oy); return; } ////////////////////////////////////////////////////////////////////////////////////////////// // out // void out( DWORD dimx, DWORD dimy, DWORD* x, DWORD* y, string* left, string* right, bool del) { DWORD written; UINT len; SHORT ox,oy; long ctoe; // characters to end UINT _pos; len = left->length() + right->length(); _pos = left->length(); gotoxy( *x, *y ); //////////////////////////// // calculate reseading space ctoe = dimx * dimy - ( *y * dimx + *x); //////////////////////////// // adjust y if new line if ( len >= ctoe ){ *y = *y - 1; } //////////////////////////// // write left part WriteConsole( GetStdHandle(STD_OUTPUT_HANDLE), left->c_str(), (DWORD)left->length(), &written, 0); //////////////////////////// // write right part WriteConsole( GetStdHandle(STD_OUTPUT_HANDLE), right->c_str(), (DWORD)right->length(), &written, 0); //////////////////////////// // write ' ' if string got shorter if ( del ) cout << " "; setcursor( dimx, dimy, *x,*y,left->length() ); } ////////////////////////////////////////////////////////////////////////////////////////////// // GetInput // string GetInput() { string left_,right_; string inp; int ch; DWORD x_start,y_start; DWORD dimx,dimy; DWORD conmode; x_start = con.getCaretX(); // initial cursorpos on start y_start = con.getCaretY(); dimx = con.getSizeX(); dimy = con.getSizeY(); //////////////////////////////////// // enable wrap (important for out()) GetConsoleMode( GetStdHandle(STD_OUTPUT_HANDLE), &conmode ); SetConsoleMode( GetStdHandle(STD_OUTPUT_HANDLE), conmode | ENABLE_WRAP_AT_EOL_OUTPUT ); start: ch = _getch(); ///////////////////////////////////////////////////////////////////////////////////////////// // handle TAB ==> Input Completion if ( ch == 9 ) { string tmp; tmp.assign( left_.c_str() ); tmp.append( right_.c_str() ); int oldlen = (int)tmp.length(); ///////////////////////////////////////////////////////////////////////////////////////////// // if Completion successfull if ( InpComplete(&tmp) ) { left_.clear(); right_.clear(); left_.assign( tmp.c_str() ); out(dimx,dimy,&x_start,&y_start,&left_,&right_,false); /////////////////////////////////////// // if new string is shorter, print " " while ( oldlen > (int)left_.length() ) { cout << " "; oldlen--; } out(dimx,dimy,&x_start,&y_start,&left_,&right_,false); } goto start; } ///////////////////////////////////////////////////////////////////////////////////////////// // handle backspace if ( ch == 8 ) { if ( getlast(&left_) != 0 ) { //////////////////////// // cut last from left left_ = cutlast( left_ ); //////////////////////// // print output out(dimx,dimy,&x_start,&y_start,&left_,&right_,true); } goto start; } ///////////////////////////////////////////////////////////////////////////////////////////// // handle function keys if ( ( ch == 0) || ( ch == 0xE0 ) ) { ch = _getch(); ///////////////////////////////////////////////////////////////////////////////////////////// // handle end if ( ch == 79 ) { //if ( pos < ( left_.length() + right_.length() ) ) { if ( right_.length() > 0 ) { /////////////////////////// // copy everything to left string tmp; tmp.assign( left_.c_str() ); tmp.append( right_.c_str() ); left_.clear(); right_.clear(); left_.assign( tmp.c_str() ); /////////////////////////// // print output setcursor( dimx, dimy, x_start,y_start, left_.length()); } } ///////////////////////////////////////////////////////////////////////////////////////////// // handle Pos1 if ( ch == 71 ) { if ( left_.length() > 0 ) { /////////////////////////// // copy everything to right string tmp; tmp.assign( left_.c_str() ); tmp.append( right_.c_str() ); left_.clear(); right_.clear(); right_.assign( tmp.c_str() ); /////////////////////////// // print output //out(dimx,dimy,&x_start,&y_start,&left_,&right_,false); setcursor( dimx, dimy, x_start,y_start, left_.length()); } } ///////////////////////////////////////////////////////////////////////////////////////////// // handle Erase if ( ch == 83 ) { if ( getfirst(&right_) != 0 ) { /////////////////////////// // cut first right string tmp2; tmp2.assign( right_.substr( 1 ) ); right_.clear(); right_.assign( tmp2.c_str() ); /////////////////////////// // print output out(dimx,dimy,&x_start,&y_start,&left_,&right_,true); } } ///////////////////////////////////////////////////////////////////////////////////////////// // handle right arrow if ( ch == 77 ) { if ( getfirst(&right_) != 0 ) { /////////////////////////// // append first right to left stringstream tmp; tmp << left_.c_str(); tmp << (char)getfirst(&right_); left_.clear(); left_.assign( tmp.str().c_str() ); /////////////////////////// // cut first right string tmp2; tmp2.assign( right_.substr( 1 ) ); right_.clear(); right_.assign( tmp2.c_str() ); /////////////////////////// // move cursor setcursor( dimx, dimy, x_start,y_start, left_.length()); } } ///////////////////////////////////////////////////////////////////////////////////////////// // handle left arrow if ( ch == 75 ) { if ( getlast(&left_) != 0 ) { /////////////////////////// // copy last character from left to first right stringstream tmp; tmp << (char)getlast(&left_); tmp << right_.c_str(); right_.clear(); right_.assign( tmp.str().c_str() ); /////////////////////////// // cut last character from left left_ = cutlast(left_); /////////////////////////// // move cursor - x setcursor( dimx, dimy, x_start,y_start, left_.length()); } } goto start; } ///////////////////////////////////////////////////////////////////////////////////////////// // append the character and put it on screen if ( ch != 13 ) { stringstream tmp; tmp << left_.c_str(); tmp << (char)ch; left_.clear(); left_.assign( tmp.str().c_str() ); ///////////////////////// // print output out(dimx,dimy,&x_start,&y_start,&left_,&right_,false); } if ( ch != 13 ) goto start; cout << "\n"; ////////////////////////// // reset mode SetConsoleMode( GetStdHandle(STD_OUTPUT_HANDLE), conmode ); inp.assign( left_ ); inp.append( right_ ); return inp; }