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 let pl = handle.read(pa);
68 if let Some(main) = pl.text.selections().get_main() {
69 handle
70 .area(pa)
71 .scroll_around_point(&pl.text, main.caret(), pl.print_cfg());
72 }
73 }
74
75 fn needs_update(&self, _: &Pass) -> bool {
76 false
77 }
78
79 fn cfg() -> Self::Cfg {
80 Self::Cfg {
81 prompts: HashMap::new(),
82 specs: PushSpecs::below().ver_len(1.0),
83 _ghost: PhantomData,
84 }
85 }
86
87 fn text(&self) -> &Text {
88 &self.text
89 }
90
91 fn text_mut(&mut self) -> &mut Text {
92 &mut self.text
93 }
94
95 fn print_cfg(&self) -> PrintCfg {
96 *PrintCfg::default_for_input().set_forced_horizontal_scrolloff(true)
97 }
98
99 fn once() -> Result<(), Text> {
100 Ok(())
101 }
102}
103
104impl<U: Ui> WidgetCfg<U> for PromptLineCfg<U> {
105 type Widget = PromptLine<U>;
106
107 fn build(self, _: &mut Pass, _: BuildInfo<U>) -> (Self::Widget, PushSpecs) {
108 let specs = if hook::group_exists("HidePromptLine") {
109 self.specs.ver_len(0.0)
110 } else {
111 self.specs
112 };
113
114 let widget = PromptLine {
115 text: Text::default(),
116 prompts: HashMap::new(),
117 _ghost: PhantomData,
118 };
119
120 (widget, specs)
121 }
122}
123
124#[doc(hidden)]
125pub struct PromptLineCfg<U> {
126 prompts: HashMap<TypeId, Text>,
127 specs: PushSpecs,
128 _ghost: PhantomData<U>,
129}
130
131impl<U: Ui> PromptLineCfg<U> {
132 pub fn set_prompt<M: PromptMode<U>>(mut self, prompt: Text) -> Self {
137 self.prompts.insert(TypeId::of::<M>(), prompt);
138 self
139 }
140
141 pub fn above(self) -> Self {
143 Self {
144 specs: PushSpecs::above().ver_len(1.0),
145 ..self
146 }
147 }
148
149 pub fn below(self) -> Self {
151 Self {
152 specs: PushSpecs::below().ver_len(1.0),
153 ..self
154 }
155 }
156
157 pub fn hidden(self) -> Self {
159 Self { specs: self.specs.hidden(), ..self }
160 }
161
162 pub fn left_ratioed(self, den: u16, div: u16) -> Self {
164 Self {
165 specs: PushSpecs::left().hor_ratio(den, div),
166 ..self
167 }
168 }
169}
170
171impl<U: Ui> Default for PromptLineCfg<U> {
172 fn default() -> Self {
173 PromptLine::cfg()
174 }
175}