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);
16 register_put0(vis
, &vis
->registers
[VIS_REG_COMMAND
], cmd
+1);
17 return vis_cmd(vis
, cmd
+1);
23 static void prompt_hide(Win
*win
) {
24 Text
*txt
= win
->file
->text
;
25 size_t size
= text_size(txt
);
26 /* make sure that file is new line terminated */
28 if (size
> 1 && text_byte_get(txt
, size
-1, &lastchar
) && lastchar
!= '\n')
29 text_insert(txt
, size
, "\n", 1);
30 /* remove empty entries */
31 Filerange line
= text_object_line(txt
, size
);
32 size_t line_size
= text_range_size(&line
);
34 text_delete(txt
, line
.start
, line_size
);
35 vis_window_close(win
);
38 static void prompt_restore(Win
*win
) {
40 /* restore window and mode which was active before the prompt window
41 * we deliberately don't use vis_mode_switch because we do not want
42 * to invoke the modes enter/leave functions */
44 vis
->win
= win
->parent
;
45 vis
->mode
= win
->parent_mode
;
48 static const char *prompt_enter(Vis
*vis
, const char *keys
, const Arg
*arg
) {
49 Win
*prompt
= vis
->win
;
50 View
*view
= prompt
->view
;
51 Text
*txt
= prompt
->file
->text
;
52 Win
*win
= prompt
->parent
;
55 Filerange range
= view_selection_get(view
);
56 if (!text_range_valid(&range
))
57 range
= text_object_line(txt
, view_cursor_get(view
));
58 if (text_range_valid(&range
))
59 cmd
= text_bytes_alloc0(txt
, range
.start
, text_range_size(&range
));
62 vis_info_show(vis
, "Prompt window invalid\n");
63 prompt_restore(prompt
);
69 size_t len
= strlen(cmd
);
70 if (len
> 0 && cmd
[len
-1] == '\n')
73 bool lastline
= (range
.end
== text_size(txt
));
75 prompt_restore(prompt
);
76 if (vis_prompt_cmd(vis
, cmd
)) {
79 text_delete(txt
, range
.start
, text_range_size(&range
));
80 text_appendf(txt
, "%s\n", cmd
);
84 vis
->mode
= &vis_modes
[VIS_MODE_INSERT
];
91 static const char *prompt_esc(Vis
*vis
, const char *keys
, const Arg
*arg
) {
92 Win
*prompt
= vis
->win
;
93 if (view_cursors_multiple(prompt
->view
)) {
94 view_cursors_clear(prompt
->view
);
96 prompt_restore(prompt
);
102 static const char *prompt_up(Vis
*vis
, const char *keys
, const Arg
*arg
) {
103 vis_motion(vis
, VIS_MOVE_LINE_UP
);
104 vis_window_mode_unmap(vis
->win
, VIS_MODE_INSERT
, "<Up>");
105 view_options_set(vis
->win
->view
, UI_OPTION_NONE
);
109 static const char *prompt_backspace(Vis
*vis
, const char *keys
, const Arg
*arg
) {
110 Win
*prompt
= vis
->win
;
111 Text
*txt
= prompt
->file
->text
;
112 size_t size
= text_size(txt
);
113 size_t pos
= view_cursor_get(prompt
->view
);
115 if (pos
== size
&& (pos
== 1 || (size
>= 2 && text_byte_get(txt
, size
-2, &c
) && c
== '\n'))) {
116 prompt_restore(prompt
);
119 vis_operator(vis
, VIS_OP_DELETE
);
120 vis_motion(vis
, VIS_MOVE_CHAR_PREV
);
125 static const KeyBinding prompt_enter_binding
= {
127 .action
= &(KeyAction
){
128 .func
= prompt_enter
,
132 static const KeyBinding prompt_esc_binding
= {
134 .action
= &(KeyAction
){
139 static const KeyBinding prompt_up_binding
= {
141 .action
= &(KeyAction
){
146 static const KeyBinding prompt_backspace_binding
= {
148 .action
= &(KeyAction
){
149 .func
= prompt_backspace
,
153 void vis_prompt_show(Vis
*vis
, const char *title
) {
154 Win
*active
= vis
->win
;
155 Win
*prompt
= window_new_file(vis
, title
[0] == ':' ? vis
->command_file
: vis
->search_file
);
158 if (vis
->mode
->visual
)
159 window_selection_save(active
);
160 view_options_set(prompt
->view
, UI_OPTION_ONELINE
);
161 Text
*txt
= prompt
->file
->text
;
162 text_insert(txt
, text_size(txt
), title
, strlen(title
));
163 Cursor
*cursor
= view_cursors_primary_get(prompt
->view
);
164 view_cursors_scroll_to(cursor
, text_size(txt
));
165 view_draw(prompt
->view
);
166 prompt
->parent
= active
;
167 prompt
->parent_mode
= vis
->mode
;
168 vis_window_mode_map(prompt
, VIS_MODE_NORMAL
, "<Enter>", &prompt_enter_binding
);
169 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Enter>", &prompt_enter_binding
);
170 vis_window_mode_map(prompt
, VIS_MODE_VISUAL
, "<Enter>", &prompt_enter_binding
);
171 vis_window_mode_map(prompt
, VIS_MODE_NORMAL
, "<Escape>", &prompt_esc_binding
);
172 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Up>", &prompt_up_binding
);
173 vis_window_mode_map(prompt
, VIS_MODE_INSERT
, "<Backspace>", &prompt_backspace_binding
);
174 vis_mode_switch(vis
, VIS_MODE_INSERT
);
178 void vis_info_show(Vis
*vis
, const char *msg
, ...) {
181 vis
->ui
->info(vis
->ui
, msg
, ap
);
185 void vis_info_hide(Vis
*vis
) {
186 vis
->ui
->info_hide(vis
->ui
);
189 void vis_message_show(Vis
*vis
, const char *msg
) {
192 if (!vis
->message_window
)
193 vis
->message_window
= window_new_file(vis
, vis
->error_file
);
194 Win
*win
= vis
->message_window
;
197 Text
*txt
= win
->file
->text
;
198 size_t pos
= text_size(txt
);
199 text_appendf(txt
, "%s\n", msg
);
200 text_save(txt
, NULL
);
201 view_cursor_to(win
->view
, pos
);
202 vis_window_focus(win
);
205 void vis_message_hide(Vis
*vis
) {
206 if (!vis
->message_window
)
208 vis_window_close(vis
->message_window
);
209 vis
->message_window
= NULL
;