StyledStrings

Note

واجهة برمجة التطبيقات لـ StyledStrings و AnnotatedStrings تعتبر تجريبية وقابلة للتغيير بين إصدارات جوليا.

Styling

عند العمل مع السلاسل النصية، غالبًا ما تظهر التنسيقات والأساليب كقضية ثانوية.

على سبيل المثال، عند الطباعة إلى وحدة التحكم، قد ترغب في رش ANSI escape sequences في المخرجات، وعند إخراج بناءات تنسيق HTML (<span style="...">، إلخ) تخدم غرضًا مشابهًا، وهكذا. من الممكن ببساطة إدراج بناءات التنسيق الخام في السلسلة بجوار المحتوى نفسه، ولكن سرعان ما يتضح أن هذا ليس مناسبًا إلا لأبسط حالات الاستخدام. ليست جميع وحدات التحكم تدعم نفس رموز ANSI، ويجب إزالة بناءات التنسيق بعناية عند حساب عرض المحتوى المنسق بالفعل، وذلك قبل أن تبدأ حتى في التعامل مع تنسيقات الإخراج المتعددة.

بدلاً من ترك هذه المشكلة لتُعاني منها الأجزاء السفلية بشكل واسع، يتم التعامل معها بشكل مباشر من خلال إدخال نوع سلسلة خاص (AnnotatedString). هذا النوع من السلاسل يلف أي نوع آخر AbstractString ويسمح بتطبيق معلومات التنسيق على المناطق (على سبيل المثال، الأحرف من 1 إلى 7 تكون بالخط العريض والأحمر).

تُنسق مناطق النص عن طريق تطبيق Face (فكر في "نوع الخط") عليها - وهي بنية تحمل معلومات التنسيق. كوسيلة للراحة، يمكن ببساطة تسمية الوجوه في قاموس الوجوه العالمي (مثل shadow) بدلاً من إعطاء 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 مباشرة.

بالإضافة إلى هذه القدرات، نقدم أيضًا طريقة مريحة لبناء AnnotatedString، الموضحة في Styled String Literals.

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

Annotated Strings

من المفيد أحيانًا أن تكون قادرًا على الاحتفاظ بالبيانات الوصفية المتعلقة بمناطق من سلسلة نصية. AnnotatedString يلتف حول سلسلة نصية أخرى ويسمح بتعليق مناطق منها بقيم معنونة (:label => value). يتم تطبيق جميع عمليات السلسلة النصية العامة على السلسلة الأساسية. ومع ذلك، عندما يكون ذلك ممكنًا، يتم الحفاظ على معلومات التنسيق. هذا يعني أنه يمكنك معالجة 4d61726b646f776e2e436f64652822222c2022416e6e6f7461746564537472696e672229_4072656620426173652e416e6e6f7461746564537472696e67 —أخذ أجزاء فرعية منها، وتوسيعها، ودمجها مع سلاسل نصية أخرى— وسترافق التعليقات التوضيحية للبيانات الوصفية "الرحلة".

هذا النوع من السلاسل أساسي لـ StyledStrings stdlib، الذي يستخدم تعليقات معنونة بـ :face للاحتفاظ بمعلومات التنسيق.

عند دمج AnnotatedString، تأكد من استخدام annotatedstring بدلاً من string إذا كنت ترغب في الاحتفاظ بتعليقات السلسلة.

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

يمكن الوصول إلى التعليقات الخاصة بـ AnnotatedString وتعديلها عبر دوال annotations و annotate!.

Styling via AnnotatedStrings

Faces

The Face type

A Face يحدد تفاصيل نوع الخط الذي يمكن ضبط النص فيه. يغطي مجموعة من السمات الأساسية التي تتعمم بشكل جيد عبر تنسيقات مختلفة، وهي:

  • خط
  • الارتفاع
  • الوزن
  • ميل
  • foreground
  • خلفية
  • underline
  • strikethrough
  • عكسي
  • وراثة

للحصول على تفاصيل حول الأشكال المحددة التي تتخذها هذه السمات، راجع Face docstring، ولكن ما يهم بشكل خاص هو inherit لأنه يسمح لك بـ وراثة السمات من 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365s.

The global faces dictionary

لجعل الإشارة إلى أنماط معينة أكثر ملاءمة، هناك Dict{Symbol, Face} عالمي يسمح بالإشارة إلى Face ببساطة عن طريق الاسم. يمكن للحزم إضافة الوجوه إلى هذه القاموس عبر addface!، ويمكن تحميل الوجوه بسهولة customized.

Appropriate face naming

يجب على أي حزمة تسجل وجوه جديدة التأكد من أنها مسبوقة باسم الحزمة، أي اتباع التنسيق mypackage_myface. هذا مهم للتنبؤ، ولمنع تصادم الأسماء.

علاوة على ذلك، يجب على الحزم أن تأخذ في الاعتبار استخدام (وتقديم) الوجوه الدلالية (مثل code) بدلاً من الألوان والأساليب المباشرة (مثل cyan). هذا مفيد بعدة طرق، بدءًا من جعل النية في الاستخدام أكثر وضوحًا، ومساعدة التكوين، وجعل تخصيص المستخدم أكثر سهولة.

هناك مجموعتان من الاستثناءات لقواعد بادئة الحزمة:

  • مجموعة الوجوه الأساسية التي هي جزء من القيمة الافتراضية لقاموس الوجوه
  • الوجوه التي قدمتها مكتبة جوليا القياسية الخاصة بها، وهي JuliaSyntaxHighlighting

Basic faces

الوجوه الأساسية تهدف إلى تمثيل فكرة عامة قابلة للتطبيق على نطاق واسع.

لإعداد بعض النصوص بصفة معينة، لدينا الوجوه bold و light و italic و underline و strikethrough و inverse.

هناك أيضًا أسماء محددة للألوان الطرفية الـ 16: أسود، أحمر، أخضر، أصفر، أزرق، ماغنتا، سيان، أبيض، أسود ساطع/رمادي/رمادي، أحمر ساطع، أخضر ساطع، أزرق ساطع، ماغنتا ساطع، سيان ساطع، وأبيض ساطع.

للنص المظلل (أي الخافت ولكن موجود) هناك وجه shadow. للإشارة إلى منطقة محددة، هناك وجه region. بالمثل، للتأكيد والتسليط الضوء، يتم تعريف وجهي emphasis و highlight. هناك أيضًا code للنص الشبيه بالشيفرة.

لإظهار شدة الرسائل بصريًا، يتم تعريف وجوه error و warning و success و info و note و tip.

Customisation of faces (Faces.toml)

من الجيد أن تكون أسماء الوجوه في قاموس الوجوه العالمي قابلة للتخصيص. إن التصميم والجمالية أمران جميلان، ومن المهم أيضًا لأسباب تتعلق بالوصول. يمكن تحليل ملف TOML إلى قائمة من Face المواصفات التي يتم دمجها مع الإدخال الموجود مسبقًا في قاموس الوجوه.

A Face يتم تمثيله في TOML على النحو التالي:

[facename]
attribute = "value"
...

[package.facename]
attribute = "value"

على سبيل المثال، إذا كانت واجهة shadow صعبة القراءة، يمكن جعلها أكثر سطوعًا كما يلي:

[shadow]
foreground = "white"

عند التهيئة، يتم تحميل ملف config/faces.toml الموجود تحت أول مستودع جوليا (عادةً ~/.julia).

Applying faces to a AnnotatedString

بموجب الاتفاق، فإن سمات :face ل AnnotatedString تحمل معلومات عن Face التي تنطبق حاليًا. يمكن تقديم ذلك بأشكال متعددة، كرمز واحد Symbol يسمي 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 في القاموس العالمي للوجوه، أو 4d61726b646f776e2e436f64652822222c2022466163652229_40726566205374796c6564537472696e67732e46616365 نفسه، أو متجه من أي منهما.

تقوم الطريقتان show(::IO, ::MIME"text/plain", ::AnnotatedString) و show(::IO, ::MIME"text/html", ::AnnotatedString) بالنظر إلى سمات :face ودمجها جميعًا معًا عند تحديد التنسيق العام.

يمكننا تزويد :face السمات إلى AnnotatedString أثناء الإنشاء، إضافتها إلى قائمة الخصائص لاحقًا، أو استخدام 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

لتسهيل بناء AnnotatedStrings مع Faces المطبقة، فإن styled"..." سلسلة حرفية مصممة تسمح بالتعبير عن المحتوى والسمات بسهولة معًا عبر قواعد نحوية مخصصة.

داخل حرفية styled"..."، تعتبر الأقواس المعقوفة رموزًا خاصة ويجب الهروب منها في الاستخدام العادي (\{, \}). وهذا يسمح باستخدامها للتعبير عن التعليقات مع تراكيب {annotations...:text} (قابلة للتعشيش).

مكون annotations... هو قائمة مفصولة بفواصل من ثلاثة أنواع من التعليقات التوضيحية.

  • أسماء الوجوه
  • تعبيرات Face المضمنة (key=val,...)
  • مفتاح=قيمة أزواج

التداخل ممكن في كل مكان باستثناء مفاتيح الوجه المضمنة.

للمزيد من المعلومات حول القواعد، راجع المساعدة الموسعة لـ styled"..." docstring.

كمثال، يمكننا توضيح قائمة الوجوه المدمجة المذكورة أعلاه على النحو التالي:

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

قم بإنشاء سلسلة منسقة. داخل السلسلة، تُطبق هياكل {<specs>:<content>} التنسيق على <content>، وفقًا لقائمة المواصفات المفصولة بفواصل <specs>. يمكن أن تأخذ كل مواصفة شكل اسم وجه، أو مواصفة وجه داخلية، أو زوج key=value. يجب أن تكون القيمة محاطة بـ {...} إذا كانت تحتوي على أي من الأحرف ,=:{}.

تعمل الاستبدالات النصية باستخدام $ بنفس طريقة السلاسل العادية، باستثناء أنه يجب الهروب من الاقتباسات. يمكن أيضًا استبدال الوجوه والمفاتيح والقيم باستخدام $.

مثال

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

مساعدة موسعة

يمكن وصف هذه الماكرو بواسطة قواعد EBNF التالية:

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

شرط إضافي غير مشفر في القواعد أعلاه هو أن plain يجب أن يكون إدخالًا صالحًا لـ unescape_string، مع الاحتفاظ بـ specialchar.

القواعد أعلاه لـ inlineface مبسطة، حيث أن التنفيذ الفعلي أكثر تعقيدًا قليلاً. السلوك الكامل موضح أدناه.

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

قم بإنشاء سلسلة منسقة. داخل السلسلة، تُطبق هياكل {<specs>:<content>} التنسيق على <content>، وفقًا لقائمة من المواصفات المفصولة بفواصل <specs>. يمكن أن تأخذ كل مواصفة إما شكل اسم وجه، أو مواصفة وجه داخلية، أو زوج key=value. يجب أن تكون القيمة محاطة بـ {...} إذا كانت تحتوي على أي من الأحرف ,=:{}.

هذا هو المعادل الوظيفي لماكرو @styled_str، فقط بدون قدرات الاستبدال.

source
StyledStrings.FaceType

A Face هو مجموعة من الخصائص الرسومية لعرض النص. تتحكم الوجوه في كيفية عرض النص في الطرفية، وربما في أماكن أخرى أيضًا.

معظم الوقت، سيتم تخزين Face في القواميس العالمية للوجوه كارتباط فريد مع اسم الوجه Symbol، وسيتم الإشارة إليه غالبًا بهذا الاسم بدلاً من كائن Face نفسه.

الخصائص

يمكن تعيين جميع الخصائص عبر مُنشئ الكلمات الرئيسية، وتكون افتراضيًا nothing.

  • height (نوع Int أو Float64): الارتفاع إما بوحدة الديسي-نقطة (عندما يكون Int)، أو كعامل من الحجم الأساسي (عندما يكون Float64).

  • weight (نوع Symbol): واحدة من الرموز (من الأضعف إلى الأقوى) :thin, :extralight, :light, :semilight, :normal, :medium, :semibold, :bold, :extrabold, أو :black. في الطرفيات، يتم عرض أي وزن أكبر من :normal كخط عريض، وفي الطرفيات التي تدعم النص المتغير السطوع، يتم عرض أي وزن أقل من :normal كخط خفيف.

  • slant (نوع Symbol): واحدة من الرموز :italic, :oblique, أو :normal.

  • foreground (نوع SimpleColor): لون النص الأمامي.

  • background (نوع SimpleColor): لون خلفية النص.

  • underline، خط النص السفلي، الذي يأخذ واحدة من الأشكال التالية:

    • Bool: ما إذا كان يجب أن يكون النص تحت الخط أم لا.
    • SimpleColor: يجب أن يكون النص تحت الخط بهذا اللون.
    • Tuple{Nothing, Symbol}: يجب أن يكون النص تحت الخط باستخدام النمط المحدد بواسطة الرمز، واحد من :straight, :double, :curly, :dotted, أو :dashed.
    • Tuple{SimpleColor, Symbol}: يجب أن يكون النص تحت الخط باللون SimpleColor المحدد، وباستخدام النمط المحدد بواسطة الرمز، كما هو مذكور سابقًا.
  • strikethrough (نوع Bool): ما إذا كان يجب أن يكون النص مخطوطًا.

  • inverse (نوع Bool): ما إذا كان يجب عكس ألوان المقدمة والخلفية.

  • inherit (نوع Vector{Symbol}): أسماء الوجوه التي يجب الوراثة منها، مع إعطاء الأولوية للوجوه السابقة. جميع الوجوه ترث من الوجه :default.

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

قم بإنشاء وجه جديد بالاسم name. طالما أنه لا يوجد وجه موجود بالفعل بهذا الاسم، يتم إضافة default إلى كل من FACES.default و (نسخة من) إلى FACES.current، مع إرجاع القيمة الحالية.

إذا كان الوجه name موجودًا بالفعل، يتم إرجاع nothing.

أمثلة

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 مع FACES.current المعدل مؤقتًا بواسطة صفر أو أكثر من الوسائط :name => val kv، أو kvpair_itr الذي ينتج قيمًا على شكل kv.

يتم استخدام withfaces عمومًا عبر بناء الجملة withfaces(kv...) do ... end. يمكن استخدام قيمة nothing لإلغاء تعيين وجه مؤقتًا (إذا تم تعيينه). عند عودة withfaces، يتم استعادة FACES.current الأصلي.

أمثلة

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

تمثيل أساسي للون، مخصص لأغراض تنسيق النص. يمكن أن يحتوي إما على لون مسمى (مثل :red)، أو RGBTuple وهو NamedTuple يحدد لون r و g و b بعمق بت يبلغ 8.

المنشئات

SimpleColor(name::Symbol)  # على سبيل المثال :red
SimpleColor(rgb::RGBTuple) # على سبيل المثال (r=1, b=2, g=3)
SimpleColor(r::Integer, b::Integer, b::Integer)
SimpleColor(rgb::UInt32)   # على سبيل المثال 0x123456

انظر أيضًا tryparse(SimpleColor, rgb::String).

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

نظير لـ tryparse(SimpleColor, rgb::String) (انظر هناك)، الذي يثير خطأ بدلاً من إرجاع nothing.

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

حاول تحليل rgb كـ SimpleColor. إذا كان rgb يبدأ بـ # وله طول 7، يتم تحويله إلى SimpleColor مدعوم بـ RGBTuple. إذا كان rgb يبدأ بـ a-z، يتم تفسير rgb كاسم لون ويتم تحويله إلى SimpleColor مدعوم بـ Symbol.

بخلاف ذلك، يتم إرجاع nothing.

أمثلة

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

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

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

دمج خصائص وجه initial و others، مع إعطاء الأولوية للوجوه اللاحقة.

source