inquire/prompts/sort/
mod.rs1mod action;
4mod config;
5mod prompt;
6#[cfg(test)]
7#[cfg(feature = "crossterm")]
8mod test;
9
10use std::fmt::Display;
11
12use crate::{
13 config::get_configuration,
14 error::{InquireError, InquireResult},
15 formatter::MultiOptionFormatter,
16 list_option::ListOption,
17 prompts::prompt::Prompt,
18 terminal::get_default_terminal,
19 ui::{Backend, RenderConfig, SortBackend},
20};
21
22use self::prompt::SortPrompt;
23
24#[derive(Clone)]
41pub struct Sort<'a, T> {
42 pub message: &'a str,
44
45 pub options: Vec<T>,
47
48 pub help_message: Option<&'a str>,
50
51 pub page_size: usize,
53
54 pub vim_mode: bool,
56
57 pub starting_cursor: usize,
59
60 pub formatter: MultiOptionFormatter<'a, T>,
62
63 pub render_config: RenderConfig<'a>,
65}
66
67impl<'a, T> Sort<'a, T>
68where
69 T: Display,
70{
71 pub const DEFAULT_FORMATTER: MultiOptionFormatter<'a, T> = &|ans| {
73 ans.iter()
74 .map(|opt| opt.to_string())
75 .collect::<Vec<String>>()
76 .join(", ")
77 };
78
79 pub const DEFAULT_PAGE_SIZE: usize = crate::config::DEFAULT_PAGE_SIZE;
81
82 pub const DEFAULT_VIM_MODE: bool = crate::config::DEFAULT_VIM_MODE;
84
85 pub const DEFAULT_STARTING_CURSOR: usize = 0;
87
88 pub const DEFAULT_HELP_MESSAGE: Option<&'a str> =
90 Some("[Space] to select, [↑/↓] (or j/k) to reorder, [Enter] to apply");
91
92 pub fn new(message: &'a str, options: Vec<T>) -> Self {
94 Self {
95 message,
96 options,
97 help_message: Self::DEFAULT_HELP_MESSAGE,
98 page_size: Self::DEFAULT_PAGE_SIZE,
99 vim_mode: Self::DEFAULT_VIM_MODE,
100 starting_cursor: Self::DEFAULT_STARTING_CURSOR,
101 formatter: Self::DEFAULT_FORMATTER,
102 render_config: get_configuration(),
103 }
104 }
105
106 pub fn with_help_message(mut self, message: &'a str) -> Self {
108 self.help_message = Some(message);
109 self
110 }
111
112 pub fn without_help_message(mut self) -> Self {
114 self.help_message = None;
115 self
116 }
117
118 pub fn with_page_size(mut self, page_size: usize) -> Self {
120 self.page_size = page_size;
121 self
122 }
123
124 pub fn with_vim_mode(mut self, vim_mode: bool) -> Self {
126 self.vim_mode = vim_mode;
127 self
128 }
129
130 pub fn with_starting_cursor(mut self, starting_cursor: usize) -> Self {
132 self.starting_cursor = starting_cursor;
133 self
134 }
135
136 pub fn with_formatter(mut self, formatter: MultiOptionFormatter<'a, T>) -> Self {
138 self.formatter = formatter;
139 self
140 }
141
142 pub fn with_render_config(mut self, render_config: RenderConfig<'a>) -> Self {
144 self.render_config = render_config;
145 self
146 }
147
148 pub fn prompt(self) -> InquireResult<Vec<T>> {
150 self.raw_prompt()
151 .map(|op| op.into_iter().map(|o| o.value).collect())
152 }
153
154 pub fn prompt_skippable(self) -> InquireResult<Option<Vec<T>>> {
157 match self.prompt() {
158 Ok(answer) => Ok(Some(answer)),
159 Err(InquireError::OperationCanceled) => Ok(None),
160 Err(err) => Err(err),
161 }
162 }
163
164 pub fn raw_prompt_skippable(self) -> InquireResult<Option<Vec<ListOption<T>>>> {
167 match self.raw_prompt() {
168 Ok(answer) => Ok(Some(answer)),
169 Err(InquireError::OperationCanceled) => Ok(None),
170 Err(err) => Err(err),
171 }
172 }
173
174 pub fn raw_prompt(self) -> InquireResult<Vec<ListOption<T>>> {
176 let (input_reader, terminal) = get_default_terminal()?;
177 let mut backend = Backend::new(input_reader, terminal, self.render_config)?;
178 self.prompt_with_backend(&mut backend)
179 }
180
181 pub(crate) fn prompt_with_backend<B: SortBackend>(
183 self,
184 backend: &mut B,
185 ) -> InquireResult<Vec<ListOption<T>>> {
186 SortPrompt::new(self)?.prompt(backend)
187 }
188}