@@ -9,11 +9,20 @@ use crate::{
9
9
} ;
10
10
use anyhow:: Result ;
11
11
use crossterm:: event:: { Event , KeyCode , KeyModifiers } ;
12
+ use itertools:: Itertools ;
13
+ use std:: ops:: Range ;
12
14
use tui:: {
13
15
backend:: Backend , layout:: Rect , style:: Modifier , text:: Span ,
14
16
widgets:: Clear , Frame ,
15
17
} ;
16
18
19
+ #[ derive( PartialEq ) ]
20
+ pub enum InputType {
21
+ Singleline ,
22
+ Multiline ,
23
+ Password ,
24
+ }
25
+
17
26
/// primarily a subcomponet for user input of text (used in `CommitComponent`)
18
27
pub struct TextInputComponent {
19
28
title : String ,
@@ -23,6 +32,7 @@ pub struct TextInputComponent {
23
32
theme : SharedTheme ,
24
33
key_config : SharedKeyConfig ,
25
34
cursor_position : usize ,
35
+ input_type : InputType ,
26
36
}
27
37
28
38
impl TextInputComponent {
@@ -41,9 +51,18 @@ impl TextInputComponent {
41
51
title : title. to_string ( ) ,
42
52
default_msg : default_msg. to_string ( ) ,
43
53
cursor_position : 0 ,
54
+ input_type : InputType :: Multiline ,
44
55
}
45
56
}
46
57
58
+ pub const fn with_input_type (
59
+ mut self ,
60
+ input_type : InputType ,
61
+ ) -> Self {
62
+ self . input_type = input_type;
63
+ self
64
+ }
65
+
47
66
/// Clear the `msg`.
48
67
pub fn clear ( & mut self ) {
49
68
self . msg . clear ( ) ;
@@ -113,7 +132,7 @@ impl TextInputComponent {
113
132
// if the cursor is not at the first character.
114
133
if self . cursor_position > 0 {
115
134
txt. push ( Span :: styled (
116
- & self . msg [ ..self . cursor_position ] ,
135
+ self . get_msg ( 0 ..self . cursor_position ) ,
117
136
style,
118
137
) ) ;
119
138
}
@@ -122,7 +141,9 @@ impl TextInputComponent {
122
141
. next_char_position ( )
123
142
// if the cursor is at the end of the msg
124
143
// a whitespace is used to underline
125
- . map_or ( " " , |pos| & self . msg [ self . cursor_position ..pos] ) ;
144
+ . map_or ( " " . to_owned ( ) , |pos| {
145
+ self . get_msg ( self . cursor_position ..pos)
146
+ } ) ;
126
147
127
148
if cursor_str == "\n " {
128
149
txt. push ( Span :: styled (
@@ -142,12 +163,22 @@ impl TextInputComponent {
142
163
// still remaining characters.
143
164
if let Some ( pos) = self . next_char_position ( ) {
144
165
if pos < self . msg . len ( ) {
145
- txt. push ( Span :: styled ( & self . msg [ pos..] , style) ) ;
166
+ txt. push ( Span :: styled (
167
+ self . get_msg ( pos..self . msg . len ( ) ) ,
168
+ style,
169
+ ) ) ;
146
170
}
147
171
}
148
172
149
173
txt
150
174
}
175
+
176
+ fn get_msg ( & self , range : Range < usize > ) -> String {
177
+ match self . input_type {
178
+ InputType :: Password => range. map ( |_| "*" ) . join ( "" ) ,
179
+ _ => self . msg [ range] . to_owned ( ) ,
180
+ }
181
+ }
151
182
}
152
183
153
184
impl DrawableComponent for TextInputComponent {
@@ -166,8 +197,13 @@ impl DrawableComponent for TextInputComponent {
166
197
self . get_draw_text ( )
167
198
} ;
168
199
169
- let area = ui:: centered_rect ( 60 , 20 , f. size ( ) ) ;
170
- let area = ui:: rect_min ( 10 , 3 , area) ;
200
+ let area = match self . input_type {
201
+ InputType :: Multiline => {
202
+ let area = ui:: centered_rect ( 60 , 20 , f. size ( ) ) ;
203
+ ui:: rect_min ( 10 , 3 , area)
204
+ }
205
+ _ => ui:: centered_rect_absolute ( 32 , 3 , f. size ( ) ) ,
206
+ } ;
171
207
172
208
f. render_widget ( Clear , area) ;
173
209
f. render_widget (
0 commit comments