View Full Version : [C] Output su una sola riga e key binding.
Salve a tutti.
Devo scrivere una shell unix per un progetto.
Fin quì ci siamo. Devo implementare un meccanismo di history dei comandi, e qui' nascono delle piccole perplessita'. Supponendo che voglia scorrere l'history con i tasti freccia, come faccio a "mappare" questi tasti di modo che richiamino delle mie funzioni che gestiscano questo meccanismo? Qui' si presenta un altro problema: come faccio a fare l'output di testo su una sola riga di terminale? (Per darvi un'idea, prendete una barra di scorrimento testuale che "scrive" sempre e solo su una sola riga, come quella di GNU wget, per esempio.)
Un grazie a tutti quelli che interverranno.
La cosa più semplice credo che sia quella di andare a lavorare direttamente in memoria video...anche se probabilmente questo ti fa perdere l'indipendenza dalla piattaforma hardware...
Altrimenti prova con la ncurses.h che dovrebbe avere la funzione move...e c'è anche il resto di quello che ti serve per l'I/O...
ilsensine
27-05-2003, 08:29
Per la "cattura" dei tasti speciali, come ti ho detto, devi usare stdin char-buffered e leggere un carattere alla volta (i caratteri speciali sono sequenze che iniziano con <esc>); qui ho dato qualche indicazione, le varianti sul tema sono numerose:
http://forum.hwupgrade.it/viewtopic.php?t=444081&postdays=0&postorder=asc&start=20
ilsensine
27-05-2003, 08:31
(Per darvi un'idea, prendete una barra di scorrimento testuale che "scrive" sempre e solo su una sola riga, come quella di GNU wget, per esempio.)
Se non ti serve molta flessibilità, puoi usare printf("...[/siz]")
Se devi fare le pizzette, #include <ncurses.h> e auguri :D
Se non ti serve molta flessibilità, puoi usare printf("...")
Già...bella idea ;)
Dannate ncurses... Non le POSSO usare!!! :D :D :cry:
Comunque l'argomento della cattura dei tasti speciali, guarda caso, è proprio quello dove sono arrivato fino ad adesso. Giusta coincidenza. :)
printf(...\r); ?? ?? ?? Adesso provo. Esistono milioni di modificatori di formato per la printf() sia standard che estensioni, ma questo non l'ho mai visto e sentito :muro:
Io alternativamente avevo pensato di mappare in memoria il typeahead buffer del terminale e scriverci poi con sprintf(). Funzionerebbe secondo te? Ho poco tempo, ecco perchè faccio queste domande idiote. Altrimenti proverei direttamente da me :(
Inoltre ho provato a leggere i sorgenti della shell Bash come mi avevi consigliato, ma la Bash fa l'I/O a carattere sul terminale con le librerie readline, quindi nada.
EDIT: E gestisce l'history con la libreria GNU History, quindi doppio nada ;)
Originally posted by "mjordan"
printf(...\r); ?? ?? ?? Adesso provo. Esistono milioni di modificatori di formato per la printf() sia standard che estensioni, ma questo non l'ho mai visto e sentito :muro:
Non è un modificatore... E' il carattere di ritorno carrello...
printf("Pippo\rciao"); dovrebbe stampare "ciaoo"...
Originally posted by "cionci"
La cosa più semplice credo che sia quella di andare a lavorare direttamente in memoria video...anche se probabilmente questo ti fa perdere l'indipendenza dalla piattaforma hardware...
Tu ti stai riferendo ad una sorta di memory mapped I/O giusto?
Ci avevo pensato anch'io, ma per fare una cosa del genere dovrei sapere esattamente lo starting point del buffer che usa il terminale (e questo non lo posso sapere, in quanto questo buffer è un tipo opaco), inoltre dovrei avere l'offset finale, altro dato che non conosco, in quanto questo buffer a seconda dell'implementazione, viene riallocato continuamente in modo dinamico).
ilsensine
27-05-2003, 09:51
Originally posted by "mjordan"
Tu ti stai riferendo ad una sorta di memory mapped I/O giusto?
Ci avevo pensato anch'io
Scordatelo.
Il tuo terminale può essere:
- una console fisica
- un pts (pseudoterminale)
- ...un socket :D
Usa le librerie standard, e vedrai che il tuo programma funzionerà in ogni situazione.
Originally posted by "ilsensine"
Scordatelo.
Il tuo terminale può essere:
- una console fisica
- un pts (pseudoterminale)
- ...un socket :D
Vero...non ci avevo pensato...
Originally posted by "ilsensine"
Scordatelo.
Il tuo terminale può essere:
- una console fisica
- un pts (pseudoterminale)
- ...un socket :D
Usa le librerie standard, e vedrai che il tuo programma funzionerà in ogni situazione.
Difatti l'avevo scartata come soluzione.
Originally posted by "cionci"
Non è un modificatore... E' il carattere di ritorno carrello...
printf("Pippo\rciao"); dovrebbe stampare "ciaoo"...
Quindi un modificatore di formato.
%d , %c , %l , %x modificatori di conversione
\n, \r, \t modificatori di formato
ilsensine
27-05-2003, 10:30
Non è un modificatore, è un carattere come gli altri.
\n = 0x0d = vai a capo su una nuova linea
\r = 0x0a = vai a capo della linea corrente
Originally posted by "ilsensine"
Non è un modificatore, è un carattere come gli altri.
\n = 0x0d = vai a capo su una nuova linea
\r = 0x0a = vai a capo della linea corrente
Ok ok. E' possibile una volta tanto mettere da parte le polemiche inutili? :D
Facciamo così. Ci si risente + tardi. Io intanto vedo di dominare l'argomento dell'interfaccia a terminale, che non mi sembra molto complessa, anche se sei stato abbastanza chiaro nello spezzone di codice che mi hai postato prima.
Magri non è che sei così gentile da postarmi intanto un pezzetto di codice che quando premi un tasto freccia scrive a schermo "Forza Milan iil 28 vinceremo?", tanto per unire l'utile al dilettevole :sofico: :sofico: :sofico:
O sei romanista/juventino??? :D
ilsensine
27-05-2003, 11:55
Oltre che a darti questo, rimane che ti faccio io il programma ;)
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <ctype.h>
struct termios oldtty;
void init_stdin() {
struct termios tty;
int idev = fileno(stdin);
tcgetattr(idev, &tty);
oldtty = tty;
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr(idev, TCSAFLUSH, &tty);
}
int key_queue() {
int cnt;
ioctl(fileno(stdin), FIONREAD, &cnt);
return cnt;
}
int do_getch() {
unsigned char ch;
read(fileno(stdin), &ch, 1);
return ch;
}
int main() {
int q;
int qi;
unsigned char c = '\0';
init_stdin();
fprintf(stderr, "Premi i tasti che vuoi testare; 'q' per finire.\n");
while(c!='q') {
q = key_queue();
if(q<=0) {
usleep(25000);
continue;
}
fprintf(stderr, "Il tasto che hai premuto corrisponde a una sequenza di %d caratteri\n", q);
fprintf(stderr, "Codici ascii:\n");
qi = q;
while(q--)
fprintf(stderr, "\t0x%02x", (unsigned) (c=do_getch()));
fprintf(stderr, "\n");
if(qi!=1) c='\0';
}
tcsetattr(fileno(stdin), TCSAFLUSH, &oldtty);
return 0;
}
Originally posted by "ilsensine"
Oltre che a darti questo, rimane che ti faccio io il programma ;)
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <ctype.h>
struct termios oldtty;
void init_stdin() {
struct termios tty;
int idev = fileno(stdin);
tcgetattr(idev, &tty);
oldtty = tty;
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr(idev, TCSAFLUSH, &tty);
}
int key_queue() {
int cnt;
ioctl(fileno(stdin), FIONREAD, &cnt);
return cnt;
}
int do_getch() {
unsigned char ch;
read(fileno(stdin), &ch, 1);
return ch;
}
int main() {
int q;
int qi;
unsigned char c = '\0';
init_stdin();
fprintf(stderr, "Premi i tasti che vuoi testare; 'q' per finire.\n");
while(c!='q') {
q = key_queue();
if(q<=0) {
usleep(25000);
continue;
}
fprintf(stderr, "Il tasto che hai premuto corrisponde a una sequenza di %d caratteri\n", q);
fprintf(stderr, "Codici ascii:\n");
qi = q;
while(q--)
fprintf(stderr, "\t0x%02x", (unsigned) (c=do_getch()));
fprintf(stderr, "\n");
if(qi!=1) c='\0';
}
tcsetattr(fileno(stdin), TCSAFLUSH, &oldtty);
return 0;
}
Grazie di cuore. Ma grazie veramente con la 'G' maiuscola!
Oggi concludo l'argomento, studio questo spezzone e ti faccio sapere come va. Quando finisco il progetto, posto l'intero codice sorgente della shell Unix terminata. Mi farebbe piacere se tu la vedessi poi e mi dessi un opinione sincera su cosa ne pensi.
A presto e grazie ancora a tutti queli che si sono infilati in questo thread (cioè ilsensine e cionci) :)
L'ho appena eseguito. E' fantastico. Non vedo l'ora di finire questo argomento :D :D
Vado a studiare!!! :D :D :D
Posso farti una domanda?? Ma sei "nell'ambito" accademico?
EDIT: No perchè mi era venuta in mente una cosa :D :D :D
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.