1use std::sync::{LazyLock, OnceLock};
3
4use FormType::*;
5use crossterm::style::{Attribute, Attributes, ContentStyle};
6pub use crossterm::{cursor::SetCursorStyle as CursorShape, style::Color};
7use parking_lot::{RwLock, RwLockWriteGuard};
8
9pub use self::global::{
10 FormFmt, add_colorscheme, extra_cursor, from_id, id_of, inner_to_id, main_cursor, name_of,
11 painter, set, set_colorscheme, set_extra_cursor, set_main_cursor, set_many, set_weak,
12 unset_extra_cursor, unset_main_cursor,
13};
14pub(crate) use self::global::{colorscheme_exists, exists};
15use crate::{
16 data::RwLockReadGuard,
17 hooks::{self, FormSet},
18 ui::Sender,
19};
20
21pub trait ColorScheme: Send + Sync + 'static {
22 fn apply(&self);
23
24 fn name(&self) -> &'static str;
25}
26
27static SENDER: OnceLock<Sender> = OnceLock::new();
28static BASE_FORMS: &[(&str, Form, FormType)] = &[
29 ("Default", Form::new().0, Normal),
30 ("Accent", Form::bold().0, Normal),
31 ("DefaultOk", Form::blue().0, Normal),
32 ("AccentOk", Form::cyan().0, Normal),
33 ("DefaultErr", Form::red().0, Normal),
34 ("AccentErr", Form::red().bold().0, Normal),
35 ("DefaultHint", Form::grey().0, Normal),
36 ("AccentHint", Form::grey().bold().0, Normal),
37 ("MainCursor", Form::reverse().0, Normal),
38 ("ExtraCursor", Form::reverse().0, Ref(M_CUR_ID)),
39 ("MainSelection", Form::on_dark_grey().0, Normal),
40 ("ExtraSelection", Form::on_dark_grey().0, Ref(M_SEL_ID)),
41 ("Inactive", Form::grey().0, Normal),
42 ("type", Form::yellow().italic().0, Normal),
44 ("type.builtin", Form::yellow().reset().0, Normal),
45 ("function", Form::blue().reset().0, Normal),
46 ("comment", Form::grey().0, Normal),
47 ("comment.documentation", Form::grey().bold().0, Normal),
48 ("punctuation.bracket", Form::red().0, Normal),
49 ("punctuation.delimiter", Form::cyan().0, Normal),
50 ("constant", Form::grey().0, Normal),
51 ("constant.builtin", Form::dark_yellow().0, Normal),
52 ("variable.parameter", Form::italic().0, Normal),
53 ("variable.builtin", Form::dark_yellow().0, Normal),
54 ("label", Form::green().0, Normal),
55 ("keyword", Form::magenta().0, Normal),
56 ("string", Form::green().0, Normal),
57 ("escape", Form::dark_yellow().0, Normal),
58 ("attribute", Form::magenta().0, Normal),
59 ("operator", Form::cyan().0, Normal),
60 ("constructor", Form::yellow().0, Normal),
61 ("module", Form::blue().italic().0, Normal),
62 ("markup", Form::new().0, Ref(DEFAULT_ID)),
64 ("markup.strong", Form::cyan().bold().0, Normal),
65 ("markup.italic", Form::cyan().italic().0, Normal),
66 ("markup.strikethrough", Form::cyan().crossed_out().0, Normal),
67 (
68 "markup.underline",
69 Form::underline_cyan().underlined().0,
70 Normal,
71 ),
72 ("markup.heading", Form::blue().bold().0, Normal),
73 ("markup.math", Form::yellow().0, Normal),
74 ("markup.quote", Form::grey().italic().0, Normal),
75 ("markup.link", Form::blue().underlined().0, Normal),
76 ("markup.raw", Form::cyan().0, Normal),
77 ("markup.list", Form::yellow().0, Normal),
78 ("markup.list.checked", Form::green().0, Normal),
79 ("markup.list.unchecked", Form::grey().0, Normal),
80];
81
82mod global {
84 use std::sync::LazyLock;
85
86 use parking_lot::Mutex;
87
88 use super::{BASE_FORMS, BuiltForm, ColorScheme, CursorShape, Form, FormId, Painter, Palette};
89 use crate::{
90 hooks::{self, ColorSchemeSet},
91 text::err,
92 };
93
94 static PALETTE: Palette = Palette::new();
95 static FORMS: LazyLock<Mutex<Vec<&str>>> =
96 LazyLock::new(|| Mutex::new(BASE_FORMS.iter().map(|(name, ..)| *name).collect()));
97 static COLORSCHEMES: LazyLock<Mutex<Vec<Box<dyn ColorScheme>>>> = LazyLock::new(Mutex::default);
98
99 pub trait FormFmt: InnerFormFmt {}
107 impl FormFmt for Form {}
108 impl FormFmt for BuiltForm {}
109 impl FormFmt for &str {}
110 impl FormFmt for &mut str {}
111 impl FormFmt for String {}
112
113 pub fn set(name: impl ToString, form: impl FormFmt) -> FormId {
135 let kind = form.kind();
136 let name: &'static str = name.to_string().leak();
137
138 match kind {
139 Kind::Form(form) => crate::thread::queue(move || PALETTE.set_form(name, form)),
140 Kind::Ref(refed) => crate::thread::queue(move || PALETTE.set_ref(name, refed)),
141 }
142
143 let mut forms = FORMS.lock();
144 if let Kind::Ref(refed) = kind
145 && !forms.contains(&refed)
146 {
147 forms.push(refed);
148 }
149
150 if let Some(id) = forms.iter().position(|form| *form == name) {
151 FormId(id as u16)
152 } else {
153 forms.push(name);
154 FormId(forms.len() as u16 - 1)
155 }
156 }
157
158 pub fn set_weak(name: impl ToString, form: impl FormFmt) -> FormId {
180 let kind = form.kind();
181 let name: &'static str = name.to_string().leak();
182
183 match kind {
184 Kind::Form(form) => crate::thread::queue(move || PALETTE.set_weak_form(name, form)),
185 Kind::Ref(refed) => crate::thread::queue(move || PALETTE.set_weak_ref(name, refed)),
186 }
187
188 let mut forms = FORMS.lock();
189 if let Kind::Ref(refed) = kind
190 && !forms.contains(&refed)
191 {
192 forms.push(refed);
193 }
194
195 if let Some(id) = forms.iter().position(|form| *form == name) {
196 FormId(id as u16)
197 } else {
198 forms.push(name);
199 FormId(forms.len() as u16 - 1)
200 }
201 }
202
203 pub fn from_id(id: FormId) -> Form {
210 PALETTE.form_from_id(id).unwrap_or(Form::new().0)
211 }
212
213 pub fn name_of(id: FormId) -> &'static str {
215 PALETTE.name_from_id(id)
216 }
217
218 pub fn main_cursor() -> (Form, Option<CursorShape>) {
220 PALETTE.main_cursor()
221 }
222
223 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
225 PALETTE.extra_cursor()
226 }
227
228 pub fn set_main_cursor(shape: CursorShape) {
251 crate::thread::queue(move || PALETTE.set_main_cursor(shape));
252 }
253
254 pub fn set_extra_cursor(shape: CursorShape) {
277 crate::thread::queue(move || PALETTE.set_extra_cursor(shape));
278 }
279
280 pub fn unset_main_cursor() {
291 crate::thread::queue(move || PALETTE.unset_main_cursor());
292 }
293
294 pub fn unset_extra_cursor() {
308 crate::thread::queue(move || PALETTE.unset_extra_cursor());
309 }
310
311 pub fn painter() -> Painter {
326 PALETTE.painter()
327 }
328
329 pub macro id_of {
344 ($form:expr) => {{
345 static ID: LazyLock<FormId> = LazyLock::new(|| inner_to_id($form));
346 *ID
347 }},
348 ($($form:expr),+) => {{
349 static IDS: LazyLock<&[FormId]> = LazyLock::new(|| {
350 let mut ids = Vec::new();
351 $(
352 ids.push(inner_to_id($form));
353 )+
354 ids.leak()
355 });
356 *ID
357 }}
358 }
359
360 pub fn inner_to_id(name: impl ToString) -> FormId {
362 let name: &'static str = name.to_string().leak();
363
364 crate::thread::queue(move || PALETTE.id_from_name(name));
365
366 let mut forms = FORMS.lock();
367 if let Some(id) = forms.iter().position(|form| *form == name) {
368 FormId(id as u16)
369 } else {
370 forms.push(name);
371 FormId(forms.len() as u16 - 1)
372 }
373 }
374
375 pub fn add_colorscheme(cs: impl ColorScheme) {
386 let mut colorschemes = COLORSCHEMES.lock();
387 let name = cs.name();
388 if let Some(i) = colorschemes.iter().position(|cs| cs.name() == name) {
389 colorschemes[i] = Box::new(cs);
390 } else {
391 colorschemes.push(Box::new(cs));
392 }
393 }
394
395 pub fn set_colorscheme(name: &str) {
402 let colorschemes = COLORSCHEMES.lock();
403 if let Some(cs) = colorschemes.iter().find(|cs| cs.name() == name) {
404 cs.apply();
405 hooks::trigger::<ColorSchemeSet>(cs.name());
406 } else {
407 crate::context::notify(err!("The colorscheme " [*a] name [] " was not found"));
408 }
409 }
410
411 pub macro set_many($(($name:literal, $form:expr)),+ $(,)?) {{
415 $(
416 set($name, $form);
417 )+
418 }}
419
420 pub(crate) fn exists(name: &str) -> bool {
422 FORMS.lock().contains(&name)
423 }
424
425 pub(crate) fn colorscheme_exists(name: &str) -> bool {
427 COLORSCHEMES.lock().iter().any(|cs| cs.name() == name)
428 }
429
430 #[derive(Clone, Copy)]
432 enum Kind {
433 Form(Form),
434 Ref(&'static str),
435 }
436
437 trait InnerFormFmt {
441 fn kind(self) -> Kind;
443 }
444
445 impl InnerFormFmt for Form {
446 fn kind(self) -> Kind {
447 Kind::Form(self)
448 }
449 }
450
451 impl InnerFormFmt for BuiltForm {
452 fn kind(self) -> Kind {
453 Kind::Form(self.0)
454 }
455 }
456
457 impl InnerFormFmt for &str {
458 fn kind(self) -> Kind {
459 Kind::Ref(self.to_string().leak())
460 }
461 }
462
463 impl InnerFormFmt for &mut str {
464 fn kind(self) -> Kind {
465 Kind::Ref(self.to_string().leak())
466 }
467 }
468
469 impl InnerFormFmt for String {
470 fn kind(self) -> Kind {
471 Kind::Ref(self.leak())
472 }
473 }
474}
475
476#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
487pub struct FormId(u16);
488
489impl FormId {
490 pub fn to_u16(self) -> u16 {
494 self.0
495 }
496}
497
498impl std::fmt::Debug for FormId {
499 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
500 write!(f, "FormId({})", name_of(*self))
501 }
502}
503
504#[derive(Clone, Copy, Debug, PartialEq, Eq)]
506pub struct Form {
507 pub style: ContentStyle,
508}
509
510#[rustfmt::skip]
511impl Form {
512 mimic_method_new!(bold Attribute::Bold);
513 mimic_method_new!(dim Attribute::Dim);
514 mimic_method_new!(italic Attribute::Italic);
515 mimic_method_new!(underlined Attribute::Underlined);
516 mimic_method_new!(double_underlined Attribute::DoubleUnderlined);
517 mimic_method_new!(undercurled Attribute::Undercurled);
518 mimic_method_new!(underdashed Attribute::Underdashed);
519 mimic_method_new!(reverse Attribute::Reverse);
520 mimic_method_new!(crossed_out Attribute::CrossedOut);
521 mimic_method_new!(black on_black underline_black Color::Black);
522 mimic_method_new!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
523 mimic_method_new!(red on_red underline_red Color::Red);
524 mimic_method_new!(dark_red on_dark_red underline_dark_red Color::DarkRed);
525 mimic_method_new!(green on_green underline_green Color::Green);
526 mimic_method_new!(
527 dark_green on_dark_green underline_dark_green Color::DarkGreen
528 );
529 mimic_method_new!(yellow on_yellow underline_yellow Color::Yellow);
530 mimic_method_new!(
531 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
532 );
533 mimic_method_new!(blue on_blue underline_blue Color::Blue);
534 mimic_method_new!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
535 mimic_method_new!(magenta on_magenta underline_magenta Color::Magenta);
536 mimic_method_new!(
537 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
538 );
539 mimic_method_new!(cyan on_cyan underline_cyan Color::Cyan);
540 mimic_method_new!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
541 mimic_method_new!(white on_white underline_white Color::White);
542 mimic_method_new!(grey on_grey underline_grey Color::Grey);
543}
544
545impl Form {
546 #[allow(clippy::new_ret_no_self)]
550 pub const fn new() -> BuiltForm {
551 let style = ContentStyle {
552 foreground_color: None,
553 background_color: None,
554 underline_color: None,
555 attributes: Attributes::none(),
556 };
557 BuiltForm(Self { style })
558 }
559
560 pub const fn reset() -> BuiltForm {
567 let mut built = Form::new();
568 built.0.style.attributes = built.0.style.attributes.with(Attribute::Reset);
569 built
570 }
571
572 pub const fn with(str: &str) -> BuiltForm {
582 let mut built = Form::new();
583 built.0.style.foreground_color = match str_to_color(str) {
584 Ok(color) => Some(color),
585 Err(err) => panic!("{}", err),
586 };
587 built
588 }
589
590 pub const fn on(str: &str) -> BuiltForm {
600 let mut built = Form::new();
601 built.0.style.background_color = match str_to_color(str) {
602 Ok(color) => Some(color),
603 Err(err) => panic!("{}", err),
604 };
605 built
606 }
607
608 pub const fn underline(str: &str) -> BuiltForm {
618 let mut built = Form::new();
619 built.0.style.underline_color = match str_to_color(str) {
620 Ok(color) => Some(color),
621 Err(err) => panic!("{}", err),
622 };
623 built
624 }
625
626 pub const fn fg(&self) -> Option<Color> {
628 self.style.foreground_color
629 }
630
631 pub const fn bg(&self) -> Option<Color> {
633 self.style.background_color
634 }
635
636 pub const fn ul(&self) -> Option<Color> {
638 self.style.underline_color
639 }
640
641 pub const fn attr(&self) -> Attributes {
643 self.style.attributes
644 }
645}
646
647pub struct BuiltForm(Form);
656
657#[rustfmt::skip]
658impl BuiltForm {
659 mimic_method_mod!(bold Attribute::Bold);
660 mimic_method_mod!(dim Attribute::Dim);
661 mimic_method_mod!(italic Attribute::Italic);
662 mimic_method_mod!(underlined Attribute::Underlined);
663 mimic_method_mod!(double_underlined Attribute::DoubleUnderlined);
664 mimic_method_mod!(undercurled Attribute::Undercurled);
665 mimic_method_mod!(underdashed Attribute::Underdashed);
666 mimic_method_mod!(reverse Attribute::Reverse);
667 mimic_method_mod!(crossed_out Attribute::CrossedOut);
668 mimic_method_mod!(overlined Attribute::OverLined);
669 mimic_method_mod!(black on_black underline_black Color::Black);
670 mimic_method_mod!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
671 mimic_method_mod!(red on_red underline_red Color::Red);
672 mimic_method_mod!(dark_red on_dark_red underline_dark_red Color::DarkRed);
673 mimic_method_mod!(green on_green underline_green Color::Green);
674 mimic_method_mod!(
675 dark_green on_dark_green underline_dark_green Color::DarkGreen
676 );
677 mimic_method_mod!(yellow on_yellow underline_yellow Color::Yellow);
678 mimic_method_mod!(
679 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
680 );
681 mimic_method_mod!(blue on_blue underline_blue Color::Blue);
682 mimic_method_mod!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
683 mimic_method_mod!(magenta on_magenta underline_magenta Color::Magenta);
684 mimic_method_mod!(
685 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
686 );
687 mimic_method_mod!(cyan on_cyan underline_cyan Color::Cyan);
688 mimic_method_mod!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
689 mimic_method_mod!(white on_white underline_white Color::White);
690 mimic_method_mod!(grey on_grey underline_grey Color::Grey);
691}
692
693impl BuiltForm {
694 pub const fn reset(mut self) -> BuiltForm {
701 self.0.style.attributes = self.0.style.attributes.with(Attribute::Reset);
702 self
703 }
704
705 pub const fn with(mut self, str: &str) -> Self {
715 self.0.style.foreground_color = match str_to_color(str) {
716 Ok(color) => Some(color),
717 Err(err) => panic!("{}", err),
718 };
719 self
720 }
721
722 pub const fn on(mut self, str: &str) -> Self {
732 self.0.style.background_color = match str_to_color(str) {
733 Ok(color) => Some(color),
734 Err(err) => panic!("{}", err),
735 };
736 self
737 }
738
739 pub const fn underline(mut self, str: &str) -> Self {
749 self.0.style.underline_color = match str_to_color(str) {
750 Ok(color) => Some(color),
751 Err(err) => panic!("{}", err),
752 };
753 self
754 }
755}
756
757impl std::ops::Deref for BuiltForm {
758 type Target = Form;
759
760 fn deref(&self) -> &Self::Target {
761 &self.0
762 }
763}
764
765impl std::ops::DerefMut for BuiltForm {
766 fn deref_mut(&mut self) -> &mut Self::Target {
767 &mut self.0
768 }
769}
770
771pub const DEFAULT_ID: FormId = FormId(0);
773pub const M_CUR_ID: FormId = FormId(8);
775pub const E_CUR_ID: FormId = FormId(9);
777pub const M_SEL_ID: FormId = FormId(10);
779pub const E_SEL_ID: FormId = FormId(11);
781pub const INACTIVE_ID: FormId = FormId(12);
783
784struct InnerPalette {
785 main_cursor: Option<CursorShape>,
786 extra_cursor: Option<CursorShape>,
787 forms: Vec<(&'static str, Form, FormType)>,
788}
789
790struct Palette(LazyLock<RwLock<InnerPalette>>);
792
793impl Palette {
794 const fn new() -> Self {
796 Self(LazyLock::new(|| {
797 let main_cursor = Some(CursorShape::DefaultUserShape);
798
799 RwLock::new(InnerPalette {
800 main_cursor,
801 extra_cursor: main_cursor,
802 forms: BASE_FORMS.to_vec(),
803 })
804 }))
805 }
806
807 fn set_form(&self, name: &'static str, form: Form) {
809 let mut inner = self.0.write();
810
811 let id = if let Some(i) = inner.forms.iter().position(|(cmp, ..)| *cmp == name) {
812 inner.forms[i] = (name, form, FormType::Normal);
813
814 for refed in refs_of(&inner, i, i) {
815 inner.forms[refed].1 = form;
816 }
817
818 if let Some(sender) = SENDER.get() {
819 sender.send_form_changed().unwrap()
820 }
821 FormId(i as u16)
822 } else {
823 inner.forms.push((name, form, FormType::Normal));
824 FormId(inner.forms.len() as u16 - 1)
825 };
826
827 hooks::trigger::<FormSet>((name, id, form));
828 }
829
830 fn set_weak_form(&self, name: &'static str, form: Form) {
832 let mut inner = self.0.write();
833
834 if let Some(i) = inner.forms.iter().position(|(cmp, ..)| *cmp == name) {
835 let (_, f, ty) = &mut inner.forms[i];
836 if let FormType::Weakest = ty {
837 *f = form;
838 *ty = FormType::Normal;
839
840 if let Some(sender) = SENDER.get() {
841 sender.send_form_changed().unwrap()
842 }
843 }
844 } else {
845 inner.forms.push((name, form, FormType::Normal));
846 let i = inner.forms.len() - 1;
847 for refed in refs_of(&inner, i, i) {
848 inner.forms[refed].1 = form;
849 }
850 }
851 }
852
853 fn set_ref(&self, name: &'static str, refed: impl AsRef<str>) {
855 let refed = {
856 let refed: &'static str = refed.as_ref().to_string().leak();
857 self.id_from_name(refed)
858 };
859
860 let mut inner = self.0.write();
861 let (_, form, _) = inner.forms[refed.0 as usize];
862
863 if let Some(i) = inner.forms.iter().position(|(cmp, ..)| *cmp == name) {
864 for refed in refs_of(&inner, i, i) {
865 inner.forms[refed].1 = form;
866 }
867
868 if would_be_circular(&inner, i, refed.0 as usize) {
870 inner.forms[i] = (name, form, FormType::Normal);
871 } else {
872 inner.forms[i] = (name, form, FormType::Ref(refed));
873 }
874
875 if let Some(sender) = SENDER.get() {
876 sender.send_form_changed().unwrap()
877 }
878 hooks::trigger::<FormSet>((name, FormId(i as u16), form));
879 } else {
880 inner.forms.push((name, form, FormType::Ref(refed)));
883 hooks::trigger::<FormSet>((name, FormId(inner.forms.len() as u16 - 1), form));
884 }
885 }
886
887 fn set_weak_ref(&self, name: &'static str, refed: impl AsRef<str>) {
889 let refed = {
890 let refed: &'static str = refed.as_ref().to_string().leak();
891 self.id_from_name(refed)
892 };
893
894 let mut inner = self.0.write();
895 let (_, form, _) = inner.forms[refed.0 as usize];
896
897 if let Some(i) = inner.forms.iter().position(|(cmp, ..)| *cmp == name) {
900 let (_, f, ty) = &mut inner.forms[i];
901 if let FormType::Weakest = ty {
902 *f = form;
903 *ty = FormType::Ref(refed);
904
905 if let Some(sender) = SENDER.get() {
906 sender.send_form_changed().unwrap()
907 }
908 }
909 } else {
910 inner.forms.push((name, form, FormType::Ref(refed)));
911 }
912 }
913
914 fn id_from_name(&self, name: &'static str) -> FormId {
918 let mut inner = self.0.write();
919
920 if let Some(id) = inner.forms.iter().position(|(cmp, ..)| *cmp == name) {
921 FormId(id as u16)
922 } else {
923 inner.forms.push((name, Form::new().0, FormType::Weakest));
924 FormId((inner.forms.len() - 1) as u16)
925 }
926 }
927
928 fn form_from_id(&self, id: FormId) -> Option<Form> {
930 let inner = self.0.read_recursive();
931 inner.forms.get(id.0 as usize).map(|(_, form, _)| *form)
932 }
933
934 fn name_from_id(&self, id: FormId) -> &'static str {
936 let inner = self.0.read_recursive();
937 let nth = inner.forms.get(id.0 as usize).map(|(name, ..)| name);
938
939 let Some(ret) = nth else {
940 unreachable!("Form with id {} not found, this should never happen", id.0);
941 };
942 ret
943 }
944
945 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
947 let form = self.form_from_id(M_CUR_ID).unwrap();
948 (form, self.0.read_recursive().main_cursor)
949 }
950
951 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
953 let form = self.form_from_id(E_CUR_ID).unwrap();
954 (form, self.0.read_recursive().extra_cursor)
955 }
956
957 fn set_main_cursor(&self, shape: CursorShape) {
959 self.0.write().main_cursor = Some(shape);
960 if let Some(sender) = SENDER.get() {
961 sender.send_form_changed().unwrap()
962 }
963 }
964
965 fn set_extra_cursor(&self, shape: CursorShape) {
967 self.0.write().extra_cursor = Some(shape);
968 if let Some(sender) = SENDER.get() {
969 sender.send_form_changed().unwrap()
970 }
971 }
972
973 fn unset_main_cursor(&self) {
975 self.0.write().main_cursor = None;
976 if let Some(sender) = SENDER.get() {
977 sender.send_form_changed().unwrap()
978 }
979 }
980
981 fn unset_extra_cursor(&self) {
983 self.0.write().extra_cursor = None;
984 if let Some(sender) = SENDER.get() {
985 sender.send_form_changed().unwrap()
986 }
987 }
988
989 fn painter(&'static self) -> Painter {
991 let inner = self.0.read();
992 let default = inner.forms[DEFAULT_ID.0 as usize].1;
993 Painter {
994 inner,
995 forms: vec![(default, DEFAULT_ID)],
996 reset_count: 0,
997 final_form_start: 1,
998 still_on_same_byte: false,
999 reset_is_needed: false,
1000 }
1001 }
1002}
1003
1004pub struct Painter {
1005 inner: RwLockReadGuard<'static, InnerPalette>,
1006 forms: Vec<(Form, FormId)>,
1007 reset_count: usize,
1008 final_form_start: usize,
1009 still_on_same_byte: bool,
1010 reset_is_needed: bool,
1011}
1012
1013impl Painter {
1014 #[inline(always)]
1022 pub fn apply(&mut self, id: FormId) -> ContentStyle {
1023 let i = id.0 as usize;
1024 let forms = &self.inner.forms;
1025 let form = forms.get(i).map(|(_, f, _)| *f).unwrap_or(Form::new().0);
1026
1027 self.reset_count += form.style.attributes.has(Attribute::Reset) as usize;
1028
1029 self.forms.insert(self.final_form_start, (form, id));
1030 if !(id == M_SEL_ID || id == E_SEL_ID) {
1031 self.final_form_start += 1;
1032 }
1033
1034 let mut style = self.make_style();
1035 if self.reset_is_needed || self.reset_count > 0 {
1036 self.still_on_same_byte = true;
1037 self.reset_is_needed = true;
1038 style.attributes.set(Attribute::Reset);
1039 } else if !self.still_on_same_byte {
1043 self.still_on_same_byte = true;
1044 style.foreground_color = form.fg().and(style.foreground_color.or(Some(Color::Reset)));
1045 style.background_color = form.bg().and(style.background_color.or(Some(Color::Reset)));
1046 style.underline_color = form.ul().and(style.underline_color.or(Some(Color::Reset)));
1047 }
1048 style
1049 }
1050
1051 #[inline(always)]
1054 pub fn remove(&mut self, id: FormId) -> ContentStyle {
1055 let mut applied_forms = self.forms.iter().enumerate();
1056 let Some((i, &(form, _))) = applied_forms.rfind(|(_, (_, i))| *i == id) else {
1057 return absolute_style(&self.forms);
1058 };
1059
1060 self.reset_count -= form.style.attributes.has(Attribute::Reset) as usize;
1061 self.forms.remove(i);
1062 if id != M_SEL_ID && id != E_SEL_ID {
1063 self.final_form_start -= 1;
1064 }
1065
1066 let mut style = self.make_style();
1067 if !form.style.attributes.is_empty() || self.reset_is_needed || self.reset_count > 0 {
1068 self.still_on_same_byte = true;
1069 self.reset_is_needed = true;
1070 style.attributes.set(Attribute::Reset);
1071 } else if !self.still_on_same_byte {
1075 self.still_on_same_byte = true;
1076 style.foreground_color = form.fg().and(style.foreground_color.or(Some(Color::Reset)));
1077 style.background_color = form.bg().and(style.background_color.or(Some(Color::Reset)));
1078 style.underline_color = form.ul().and(style.underline_color.or(Some(Color::Reset)));
1079 }
1080 style
1081 }
1082
1083 #[inline(always)]
1089 pub fn reset(&mut self) -> ContentStyle {
1090 self.forms.splice(1.., []);
1091 self.make_style()
1092 }
1093
1094 #[inline(always)]
1097 pub fn make_style(&self) -> ContentStyle {
1098 let mut style = ContentStyle::new();
1099
1100 for &(form, _) in &self.forms {
1101 style.foreground_color = form.fg().or(style.foreground_color);
1102 style.background_color = form.bg().or(style.background_color);
1103 style.underline_color = form.ul().or(style.underline_color);
1104 style.attributes = if form.attr().has(Attribute::Reset) {
1105 form.attr()
1106 } else {
1107 form.attr() | style.attributes
1108 }
1109 }
1110
1111 style
1112 }
1113
1114 #[inline(always)]
1115 pub fn apply_main_cursor(&mut self) -> ContentStyle {
1116 let style = self.apply(M_CUR_ID);
1117 self.final_form_start -= 1;
1118 style
1119 }
1120
1121 #[inline(always)]
1122 pub fn remove_main_cursor(&mut self) -> ContentStyle {
1123 let style = self.remove(M_CUR_ID);
1124 self.final_form_start += 1;
1125 style
1126 }
1127
1128 #[inline(always)]
1129 pub fn apply_extra_cursor(&mut self) -> ContentStyle {
1130 let style = self.apply(E_CUR_ID);
1131 self.final_form_start -= 1;
1132 style
1133 }
1134
1135 #[inline(always)]
1136 pub fn remove_extra_cursor(&mut self) -> ContentStyle {
1137 let style = self.remove(E_CUR_ID);
1138 self.final_form_start += 1;
1139 style
1140 }
1141
1142 pub fn confirm_printing(&mut self) {
1144 self.still_on_same_byte = false;
1145 self.reset_is_needed = false;
1146 }
1147
1148 pub fn main_cursor(&self) -> Option<CursorShape> {
1150 self.inner.main_cursor
1151 }
1152
1153 pub fn extra_cursor(&self) -> Option<CursorShape> {
1155 self.inner.extra_cursor
1156 }
1157
1158 pub fn get_default(&self) -> Form {
1160 self.forms[0].0
1161 }
1162}
1163
1164pub(crate) fn set_sender(sender: Sender) {
1165 SENDER
1166 .set(sender)
1167 .unwrap_or_else(|_| panic!("Sender set more than once"));
1168}
1169
1170#[derive(Debug, Clone)]
1172enum FormType {
1173 Normal,
1174 Ref(FormId),
1175 Weakest,
1176}
1177
1178fn refs_of(inner: &RwLockWriteGuard<InnerPalette>, refed: usize, top_ref: usize) -> Vec<usize> {
1180 let mut refs = Vec::new();
1181 for (i, (.., f_ty)) in inner.forms.iter().enumerate() {
1182 if let FormType::Ref(ref_id) = f_ty
1183 && ref_id.0 as usize == refed
1184 && ref_id.0 as usize != top_ref
1185 {
1186 refs.push(i);
1187 refs.extend(refs_of(inner, i, top_ref));
1188 }
1189 }
1190 refs
1191}
1192
1193fn would_be_circular(inner: &RwLockWriteGuard<InnerPalette>, referee: usize, refed: usize) -> bool {
1195 if let (.., FormType::Ref(refed_ref)) = inner.forms[refed] {
1196 match refed_ref.0 as usize == referee {
1197 true => true,
1198 false => would_be_circular(inner, referee, refed_ref.0 as usize),
1199 }
1200 } else {
1201 false
1202 }
1203}
1204
1205fn absolute_style(list: &[(Form, FormId)]) -> ContentStyle {
1207 let mut style = ContentStyle::new();
1208
1209 for &(form, _) in list {
1210 style.foreground_color = form.fg().or(style.foreground_color);
1211 style.background_color = form.bg().or(style.background_color);
1212 style.underline_color = form.ul().or(style.underline_color);
1213 style.attributes = if form.attr().has(Attribute::Reset) {
1214 form.attr()
1215 } else {
1216 form.attr() | style.attributes
1217 }
1218 }
1219
1220 style
1221}
1222
1223const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1225 use core::str::from_utf8_unchecked as utf8_str;
1226 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1227 let prefix = prefix.as_bytes();
1228 let str = str.as_bytes();
1229
1230 let mut i = 0;
1231 while i < prefix.len() {
1232 if str[i] != prefix[i] {
1233 return None;
1234 }
1235 i += 1;
1236 }
1237
1238 let (_, str) = str.split_at(prefix.len());
1239 Some(unsafe { utf8_str(str) })
1240 }
1241 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1242 let prefix = suffix.as_bytes();
1243 let str = str.as_bytes();
1244
1245 let mut i = str.len() - 1;
1246 while i >= str.len() - prefix.len() {
1247 if str[i] != prefix[i - (str.len() - prefix.len())] {
1248 return None;
1249 }
1250 i += 1;
1251 }
1252
1253 let (str, _) = str.split_at(str.len() - suffix.len());
1254 Some(unsafe { utf8_str(str) })
1255 }
1256 const fn split_space(str: &str) -> Option<(&str, &str)> {
1257 if str.is_empty() {
1258 return None;
1259 }
1260 let str = str.as_bytes();
1261
1262 let mut i = 0;
1263 while i < str.len() {
1264 if str[i] == b' ' {
1265 break;
1266 }
1267 i += 1;
1268 }
1269
1270 let (cut, rest) = str.split_at(i);
1271 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1272 Some(unsafe { (utf8_str(cut), utf8_str(rest)) })
1273 }
1274 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1275 t = if t < 0.0 { t + 1.0 } else { t };
1276 t = if t > 1.0 { t - 1.0 } else { t };
1277 if t < 1.0 / 6.0 {
1278 p + (q - p) * 6.0 * t
1279 } else if t < 1.0 / 2.0 {
1280 q
1281 } else if t < 2.0 / 3.0 {
1282 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1283 } else {
1284 p
1285 }
1286 }
1287
1288 if let Some(hex) = strip_prefix("#", str) {
1290 let total = match u32::from_str_radix(hex, 16) {
1291 Ok(total) if hex.len() == 6 => total,
1292 _ => return Err("Hexcode does not contain 6 hex values"),
1293 };
1294 let r = (total >> 16) as u8;
1295 let g = (total >> 8) as u8;
1296 let b = total as u8;
1297
1298 Ok(Color::Rgb { r, g, b })
1299 } else if let Some(mut rgb) = strip_prefix("rgb ", str) {
1301 let mut values = [0, 0, 0];
1302 let mut i = 0;
1303 while i < values.len() {
1304 if let Some((cut, rest)) = split_space(rgb) {
1305 rgb = rest;
1306 values[i] = match u8::from_str_radix(cut, 10) {
1307 Ok(value) => value,
1308 Err(_) => return Err("Rgb format value could not be parsed"),
1309 }
1310 } else {
1311 return Err("Missing value in rgb format");
1312 }
1313 i += 1;
1314 }
1315
1316 let [r, g, b] = values;
1317 Ok(Color::Rgb { r, g, b })
1318 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1320 let mut values = [0.0, 0.0, 0.0];
1321 let mut i = 0;
1322 while i < values.len() {
1323 if let Some((cut, rest)) = split_space(hsl) {
1324 hsl = rest;
1325 let (num, div) = match strip_suffix("%", cut) {
1326 Some(perc) => (perc, 100),
1327 None => (cut, 255),
1328 };
1329 values[i] = match u8::from_str_radix(num, 10) {
1330 Ok(value) if value <= div => value as f32 / div as f32,
1331 _ => return Err("Hsl format property could not be parsed"),
1332 }
1333 } else {
1334 return Err("Missing value in hsl format");
1335 }
1336 i += 1;
1337 }
1338 let [hue, sat, lit] = values;
1339
1340 let (r, g, b) = if sat == 0.0 {
1341 (lit, lit, lit)
1342 } else {
1343 let q = if lit < 0.5 {
1344 lit * (1.0 + sat)
1345 } else {
1346 lit + sat - lit * sat
1347 };
1348 let p = 2.0 * lit - q;
1349 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1350 let g = hue_to_rgb(p, q, hue);
1351 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1352 (r, g, b)
1353 };
1354
1355 let r = (0.5 + r * 255.0) as u8;
1357 let g = (0.5 + g * 255.0) as u8;
1358 let b = (0.5 + b * 255.0) as u8;
1359 Ok(Color::Rgb { r, g, b })
1360 } else {
1361 return Err("Color format was not recognized");
1362 }
1363}
1364
1365macro mimic_method_new {
1367 (#[$attr:meta] $method:ident $attrib:expr) => {
1368 #[$attr]
1370 pub const fn $method() -> BuiltForm {
1372 let mut built = Form::new();
1373 built.0.style.attributes = built.0.style.attributes.with($attrib);
1374 built
1375 }
1376 },
1377
1378 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1379 #[$attr]
1381 pub const fn $fg() -> BuiltForm {
1383 let mut built = Form::new();
1384 built.0.style.foreground_color = Some($color);
1385 built
1386 }
1387
1388 #[$attr]
1390 pub const fn $bg() -> BuiltForm {
1392 let mut built = Form::new();
1393 built.0.style.background_color = Some($color);
1394 built
1395 }
1396
1397 #[$attr]
1399 pub const fn $ul() -> BuiltForm {
1405 let mut built = Form::new();
1406 built.0.style.underline_color = Some($color);
1407 built
1408 }
1409 }
1410}
1411
1412macro mimic_method_mod {
1413 (#[$attr:meta] $method:ident $attrib:expr) => {
1414 #[$attr]
1416 pub const fn $method(mut self) -> Self {
1418 self.0.style.attributes = self.0.style.attributes.with($attrib);
1419 self
1420 }
1421 },
1422
1423 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1424 #[$attr]
1426 pub const fn $fg(mut self) -> Self {
1427 self.0.style.foreground_color = Some($color);
1428 self
1429 }
1430
1431 #[$attr]
1433 pub const fn $bg(mut self) -> Self {
1434 self.0.style.background_color = Some($color);
1435 self
1436 }
1437
1438 #[$attr]
1440 pub const fn $ul(mut self) -> Self {
1445 self.0.style.underline_color = Some($color);
1446 self
1447 }
1448 }
1449}