gon1332 Δημοσ. 26 Ιανουαρίου 2014 Δημοσ. 26 Ιανουαρίου 2014 Η υλοποίηση της γνωστής εντολής clear του bash είναι απλή με ANSI EC: /* void clear(void) * * Clears the screen and moves the cursor in the top left corner. */ void clear(void){ printf("\033[2J\033[1;1H"); } 033 is the octal of ESC 2J is for cleaning the entire screen 1;1H moves the cursor to row 1 and column 1 Είναι όμως πλήρως cross platform; Πως αλλιώς θα μπορούσε να υλοποιηθεί ώστε να υποστηρίζεται ευρέως; Διάβασα πως οι περισσότερες γνωστές Consoles υποστηρίζουν ANSI Escape Codes. Μόνο και μόνο για εξάσκηση.. Πως δηλαδή θα ανιχνεύσω πόσες γραμμές υπάρχουν σε ένα παράθυρο terminal κάποια στιγμή; Πως θα μετακινήσω τον cursor σε κάποιο συγκεκριμένο σημείο; Ευχαριστώ.
migf1 Δημοσ. 26 Ιανουαρίου 2014 Δημοσ. 26 Ιανουαρίου 2014 Υπάρχει ένα μίνιμουμ συμβατό σετ από ANSI escape sequences. Ρίξε μια ματιά στη Wikipedia: http://en.wikipedia.org/wiki/ANSI_escape_code Επίσης... http://www.isthe.com/chongo/tech/comp/ansi_escapes.html (VT100): http://www.termsys.demon.co.uk/vtansi.htm Είχα ξεκινήσει μια μικρή cross-platform βιβλιοθήκη σε C++, αλλά την έχω παρατημένη. Για gotoXY() βλέπω είχα γράψει το παρακάτω... /* ------------------------------------------------------------ * Cross-platform function to move arbitrarily the console cursor. * * It works both on the Windows console and on terminals that * support ANSI escape sequences (that is on most Unix/Linux * terminals). */ bool cui_gotoxy( int x, int y ) { #if defined( CUI_OS_WINDOWS ) COORD temp; temp.X = x; temp.Y = y; if ( !SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp) ) { return false; } #elif defined( CUI_OS_UNIX ) || defined( CUI_OS_LINUX ) std::cout << "\033[" << (y+1) << ";" << (x+1) << "H"; std::cout.flush(); #endif return true; } Για ClearScreen ... /* ----------------------------------------------------- * Cross-platform function to clear the standard output. * * It works both on the Windows console and on terminals that * support ANSI escape sequences (that is on most Unix/Linux * terminals). */ bool cui_cls( void ) { #if defined( CUI_OS_WINDOWS ) // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682022(v=vs.85).aspx HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); COORD coordScreen = {0, 0}; /* home for the cursor */ DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwConSize; if ( INVALID_HANDLE_VALUE == hConsole) { return false; } // get the number of character cells in the current buffer if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) ) { return false; } dwConSize = csbi.dwSize.X * csbi.dwSize.Y; // fill the entire screen with blanks if ( !FillConsoleOutputCharacter( hConsole, /* Handle to console screen buffer */ (TCHAR) ' ', /* Character to write to the buffer */ dwConSize, /* Number of cells to write */ coordScreen, /* Coordinates of first cell */ &cCharsWritten ) /* Receive number of characters written */ ){ return false; } // get the current text attribute if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) ) { return false; } // set the buffer's attributes accordingly if ( !FillConsoleOutputAttribute( hConsole, /* Handle to console screen buffer */ csbi.wAttributes, /* Character attributes to use */ dwConSize, /* Number of cells to set attribute */ coordScreen, /* Coordinates of first cell */ &cCharsWritten ) /* Receive number of characters written */ ){ return false; } // put the cursor at its home coordinates if ( !SetConsoleCursorPosition(hConsole, coordScreen) ) { return false; } #elif defined( CUI_OS_UNIX ) || defined( CUI_OS_LINUX ) std::cout << "\033[2J" << "\033[H"; std::cout.flush(); #else /* On Unsupported Platforms */ for (int i=0; i < 24; i++) std::cout << std::endl; #endif return true; } Για διάβασμα του κέρσορα... /* ------------------------------------------------------------ * Get cursor's current x & y coords. */ inline bool cui_getxy( int &x, int &y ) { #if defined( CUI_OS_WINDOWS ) CONSOLE_SCREEN_BUFFER_INFO csbiInfo; HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE ); if ( INVALID_HANDLE_VALUE == hConsole ) { return false; } if ( !GetConsoleScreenBufferInfo(hConsole, &csbiInfo) ) { return false; } x = csbiInfo.dwCursorPosition.X; y = csbiInfo.dwCursorPosition.Y; #elif defined( CUI_OS_UNIX ) || defined( CUI_OS_LINUX ) char keycodes[18+1] = {'\0'}; int tempX, tempY; cui_echo_onoff( false ); cui_raw_onoff( true ); // query cursor coords std::cout << "\033[6n"; std::cout.flush(); read( fileno(stdin), keycodes, 18 ); keycodes[18] = '\0'; if ( 2 != sscanf(keycodes, "\033[%d;%dR", &tempY, &tempX) ) { return false; } x = tempX-1; y = tempY-1; cui_raw_onoff( false ); cui_echo_onoff( true ); #else /* On UnSupported Platforms */ return false; #endif return true; } /* ----------------------------------------------------- * */ static inline bool cui_raw_on( void ) { #if defined( CUI_OS_WINDOWS ) HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; if ( INVALID_HANDLE_VALUE == hConsole) { return false; } if ( !GetConsoleMode(hConsole, &mode) ) { return false; } if ( !SetConsoleMode(hConsole, mode & ~(ENABLE_LINE_INPUT)) ) { return false; } #elif defined( CUI_OS_UNIX ) || defined( CUI_OS_LINUX ) struct termios term; if ( 0 != tcgetattr(fileno(stdout), &term) ) { return false; } term.c_lflag &= ~(IXOFF); term.c_lflag &= ~(ICANON); // if ( 0 != tcsetattr(fileno(stdout), TCSAFLUSH, &term) ) { if ( 0 != tcsetattr(fileno(stdout), TCSANOW, &term) ) { return false; } #else /* on Unsupported Platforms */ return false; #endif return true; } /* ----------------------------------------------------- * */ static inline bool cui_raw_off( void ) { #if defined( CUI_OS_WINDOWS ) HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; if ( INVALID_HANDLE_VALUE == hConsole) { return false; } if ( !GetConsoleMode(hConsole, &mode) ) { return false; } if ( !SetConsoleMode(hConsole, mode | ENABLE_LINE_INPUT) ) { return false; } #elif defined( CUI_OS_UNIX ) || defined( CUI_OS_LINUX ) struct termios term; if ( 0 != tcgetattr(fileno(stdout), &term) ) { return false; } term.c_lflag |= IXOFF; term.c_lflag |= ICANON; // if ( 0 != tcsetattr(fileno(stdout), TCSAFLUSH, &term) ) { if ( 0 != tcsetattr(fileno(stdout), TCSANOW, &term) ) { return false; } #else /* on Unsupported Platforms */ return false; #endif return true; } κλπ, κλπ. Όρεξη να 'χεις και χρόνο... αν δεν τα θέλεις cross-platform είναι ακόμα πιο εύκολο.
gon1332 Δημοσ. 28 Ιανουαρίου 2014 Μέλος Δημοσ. 28 Ιανουαρίου 2014 Ευχαριστώ. Όντως θέλει λίγο χρόνο. Όταν αποκτήσω λίγο θα τους ρίξω μία ματιά.
migf1 Δημοσ. 29 Ιανουαρίου 2014 Δημοσ. 29 Ιανουαρίου 2014 Ευχαριστώ. Όντως θέλει λίγο χρόνο. Όταν αποκτήσω λίγο θα τους ρίξω μία ματιά. Βγάζοντας απ' έξω την native υποστήριξη για Windows, ουσιαστικά πρόκειται κατά κανόνα για απλά output ακολουθιών χαρακτήρων (ενίοτε με χρήση μιας-δυο μεταβλητών). Η δυσκολία προκύπτει όταν θες να κάνεις πιο advanced πράγματα, αλλά τότε είναι καλύτερα να χρησιμοποιήσεις απευθείας κάποια έτοιμη βιβλιοθήκη, όπως π.χ τις ncurses (posix), pdcurses (windows/X). Πάντως ακόμα και η κονσόλα των Windows μπορεί να γίνει ANSI codes aware, με τη βοήθεια π.χ. του ansicon. Το συγκεκριμένο το έχω δοκιμάσει με επιτυχία. Υπάρχουν και διάφορα console replacements για Windows που καταλαβαίνουν και ANSI Codes, με ναυαρχίδα υποθέτω το ConEmu (είναι πράγματι jaw dropper αυτό το πρόγραμμα).
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα