duat_utils/widgets/
prompt_line.rs1use std::{any::TypeId, collections::HashMap, marker::PhantomData};
19
20use duat_core::prelude::*;
21
22use crate::modes::PromptMode;
23
24pub struct PromptLine<U> {
46 text: Text,
47 prompts: HashMap<TypeId, Text>,
48 _ghost: PhantomData<U>,
49}
50
51impl<U: Ui> PromptLine<U> {
52 pub fn prompt_of<M: PromptMode<U>>(&self) -> Option<Text> {
54 self.prompts.get(&TypeId::of::<M>()).cloned()
55 }
56
57 pub fn set_prompt<M: PromptMode<U>>(&mut self, text: Text) {
59 self.prompts.entry(TypeId::of::<M>()).or_insert(text);
60 }
61}
62
63impl<U: Ui> Widget<U> for PromptLine<U> {
64 type Cfg = PromptLineCfg<U>;
65
66 fn update(pa: &mut Pass, handle: Handle<Self, U>) {
67 handle.write(pa, |pl, area| {
68 if let Some(sels) = pl.text.selections()
69 && let Some(main) = sels.get_main()
70 {
71 area.scroll_around_point(&pl.text, main.caret(), pl.print_cfg());
72 }
73 })
74 }
75
76 fn needs_update(&self) -> bool {
77 false
78 }
79
80 fn cfg() -> Self::Cfg {
81 Self::Cfg {
82 prompts: HashMap::new(),
83 specs: PushSpecs::below().with_ver_len(1.0),
84 _ghost: PhantomData,
85 }
86 }
87
88 fn text(&self) -> &Text {
89 &self.text
90 }
91
92 fn text_mut(&mut self) -> &mut Text {
93 &mut self.text
94 }
95
96 fn print_cfg(&self) -> PrintCfg {
97 PrintCfg::default_for_input().with_forced_horizontal_scrolloff()
98 }
99
100 fn once() -> Result<(), Text> {
101 Ok(())
102 }
103}
104
105impl<U: Ui> WidgetCfg<U> for PromptLineCfg<U> {
106 type Widget = PromptLine<U>;
107
108 fn build(self, _: &mut Pass, _: Option<FileHandle<U>>) -> (Self::Widget, PushSpecs) {
109 let specs = if hook::group_exists("HidePromptLine") {
110 self.specs.with_ver_len(0.0)
111 } else {
112 self.specs
113 };
114
115 let widget = PromptLine {
116 text: Text::default(),
117 prompts: HashMap::new(),
118 _ghost: PhantomData,
119 };
120
121 (widget, specs)
122 }
123}
124
125#[doc(hidden)]
126pub struct PromptLineCfg<U> {
127 prompts: HashMap<TypeId, Text>,
128 specs: PushSpecs,
129 _ghost: PhantomData<U>,
130}
131
132impl<U: Ui> PromptLineCfg<U> {
133 pub fn set_prompt<M: PromptMode<U>>(mut self, prompt: Text) -> Self {
138 self.prompts.insert(TypeId::of::<M>(), prompt);
139 self
140 }
141
142 pub fn above(self) -> Self {
144 Self {
145 specs: PushSpecs::above().with_ver_len(1.0),
146 ..self
147 }
148 }
149
150 pub fn below(self) -> Self {
152 Self {
153 specs: PushSpecs::below().with_ver_len(1.0),
154 ..self
155 }
156 }
157
158 pub fn hidden(self) -> Self {
160 Self { specs: self.specs.hidden(), ..self }
161 }
162
163 pub fn left_ratioed(self, den: u16, div: u16) -> Self {
165 Self {
166 specs: PushSpecs::left().with_hor_ratio(den, div),
167 ..self
168 }
169 }
170}
171
172impl<U: Ui> Default for PromptLineCfg<U> {
173 fn default() -> Self {
174 PromptLine::cfg()
175 }
176}