3 #include "text-objects.h"
6 bool vis_prompt_cmd(Vis
*vis
, const char *cmd
) {
7 if (!cmd
|| !cmd
[0] || !cmd
[1])
11 return vis_motion(vis
, VIS_MOVE_SEARCH_FORWARD
, cmd
+1);
13 return vis_motion(vis
, VIS_MOVE_SEARCH_BACKWARD
, cmd
+1);
17 bool ret
= vis_cmd(vis
, cmd
+1);
18 if (ret
&& vis
->mode
->visual
)
19 vis_mode_switch(vis
, VIS_MODE_NORMAL
);
27 static void prompt_hide(Win
*win
) {
28 Text
*txt
= win
->file
->text
;
29 size_t size
= text_size(txt
);
30 /* make sure that file is new line terminated */
32 if (size
> 1 && text_byte_get(txt
, size
-1, &lastchar
) && lastchar
!= '\n')
33 text_insert(txt
, size
, "\n", 1);
34 /* remove empty entries */
35 Filerange line
= text_object_line(txt
, size
);
36 size_t line_size
= text_range_size(&line
);
38 text_delete(txt
, line
.start
, line_size
);
39 vis_window_close(win
);
42 static void prompt_restore(Win
*win
) {
44 /* restore window and mode which was active before the prompt window
45 * we deliberately don't use vis_mode_switch because we do not want
46 * to invoke the modes enter/leave functions */
48 vis
->win
= win
->parent
;
49 vis
->mode
= win
->parent_mode
;
52 static const char *prompt_enter(Vis
*vis
, const char *keys
, const Arg
*arg
) {
53 Win
*prompt
= vis
->win
;
54 View
*view
= prompt
->view
;
55 Text
*txt
= prompt
->file
->text
;
56 Win
*win
= prompt
->parent
;
59 Filerange range
= view_selection_get(view
);
60 if (!text_range_valid(&range
))
61 range
= text_object_line(txt
, view_cursor_get(view
));
62 if (text_range_valid(&range
))
63 cmd
= text_bytes_alloc0(txt
, range
.start
, text_range_size(&range
));
66 vis_info_show(vis
, "Prompt window invalid\n");
67 prompt_restore(prompt
);
73 size_t len
= strlen(cmd
);
74 if (len
> 0 && cmd
[len
-1] == '\n')
77 bool lastline
= (range
.end
== text_size(txt
));
79 prompt_restore(prompt
);
80 if (vis_prompt_cmd(vis
, cmd
)) {
83 text_delete(txt
, range
.start
, text_range_size(&range
));
84 text_appendf(txt
, "%s\n", cmd
);
88 vis
->mode
= &vis_modes
[VIS_MODE_INSERT
];
95 static const char *prompt_esc(Vis
*vis
, const char *keys
, const Arg
*arg
) {
96 Win
*prompt
= vis
->win
;
97 if (view_cursors_count(prompt
->view
) > 1) {
98 view_cursors_clear(prompt
->view
);
100 prompt_restore(prompt
);
106 static const char *prompt_up(Vis
*vis
, const char *keys
, const Arg
*arg
) {
107 vis_motion(vis
, VIS_MOVE_LINE_UP
);
108 vis_window_mode_unmap(vis
->win
, VIS_MODE_INSERT
, "<Up>");
109 view_options_set(vis
->win
->view
, UI_OPTION_NONE
);
113 static const char *prompt_backspace(Vis
*vis
, const char *keys
, const Arg
*arg
) {
114 Win
*prompt
= vis
->win
;
115 Text
*txt
= prompt
->file
->text
;
116 size_t size
= text_size(txt
);
117 size_t pos
= view_cursor_get(prompt
->view
);
119 if (pos
== size
&& (pos
== 1 || (size
>= 2 && text_byte_get(txt
, size
-2, &c
) && c
== '\n'))) {
120 prompt_restore(prompt
);
123 vis_operator(vis
, VIS_OP_DELETE
);
124 vis_motion(vis
, VIS_MOVE_CHAR_PREV
);
129 static const KeyBinding prompt_enter_binding
= {
131 .action
= &(KeyAction
){
132 .func
= prompt_enter
,
136 static const KeyBinding prompt_esc_binding
= {
138 .action
= &(KeyAction
){
143 static const KeyBinding prompt_up_binding
= {
145 .action
= &(KeyAction
){
150 static const KeyBinding prompt_backspace_binding
= {
152 .action
= &(KeyAction
){
153 .func
= prompt_backspace
,
157 void vis_prompt_show(Vis
*vis
, const char *title
) {
158 Win
*active
= vis
->win
;
159 Win
*prompt
= window_new_file(vis
, title
[0] == ':' ? vis
->command_file
: vis
->search_file
);
162 if (vis
->mode
->visual
)
163 window_selection_save(active
);
164 view_options_set(prompt
->view
, UI_OPTION_ONELINE
);
165 Text
*txt
= prompt
->file
->text
;
166 text_insert(txt
, text_size(txt
), title
, strlen(title
));
167 view_cursors_scroll_to(view_cursor(prompt
->view
), text_size(txt
));
168 view_draw(prompt
->view
);
169 prompt
->parent
= active
;
170 prompt
->parent_mode
= vis
->mode
;
171 vis_window_mode_map(prompt
, VIS_MODE_NORMAL
, "<Enter>", &prompt_enter_binding
);
172 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Enter>", &prompt_enter_binding
);
173 vis_window_mode_map(prompt
, VIS_MODE_VISUAL
, "<Enter>", &prompt_enter_binding
);
174 vis_window_mode_map(prompt
, VIS_MODE_NORMAL
, "<Escape>", &prompt_esc_binding
);
175 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Up>", &prompt_up_binding
);
176 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Backspace>", &prompt_backspace_binding
);
177 vis_mode_switch(vis
, VIS_MODE_INSERT
);
181 void vis_info_show(Vis
*vis
, const char *msg
, ...) {
184 vis
->ui
->info(vis
->ui
, msg
, ap
);
188 void vis_info_hide(Vis
*vis
) {
189 vis
->ui
->info_hide(vis
->ui
);
192 void vis_message_show(Vis
*vis
, const char *msg
) {
195 if (!vis
->message_window
) {
196 if (!vis_window_new(vis
, NULL
))
198 vis
->message_window
= vis
->win
;
201 Win
*win
= vis
->message_window
;
202 Text
*txt
= win
->file
->text
;
203 size_t pos
= text_size(txt
);
204 text_appendf(txt
, "%s\n", msg
);
205 text_save(txt
, NULL
);
206 view_cursor_to(win
->view
, pos
);
209 void vis_message_hide(Vis
*vis
) {
210 if (!vis
->message_window
)
212 vis_window_close(vis
->message_window
);
213 vis
->message_window
= NULL
;