1
1
use crate :: {
2
2
components:: { render_container, RenderAbleComponent } ,
3
3
config:: Config ,
4
- constants:: HIGHLIGHT_COLOR ,
4
+ constants:: { BORDER_TYPE , HIGHLIGHT_COLOR } ,
5
5
events:: { EventState , Key } ,
6
6
} ;
7
7
use anyhow:: Result ;
@@ -10,7 +10,7 @@ use tui::{
10
10
layout:: Rect ,
11
11
style:: { Color , Modifier , Style } ,
12
12
text:: Text ,
13
- widgets:: Paragraph ,
13
+ widgets:: { Block , Borders , Paragraph } ,
14
14
Frame ,
15
15
} ;
16
16
use tui_textarea:: { Input , Key as InputKey , TextArea } ;
@@ -20,23 +20,62 @@ enum Focus {
20
20
Textarea ,
21
21
}
22
22
23
- pub struct TextareaComponent {
23
+ #[ derive( Clone , Debug ) ]
24
+ pub struct Command {
25
+ pub token : String ,
26
+ pub value : String ,
27
+ }
28
+
29
+ pub struct CommandComponent {
24
30
config : Config ,
25
31
text : Vec < char > ,
26
32
focus : Focus ,
33
+ invalid : ( bool , String ) ,
34
+ pub commands : Vec < Command > ,
27
35
}
28
36
29
- impl TextareaComponent {
37
+ impl CommandComponent {
30
38
pub fn new ( config : Config ) -> Self {
31
- TextareaComponent {
39
+ CommandComponent {
32
40
config,
33
41
text : vec ! [ ] ,
34
42
focus : Focus :: Container ,
43
+ invalid : ( false , "" . to_string ( ) ) ,
44
+ commands : vec ! [ ] ,
35
45
}
36
46
}
37
47
48
+ fn set_invalid ( & mut self , invalid : bool , err : & str ) {
49
+ self . invalid = ( invalid, err. to_string ( ) ) ;
50
+ }
51
+
52
+ fn add_command ( & mut self , command : Command ) {
53
+ self . commands . push ( command) ;
54
+ }
55
+
38
56
fn handle_command ( & mut self ) {
39
- unimplemented ! ( )
57
+ let mapped: Vec < _ > = self . text . iter ( ) . map ( |t| t. to_string ( ) ) . collect ( ) ;
58
+ let complete = mapped. join ( "" ) ;
59
+ let splitted = complete. split ( ' ' ) ;
60
+ for token in splitted {
61
+ match token {
62
+ t if token. starts_with ( "COLUMN" ) | token. starts_with ( "TABLE" ) => {
63
+ let value = t. split ( '=' ) . nth ( 1 ) ;
64
+ match value {
65
+ Some ( v) => self . add_command ( Command {
66
+ token : "COLUMN" . to_string ( ) ,
67
+ value : v. to_string ( ) ,
68
+ } ) ,
69
+ None => {
70
+ return self . set_invalid ( true , "No COLUMN value found" ) ;
71
+ }
72
+ }
73
+ }
74
+ _ => return self . set_invalid ( true , "Mismatch command" ) ,
75
+ }
76
+ }
77
+
78
+ self . set_invalid ( false , "" ) ;
40
79
}
41
80
42
81
pub async fn event ( & mut self , key : Key ) -> Result < EventState > {
@@ -72,34 +111,43 @@ impl TextareaComponent {
72
111
}
73
112
}
74
113
75
- impl RenderAbleComponent for TextareaComponent {
114
+ impl RenderAbleComponent for CommandComponent {
76
115
fn render < B : Backend > (
77
116
& self ,
78
117
f : & mut Frame < B > ,
79
118
rect : Rect ,
80
119
focused : bool ,
81
120
) -> Result < ( ) , anyhow:: Error > {
121
+ let keycode = match self . focus {
122
+ Focus :: Container => "ENTER" ,
123
+ Focus :: Textarea => "ESC" ,
124
+ } ;
125
+ let label = & format ! ( "Command [{}]" , keycode) ;
82
126
if matches ! ( self . focus, Focus :: Container ) && self . text . is_empty ( ) {
83
127
let mut placeholder = Text :: from ( "Press Enter to write a command" ) ;
84
128
placeholder. patch_style ( Style :: default ( ) . fg ( Color :: DarkGray ) ) ;
85
129
86
- let keycode = match self . focus {
87
- Focus :: Container => "ENTER" ,
88
- Focus :: Textarea => "ESC" ,
89
- } ;
90
- let label = & format ! ( "Command [{}]" , keycode) ;
91
130
let widget = Paragraph :: new ( placeholder) . block ( render_container ( label, focused) ) ;
92
131
f. render_widget ( widget, rect) ;
93
132
} else if matches ! ( self . focus, Focus :: Textarea ) || !self . text . is_empty ( ) {
94
133
let style = Style :: default ( ) . bg ( HIGHLIGHT_COLOR ) . add_modifier ( Modifier :: BOLD ) ;
95
134
let mut textarea = TextArea :: default ( ) ;
96
135
textarea. set_cursor_style ( style) ;
97
- let keycode = match self . focus {
98
- Focus :: Container => "ENTER" ,
99
- Focus :: Textarea => "ESC" ,
136
+
137
+ let ( invalid, err) = & self . invalid ;
138
+ if * invalid {
139
+ let label = & format ! ( "{} [{}]" , err, keycode) ;
140
+ let container = Block :: default ( )
141
+ . borders ( Borders :: ALL )
142
+ . style ( Style :: default ( ) . fg ( Color :: Red ) )
143
+ . title ( label. clone ( ) )
144
+ . border_type ( BORDER_TYPE ) ;
145
+ textarea. set_style ( Style :: default ( ) . fg ( Color :: Red ) ) ;
146
+ textarea. set_block ( container) ;
147
+ } else {
148
+ let container = render_container ( label, focused) ;
149
+ textarea. set_block ( container) ;
100
150
} ;
101
- let label = & format ! ( "Command [{}]" , keycode) ;
102
- textarea. set_block ( render_container ( label, focused) ) ;
103
151
104
152
for c in self . text . iter ( ) {
105
153
textarea. input ( Input {
0 commit comments