Terminalbreite mit getenv() auswerten
Hallo *, ich würde gerne die Shellfensterbreite auswerten um einen Fortschrittsbalken zu erzeugen. Derzeit versuche ich das so: --- snip --- void progress( float factor ) { int MAX_CHARS = 70; char* string_ptr = getenv( "COLUMNS" ); if( string_ptr != NULL ) { //cout << "COL: " << string_ptr << endl; MAX_CHARS = atoi( string_ptr ) - 10; if( MAX_CHARS < 0 ) MAX_CHARS = 0; } cout << setw( static_cast<int>( factor * MAX_CHARS ) ) << setfill( '#' ) << ""; cout << setw( MAX_CHARS - static_cast<int>( factor * MAX_CHARS ) ) << setfill( '·' ) << ""; cout << " " << setw( 6 ) << setfill( ' ' ) << setprecision( 2 ) << fixed << right << static_cast<float>( factor * 100 ) << "%"; cout << flush; cout << "\r"; } --- snap --- Leider ist "string_ptr" immer NULL. Wie kommt das? Viele Grüße Bastian
Hi, On Tue, 11 May 2004, Bastian Schern wrote:
Leider ist "string_ptr" immer NULL. Wie kommt das?
COLUMNS ist standardmaessig nicht exported. Und zwar deshalb weil es keinen Sinn macht, da sich waehrend des Programmlaufes die Groesse des Terminals ja aendern kann, Aenderungen im Environment aber nicht mehr vom Parent (der Shell, also dem Programm was diese Variable erst einmal setzt) vorgenommen werden koennen. D.h. entweder du machst ein "export COLUMNS LINES" vor Programmaufruf, oder implementierst es richtig: D.h. ueber Terminal ioctls (TIOCGWINSZ und struct winsize. Man bekommt das Signal SIGWINCH wenn sich die Terminalgroesse aendert). Koennte vielleicht overkill sein. Ciao, Micha.
Michael Matz schrieb:
Hi,
On Tue, 11 May 2004, Bastian Schern wrote:
Leider ist "string_ptr" immer NULL. Wie kommt das?
COLUMNS ist standardmaessig nicht exported. Und zwar deshalb weil es keinen Sinn macht, da sich waehrend des Programmlaufes die Groesse des Terminals ja aendern kann, Aenderungen im Environment aber nicht mehr vom Parent (der Shell, also dem Programm was diese Variable erst einmal setzt) vorgenommen werden koennen.
D.h. entweder du machst ein "export COLUMNS LINES" vor Programmaufruf, oder implementierst es richtig: D.h. ueber Terminal ioctls (TIOCGWINSZ und struct winsize. Man bekommt das Signal SIGWINCH wenn sich die Terminalgroesse aendert). Koennte vielleicht overkill sein.
Cool! Ich habe das jetzt so gemacht: // void progress( float factor ) {{{ void progress( float factor ) { static struct winsize winsz; ioctl( 0, TIOCGWINSZ, &winsz ); int MAX_CHARS = winsz.ws_col; if( MAX_CHARS > 8 ) MAX_CHARS -= 8; cout << setw( static_cast<int>( factor * MAX_CHARS ) ) << setfill( '#' ) << ""; cout << setw( MAX_CHARS - static_cast<int>( factor * MAX_CHARS ) ) << setfill( '·' ) << ""; cout << " " << setw( 6 ) << setfill( ' ' ) << setprecision( 2 ) << fixed << right << static_cast<float>( factor * 100 ) << "%"; cout << flush; cout << "\r"; } // }}} Signalverarbeitung benötige ich nicht, da ich die Funktion nur aufrufe, wenn sich etwas geändert hat. Vielen Dank Bastian
Hi, On Tue, 11 May 2004, Bastian Schern wrote:
Ich habe das jetzt so gemacht:
// void progress( float factor ) {{{ void progress( float factor ) { static struct winsize winsz; ioctl( 0, TIOCGWINSZ, &winsz ); int MAX_CHARS = winsz.ws_col;
Schon recht huebsch. Natuerlich fehlt Fehlerbehandlung. Wenn z.B. stdin gar kein Terminal ist (sondern z.B. ne pipe) geht obiges natuerlich schief. Also "if (ioctl (...) == 0) { MAX_CHARS = ... }" . Und siehe auch isatty(3) . Ciao, Micha.
Michael Matz schrieb:
Hi,
On Tue, 11 May 2004, Bastian Schern wrote:
Ich habe das jetzt so gemacht:
// void progress( float factor ) {{{ void progress( float factor ) { static struct winsize winsz; ioctl( 0, TIOCGWINSZ, &winsz ); int MAX_CHARS = winsz.ws_col;
Schon recht huebsch. Natuerlich fehlt Fehlerbehandlung. Wenn z.B. stdin gar kein Terminal ist (sondern z.B. ne pipe) geht obiges natuerlich schief. Also "if (ioctl (...) == 0) { MAX_CHARS = ... }" . Und siehe auch isatty(3) .
Vielen Dank für den Hinweis. Die Funktion sieht jetzt so aus: // void progress( float factor ) {{{ void progress( float factor ) { static struct winsize winsz; static int MAX_CHARS = 72; if( 0 == ioctl( 0, TIOCGWINSZ, &winsz ) ) { MAX_CHARS = winsz.ws_col; if( MAX_CHARS > 8 ) MAX_CHARS -= 8; } cout << setw( static_cast<int>( factor * MAX_CHARS ) ) << setfill( '#' ) << ""; cout << setw( MAX_CHARS - static_cast<int>( factor * MAX_CHARS ) ) << setfill( '·' ) << ""; cout << " " << setw( 6 ) << setfill( ' ' ) << setprecision( 2 ) << fixed << right << static_cast<float>( factor * 100 ) << "%"; cout << flush; cout << "\r"; } // }}} isatty( ... ) benötige ich dann nicht mehr, oder? Viele Grüße Bastian
participants (3)
-
Bastian Schern
-
Michael Matz
-
Philipp Thomas