Question

J'ai découvert ce en utilisant printf rubis, mais il applique également à la printf de C.

Si vous incluez les codes d'échappement couleur ANSI dans une chaîne de sortie, il salit l'alignement.

Ruby:

ruby-1.9.2-head > printf "%20s\n%20s\n", "\033[32mGreen\033[0m", "Green"
      Green          # 6 spaces to the left of this one
               Green # correctly padded to 20 chars
 => nil

Le même ligne dans un programme C produit la même sortie.

Y at-il de toute façon à obtenir printf (ou autre chose) à la sortie align et ne pas ajouter des espaces pour les caractères non-imprimés?

Est-ce un bug, ou est-il une bonne raison?

Mise à jour: Depuis printf ne peut pas se fier aux données d'alignement quand il y a des codes ANSI et de grands caractères, est-il une meilleure façon pratique de faire la queue des données tabulaires de couleur dans la console en rubis

Était-ce utile?

La solution

Je suis en désaccord avec votre interprétation des « 9 espaces après le vert vert ». J'utilise Perl plutôt que Ruby, mais si j'utilise une modification de votre déclaration, l'impression d'un symbole de la conduite après la chaîne, je reçois:

perl -e 'printf "%20s|\n%20s|\n", "\033[32mGreen\033[0m", "Green";'
      Green|
               Green|

Cela me montre que la déclaration de 14 caractères printf() compté dans la chaîne, il préfixé 6 places pour produire 20 caractères alignés à droite. Cependant, le terminal avalé 9 de ces caractères, les interpréter comme des changements de couleur. Ainsi, la sortie est apparu 9 caractères plus courte que vous le voulais. Cependant, la printf() n'a pas imprimer 9 blancs après la première « verte ».


En ce qui concerne les meilleures pratiques pour la sortie alignée (avec colorisation), je pense que vous aurez besoin d'avoir chaque champ de taille et aligné entouré par un simple champs '% s de qui traitent de la colorisation:

printf "%s%20.20s%s|%s%-10d%s|%s%12.12s%s|\n",
       co_green, column_1_data, co_plain,
       co_blue,  column_2_data, co_plain,
       co_red,   column_3_data, co_plain;

Si, de toute évidence, les variables co_XXXX (constantes?) Contiennent les séquences d'échappement pour passer à la couleur du nom (et co_plain peut-être mieux comme co_black). S'il se avère que vous n'avez pas besoin colorisation sur un domaine, vous pouvez utiliser la chaîne vide à la place des variables co_XXXX (ou appeler co_empty).

Autres conseils

Il est pas un bug: il n'y a pas ruby ??moyen devrait savoir (au moins dans printf, ce serait une autre histoire pour quelque chose comme malédictions) que son stdout va un terminal qui comprend VT100 séquences d'échappement

.

Si vous n'êtes pas ajuster les couleurs d'arrière-plan, quelque chose comme cela pourrait être une meilleure idée:

GREEN = "\033[32m"
NORMAL = "\033[0m"
printf "%s%20s%s\n", GREEN, "Green", NORMAL

champ printf largeur spécificateurs ne sont pas utiles pour aligner des données tabulaires, des éléments d'interface, etc. Outre la question des caractères de contrôle que vous avez déjà découvert, il y a aussi sans chasse et caractères à double largeur de votre programme devra traiter si vous ne voulez pas les choses à limiter les codages de caractères hérités (que beaucoup d'utilisateurs considèrent déconseillés).

Si vous insistez sur l'utilisation printf cette façon, vous avez probablement besoin de faire quelque chose comme:

printf("%*s\n%*s\n", bytestopad("\033[32mGreen\033[0m", 20), "\033[32mGreen\033[0m", bytestopad("Green", 20), "Green");

bytestopad(s,n) est une fonction que vous écrivez qui calcule le nombre total d'octets sont nécessaires (chaîne, plus les espaces rembourrage) pour entraîner la s chaîne prenant des colonnes terminales de n. Cela impliquerait l'analyse syntaxique échappe et le traitement de caractères multi-octets et en utilisant une installation (comme la fonction wcwidth Posix) pour rechercher le nombre de colonnes du terminal chaque Takes. Notez l'utilisation de * en place d'un champ constant largeur dans la chaîne de format printf. Cela vous permet de passer un argument int à printf pour des largeurs de champ d'exécution variable.

Je séparer des séquences d'échappement de texte réel pour éviter toute la question.

# in Ruby
printf "%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green"

ou

/* In C */
printf("%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green");

Étant donné que les séquences d'échappement ANSI ne font pas partie de l'une ou Ruby C ne pense qu'ils ont besoin de traiter ces caractères spéciaux, et à juste titre.

Si vous allez faire beaucoup de choses de couleur du terminal, alors vous devriez regarder dans malédictions et ncurses qui fournissent des fonctions pour faire la couleur change qui travaillent pour différents types de terminaux. Ils offrent également des fonctionnalités beaucoup plus, comme les fenêtres en mode texte, touches de fonction, et parfois même l'interaction de la souris.

scroll top