1use std::sync::{LazyLock, 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];
45
46mod global {
48 use std::{
49 any::TypeId,
50 collections::HashMap,
51 sync::{LazyLock, Mutex, mpsc},
52 thread,
53 time::Duration,
54 };
55
56 use super::{BASE_FORMS, BuiltForm, ColorScheme, CursorShape, Form, FormId, Painter, Palette};
57 use crate::{
58 context,
59 hook::{self, ColorSchemeSet},
60 };
61
62 static PALETTE: Palette = Palette::new();
63 static FORMS: LazyLock<Mutex<Vec<&str>>> =
64 LazyLock::new(|| Mutex::new(BASE_FORMS.iter().map(|(name, ..)| *name).collect()));
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 {
103 let kind = form.kind();
104 let name: &'static str = name.to_string().leak();
105
106 match kind {
107 Kind::Form(form) => queue(move || PALETTE.set_form(name, form)),
108 Kind::Ref(refed) => queue(move || PALETTE.set_ref(name, refed)),
109 };
110
111 let mut forms = FORMS.lock().unwrap();
112 if let Kind::Ref(refed) = kind {
113 position_of_name(&mut forms, refed);
114 }
115 FormId(position_of_name(&mut forms, name) as u16)
116 }
117
118 pub fn set_weak(name: impl ToString, form: impl FormFmt) -> FormId {
143 let kind = form.kind();
144 let name: &'static str = name.to_string().leak();
145
146 match kind {
147 Kind::Form(form) => queue(move || PALETTE.set_weak_form(name, form)),
148 Kind::Ref(refed) => queue(move || PALETTE.set_weak_ref(name, refed)),
149 };
150
151 let mut forms = FORMS.lock().unwrap();
152 if let Kind::Ref(refed) = kind {
153 position_of_name(&mut forms, refed);
154 }
155 FormId(position_of_name(&mut forms, name) as u16)
156 }
157
158 pub fn from_id(id: FormId) -> Form {
160 PALETTE.form_from_id(id).unwrap_or(Form::new().0)
161 }
162
163 pub fn main_cursor() -> (Form, Option<CursorShape>) {
165 PALETTE.main_cursor()
166 }
167
168 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
170 PALETTE.extra_cursor()
171 }
172
173 pub fn set_main_cursor(shape: CursorShape) {
196 queue(move || PALETTE.set_main_cursor(shape));
197 }
198
199 pub fn set_extra_cursor(shape: CursorShape) {
222 queue(move || PALETTE.set_extra_cursor(shape));
223 }
224
225 pub fn unset_main_cursor() {
236 queue(move || PALETTE.unset_main_cursor());
237 }
238
239 pub fn unset_extra_cursor() {
253 queue(move || PALETTE.unset_extra_cursor());
254 }
255
256 pub fn unset_cursors() {
263 queue(move || {
264 PALETTE.unset_main_cursor();
265 PALETTE.unset_extra_cursor();
266 })
267 }
268
269 pub(crate) fn painter_with_mask<W: ?Sized + 'static>(mask: &'static str) -> Painter {
271 PALETTE.painter(default_id(TypeId::of::<W>(), crate::duat_name::<W>()), mask)
272 }
273
274 pub fn enable_mask(mask: &'static str) {
335 queue(move || {
336 let mut inner = PALETTE.0.write().unwrap();
337 if !inner.masks.iter().any(|(m, _)| *m == mask) {
338 let mut remaps: Vec<u16> = (0..inner.forms.len() as u16).collect();
339
340 for (i, (name, ..)) in inner.forms.iter().enumerate() {
341 if let Some((pref, suf)) = name.rsplit_once('.')
342 && suf == mask
343 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
344 {
345 remaps[j] = i as u16;
346 }
347 }
348
349 inner.masks.push((mask, remaps));
350 }
351 })
352 }
353
354 pub macro id_of {
384 ($form:expr) => {{
385 use $crate::form::FormId;
386
387 static ID: std::sync::OnceLock<FormId> = std::sync::OnceLock::new();
388 *ID.get_or_init(|| {
389 let name: &'static str = $form;
390 let id = id_from_name(name);
391 add_forms(vec![name]);
392 id
393 })
394 }},
395 ($($form:expr),+) => {{
396 static IDS: std::sync::OnceLock<&[FormId]> = std::sync::OnceLock::new();
397 let ids = *IDS.get_or_init(|| {
398 let mut ids = Vec::new();
399 let names = vec![$( $form ),+];
400 for name in names.iter() {
401 ids.push(id_from_name(name));
402 }
403 add_forms(names);
404 ids.leak()
405 });
406 ids
407 }}
408 }
409
410 pub fn ids_of_non_static(names: impl IntoIterator<Item = impl ToString>) -> Vec<FormId> {
417 let names: Vec<&str> = names
418 .into_iter()
419 .map(|n| {
420 let str: &'static str = n.to_string().leak();
421 str
422 })
423 .collect();
424
425 let mut ids = Vec::new();
426 let mut forms = FORMS.lock().unwrap();
427 for name in names.iter() {
428 ids.push(FormId(position_of_name(&mut forms, name) as u16));
429 }
430 add_forms(names);
431 ids
432 }
433
434 #[doc(hidden)]
436 pub fn id_from_name(name: &'static str) -> FormId {
437 let mut forms = FORMS.lock().unwrap();
438 FormId(position_of_name(&mut forms, name) as u16)
439 }
440
441 #[doc(hidden)]
442 pub fn add_forms(names: Vec<&'static str>) {
443 queue(move || PALETTE.set_many(names.as_ref()));
444 }
445
446 pub fn add_colorscheme(cs: impl ColorScheme) {
457 let mut colorschemes = COLORSCHEMES.lock().unwrap();
458 let name = cs.name();
459 if let Some(i) = colorschemes.iter().position(|cs| cs.name() == name) {
460 colorschemes[i] = Box::new(cs);
461 } else {
462 colorschemes.push(Box::new(cs));
463 }
464 }
465
466 pub fn set_colorscheme(name: &str) {
473 let colorschemes = COLORSCHEMES.lock().unwrap();
474 if let Some(cs) = colorschemes.iter().find(|cs| cs.name() == name) {
475 cs.apply();
476 hook::queue(ColorSchemeSet(cs.name()));
477 } else {
478 context::error!("The colorscheme [a]{name}[] was not found");
479 }
480 }
481
482 pub macro set_many($(($name:literal, $form:expr)),+ $(,)?) {{
486 $(
487 set($name, $form);
488 )+
489 }}
490
491 pub(crate) fn exists(name: &str) -> bool {
493 FORMS.lock().unwrap().contains(&name)
494 }
495
496 pub(crate) fn colorscheme_exists(name: &str) -> bool {
498 COLORSCHEMES
499 .lock()
500 .unwrap()
501 .iter()
502 .any(|cs| cs.name() == name)
503 }
504
505 pub(super) fn name_of(id: FormId) -> &'static str {
507 FORMS.lock().unwrap()[id.0 as usize]
508 }
509
510 fn default_id(type_id: TypeId, type_name: &'static str) -> FormId {
511 static IDS: LazyLock<Mutex<HashMap<TypeId, FormId>>> = LazyLock::new(Mutex::default);
512 let mut ids = IDS.lock().unwrap();
513
514 if let Some(id) = ids.get(&type_id) {
515 *id
516 } else {
517 let name: &'static str = format!("default.{type_name}").leak();
518 let id = id_from_name(name);
519 add_forms(vec![name]);
520 ids.insert(type_id, id);
521 id
522 }
523 }
524
525 fn position_of_name(names: &mut Vec<&'static str>, name: &'static str) -> usize {
526 if let Some((i, _)) = names.iter().enumerate().find(|(_, rhs)| **rhs == name) {
527 i
528 } else if let Some((refed, _)) = name.rsplit_once('.') {
529 position_of_name(names, refed);
530 names.push(name);
531 names.len() - 1
532 } else {
533 names.push(name);
534 names.len() - 1
535 }
536 }
537
538 fn queue<R>(f: impl FnOnce() -> R + Send + Sync + 'static) {
539 static SENDER: Mutex<Option<mpsc::Sender<Box<dyn FnOnce() + Send + Sync>>>> =
540 Mutex::new(None);
541
542 if context::will_reload_or_quit() {
543 return;
544 }
545
546 let f = Box::new(move || {
547 f();
548 });
549
550 let mut sender = SENDER.lock().unwrap();
551 let f = if let Some(tx) = sender.as_ref() {
552 let Err(err) = tx.send(f) else {
553 return;
554 };
555 err.0
556 } else {
557 f
558 };
559 let (tx, rx) = mpsc::channel();
560 tx.send(f).unwrap();
561 *sender = Some(tx);
562
563 thread::spawn(move || {
564 while let Ok(f) = rx.recv_timeout(Duration::from_micros(500)) {
565 f();
566 }
567 });
568 }
569
570 #[derive(Clone, Copy)]
572 enum Kind {
573 Form(Form),
574 Ref(&'static str),
575 }
576
577 trait InnerFormFmt {
581 fn kind(self) -> Kind;
583 }
584
585 impl InnerFormFmt for Form {
586 fn kind(self) -> Kind {
587 Kind::Form(self)
588 }
589 }
590
591 impl InnerFormFmt for BuiltForm {
592 fn kind(self) -> Kind {
593 Kind::Form(self.0)
594 }
595 }
596
597 impl InnerFormFmt for &str {
598 fn kind(self) -> Kind {
599 Kind::Ref(self.to_string().leak())
600 }
601 }
602
603 impl InnerFormFmt for &mut str {
604 fn kind(self) -> Kind {
605 Kind::Ref(self.to_string().leak())
606 }
607 }
608
609 impl InnerFormFmt for String {
610 fn kind(self) -> Kind {
611 Kind::Ref(self.leak())
612 }
613 }
614}
615
616#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
630pub struct FormId(u16);
631
632impl FormId {
633 pub const fn to_tag(self, prio: u8) -> FormTag {
642 FormTag(self, prio)
643 }
644
645 pub const fn to_u16(self) -> u16 {
649 self.0
650 }
651
652 pub fn name(self) -> &'static str {
654 name_of(self)
655 }
656}
657
658impl std::fmt::Debug for FormId {
659 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
660 write!(f, "FormId({})", name_of(*self))
661 }
662}
663
664#[derive(Clone, Copy, PartialEq, Eq)]
666pub struct Form {
667 pub style: ContentStyle,
669}
670
671#[rustfmt::skip]
672impl Form {
673 mimic_method_new!(bold Attribute::Bold);
674 mimic_method_new!(dim Attribute::Dim);
675 mimic_method_new!(italic Attribute::Italic);
676 mimic_method_new!(underlined Attribute::Underlined);
677 mimic_method_new!(double_underlined Attribute::DoubleUnderlined);
678 mimic_method_new!(undercurled Attribute::Undercurled);
679 mimic_method_new!(underdashed Attribute::Underdashed);
680 mimic_method_new!(reverse Attribute::Reverse);
681 mimic_method_new!(crossed_out Attribute::CrossedOut);
682 mimic_method_new!(black on_black underline_black Color::Black);
683 mimic_method_new!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
684 mimic_method_new!(red on_red underline_red Color::Red);
685 mimic_method_new!(dark_red on_dark_red underline_dark_red Color::DarkRed);
686 mimic_method_new!(green on_green underline_green Color::Green);
687 mimic_method_new!(
688 dark_green on_dark_green underline_dark_green Color::DarkGreen
689 );
690 mimic_method_new!(yellow on_yellow underline_yellow Color::Yellow);
691 mimic_method_new!(
692 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
693 );
694 mimic_method_new!(blue on_blue underline_blue Color::Blue);
695 mimic_method_new!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
696 mimic_method_new!(magenta on_magenta underline_magenta Color::Magenta);
697 mimic_method_new!(
698 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
699 );
700 mimic_method_new!(cyan on_cyan underline_cyan Color::Cyan);
701 mimic_method_new!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
702 mimic_method_new!(white on_white underline_white Color::White);
703 mimic_method_new!(grey on_grey underline_grey Color::Grey);
704}
705
706impl Form {
707 #[allow(clippy::new_ret_no_self)]
711 pub const fn new() -> BuiltForm {
712 let style = ContentStyle {
713 foreground_color: None,
714 background_color: None,
715 underline_color: None,
716 attributes: Attributes::none(),
717 };
718 BuiltForm(Self { style })
719 }
720
721 pub const fn reset() -> BuiltForm {
728 let mut built = Form::new();
729 built.0.style.attributes = built.0.style.attributes.with(Attribute::Reset);
730 built
731 }
732
733 pub const fn with(str: &str) -> BuiltForm {
743 let mut built = Form::new();
744 built.0.style.foreground_color = match str_to_color(str) {
745 Ok(color) => Some(color),
746 Err(err) => panic!("{}", err),
747 };
748 built
749 }
750
751 pub const fn on(str: &str) -> BuiltForm {
761 let mut built = Form::new();
762 built.0.style.background_color = match str_to_color(str) {
763 Ok(color) => Some(color),
764 Err(err) => panic!("{}", err),
765 };
766 built
767 }
768
769 pub const fn underline(str: &str) -> BuiltForm {
779 let mut built = Form::new();
780 built.0.style.underline_color = match str_to_color(str) {
781 Ok(color) => Some(color),
782 Err(err) => panic!("{}", err),
783 };
784 built
785 }
786
787 pub const fn fg(&self) -> Option<Color> {
789 self.style.foreground_color
790 }
791
792 pub const fn bg(&self) -> Option<Color> {
794 self.style.background_color
795 }
796
797 pub const fn ul(&self) -> Option<Color> {
799 self.style.underline_color
800 }
801
802 pub const fn attrs(&self) -> Attributes {
804 self.style.attributes
805 }
806}
807
808#[derive(Clone, Copy, Debug)]
817pub struct BuiltForm(Form);
818
819#[rustfmt::skip]
820impl BuiltForm {
821 mimic_method_mod!(bold Attribute::Bold);
822 mimic_method_mod!(dim Attribute::Dim);
823 mimic_method_mod!(italic Attribute::Italic);
824 mimic_method_mod!(underlined Attribute::Underlined);
825 mimic_method_mod!(double_underlined Attribute::DoubleUnderlined);
826 mimic_method_mod!(undercurled Attribute::Undercurled);
827 mimic_method_mod!(underdashed Attribute::Underdashed);
828 mimic_method_mod!(reverse Attribute::Reverse);
829 mimic_method_mod!(crossed_out Attribute::CrossedOut);
830 mimic_method_mod!(overlined Attribute::OverLined);
831 mimic_method_mod!(black on_black underline_black Color::Black);
832 mimic_method_mod!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
833 mimic_method_mod!(red on_red underline_red Color::Red);
834 mimic_method_mod!(dark_red on_dark_red underline_dark_red Color::DarkRed);
835 mimic_method_mod!(green on_green underline_green Color::Green);
836 mimic_method_mod!(
837 dark_green on_dark_green underline_dark_green Color::DarkGreen
838 );
839 mimic_method_mod!(yellow on_yellow underline_yellow Color::Yellow);
840 mimic_method_mod!(
841 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
842 );
843 mimic_method_mod!(blue on_blue underline_blue Color::Blue);
844 mimic_method_mod!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
845 mimic_method_mod!(magenta on_magenta underline_magenta Color::Magenta);
846 mimic_method_mod!(
847 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
848 );
849 mimic_method_mod!(cyan on_cyan underline_cyan Color::Cyan);
850 mimic_method_mod!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
851 mimic_method_mod!(white on_white underline_white Color::White);
852 mimic_method_mod!(grey on_grey underline_grey Color::Grey);
853}
854
855impl BuiltForm {
856 pub const fn reset(mut self) -> BuiltForm {
863 self.0.style.attributes = self.0.style.attributes.with(Attribute::Reset);
864 self
865 }
866
867 pub const fn with(mut self, str: &str) -> Self {
877 self.0.style.foreground_color = match str_to_color(str) {
878 Ok(color) => Some(color),
879 Err(err) => panic!("{}", err),
880 };
881 self
882 }
883
884 pub const fn on(mut self, str: &str) -> Self {
894 self.0.style.background_color = match str_to_color(str) {
895 Ok(color) => Some(color),
896 Err(err) => panic!("{}", err),
897 };
898 self
899 }
900
901 pub const fn underline(mut self, str: &str) -> Self {
911 self.0.style.underline_color = match str_to_color(str) {
912 Ok(color) => Some(color),
913 Err(err) => panic!("{}", err),
914 };
915 self
916 }
917}
918
919impl std::ops::Deref for BuiltForm {
920 type Target = Form;
921
922 fn deref(&self) -> &Self::Target {
923 &self.0
924 }
925}
926
927impl std::ops::DerefMut for BuiltForm {
928 fn deref_mut(&mut self) -> &mut Self::Target {
929 &mut self.0
930 }
931}
932
933impl From<BuiltForm> for Form {
934 fn from(value: BuiltForm) -> Self {
935 value.0
936 }
937}
938
939pub const DEFAULT_ID: FormId = FormId(0);
941pub const ACCENT_ID: FormId = FormId(1);
943pub const M_CAR_ID: FormId = FormId(2);
945pub const E_CAR_ID: FormId = FormId(3);
947pub const M_SEL_ID: FormId = FormId(4);
949pub const E_SEL_ID: FormId = FormId(5);
951
952struct InnerPalette {
953 main_cursor: Option<CursorShape>,
954 extra_cursor: Option<CursorShape>,
955 forms: Vec<(&'static str, Form, FormType)>,
956 masks: Vec<(&'static str, Vec<u16>)>,
957}
958
959struct Palette(LazyLock<RwLock<InnerPalette>>);
961
962impl Palette {
963 const fn new() -> Self {
965 Self(LazyLock::new(|| {
966 let main_cursor = Some(CursorShape::DefaultUserShape);
967
968 RwLock::new(InnerPalette {
969 main_cursor,
970 extra_cursor: main_cursor,
971 forms: BASE_FORMS.to_vec(),
972 masks: vec![("", (0..BASE_FORMS.len() as u16).collect())],
973 })
974 }))
975 }
976
977 fn set_form(&self, name: &'static str, form: Form) {
979 let mut inner = self.0.write().unwrap();
980 let (i, _) = position_and_form(&mut inner.forms, name);
981
982 inner.forms[i] = (name, form, FormType::Normal);
983
984 for refed in refs_of(&inner, i) {
985 inner.forms[refed].1 = form;
986 }
987
988 if let Some(sender) = SENDER.get() {
989 sender.send_form_changed().unwrap()
990 }
991
992 mask_form(name, i, &mut inner);
993 hook::queue(FormSet((name, FormId(i as u16), form)));
994 }
995
996 fn set_weak_form(&self, name: &'static str, form: Form) {
998 let mut inner = self.0.write().unwrap();
999 let (i, _) = position_and_form(&mut inner.forms, name);
1000
1001 let (_, f, f_ty) = &mut inner.forms[i];
1002 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
1003 *f = form;
1004 *f_ty = FormType::Normal;
1005
1006 if let Some(sender) = SENDER.get() {
1007 sender.send_form_changed().unwrap()
1008 }
1009 for refed in refs_of(&inner, i) {
1010 inner.forms[refed].1 = form;
1011 }
1012
1013 mask_form(name, i, &mut inner);
1014 }
1015 }
1016
1017 fn set_ref(&self, name: &'static str, refed: &'static str) {
1019 let mut inner = self.0.write().unwrap();
1020 let (refed, form) = position_and_form(&mut inner.forms, refed);
1021 let (i, _) = position_and_form(&mut inner.forms, name);
1022
1023 for refed in refs_of(&inner, i) {
1024 inner.forms[refed].1 = form;
1025 }
1026
1027 if would_be_circular(&inner, i, refed) {
1029 inner.forms[i] = (name, form, FormType::Normal);
1030 } else {
1031 inner.forms[i] = (name, form, FormType::Ref(refed));
1032 }
1033
1034 if let Some(sender) = SENDER.get() {
1035 sender.send_form_changed().unwrap()
1036 }
1037
1038 mask_form(name, i, &mut inner);
1039 hook::queue(FormSet((name, FormId(i as u16), form)));
1040 }
1041
1042 fn set_weak_ref(&self, name: &'static str, refed: &'static str) {
1044 let mut inner = self.0.write().unwrap();
1045 let (refed, form) = position_and_form(&mut inner.forms, refed);
1046 let (i, _) = position_and_form(&mut inner.forms, name);
1047
1048 let (_, f, f_ty) = &mut inner.forms[i];
1051 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
1052 *f = form;
1053 *f_ty = FormType::WeakestRef(refed);
1054
1055 if let Some(sender) = SENDER.get() {
1056 sender.send_form_changed().unwrap()
1057 }
1058 for refed in refs_of(&inner, i) {
1059 inner.forms[refed].1 = form;
1060 }
1061
1062 mask_form(name, i, &mut inner);
1063 }
1064 }
1065
1066 fn set_many(&self, names: &[&'static str]) {
1068 let mut inner = self.0.write().unwrap();
1069 let form_indices: Vec<(usize, &str)> = names
1070 .iter()
1071 .map(|name| {
1072 let (i, _) = position_and_form(&mut inner.forms, name);
1073 (i, *name)
1074 })
1075 .collect();
1076
1077 for (i, name) in form_indices {
1078 mask_form(name, i, &mut inner);
1079 }
1080 }
1081
1082 fn form_from_id(&self, id: FormId) -> Option<Form> {
1084 let inner = self.0.read().unwrap();
1085 inner.forms.get(id.0 as usize).map(|(_, form, _)| *form)
1086 }
1087
1088 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
1090 let form = self.form_from_id(M_CAR_ID).unwrap();
1091 (form, self.0.read().unwrap().main_cursor)
1092 }
1093
1094 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
1096 let form = self.form_from_id(E_CAR_ID).unwrap();
1097 (form, self.0.read().unwrap().extra_cursor)
1098 }
1099
1100 fn set_main_cursor(&self, shape: CursorShape) {
1102 self.0.write().unwrap().main_cursor = Some(shape);
1103 if let Some(sender) = SENDER.get() {
1104 sender.send_form_changed().unwrap()
1105 }
1106 }
1107
1108 fn set_extra_cursor(&self, shape: CursorShape) {
1110 self.0.write().unwrap().extra_cursor = Some(shape);
1111 if let Some(sender) = SENDER.get() {
1112 sender.send_form_changed().unwrap()
1113 }
1114 }
1115
1116 fn unset_main_cursor(&self) {
1118 self.0.write().unwrap().main_cursor = None;
1119 if let Some(sender) = SENDER.get() {
1120 sender.send_form_changed().unwrap()
1121 }
1122 }
1123
1124 fn unset_extra_cursor(&self) {
1126 self.0.write().unwrap().extra_cursor = None;
1127 if let Some(sender) = SENDER.get() {
1128 sender.send_form_changed().unwrap()
1129 }
1130 }
1131
1132 fn painter(&'static self, default_id: FormId, mask: &str) -> Painter {
1134 let inner = self.0.read().unwrap();
1135 let mask_i = inner
1136 .masks
1137 .iter()
1138 .position(|(m, _)| *m == mask)
1139 .unwrap_or_default();
1140
1141 let default = inner
1142 .forms
1143 .get(match inner.masks[mask_i].1.get(default_id.0 as usize) {
1144 Some(i) => *i as usize,
1145 None => default_id.0 as usize,
1146 })
1147 .map(|(_, f, _)| *f)
1148 .unwrap_or(Form::new().0);
1149
1150 Painter {
1151 inner,
1152 mask_i,
1153 default,
1154 forms: Vec::new(),
1155 final_form_start: 0,
1156 set_fg: true,
1157 set_bg: true,
1158 set_ul: true,
1159 reset_attrs: false,
1160 }
1161 }
1162}
1163
1164fn mask_form(name: &'static str, form_i: usize, inner: &mut InnerPalette) {
1166 if inner.masks[0].1.len() < inner.forms.len() {
1167 for (_, remaps) in inner.masks.iter_mut() {
1168 remaps.extend(remaps.len() as u16..inner.forms.len() as u16);
1169 }
1170 }
1171
1172 if let Some((pref, mask)) = name.rsplit_once(".")
1173 && let Some((_, remaps)) = inner.masks.iter_mut().find(|(m, _)| *m == mask)
1174 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
1175 {
1176 remaps[j] = form_i as u16;
1177 }
1178}
1179
1180pub struct Painter {
1241 inner: RwLockReadGuard<'static, InnerPalette>,
1242 mask_i: usize,
1243 default: Form,
1244 forms: Vec<(Form, FormId)>,
1245 final_form_start: usize,
1246 set_fg: bool,
1247 set_bg: bool,
1248 set_ul: bool,
1249 reset_attrs: bool,
1250}
1251
1252impl Painter {
1253 #[inline(always)]
1261 pub fn apply(&mut self, id: FormId) {
1262 let (_, mask) = &self.inner.masks[self.mask_i];
1263 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1264
1265 let forms = &self.inner.forms;
1266 let form = forms
1267 .get(id.0 as usize)
1268 .map(|(_, f, _)| *f)
1269 .unwrap_or(Form::new().0);
1270
1271 self.forms.insert(self.final_form_start, (form, id));
1272 if id != M_SEL_ID && id != E_SEL_ID {
1273 self.final_form_start += 1;
1274 }
1275
1276 self.set_fg |= form.fg().is_some();
1277 self.set_bg |= form.bg().is_some();
1278 self.set_ul |= form.ul().is_some();
1279 self.reset_attrs |= form.attrs().has(Attribute::Reset);
1280 }
1281
1282 #[inline(always)]
1285 pub fn remove(&mut self, id: FormId) {
1286 let mask = &self.inner.masks[self.mask_i].1;
1287 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1288
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 if id != M_SEL_ID && id != E_SEL_ID {
1293 self.final_form_start -= 1;
1294 }
1295
1296 self.set_fg |= form.fg().is_some();
1297 self.set_bg |= form.bg().is_some();
1298 self.set_ul |= form.ul().is_some();
1299 self.reset_attrs |= !form.attrs().is_empty();
1300 };
1301 }
1302
1303 #[inline(always)]
1309 pub fn reset(&mut self) -> ContentStyle {
1310 self.final_form_start = 0;
1311 self.forms.clear();
1312 self.absolute_style()
1313 }
1314
1315 #[inline(always)]
1320 pub fn absolute_style(&self) -> ContentStyle {
1321 let mut style = self.default.style;
1322
1323 for &(form, _) in &self.forms {
1324 style.foreground_color = form.fg().or(style.foreground_color);
1325 style.background_color = form.bg().or(style.background_color);
1326 style.underline_color = form.ul().or(style.underline_color);
1327 style.attributes = if form.attrs().has(Attribute::Reset) {
1328 form.attrs()
1329 } else {
1330 form.attrs() | style.attributes
1331 }
1332 }
1333
1334 style
1335 }
1336
1337 #[inline(always)]
1349 pub fn relative_style(&mut self) -> ContentStyle {
1350 let mut style = self.absolute_style();
1351
1352 if style.attributes.has(Attribute::Reset) || self.reset_attrs {
1353 style.attributes.set(Attribute::Reset);
1354 } else {
1358 style.foreground_color = self
1359 .set_fg
1360 .then_some(style.foreground_color.unwrap_or(Color::Reset));
1361 style.background_color = self
1362 .set_bg
1363 .then_some(style.background_color.unwrap_or(Color::Reset));
1364 style.underline_color = self
1365 .set_ul
1366 .then_some(style.underline_color.unwrap_or(Color::Reset));
1367 }
1368
1369 self.set_fg = false;
1370 self.set_bg = false;
1371 self.set_ul = false;
1372 self.reset_attrs = false;
1373
1374 style
1375 }
1376
1377 #[inline(always)]
1379 pub fn apply_main_cursor(&mut self) {
1380 self.apply(M_CAR_ID);
1381 self.final_form_start -= 1;
1382 }
1383
1384 #[inline(always)]
1386 pub fn remove_main_caret(&mut self) {
1387 self.final_form_start += 1;
1388 self.remove(M_CAR_ID);
1389 }
1390
1391 #[inline(always)]
1393 pub fn apply_extra_cursor(&mut self) {
1394 self.apply(E_CAR_ID);
1395 self.final_form_start -= 1;
1396 }
1397
1398 #[inline(always)]
1400 pub fn remove_extra_caret(&mut self) {
1401 self.final_form_start += 1;
1402 self.remove(E_CAR_ID);
1403 }
1404
1405 pub fn main_cursor(&self) -> Option<CursorShape> {
1407 self.inner.main_cursor
1408 }
1409
1410 pub fn extra_cursor(&self) -> Option<CursorShape> {
1412 self.inner.extra_cursor
1413 }
1414
1415 pub fn get_default(&self) -> Form {
1417 self.default
1418 }
1419}
1420
1421pub(crate) fn set_sender(sender: Sender) {
1422 SENDER
1423 .set(sender)
1424 .unwrap_or_else(|_| panic!("Sender set more than once"));
1425}
1426
1427#[derive(Clone)]
1429enum FormType {
1430 Normal,
1431 Ref(usize),
1432 Weakest,
1433 WeakestRef(usize),
1434}
1435
1436fn refs_of(inner: &InnerPalette, refed: usize) -> Vec<usize> {
1438 let mut refs = Vec::new();
1439 for (i, (.., f_ty)) in inner.forms.iter().enumerate() {
1440 if let FormType::Ref(ref_id) | FormType::WeakestRef(ref_id) = f_ty
1441 && *ref_id == refed
1442 {
1443 refs.push(i);
1444 refs.extend(refs_of(inner, i));
1445 }
1446 }
1447 refs
1448}
1449
1450fn would_be_circular(inner: &InnerPalette, referee: usize, refed: usize) -> bool {
1452 if let (.., FormType::Ref(refed_ref) | FormType::WeakestRef(refed_ref)) = inner.forms[refed] {
1453 match refed_ref == referee {
1454 true => true,
1455 false => would_be_circular(inner, referee, refed_ref),
1456 }
1457 } else {
1458 false
1459 }
1460}
1461
1462fn position_and_form(forms: &mut Vec<(&str, Form, FormType)>, name: &'static str) -> (usize, Form) {
1463 if let Some((i, (_, form, _))) = forms.iter().enumerate().find(|(_, (lhs, ..))| *lhs == name) {
1464 (i, *form)
1465 } else if let Some((refed, _)) = name.rsplit_once('.') {
1466 let (i, form) = position_and_form(forms, refed);
1467 forms.push((name, form, FormType::WeakestRef(i)));
1468 (forms.len() - 1, form)
1469 } else {
1470 forms.push((name, Form::new().0, FormType::Weakest));
1471 (forms.len() - 1, Form::new().0)
1472 }
1473}
1474
1475const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1477 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1478 let prefix = prefix.as_bytes();
1479
1480 let mut i = 0;
1481 while i < prefix.len() {
1482 if str.as_bytes()[i] != prefix[i] {
1483 return None;
1484 }
1485 i += 1;
1486 }
1487
1488 Some(str.split_at(prefix.len()).1)
1489 }
1490 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1491 let prefix = suffix.as_bytes();
1492
1493 let mut i = str.len() - 1;
1494 while i >= str.len() - prefix.len() {
1495 if str.as_bytes()[i] != prefix[i - (str.len() - prefix.len())] {
1496 return None;
1497 }
1498 i += 1;
1499 }
1500
1501 Some(str.split_at(str.len() - suffix.len()).0)
1502 }
1503 const fn split_space(str: &str) -> Option<(&str, &str)> {
1504 if str.is_empty() {
1505 return None;
1506 }
1507
1508 let mut i = 0;
1509 while i < str.len() {
1510 if str.as_bytes()[i] == b' ' {
1511 break;
1512 }
1513 i += 1;
1514 }
1515
1516 let (cut, rest) = str.split_at(i);
1517 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1518 Some((cut, rest))
1519 }
1520 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1521 t = if t < 0.0 { t + 1.0 } else { t };
1522 t = if t > 1.0 { t - 1.0 } else { t };
1523 if t < 1.0 / 6.0 {
1524 p + (q - p) * 6.0 * t
1525 } else if t < 1.0 / 2.0 {
1526 q
1527 } else if t < 2.0 / 3.0 {
1528 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1529 } else {
1530 p
1531 }
1532 }
1533
1534 if let Some(hex) = strip_prefix("#", str) {
1536 let total = match u32::from_str_radix(hex, 16) {
1537 Ok(total) if hex.len() == 6 => total,
1538 _ => return Err("Hexcode does not contain 6 hex values"),
1539 };
1540 let r = (total >> 16) as u8;
1541 let g = (total >> 8) as u8;
1542 let b = total as u8;
1543
1544 Ok(Color::Rgb { r, g, b })
1545 } else if let Some(mut rgb) = strip_prefix("rgb ", str) {
1547 let mut values = [0, 0, 0];
1548 let mut i = 0;
1549
1550 while i < values.len() {
1551 if let Some((cut, rest)) = split_space(rgb) {
1552 rgb = rest;
1553 values[i] = match u8::from_str_radix(cut, 10) {
1554 Ok(value) => value,
1555 Err(_) => return Err("Rgb format value could not be parsed"),
1556 }
1557 } else {
1558 return Err("Missing value in rgb format");
1559 }
1560 i += 1;
1561 }
1562
1563 let [r, g, b] = values;
1564 Ok(Color::Rgb { r, g, b })
1565 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1567 let mut values = [0.0, 0.0, 0.0];
1568 let mut i = 0;
1569 while i < values.len() {
1570 if let Some((cut, rest)) = split_space(hsl) {
1571 hsl = rest;
1572 let (num, div) = match strip_suffix("%", cut) {
1573 Some(perc) => (perc, 100),
1574 None => (cut, 255),
1575 };
1576 values[i] = match u8::from_str_radix(num, 10) {
1577 Ok(value) if value <= div => value as f32 / div as f32,
1578 _ => return Err("Hsl format property could not be parsed"),
1579 }
1580 } else {
1581 return Err("Missing value in hsl format");
1582 }
1583 i += 1;
1584 }
1585 let [hue, sat, lit] = values;
1586
1587 let (r, g, b) = if sat == 0.0 {
1588 (lit, lit, lit)
1589 } else {
1590 let q = if lit < 0.5 {
1591 lit * (1.0 + sat)
1592 } else {
1593 lit + sat - lit * sat
1594 };
1595 let p = 2.0 * lit - q;
1596 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1597 let g = hue_to_rgb(p, q, hue);
1598 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1599 (r, g, b)
1600 };
1601
1602 let r = (0.5 + r * 255.0) as u8;
1604 let g = (0.5 + g * 255.0) as u8;
1605 let b = (0.5 + b * 255.0) as u8;
1606 Ok(Color::Rgb { r, g, b })
1607 } else {
1608 Err("Color format was not recognized")
1609 }
1610}
1611
1612impl std::fmt::Debug for Form {
1613 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1614 struct DebugColor(Option<Color>);
1615 impl std::fmt::Debug for DebugColor {
1616 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1617 match self.0 {
1618 Some(Color::Rgb { r, g, b }) => write!(f, "Some(Rgb({r}, {g}, {b}))"),
1619 Some(Color::AnsiValue(ansi)) => write!(f, "Some(Ansi({ansi}))"),
1620 Some(color) => write!(f, "Some({color:?})"),
1621 None => f.write_str("None"),
1622 }
1623 }
1624 }
1625
1626 struct DebugAttributes(Attributes);
1627 impl std::fmt::Debug for DebugAttributes {
1628 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1629 if self.0.is_empty() {
1630 f.write_str("None")
1631 } else {
1632 let mut is_first = true;
1633 for attr in Attribute::iterator() {
1634 if self.0.has(attr) {
1635 if !is_first {
1636 f.write_str(" | ")?;
1637 }
1638 is_first = false;
1639 write!(f, "{attr:?}")?;
1640 }
1641 }
1642 Ok(())
1643 }
1644 }
1645 }
1646
1647 f.debug_struct("Form")
1648 .field("fg", &DebugColor(self.style.foreground_color))
1649 .field("bg", &DebugColor(self.style.background_color))
1650 .field("ul", &DebugColor(self.style.underline_color))
1651 .field("attr", &DebugAttributes(self.style.attributes))
1652 .finish()
1653 }
1654}
1655
1656impl std::fmt::Debug for InnerPalette {
1657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1658 struct DebugForms<'a>(&'a [(&'static str, Form, FormType)]);
1659 impl std::fmt::Debug for DebugForms<'_> {
1660 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1661 if f.alternate() {
1662 f.write_str("[\n")?;
1663 let max = self.0.len().ilog10() as usize + 3;
1664 for (n, (name, form, ty)) in self.0.iter().enumerate() {
1665 let num = format!("{n}:");
1666 writeln!(f, "{num:<max$}({name}, {ty:?}, {form:#?})")?;
1667 }
1668 f.write_str("]")
1669 } else {
1670 write!(f, "{:?}", self.0)
1671 }
1672 }
1673 }
1674
1675 struct DebugCursorShape(CursorShape);
1676 impl std::fmt::Debug for DebugCursorShape {
1677 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1678 match self.0 {
1679 CursorShape::DefaultUserShape => f.write_str("DefaultUserShape"),
1680 CursorShape::BlinkingBlock => f.write_str("BlinkingBlock"),
1681 CursorShape::SteadyBlock => f.write_str("SteadyBlock"),
1682 CursorShape::BlinkingUnderScore => f.write_str("BlinkingUnderScore"),
1683 CursorShape::SteadyUnderScore => f.write_str("SteadyUnderScore"),
1684 CursorShape::BlinkingBar => f.write_str("BlinkingBar"),
1685 CursorShape::SteadyBar => f.write_str("SteadyBar"),
1686 }
1687 }
1688 }
1689
1690 f.debug_struct("InnerPalette")
1691 .field("main_cursor", &self.main_cursor.map(DebugCursorShape))
1692 .field("extra_cursor", &self.extra_cursor.map(DebugCursorShape))
1693 .field("forms", &DebugForms(&self.forms))
1694 .field("masks", &self.masks)
1695 .finish()
1696 }
1697}
1698
1699impl std::fmt::Debug for FormType {
1700 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1701 match self {
1702 Self::Normal => write!(f, "Normal"),
1703 Self::Ref(refed) => write!(f, "Ref({refed})"),
1704 Self::Weakest => write!(f, "Weakest"),
1705 Self::WeakestRef(refed) => write!(f, "WeakestRef({refed})"),
1706 }
1707 }
1708}
1709
1710macro mimic_method_new {
1712 (#[$attr:meta] $method:ident $attrib:expr) => {
1713 #[$attr]
1715 pub const fn $method() -> BuiltForm {
1717 let mut built = Form::new();
1718 built.0.style.attributes = built.0.style.attributes.with($attrib);
1719 built
1720 }
1721 },
1722
1723 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1724 #[$attr]
1726 pub const fn $fg() -> BuiltForm {
1728 let mut built = Form::new();
1729 built.0.style.foreground_color = Some($color);
1730 built
1731 }
1732
1733 #[$attr]
1735 pub const fn $bg() -> BuiltForm {
1737 let mut built = Form::new();
1738 built.0.style.background_color = Some($color);
1739 built
1740 }
1741
1742 #[$attr]
1744 pub const fn $ul() -> BuiltForm {
1750 let mut built = Form::new();
1751 built.0.style.underline_color = Some($color);
1752 built
1753 }
1754 }
1755}
1756
1757macro mimic_method_mod {
1758 (#[$attr:meta] $method:ident $attrib:expr) => {
1759 #[$attr]
1761 pub const fn $method(mut self) -> Self {
1763 self.0.style.attributes = self.0.style.attributes.with($attrib);
1764 self
1765 }
1766 },
1767
1768 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1769 #[$attr]
1771 pub const fn $fg(mut self) -> Self {
1772 self.0.style.foreground_color = Some($color);
1773 self
1774 }
1775
1776 #[$attr]
1778 pub const fn $bg(mut self) -> Self {
1779 self.0.style.background_color = Some($color);
1780 self
1781 }
1782
1783 #[$attr]
1785 pub const fn $ul(mut self) -> Self {
1790 self.0.style.underline_color = Some($color);
1791 self
1792 }
1793 }
1794}