StyledStrings
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 Face
s (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 AnnotatedString
s
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_40726566205374796c6564537472696e67732e46616365
s 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.
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 Face
s, 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 == str2
true
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_str
— Macro@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 ;
StyledStrings.StyledMarkup.styled
— Functionstyled(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.
StyledStrings.Face
— TypeEin 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
(einInt
oderFloat64
): Die Höhe entweder in dezi-pt (wenn einInt
), oder als Faktor der Basisgröße (wenn einFloat64
).weight
(einSymbol
): 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
(einSymbol
): Eines der Symbole:italic
,:oblique
oder:normal
.foreground
(eineSimpleColor
): Die Vordergrundfarbe des Textes.background
(eineSimpleColor
): 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.
- ein
strikethrough
(einBool
): Ob der Text durchgestrichen werden soll.inverse
(einBool
): Ob die Vordergrund- und Hintergrundfarben invertiert werden sollen.inherit
(einVector{Symbol}
): Namen von Faces, von denen geerbt werden soll, wobei frühere Faces Priorität haben. Alle Faces erben von dem:default
Face.
StyledStrings.addface!
— Functionaddface!(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
StyledStrings.withfaces
— Functionwithfaces(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
StyledStrings.SimpleColor
— Typestruct 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)
.
Base.parse
— Methodparse(::Type{SimpleColor}, rgb::String)
Eine Analogie zu tryparse(SimpleColor, rgb::String)
(siehe dort), die einen Fehler auslöst, anstatt nichts
zurückzugeben.
Base.tryparse
— Methodtryparse(::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")
Base.merge
— Methodmerge(initial::Face, others::Face...)
Fügen Sie die Eigenschaften des initial
Gesichts und der anderen hinzu, wobei die späteren Gesichter Vorrang haben.