StyledStrings

Note

L'API pour StyledStrings et AnnotatedStrings est considérée comme expérimentale et est sujette à des modifications entre les versions de Julia.

Styling

Lorsqu'on travaille avec des chaînes de caractères, le formatage et le style apparaissent souvent comme une préoccupation secondaire.

Par exemple, lorsque vous imprimez dans un terminal, vous pourriez vouloir saupoudrer ANSI escape sequences dans la sortie. Lors de la sortie de constructions de style HTML (<span style="...">, etc.), cela sert un but similaire, et ainsi de suite. Il est possible d'insérer simplement les constructions de style brutes dans la chaîne à côté du contenu lui-même, mais il devient rapidement évident que ce n'est pas bien adapté à autre chose que les cas d'utilisation les plus basiques. Tous les terminaux ne prennent pas en charge les mêmes codes ANSI, les constructions de style doivent être soigneusement supprimées lors du calcul de la largeur du contenu déjà stylé, et cela avant même de commencer à gérer plusieurs formats de sortie.

Au lieu de laisser ce mal de tête être largement ressenti en aval, il est abordé de front par l'introduction d'un type de chaîne spécial (AnnotatedString). Ce type de chaîne enveloppe tout autre type AbstractString et permet d'appliquer des informations de formatage à des régions (par exemple, les caractères 1 à 7 sont en gras et rouges).

Les régions d'une chaîne sont stylisées en appliquant Face (pensez à "police") à celles-ci — une structure qui contient des informations de style. Par commodité, les polices dans le dictionnaire global des polices (par exemple shadow) peuvent simplement être nommées au lieu de donner directement le 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365.

Avec ces capacités, nous fournissons également un moyen pratique de construire AnnotatedString, détaillé dans Styled String Literals.

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

Annotated Strings

Il est parfois utile de pouvoir conserver des métadonnées relatives à des régions d'une chaîne de caractères. Un AnnotatedString enveloppe une autre chaîne et permet d'annoter des régions avec des valeurs étiquetées (:label => value). Toutes les opérations de chaîne génériques sont appliquées à la chaîne sous-jacente. Cependant, lorsque cela est possible, les informations de style sont préservées. Cela signifie que vous pouvez manipuler un 4d61726b646f776e2e436f64652822222c2022416e6e6f7461746564537472696e672229_4072656620426173652e416e6e6f7461746564537472696e67 — en prenant des sous-chaînes, en les remplissant, en les concaténant avec d'autres chaînes — et les annotations de métadonnées "viendront avec".

Ce type de chaîne est fondamental pour le StyledStrings stdlib, qui utilise des annotations étiquetées :face pour contenir des informations de style.

Lors de la concaténation d'un AnnotatedString, veillez à utiliser annotatedstring au lieu de string si vous souhaitez conserver les annotations de chaîne.

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

Les annotations d'un AnnotatedString peuvent être accessibles et modifiées via les fonctions annotations et annotate!.

Styling via AnnotatedStrings

Faces

The Face type

Un Face spécifie les détails d'une police de caractères dans laquelle le texte peut être mis en forme. Il couvre un ensemble d'attributs de base qui se généralisent bien à travers différents formats, à savoir :

  • police
  • hauteur
  • poids
  • inclinaison
  • premier plan
  • arrière-plan
  • souligner
  • barré
  • inverse
  • hériter

Pour des détails sur les formes particulières que prennent ces attributs, consultez la Face docstring, mais ce qui est particulièrement intéressant est inherit car il vous permet de hériter des attributs d'autres 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365.

The global faces dictionary

Pour rendre la référence à des styles particuliers plus pratique, il existe un Dict{Symbol, Face} global qui permet de référencer des Face simplement par leur nom. Les packages peuvent ajouter des visages à ce dictionnaire via la fonction addface!, et les visages chargés peuvent être facilement customized.

Appropriate face naming

Tout package enregistrant de nouveaux visages doit s'assurer qu'ils sont préfixés par le nom du package, c'est-à-dire suivre le format mypackage_myface. Cela est important pour la prévisibilité et pour éviter les conflits de noms.

De plus, les packages devraient veiller à utiliser (et à introduire) des visages sémantiques (comme code) plutôt que des couleurs et styles directs (comme cyan). Cela est utile de plusieurs manières, en rendant l'intention d'utilisation plus évidente, en aidant à la composition et en rendant la personnalisation par l'utilisateur plus intuitive.

Il existe deux ensembles d'exemptions à la règle de préfixe de paquet :

  • l'ensemble des visages de base qui font partie de la valeur par défaut du dictionnaire des visages
  • faces introduits par la propre bibliothèque standard de Julia, à savoir JuliaSyntaxHighlighting

Basic faces

Les visages de base sont destinés à représenter une idée générale qui est largement applicable.

Pour définir un texte avec un certain attribut, nous avons les styles gras, clair, italique, souligné, barré et inverse.

Il existe également des noms pour les 16 couleurs terminales : noir, rouge, vert, jaune, bleu, magenta, cyan, blanc, noir_clair/gris, rouge_clair, vert_clair, bleu_clair, magenta_clair, cyan_clair, et blanc_clair.

Pour le texte ombragé (c'est-à-dire atténué mais présent), il y a la face shadow. Pour indiquer une région sélectionnée, il y a la face region. De même, pour l'accentuation et la mise en évidence, les faces emphasis et highlight sont définies. Il y a aussi code pour le texte de type code.

Pour indiquer visuellement la gravité des messages, les visages error, warning, success, info, note et tip sont définis.

Customisation of faces (Faces.toml)

Il est bon que les noms des visages dans le dictionnaire mondial des visages soient personnalisables. Le thème et l'esthétique sont agréables, et c'est également important pour des raisons d'accessibilité. Un fichier TOML peut être analysé en une liste de Face spécifications qui sont fusionnées avec l'entrée préexistante dans le dictionnaire des visages.

Un Face est représenté en TOML comme suit :

[facename]
attribute = "value"
...

[package.facename]
attribute = "value"

Par exemple, si le visage shadow est trop difficile à lire, il peut être éclairci comme ceci :

[shadow]
foreground = "white"

Lors de l'initialisation, le fichier config/faces.toml sous le premier dépôt Julia (généralement ~/.julia) est chargé.

Applying faces to a AnnotatedString

Par convention, les attributs :face d'un AnnotatedString contiennent des informations sur les Face qui s'appliquent actuellement. Cela peut être donné sous plusieurs formes, comme un seul Symbol nommant un 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 dans le dictionnaire global des faces, un 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 lui-même, ou un vecteur de l'un ou l'autre.

Les méthodes show(::IO, ::MIME"text/plain", ::AnnotatedString) et show(::IO, ::MIME"text/html", ::AnnotatedString) examinent toutes deux les attributs :face et les fusionnent toutes ensemble lors de la détermination du style global.

Nous pouvons fournir des attributs :face à un AnnotatedString lors de la construction, les ajouter à la liste des propriétés par la suite, ou utiliser le pratique Styled String literals.

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

Pour faciliter la construction de AnnotatedString avec Face appliqués, le littéral de chaîne stylé styled"..." permet d'exprimer facilement le contenu et les attributs ensemble via une grammaire personnalisée.

Dans un littéral styled"...", les accolades sont considérées comme des caractères spéciaux et doivent être échappées dans une utilisation normale (\{, \}). Cela permet de les utiliser pour exprimer des annotations avec des constructions {annotations...:text} (imbriquées).

Le composant annotations... est une liste séparée par des virgules de trois types d'annotations.

  • Noms de visage
  • Expressions Face en ligne (clé=val,...)
  • clé=valeur paires

L'interpolation est possible partout sauf pour les clés de visage en ligne.

Pour plus d'informations sur la grammaire, consultez l'aide étendue de la docstring styled"...".

En tant qu'exemple, nous pouvons démontrer la liste des visages intégrés mentionnés ci-dessus comme suit :

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

Construisez une chaîne stylée. Dans la chaîne, les structures {<specs>:<content>} appliquent le formatage à <content>, selon la liste des spécifications séparées par des virgules <specs>. Chaque spécification peut prendre la forme d'un nom de face, d'une spécification de face en ligne, ou d'une paire key=value. La valeur doit être entourée par {...} si elle contient l'un des caractères ,=:{}.

L'interpolation de chaînes avec $ fonctionne de la même manière que pour les chaînes régulières, sauf que les guillemets doivent être échappés. Les faces, les clés et les valeurs peuvent également être interpolées avec $.

Exemple

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

Aide étendue

Cette macro peut être décrite par la grammaire EBNF suivante :

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' } ; (* espace blanc *)

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 = [^${},:], [^,:]* ;

Une stipulation supplémentaire non encodée dans la grammaire ci-dessus est que plain doit être une entrée valide pour unescape_string, avec specialchar conservé.

La grammaire ci-dessus pour inlineface est simplifiée, car l'implémentation réelle est un peu plus sophistiquée. Le comportement complet est donné ci-dessous.

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

Construit une chaîne stylée. Dans la chaîne, les structures {<specs>:<content>} appliquent le formatage à <content>, selon la liste des spécifications séparées par des virgules <specs>. Chaque spécification peut prendre la forme d'un nom de police, d'une spécification de police en ligne, ou d'une paire key=value. La valeur doit être entourée par {...} si elle contient l'un des caractères ,=:{}.

Ceci est un équivalent fonctionnel du macro @styled_str, juste sans capacités d'interpolation.

source
StyledStrings.FaceType

Un Face est une collection d'attributs graphiques pour afficher du texte. Les faces contrôlent la façon dont le texte est affiché dans le terminal, et peut-être aussi dans d'autres endroits.

La plupart du temps, un Face sera stocké dans les dictionnaires de faces globaux comme une association unique avec un nom de face Symbol, et sera le plus souvent référencé par ce nom plutôt que par l'objet Face lui-même.

Attributs

Tous les attributs peuvent être définis via le constructeur par mot-clé, et par défaut à nothing.

  • height (un Int ou Float64): La hauteur en décimales (lorsqu'un Int), ou comme un facteur de la taille de base (lorsqu'un Float64).

  • weight (un Symbol): L'un des symboles (du plus léger au plus dense) :thin, :extralight, :light, :semilight, :normal, :medium, :semibold, :bold, :extrabold, ou :black. Dans les terminaux, tout poids supérieur à :normal est affiché en gras, et dans les terminaux qui supportent le texte à luminosité variable, tout poids inférieur à :normal est affiché comme léger.

  • slant (un Symbol): L'un des symboles :italic, :oblique, ou :normal.

  • foreground (un SimpleColor): La couleur de premier plan du texte.

  • background (un SimpleColor): La couleur de fond du texte.

  • underline, le soulignement du texte, qui prend l'une des formes suivantes :

    • un Bool: Si le texte doit être souligné ou non.
    • un SimpleColor: Le texte doit être souligné avec cette couleur.
    • un Tuple{Nothing, Symbol}: Le texte doit être souligné en utilisant le style défini par le Symbol, l'un de :straight, :double, :curly, :dotted, ou :dashed.
    • un Tuple{SimpleColor, Symbol}: Le texte doit être souligné dans la SimpleColor spécifiée, et en utilisant le style spécifié par le Symbol, comme précédemment.
  • strikethrough (un Bool): Si le texte doit être barré.

  • inverse (un Bool): Si les couleurs de premier plan et de fond doivent être inversées.

  • inherit (un Vector{Symbol}): Noms des faces à hériter, avec les faces antérieures prenant la priorité. Toutes les faces héritent de la face :default.

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

Créez un nouveau visage par le nom name. Tant qu'aucun visage n'existe déjà sous ce nom, default est ajouté à la fois à FACES.default et (une copie de) à FACES.current, avec la valeur actuelle retournée.

Si le visage name existe déjà, nothing est retourné.

Exemples

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

Exécutez f avec FACES.current temporairement modifié par zéro ou plusieurs arguments :name => val kv, ou kvpair_itr qui produit des valeurs au format kv.

withfaces est généralement utilisé via la syntaxe withfaces(kv...) do ... end. Une valeur de nothing peut être utilisée pour désactiver temporairement une face (si elle a été définie). Lorsque withfaces retourne, l'original FACES.current a été restauré.

Exemples

julia> withfaces(:yellow => Face(foreground=:red), :green => :blue) do
           println(styled"{yellow:red} and {green:blue} mixed make {magenta:purple}")
       end
red and blue mixed make purple
source
StyledStrings.SimpleColorType
struct SimpleColor

Une représentation de base d'une couleur, destinée à des fins de stylisation de chaîne. Elle peut contenir soit une couleur nommée (comme :red), soit un RGBTuple qui est un NamedTuple spécifiant une couleur r, g, b avec une profondeur de bits de 8.

Constructeurs

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

Voir aussi tryparse(SimpleColor, rgb::String).

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

Un analogue de tryparse(SimpleColor, rgb::String) (voir ci-dessus), qui lève une erreur au lieu de retourner nothing.

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

Tente de parser rgb en tant que SimpleColor. Si rgb commence par # et a une longueur de 7, il est converti en un SimpleColor soutenu par un RGBTuple. Si rgb commence par a-z, rgb est interprété comme un nom de couleur et converti en un SimpleColor soutenu par un Symbol.

Sinon, nothing est retourné.

Exemples

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

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

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

Fusionner les propriétés du visage initial et des autres, les visages ultérieurs ayant la priorité.

source