StyledStrings

Note

Die API für StyledStrings und AnnotatedStrings wird als experimentell betrachtet und kann sich zwischen den Julia-Versionen ändern.

Styling

Beim Arbeiten mit Zeichenfolgen erscheinen Formatierung und Stil oft als sekundäre Anliegen.

Zum Beispiel, wenn Sie in ein Terminal drucken, möchten Sie möglicherweise ANSI escape sequences in die Ausgabe streuen. Beim Ausgeben von HTML-Stil-Konstrukten (<span style="...">, usw.) dient dies einem ähnlichen Zweck, und so weiter. Es ist möglich, die rohen Stil-Konstrukte einfach in den String neben dem Inhalt selbst einzufügen, aber es wird schnell offensichtlich, dass dies nicht gut geeignet ist für anything but the most basic use cases. Nicht alle Terminals unterstützen die gleichen ANSI-Codes, die Stil-Konstrukte müssen mühsam entfernt werden, wenn die Breite bereits gestylter Inhalte berechnet wird, und das ist noch bevor Sie sich mit der Handhabung mehrerer Ausgabeformate befassen.

Statt dieses Kopfzerbrechen weit verbreitet downstream zu lassen, wird es direkt angegangen durch die Einführung eines speziellen String-Typs (AnnotatedString). Dieser String-Typ umschließt jeden anderen AbstractString Typ und ermöglicht es, Formatierungsinformationen auf Bereiche anzuwenden (z.B. sind die Zeichen 1 bis 7 fett und rot).

Regionen eines Strings werden gestylt, indem Faces (denken Sie an "Schriftart") auf sie angewendet werden — eine Struktur, die Stylinginformationen enthält. Zur Vereinfachung können Schriftarten im globalen Schriftartenwörterbuch (z. B. shadow) einfach benannt werden, anstatt die 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 direkt anzugeben.

Neben diesen Fähigkeiten bieten wir auch eine bequeme Möglichkeit zum Erstellen von AnnotatedString, die in Styled String Literals detailliert beschrieben ist.

julia> using StyledStrings
julia> styled"{yellow:hello} {blue:there}""hello there"

Annotated Strings

Es ist manchmal nützlich, Metadaten zu Regionen eines Strings zu halten. Ein AnnotatedString umschließt einen anderen String und ermöglicht es, Regionen davon mit beschrifteten Werten (:label => value) zu annotieren. Alle generischen String-Operationen werden auf den zugrunde liegenden String angewendet. Wenn möglich, werden jedoch Stilinformationen beibehalten. Das bedeutet, dass Sie einen 4d61726b646f776e2e436f64652822222c2022416e6e6f7461746564537472696e672229_4072656620426173652e416e6e6f7461746564537472696e67 manipulieren können — indem Sie Teilstrings entnehmen, sie auffüllen, sie mit anderen Strings verketten — und die Metadatenannotationen werden "mitkommen".

Dieser Stringtyp ist grundlegend für die StyledStrings stdlib, die :face-beschriftete Annotationen verwendet, um Stilinformationen zu halten.

Beim Verketten von AnnotatedString achte darauf, annotatedstring anstelle von string zu verwenden, wenn du die String-Anmerkungen beibehalten möchtest.

julia> str = AnnotatedString("hello there", [(1:5, :word, :greeting), (7:11, :label, 1)])
"hello there"

julia> length(str)
11

julia> lpad(str, 14)
"   hello there"

julia> typeof(lpad(str, 7))
AnnotatedString{String}

julia> str2 = AnnotatedString(" julia", [(2:6, :face, :magenta)])
" julia"

julia> annotatedstring(str, str2)
"hello there julia"

julia> str * str2 == annotatedstring(str, str2) # *-concatenation works
true

Die Anmerkungen eines AnnotatedString können über die Funktionen annotations und annotate! zugegriffen und geändert werden.

Styling via AnnotatedStrings

Faces

The Face type

Ein Face spezifiziert Details einer Schriftart, in der Text gesetzt werden kann. Es umfasst eine Reihe grundlegender Attribute, die sich gut auf verschiedene Formate verallgemeinern lassen, nämlich:

  • Schriftart
  • höhe
  • gewicht
  • schräg
  • Vordergrund
  • Hintergrund
  • unterstreichen
  • Durchgestrichen
  • invers
  • erben

Für Details zu den spezifischen Formen, die diese Attribute annehmen, siehe die Face Docstring, aber von besonderem Interesse ist inherit, da es Ihnen ermöglicht, Attribute von anderen 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365s zu erben.

The global faces dictionary

Um das Verweisen auf bestimmte Stile bequemer zu gestalten, gibt es ein globales Dict{Symbol, Face}, das es ermöglicht, Face einfach nur beim Namen zu nennen. Pakete können über die Funktion addface! Gesichter zu diesem Wörterbuch hinzufügen, und die geladenen Gesichter können leicht customized werden.

Appropriate face naming

Jedes Paket, das neue Gesichter registriert, sollte sicherstellen, dass sie mit dem Paketnamen vorangestellt sind, d.h. dem Format mypackage_myface folgen. Dies ist wichtig für Vorhersehbarkeit und um Namenskonflikte zu vermeiden.

Darüber hinaus sollten Pakete darauf achten, semantische Gesichter (wie code) anstelle von direkten Farben und Stilen (wie cyan) zu verwenden (und einzuführen). Dies ist in vielerlei Hinsicht hilfreich, von der Klarheit der Absicht in der Verwendung über die Unterstützung der Komponierbarkeit bis hin zur intuitiveren Benutzeranpassung.

Es gibt zwei Ausnahmen von der Paket-Präfixregel:

  • die Menge der grundlegenden Gesichter, die Teil des Standardwerts des Gesichter-Wörterbuchs sind
  • Gesichter, die von Julias eigener Standardbibliothek eingeführt wurden, nämlich JuliaSyntaxHighlighting

Basic faces

Basisgesichter sollen eine allgemeine Idee darstellen, die weit verbreitet anwendbar ist.

Für die Einstellung von Text mit einem bestimmten Attribut haben wir die Schriftarten fett, leicht, kursiv, unterstrichen, durchgestrichen und inverse.

Es gibt auch benannte Farben für die 16 Terminalfarben: schwarz, rot, grün, gelb, blau, magenta, cyan, weiß, hellschwarz/grau, hellrot, hellgrün, hellblau, hellmagenta, hellcyan und hellweiß.

Für schattierten Text (d.h. gedimmt, aber vorhanden) gibt es das shadow-Gesicht. Um einen ausgewählten Bereich anzuzeigen, gibt es das region-Gesicht. Ähnlich für Betonung und Hervorhebung sind die emphasis- und highlight-Gesichter definiert. Es gibt auch code für codeähnlichen Text.

Um die Schwere von Nachrichten visuell anzuzeigen, sind die Gesichter error, warning, success, info, note und tip definiert.

Customisation of faces (Faces.toml)

Es ist gut, dass die Namen in dem globalen Gesichtswörterbuch anpassbar sind. Themen und Ästhetik sind schön, und es ist auch aus Gründen der Barrierefreiheit wichtig. Eine TOML-Datei kann in eine Liste von Face Spezifikationen geparst werden, die mit dem bereits vorhandenen Eintrag im Gesichtswörterbuch zusammengeführt werden.

Ein Face wird in TOML wie folgt dargestellt:

[facename]
attribute = "value"
...

[package.facename]
attribute = "value"

Wenn zum Beispiel das shadow-Gesicht zu schwer zu lesen ist, kann es so heller gemacht werden:

[shadow]
foreground = "white"

Bei der Initialisierung wird die Datei config/faces.toml im ersten Julia-Depot (normalerweise ~/.julia) geladen.

Applying faces to a AnnotatedString

Nach Konvention enthalten die :face-Attribute eines AnnotatedString Informationen über die Faces, die derzeit gelten. Dies kann in mehreren Formen angegeben werden, als ein einzelnes Symbol, das einen 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 im globalen Gesichtswörterbuch benennt, ein 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 selbst oder ein Vektor von beidem.

Die show(::IO, ::MIME"text/plain", ::AnnotatedString) und show(::IO, ::MIME"text/html", ::AnnotatedString) Methoden betrachten beide die :face Attribute und fügen sie zusammen, um die gesamte Formatierung zu bestimmen.

Wir können :face-Attribute während der Konstruktion zu einem AnnotatedString hinzufügen, sie anschließend zur Eigenschaftenliste hinzufügen oder die praktische Styled String literals verwenden.

julia> str1 = AnnotatedString("blue text", [(1:9, :face, :blue)])"blue text"
julia> str2 = styled"{blue:blue text}""blue text"
julia> str1 == str2true
julia> sprint(print, str1, context = :color => true)"\e[34mblue text\e[39m"
julia> sprint(show, MIME("text/html"), str1, context = :color => true)"<span style=\"color: #195eb3\">blue text</span>"

Styled String Literals

Um den Bau von AnnotatedString zu erleichtern, mit Face, ermöglicht der styled"..." formatierte String-Literal, dass der Inhalt und die Attribute zusammen über eine benutzerdefinierte Grammatik leicht ausgedrückt werden können.

Innerhalb eines styled"..." Literals werden geschweifte Klammern als Sonderzeichen betrachtet und müssen in der normalen Verwendung escaped werden (\{, \}). Dies ermöglicht es, sie zu verwenden, um Annotationen mit (verschachtelbaren) {annotations...:text} Konstrukten auszudrücken.

Die annotations...-Komponente ist eine durch Kommas getrennte Liste von drei Arten von Annotationen.

  • Gesichtsnamen
  • Inline Gesicht Ausdrücke (key=val,...)
  • key=value Paare

Interpolation ist überall möglich, außer bei Inline-Gesichtsschlüsseln.

Für weitere Informationen zur Grammatik siehe die erweiterte Hilfe des styled"..." Docstring.

Als Beispiel können wir die oben genannten integrierten Gesichter wie folgt demonstrieren:

julia> println(styled"
The basic font-style attributes are {bold:bold}, {light:light}, {italic:italic},
{underline:underline}, and {strikethrough:strikethrough}.

In terms of color, we have named faces for the 16 standard terminal colors:
 {black:■} {red:■} {green:■} {yellow:■} {blue:■} {magenta:■} {cyan:■} {white:■}
 {bright_black:■} {bright_red:■} {bright_green:■} {bright_yellow:■} {bright_blue:■} {bright_magenta:■} {bright_cyan:■} {bright_white:■}

Since {code:bright_black} is effectively grey, we define two aliases for it:
{code:grey} and {code:gray} to allow for regional spelling differences.

To flip the foreground and background colors of some text, you can use the
{code:inverse} face, for example: {magenta:some {inverse:inverse} text}.

The intent-based basic faces are {shadow:shadow} (for dim but visible text),
{region:region} for selections, {emphasis:emphasis}, and {highlight:highlight}.
As above, {code:code} is used for code-like text.

Lastly, we have the 'message severity' faces: {error:error}, {warning:warning},
{success:success}, {info:info}, {note:note}, and {tip:tip}.

Remember that all these faces (and any user or package-defined ones) can
arbitrarily nest and overlap, {region,tip:like {bold,italic:so}}.")
 The basic font-style attributes are bold, light, italic,
 underline, and strikethrough.

 In terms of color, we have named faces for the 16 standard terminal colors:
         
         

 Since bright_black is effectively grey, we define two aliases for it:
 grey and gray to allow for regional spelling differences.

 To flip the foreground and background colors of some text, you can use the
 inverse face, for example: some inverse text.

 The intent-based basic faces are shadow (for dim but visible text),
 region for selections, emphasis, and highlight.
 As above, code is used for code-like text.

 Lastly, we have the 'message severity' faces: error, warning,
 success, info, note, and tip.

 Remember that all these faces (and any user or package-defined ones) can
 arbitrarily nest and overlap, like so.

API reference

Styling and Faces

StyledStrings.StyledMarkup.@styled_strMacro
@styled_str -> AnnotatedString

Konstruiere einen stilisierten String. Innerhalb des Strings wenden {<specs>:<content>}-Strukturen die Formatierung auf <content> an, gemäß der Liste von durch Kommas getrennten Spezifikationen <specs>. Jede Spezifikation kann entweder in Form eines Schriftgesichtsnamens, einer Inline-Schriftgesichtsspezifikation oder eines key=value-Paars vorliegen. Der Wert muss in {...} eingeschlossen werden, wenn er eines der Zeichen ,=:{} enthält.

Die String-Interpolation mit $ funktioniert auf die gleiche Weise wie bei regulären Strings, außer dass Anführungszeichen escaped werden müssen. Schriftgesichter, Schlüssel und Werte können ebenfalls mit $ interpoliert werden.

Beispiel

styled"The {bold:{italic:quick} {(foreground=#cd853f):brown} fox} jumped over the {link={https://en.wikipedia.org/wiki/Laziness}:lazy} dog"

Erweiterte Hilfe

Dieses Makro kann durch die folgende EBNF-Grammatik beschrieben werden:

styledstring = { styled | interpolated | escaped | plain } ;

specialchar = '{' | '}' | '$' | '\"' ;
anychar = [\u0-\u1fffff] ;
plain = { anychar - specialchar } ;
escaped = '\\', specialchar ;

interpolated = '$', ? expr ? | '$(', ? expr ?, ')' ;

styled = '{', ws, annotations, ':', content, '}' ;
content = { interpolated | plain | escaped | styled } ;
annotations = annotation | annotations, ws, ',', ws, annotation ;
annotation = face | inlineface | keyvalue ;
ws = { ' ' | '\t' | '\n' } ; (* whitespace *)

face = facename | interpolated ;
facename = [A-Za-z0-9_]+ ;

inlineface = '(', ws, [ faceprop ], { ws, ',', faceprop }, ws, ')' ;
faceprop = [a-z]+, ws, '=', ws, ( [^,)]+ | interpolated) ;

keyvalue = key, ws, '=', ws, value ;
key = ( [^\0${}=,:], [^\0=,:]* ) | interpolated ;
value = simplevalue | curlybraced | interpolated ;
curlybraced = '{' { escaped | plain } '}' ;
simplevalue = [^${},:], [^,:]* ;

Eine zusätzliche Bestimmung, die nicht in der obigen Grammatik kodiert ist, ist, dass plain eine gültige Eingabe für unescape_string sein sollte, wobei specialchar beibehalten wird.

Die obige Grammatik für inlineface ist vereinfacht, da die tatsächliche Implementierung etwas ausgefeilter ist. Das vollständige Verhalten ist unten angegeben.

faceprop = ( 'face', ws, '=', ws, ( ? string ? | interpolated ) ) |
           ( 'height', ws, '=', ws, ( ? number ? | interpolated ) ) |
           ( 'weight', ws, '=', ws, ( symbol | interpolated ) ) |
           ( 'slant', ws, '=', ws, ( symbol | interpolated ) ) |
           ( ( 'foreground' | 'fg' | 'background' | 'bg' ),
               ws, '=', ws, ( simplecolor | interpolated ) ) |
           ( 'underline', ws, '=', ws, ( underline | interpolated ) ) |
           ( 'strikethrough', ws, '=', ws, ( bool | interpolated ) ) |
           ( 'inverse', ws, '=', ws, ( bool | interpolated ) ) |
           ( 'inherit', ws, '=', ws, ( inherit | interpolated ) ) ;

nothing = 'nothing' ;
bool = 'true' | 'false' ;
symbol = [^ ,)]+ ;
hexcolor = ('#' | '0x'), [0-9a-f]{6} ;
simplecolor = hexcolor | symbol | nothing ;

underline = nothing | bool | simplecolor | underlinestyled;
underlinestyled = '(', ws, ('' | nothing | simplecolor | interpolated), ws,
                  ',', ws, ( symbol | interpolated ), ws ')' ;

inherit = ( '[', inheritval, { ',', inheritval }, ']' ) | inheritval;
inheritval = ws, ':'?, symbol ;
source
StyledStrings.StyledMarkup.styledFunction
styled(content::AbstractString) -> AnnotatedString

Konstruiere einen stilisierten String. Innerhalb des Strings wenden {<specs>:<content>}-Strukturen die Formatierung auf <content> an, gemäß der Liste von durch Kommas getrennten Spezifikationen <specs>. Jede Spezifikation kann entweder in Form eines Schriftartnamens, einer Inline-Schriftartspezifikation oder eines key=value-Paars vorliegen. Der Wert muss in {...} eingeschlossen werden, wenn er eines der Zeichen ,=:{} enthält.

Dies ist ein funktionales Äquivalent zum @styled_str Makro, jedoch ohne Interpolationsmöglichkeiten.

source
StyledStrings.FaceType

Ein Face ist eine Sammlung grafischer Attribute zur Anzeige von Text. Faces steuern, wie Text im Terminal und möglicherweise auch an anderen Orten angezeigt wird.

Die meiste Zeit wird ein Face in den globalen Faces-Dictionaries als einzigartige Zuordnung zu einem Face-Namen Symbol gespeichert und wird am häufigsten unter diesem Namen anstelle des Face Objekts selbst referenziert.

Attribute

Alle Attribute können über den Schlüsselwort-Konstruktor gesetzt werden und standardmäßig auf nothing gesetzt.

  • height (ein Int oder Float64): Die Höhe entweder in dezi-pt (wenn ein Int), oder als Faktor der Basisgröße (wenn ein Float64).

  • weight (ein Symbol): Eines der Symbole (von am schwächsten bis am stärksten) :thin, :extralight, :light, :semilight, :normal, :medium, :semibold, :bold, :extrabold oder :black. In Terminals wird jedes Gewicht größer als :normal als fett angezeigt, und in Terminals, die variabel hellen Text unterstützen, wird jedes Gewicht kleiner als :normal als schwach angezeigt.

  • slant (ein Symbol): Eines der Symbole :italic, :oblique oder :normal.

  • foreground (eine SimpleColor): Die Vordergrundfarbe des Textes.

  • background (eine SimpleColor): Die Hintergrundfarbe des Textes.

  • underline, die Unterstreichung des Textes, die eine der folgenden Formen annimmt:

    • ein Bool: Ob der Text unterstrichen werden soll oder nicht.
    • eine SimpleColor: Der Text sollte mit dieser Farbe unterstrichen werden.
    • ein Tuple{Nothing, Symbol}: Der Text sollte mit dem Stil unterstrichen werden, der durch das Symbol festgelegt ist, eines von :straight, :double, :curly, :dotted oder :dashed.
    • ein Tuple{SimpleColor, Symbol}: Der Text sollte in der angegebenen SimpleColor unterstrichen werden und den zuvor durch das Symbol festgelegten Stil verwenden.
  • strikethrough (ein Bool): Ob der Text durchgestrichen werden soll.

  • inverse (ein Bool): Ob die Vordergrund- und Hintergrundfarben invertiert werden sollen.

  • inherit (ein Vector{Symbol}): Namen von Faces, von denen geerbt werden soll, wobei frühere Faces Priorität haben. Alle Faces erben von dem :default Face.

source
StyledStrings.addface!Function
addface!(name::Symbol => default::Face)

Erstelle ein neues Gesicht mit dem Namen name. Sofern kein Gesicht mit diesem Namen bereits existiert, wird default sowohl zu FACES.default als auch (eine Kopie davon) zu FACES.current hinzugefügt, wobei der aktuelle Wert zurückgegeben wird.

Sollte das Gesicht name bereits existieren, wird nothing zurückgegeben.

Beispiele

julia> addface!(:mypkg_myface => Face(slant=:italic, underline=true))
Face (sample)
         slant: italic
     underline: true
source
StyledStrings.withfacesFunction
withfaces(f, kv::Pair...)
withfaces(f, kvpair_itr)

Führt f mit FACES.current aus, das vorübergehend durch null oder mehr :name => val Argumente kv oder kvpair_itr, das kv-Formwerte erzeugt, modifiziert wird.

withfaces wird allgemein über die Syntax withfaces(kv...) do ... end verwendet. Ein Wert von nothing kann verwendet werden, um vorübergehend ein Gesicht zurückzusetzen (wenn es gesetzt wurde). Wenn withfaces zurückkehrt, wurde das ursprüngliche FACES.current wiederhergestellt.

Beispiele

julia> withfaces(:yellow => Face(foreground=:red), :green => :blue) do
           println(styled"{yellow:red} und {green:blue} gemischt ergeben {magenta:purple}")
       end
rot und blau gemischt ergeben lila
source
StyledStrings.SimpleColorType
struct SimpleColor

Eine grundlegende Darstellung einer Farbe, die für die Formatierung von Zeichenfolgen gedacht ist. Sie kann entweder eine benannte Farbe (wie :red) oder ein RGBTuple enthalten, das ein NamedTuple ist, das eine r, g, b Farbe mit einer Farbtiefe von 8 angibt.

Konstruktoren

SimpleColor(name::Symbol)  # z.B. :red
SimpleColor(rgb::RGBTuple) # z.B. (r=1, b=2, g=3)
SimpleColor(r::Integer, b::Integer, b::Integer)
SimpleColor(rgb::UInt32)   # z.B. 0x123456

Siehe auch tryparse(SimpleColor, rgb::String).

source
Base.parseMethod
parse(::Type{SimpleColor}, rgb::String)

Eine Analogie zu tryparse(SimpleColor, rgb::String) (siehe dort), die einen Fehler auslöst, anstatt nichts zurückzugeben.

source
Base.tryparseMethod
tryparse(::Type{SimpleColor}, rgb::String)

Versuchen Sie, rgb als SimpleColor zu parsen. Wenn rgb mit # beginnt und eine Länge von 7 hat, wird es in einen RGBTuple-unterstützten SimpleColor umgewandelt. Wenn rgb mit a-z beginnt, wird rgb als Farbname interpretiert und in einen Symbol-unterstützten SimpleColor umgewandelt.

Andernfalls wird nothing zurückgegeben.

Beispiele

julia> tryparse(SimpleColor, "blue")
SimpleColor(blue)

julia> tryparse(SimpleColor, "#9558b2")
SimpleColor(#9558b2)

julia> tryparse(SimpleColor, "#nocolor")
source
Base.mergeMethod
merge(initial::Face, others::Face...)

Fügen Sie die Eigenschaften des initial Gesichts und der anderen hinzu, wobei die späteren Gesichter Vorrang haben.

source