tui_canvas/
data_provider.rs1#[cfg(feature = "suggestions")]
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum SuggestionTrigger {
8 None,
10 WhenFieldStarts,
12 SpecialChar(char),
14}
15
16#[cfg(feature = "suggestions")]
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct SuggestionQuery {
19 pub query: String,
20 pub replace_range: Option<(usize, usize)>,
21}
22
23#[cfg(feature = "suggestions")]
24impl SuggestionQuery {
25 pub fn whole_field(query: impl Into<String>) -> Self {
26 Self {
27 query: query.into(),
28 replace_range: None,
29 }
30 }
31
32 pub fn with_replace_range(query: impl Into<String>, replace_range: (usize, usize)) -> Self {
33 Self {
34 query: query.into(),
35 replace_range: Some(replace_range),
36 }
37 }
38}
39
40pub trait DataProvider {
42 fn field_count(&self) -> usize;
44
45 fn field_name(&self, index: usize) -> &str;
47
48 fn field_value(&self, index: usize) -> &str;
50
51 fn set_field_value(&mut self, index: usize, value: String);
53
54 fn capture_content(&self) -> Vec<String> {
61 (0..self.field_count())
62 .map(|i| self.field_value(i).to_string())
63 .collect()
64 }
65
66 fn restore_content(&mut self, fields: &[String]) {
72 let count = self.field_count();
73 for (i, value) in fields.iter().enumerate() {
74 if i < count {
75 self.set_field_value(i, value.clone());
76 }
77 }
78 }
79
80 fn supports_suggestions(&self, _field_index: usize) -> bool {
82 false
83 }
84
85 #[cfg(feature = "suggestions")]
88 fn suggestion_trigger(&self, _field_index: usize) -> SuggestionTrigger {
89 SuggestionTrigger::None
90 }
91
92 #[cfg(feature = "suggestions")]
98 fn suggestion_query(&self, field_index: usize, _cursor_char: usize) -> Option<SuggestionQuery> {
99 Some(SuggestionQuery::whole_field(self.field_value(field_index)))
100 }
101
102 #[cfg(feature = "suggestions")]
105 fn fetch_suggestions_sync(&self, _field_index: usize, _query: &str) -> Vec<SuggestionItem> {
106 Vec::new()
107 }
108
109 #[cfg(feature = "suggestions")]
112 fn accept_suggestion(
113 &mut self,
114 field_index: usize,
115 _cursor_char: usize,
116 suggestion: &SuggestionItem,
117 _query: &SuggestionQuery,
118 ) -> usize {
119 let value = suggestion.value_to_store.clone();
120 let cursor = value.chars().count();
121 self.set_field_value(field_index, value);
122 cursor
123 }
124
125 fn display_value(&self, _index: usize) -> Option<&str> {
127 None }
129
130 #[cfg(feature = "validation")]
133 fn validation_config(
134 &self,
135 _field_index: usize,
136 ) -> Option<crate::validation::ValidationConfig> {
137 None
138 }
139
140 #[cfg(feature = "computed")]
143 fn is_computed_field(&self, _field_index: usize) -> bool {
144 false
145 }
146
147 #[cfg(feature = "computed")]
150 fn computed_field_value(&self, _field_index: usize) -> Option<String> {
151 None
152 }
153}
154
155#[cfg(feature = "suggestions")]
156#[derive(Debug, Clone)]
157pub struct SuggestionItem {
158 pub display_text: String,
159 pub value_to_store: String,
160}
161
162#[cfg(feature = "suggestions")]
163impl SuggestionItem {
164 pub fn new(display: impl Into<String>, value: impl Into<String>) -> Self {
165 Self {
166 display_text: display.into(),
167 value_to_store: value.into(),
168 }
169 }
170}