1use std::sync::{RwLock, RwLockReadGuard};
3
4use FormKind::*;
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 context::{self, sender},
12 hook::{self, FormSet},
13 session::DuatEvent,
14 text::FormTag,
15};
16
17static BASE_FORMS: &[(&str, Form)] = &[
18 ("default", Form::new()),
19 ("accent", Form::new().bold()),
20 ("caret.main", Form::new().reverse()),
21 ("caret.extra", Form {
22 kind: Ref(2, default_style()),
23 ..Form::new().reverse()
24 }),
25 ("selection.main", Form::new().white().on_dark_grey()),
26 ("selection.extra", Form::new().white().on_grey()),
27 ("cloak", Form::new().grey().on_black()),
28 ("character.control", Form::new().grey()),
29 ("param.path", Form::new().yellow()),
30 ("param.path.exists", Form {
31 kind: Ref(8, ContentStyle {
32 attributes: Attributes::none().with(Attribute::Underlined),
33 ..default_style()
34 }),
35 ..Form::new().yellow().underlined()
36 }),
37 ("replace", Form::new().grey()),
38];
39
40mod global {
42 use std::{
43 any::TypeId,
44 collections::HashMap,
45 sync::{Arc, LazyLock, Mutex},
46 };
47
48 use super::{CursorShape, Form, FormId, Painter, Palette};
49 #[doc(inline)]
50 pub use crate::__id_of__ as id_of;
51 use crate::{
52 context,
53 form::{FormKind, MaskId},
54 hook::{self, ColorschemeSet},
55 };
56
57 static PALETTE: LazyLock<Palette> = LazyLock::new(Palette::new);
58 static COLORSCHEMES: LazyLock<Mutex<HashMap<Arc<str>, ColorschemeFn>>> =
59 LazyLock::new(Mutex::default);
60
61 pub fn set(name: impl ToString, form: Form) -> FormId {
83 let name = name.to_string();
84 let cloned_name = name.clone();
85
86 match form.kind {
87 FormKind::Normal => PALETTE.set_form(cloned_name, form),
88 FormKind::Ref(refed, style) => PALETTE.set_ref(cloned_name, refed, style),
89 _ => unreachable!(),
90 }
91 }
92
93 pub fn set_weak(name: impl ToString, form: Form) -> FormId {
118 let name = name.to_string();
119 let cloned_name = name.clone();
120
121 match form.kind {
122 FormKind::Normal => PALETTE.set_weak_form(cloned_name, form),
123 FormKind::Ref(refed, style) => PALETTE.set_weak_ref(cloned_name, refed, style),
124 _ => unreachable!(),
125 }
126 }
127
128 pub fn from_id(id: FormId) -> Form {
130 PALETTE.form_from_id(id).unwrap_or_default()
131 }
132
133 pub fn main_cursor() -> (Form, Option<CursorShape>) {
135 PALETTE.main_cursor()
136 }
137
138 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
140 PALETTE.extra_cursor()
141 }
142
143 pub fn set_main_cursor(shape: CursorShape) {
166 PALETTE.set_main_cursor(shape);
167 }
168
169 pub fn set_extra_cursor(shape: CursorShape) {
192 PALETTE.set_extra_cursor(shape);
193 }
194
195 pub fn unset_main_cursor() {
206 PALETTE.unset_main_cursor();
207 }
208
209 pub fn unset_extra_cursor() {
223 PALETTE.unset_extra_cursor();
224 }
225
226 pub fn unset_cursors() {
233 PALETTE.unset_main_cursor();
234 PALETTE.unset_extra_cursor();
235 }
236
237 pub fn painter() -> Painter {
252 PALETTE.painter(super::DEFAULT_ID)
253 }
254
255 pub(crate) fn painter_with_widget<W: ?Sized + 'static>() -> Painter {
257 PALETTE.painter(default_id(
258 TypeId::of::<W>(),
259 crate::utils::duat_name::<W>(),
260 ))
261 }
262
263 pub fn enable_mask(mask: impl AsRef<str> + Send + Sync + 'static) {
320 let mask = mask.as_ref();
321 let mut inner = PALETTE.0.write().unwrap();
322 if !inner.masks.iter().any(|(m, _)| *m == mask) {
323 let mut remaps: Vec<u16> = (0..inner.forms.len() as u16).collect();
324
325 for (i, (name, ..)) in inner.forms.iter().enumerate() {
326 if let Some((pref, suf)) = name.rsplit_once('.')
327 && suf == mask
328 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
329 {
330 remaps[j] = i as u16;
331 }
332 }
333
334 inner.masks.push((mask.to_string().leak(), remaps));
335 }
336 }
337
338 pub(crate) fn mask_id_for(mask: &'static str) -> Option<MaskId> {
340 let inner = PALETTE.0.read().unwrap();
341 Some(MaskId(
342 inner.masks.iter().position(|(m, _)| *m == mask)? as u32
343 ))
344 }
345
346 #[macro_export]
380 #[doc(hidden)]
381 macro_rules! __id_of__ {
382 ($form:expr) => {{
383 use $crate::form::{DEFAULT_ID, FormId, set_many};
384
385 static mut WAS_SET: bool = false;
386 static mut ID: FormId = DEFAULT_ID;
387 if unsafe { WAS_SET } {
388 unsafe { ID }
389 } else {
390 let name = $form.to_string();
391 let id = set_many([(name, None)])[0];
392 unsafe {
393 ID = id;
394 WAS_SET = true;
395 }
396 id
397 }
398 }};
399 }
400
401 pub fn id_of_non_static(name: impl ToString) -> FormId {
408 let name = name.to_string();
409 set_many([(name, None)])[0]
410 }
411
412 pub fn ids_of_non_static(names: impl IntoIterator<Item = impl ToString>) -> Vec<FormId> {
419 set_many(names.into_iter().map(|n| (n.to_string(), None)))
420 }
421
422 #[doc(hidden)]
424 pub fn set_many<S: AsRef<str>>(
425 sets: impl IntoIterator<Item = (S, Option<Form>)>,
426 ) -> Vec<FormId> {
427 PALETTE.set_many(&Vec::from_iter(sets))
428 }
429
430 pub fn add_colorscheme(
443 name: impl ToString,
444 pairs: impl FnMut() -> Vec<(String, Form)> + Send + 'static,
445 ) {
446 let name = name.to_string();
447 COLORSCHEMES
448 .lock()
449 .unwrap()
450 .insert(Arc::from(name), Box::new(pairs));
451 }
452
453 pub fn set_colorscheme(name: &str) {
460 let name = name.to_string();
461 let mut colorschemes = COLORSCHEMES.lock().unwrap();
462 if let Some(pairs_fn) = colorschemes.get_mut(name.as_str()) {
463 let Some(pairs) = crate::utils::catch_panic(pairs_fn) else {
464 context::error!("Failed to set [a]{name}[] colorscheme");
465 return;
466 };
467
468 set_many(pairs.iter().cloned().map(|(name, form)| (name, Some(form))));
469 context::queue(move |pa| {
470 _ = hook::trigger(pa, ColorschemeSet((name.to_string(), pairs)))
471 });
472 } else {
473 context::error!("The colorscheme [a]{name}[] was not found");
474 }
475 }
476
477 pub fn colorscheme_list() -> Vec<String> {
479 let mut list = Vec::from_iter(
480 COLORSCHEMES
481 .lock()
482 .unwrap()
483 .keys()
484 .map(|name| name.to_string()),
485 );
486 list.sort_unstable();
487 list
488 }
489
490 pub(crate) fn exists(name: &str) -> bool {
492 let palette = PALETTE.0.read().unwrap();
493 palette.forms.iter().any(|(n, _)| *n == name)
494 }
495
496 pub(crate) fn colorscheme_exists(name: &str) -> bool {
498 COLORSCHEMES.lock().unwrap().contains_key(name)
499 }
500
501 pub(super) fn name_of_form(id: FormId) -> &'static str {
503 PALETTE.0.read().unwrap().forms[id.0 as usize].0
504 }
505
506 pub(super) fn name_of_mask(id: MaskId) -> &'static str {
508 PALETTE.0.read().unwrap().masks[id.0 as usize].0
509 }
510
511 fn default_id(type_id: TypeId, type_name: &'static str) -> FormId {
513 static IDS: LazyLock<Mutex<HashMap<TypeId, FormId>>> = LazyLock::new(Mutex::default);
514 let mut ids = IDS.lock().unwrap();
515
516 if let Some(id) = ids.get(&type_id) {
517 *id
518 } else {
519 let name = format!("default.{type_name}");
520 let id = set_many(vec![(name, None)])[0];
521 ids.insert(type_id, id);
522 id
523 }
524 }
525
526 type ColorschemeFn = Box<dyn FnMut() -> Vec<(String, Form)> + Send>;
527}
528
529#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
543pub struct FormId(u16);
544
545impl FormId {
546 pub const fn to_tag(self, prio: u8) -> FormTag {
555 FormTag { id: self, priority: prio }
556 }
557
558 pub const fn to_u16(self) -> u16 {
562 self.0
563 }
564
565 pub fn name(self) -> &'static str {
567 name_of_form(self)
568 }
569}
570
571impl std::fmt::Debug for FormId {
572 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
573 write!(f, "FormId({}: {})", self.0, name_of_form(*self))
574 }
575}
576
577macro_rules! mimic_method {
579 (#[$attr:meta] $method:ident $attrib:expr) => {
580 #[$attr]
582 pub const fn $method(mut self) -> Form {
584 self.style.attributes = self.style.attributes.with($attrib);
585 self
586 }
587 };
588 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
589 #[$attr]
591 pub const fn $fg(mut self) -> Form {
593 self.style.foreground_color = Some($color);
594 self
595 }
596
597 #[$attr]
599 pub const fn $bg(mut self) -> Form {
601 self.style.background_color = Some($color);
602 self
603 }
604
605 #[$attr]
607 pub const fn $ul(mut self) -> Form {
616 self.style.underline_color = Some($color);
617 self
618 }
619 };
620}
621
622#[derive(Default, Clone, Copy)]
624pub struct Form {
625 pub style: ContentStyle,
627 kind: FormKind,
628}
629
630#[rustfmt::skip]
631impl Form {
632 mimic_method!(bold Attribute::Bold);
633 mimic_method!(dim Attribute::Dim);
634 mimic_method!(italic Attribute::Italic);
635 mimic_method!(underlined Attribute::Underlined);
636 mimic_method!(double_underlined Attribute::DoubleUnderlined);
637 mimic_method!(undercurled Attribute::Undercurled);
638 mimic_method!(underdashed Attribute::Underdashed);
639 mimic_method!(reverse Attribute::Reverse);
640 mimic_method!(crossed_out Attribute::CrossedOut);
641 mimic_method!(black on_black underline_black Color::Black);
642 mimic_method!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
643 mimic_method!(red on_red underline_red Color::Red);
644 mimic_method!(dark_red on_dark_red underline_dark_red Color::DarkRed);
645 mimic_method!(green on_green underline_green Color::Green);
646 mimic_method!(
647 dark_green on_dark_green underline_dark_green Color::DarkGreen
648 );
649 mimic_method!(yellow on_yellow underline_yellow Color::Yellow);
650 mimic_method!(
651 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
652 );
653 mimic_method!(blue on_blue underline_blue Color::Blue);
654 mimic_method!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
655 mimic_method!(magenta on_magenta underline_magenta Color::Magenta);
656 mimic_method!(
657 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
658 );
659 mimic_method!(cyan on_cyan underline_cyan Color::Cyan);
660 mimic_method!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
661 mimic_method!(white on_white underline_white Color::White);
662 mimic_method!(grey on_grey underline_grey Color::Grey);
663}
664
665impl Form {
666 pub const fn new() -> Form {
668 Self {
669 style: default_style(),
670 kind: FormKind::Normal,
671 }
672 }
673
674 pub fn of(form_name: impl AsRef<str>) -> Self {
676 let mut form = from_id(id_of_non_static(form_name.as_ref()));
677 form.kind = FormKind::Normal;
678 form
679 }
680
681 pub fn mimic(form_name: impl AsRef<str>) -> Self {
697 let id = id_of_non_static(form_name.as_ref());
698 let mut form = from_id(id);
699 form.kind = FormKind::Ref(id.0, default_style());
700 form
701 }
702
703 pub const fn reset(mut self) -> Self {
710 self.style.attributes = self.style.attributes.with(Attribute::Reset);
711
712 if let FormKind::Ref(_, style) = &mut self.kind {
713 style.attributes = style.attributes.with(Attribute::Reset);
714 }
715
716 self
717 }
718
719 #[track_caller]
732 pub const fn with(mut self, color: &str) -> Self {
733 self.style.foreground_color = match str_to_color(color) {
734 Ok(color) => Some(color),
735 Err(_) => panic!("Ill-formed color"),
736 };
737
738 if let FormKind::Ref(_, style) = &mut self.kind {
739 style.foreground_color = self.style.foreground_color;
740 }
741
742 self
743 }
744
745 #[track_caller]
758 pub const fn on(mut self, color: &str) -> Self {
759 self.style.background_color = match str_to_color(color) {
760 Ok(color) => Some(color),
761 Err(_) => panic!("Ill-formed color"),
762 };
763
764 if let FormKind::Ref(_, style) = &mut self.kind {
765 style.background_color = self.style.background_color;
766 }
767
768 self
769 }
770
771 #[track_caller]
787 pub const fn with_on(mut self, color: &str) -> Self {
788 let color = match str_to_color(color) {
789 Ok(color) => color,
790 Err(_) => panic!("Ill-formed color"),
791 };
792
793 self.style.background_color = Some(color);
794 self.style.foreground_color = Some(color);
795
796 if let FormKind::Ref(_, style) = &mut self.kind {
797 style.background_color = self.style.background_color;
798 style.foreground_color = self.style.foreground_color;
799 }
800
801 self
802 }
803
804 #[track_caller]
821 pub fn underline(mut self, color: &str) -> Self {
822 self.style.underline_color = match str_to_color(color) {
823 Ok(color) => Some(color),
824 Err(_) => panic!("Ill-formed color"),
825 };
826
827 if let FormKind::Ref(_, style) = &mut self.kind {
828 style.underline_color = self.style.underline_color;
829 }
830
831 self
832 }
833
834 #[track_caller]
859 pub const fn interpolate(mut self, other: Self, factor: u8) -> Self {
860 const fn interpolate(color: Color, other: Color, factor: u8) -> Color {
861 if let (Color::Rgb { r, g, b }, Color::Rgb { r: or, g: og, b: ob }) = (color, other) {
862 let factor = factor as usize;
863 Color::Rgb {
864 r: ((r as usize * factor + or as usize * (100 - factor)) / 100) as u8,
865 g: ((g as usize * factor + og as usize * (100 - factor)) / 100) as u8,
866 b: ((b as usize * factor + ob as usize * (100 - factor)) / 100) as u8,
867 }
868 } else {
869 color
870 }
871 }
872
873 assert!(factor <= 100, "factor must be between 0 and 100");
874
875 if let (Some(other_fg), Some(self_fg)) = (other.fg(), &mut self.style.foreground_color) {
876 *self_fg = interpolate(*self_fg, other_fg, factor);
877 if let FormKind::Ref(_, style) = &mut self.kind {
878 style.foreground_color = self.style.foreground_color;
879 }
880 }
881 if let (Some(other_bg), Some(self_bg)) = (other.bg(), &mut self.style.background_color) {
882 *self_bg = interpolate(*self_bg, other_bg, factor);
883 if let FormKind::Ref(_, style) = &mut self.kind {
884 style.background_color = self.style.background_color;
885 }
886 }
887 if let (Some(other_ul), Some(self_ul)) = (other.ul(), &mut self.style.underline_color) {
888 *self_ul = interpolate(*self_ul, other_ul, factor);
889 if let FormKind::Ref(_, style) = &mut self.kind {
890 style.underline_color = self.style.underline_color;
891 }
892 }
893
894 self
895 }
896
897 const fn fg(&self) -> Option<Color> {
899 self.style.foreground_color
900 }
901
902 const fn bg(&self) -> Option<Color> {
904 self.style.background_color
905 }
906
907 const fn ul(&self) -> Option<Color> {
909 self.style.underline_color
910 }
911
912 const fn attrs(&self) -> Attributes {
914 self.style.attributes
915 }
916}
917
918impl PartialEq for Form {
919 fn eq(&self, other: &Self) -> bool {
920 self.style == other.style
921 }
922}
923
924impl Eq for Form {}
925
926#[derive(Debug)]
930#[doc(hidden)]
931pub struct Palette(RwLock<InnerPalette>);
932
933impl Palette {
934 fn new() -> Self {
936 let main_cursor = Some(CursorShape::DefaultUserShape);
937 Self(RwLock::new(InnerPalette {
938 main_cursor,
939 extra_cursor: main_cursor,
940 forms: BASE_FORMS.iter().map(|(str, form)| (*str, *form)).collect(),
941 masks: vec![("", (0..BASE_FORMS.len() as u16).collect())],
942 }))
943 }
944
945 fn set_form(&self, name: impl AsRef<str>, form: Form) -> FormId {
947 let name = name.as_ref();
948 self.0.write().unwrap().set_form(name, form)
949 }
950
951 fn set_weak_form(&self, name: impl AsRef<str>, form: Form) -> FormId {
953 let name = name.as_ref();
954 self.0.write().unwrap().set_weak_form(name, form)
955 }
956
957 fn set_ref(&self, name: impl AsRef<str>, refed: u16, override_style: ContentStyle) -> FormId {
959 let name = name.as_ref();
960 self.0.write().unwrap().set_ref(name, refed, override_style)
961 }
962
963 fn set_weak_ref(
965 &self,
966 name: impl AsRef<str>,
967 refed: u16,
968 override_style: ContentStyle,
969 ) -> FormId {
970 let name = name.as_ref();
971 let mut inner_palette = self.0.write().unwrap();
972 inner_palette.set_weak_ref(name, refed, override_style)
973 }
974
975 fn set_many<S: AsRef<str>>(&self, sets: &[(S, Option<Form>)]) -> Vec<FormId> {
977 let mut inner = self.0.write().unwrap();
978 let mut ids = Vec::new();
979
980 for (name, form) in sets {
981 let Some(form) = *form else {
982 let (idx, _) = position_and_form(&mut inner.forms, name);
983 ids.push(FormId(idx as u16));
984 continue;
985 };
986
987 ids.push(match form.kind {
988 FormKind::Normal => inner.set_form(name.as_ref(), form),
989 FormKind::Ref(refed, style) => inner.set_ref(name.as_ref(), refed, style),
990 FormKind::Weakest => inner.set_weak_form(name.as_ref(), form),
991 FormKind::WeakestRef(refed, style) => {
992 inner.set_weak_ref(name.as_ref(), refed, style)
993 }
994 });
995 }
996
997 ids
998 }
999
1000 fn form_from_id(&self, id: FormId) -> Option<Form> {
1002 let inner = self.0.read().unwrap();
1003 inner.forms.get(id.0 as usize).map(|(_, form)| *form)
1004 }
1005
1006 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
1008 let form = self.form_from_id(M_CAR_ID).unwrap();
1009 (form, self.0.read().unwrap().main_cursor)
1010 }
1011
1012 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
1014 let form = self.form_from_id(E_CAR_ID).unwrap();
1015 (form, self.0.read().unwrap().extra_cursor)
1016 }
1017
1018 fn set_main_cursor(&self, shape: CursorShape) {
1020 self.0.write().unwrap().main_cursor = Some(shape);
1021 sender().send(DuatEvent::FormChange);
1022 }
1023
1024 fn set_extra_cursor(&self, shape: CursorShape) {
1026 self.0.write().unwrap().extra_cursor = Some(shape);
1027 sender().send(DuatEvent::FormChange);
1028 }
1029
1030 fn unset_main_cursor(&self) {
1032 self.0.write().unwrap().main_cursor = None;
1033 sender().send(DuatEvent::FormChange);
1034 }
1035
1036 fn unset_extra_cursor(&self) {
1038 self.0.write().unwrap().extra_cursor = None;
1039 sender().send(DuatEvent::FormChange);
1040 }
1041
1042 fn painter(&'static self, default_id: FormId) -> Painter {
1044 let inner = self.0.read().unwrap();
1045
1046 let default = inner
1047 .forms
1048 .get(default_id.0 as usize)
1049 .map(|(_, f)| *f)
1050 .unwrap_or_default();
1051
1052 Painter {
1053 inner,
1054 applied_masks: vec![0],
1055 default: (default, default_id),
1056 forms: Vec::new(),
1057 set_fg: true,
1058 set_bg: true,
1059 set_ul: true,
1060 reset_attrs: true,
1061 prev_style: None,
1062 }
1063 }
1064}
1065
1066struct InnerPalette {
1067 main_cursor: Option<CursorShape>,
1068 extra_cursor: Option<CursorShape>,
1069 forms: Vec<(&'static str, Form)>,
1070 masks: Vec<(&'static str, Vec<u16>)>,
1071}
1072
1073impl InnerPalette {
1074 fn set_form(&mut self, name: &str, form: Form) -> FormId {
1076 let (idx, _) = position_and_form(&mut self.forms, name);
1077
1078 self.forms[idx].1 = form;
1079
1080 for (referee, override_style) in refs_of(self, idx) {
1081 mimic_form_to_referee(&mut self.forms[referee].1, form, override_style);
1082 }
1083
1084 sender().send(DuatEvent::FormChange);
1085
1086 mask_form(name, idx, self);
1087
1088 let form_set = FormSet((self.forms[idx].0, FormId(idx as u16), form));
1089 context::queue(move |pa| _ = hook::trigger(pa, form_set));
1090
1091 FormId(idx as u16)
1092 }
1093
1094 fn set_weak_form(&mut self, name: &str, form: Form) -> FormId {
1096 let (idx, _) = position_and_form(&mut self.forms, name);
1097
1098 let (_, f) = &mut self.forms[idx];
1099 if let FormKind::Weakest | FormKind::WeakestRef(..) = f.kind {
1100 *f = form;
1101 f.kind = FormKind::Normal;
1102
1103 sender().send(DuatEvent::FormChange);
1104 for (referee, override_style) in refs_of(self, idx) {
1105 mimic_form_to_referee(&mut self.forms[referee].1, form, override_style);
1106 }
1107
1108 mask_form(name, idx, self);
1109 }
1110
1111 FormId(idx as u16)
1112 }
1113
1114 fn set_ref(&mut self, name: &str, refed: u16, override_style: ContentStyle) -> FormId {
1116 let (_, form) = self.forms[refed as usize];
1117 let (idx, _) = position_and_form(&mut self.forms, name);
1118
1119 self.forms[idx].1 = form;
1120 for (referee, override_style) in refs_of(self, idx) {
1121 mimic_form_to_referee(&mut self.forms[referee].1, form, override_style);
1122 }
1123
1124 if would_be_circular(self, idx, refed as usize) {
1126 self.forms[idx].1.kind = FormKind::Normal;
1127 } else {
1128 self.forms[idx].1.kind = FormKind::Ref(refed, override_style);
1129 }
1130
1131 sender().send(DuatEvent::FormChange);
1132
1133 mask_form(name, idx, self);
1134 let form_set = FormSet((self.forms[idx].0, FormId(idx as u16), form));
1135 context::queue(move |pa| _ = hook::trigger(pa, form_set));
1136
1137 FormId(idx as u16)
1138 }
1139
1140 fn set_weak_ref(&mut self, name: &str, refed: u16, override_style: ContentStyle) -> FormId {
1142 let (_, form) = self.forms[refed as usize];
1143 let (idx, _) = position_and_form(&mut self.forms, name);
1144
1145 let (_, f) = &mut self.forms[idx];
1146 if let FormKind::Weakest | FormKind::WeakestRef(..) = f.kind {
1147 *f = form;
1148 f.kind = FormKind::WeakestRef(refed, override_style);
1149
1150 sender().send(DuatEvent::FormChange);
1151
1152 for (referee, override_style) in refs_of(self, idx) {
1153 mimic_form_to_referee(&mut self.forms[referee].1, form, override_style);
1154 }
1155
1156 mask_form(name, idx, self);
1157 }
1158
1159 FormId(idx as u16)
1160 }
1161}
1162
1163fn mimic_form_to_referee(referee: &mut Form, form: Form, override_style: ContentStyle) {
1164 referee.style = form.style;
1165 referee.style.attributes.extend(override_style.attributes);
1166 if let Some(color) = override_style.foreground_color {
1167 referee.style.foreground_color = Some(color);
1168 }
1169 if let Some(color) = override_style.background_color {
1170 referee.style.background_color = Some(color);
1171 }
1172 if let Some(color) = override_style.underline_color {
1173 referee.style.underline_color = Some(color);
1174 }
1175}
1176
1177fn mask_form(name: &str, form_i: usize, inner: &mut InnerPalette) {
1179 if inner.masks[0].1.len() < inner.forms.len() {
1180 for (_, remaps) in inner.masks.iter_mut() {
1181 remaps.extend(remaps.len() as u16..inner.forms.len() as u16);
1182 }
1183 }
1184
1185 if let Some((pref, mask)) = name.rsplit_once(".")
1186 && let Some((_, remaps)) = inner.masks.iter_mut().find(|(m, _)| *m == mask)
1187 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
1188 {
1189 remaps[j] = form_i as u16;
1190 }
1191}
1192
1193pub struct Painter {
1250 inner: RwLockReadGuard<'static, InnerPalette>,
1251 applied_masks: Vec<usize>,
1252 default: (Form, FormId),
1253 forms: Vec<(Form, FormId, u8)>,
1254 set_fg: bool,
1255 set_bg: bool,
1256 set_ul: bool,
1257 reset_attrs: bool,
1258 prev_style: Option<ContentStyle>,
1259}
1260
1261impl Painter {
1262 #[inline(always)]
1270 pub fn apply(&mut self, id: FormId, prio: u8) {
1271 let forms = &self.inner.forms;
1272
1273 let form = get_form_for(id, &self.applied_masks, forms, &self.inner.masks);
1274
1275 let gt = |(.., p): &&(_, _, u8)| *p > prio;
1276 let i = self.forms.len() - self.forms.iter().rev().take_while(gt).count();
1277 self.forms.insert(i, (form, id, prio));
1278
1279 self.set_fg |= form.fg().is_some();
1280 self.set_bg |= form.bg().is_some();
1281 self.set_ul |= form.ul().is_some();
1282 self.reset_attrs |= form.attrs().has(Attribute::Reset);
1283 }
1284
1285 #[inline(always)]
1288 pub fn remove(&mut self, id: FormId) {
1289 let mut applied_forms = self.forms.iter().enumerate();
1290 if let Some((i, &(form, ..))) = applied_forms.rfind(|(_, (_, lhs, _))| *lhs == id) {
1291 self.forms.remove(i);
1292
1293 self.set_fg |= form.fg().is_some();
1294 self.set_bg |= form.bg().is_some();
1295 self.set_ul |= form.ul().is_some();
1296 self.reset_attrs |= !form.attrs().is_empty();
1297 };
1298 }
1299
1300 #[inline(always)]
1306 pub fn reset(&mut self) -> ContentStyle {
1307 self.forms.clear();
1308 self.absolute_style()
1309 }
1310
1311 #[inline(always)]
1316 pub fn absolute_style(&self) -> ContentStyle {
1317 let mut style = self.default.0.style;
1318
1319 for &(form, ..) in &self.forms {
1320 style.foreground_color = form.fg().or(style.foreground_color);
1321 style.background_color = form.bg().or(style.background_color);
1322 style.underline_color = form.ul().or(style.underline_color);
1323 style.attributes = if form.attrs().has(Attribute::Reset) {
1324 form.attrs()
1325 } else {
1326 form.attrs() | style.attributes
1327 }
1328 }
1329
1330 style
1331 }
1332
1333 #[inline(always)]
1345 pub fn relative_style(&mut self) -> Option<ContentStyle> {
1346 let abs_style = self.absolute_style();
1347 let mut style = abs_style;
1348
1349 if style.attributes.has(Attribute::Reset) || self.reset_attrs {
1350 style.attributes.set(Attribute::Reset);
1351 } else {
1355 style.foreground_color = self
1356 .set_fg
1357 .then_some(style.foreground_color.unwrap_or(Color::Reset))
1358 .filter(|fg| Some(*fg) != self.prev_style.and_then(|s| s.foreground_color));
1359 style.background_color = self
1360 .set_bg
1361 .then_some(style.background_color.unwrap_or(Color::Reset))
1362 .filter(|bg| Some(*bg) != self.prev_style.and_then(|s| s.background_color));
1363 style.underline_color = self
1364 .set_ul
1365 .then_some(style.underline_color.unwrap_or(Color::Reset))
1366 .filter(|ul| Some(*ul) != self.prev_style.and_then(|s| s.underline_color));
1367 }
1368
1369 self.set_fg = false;
1370 self.set_bg = false;
1371 self.set_ul = false;
1372 self.reset_attrs = false;
1373
1374 if let Some(prev_style) = self.prev_style.replace(abs_style) {
1375 (style != prev_style && style != Default::default()).then_some(style)
1376 } else {
1377 Some(style)
1378 }
1379 }
1380
1381 pub fn reset_prev_style(&mut self) {
1387 self.prev_style = None;
1388 self.set_fg = true;
1389 self.set_bg = true;
1390 self.set_ul = true;
1391 self.reset_attrs = true;
1392 }
1393
1394 #[inline(always)]
1396 pub fn apply_main_selection(&mut self, is_caret: bool, start_range: bool) {
1397 if is_caret {
1398 self.apply(M_CAR_ID, 150);
1399 }
1400 if start_range {
1401 self.apply(M_SEL_ID, 145);
1402 }
1403 }
1404
1405 #[inline(always)]
1407 pub fn remove_main_selection(&mut self, is_caret: bool, end_range: bool) {
1408 if is_caret {
1409 self.remove(M_CAR_ID);
1410 }
1411 if end_range {
1412 self.remove(M_SEL_ID);
1413 }
1414 }
1415
1416 #[inline(always)]
1418 pub fn apply_extra_selection(&mut self, is_caret: bool, start_range: bool) {
1419 if is_caret {
1420 self.apply(E_CAR_ID, 149);
1421 }
1422 if start_range {
1423 self.apply(E_SEL_ID, 144);
1424 }
1425 }
1426
1427 #[inline(always)]
1429 pub fn remove_extra_selection(&mut self, is_caret: bool, end_range: bool) {
1430 if is_caret {
1431 self.remove(E_CAR_ID);
1432 }
1433 if end_range {
1434 self.remove(E_SEL_ID);
1435 }
1436 }
1437
1438 pub fn apply_mask(&mut self, id: MaskId) {
1443 self.reset_prev_style();
1444 self.applied_masks.push(id.0 as usize);
1445
1446 let forms = &self.inner.forms;
1447
1448 for (form, id) in std::iter::once((&mut self.default.0, &mut self.default.1))
1449 .chain(self.forms.iter_mut().map(|(form, id, _)| (form, id)))
1450 {
1451 *form = get_form_for(*id, &self.applied_masks, forms, &self.inner.masks);
1452 }
1453 }
1454
1455 pub fn remove_mask(&mut self, id: MaskId) {
1460 self.reset_prev_style();
1461 self.applied_masks.retain(|idx| *idx != id.0 as usize);
1462
1463 let forms = &self.inner.forms;
1464
1465 for (form, id) in std::iter::once((&mut self.default.0, &mut self.default.1))
1466 .chain(self.forms.iter_mut().map(|(form, id, _)| (form, id)))
1467 {
1468 *form = get_form_for(*id, &self.applied_masks, forms, &self.inner.masks);
1469 }
1470 }
1471
1472 pub fn main_cursor(&self) -> Option<CursorShape> {
1474 self.inner.main_cursor
1475 }
1476
1477 pub fn extra_cursor(&self) -> Option<CursorShape> {
1479 self.inner.extra_cursor
1480 }
1481
1482 pub fn get_default(&self) -> Form {
1484 self.default.0
1485 }
1486}
1487
1488#[derive(Default, Clone, Copy)]
1490enum FormKind {
1491 #[default]
1492 Normal,
1493 Ref(u16, ContentStyle),
1494 Weakest,
1495 WeakestRef(u16, ContentStyle),
1496}
1497
1498fn get_form_for(
1499 id: FormId,
1500 applied_masks: &[usize],
1501 forms: &[(&str, Form)],
1502 masks: &[(&'static str, Vec<u16>)],
1503) -> Form {
1504 unsafe {
1507 applied_masks
1508 .iter()
1509 .rev()
1510 .find_map(|mask_id| {
1511 let (_, mask) = masks.get(*mask_id).unwrap_unchecked();
1512 let idx = mask
1513 .get(id.0 as usize)
1514 .copied()
1515 .filter(|idx| *idx != id.0)?;
1516 Some(forms.get(idx as usize).unwrap_unchecked().1)
1517 })
1518 .unwrap_or(forms.get(id.0 as usize).unwrap_unchecked().1)
1519 }
1520}
1521
1522fn refs_of(inner: &InnerPalette, refed: usize) -> Vec<(usize, ContentStyle)> {
1524 let mut refs = Vec::new();
1525 for (i, (_, form)) in inner.forms.iter().enumerate() {
1526 if let FormKind::Ref(id, style) | FormKind::WeakestRef(id, style) = form.kind
1527 && id as usize == refed
1528 {
1529 refs.push((i, style));
1530 refs.extend(refs_of(inner, i));
1531 }
1532 }
1533 refs
1534}
1535
1536fn would_be_circular(inner: &InnerPalette, referee: usize, refed: usize) -> bool {
1538 if let FormKind::Ref(id, _) | FormKind::WeakestRef(id, _) = inner.forms[refed].1.kind {
1539 match id as usize == referee {
1540 true => true,
1541 false => would_be_circular(inner, referee, id as usize),
1542 }
1543 } else {
1544 false
1545 }
1546}
1547
1548fn position_and_form(
1549 forms: &mut Vec<(&'static str, Form)>,
1550 name: impl AsRef<str>,
1551) -> (usize, Form) {
1552 let name = name.as_ref();
1553 if let Some((i, (_, form))) = forms.iter().enumerate().find(|(_, (lhs, _))| *lhs == name) {
1554 (i, *form)
1555 } else if let Some((refed, _)) = name.rsplit_once('.') {
1556 let (i, mut form) = position_and_form(forms, refed);
1557 form.kind = FormKind::WeakestRef(i as u16, default_style());
1558 forms.push((name.to_string().leak(), form));
1559 (forms.len() - 1, form)
1560 } else {
1561 let mut form = Form::new();
1562 form.kind = FormKind::Weakest;
1563 forms.push((name.to_string().leak(), form));
1564 (forms.len() - 1, form)
1565 }
1566}
1567
1568const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1570 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1571 let prefix = prefix.as_bytes();
1572
1573 let mut i = 0;
1574 while i < prefix.len() {
1575 if str.as_bytes()[i] != prefix[i] {
1576 return None;
1577 }
1578 i += 1;
1579 }
1580
1581 Some(str.split_at(prefix.len()).1)
1582 }
1583 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1584 let prefix = suffix.as_bytes();
1585
1586 let mut i = str.len() - 1;
1587 while i >= str.len() - prefix.len() {
1588 if str.as_bytes()[i] != prefix[i - (str.len() - prefix.len())] {
1589 return None;
1590 }
1591 i += 1;
1592 }
1593
1594 Some(str.split_at(str.len() - suffix.len()).0)
1595 }
1596 const fn split_space(str: &str) -> Option<(&str, &str)> {
1597 if str.is_empty() {
1598 return None;
1599 }
1600
1601 let mut i = 0;
1602 while i < str.len() {
1603 if str.as_bytes()[i] == b' ' {
1604 break;
1605 }
1606 i += 1;
1607 }
1608
1609 let (cut, rest) = str.split_at(i);
1610 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1611 Some((cut, rest))
1612 }
1613 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1614 t = if t < 0.0 { t + 1.0 } else { t };
1615 t = if t > 1.0 { t - 1.0 } else { t };
1616 if t < 1.0 / 6.0 {
1617 p + (q - p) * 6.0 * t
1618 } else if t < 1.0 / 2.0 {
1619 q
1620 } else if t < 2.0 / 3.0 {
1621 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1622 } else {
1623 p
1624 }
1625 }
1626
1627 if let Some(hex) = strip_prefix("#", str) {
1629 let total = match u32::from_str_radix(hex, 16) {
1630 Ok(total) if hex.len() == 6 => total,
1631 _ => return Err("Hexcode does not contain 6 hex values"),
1632 };
1633 let r = (total >> 16) as u8;
1634 let g = (total >> 8) as u8;
1635 let b = total as u8;
1636
1637 Ok(Color::Rgb { r, g, b })
1638 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1640 let mut values = [0.0, 0.0, 0.0];
1641 let mut i = 0;
1642 while i < values.len() {
1643 if let Some((cut, rest)) = split_space(hsl) {
1644 hsl = rest;
1645 let (num, div) = match strip_suffix("%", cut) {
1646 Some(perc) => (perc, 100),
1647 None => (cut, 255),
1648 };
1649 values[i] = match u8::from_str_radix(num, 10) {
1650 Ok(value) if value <= div => value as f32 / div as f32,
1651 _ => return Err("Hsl format property could not be parsed"),
1652 }
1653 } else {
1654 return Err("Missing value in hsl format");
1655 }
1656 i += 1;
1657 }
1658 let [hue, sat, lit] = values;
1659
1660 let (r, g, b) = if sat == 0.0 {
1661 (lit, lit, lit)
1662 } else {
1663 let q = if lit < 0.5 {
1664 lit * (1.0 + sat)
1665 } else {
1666 lit + sat - lit * sat
1667 };
1668 let p = 2.0 * lit - q;
1669 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1670 let g = hue_to_rgb(p, q, hue);
1671 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1672 (r, g, b)
1673 };
1674
1675 let r = (0.5 + r * 255.0) as u8;
1677 let g = (0.5 + g * 255.0) as u8;
1678 let b = (0.5 + b * 255.0) as u8;
1679 Ok(Color::Rgb { r, g, b })
1680 } else {
1681 Err("Color format was not recognized")
1682 }
1683}
1684
1685const fn default_style() -> ContentStyle {
1687 ContentStyle {
1688 foreground_color: None,
1689 background_color: None,
1690 underline_color: None,
1691 attributes: Attributes::none(),
1692 }
1693}
1694
1695impl std::fmt::Debug for Form {
1696 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1697 struct DebugColor(Option<Color>);
1698 impl std::fmt::Debug for DebugColor {
1699 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1700 match self.0 {
1701 Some(Color::Rgb { r, g, b }) => write!(f, "Some(Rgb({r}, {g}, {b}))"),
1702 Some(Color::AnsiValue(ansi)) => write!(f, "Some(Ansi({ansi}))"),
1703 Some(color) => write!(f, "Some({color:?})"),
1704 None => f.write_str("None"),
1705 }
1706 }
1707 }
1708
1709 struct DebugAttributes(Attributes);
1710 impl std::fmt::Debug for DebugAttributes {
1711 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1712 if self.0.is_empty() {
1713 f.write_str("None")
1714 } else {
1715 let mut is_first = true;
1716 for attr in Attribute::iterator() {
1717 if self.0.has(attr) {
1718 if !is_first {
1719 f.write_str(" | ")?;
1720 }
1721 is_first = false;
1722 write!(f, "{attr:?}")?;
1723 }
1724 }
1725 Ok(())
1726 }
1727 }
1728 }
1729
1730 f.debug_struct("Form")
1731 .field("fg", &DebugColor(self.style.foreground_color))
1732 .field("bg", &DebugColor(self.style.background_color))
1733 .field("ul", &DebugColor(self.style.underline_color))
1734 .field("attr", &DebugAttributes(self.style.attributes))
1735 .finish()
1736 }
1737}
1738
1739impl std::fmt::Debug for InnerPalette {
1740 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1741 struct DebugForms<'a>(&'a [(&'static str, Form)]);
1742 impl std::fmt::Debug for DebugForms<'_> {
1743 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1744 if f.alternate() {
1745 f.write_str("[\n")?;
1746 let max = self.0.len().ilog10() as usize + 3;
1747 for (n, (name, form)) in self.0.iter().enumerate() {
1748 let num = format!("{n}:");
1749 writeln!(f, "{num:<max$}({name}, {form:#?})")?;
1750 }
1751 f.write_str("]")
1752 } else {
1753 write!(f, "{:?}", self.0)
1754 }
1755 }
1756 }
1757
1758 struct DebugCursorShape(CursorShape);
1759 impl std::fmt::Debug for DebugCursorShape {
1760 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1761 match self.0 {
1762 CursorShape::DefaultUserShape => f.write_str("DefaultUserShape"),
1763 CursorShape::BlinkingBlock => f.write_str("BlinkingBlock"),
1764 CursorShape::SteadyBlock => f.write_str("SteadyBlock"),
1765 CursorShape::BlinkingUnderScore => f.write_str("BlinkingUnderScore"),
1766 CursorShape::SteadyUnderScore => f.write_str("SteadyUnderScore"),
1767 CursorShape::BlinkingBar => f.write_str("BlinkingBar"),
1768 CursorShape::SteadyBar => f.write_str("SteadyBar"),
1769 }
1770 }
1771 }
1772
1773 f.debug_struct("InnerPalette")
1774 .field("main_cursor", &self.main_cursor.map(DebugCursorShape))
1775 .field("extra_cursor", &self.extra_cursor.map(DebugCursorShape))
1776 .field("forms", &DebugForms(&self.forms))
1777 .field("masks", &self.masks)
1778 .finish()
1779 }
1780}
1781
1782impl std::fmt::Debug for FormKind {
1783 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1784 match self {
1785 Self::Normal => write!(f, "Normal"),
1786 Self::Ref(refed, _) => write!(f, "Ref({refed})"),
1787 Self::Weakest => write!(f, "Weakest"),
1788 Self::WeakestRef(refed, _) => write!(f, "WeakestRef({refed})"),
1789 }
1790 }
1791}
1792
1793pub const DEFAULT_ID: FormId = FormId(0);
1795pub const ACCENT_ID: FormId = FormId(1);
1797pub const M_CAR_ID: FormId = FormId(2);
1799pub const E_CAR_ID: FormId = FormId(3);
1801pub const M_SEL_ID: FormId = FormId(4);
1803pub const E_SEL_ID: FormId = FormId(5);
1805pub const CONTROL_CHAR_ID: FormId = FormId(7);
1807
1808#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1810pub struct MaskId(u32);
1811
1812impl MaskId {
1813 pub fn name(&self) -> &'static str {
1815 name_of_mask(*self)
1816 }
1817}
1818
1819impl std::fmt::Debug for MaskId {
1820 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1821 write!(f, "MaskId({:?})", name_of_mask(*self))
1822 }
1823}