1use std::sync::{OnceLock, RwLock, RwLockReadGuard};
3
4use FormType::*;
5use crossterm::style::{Attribute, Attributes, ContentStyle};
6pub use crossterm::{cursor::SetCursorStyle as CursorShape, style::Color};
7
8pub use self::global::*;
9pub(crate) use self::global::{colorscheme_exists, exists};
10use crate::{
11 hook::{self, FormSet},
12 text::FormTag,
13 ui::Sender,
14};
15
16pub trait ColorScheme: Send + Sync + 'static {
18 fn apply(&self);
27
28 fn name(&self) -> &'static str;
30}
31
32static SENDER: OnceLock<Sender> = OnceLock::new();
33static BASE_FORMS: &[(&str, Form, FormType)] = &[
34 ("default", Form::new().0, Normal),
35 ("accent", Form::bold().0, Normal),
36 ("caret.main", Form::reverse().0, Normal),
37 ("caret.extra", Form::reverse().0, Ref(M_CAR_ID.0 as usize)),
38 ("selection.main", Form::white().on_dark_grey().0, Normal),
39 (
40 "selection.extra",
41 Form::white().on_dark_grey().0,
42 Ref(M_SEL_ID.0 as usize),
43 ),
44 ("cloak", Form::grey().on_black().0, Normal),
45];
46
47mod global {
49 use std::{
50 any::TypeId,
51 collections::HashMap,
52 sync::{LazyLock, Mutex, OnceLock, mpsc},
53 thread,
54 time::Duration,
55 };
56
57 use super::{BASE_FORMS, BuiltForm, ColorScheme, CursorShape, Form, FormId, Painter, Palette};
58 use crate::{
59 context,
60 hook::{self, ColorSchemeSet},
61 };
62
63 static PALETTE: OnceLock<&'static Palette> = OnceLock::new();
64 static FORMS: OnceLock<&'static Mutex<Vec<&str>>> = OnceLock::new();
65 static COLORSCHEMES: LazyLock<Mutex<Vec<Box<dyn ColorScheme>>>> = LazyLock::new(Mutex::default);
66
67 pub trait FormFmt: InnerFormFmt {}
75 impl FormFmt for Form {}
76 impl FormFmt for BuiltForm {}
77 impl FormFmt for &str {}
78 impl FormFmt for &mut str {}
79 impl FormFmt for String {}
80
81 pub fn set(name: impl ToString, form: impl FormFmt) -> FormId {
104 let kind = form.kind();
105 let name: &'static str = name.to_string().leak();
106
107 match kind {
108 Kind::Form(form) => queue(move || PALETTE.get().unwrap().set_form(name, form)),
109 Kind::Ref(refed) => queue(move || PALETTE.get().unwrap().set_ref(name, refed)),
110 };
111
112 let mut forms = FORMS.get().unwrap().lock().unwrap();
113 if let Kind::Ref(refed) = kind {
114 position_of_name(&mut forms, refed);
115 }
116 FormId(position_of_name(&mut forms, name) as u16)
117 }
118
119 pub fn set_weak(name: impl ToString, form: impl FormFmt) -> FormId {
145 let kind = form.kind();
146 let name: &'static str = name.to_string().leak();
147
148 match kind {
149 Kind::Form(form) => queue(move || PALETTE.get().unwrap().set_weak_form(name, form)),
150 Kind::Ref(refed) => queue(move || PALETTE.get().unwrap().set_weak_ref(name, refed)),
151 };
152
153 let mut forms = FORMS.get().unwrap().lock().unwrap();
154 if let Kind::Ref(refed) = kind {
155 position_of_name(&mut forms, refed);
156 }
157 FormId(position_of_name(&mut forms, name) as u16)
158 }
159
160 pub fn from_id(id: FormId) -> Form {
162 PALETTE
163 .get()
164 .unwrap()
165 .form_from_id(id)
166 .unwrap_or(Form::new().0)
167 }
168
169 pub fn main_cursor() -> (Form, Option<CursorShape>) {
171 PALETTE.get().unwrap().main_cursor()
172 }
173
174 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
176 PALETTE.get().unwrap().extra_cursor()
177 }
178
179 pub fn set_main_cursor(shape: CursorShape) {
203 queue(move || PALETTE.get().unwrap().set_main_cursor(shape));
204 }
205
206 pub fn set_extra_cursor(shape: CursorShape) {
230 queue(move || PALETTE.get().unwrap().set_extra_cursor(shape));
231 }
232
233 pub fn unset_main_cursor() {
244 queue(move || PALETTE.get().unwrap().unset_main_cursor());
245 }
246
247 pub fn unset_extra_cursor() {
261 queue(move || PALETTE.get().unwrap().unset_extra_cursor());
262 }
263
264 pub fn unset_cursors() {
271 queue(move || {
272 PALETTE.get().unwrap().unset_main_cursor();
273 PALETTE.get().unwrap().unset_extra_cursor();
274 })
275 }
276
277 pub(crate) fn painter_with_mask<W: ?Sized + 'static>(mask: &'static str) -> Painter {
279 PALETTE
280 .get()
281 .unwrap()
282 .painter(default_id(TypeId::of::<W>(), crate::duat_name::<W>()), mask)
283 }
284
285 pub fn enable_mask(mask: &'static str) {
344 queue(move || {
345 let mut inner = PALETTE.get().unwrap().0.write().unwrap();
346 if !inner.masks.iter().any(|(m, _)| *m == mask) {
347 let mut remaps: Vec<u16> = (0..inner.forms.len() as u16).collect();
348
349 for (i, (name, ..)) in inner.forms.iter().enumerate() {
350 if let Some((pref, suf)) = name.rsplit_once('.')
351 && suf == mask
352 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
353 {
354 remaps[j] = i as u16;
355 }
356 }
357
358 inner.masks.push((mask, remaps));
359 }
360 })
361 }
362
363 pub macro id_of {
393 ($form:expr) => {{
394 use $crate::form::FormId;
395
396 static ID: std::sync::OnceLock<FormId> = std::sync::OnceLock::new();
397 *ID.get_or_init(|| {
398 let name: &'static str = $form;
399 let id = id_from_name(name);
400 add_forms(vec![name]);
401 id
402 })
403 }},
404 ($($form:expr),+) => {{
405 static IDS: std::sync::OnceLock<&[FormId]> = std::sync::OnceLock::new();
406 let ids = *IDS.get_or_init(|| {
407 let mut ids = Vec::new();
408 let names = vec![$( $form ),+];
409 for name in names.iter() {
410 ids.push(id_from_name(name));
411 }
412 add_forms(names);
413 ids.leak()
414 });
415 ids
416 }}
417 }
418
419 pub fn id_of_non_static(name: impl ToString) -> FormId {
426 let name = name.to_string().leak();
427
428 let mut forms = FORMS.get().unwrap().lock().unwrap();
429 let id = FormId(position_of_name(&mut forms, name) as u16);
430 add_forms(vec![name]);
431 id
432 }
433
434 pub fn ids_of_non_static(names: impl IntoIterator<Item = impl ToString>) -> Vec<FormId> {
441 let names: Vec<&str> = names
442 .into_iter()
443 .map(|n| {
444 let str: &'static str = n.to_string().leak();
445 str
446 })
447 .collect();
448
449 let mut ids = Vec::new();
450 let mut forms = FORMS.get().unwrap().lock().unwrap();
451 for name in names.iter() {
452 ids.push(FormId(position_of_name(&mut forms, name) as u16));
453 }
454 add_forms(names);
455 ids
456 }
457
458 #[doc(hidden)]
460 pub fn id_from_name(name: &'static str) -> FormId {
461 let mut forms = FORMS.get().unwrap().lock().unwrap();
462 FormId(position_of_name(&mut forms, name) as u16)
463 }
464
465 #[doc(hidden)]
466 pub fn add_forms(names: Vec<&'static str>) {
467 queue(move || PALETTE.get().unwrap().set_many(names.as_ref()));
468 }
469
470 pub fn add_colorscheme(cs: impl ColorScheme) {
481 let mut colorschemes = COLORSCHEMES.lock().unwrap();
482 let name = cs.name();
483 if let Some(i) = colorschemes.iter().position(|cs| cs.name() == name) {
484 colorschemes[i] = Box::new(cs);
485 } else {
486 colorschemes.push(Box::new(cs));
487 }
488 }
489
490 pub fn set_colorscheme(name: &str) {
497 let colorschemes = COLORSCHEMES.lock().unwrap();
498 if let Some(cs) = colorschemes.iter().find(|cs| cs.name() == name) {
499 cs.apply();
500 hook::queue(ColorSchemeSet(cs.name()));
501 } else {
502 context::error!("The colorscheme [a]{name}[] was not found");
503 }
504 }
505
506 pub macro set_many($(($name:literal, $form:expr)),+ $(,)?) {{
510 $(
511 set($name, $form);
512 )+
513 }}
514
515 pub(crate) fn exists(name: &str) -> bool {
517 FORMS.get().unwrap().lock().unwrap().contains(&name)
518 }
519
520 pub(crate) fn colorscheme_exists(name: &str) -> bool {
522 COLORSCHEMES
523 .lock()
524 .unwrap()
525 .iter()
526 .any(|cs| cs.name() == name)
527 }
528
529 pub(super) fn name_of(id: FormId) -> &'static str {
531 FORMS.get().unwrap().lock().unwrap()[id.0 as usize]
532 }
533
534 fn default_id(type_id: TypeId, type_name: &'static str) -> FormId {
535 static IDS: LazyLock<Mutex<HashMap<TypeId, FormId>>> = LazyLock::new(Mutex::default);
536 let mut ids = IDS.lock().unwrap();
537
538 if let Some(id) = ids.get(&type_id) {
539 *id
540 } else {
541 let name: &'static str = format!("default.{type_name}").leak();
542 let id = id_from_name(name);
543 add_forms(vec![name]);
544 ids.insert(type_id, id);
545 id
546 }
547 }
548
549 fn position_of_name(names: &mut Vec<&'static str>, name: &'static str) -> usize {
550 if let Some((i, _)) = names.iter().enumerate().find(|(_, rhs)| **rhs == name) {
551 i
552 } else if let Some((refed, _)) = name.rsplit_once('.') {
553 position_of_name(names, refed);
554 names.push(name);
555 names.len() - 1
556 } else {
557 names.push(name);
558 names.len() - 1
559 }
560 }
561
562 fn queue<R>(f: impl FnOnce() -> R + Send + Sync + 'static) {
563 static SENDER: Mutex<Option<mpsc::Sender<Box<dyn FnOnce() + Send + Sync>>>> =
564 Mutex::new(None);
565
566 if context::will_reload_or_quit() {
567 return;
568 }
569
570 let f = Box::new(move || {
571 f();
572 });
573
574 let mut sender = SENDER.lock().unwrap();
575 let f = if let Some(tx) = sender.as_ref() {
576 let Err(err) = tx.send(f) else {
577 return;
578 };
579 err.0
580 } else {
581 f
582 };
583 let (tx, rx) = mpsc::channel();
584 tx.send(f).unwrap();
585 *sender = Some(tx);
586
587 thread::spawn(move || {
588 while let Ok(f) = rx.recv_timeout(Duration::from_micros(500)) {
589 f();
590 }
591 });
592 }
593
594 #[doc(hidden)]
598 pub fn get_initial() -> (&'static Mutex<Vec<&'static str>>, &'static Palette) {
599 let forms = Box::leak(Box::new(Mutex::new(
600 BASE_FORMS.iter().map(|(n, ..)| *n).collect(),
601 )));
602 let palette = Box::leak(Box::new(Palette::new()));
603 (forms, palette)
604 }
605
606 #[doc(hidden)]
610 pub fn set_initial((forms, palette): (&'static Mutex<Vec<&'static str>>, &'static Palette)) {
611 FORMS.set(forms).expect("Forms setup ran twice");
612 PALETTE.set(palette).expect("Forms setup ran twice");
613 }
614
615 #[doc(hidden)]
619 pub fn clear() {
620 *FORMS.get().unwrap().lock().unwrap() = BASE_FORMS.iter().map(|(n, ..)| *n).collect();
621 PALETTE.get().unwrap().reset();
622 }
623
624 #[derive(Clone, Copy)]
626 enum Kind {
627 Form(Form),
628 Ref(&'static str),
629 }
630
631 trait InnerFormFmt {
635 fn kind(self) -> Kind;
637 }
638
639 impl InnerFormFmt for Form {
640 fn kind(self) -> Kind {
641 Kind::Form(self)
642 }
643 }
644
645 impl InnerFormFmt for BuiltForm {
646 fn kind(self) -> Kind {
647 Kind::Form(self.0)
648 }
649 }
650
651 impl InnerFormFmt for &str {
652 fn kind(self) -> Kind {
653 Kind::Ref(self.to_string().leak())
654 }
655 }
656
657 impl InnerFormFmt for &mut str {
658 fn kind(self) -> Kind {
659 Kind::Ref(self.to_string().leak())
660 }
661 }
662
663 impl InnerFormFmt for String {
664 fn kind(self) -> Kind {
665 Kind::Ref(self.leak())
666 }
667 }
668}
669
670#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
684pub struct FormId(u16);
685
686impl FormId {
687 pub const fn to_tag(self, prio: u8) -> FormTag {
696 FormTag(self, prio)
697 }
698
699 pub const fn to_u16(self) -> u16 {
703 self.0
704 }
705
706 pub fn name(self) -> &'static str {
708 name_of(self)
709 }
710}
711
712impl std::fmt::Debug for FormId {
713 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714 write!(f, "FormId({})", name_of(*self))
715 }
716}
717
718#[derive(Clone, Copy, PartialEq, Eq)]
720pub struct Form {
721 pub style: ContentStyle,
723}
724
725#[rustfmt::skip]
726impl Form {
727 mimic_method_new!(bold Attribute::Bold);
728 mimic_method_new!(dim Attribute::Dim);
729 mimic_method_new!(italic Attribute::Italic);
730 mimic_method_new!(underlined Attribute::Underlined);
731 mimic_method_new!(double_underlined Attribute::DoubleUnderlined);
732 mimic_method_new!(undercurled Attribute::Undercurled);
733 mimic_method_new!(underdashed Attribute::Underdashed);
734 mimic_method_new!(reverse Attribute::Reverse);
735 mimic_method_new!(crossed_out Attribute::CrossedOut);
736 mimic_method_new!(black on_black underline_black Color::Black);
737 mimic_method_new!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
738 mimic_method_new!(red on_red underline_red Color::Red);
739 mimic_method_new!(dark_red on_dark_red underline_dark_red Color::DarkRed);
740 mimic_method_new!(green on_green underline_green Color::Green);
741 mimic_method_new!(
742 dark_green on_dark_green underline_dark_green Color::DarkGreen
743 );
744 mimic_method_new!(yellow on_yellow underline_yellow Color::Yellow);
745 mimic_method_new!(
746 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
747 );
748 mimic_method_new!(blue on_blue underline_blue Color::Blue);
749 mimic_method_new!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
750 mimic_method_new!(magenta on_magenta underline_magenta Color::Magenta);
751 mimic_method_new!(
752 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
753 );
754 mimic_method_new!(cyan on_cyan underline_cyan Color::Cyan);
755 mimic_method_new!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
756 mimic_method_new!(white on_white underline_white Color::White);
757 mimic_method_new!(grey on_grey underline_grey Color::Grey);
758}
759
760impl Form {
761 #[allow(clippy::new_ret_no_self)]
765 pub const fn new() -> BuiltForm {
766 let style = ContentStyle {
767 foreground_color: None,
768 background_color: None,
769 underline_color: None,
770 attributes: Attributes::none(),
771 };
772 BuiltForm(Self { style })
773 }
774
775 pub const fn reset() -> BuiltForm {
782 let mut built = Form::new();
783 built.0.style.attributes = built.0.style.attributes.with(Attribute::Reset);
784 built
785 }
786
787 pub const fn with(str: &str) -> BuiltForm {
797 let mut built = Form::new();
798 built.0.style.foreground_color = match str_to_color(str) {
799 Ok(color) => Some(color),
800 Err(err) => panic!("{}", err),
801 };
802 built
803 }
804
805 pub const fn on(str: &str) -> BuiltForm {
815 let mut built = Form::new();
816 built.0.style.background_color = match str_to_color(str) {
817 Ok(color) => Some(color),
818 Err(err) => panic!("{}", err),
819 };
820 built
821 }
822
823 pub const fn underline(str: &str) -> BuiltForm {
833 let mut built = Form::new();
834 built.0.style.underline_color = match str_to_color(str) {
835 Ok(color) => Some(color),
836 Err(err) => panic!("{}", err),
837 };
838 built
839 }
840
841 pub const fn fg(&self) -> Option<Color> {
843 self.style.foreground_color
844 }
845
846 pub const fn bg(&self) -> Option<Color> {
848 self.style.background_color
849 }
850
851 pub const fn ul(&self) -> Option<Color> {
853 self.style.underline_color
854 }
855
856 pub const fn attrs(&self) -> Attributes {
858 self.style.attributes
859 }
860}
861
862#[derive(Clone, Copy, Debug)]
871pub struct BuiltForm(Form);
872
873#[rustfmt::skip]
874impl BuiltForm {
875 mimic_method_mod!(bold Attribute::Bold);
876 mimic_method_mod!(dim Attribute::Dim);
877 mimic_method_mod!(italic Attribute::Italic);
878 mimic_method_mod!(underlined Attribute::Underlined);
879 mimic_method_mod!(double_underlined Attribute::DoubleUnderlined);
880 mimic_method_mod!(undercurled Attribute::Undercurled);
881 mimic_method_mod!(underdashed Attribute::Underdashed);
882 mimic_method_mod!(reverse Attribute::Reverse);
883 mimic_method_mod!(crossed_out Attribute::CrossedOut);
884 mimic_method_mod!(overlined Attribute::OverLined);
885 mimic_method_mod!(black on_black underline_black Color::Black);
886 mimic_method_mod!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
887 mimic_method_mod!(red on_red underline_red Color::Red);
888 mimic_method_mod!(dark_red on_dark_red underline_dark_red Color::DarkRed);
889 mimic_method_mod!(green on_green underline_green Color::Green);
890 mimic_method_mod!(
891 dark_green on_dark_green underline_dark_green Color::DarkGreen
892 );
893 mimic_method_mod!(yellow on_yellow underline_yellow Color::Yellow);
894 mimic_method_mod!(
895 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
896 );
897 mimic_method_mod!(blue on_blue underline_blue Color::Blue);
898 mimic_method_mod!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
899 mimic_method_mod!(magenta on_magenta underline_magenta Color::Magenta);
900 mimic_method_mod!(
901 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
902 );
903 mimic_method_mod!(cyan on_cyan underline_cyan Color::Cyan);
904 mimic_method_mod!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
905 mimic_method_mod!(white on_white underline_white Color::White);
906 mimic_method_mod!(grey on_grey underline_grey Color::Grey);
907}
908
909impl BuiltForm {
910 pub const fn reset(mut self) -> BuiltForm {
917 self.0.style.attributes = self.0.style.attributes.with(Attribute::Reset);
918 self
919 }
920
921 pub const fn with(mut self, str: &str) -> Self {
931 self.0.style.foreground_color = match str_to_color(str) {
932 Ok(color) => Some(color),
933 Err(err) => panic!("{}", err),
934 };
935 self
936 }
937
938 pub const fn on(mut self, str: &str) -> Self {
948 self.0.style.background_color = match str_to_color(str) {
949 Ok(color) => Some(color),
950 Err(err) => panic!("{}", err),
951 };
952 self
953 }
954
955 pub const fn underline(mut self, str: &str) -> Self {
965 self.0.style.underline_color = match str_to_color(str) {
966 Ok(color) => Some(color),
967 Err(err) => panic!("{}", err),
968 };
969 self
970 }
971}
972
973impl std::ops::Deref for BuiltForm {
974 type Target = Form;
975
976 fn deref(&self) -> &Self::Target {
977 &self.0
978 }
979}
980
981impl std::ops::DerefMut for BuiltForm {
982 fn deref_mut(&mut self) -> &mut Self::Target {
983 &mut self.0
984 }
985}
986
987impl From<BuiltForm> for Form {
988 fn from(value: BuiltForm) -> Self {
989 value.0
990 }
991}
992
993pub const DEFAULT_ID: FormId = FormId(0);
995pub const ACCENT_ID: FormId = FormId(1);
997pub const M_CAR_ID: FormId = FormId(2);
999pub const E_CAR_ID: FormId = FormId(3);
1001pub const M_SEL_ID: FormId = FormId(4);
1003pub const E_SEL_ID: FormId = FormId(5);
1005
1006struct InnerPalette {
1007 main_cursor: Option<CursorShape>,
1008 extra_cursor: Option<CursorShape>,
1009 forms: Vec<(&'static str, Form, FormType)>,
1010 masks: Vec<(&'static str, Vec<u16>)>,
1011}
1012
1013#[derive(Debug)]
1017#[doc(hidden)]
1018pub struct Palette(RwLock<InnerPalette>);
1019
1020impl Palette {
1021 fn new() -> Self {
1023 let main_cursor = Some(CursorShape::DefaultUserShape);
1024 Self(RwLock::new(InnerPalette {
1025 main_cursor,
1026 extra_cursor: main_cursor,
1027 forms: BASE_FORMS.to_vec(),
1028 masks: vec![("", (0..BASE_FORMS.len() as u16).collect())],
1029 }))
1030 }
1031
1032 fn set_form(&self, name: &'static str, form: Form) {
1034 let mut inner = self.0.write().unwrap();
1035 let (i, _) = position_and_form(&mut inner.forms, name);
1036
1037 inner.forms[i] = (name, form, FormType::Normal);
1038
1039 for refed in refs_of(&inner, i) {
1040 inner.forms[refed].1 = form;
1041 }
1042
1043 if let Some(sender) = SENDER.get() {
1044 sender.send_form_changed().unwrap()
1045 }
1046
1047 mask_form(name, i, &mut inner);
1048 hook::queue(FormSet((name, FormId(i as u16), form)));
1049 }
1050
1051 fn set_weak_form(&self, name: &'static str, form: Form) {
1053 let mut inner = self.0.write().unwrap();
1054 let (i, _) = position_and_form(&mut inner.forms, name);
1055
1056 let (_, f, f_ty) = &mut inner.forms[i];
1057 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
1058 *f = form;
1059 *f_ty = FormType::Normal;
1060
1061 if let Some(sender) = SENDER.get() {
1062 sender.send_form_changed().unwrap()
1063 }
1064 for refed in refs_of(&inner, i) {
1065 inner.forms[refed].1 = form;
1066 }
1067
1068 mask_form(name, i, &mut inner);
1069 }
1070 }
1071
1072 fn set_ref(&self, name: &'static str, refed: &'static str) {
1074 let mut inner = self.0.write().unwrap();
1075 let (refed, form) = position_and_form(&mut inner.forms, refed);
1076 let (i, _) = position_and_form(&mut inner.forms, name);
1077
1078 for refed in refs_of(&inner, i) {
1079 inner.forms[refed].1 = form;
1080 }
1081
1082 if would_be_circular(&inner, i, refed) {
1084 inner.forms[i] = (name, form, FormType::Normal);
1085 } else {
1086 inner.forms[i] = (name, form, FormType::Ref(refed));
1087 }
1088
1089 if let Some(sender) = SENDER.get() {
1090 sender.send_form_changed().unwrap()
1091 }
1092
1093 mask_form(name, i, &mut inner);
1094 hook::queue(FormSet((name, FormId(i as u16), form)));
1095 }
1096
1097 fn set_weak_ref(&self, name: &'static str, refed: &'static str) {
1099 let mut inner = self.0.write().unwrap();
1100 let (refed, form) = position_and_form(&mut inner.forms, refed);
1101 let (i, _) = position_and_form(&mut inner.forms, name);
1102
1103 let (_, f, f_ty) = &mut inner.forms[i];
1106 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
1107 *f = form;
1108 *f_ty = FormType::WeakestRef(refed);
1109
1110 if let Some(sender) = SENDER.get() {
1111 sender.send_form_changed().unwrap()
1112 }
1113 for refed in refs_of(&inner, i) {
1114 inner.forms[refed].1 = form;
1115 }
1116
1117 mask_form(name, i, &mut inner);
1118 }
1119 }
1120
1121 fn set_many(&self, names: &[&'static str]) {
1123 let mut inner = self.0.write().unwrap();
1124 let form_indices: Vec<(usize, &str)> = names
1125 .iter()
1126 .map(|name| {
1127 let (i, _) = position_and_form(&mut inner.forms, name);
1128 (i, *name)
1129 })
1130 .collect();
1131
1132 for (i, name) in form_indices {
1133 mask_form(name, i, &mut inner);
1134 }
1135 }
1136
1137 fn form_from_id(&self, id: FormId) -> Option<Form> {
1139 let inner = self.0.read().unwrap();
1140 inner.forms.get(id.0 as usize).map(|(_, form, _)| *form)
1141 }
1142
1143 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
1145 let form = self.form_from_id(M_CAR_ID).unwrap();
1146 (form, self.0.read().unwrap().main_cursor)
1147 }
1148
1149 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
1151 let form = self.form_from_id(E_CAR_ID).unwrap();
1152 (form, self.0.read().unwrap().extra_cursor)
1153 }
1154
1155 fn set_main_cursor(&self, shape: CursorShape) {
1157 self.0.write().unwrap().main_cursor = Some(shape);
1158 if let Some(sender) = SENDER.get() {
1159 sender.send_form_changed().unwrap()
1160 }
1161 }
1162
1163 fn set_extra_cursor(&self, shape: CursorShape) {
1165 self.0.write().unwrap().extra_cursor = Some(shape);
1166 if let Some(sender) = SENDER.get() {
1167 sender.send_form_changed().unwrap()
1168 }
1169 }
1170
1171 fn unset_main_cursor(&self) {
1173 self.0.write().unwrap().main_cursor = None;
1174 if let Some(sender) = SENDER.get() {
1175 sender.send_form_changed().unwrap()
1176 }
1177 }
1178
1179 fn unset_extra_cursor(&self) {
1181 self.0.write().unwrap().extra_cursor = None;
1182 if let Some(sender) = SENDER.get() {
1183 sender.send_form_changed().unwrap()
1184 }
1185 }
1186
1187 fn painter(&'static self, default_id: FormId, mask: &str) -> Painter {
1189 let inner = self.0.read().unwrap();
1190 let mask_i = inner
1191 .masks
1192 .iter()
1193 .position(|(m, _)| *m == mask)
1194 .unwrap_or_default();
1195
1196 let default = inner
1197 .forms
1198 .get(match inner.masks[mask_i].1.get(default_id.0 as usize) {
1199 Some(i) => *i as usize,
1200 None => default_id.0 as usize,
1201 })
1202 .map(|(_, f, _)| *f)
1203 .unwrap_or(Form::new().0);
1204
1205 Painter {
1206 inner,
1207 mask_i,
1208 default,
1209 forms: Vec::new(),
1210 set_fg: true,
1211 set_bg: true,
1212 set_ul: true,
1213 reset_attrs: false,
1214 }
1215 }
1216
1217 fn reset(&self) {
1218 let main_cursor = Some(CursorShape::DefaultUserShape);
1219 *self.0.write().unwrap() = InnerPalette {
1220 main_cursor,
1221 extra_cursor: main_cursor,
1222 forms: BASE_FORMS.to_vec(),
1223 masks: vec![("", (0..BASE_FORMS.len() as u16).collect())],
1224 };
1225 }
1226}
1227
1228fn mask_form(name: &'static str, form_i: usize, inner: &mut InnerPalette) {
1230 if inner.masks[0].1.len() < inner.forms.len() {
1231 for (_, remaps) in inner.masks.iter_mut() {
1232 remaps.extend(remaps.len() as u16..inner.forms.len() as u16);
1233 }
1234 }
1235
1236 if let Some((pref, mask)) = name.rsplit_once(".")
1237 && let Some((_, remaps)) = inner.masks.iter_mut().find(|(m, _)| *m == mask)
1238 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
1239 {
1240 remaps[j] = form_i as u16;
1241 }
1242}
1243
1244pub struct Painter {
1302 inner: RwLockReadGuard<'static, InnerPalette>,
1303 mask_i: usize,
1304 default: Form,
1305 forms: Vec<(Form, FormId, u8)>,
1306 set_fg: bool,
1307 set_bg: bool,
1308 set_ul: bool,
1309 reset_attrs: bool,
1310}
1311
1312impl Painter {
1313 #[inline(always)]
1321 pub fn apply(&mut self, id: FormId, prio: u8) {
1322 let (_, mask) = &self.inner.masks[self.mask_i];
1323 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1324
1325 let forms = &self.inner.forms;
1326 let form = forms
1327 .get(id.0 as usize)
1328 .map(|(_, f, _)| *f)
1329 .unwrap_or(Form::new().0);
1330
1331 let gt = |(.., p): &&(_, _, u8)| *p > prio;
1332 let i = self.forms.len() - self.forms.iter().rev().take_while(gt).count();
1333 self.forms.insert(i, (form, id, prio));
1334
1335 self.set_fg |= form.fg().is_some();
1336 self.set_bg |= form.bg().is_some();
1337 self.set_ul |= form.ul().is_some();
1338 self.reset_attrs |= form.attrs().has(Attribute::Reset);
1339 }
1340
1341 #[inline(always)]
1344 pub fn remove(&mut self, id: FormId) {
1345 let mask = &self.inner.masks[self.mask_i].1;
1346 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1347
1348 let mut applied_forms = self.forms.iter().enumerate();
1349 if let Some((i, &(form, ..))) = applied_forms.rfind(|(_, (_, lhs, _))| *lhs == id) {
1350 self.forms.remove(i);
1351
1352 self.set_fg |= form.fg().is_some();
1353 self.set_bg |= form.bg().is_some();
1354 self.set_ul |= form.ul().is_some();
1355 self.reset_attrs |= !form.attrs().is_empty();
1356 };
1357 }
1358
1359 #[inline(always)]
1365 pub fn reset(&mut self) -> ContentStyle {
1366 self.forms.clear();
1367 self.absolute_style()
1368 }
1369
1370 #[inline(always)]
1375 pub fn absolute_style(&self) -> ContentStyle {
1376 let mut style = self.default.style;
1377
1378 for &(form, ..) in &self.forms {
1379 style.foreground_color = form.fg().or(style.foreground_color);
1380 style.background_color = form.bg().or(style.background_color);
1381 style.underline_color = form.ul().or(style.underline_color);
1382 style.attributes = if form.attrs().has(Attribute::Reset) {
1383 form.attrs()
1384 } else {
1385 form.attrs() | style.attributes
1386 }
1387 }
1388
1389 style
1390 }
1391
1392 #[inline(always)]
1404 pub fn relative_style(&mut self) -> ContentStyle {
1405 let mut style = self.absolute_style();
1406
1407 if style.attributes.has(Attribute::Reset) || self.reset_attrs {
1408 style.attributes.set(Attribute::Reset);
1409 } else {
1413 style.foreground_color = self
1414 .set_fg
1415 .then_some(style.foreground_color.unwrap_or(Color::Reset));
1416 style.background_color = self
1417 .set_bg
1418 .then_some(style.background_color.unwrap_or(Color::Reset));
1419 style.underline_color = self
1420 .set_ul
1421 .then_some(style.underline_color.unwrap_or(Color::Reset));
1422 }
1423
1424 self.set_fg = false;
1425 self.set_bg = false;
1426 self.set_ul = false;
1427 self.reset_attrs = false;
1428
1429 style
1430 }
1431
1432 #[inline(always)]
1434 pub fn apply_main_cursor(&mut self) {
1435 self.apply(M_CAR_ID, 100);
1436 }
1437
1438 #[inline(always)]
1440 pub fn remove_main_caret(&mut self) {
1441 self.remove(M_CAR_ID);
1442 }
1443
1444 #[inline(always)]
1446 pub fn apply_extra_cursor(&mut self) {
1447 self.apply(E_CAR_ID, 100);
1448 }
1449
1450 #[inline(always)]
1452 pub fn remove_extra_caret(&mut self) {
1453 self.remove(E_CAR_ID);
1454 }
1455
1456 pub fn main_cursor(&self) -> Option<CursorShape> {
1458 self.inner.main_cursor
1459 }
1460
1461 pub fn extra_cursor(&self) -> Option<CursorShape> {
1463 self.inner.extra_cursor
1464 }
1465
1466 pub fn get_default(&self) -> Form {
1468 self.default
1469 }
1470}
1471
1472pub(crate) fn set_sender(sender: Sender) {
1473 SENDER
1474 .set(sender)
1475 .unwrap_or_else(|_| panic!("Sender set more than once"));
1476}
1477
1478#[derive(Clone)]
1480enum FormType {
1481 Normal,
1482 Ref(usize),
1483 Weakest,
1484 WeakestRef(usize),
1485}
1486
1487fn refs_of(inner: &InnerPalette, refed: usize) -> Vec<usize> {
1489 let mut refs = Vec::new();
1490 for (i, (.., f_ty)) in inner.forms.iter().enumerate() {
1491 if let FormType::Ref(ref_id) | FormType::WeakestRef(ref_id) = f_ty
1492 && *ref_id == refed
1493 {
1494 refs.push(i);
1495 refs.extend(refs_of(inner, i));
1496 }
1497 }
1498 refs
1499}
1500
1501fn would_be_circular(inner: &InnerPalette, referee: usize, refed: usize) -> bool {
1503 if let (.., FormType::Ref(refed_ref) | FormType::WeakestRef(refed_ref)) = inner.forms[refed] {
1504 match refed_ref == referee {
1505 true => true,
1506 false => would_be_circular(inner, referee, refed_ref),
1507 }
1508 } else {
1509 false
1510 }
1511}
1512
1513fn position_and_form(forms: &mut Vec<(&str, Form, FormType)>, name: &'static str) -> (usize, Form) {
1514 if let Some((i, (_, form, _))) = forms.iter().enumerate().find(|(_, (lhs, ..))| *lhs == name) {
1515 (i, *form)
1516 } else if let Some((refed, _)) = name.rsplit_once('.') {
1517 let (i, form) = position_and_form(forms, refed);
1518 forms.push((name, form, FormType::WeakestRef(i)));
1519 (forms.len() - 1, form)
1520 } else {
1521 forms.push((name, Form::new().0, FormType::Weakest));
1522 (forms.len() - 1, Form::new().0)
1523 }
1524}
1525
1526const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1528 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1529 let prefix = prefix.as_bytes();
1530
1531 let mut i = 0;
1532 while i < prefix.len() {
1533 if str.as_bytes()[i] != prefix[i] {
1534 return None;
1535 }
1536 i += 1;
1537 }
1538
1539 Some(str.split_at(prefix.len()).1)
1540 }
1541 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1542 let prefix = suffix.as_bytes();
1543
1544 let mut i = str.len() - 1;
1545 while i >= str.len() - prefix.len() {
1546 if str.as_bytes()[i] != prefix[i - (str.len() - prefix.len())] {
1547 return None;
1548 }
1549 i += 1;
1550 }
1551
1552 Some(str.split_at(str.len() - suffix.len()).0)
1553 }
1554 const fn split_space(str: &str) -> Option<(&str, &str)> {
1555 if str.is_empty() {
1556 return None;
1557 }
1558
1559 let mut i = 0;
1560 while i < str.len() {
1561 if str.as_bytes()[i] == b' ' {
1562 break;
1563 }
1564 i += 1;
1565 }
1566
1567 let (cut, rest) = str.split_at(i);
1568 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1569 Some((cut, rest))
1570 }
1571 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1572 t = if t < 0.0 { t + 1.0 } else { t };
1573 t = if t > 1.0 { t - 1.0 } else { t };
1574 if t < 1.0 / 6.0 {
1575 p + (q - p) * 6.0 * t
1576 } else if t < 1.0 / 2.0 {
1577 q
1578 } else if t < 2.0 / 3.0 {
1579 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1580 } else {
1581 p
1582 }
1583 }
1584
1585 if let Some(hex) = strip_prefix("#", str) {
1587 let total = match u32::from_str_radix(hex, 16) {
1588 Ok(total) if hex.len() == 6 => total,
1589 _ => return Err("Hexcode does not contain 6 hex values"),
1590 };
1591 let r = (total >> 16) as u8;
1592 let g = (total >> 8) as u8;
1593 let b = total as u8;
1594
1595 Ok(Color::Rgb { r, g, b })
1596 } else if let Some(mut rgb) = strip_prefix("rgb ", str) {
1598 let mut values = [0, 0, 0];
1599 let mut i = 0;
1600
1601 while i < values.len() {
1602 if let Some((cut, rest)) = split_space(rgb) {
1603 rgb = rest;
1604 values[i] = match u8::from_str_radix(cut, 10) {
1605 Ok(value) => value,
1606 Err(_) => return Err("Rgb format value could not be parsed"),
1607 }
1608 } else {
1609 return Err("Missing value in rgb format");
1610 }
1611 i += 1;
1612 }
1613
1614 let [r, g, b] = values;
1615 Ok(Color::Rgb { r, g, b })
1616 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1618 let mut values = [0.0, 0.0, 0.0];
1619 let mut i = 0;
1620 while i < values.len() {
1621 if let Some((cut, rest)) = split_space(hsl) {
1622 hsl = rest;
1623 let (num, div) = match strip_suffix("%", cut) {
1624 Some(perc) => (perc, 100),
1625 None => (cut, 255),
1626 };
1627 values[i] = match u8::from_str_radix(num, 10) {
1628 Ok(value) if value <= div => value as f32 / div as f32,
1629 _ => return Err("Hsl format property could not be parsed"),
1630 }
1631 } else {
1632 return Err("Missing value in hsl format");
1633 }
1634 i += 1;
1635 }
1636 let [hue, sat, lit] = values;
1637
1638 let (r, g, b) = if sat == 0.0 {
1639 (lit, lit, lit)
1640 } else {
1641 let q = if lit < 0.5 {
1642 lit * (1.0 + sat)
1643 } else {
1644 lit + sat - lit * sat
1645 };
1646 let p = 2.0 * lit - q;
1647 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1648 let g = hue_to_rgb(p, q, hue);
1649 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1650 (r, g, b)
1651 };
1652
1653 let r = (0.5 + r * 255.0) as u8;
1655 let g = (0.5 + g * 255.0) as u8;
1656 let b = (0.5 + b * 255.0) as u8;
1657 Ok(Color::Rgb { r, g, b })
1658 } else {
1659 Err("Color format was not recognized")
1660 }
1661}
1662
1663impl std::fmt::Debug for Form {
1664 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1665 struct DebugColor(Option<Color>);
1666 impl std::fmt::Debug for DebugColor {
1667 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1668 match self.0 {
1669 Some(Color::Rgb { r, g, b }) => write!(f, "Some(Rgb({r}, {g}, {b}))"),
1670 Some(Color::AnsiValue(ansi)) => write!(f, "Some(Ansi({ansi}))"),
1671 Some(color) => write!(f, "Some({color:?})"),
1672 None => f.write_str("None"),
1673 }
1674 }
1675 }
1676
1677 struct DebugAttributes(Attributes);
1678 impl std::fmt::Debug for DebugAttributes {
1679 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1680 if self.0.is_empty() {
1681 f.write_str("None")
1682 } else {
1683 let mut is_first = true;
1684 for attr in Attribute::iterator() {
1685 if self.0.has(attr) {
1686 if !is_first {
1687 f.write_str(" | ")?;
1688 }
1689 is_first = false;
1690 write!(f, "{attr:?}")?;
1691 }
1692 }
1693 Ok(())
1694 }
1695 }
1696 }
1697
1698 f.debug_struct("Form")
1699 .field("fg", &DebugColor(self.style.foreground_color))
1700 .field("bg", &DebugColor(self.style.background_color))
1701 .field("ul", &DebugColor(self.style.underline_color))
1702 .field("attr", &DebugAttributes(self.style.attributes))
1703 .finish()
1704 }
1705}
1706
1707impl std::fmt::Debug for InnerPalette {
1708 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1709 struct DebugForms<'a>(&'a [(&'static str, Form, FormType)]);
1710 impl std::fmt::Debug for DebugForms<'_> {
1711 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1712 if f.alternate() {
1713 f.write_str("[\n")?;
1714 let max = self.0.len().ilog10() as usize + 3;
1715 for (n, (name, form, ty)) in self.0.iter().enumerate() {
1716 let num = format!("{n}:");
1717 writeln!(f, "{num:<max$}({name}, {ty:?}, {form:#?})")?;
1718 }
1719 f.write_str("]")
1720 } else {
1721 write!(f, "{:?}", self.0)
1722 }
1723 }
1724 }
1725
1726 struct DebugCursorShape(CursorShape);
1727 impl std::fmt::Debug for DebugCursorShape {
1728 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1729 match self.0 {
1730 CursorShape::DefaultUserShape => f.write_str("DefaultUserShape"),
1731 CursorShape::BlinkingBlock => f.write_str("BlinkingBlock"),
1732 CursorShape::SteadyBlock => f.write_str("SteadyBlock"),
1733 CursorShape::BlinkingUnderScore => f.write_str("BlinkingUnderScore"),
1734 CursorShape::SteadyUnderScore => f.write_str("SteadyUnderScore"),
1735 CursorShape::BlinkingBar => f.write_str("BlinkingBar"),
1736 CursorShape::SteadyBar => f.write_str("SteadyBar"),
1737 }
1738 }
1739 }
1740
1741 f.debug_struct("InnerPalette")
1742 .field("main_cursor", &self.main_cursor.map(DebugCursorShape))
1743 .field("extra_cursor", &self.extra_cursor.map(DebugCursorShape))
1744 .field("forms", &DebugForms(&self.forms))
1745 .field("masks", &self.masks)
1746 .finish()
1747 }
1748}
1749
1750impl std::fmt::Debug for FormType {
1751 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1752 match self {
1753 Self::Normal => write!(f, "Normal"),
1754 Self::Ref(refed) => write!(f, "Ref({refed})"),
1755 Self::Weakest => write!(f, "Weakest"),
1756 Self::WeakestRef(refed) => write!(f, "WeakestRef({refed})"),
1757 }
1758 }
1759}
1760
1761macro mimic_method_new {
1763 (#[$attr:meta] $method:ident $attrib:expr) => {
1764 #[$attr]
1766 pub const fn $method() -> BuiltForm {
1768 let mut built = Form::new();
1769 built.0.style.attributes = built.0.style.attributes.with($attrib);
1770 built
1771 }
1772 },
1773
1774 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1775 #[$attr]
1777 pub const fn $fg() -> BuiltForm {
1779 let mut built = Form::new();
1780 built.0.style.foreground_color = Some($color);
1781 built
1782 }
1783
1784 #[$attr]
1786 pub const fn $bg() -> BuiltForm {
1788 let mut built = Form::new();
1789 built.0.style.background_color = Some($color);
1790 built
1791 }
1792
1793 #[$attr]
1795 pub const fn $ul() -> BuiltForm {
1801 let mut built = Form::new();
1802 built.0.style.underline_color = Some($color);
1803 built
1804 }
1805 }
1806}
1807
1808macro mimic_method_mod {
1809 (#[$attr:meta] $method:ident $attrib:expr) => {
1810 #[$attr]
1812 pub const fn $method(mut self) -> Self {
1814 self.0.style.attributes = self.0.style.attributes.with($attrib);
1815 self
1816 }
1817 },
1818
1819 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1820 #[$attr]
1822 pub const fn $fg(mut self) -> Self {
1823 self.0.style.foreground_color = Some($color);
1824 self
1825 }
1826
1827 #[$attr]
1829 pub const fn $bg(mut self) -> Self {
1830 self.0.style.background_color = Some($color);
1831 self
1832 }
1833
1834 #[$attr]
1836 pub const fn $ul(mut self) -> Self {
1841 self.0.style.underline_color = Some($color);
1842 self
1843 }
1844 }
1845}