Frage

Ich entdeckte diese während Rubin printf verwenden, aber es gilt auch für C des printf.

Wenn Sie ANSI-Farben-Escape-Codes in einem Ausgabe-String enthalten, vermasselt es die Ausrichtung auf.

Rubin:

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

Die gleiche Zeile in einem C-Programm erzeugt die gleiche Ausgabe.

Gibt es trotzdem printf zu bekommen (oder etwas anderes) auszurichten Ausgang und nicht fügen Räume für nicht gedruckte Zeichen?

Ist das ein Fehler ist, oder gibt es einen guten Grund dafür?

Update: Da printf kann nicht auf zu align Daten herangezogen werden, wenn es ANSI ist Codes und breite Zeichen, gibt es eine bewährte Methode, Art und Weise der Schlange farbige Tabellendaten in der Konsole in Ruby

War es hilfreich?

Lösung

Ich bin nicht einverstanden mit der Charakterisierung von ‚9 Leerzeichen nach dem grünen Green‘. Ich benutze Perl statt Rubin, aber wenn ich eine Änderung Ihrer Anweisung verwenden, Drucken eines Pipe-Symbol nach der Zeichenfolge, die ich erhalten:

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

Das zeigt mir, dass die printf() Anweisung 14 Zeichen in der Zeichenkette gezählt, so dass es 6 Räume voran 20 Zeichen zu erzeugen, rechtsbündig. Allerdings geschluckt der Anschluß 9 dieser Zeichen, sie als Farbänderungen zu interpretieren. So erschien die Ausgabe 9 Zeichen kürzer als Sie es wollten. Allerdings druckt das printf() nicht 9 Rohlinge nach dem ersten ‚Green‘.


Im Hinblick auf die Best Practices für die ausgerichteten Ausgang (mit -farbauftrag), ich glaube, Sie werden jede Größe-and-ausgerichteten Feld durch einfache ‚% s‘ Felder, die befassen sich mit der -farbauftrag umgeben haben müssen:

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;

Dabei gilt offensichtlich die co_XXXX Variablen (Konstanten?), Um die Escape-Sequenzen Schalter auf die benannte Farbe enthält (und co_plain vielleicht besser als co_black). Sollte sich herausstellen, dass Sie -farbauftrag auf einem Feld nicht brauchen, können Sie die leere Zeichenfolge anstelle der co_XXXX Variablen (oder nennen es co_empty).

Andere Tipps

Es ist kein Fehler: Es gibt keine Möglichkeit, Rubin wissen sollte (zumindest innerhalb printf, wäre es eine andere Geschichte für so etwas wie Flüche sein), dass sein stdout zu einem Terminal wird die VT100-Escape-Sequenzen versteht

.

Wenn Sie nicht Hintergrundfarben eingestellt, so etwas wie dies könnte eine bessere Idee:

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

printf Feldbreite Bezeich ist nicht nützlich für tabellarische Daten Ausrichten Interface-Elemente, usw. Abgesehen von der Frage der Steuerzeichen, die Sie bereits entdeckt haben, gibt es auch Ohne Zwischenraum und Zeichen doppelte Breite, die Ihr Programm mit zu tun hat wenn Sie nicht zu begrenzen Dinge Legacy Zeichenkodierungen wollen (was viele Benutzer betrachten veraltet).

Wenn Sie sich mit printf diese Art und Weise bestehen, müssen Sie wahrscheinlich etwas tun:

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

wo bytestopad(s,n) ist eine Funktion, die Sie, dass berechnet schreiben, wie viele Bytes insgesamt benötigt werden (Zeichenfolge plus Polsterung Leerzeichen) führt in dem String s nimmt n Terminal Spalten auf. Dies würde Fluchten und Verarbeitung von Mehrbytezeichen und mit einer Einrichtung (wie die POSIX wcwidth Funktion) beinhalten Parsen Spalten nachzuschlagen, wie viele Terminal jeder nimmt. Beachten Sie die Verwendung von * anstelle einer konstanten Feldbreite in dem printf Format-String. Auf diese Weise können Sie ein int Argument printf für Runtime-variablen Feldbreiten zu übergeben.

Ich würde keine Escape-Sequenzen von den tatsächlichen Text trennen, die ganze Angelegenheit zu vermeiden.

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

oder

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

Da ANSI-Escape-Sequenzen sind nicht Teil entweder Rubin oder C weder denkt, dass sie diese Zeichen eine besondere Behandlung benötigen, und das zu Recht.

Wenn Sie tun eine Menge Terminal Farbe Sachen zu gehen, dann sollten Sie Flüche und ncurses Blick in die Funktionen bieten Farbe zu tun ändert, dass die Arbeit für viele verschiedene Arten von Terminals. Sie bieten auch viel viel mehr Funktionalität, wie textbasierte Fenster, Funktionstasten, und manchmal sogar Maus Interaktion.

Hier ist eine Lösung, die ich mit vor kurzem kam. Auf diese Weise können Sie color("my string", :red) in einer printf Anweisung verwenden. Ich mag die gleiche Formatierung Zeichenfolge mit für Kopf- und die Daten - DRY. Dies macht das möglich. I Verwenden Sie auch die rainbow gem die Farbcodes zu erzeugen; es ist nicht perfekt, aber erhält die Arbeit erledigt. Der CPAD Hash enthält zwei Werte für jede Farbe, nach links und rechts padding entsprechen. Natürlich sollte diese Lösung erweitert werden, um andere Farben und Modifikatoren zu erleichtern wie fett und unterstrichen.

CPAD = {
  :default => [0, 2],
  :green   => [0, 3],
  :yellow  => [0, 2],
  :red     => [0, 1],
}

def color(text, color)
  "%*s%s%*s" % [CPAD[color][0], '', text.color(color), CPAD[color][1], '']
end

Beispiel:

puts "%-10s   %-10s   %-10s   %-10s" % [
  color('apple',  :red),
  color('pear',   :green),
  color('banana', :yellow)
  color('kiwi',   :default)
]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top