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 {
105 let kind = form.kind();
106 let name: &'static str = name.to_string().leak();
107
108 match kind {
109 Kind::Form(form) => queue(move || PALETTE.set_form(name, form)),
110 Kind::Ref(refed) => queue(move || PALETTE.set_ref(name, refed)),
111 };
112
113 let mut forms = FORMS.lock().unwrap();
114 if let Kind::Ref(refed) = kind {
115 position_of_name(&mut forms, refed);
116 }
117 FormId(position_of_name(&mut forms, name) as u16)
118 }
119
120 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.set_weak_form(name, form)),
150 Kind::Ref(refed) => queue(move || PALETTE.set_weak_ref(name, refed)),
151 };
152
153 let mut forms = FORMS.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.form_from_id(id).unwrap_or(Form::new().0)
163 }
164
165 pub fn main_cursor() -> (Form, Option<CursorShape>) {
167 PALETTE.main_cursor()
168 }
169
170 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
172 PALETTE.extra_cursor()
173 }
174
175 pub fn set_main_cursor(shape: CursorShape) {
198 queue(move || PALETTE.set_main_cursor(shape));
199 }
200
201 pub fn set_extra_cursor(shape: CursorShape) {
224 queue(move || PALETTE.set_extra_cursor(shape));
225 }
226
227 pub fn unset_main_cursor() {
238 queue(move || PALETTE.unset_main_cursor());
239 }
240
241 pub fn unset_extra_cursor() {
255 queue(move || PALETTE.unset_extra_cursor());
256 }
257
258 pub(crate) fn painter_with_mask<W: ?Sized + 'static>(mask: &'static str) -> Painter {
260 PALETTE.painter(default_id(TypeId::of::<W>(), crate::duat_name::<W>()), mask)
261 }
262
263 pub fn enable_mask(mask: &'static str) {
324 queue(move || {
325 let mut inner = PALETTE.0.write().unwrap();
326 if !inner.masks.iter().any(|(m, _)| *m == mask) {
327 let mut remaps: Vec<u16> = (0..inner.forms.len() as u16).collect();
328
329 for (i, (name, ..)) in inner.forms.iter().enumerate() {
330 if let Some((pref, suf)) = name.rsplit_once('.')
331 && suf == mask
332 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
333 {
334 remaps[j] = i as u16;
335 }
336 }
337
338 inner.masks.push((mask, remaps));
339 }
340 })
341 }
342
343 pub macro id_of {
373 ($form:expr) => {{
374 static ID: std::sync::OnceLock<FormId> = std::sync::OnceLock::new();
375 *ID.get_or_init(|| {
376 let name: &'static str = $form;
377 let id = id_from_name(name);
378 add_forms(vec![name]);
379 id
380 })
381 }},
382 ($($form:expr),+) => {{
383 static IDS: std::sync::OnceLock<&[FormId]> = std::sync::OnceLock::new();
384 let ids = *IDS.get_or_init(|| {
385 let mut ids = Vec::new();
386 let names = vec![$( $form ),+];
387 for name in names.iter() {
388 ids.push(id_from_name(name));
389 }
390 add_forms(names);
391 ids.leak()
392 });
393 ids
394 }}
395 }
396
397 pub fn ids_of_non_static(names: impl IntoIterator<Item = impl ToString>) -> Vec<FormId> {
404 let names: Vec<&str> = names
405 .into_iter()
406 .map(|n| {
407 let str: &'static str = n.to_string().leak();
408 str
409 })
410 .collect();
411
412 let mut ids = Vec::new();
413 let mut forms = FORMS.lock().unwrap();
414 for name in names.iter() {
415 ids.push(FormId(position_of_name(&mut forms, name) as u16));
416 }
417 add_forms(names);
418 ids
419 }
420
421 #[doc(hidden)]
423 pub fn id_from_name(name: &'static str) -> FormId {
424 let mut forms = FORMS.lock().unwrap();
425 FormId(position_of_name(&mut forms, name) as u16)
426 }
427
428 #[doc(hidden)]
429 pub fn add_forms(names: Vec<&'static str>) {
430 queue(move || PALETTE.set_many(names.as_ref()));
431 }
432
433 pub fn add_colorscheme(cs: impl ColorScheme) {
444 let mut colorschemes = COLORSCHEMES.lock().unwrap();
445 let name = cs.name();
446 if let Some(i) = colorschemes.iter().position(|cs| cs.name() == name) {
447 colorschemes[i] = Box::new(cs);
448 } else {
449 colorschemes.push(Box::new(cs));
450 }
451 }
452
453 pub fn set_colorscheme(name: &str) {
460 let colorschemes = COLORSCHEMES.lock().unwrap();
461 if let Some(cs) = colorschemes.iter().find(|cs| cs.name() == name) {
462 cs.apply();
463 hook::queue(ColorSchemeSet(cs.name()));
464 } else {
465 context::error!("The colorscheme [a]{name}[] was not found");
466 }
467 }
468
469 pub macro set_many($(($name:literal, $form:expr)),+ $(,)?) {{
473 $(
474 set($name, $form);
475 )+
476 }}
477
478 pub(crate) fn exists(name: &str) -> bool {
480 FORMS.lock().unwrap().contains(&name)
481 }
482
483 pub(crate) fn colorscheme_exists(name: &str) -> bool {
485 COLORSCHEMES
486 .lock()
487 .unwrap()
488 .iter()
489 .any(|cs| cs.name() == name)
490 }
491
492 pub(super) fn name_of(id: FormId) -> &'static str {
494 FORMS.lock().unwrap()[id.0 as usize]
495 }
496
497 fn default_id(type_id: TypeId, type_name: &'static str) -> FormId {
498 static IDS: LazyLock<Mutex<HashMap<TypeId, FormId>>> = LazyLock::new(Mutex::default);
499 let mut ids = IDS.lock().unwrap();
500
501 if let Some(id) = ids.get(&type_id) {
502 *id
503 } else {
504 let name: &'static str = format!("default.{type_name}").leak();
505 let id = id_from_name(name);
506 add_forms(vec![name]);
507 ids.insert(type_id, id);
508 id
509 }
510 }
511
512 fn position_of_name(names: &mut Vec<&'static str>, name: &'static str) -> usize {
513 if let Some((i, _)) = names.iter().enumerate().find(|(_, rhs)| **rhs == name) {
514 i
515 } else if let Some((refed, _)) = name.rsplit_once('.') {
516 position_of_name(names, refed);
517 names.push(name);
518 names.len() - 1
519 } else {
520 names.push(name);
521 names.len() - 1
522 }
523 }
524
525 fn queue<R>(f: impl FnOnce() -> R + Send + Sync + 'static) {
526 static SENDER: Mutex<Option<mpsc::Sender<Box<dyn FnOnce() + Send + Sync>>>> =
527 Mutex::new(None);
528
529 if context::will_reload_or_quit() {
530 return;
531 }
532
533 let f = Box::new(move || {
534 f();
535 });
536
537 let mut sender = SENDER.lock().unwrap();
538 let f = if let Some(tx) = sender.as_ref() {
539 let Err(err) = tx.send(f) else {
540 return;
541 };
542 err.0
543 } else {
544 f
545 };
546 let (tx, rx) = mpsc::channel();
547 tx.send(f).unwrap();
548 *sender = Some(tx);
549
550 thread::spawn(move || {
551 while let Ok(f) = rx.recv_timeout(Duration::from_micros(500)) {
552 f();
553 }
554 });
555 }
556
557 #[derive(Clone, Copy)]
559 enum Kind {
560 Form(Form),
561 Ref(&'static str),
562 }
563
564 trait InnerFormFmt {
568 fn kind(self) -> Kind;
570 }
571
572 impl InnerFormFmt for Form {
573 fn kind(self) -> Kind {
574 Kind::Form(self)
575 }
576 }
577
578 impl InnerFormFmt for BuiltForm {
579 fn kind(self) -> Kind {
580 Kind::Form(self.0)
581 }
582 }
583
584 impl InnerFormFmt for &str {
585 fn kind(self) -> Kind {
586 Kind::Ref(self.to_string().leak())
587 }
588 }
589
590 impl InnerFormFmt for &mut str {
591 fn kind(self) -> Kind {
592 Kind::Ref(self.to_string().leak())
593 }
594 }
595
596 impl InnerFormFmt for String {
597 fn kind(self) -> Kind {
598 Kind::Ref(self.leak())
599 }
600 }
601}
602
603#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
617pub struct FormId(u16);
618
619impl FormId {
620 pub const fn to_tag(self, prio: u8) -> FormTag {
629 FormTag(self, prio)
630 }
631
632 pub const fn to_u16(self) -> u16 {
636 self.0
637 }
638
639 pub fn name(self) -> &'static str {
641 name_of(self)
642 }
643}
644
645impl std::fmt::Debug for FormId {
646 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
647 write!(f, "FormId({})", name_of(*self))
648 }
649}
650
651#[derive(Clone, Copy, PartialEq, Eq)]
653pub struct Form {
654 pub style: ContentStyle,
656}
657
658#[rustfmt::skip]
659impl Form {
660 mimic_method_new!(bold Attribute::Bold);
661 mimic_method_new!(dim Attribute::Dim);
662 mimic_method_new!(italic Attribute::Italic);
663 mimic_method_new!(underlined Attribute::Underlined);
664 mimic_method_new!(double_underlined Attribute::DoubleUnderlined);
665 mimic_method_new!(undercurled Attribute::Undercurled);
666 mimic_method_new!(underdashed Attribute::Underdashed);
667 mimic_method_new!(reverse Attribute::Reverse);
668 mimic_method_new!(crossed_out Attribute::CrossedOut);
669 mimic_method_new!(black on_black underline_black Color::Black);
670 mimic_method_new!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
671 mimic_method_new!(red on_red underline_red Color::Red);
672 mimic_method_new!(dark_red on_dark_red underline_dark_red Color::DarkRed);
673 mimic_method_new!(green on_green underline_green Color::Green);
674 mimic_method_new!(
675 dark_green on_dark_green underline_dark_green Color::DarkGreen
676 );
677 mimic_method_new!(yellow on_yellow underline_yellow Color::Yellow);
678 mimic_method_new!(
679 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
680 );
681 mimic_method_new!(blue on_blue underline_blue Color::Blue);
682 mimic_method_new!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
683 mimic_method_new!(magenta on_magenta underline_magenta Color::Magenta);
684 mimic_method_new!(
685 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
686 );
687 mimic_method_new!(cyan on_cyan underline_cyan Color::Cyan);
688 mimic_method_new!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
689 mimic_method_new!(white on_white underline_white Color::White);
690 mimic_method_new!(grey on_grey underline_grey Color::Grey);
691}
692
693impl Form {
694 #[allow(clippy::new_ret_no_self)]
698 pub const fn new() -> BuiltForm {
699 let style = ContentStyle {
700 foreground_color: None,
701 background_color: None,
702 underline_color: None,
703 attributes: Attributes::none(),
704 };
705 BuiltForm(Self { style })
706 }
707
708 pub const fn reset() -> BuiltForm {
715 let mut built = Form::new();
716 built.0.style.attributes = built.0.style.attributes.with(Attribute::Reset);
717 built
718 }
719
720 pub const fn with(str: &str) -> BuiltForm {
730 let mut built = Form::new();
731 built.0.style.foreground_color = match str_to_color(str) {
732 Ok(color) => Some(color),
733 Err(err) => panic!("{}", err),
734 };
735 built
736 }
737
738 pub const fn on(str: &str) -> BuiltForm {
748 let mut built = Form::new();
749 built.0.style.background_color = match str_to_color(str) {
750 Ok(color) => Some(color),
751 Err(err) => panic!("{}", err),
752 };
753 built
754 }
755
756 pub const fn underline(str: &str) -> BuiltForm {
766 let mut built = Form::new();
767 built.0.style.underline_color = match str_to_color(str) {
768 Ok(color) => Some(color),
769 Err(err) => panic!("{}", err),
770 };
771 built
772 }
773
774 pub const fn fg(&self) -> Option<Color> {
776 self.style.foreground_color
777 }
778
779 pub const fn bg(&self) -> Option<Color> {
781 self.style.background_color
782 }
783
784 pub const fn ul(&self) -> Option<Color> {
786 self.style.underline_color
787 }
788
789 pub const fn attrs(&self) -> Attributes {
791 self.style.attributes
792 }
793}
794
795#[derive(Clone, Copy, Debug)]
804pub struct BuiltForm(Form);
805
806#[rustfmt::skip]
807impl BuiltForm {
808 mimic_method_mod!(bold Attribute::Bold);
809 mimic_method_mod!(dim Attribute::Dim);
810 mimic_method_mod!(italic Attribute::Italic);
811 mimic_method_mod!(underlined Attribute::Underlined);
812 mimic_method_mod!(double_underlined Attribute::DoubleUnderlined);
813 mimic_method_mod!(undercurled Attribute::Undercurled);
814 mimic_method_mod!(underdashed Attribute::Underdashed);
815 mimic_method_mod!(reverse Attribute::Reverse);
816 mimic_method_mod!(crossed_out Attribute::CrossedOut);
817 mimic_method_mod!(overlined Attribute::OverLined);
818 mimic_method_mod!(black on_black underline_black Color::Black);
819 mimic_method_mod!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
820 mimic_method_mod!(red on_red underline_red Color::Red);
821 mimic_method_mod!(dark_red on_dark_red underline_dark_red Color::DarkRed);
822 mimic_method_mod!(green on_green underline_green Color::Green);
823 mimic_method_mod!(
824 dark_green on_dark_green underline_dark_green Color::DarkGreen
825 );
826 mimic_method_mod!(yellow on_yellow underline_yellow Color::Yellow);
827 mimic_method_mod!(
828 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
829 );
830 mimic_method_mod!(blue on_blue underline_blue Color::Blue);
831 mimic_method_mod!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
832 mimic_method_mod!(magenta on_magenta underline_magenta Color::Magenta);
833 mimic_method_mod!(
834 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
835 );
836 mimic_method_mod!(cyan on_cyan underline_cyan Color::Cyan);
837 mimic_method_mod!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
838 mimic_method_mod!(white on_white underline_white Color::White);
839 mimic_method_mod!(grey on_grey underline_grey Color::Grey);
840}
841
842impl BuiltForm {
843 pub const fn reset(mut self) -> BuiltForm {
850 self.0.style.attributes = self.0.style.attributes.with(Attribute::Reset);
851 self
852 }
853
854 pub const fn with(mut self, str: &str) -> Self {
864 self.0.style.foreground_color = match str_to_color(str) {
865 Ok(color) => Some(color),
866 Err(err) => panic!("{}", err),
867 };
868 self
869 }
870
871 pub const fn on(mut self, str: &str) -> Self {
881 self.0.style.background_color = match str_to_color(str) {
882 Ok(color) => Some(color),
883 Err(err) => panic!("{}", err),
884 };
885 self
886 }
887
888 pub const fn underline(mut self, str: &str) -> Self {
898 self.0.style.underline_color = match str_to_color(str) {
899 Ok(color) => Some(color),
900 Err(err) => panic!("{}", err),
901 };
902 self
903 }
904}
905
906impl std::ops::Deref for BuiltForm {
907 type Target = Form;
908
909 fn deref(&self) -> &Self::Target {
910 &self.0
911 }
912}
913
914impl std::ops::DerefMut for BuiltForm {
915 fn deref_mut(&mut self) -> &mut Self::Target {
916 &mut self.0
917 }
918}
919
920pub const DEFAULT_ID: FormId = FormId(0);
922pub const ACCENT_ID: FormId = FormId(1);
924pub const M_CAR_ID: FormId = FormId(2);
926pub const E_CAR_ID: FormId = FormId(3);
928pub const M_SEL_ID: FormId = FormId(4);
930pub const E_SEL_ID: FormId = FormId(5);
932
933struct InnerPalette {
934 main_cursor: Option<CursorShape>,
935 extra_cursor: Option<CursorShape>,
936 forms: Vec<(&'static str, Form, FormType)>,
937 masks: Vec<(&'static str, Vec<u16>)>,
938}
939
940struct Palette(LazyLock<RwLock<InnerPalette>>);
942
943impl Palette {
944 const fn new() -> Self {
946 Self(LazyLock::new(|| {
947 let main_cursor = Some(CursorShape::DefaultUserShape);
948
949 RwLock::new(InnerPalette {
950 main_cursor,
951 extra_cursor: main_cursor,
952 forms: BASE_FORMS.to_vec(),
953 masks: vec![("", (0..BASE_FORMS.len() as u16).collect())],
954 })
955 }))
956 }
957
958 fn set_form(&self, name: &'static str, form: Form) {
960 let mut inner = self.0.write().unwrap();
961 let (i, _) = position_and_form(&mut inner.forms, name);
962
963 inner.forms[i] = (name, form, FormType::Normal);
964
965 for refed in refs_of(&inner, i) {
966 inner.forms[refed].1 = form;
967 }
968
969 if let Some(sender) = SENDER.get() {
970 sender.send_form_changed().unwrap()
971 }
972
973 mask_form(name, i, &mut inner);
974 hook::queue(FormSet((name, FormId(i as u16), form)));
975 }
976
977 fn set_weak_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 let (_, f, f_ty) = &mut inner.forms[i];
983 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
984 *f = form;
985 *f_ty = FormType::Normal;
986
987 if let Some(sender) = SENDER.get() {
988 sender.send_form_changed().unwrap()
989 }
990 for refed in refs_of(&inner, i) {
991 inner.forms[refed].1 = form;
992 }
993
994 mask_form(name, i, &mut inner);
995 }
996 }
997
998 fn set_ref(&self, name: &'static str, refed: &'static str) {
1000 let mut inner = self.0.write().unwrap();
1001 let (refed, form) = position_and_form(&mut inner.forms, refed);
1002 let (i, _) = position_and_form(&mut inner.forms, name);
1003
1004 for refed in refs_of(&inner, i) {
1005 inner.forms[refed].1 = form;
1006 }
1007
1008 if would_be_circular(&inner, i, refed) {
1010 inner.forms[i] = (name, form, FormType::Normal);
1011 } else {
1012 inner.forms[i] = (name, form, FormType::Ref(refed));
1013 }
1014
1015 if let Some(sender) = SENDER.get() {
1016 sender.send_form_changed().unwrap()
1017 }
1018
1019 mask_form(name, i, &mut inner);
1020 hook::queue(FormSet((name, FormId(i as u16), form)));
1021 }
1022
1023 fn set_weak_ref(&self, name: &'static str, refed: &'static str) {
1025 let mut inner = self.0.write().unwrap();
1026 let (refed, form) = position_and_form(&mut inner.forms, refed);
1027 let (i, _) = position_and_form(&mut inner.forms, name);
1028
1029 let (_, f, f_ty) = &mut inner.forms[i];
1032 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
1033 *f = form;
1034 *f_ty = FormType::WeakestRef(refed);
1035
1036 if let Some(sender) = SENDER.get() {
1037 sender.send_form_changed().unwrap()
1038 }
1039 for refed in refs_of(&inner, i) {
1040 inner.forms[refed].1 = form;
1041 }
1042
1043 mask_form(name, i, &mut inner);
1044 }
1045 }
1046
1047 fn set_many(&self, names: &[&'static str]) {
1049 let mut inner = self.0.write().unwrap();
1050 let form_indices: Vec<(usize, &str)> = names
1051 .iter()
1052 .map(|name| {
1053 let (i, _) = position_and_form(&mut inner.forms, name);
1054 (i, *name)
1055 })
1056 .collect();
1057
1058 for (i, name) in form_indices {
1059 mask_form(name, i, &mut inner);
1060 }
1061 }
1062
1063 fn form_from_id(&self, id: FormId) -> Option<Form> {
1065 let inner = self.0.read().unwrap();
1066 inner.forms.get(id.0 as usize).map(|(_, form, _)| *form)
1067 }
1068
1069 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
1071 let form = self.form_from_id(M_CAR_ID).unwrap();
1072 (form, self.0.read().unwrap().main_cursor)
1073 }
1074
1075 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
1077 let form = self.form_from_id(E_CAR_ID).unwrap();
1078 (form, self.0.read().unwrap().extra_cursor)
1079 }
1080
1081 fn set_main_cursor(&self, shape: CursorShape) {
1083 self.0.write().unwrap().main_cursor = Some(shape);
1084 if let Some(sender) = SENDER.get() {
1085 sender.send_form_changed().unwrap()
1086 }
1087 }
1088
1089 fn set_extra_cursor(&self, shape: CursorShape) {
1091 self.0.write().unwrap().extra_cursor = Some(shape);
1092 if let Some(sender) = SENDER.get() {
1093 sender.send_form_changed().unwrap()
1094 }
1095 }
1096
1097 fn unset_main_cursor(&self) {
1099 self.0.write().unwrap().main_cursor = None;
1100 if let Some(sender) = SENDER.get() {
1101 sender.send_form_changed().unwrap()
1102 }
1103 }
1104
1105 fn unset_extra_cursor(&self) {
1107 self.0.write().unwrap().extra_cursor = None;
1108 if let Some(sender) = SENDER.get() {
1109 sender.send_form_changed().unwrap()
1110 }
1111 }
1112
1113 fn painter(&'static self, default_id: FormId, mask: &str) -> Painter {
1115 let inner = self.0.read().unwrap();
1116 let mask_i = inner
1117 .masks
1118 .iter()
1119 .position(|(m, _)| *m == mask)
1120 .unwrap_or_default();
1121
1122 let default = inner
1123 .forms
1124 .get(match inner.masks[mask_i].1.get(default_id.0 as usize) {
1125 Some(i) => *i as usize,
1126 None => default_id.0 as usize,
1127 })
1128 .map(|(_, f, _)| *f)
1129 .unwrap_or(Form::new().0);
1130
1131 Painter {
1132 inner,
1133 mask_i,
1134 default,
1135 forms: Vec::new(),
1136 final_form_start: 0,
1137 set_fg: true,
1138 set_bg: true,
1139 set_ul: true,
1140 reset_attrs: false,
1141 }
1142 }
1143}
1144
1145fn mask_form(name: &'static str, form_i: usize, inner: &mut InnerPalette) {
1147 if inner.masks[0].1.len() < inner.forms.len() {
1148 for (_, remaps) in inner.masks.iter_mut() {
1149 remaps.extend(remaps.len() as u16..inner.forms.len() as u16);
1150 }
1151 }
1152
1153 if let Some((pref, mask)) = name.rsplit_once(".")
1154 && let Some((_, remaps)) = inner.masks.iter_mut().find(|(m, _)| *m == mask)
1155 && let Some(j) = inner.forms.iter().position(|(name, ..)| *name == pref)
1156 {
1157 remaps[j] = form_i as u16;
1158 }
1159}
1160
1161pub struct Painter {
1222 inner: RwLockReadGuard<'static, InnerPalette>,
1223 mask_i: usize,
1224 default: Form,
1225 forms: Vec<(Form, FormId)>,
1226 final_form_start: usize,
1227 set_fg: bool,
1228 set_bg: bool,
1229 set_ul: bool,
1230 reset_attrs: bool,
1231}
1232
1233impl Painter {
1234 #[inline(always)]
1242 pub fn apply(&mut self, id: FormId) {
1243 let (_, mask) = &self.inner.masks[self.mask_i];
1244 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1245
1246 let forms = &self.inner.forms;
1247 let form = forms
1248 .get(id.0 as usize)
1249 .map(|(_, f, _)| *f)
1250 .unwrap_or(Form::new().0);
1251
1252 self.forms.insert(self.final_form_start, (form, id));
1253 if id != M_SEL_ID && id != E_SEL_ID {
1254 self.final_form_start += 1;
1255 }
1256
1257 self.set_fg |= form.fg().is_some();
1258 self.set_bg |= form.bg().is_some();
1259 self.set_ul |= form.ul().is_some();
1260 self.reset_attrs |= form.attrs().has(Attribute::Reset);
1261 }
1262
1263 #[inline(always)]
1266 pub fn remove(&mut self, id: FormId) {
1267 let mask = &self.inner.masks[self.mask_i].1;
1268 let id = FormId(mask.get(id.0 as usize).copied().unwrap_or(id.0));
1269
1270 let mut applied_forms = self.forms.iter().enumerate();
1271 if let Some((i, &(form, _))) = applied_forms.rfind(|(_, (_, lhs))| *lhs == id) {
1272 self.forms.remove(i);
1273 if id != M_SEL_ID && id != E_SEL_ID {
1274 self.final_form_start -= 1;
1275 }
1276
1277 self.set_fg |= form.fg().is_some();
1278 self.set_bg |= form.bg().is_some();
1279 self.set_ul |= form.ul().is_some();
1280 self.reset_attrs |= !form.attrs().is_empty();
1281 };
1282 }
1283
1284 #[inline(always)]
1290 pub fn reset(&mut self) -> ContentStyle {
1291 self.final_form_start = 0;
1292 self.forms.clear();
1293 self.absolute_style()
1294 }
1295
1296 #[inline(always)]
1301 pub fn absolute_style(&self) -> ContentStyle {
1302 let mut style = self.default.style;
1303
1304 for &(form, _) in &self.forms {
1305 style.foreground_color = form.fg().or(style.foreground_color);
1306 style.background_color = form.bg().or(style.background_color);
1307 style.underline_color = form.ul().or(style.underline_color);
1308 style.attributes = if form.attrs().has(Attribute::Reset) {
1309 form.attrs()
1310 } else {
1311 form.attrs() | style.attributes
1312 }
1313 }
1314
1315 style
1316 }
1317
1318 #[inline(always)]
1330 pub fn relative_style(&mut self) -> ContentStyle {
1331 let mut style = self.absolute_style();
1332
1333 if style.attributes.has(Attribute::Reset) || self.reset_attrs {
1334 style.attributes.set(Attribute::Reset);
1335 } else {
1339 style.foreground_color = self
1340 .set_fg
1341 .then_some(style.foreground_color.unwrap_or(Color::Reset));
1342 style.background_color = self
1343 .set_bg
1344 .then_some(style.background_color.unwrap_or(Color::Reset));
1345 style.underline_color = self
1346 .set_ul
1347 .then_some(style.underline_color.unwrap_or(Color::Reset));
1348 }
1349
1350 self.set_fg = false;
1351 self.set_bg = false;
1352 self.set_ul = false;
1353 self.reset_attrs = false;
1354
1355 style
1356 }
1357
1358 #[inline(always)]
1360 pub fn apply_main_cursor(&mut self) {
1361 self.apply(M_CAR_ID);
1362 self.final_form_start -= 1;
1363 }
1364
1365 #[inline(always)]
1367 pub fn remove_main_caret(&mut self) {
1368 self.final_form_start += 1;
1369 self.remove(M_CAR_ID);
1370 }
1371
1372 #[inline(always)]
1374 pub fn apply_extra_cursor(&mut self) {
1375 self.apply(E_CAR_ID);
1376 self.final_form_start -= 1;
1377 }
1378
1379 #[inline(always)]
1381 pub fn remove_extra_caret(&mut self) {
1382 self.final_form_start += 1;
1383 self.remove(E_CAR_ID);
1384 }
1385
1386 pub fn main_cursor(&self) -> Option<CursorShape> {
1388 self.inner.main_cursor
1389 }
1390
1391 pub fn extra_cursor(&self) -> Option<CursorShape> {
1393 self.inner.extra_cursor
1394 }
1395
1396 pub fn get_default(&self) -> Form {
1398 self.default
1399 }
1400}
1401
1402pub(crate) fn set_sender(sender: Sender) {
1403 SENDER
1404 .set(sender)
1405 .unwrap_or_else(|_| panic!("Sender set more than once"));
1406}
1407
1408#[derive(Clone)]
1410enum FormType {
1411 Normal,
1412 Ref(usize),
1413 Weakest,
1414 WeakestRef(usize),
1415}
1416
1417fn refs_of(inner: &InnerPalette, refed: usize) -> Vec<usize> {
1419 let mut refs = Vec::new();
1420 for (i, (.., f_ty)) in inner.forms.iter().enumerate() {
1421 if let FormType::Ref(ref_id) | FormType::WeakestRef(ref_id) = f_ty
1422 && *ref_id == refed
1423 {
1424 refs.push(i);
1425 refs.extend(refs_of(inner, i));
1426 }
1427 }
1428 refs
1429}
1430
1431fn would_be_circular(inner: &InnerPalette, referee: usize, refed: usize) -> bool {
1433 if let (.., FormType::Ref(refed_ref) | FormType::WeakestRef(refed_ref)) = inner.forms[refed] {
1434 match refed_ref == referee {
1435 true => true,
1436 false => would_be_circular(inner, referee, refed_ref),
1437 }
1438 } else {
1439 false
1440 }
1441}
1442
1443fn position_and_form(forms: &mut Vec<(&str, Form, FormType)>, name: &'static str) -> (usize, Form) {
1444 if let Some((i, (_, form, _))) = forms.iter().enumerate().find(|(_, (lhs, ..))| *lhs == name) {
1445 (i, *form)
1446 } else if let Some((refed, _)) = name.rsplit_once('.') {
1447 let (i, form) = position_and_form(forms, refed);
1448 forms.push((name, form, FormType::WeakestRef(i)));
1449 (forms.len() - 1, form)
1450 } else {
1451 forms.push((name, Form::new().0, FormType::Weakest));
1452 (forms.len() - 1, Form::new().0)
1453 }
1454}
1455
1456const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1458 use core::str::from_utf8_unchecked as utf8_str;
1459 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1460 let prefix = prefix.as_bytes();
1461 let str = str.as_bytes();
1462
1463 let mut i = 0;
1464 while i < prefix.len() {
1465 if str[i] != prefix[i] {
1466 return None;
1467 }
1468 i += 1;
1469 }
1470
1471 let (_, str) = str.split_at(prefix.len());
1472 Some(unsafe { utf8_str(str) })
1473 }
1474 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1475 let prefix = suffix.as_bytes();
1476 let str = str.as_bytes();
1477
1478 let mut i = str.len() - 1;
1479 while i >= str.len() - prefix.len() {
1480 if str[i] != prefix[i - (str.len() - prefix.len())] {
1481 return None;
1482 }
1483 i += 1;
1484 }
1485
1486 let (str, _) = str.split_at(str.len() - suffix.len());
1487 Some(unsafe { utf8_str(str) })
1488 }
1489 const fn split_space(str: &str) -> Option<(&str, &str)> {
1490 if str.is_empty() {
1491 return None;
1492 }
1493 let str = str.as_bytes();
1494
1495 let mut i = 0;
1496 while i < str.len() {
1497 if str[i] == b' ' {
1498 break;
1499 }
1500 i += 1;
1501 }
1502
1503 let (cut, rest) = str.split_at(i);
1504 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1505 Some(unsafe { (utf8_str(cut), utf8_str(rest)) })
1506 }
1507 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1508 t = if t < 0.0 { t + 1.0 } else { t };
1509 t = if t > 1.0 { t - 1.0 } else { t };
1510 if t < 1.0 / 6.0 {
1511 p + (q - p) * 6.0 * t
1512 } else if t < 1.0 / 2.0 {
1513 q
1514 } else if t < 2.0 / 3.0 {
1515 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1516 } else {
1517 p
1518 }
1519 }
1520
1521 if let Some(hex) = strip_prefix("#", str) {
1523 let total = match u32::from_str_radix(hex, 16) {
1524 Ok(total) if hex.len() == 6 => total,
1525 _ => return Err("Hexcode does not contain 6 hex values"),
1526 };
1527 let r = (total >> 16) as u8;
1528 let g = (total >> 8) as u8;
1529 let b = total as u8;
1530
1531 Ok(Color::Rgb { r, g, b })
1532 } else if let Some(mut rgb) = strip_prefix("rgb ", str) {
1534 let mut values = [0, 0, 0];
1535 let mut i = 0;
1536 while i < values.len() {
1537 if let Some((cut, rest)) = split_space(rgb) {
1538 rgb = rest;
1539 values[i] = match u8::from_str_radix(cut, 10) {
1540 Ok(value) => value,
1541 Err(_) => return Err("Rgb format value could not be parsed"),
1542 }
1543 } else {
1544 return Err("Missing value in rgb format");
1545 }
1546 i += 1;
1547 }
1548
1549 let [r, g, b] = values;
1550 Ok(Color::Rgb { r, g, b })
1551 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1553 let mut values = [0.0, 0.0, 0.0];
1554 let mut i = 0;
1555 while i < values.len() {
1556 if let Some((cut, rest)) = split_space(hsl) {
1557 hsl = rest;
1558 let (num, div) = match strip_suffix("%", cut) {
1559 Some(perc) => (perc, 100),
1560 None => (cut, 255),
1561 };
1562 values[i] = match u8::from_str_radix(num, 10) {
1563 Ok(value) if value <= div => value as f32 / div as f32,
1564 _ => return Err("Hsl format property could not be parsed"),
1565 }
1566 } else {
1567 return Err("Missing value in hsl format");
1568 }
1569 i += 1;
1570 }
1571 let [hue, sat, lit] = values;
1572
1573 let (r, g, b) = if sat == 0.0 {
1574 (lit, lit, lit)
1575 } else {
1576 let q = if lit < 0.5 {
1577 lit * (1.0 + sat)
1578 } else {
1579 lit + sat - lit * sat
1580 };
1581 let p = 2.0 * lit - q;
1582 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1583 let g = hue_to_rgb(p, q, hue);
1584 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1585 (r, g, b)
1586 };
1587
1588 let r = (0.5 + r * 255.0) as u8;
1590 let g = (0.5 + g * 255.0) as u8;
1591 let b = (0.5 + b * 255.0) as u8;
1592 Ok(Color::Rgb { r, g, b })
1593 } else {
1594 Err("Color format was not recognized")
1595 }
1596}
1597
1598impl std::fmt::Debug for Form {
1599 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1600 struct DebugColor(Option<Color>);
1601 impl std::fmt::Debug for DebugColor {
1602 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1603 match self.0 {
1604 Some(Color::Rgb { r, g, b }) => write!(f, "Some(Rgb({r}, {g}, {b}))"),
1605 Some(Color::AnsiValue(ansi)) => write!(f, "Some(Ansi({ansi}))"),
1606 Some(color) => write!(f, "Some({color:?})"),
1607 None => f.write_str("None"),
1608 }
1609 }
1610 }
1611
1612 struct DebugAttributes(Attributes);
1613 impl std::fmt::Debug for DebugAttributes {
1614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1615 if self.0.is_empty() {
1616 f.write_str("None")
1617 } else {
1618 let mut is_first = true;
1619 for attr in Attribute::iterator() {
1620 if self.0.has(attr) {
1621 if !is_first {
1622 f.write_str(" | ")?;
1623 }
1624 is_first = false;
1625 write!(f, "{attr:?}")?;
1626 }
1627 }
1628 Ok(())
1629 }
1630 }
1631 }
1632
1633 f.debug_struct("Form")
1634 .field("fg", &DebugColor(self.style.foreground_color))
1635 .field("bg", &DebugColor(self.style.background_color))
1636 .field("ul", &DebugColor(self.style.underline_color))
1637 .field("attr", &DebugAttributes(self.style.attributes))
1638 .finish()
1639 }
1640}
1641
1642impl std::fmt::Debug for InnerPalette {
1643 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1644 struct DebugForms<'a>(&'a [(&'static str, Form, FormType)]);
1645 impl std::fmt::Debug for DebugForms<'_> {
1646 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1647 if f.alternate() {
1648 f.write_str("[\n")?;
1649 let max = self.0.len().ilog10() as usize + 3;
1650 for (n, (name, form, ty)) in self.0.iter().enumerate() {
1651 let num = format!("{n}:");
1652 writeln!(f, "{num:<max$}({name}, {ty:?}, {form:#?})")?;
1653 }
1654 f.write_str("]")
1655 } else {
1656 write!(f, "{:?}", self.0)
1657 }
1658 }
1659 }
1660
1661 struct DebugCursorShape(CursorShape);
1662 impl std::fmt::Debug for DebugCursorShape {
1663 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1664 match self.0 {
1665 CursorShape::DefaultUserShape => f.write_str("DefaultUserShape"),
1666 CursorShape::BlinkingBlock => f.write_str("BlinkingBlock"),
1667 CursorShape::SteadyBlock => f.write_str("SteadyBlock"),
1668 CursorShape::BlinkingUnderScore => f.write_str("BlinkingUnderScore"),
1669 CursorShape::SteadyUnderScore => f.write_str("SteadyUnderScore"),
1670 CursorShape::BlinkingBar => f.write_str("BlinkingBar"),
1671 CursorShape::SteadyBar => f.write_str("SteadyBar"),
1672 }
1673 }
1674 }
1675
1676 f.debug_struct("InnerPalette")
1677 .field("main_cursor", &self.main_cursor.map(DebugCursorShape))
1678 .field("extra_cursor", &self.extra_cursor.map(DebugCursorShape))
1679 .field("forms", &DebugForms(&self.forms))
1680 .field("masks", &self.masks)
1681 .finish()
1682 }
1683}
1684
1685impl std::fmt::Debug for FormType {
1686 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1687 match self {
1688 Self::Normal => write!(f, "Normal"),
1689 Self::Ref(refed) => write!(f, "Ref({refed})"),
1690 Self::Weakest => write!(f, "Weakest"),
1691 Self::WeakestRef(refed) => write!(f, "WeakestRef({refed})"),
1692 }
1693 }
1694}
1695
1696macro mimic_method_new {
1698 (#[$attr:meta] $method:ident $attrib:expr) => {
1699 #[$attr]
1701 pub const fn $method() -> BuiltForm {
1703 let mut built = Form::new();
1704 built.0.style.attributes = built.0.style.attributes.with($attrib);
1705 built
1706 }
1707 },
1708
1709 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1710 #[$attr]
1712 pub const fn $fg() -> BuiltForm {
1714 let mut built = Form::new();
1715 built.0.style.foreground_color = Some($color);
1716 built
1717 }
1718
1719 #[$attr]
1721 pub const fn $bg() -> BuiltForm {
1723 let mut built = Form::new();
1724 built.0.style.background_color = Some($color);
1725 built
1726 }
1727
1728 #[$attr]
1730 pub const fn $ul() -> BuiltForm {
1736 let mut built = Form::new();
1737 built.0.style.underline_color = Some($color);
1738 built
1739 }
1740 }
1741}
1742
1743macro mimic_method_mod {
1744 (#[$attr:meta] $method:ident $attrib:expr) => {
1745 #[$attr]
1747 pub const fn $method(mut self) -> Self {
1749 self.0.style.attributes = self.0.style.attributes.with($attrib);
1750 self
1751 }
1752 },
1753
1754 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1755 #[$attr]
1757 pub const fn $fg(mut self) -> Self {
1758 self.0.style.foreground_color = Some($color);
1759 self
1760 }
1761
1762 #[$attr]
1764 pub const fn $bg(mut self) -> Self {
1765 self.0.style.background_color = Some($color);
1766 self
1767 }
1768
1769 #[$attr]
1771 pub const fn $ul(mut self) -> Self {
1776 self.0.style.underline_color = Some($color);
1777 self
1778 }
1779 }
1780}