Ecrire un" vrai " programme de terminal interactif comme vim, htop, ... en C/C++ sans ncurses
Non, je ne veux pas utiliser ncurses, parce que je veux apprendre comment les le terminal fonctionne et avoir du plaisir programmation sur mon propre. :) Il n'a pas doit être portable, il doit fonctionner uniquement sur les émulateurs de terminaux linux xterm.
ce que je veux faire, c'est programmer une application de terminal interactive comme htop et vim are. Ce que je veux dire n'est pas la sortie de caractères qui ressemblent à des boîtes ou des couleurs de réglage, c'est trivial; aussi pour faire le contenu adapté à la taille de la fenêtre. Ce dont j'ai besoin est
comment obtenir interactions avec la souris comme cliquer sur un caractère et faire défiler la roue de la souris (quand la souris est à un caractère spécifique) pour mettre en place le défilement [EDIT: dans un émulateur de terminal de cours] et
complètement sauvegarder et restaurer la sortie du processus parent et séparer mon impression de sa sortie, Donc après avoir quitté mon demande rien, mais la commande je suis entré dans la coque devrait être là, comme lors de l'exécution de htop et l'abandon de nouveau: rien n'est visible à partir de cette application plus.
je ne veux vraiment pas utiliser ncurses. Mais bien sûr, si vous savez quelle partie de ncurses est responsable de ces tâches, vous êtes les bienvenus pour me dire où dans le code source je peux le trouver, je vais l'étudier.
3 réponses
je suis un peu confus. Vous parlez d'une "application terminale"", comme vim; les applications de terminaux n'ont pas d'événements de souris, et ne répondre à la souris.
si vous parlez de véritables applications de terminal, qui fonctionnent dans un
xterm
, l'important de penser à noter est que beaucoup de la portabilité
les problèmes concernent le terminal, et non L'OS. Le terminal est contrôlé
en envoyant différentes séquences d'évasion. Ceux qui font ce qui dépend du terminal; les codes de fuite ANSI sont maintenant assez répandue, cependant, voir http://en.wikipedia.org/wiki/ANSI_escape_code. Ceux-ci sont généralement compris par xterm
, par exemple.
vous devrez peut-être produire une séquence supplémentaire au début et à la fin pour entrer et quitter le mode "plein écran"; Ceci est nécessaire pour xterm
.
enfin, vous devrez faire quelque chose de spécial au niveau des entrées/sorties pour vous assurer que votre pilote de sortie n'ajoute pas de caractères (par exemple, convertir un simple LF en CRLF), et s'assurer que les entrées ne résonnent pas, qu'elles sont transparentes et qu'elles reviennent immédiatement. Sous Linux, ceci est fait en utilisant ioctl
. (Encore une fois, n'oubliez pas de le Restaurer lorsque vous aurez terminé.)
pour manipuler le terminal vous devez utiliser séquences de contrôle. Malheureusement, ces codes dépendent du terminal que vous utilisez. C'est pourquoi terminfo
(précédemment termcap
) existe en premier lieu.
Vous ne dites pas si vous souhaitez utiliser terminfo ou pas. Donc:
- si vous utilisez terminfo, il vous donnera la séquence de contrôle correcte pour chaque action prise en charge par votre terminal.
- si vous ne voulez pas utiliser terminfo... Eh bien, vous devez coder manuellement chaque action dans chaque type de terminal que vous voulez prendre en charge.
comme vous le voulez à des fins d'apprentissage, je vais développer dans la seconde.
Vous pouvez découvrir le type de terminal que vous utilisez à partir de la variable d'environnement $TERM
. Sous linux les plus habituelles sont xterm
pour les émulateurs de terminaux (XTerm, gnome-terminal, konsole), et linux
pour les terminaux virtuels (lorsque X n'est pas en cours d'exécution).
Vous pouvez découvrez facilement les séquences de contrôle avec la commande tput
. Mais comme tput
impressions sur la console, ils s'appliquent immédiatement, donc si vous voulez vraiment les voir, utilisez:
$ TERM=xterm tput clear | hd
00000000 1b 5b 48 1b 5b 32 4a |.[H.[2J|
$ TERM=linux tput clear | hd
00000000 1b 5b 48 1b 5b 4a |.[H.[J|
Qui est, pour effacer l'écran dans un xterm
vous avez de sortie ESC [ H ESC [ 2J
dans un xterm, mais ESC [ H ESC [ J
dans un terminal linux.
au sujet des commandes particulières que vous demandez, vous devriez lire attentivement man 5 terminfo
. Il y a beaucoup de renseignements.
bien que ce soit une question un peu vieille, j'ai pensé que je devrais partager un exemple court de la façon de le faire sans utiliser ncurses, il n'est pas difficile, mais je suis sûr qu'il ne sera pas aussi portable.
ce code positionne stdin en mode brut, passe à un écran tampon alternatif (qui sauve l'état du terminal avant de le lancer), permet de suivre la souris et d'imprimer le bouton et les coordonnées lorsque l'utilisateur clique quelque part. Après avoir cessé de fumer avec Ctrl+ C la le programme inverse la configuration du terminal.
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
int main (void)
{
unsigned char buff [6];
unsigned int x, y, btn;
struct termios original, raw;
// Save original serial communication configuration for stdin
tcgetattr( STDIN_FILENO, &original);
// Put stdin in raw mode so keys get through directly without
// requiring pressing enter.
cfmakeraw (&raw);
tcsetattr (STDIN_FILENO, TCSANOW, &raw);
// Switch to the alternate buffer screen
write (STDOUT_FILENO, "\e[?47h", 6);
// Enable mouse tracking
write (STDOUT_FILENO, "\e[?9h", 5);
while (1) {
read (STDIN_FILENO, &buff, 1);
if (buff[0] == 3) {
// User pressd Ctr+C
break;
} else if (buff[0] == '\x1B') {
// We assume all escape sequences received
// are mouse coordinates
read (STDIN_FILENO, &buff, 5);
btn = buff[2] - 32;
x = buff[3] - 32;
y = buff[4] - 32;
printf ("button:%u\n\rx:%u\n\ry:%u\n\n\r", btn, x, y);
}
}
// Revert the terminal back to its original state
write (STDOUT_FILENO, "\e[?9l", 5);
write (STDOUT_FILENO, "\e[?47l", 6);
tcsetattr (STDIN_FILENO, TCSANOW, &original);
return 0;
}
Note: cela ne fonctionnera pas correctement pour les terminaux qui ont plus de 255 colonnes.
Les meilleures références pour les séquences d'échappement que j'ai trouvé sont et .