1use std::sync::{LazyLock, OnceLock};
3
4use FormType::*;
5use crossterm::style::{Attribute, Attributes, ContentStyle};
6pub use crossterm::{cursor::SetCursorStyle as CursorShape, style::Color};
7use parking_lot::{RwLock, RwLockReadGuard};
8
9pub use self::global::*;
10pub(crate) use self::global::{colorscheme_exists, exists};
11use crate::{
12 hooks::{self, FormSet},
13 ui::Sender,
14};
15
16pub trait ColorScheme: Send + Sync + 'static {
17 fn apply(&self);
18
19 fn name(&self) -> &'static str;
20}
21
22static SENDER: OnceLock<Sender> = OnceLock::new();
23static BASE_FORMS: &[(&str, Form, FormType)] = &[
24 ("Default", Form::new().0, Normal),
25 ("Accent", Form::bold().0, Normal),
26 ("DefaultOk", Form::blue().0, Normal),
27 ("AccentOk", Form::cyan().0, Normal),
28 ("DefaultErr", Form::red().0, Normal),
29 ("AccentErr", Form::red().bold().0, Normal),
30 ("DefaultHint", Form::grey().0, Normal),
31 ("AccentHint", Form::grey().bold().0, Normal),
32 ("MainCursor", Form::reverse().0, Normal),
33 ("ExtraCursor", Form::reverse().0, Ref(M_CUR_ID.0 as usize)),
34 ("MainSelection", Form::white().on_dark_grey().0, Normal),
35 (
36 "ExtraSelection",
37 Form::white().on_dark_grey().0,
38 Ref(M_SEL_ID.0 as usize),
39 ),
40 ("Inactive", Form::grey().0, Normal),
41];
42
43mod global {
45 use std::{
46 any::TypeId,
47 collections::HashMap,
48 sync::{LazyLock, mpsc},
49 time::Duration,
50 };
51
52 use parking_lot::Mutex;
53
54 use super::{BASE_FORMS, BuiltForm, ColorScheme, CursorShape, Form, FormId, Painter, Palette};
55 use crate::{
56 context,
57 hooks::{self, ColorSchemeSet},
58 text::err,
59 };
60
61 static PALETTE: Palette = Palette::new();
62 static FORMS: LazyLock<Mutex<Vec<&str>>> =
63 LazyLock::new(|| Mutex::new(BASE_FORMS.iter().map(|(name, ..)| *name).collect()));
64 static COLORSCHEMES: LazyLock<Mutex<Vec<Box<dyn ColorScheme>>>> = LazyLock::new(Mutex::default);
65
66 pub trait FormFmt: InnerFormFmt {}
74 impl FormFmt for Form {}
75 impl FormFmt for BuiltForm {}
76 impl FormFmt for &str {}
77 impl FormFmt for &mut str {}
78 impl FormFmt for String {}
79
80 pub fn set(name: impl ToString, form: impl FormFmt) -> FormId {
102 let kind = form.kind();
103 let name: &'static str = name.to_string().leak();
104
105 match kind {
106 Kind::Form(form) => queue(move || PALETTE.set_form(name, form)),
107 Kind::Ref(refed) => queue(move || PALETTE.set_ref(name, refed)),
108 };
109
110 let mut forms = FORMS.lock();
111 if let Kind::Ref(refed) = kind {
112 position_of_name(&mut forms, refed);
113 }
114 FormId(position_of_name(&mut forms, name) as u16)
115 }
116
117 pub fn set_weak(name: impl ToString, form: impl FormFmt) -> FormId {
139 let kind = form.kind();
140 let name: &'static str = name.to_string().leak();
141
142 match kind {
143 Kind::Form(form) => queue(move || PALETTE.set_weak_form(name, form)),
144 Kind::Ref(refed) => queue(move || PALETTE.set_weak_ref(name, refed)),
145 };
146
147 let mut forms = FORMS.lock();
148 if let Kind::Ref(refed) = kind {
149 position_of_name(&mut forms, refed);
150 }
151 FormId(position_of_name(&mut forms, name) as u16)
152 }
153
154 pub fn from_id(id: FormId) -> Form {
161 PALETTE.form_from_id(id).unwrap_or(Form::new().0)
162 }
163
164 pub fn main_cursor() -> (Form, Option<CursorShape>) {
166 PALETTE.main_cursor()
167 }
168
169 pub fn extra_cursor() -> (Form, Option<CursorShape>) {
171 PALETTE.extra_cursor()
172 }
173
174 pub fn set_main_cursor(shape: CursorShape) {
197 queue(move || PALETTE.set_main_cursor(shape));
198 }
199
200 pub fn set_extra_cursor(shape: CursorShape) {
223 queue(move || PALETTE.set_extra_cursor(shape));
224 }
225
226 pub fn unset_main_cursor() {
237 queue(move || PALETTE.unset_main_cursor());
238 }
239
240 pub fn unset_extra_cursor() {
254 queue(move || PALETTE.unset_extra_cursor());
255 }
256
257 pub fn painter<W: ?Sized + 'static>() -> Painter {
276 fn default_id(type_id: TypeId, type_name: &'static str) -> FormId {
277 static IDS: LazyLock<Mutex<HashMap<TypeId, FormId>>> = LazyLock::new(Mutex::default);
278 let mut ids = IDS.lock();
279
280 if let Some(id) = ids.get(&type_id) {
281 *id
282 } else {
283 let name: &'static str = format!("Default.{type_name}").leak();
284 let id = id_from_name(name);
285 add_forms(vec![name]);
286 ids.insert(type_id, id);
287 id
288 }
289 }
290 PALETTE.painter(default_id(TypeId::of::<W>(), crate::duat_name::<W>()))
291 }
292
293 pub macro id_of {
323 ($form:expr) => {{
324 static ID: std::sync::OnceLock<FormId> = std::sync::OnceLock::new();
325 *ID.get_or_init(|| {
326 let name: &'static str = $form;
327 let id = id_from_name(name);
328 add_forms(vec![name]);
329 id
330 })
331 }},
332 ($($form:expr),+) => {{
333 static IDS: std::sync::OnceLock<&[FormId]> = std::sync::OnceLock::new();
334 let ids = *IDS.get_or_init(|| {
335 let mut ids = Vec::new();
336 let names = vec![$( $form ),+];
337 for name in names.iter() {
338 ids.push(id_from_name(name));
339 }
340 add_forms(names);
341 ids.leak()
342 });
343 ids
344 }}
345 }
346
347 pub fn ids_of_non_static(names: impl IntoIterator<Item = impl ToString>) -> Vec<FormId> {
354 let names: Vec<&str> = names
355 .into_iter()
356 .map(|n| {
357 let str: &'static str = n.to_string().leak();
358 str
359 })
360 .collect();
361
362 let mut ids = Vec::new();
363 let mut forms = FORMS.lock();
364 for name in names.iter() {
365 ids.push(FormId(position_of_name(&mut forms, name) as u16));
366 }
367 add_forms(names);
368 ids
369 }
370
371 #[doc(hidden)]
373 pub fn id_from_name(name: &'static str) -> FormId {
374 let mut forms = FORMS.lock();
375 FormId(position_of_name(&mut forms, name) as u16)
376 }
377
378 #[doc(hidden)]
379 pub fn add_forms(names: Vec<&'static str>) {
380 queue(move || PALETTE.set_many(names.as_ref()));
381 }
382
383 pub fn add_colorscheme(cs: impl ColorScheme) {
394 let mut colorschemes = COLORSCHEMES.lock();
395 let name = cs.name();
396 if let Some(i) = colorschemes.iter().position(|cs| cs.name() == name) {
397 colorschemes[i] = Box::new(cs);
398 } else {
399 colorschemes.push(Box::new(cs));
400 }
401 }
402
403 pub fn set_colorscheme(name: &str) {
410 let colorschemes = COLORSCHEMES.lock();
411 if let Some(cs) = colorschemes.iter().find(|cs| cs.name() == name) {
412 cs.apply();
413 hooks::trigger::<ColorSchemeSet>(cs.name());
414 } else {
415 context::notify(err!("The colorscheme " [*a] name [] " was not found"));
416 }
417 }
418
419 pub macro set_many($(($name:literal, $form:expr)),+ $(,)?) {{
423 $(
424 set($name, $form);
425 )+
426 }}
427
428 pub(crate) fn exists(name: &str) -> bool {
430 FORMS.lock().contains(&name)
431 }
432
433 pub(crate) fn colorscheme_exists(name: &str) -> bool {
435 COLORSCHEMES.lock().iter().any(|cs| cs.name() == name)
436 }
437
438 pub(super) fn name_of(id: FormId) -> &'static str {
440 FORMS.lock()[id.0 as usize]
441 }
442
443 fn position_of_name(names: &mut Vec<&'static str>, name: &'static str) -> usize {
444 if let Some((i, _)) = names.iter().enumerate().find(|(_, rhs)| **rhs == name) {
445 i
446 } else if let Some((refed, _)) = name.rsplit_once('.') {
447 position_of_name(names, refed);
448 names.push(name);
449 names.len() - 1
450 } else {
451 names.push(name);
452 names.len() - 1
453 }
454 }
455
456 fn queue<R>(f: impl FnOnce() -> R + Send + Sync + 'static) {
457 static SENDER: Mutex<Option<mpsc::Sender<Box<dyn FnOnce() + Send + Sync>>>> =
458 Mutex::new(None);
459
460 if context::will_reload_or_quit() {
461 return;
462 }
463
464 let f = Box::new(move || {
465 f();
466 });
467
468 let mut sender = SENDER.lock();
469 let f = if let Some(tx) = sender.as_ref() {
470 let Err(err) = tx.send(f) else {
471 return;
472 };
473 err.0
474 } else {
475 f
476 };
477 let (tx, rx) = mpsc::channel();
478 tx.send(f).unwrap();
479 *sender = Some(tx);
480
481 crate::thread::spawn(move || {
482 while let Ok(f) = rx.recv_timeout(Duration::from_micros(500)) {
483 f();
484 }
485 });
486 }
487
488 #[derive(Clone, Copy)]
490 enum Kind {
491 Form(Form),
492 Ref(&'static str),
493 }
494
495 trait InnerFormFmt {
499 fn kind(self) -> Kind;
501 }
502
503 impl InnerFormFmt for Form {
504 fn kind(self) -> Kind {
505 Kind::Form(self)
506 }
507 }
508
509 impl InnerFormFmt for BuiltForm {
510 fn kind(self) -> Kind {
511 Kind::Form(self.0)
512 }
513 }
514
515 impl InnerFormFmt for &str {
516 fn kind(self) -> Kind {
517 Kind::Ref(self.to_string().leak())
518 }
519 }
520
521 impl InnerFormFmt for &mut str {
522 fn kind(self) -> Kind {
523 Kind::Ref(self.to_string().leak())
524 }
525 }
526
527 impl InnerFormFmt for String {
528 fn kind(self) -> Kind {
529 Kind::Ref(self.leak())
530 }
531 }
532}
533
534#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
545pub struct FormId(u16);
546
547impl FormId {
548 pub const fn to_u16(self) -> u16 {
552 self.0
553 }
554
555 pub fn name(self) -> &'static str {
557 name_of(self)
558 }
559}
560
561impl std::fmt::Debug for FormId {
562 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
563 write!(f, "FormId({})", name_of(*self))
564 }
565}
566
567#[derive(Clone, Copy, PartialEq, Eq)]
569pub struct Form {
570 pub style: ContentStyle,
571}
572
573#[rustfmt::skip]
574impl Form {
575 mimic_method_new!(bold Attribute::Bold);
576 mimic_method_new!(dim Attribute::Dim);
577 mimic_method_new!(italic Attribute::Italic);
578 mimic_method_new!(underlined Attribute::Underlined);
579 mimic_method_new!(double_underlined Attribute::DoubleUnderlined);
580 mimic_method_new!(undercurled Attribute::Undercurled);
581 mimic_method_new!(underdashed Attribute::Underdashed);
582 mimic_method_new!(reverse Attribute::Reverse);
583 mimic_method_new!(crossed_out Attribute::CrossedOut);
584 mimic_method_new!(black on_black underline_black Color::Black);
585 mimic_method_new!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
586 mimic_method_new!(red on_red underline_red Color::Red);
587 mimic_method_new!(dark_red on_dark_red underline_dark_red Color::DarkRed);
588 mimic_method_new!(green on_green underline_green Color::Green);
589 mimic_method_new!(
590 dark_green on_dark_green underline_dark_green Color::DarkGreen
591 );
592 mimic_method_new!(yellow on_yellow underline_yellow Color::Yellow);
593 mimic_method_new!(
594 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
595 );
596 mimic_method_new!(blue on_blue underline_blue Color::Blue);
597 mimic_method_new!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
598 mimic_method_new!(magenta on_magenta underline_magenta Color::Magenta);
599 mimic_method_new!(
600 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
601 );
602 mimic_method_new!(cyan on_cyan underline_cyan Color::Cyan);
603 mimic_method_new!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
604 mimic_method_new!(white on_white underline_white Color::White);
605 mimic_method_new!(grey on_grey underline_grey Color::Grey);
606}
607
608impl Form {
609 #[allow(clippy::new_ret_no_self)]
613 pub const fn new() -> BuiltForm {
614 let style = ContentStyle {
615 foreground_color: None,
616 background_color: None,
617 underline_color: None,
618 attributes: Attributes::none(),
619 };
620 BuiltForm(Self { style })
621 }
622
623 pub const fn reset() -> BuiltForm {
630 let mut built = Form::new();
631 built.0.style.attributes = built.0.style.attributes.with(Attribute::Reset);
632 built
633 }
634
635 pub const fn with(str: &str) -> BuiltForm {
645 let mut built = Form::new();
646 built.0.style.foreground_color = match str_to_color(str) {
647 Ok(color) => Some(color),
648 Err(err) => panic!("{}", err),
649 };
650 built
651 }
652
653 pub const fn on(str: &str) -> BuiltForm {
663 let mut built = Form::new();
664 built.0.style.background_color = match str_to_color(str) {
665 Ok(color) => Some(color),
666 Err(err) => panic!("{}", err),
667 };
668 built
669 }
670
671 pub const fn underline(str: &str) -> BuiltForm {
681 let mut built = Form::new();
682 built.0.style.underline_color = match str_to_color(str) {
683 Ok(color) => Some(color),
684 Err(err) => panic!("{}", err),
685 };
686 built
687 }
688
689 pub const fn fg(&self) -> Option<Color> {
691 self.style.foreground_color
692 }
693
694 pub const fn bg(&self) -> Option<Color> {
696 self.style.background_color
697 }
698
699 pub const fn ul(&self) -> Option<Color> {
701 self.style.underline_color
702 }
703
704 pub const fn attr(&self) -> Attributes {
706 self.style.attributes
707 }
708}
709
710pub struct BuiltForm(Form);
719
720#[rustfmt::skip]
721impl BuiltForm {
722 mimic_method_mod!(bold Attribute::Bold);
723 mimic_method_mod!(dim Attribute::Dim);
724 mimic_method_mod!(italic Attribute::Italic);
725 mimic_method_mod!(underlined Attribute::Underlined);
726 mimic_method_mod!(double_underlined Attribute::DoubleUnderlined);
727 mimic_method_mod!(undercurled Attribute::Undercurled);
728 mimic_method_mod!(underdashed Attribute::Underdashed);
729 mimic_method_mod!(reverse Attribute::Reverse);
730 mimic_method_mod!(crossed_out Attribute::CrossedOut);
731 mimic_method_mod!(overlined Attribute::OverLined);
732 mimic_method_mod!(black on_black underline_black Color::Black);
733 mimic_method_mod!(dark_grey on_dark_grey underline_dark_grey Color::DarkGrey);
734 mimic_method_mod!(red on_red underline_red Color::Red);
735 mimic_method_mod!(dark_red on_dark_red underline_dark_red Color::DarkRed);
736 mimic_method_mod!(green on_green underline_green Color::Green);
737 mimic_method_mod!(
738 dark_green on_dark_green underline_dark_green Color::DarkGreen
739 );
740 mimic_method_mod!(yellow on_yellow underline_yellow Color::Yellow);
741 mimic_method_mod!(
742 dark_yellow on_dark_yellow underline_dark_yellow Color::DarkYellow
743 );
744 mimic_method_mod!(blue on_blue underline_blue Color::Blue);
745 mimic_method_mod!(dark_blue on_dark_blue underline_dark_blue Color::DarkBlue);
746 mimic_method_mod!(magenta on_magenta underline_magenta Color::Magenta);
747 mimic_method_mod!(
748 dark_magenta on_dark_magenta underline_dark_magenta Color::DarkMagenta
749 );
750 mimic_method_mod!(cyan on_cyan underline_cyan Color::Cyan);
751 mimic_method_mod!(dark_cyan on_dark_cyan underline_dark_cyan Color::DarkCyan);
752 mimic_method_mod!(white on_white underline_white Color::White);
753 mimic_method_mod!(grey on_grey underline_grey Color::Grey);
754}
755
756impl BuiltForm {
757 pub const fn reset(mut self) -> BuiltForm {
764 self.0.style.attributes = self.0.style.attributes.with(Attribute::Reset);
765 self
766 }
767
768 pub const fn with(mut self, str: &str) -> Self {
778 self.0.style.foreground_color = match str_to_color(str) {
779 Ok(color) => Some(color),
780 Err(err) => panic!("{}", err),
781 };
782 self
783 }
784
785 pub const fn on(mut self, str: &str) -> Self {
795 self.0.style.background_color = match str_to_color(str) {
796 Ok(color) => Some(color),
797 Err(err) => panic!("{}", err),
798 };
799 self
800 }
801
802 pub const fn underline(mut self, str: &str) -> Self {
812 self.0.style.underline_color = match str_to_color(str) {
813 Ok(color) => Some(color),
814 Err(err) => panic!("{}", err),
815 };
816 self
817 }
818}
819
820impl std::ops::Deref for BuiltForm {
821 type Target = Form;
822
823 fn deref(&self) -> &Self::Target {
824 &self.0
825 }
826}
827
828impl std::ops::DerefMut for BuiltForm {
829 fn deref_mut(&mut self) -> &mut Self::Target {
830 &mut self.0
831 }
832}
833
834pub const DEFAULT_ID: FormId = FormId(0);
836pub const M_CUR_ID: FormId = FormId(8);
838pub const E_CUR_ID: FormId = FormId(9);
840pub const M_SEL_ID: FormId = FormId(10);
842pub const E_SEL_ID: FormId = FormId(11);
844pub const INACTIVE_ID: FormId = FormId(12);
846
847struct InnerPalette {
848 main_cursor: Option<CursorShape>,
849 extra_cursor: Option<CursorShape>,
850 forms: Vec<(&'static str, Form, FormType)>,
851}
852
853struct Palette(LazyLock<RwLock<InnerPalette>>);
855
856impl Palette {
857 const fn new() -> Self {
859 Self(LazyLock::new(|| {
860 let main_cursor = Some(CursorShape::DefaultUserShape);
861
862 RwLock::new(InnerPalette {
863 main_cursor,
864 extra_cursor: main_cursor,
865 forms: BASE_FORMS.to_vec(),
866 })
867 }))
868 }
869
870 fn set_form(&self, name: &'static str, form: Form) {
872 let mut inner = self.0.write();
873 let (i, _) = position_and_form(&mut inner.forms, name);
874
875 inner.forms[i] = (name, form, FormType::Normal);
876
877 for refed in refs_of(&inner, i) {
878 inner.forms[refed].1 = form;
879 }
880
881 if let Some(sender) = SENDER.get() {
882 sender.send_form_changed().unwrap()
883 }
884
885 hooks::trigger::<FormSet>((name, FormId(i as u16), form));
886 }
887
888 fn set_weak_form(&self, name: &'static str, form: Form) {
890 let mut inner = self.0.write();
891 let (i, _) = position_and_form(&mut inner.forms, name);
892
893 let (_, f, f_ty) = &mut inner.forms[i];
894 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
895 *f = form;
896 *f_ty = FormType::Normal;
897
898 if let Some(sender) = SENDER.get() {
899 sender.send_form_changed().unwrap()
900 }
901 for refed in refs_of(&inner, i) {
902 inner.forms[refed].1 = form;
903 }
904 }
905 }
906
907 fn set_ref(&self, name: &'static str, refed: &'static str) {
909 let mut inner = self.0.write();
910 let (refed, form) = position_and_form(&mut inner.forms, refed);
911 let (i, _) = position_and_form(&mut inner.forms, name);
912
913 for refed in refs_of(&inner, i) {
914 inner.forms[refed].1 = form;
915 }
916
917 if would_be_circular(&inner, i, refed) {
919 inner.forms[i] = (name, form, FormType::Normal);
920 } else {
921 inner.forms[i] = (name, form, FormType::Ref(refed));
922 }
923
924 if let Some(sender) = SENDER.get() {
925 sender.send_form_changed().unwrap()
926 }
927 hooks::trigger::<FormSet>((name, FormId(i as u16), form));
928 }
929
930 fn set_weak_ref(&self, name: &'static str, refed: &'static str) {
932 let mut inner = self.0.write();
933 let (refed, form) = position_and_form(&mut inner.forms, refed);
934 let (i, _) = position_and_form(&mut inner.forms, name);
935
936 let (_, f, f_ty) = &mut inner.forms[i];
939 if let FormType::Weakest | FormType::WeakestRef(_) = f_ty {
940 *f = form;
941 *f_ty = FormType::WeakestRef(refed);
942
943 if let Some(sender) = SENDER.get() {
944 sender.send_form_changed().unwrap()
945 }
946 for refed in refs_of(&inner, i) {
947 inner.forms[refed].1 = form;
948 }
949 }
950 }
951
952 fn set_many(&self, names: &[&'static str]) {
954 let mut inner = self.0.write();
955 for name in names {
956 position_and_form(&mut inner.forms, name);
957 }
958 }
959
960 fn form_from_id(&self, id: FormId) -> Option<Form> {
962 let inner = self.0.read();
963 inner.forms.get(id.0 as usize).map(|(_, form, _)| *form)
964 }
965
966 fn main_cursor(&self) -> (Form, Option<CursorShape>) {
968 let form = self.form_from_id(M_CUR_ID).unwrap();
969 (form, self.0.read().main_cursor)
970 }
971
972 fn extra_cursor(&self) -> (Form, Option<CursorShape>) {
974 let form = self.form_from_id(E_CUR_ID).unwrap();
975 (form, self.0.read().extra_cursor)
976 }
977
978 fn set_main_cursor(&self, shape: CursorShape) {
980 self.0.write().main_cursor = Some(shape);
981 if let Some(sender) = SENDER.get() {
982 sender.send_form_changed().unwrap()
983 }
984 }
985
986 fn set_extra_cursor(&self, shape: CursorShape) {
988 self.0.write().extra_cursor = Some(shape);
989 if let Some(sender) = SENDER.get() {
990 sender.send_form_changed().unwrap()
991 }
992 }
993
994 fn unset_main_cursor(&self) {
996 self.0.write().main_cursor = None;
997 if let Some(sender) = SENDER.get() {
998 sender.send_form_changed().unwrap()
999 }
1000 }
1001
1002 fn unset_extra_cursor(&self) {
1004 self.0.write().extra_cursor = None;
1005 if let Some(sender) = SENDER.get() {
1006 sender.send_form_changed().unwrap()
1007 }
1008 }
1009
1010 fn painter(&'static self, id: FormId) -> Painter {
1012 let inner = self.0.read();
1013 let default = inner
1014 .forms
1015 .get(id.0 as usize)
1016 .map(|(_, f, _)| *f)
1017 .unwrap_or(Form::new().0);
1018 Painter {
1019 inner,
1020 forms: vec![(default, id)],
1021 reset_count: 0,
1022 final_form_start: 1,
1023 still_on_same_byte: false,
1024 reset_is_needed: false,
1025 }
1026 }
1027}
1028
1029pub struct Painter {
1030 inner: RwLockReadGuard<'static, InnerPalette>,
1031 forms: Vec<(Form, FormId)>,
1032 reset_count: usize,
1033 final_form_start: usize,
1034 still_on_same_byte: bool,
1035 reset_is_needed: bool,
1036}
1037
1038impl Painter {
1039 #[inline(always)]
1047 pub fn apply(&mut self, id: FormId) -> ContentStyle {
1048 let i = id.0 as usize;
1049 let forms = &self.inner.forms;
1050 let form = forms.get(i).map(|(_, f, _)| *f).unwrap_or(Form::new().0);
1051
1052 self.reset_count += form.style.attributes.has(Attribute::Reset) as usize;
1053
1054 self.forms.insert(self.final_form_start, (form, id));
1055 if !(id == M_SEL_ID || id == E_SEL_ID) {
1056 self.final_form_start += 1;
1057 }
1058
1059 let mut style = self.make_style();
1060 if self.reset_is_needed || self.reset_count > 0 {
1061 self.still_on_same_byte = true;
1062 self.reset_is_needed = true;
1063 style.attributes.set(Attribute::Reset);
1064 } else if !self.still_on_same_byte {
1068 self.still_on_same_byte = true;
1069 style.foreground_color = form.fg().and(style.foreground_color.or(Some(Color::Reset)));
1070 style.background_color = form.bg().and(style.background_color.or(Some(Color::Reset)));
1071 style.underline_color = form.ul().and(style.underline_color.or(Some(Color::Reset)));
1072 }
1073 style
1074 }
1075
1076 #[inline(always)]
1079 pub fn remove(&mut self, id: FormId) -> ContentStyle {
1080 let mut applied_forms = self.forms.iter().enumerate();
1081 let Some((i, &(form, _))) = applied_forms.rfind(|(_, (_, i))| *i == id) else {
1082 return absolute_style(&self.forms);
1083 };
1084
1085 self.reset_count -= form.style.attributes.has(Attribute::Reset) as usize;
1086 self.forms.remove(i);
1087 if id != M_SEL_ID && id != E_SEL_ID {
1088 self.final_form_start -= 1;
1089 }
1090
1091 let mut style = self.make_style();
1092 if !form.style.attributes.is_empty() || self.reset_is_needed || self.reset_count > 0 {
1093 self.still_on_same_byte = true;
1094 self.reset_is_needed = true;
1095 style.attributes.set(Attribute::Reset);
1096 } else if !self.still_on_same_byte {
1100 self.still_on_same_byte = true;
1101 style.foreground_color = form.fg().and(style.foreground_color.or(Some(Color::Reset)));
1102 style.background_color = form.bg().and(style.background_color.or(Some(Color::Reset)));
1103 style.underline_color = form.ul().and(style.underline_color.or(Some(Color::Reset)));
1104 }
1105 style
1106 }
1107
1108 #[inline(always)]
1114 pub fn reset(&mut self) -> ContentStyle {
1115 self.forms.splice(1.., []);
1116 self.make_style()
1117 }
1118
1119 #[inline(always)]
1122 pub fn make_style(&self) -> ContentStyle {
1123 let mut style = ContentStyle::new();
1124
1125 for &(form, _) in &self.forms {
1126 style.foreground_color = form.fg().or(style.foreground_color);
1127 style.background_color = form.bg().or(style.background_color);
1128 style.underline_color = form.ul().or(style.underline_color);
1129 style.attributes = if form.attr().has(Attribute::Reset) {
1130 form.attr()
1131 } else {
1132 form.attr() | style.attributes
1133 }
1134 }
1135
1136 style
1137 }
1138
1139 #[inline(always)]
1140 pub fn apply_main_cursor(&mut self) -> ContentStyle {
1141 let style = self.apply(M_CUR_ID);
1142 self.final_form_start -= 1;
1143 style
1144 }
1145
1146 #[inline(always)]
1147 pub fn remove_main_cursor(&mut self) -> ContentStyle {
1148 let style = self.remove(M_CUR_ID);
1149 self.final_form_start += 1;
1150 style
1151 }
1152
1153 #[inline(always)]
1154 pub fn apply_extra_cursor(&mut self) -> ContentStyle {
1155 let style = self.apply(E_CUR_ID);
1156 self.final_form_start -= 1;
1157 style
1158 }
1159
1160 #[inline(always)]
1161 pub fn remove_extra_cursor(&mut self) -> ContentStyle {
1162 let style = self.remove(E_CUR_ID);
1163 self.final_form_start += 1;
1164 style
1165 }
1166
1167 pub fn confirm_printing(&mut self) {
1169 self.still_on_same_byte = false;
1170 self.reset_is_needed = false;
1171 }
1172
1173 pub fn main_cursor(&self) -> Option<CursorShape> {
1175 self.inner.main_cursor
1176 }
1177
1178 pub fn extra_cursor(&self) -> Option<CursorShape> {
1180 self.inner.extra_cursor
1181 }
1182
1183 pub fn get_default(&self) -> Form {
1185 self.forms[0].0
1186 }
1187}
1188
1189pub(crate) fn set_sender(sender: Sender) {
1190 SENDER
1191 .set(sender)
1192 .unwrap_or_else(|_| panic!("Sender set more than once"));
1193}
1194
1195#[derive(Clone)]
1197enum FormType {
1198 Normal,
1199 Ref(usize),
1200 Weakest,
1201 WeakestRef(usize),
1202}
1203
1204fn refs_of(inner: &InnerPalette, refed: usize) -> Vec<usize> {
1206 let mut refs = Vec::new();
1207 for (i, (.., f_ty)) in inner.forms.iter().enumerate() {
1208 if let FormType::Ref(ref_id) | FormType::WeakestRef(ref_id) = f_ty
1209 && *ref_id == refed
1210 {
1211 refs.push(i);
1212 refs.extend(refs_of(inner, i));
1213 }
1214 }
1215 refs
1216}
1217
1218fn would_be_circular(inner: &InnerPalette, referee: usize, refed: usize) -> bool {
1220 if let (.., FormType::Ref(refed_ref) | FormType::WeakestRef(refed_ref)) = inner.forms[refed] {
1221 match refed_ref == referee {
1222 true => true,
1223 false => would_be_circular(inner, referee, refed_ref),
1224 }
1225 } else {
1226 false
1227 }
1228}
1229
1230fn absolute_style(list: &[(Form, FormId)]) -> ContentStyle {
1232 let mut style = ContentStyle::new();
1233
1234 for &(form, _) in list {
1235 style.foreground_color = form.fg().or(style.foreground_color);
1236 style.background_color = form.bg().or(style.background_color);
1237 style.underline_color = form.ul().or(style.underline_color);
1238 style.attributes = if form.attr().has(Attribute::Reset) {
1239 form.attr()
1240 } else {
1241 form.attr() | style.attributes
1242 }
1243 }
1244
1245 style
1246}
1247
1248fn position_and_form(forms: &mut Vec<(&str, Form, FormType)>, name: &'static str) -> (usize, Form) {
1249 if let Some((i, (_, form, _))) = forms.iter().enumerate().find(|(_, (lhs, ..))| *lhs == name) {
1250 (i, *form)
1251 } else if let Some((refed, _)) = name.rsplit_once('.') {
1252 let (i, form) = position_and_form(forms, refed);
1253 forms.push((name, form, FormType::WeakestRef(i)));
1254 (forms.len() - 1, form)
1255 } else {
1256 forms.push((name, Form::new().0, FormType::Weakest));
1257 (forms.len() - 1, Form::new().0)
1258 }
1259}
1260
1261const fn str_to_color(str: &str) -> std::result::Result<Color, &'static str> {
1263 use core::str::from_utf8_unchecked as utf8_str;
1264 const fn strip_prefix<'a>(prefix: &str, str: &'a str) -> Option<&'a str> {
1265 let prefix = prefix.as_bytes();
1266 let str = str.as_bytes();
1267
1268 let mut i = 0;
1269 while i < prefix.len() {
1270 if str[i] != prefix[i] {
1271 return None;
1272 }
1273 i += 1;
1274 }
1275
1276 let (_, str) = str.split_at(prefix.len());
1277 Some(unsafe { utf8_str(str) })
1278 }
1279 const fn strip_suffix<'a>(suffix: &str, str: &'a str) -> Option<&'a str> {
1280 let prefix = suffix.as_bytes();
1281 let str = str.as_bytes();
1282
1283 let mut i = str.len() - 1;
1284 while i >= str.len() - prefix.len() {
1285 if str[i] != prefix[i - (str.len() - prefix.len())] {
1286 return None;
1287 }
1288 i += 1;
1289 }
1290
1291 let (str, _) = str.split_at(str.len() - suffix.len());
1292 Some(unsafe { utf8_str(str) })
1293 }
1294 const fn split_space(str: &str) -> Option<(&str, &str)> {
1295 if str.is_empty() {
1296 return None;
1297 }
1298 let str = str.as_bytes();
1299
1300 let mut i = 0;
1301 while i < str.len() {
1302 if str[i] == b' ' {
1303 break;
1304 }
1305 i += 1;
1306 }
1307
1308 let (cut, rest) = str.split_at(i);
1309 let (_, rest) = rest.split_at(if rest.is_empty() { 0 } else { 1 });
1310 Some(unsafe { (utf8_str(cut), utf8_str(rest)) })
1311 }
1312 const fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
1313 t = if t < 0.0 { t + 1.0 } else { t };
1314 t = if t > 1.0 { t - 1.0 } else { t };
1315 if t < 1.0 / 6.0 {
1316 p + (q - p) * 6.0 * t
1317 } else if t < 1.0 / 2.0 {
1318 q
1319 } else if t < 2.0 / 3.0 {
1320 p + (q - p) * (2.0 / 3.0 - t) * 6.0
1321 } else {
1322 p
1323 }
1324 }
1325
1326 if let Some(hex) = strip_prefix("#", str) {
1328 let total = match u32::from_str_radix(hex, 16) {
1329 Ok(total) if hex.len() == 6 => total,
1330 _ => return Err("Hexcode does not contain 6 hex values"),
1331 };
1332 let r = (total >> 16) as u8;
1333 let g = (total >> 8) as u8;
1334 let b = total as u8;
1335
1336 Ok(Color::Rgb { r, g, b })
1337 } else if let Some(mut rgb) = strip_prefix("rgb ", str) {
1339 let mut values = [0, 0, 0];
1340 let mut i = 0;
1341 while i < values.len() {
1342 if let Some((cut, rest)) = split_space(rgb) {
1343 rgb = rest;
1344 values[i] = match u8::from_str_radix(cut, 10) {
1345 Ok(value) => value,
1346 Err(_) => return Err("Rgb format value could not be parsed"),
1347 }
1348 } else {
1349 return Err("Missing value in rgb format");
1350 }
1351 i += 1;
1352 }
1353
1354 let [r, g, b] = values;
1355 Ok(Color::Rgb { r, g, b })
1356 } else if let Some(mut hsl) = strip_prefix("hsl ", str) {
1358 let mut values = [0.0, 0.0, 0.0];
1359 let mut i = 0;
1360 while i < values.len() {
1361 if let Some((cut, rest)) = split_space(hsl) {
1362 hsl = rest;
1363 let (num, div) = match strip_suffix("%", cut) {
1364 Some(perc) => (perc, 100),
1365 None => (cut, 255),
1366 };
1367 values[i] = match u8::from_str_radix(num, 10) {
1368 Ok(value) if value <= div => value as f32 / div as f32,
1369 _ => return Err("Hsl format property could not be parsed"),
1370 }
1371 } else {
1372 return Err("Missing value in hsl format");
1373 }
1374 i += 1;
1375 }
1376 let [hue, sat, lit] = values;
1377
1378 let (r, g, b) = if sat == 0.0 {
1379 (lit, lit, lit)
1380 } else {
1381 let q = if lit < 0.5 {
1382 lit * (1.0 + sat)
1383 } else {
1384 lit + sat - lit * sat
1385 };
1386 let p = 2.0 * lit - q;
1387 let r = hue_to_rgb(p, q, hue + 1.0 / 3.0);
1388 let g = hue_to_rgb(p, q, hue);
1389 let b = hue_to_rgb(p, q, hue - 1.0 / 3.0);
1390 (r, g, b)
1391 };
1392
1393 let r = (0.5 + r * 255.0) as u8;
1395 let g = (0.5 + g * 255.0) as u8;
1396 let b = (0.5 + b * 255.0) as u8;
1397 Ok(Color::Rgb { r, g, b })
1398 } else {
1399 return Err("Color format was not recognized");
1400 }
1401}
1402
1403impl std::fmt::Debug for Form {
1404 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1405 struct DebugColor(Option<Color>);
1406 impl std::fmt::Debug for DebugColor {
1407 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1408 match self.0 {
1409 Some(Color::Rgb { r, g, b }) => write!(f, "Some(Rgb({r}, {g}, {b}))"),
1410 Some(Color::AnsiValue(ansi)) => write!(f, "Some(Ansi({ansi}))"),
1411 Some(color) => write!(f, "Some({color:?})"),
1412 None => f.write_str("None"),
1413 }
1414 }
1415 }
1416
1417 struct DebugAttributes(Attributes);
1418 impl std::fmt::Debug for DebugAttributes {
1419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1420 if self.0.is_empty() {
1421 f.write_str("None")
1422 } else {
1423 let mut is_first = true;
1424 for attr in Attribute::iterator() {
1425 if self.0.has(attr) {
1426 if !is_first {
1427 f.write_str(" | ")?;
1428 }
1429 is_first = false;
1430 write!(f, "{attr:?}")?;
1431 }
1432 }
1433 Ok(())
1434 }
1435 }
1436 }
1437
1438 f.debug_struct("Form")
1439 .field("fg", &DebugColor(self.style.foreground_color))
1440 .field("bg", &DebugColor(self.style.background_color))
1441 .field("ul", &DebugColor(self.style.underline_color))
1442 .field("attr", &DebugAttributes(self.style.attributes))
1443 .finish()
1444 }
1445}
1446
1447impl std::fmt::Debug for InnerPalette {
1448 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1449 struct DebugForms<'a>(&'a [(&'static str, Form, FormType)]);
1450 impl std::fmt::Debug for DebugForms<'_> {
1451 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1452 if f.alternate() {
1453 f.write_str("[\n")?;
1454 let max = self.0.len().ilog10() as usize + 3;
1455 for (n, entry) in self.0.iter().enumerate() {
1456 let num = format!("{n}:");
1457 writeln!(f, "{num:<max$}{entry:#?}")?;
1458 }
1459 f.write_str("]")
1460 } else {
1461 write!(f, "{:?}", self.0)
1462 }
1463 }
1464 }
1465
1466 struct DebugCursorShape(CursorShape);
1467 impl std::fmt::Debug for DebugCursorShape {
1468 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1469 match self.0 {
1470 CursorShape::DefaultUserShape => f.write_str("DefaultUserShape"),
1471 CursorShape::BlinkingBlock => f.write_str("BlinkingBlock"),
1472 CursorShape::SteadyBlock => f.write_str("SteadyBlock"),
1473 CursorShape::BlinkingUnderScore => f.write_str("BlinkingUnderScore"),
1474 CursorShape::SteadyUnderScore => f.write_str("SteadyUnderScore"),
1475 CursorShape::BlinkingBar => f.write_str("BlinkingBar"),
1476 CursorShape::SteadyBar => f.write_str("SteadyBar"),
1477 }
1478 }
1479 }
1480
1481 f.debug_struct("InnerPalette")
1482 .field("main_cursor", &self.main_cursor.map(DebugCursorShape))
1483 .field("extra_cursor", &self.extra_cursor.map(DebugCursorShape))
1484 .field("forms", &DebugForms(&self.forms))
1485 .finish()
1486 }
1487}
1488
1489impl std::fmt::Debug for FormType {
1490 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1491 match self {
1492 Self::Normal => write!(f, "Normal"),
1493 Self::Ref(refed) => write!(f, "Ref({refed})"),
1494 Self::Weakest => write!(f, "Weakest"),
1495 Self::WeakestRef(refed) => write!(f, "WeakestRef({refed})"),
1496 }
1497 }
1498}
1499
1500macro mimic_method_new {
1502 (#[$attr:meta] $method:ident $attrib:expr) => {
1503 #[$attr]
1505 pub const fn $method() -> BuiltForm {
1507 let mut built = Form::new();
1508 built.0.style.attributes = built.0.style.attributes.with($attrib);
1509 built
1510 }
1511 },
1512
1513 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1514 #[$attr]
1516 pub const fn $fg() -> BuiltForm {
1518 let mut built = Form::new();
1519 built.0.style.foreground_color = Some($color);
1520 built
1521 }
1522
1523 #[$attr]
1525 pub const fn $bg() -> BuiltForm {
1527 let mut built = Form::new();
1528 built.0.style.background_color = Some($color);
1529 built
1530 }
1531
1532 #[$attr]
1534 pub const fn $ul() -> BuiltForm {
1540 let mut built = Form::new();
1541 built.0.style.underline_color = Some($color);
1542 built
1543 }
1544 }
1545}
1546
1547macro mimic_method_mod {
1548 (#[$attr:meta] $method:ident $attrib:expr) => {
1549 #[$attr]
1551 pub const fn $method(mut self) -> Self {
1553 self.0.style.attributes = self.0.style.attributes.with($attrib);
1554 self
1555 }
1556 },
1557
1558 (#[$attr:meta] $fg:ident $bg:ident $ul:ident $color:expr) => {
1559 #[$attr]
1561 pub const fn $fg(mut self) -> Self {
1562 self.0.style.foreground_color = Some($color);
1563 self
1564 }
1565
1566 #[$attr]
1568 pub const fn $bg(mut self) -> Self {
1569 self.0.style.background_color = Some($color);
1570 self
1571 }
1572
1573 #[$attr]
1575 pub const fn $ul(mut self) -> Self {
1580 self.0.style.underline_color = Some($color);
1581 self
1582 }
1583 }
1584}