Merge branch '4562_mcedit_macros_paste'
[midnight-commander.git] / src / filemanager / command.c
blob9a3d74f447c2de84084746701ce365369993bf97
1 /*
2 Command line widget.
3 This widget is derived from the WInput widget, it's used to cope
4 with all the magic of the command input line, we depend on some
5 help from the program's callback.
7 Copyright (C) 1995-2024
8 Free Software Foundation, Inc.
10 Written by:
11 Slava Zanko <slavazanko@gmail.com>, 2013
12 Andrew Borodin <aborodin@vmail.ru>, 2011-2022
14 This file is part of the Midnight Commander.
16 The Midnight Commander is free software: you can redistribute it
17 and/or modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation, either version 3 of the License,
19 or (at your option) any later version.
21 The Midnight Commander is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 /** \file command.c
31 * \brief Source: command line widget
34 #include <config.h>
36 #include <stdlib.h>
37 #include <string.h>
39 #include "lib/global.h"
40 #include "lib/vfs/vfs.h" /* vfs_current_is_local() */
41 #include "lib/skin.h" /* DEFAULT_COLOR */
42 #include "lib/util.h" /* whitespace() */
43 #include "lib/widget.h"
45 #include "src/setup.h" /* quit */
46 #ifdef ENABLE_SUBSHELL
47 #include "src/subshell/subshell.h"
48 #endif
49 #include "src/execute.h" /* shell_execute() */
50 #include "src/usermenu.h" /* expand_format() */
52 #include "filemanager.h" /* quiet_quit_cmd(), layout.h */
53 #include "cd.h" /* cd_to() */
55 #include "command.h"
57 /*** global variables ****************************************************************************/
59 /* This holds the command line */
60 WInput *cmdline;
62 /*** file scope macro definitions ****************************************************************/
64 /*** file scope type declarations ****************************************************************/
66 /*** forward declarations (file scope functions) *************************************************/
68 /*** file scope variables ************************************************************************/
70 /* Color styles command line */
71 static input_colors_t command_colors;
73 /* --------------------------------------------------------------------------------------------- */
74 /*** file scope functions ************************************************************************/
75 /* --------------------------------------------------------------------------------------------- */
77 /** Handle Enter on the command line
79 * @param lc_cmdline string for handling
80 * @return MSG_HANDLED on success else MSG_NOT_HANDLED
83 static cb_ret_t
84 enter (WInput *lc_cmdline)
86 const char *cmd;
88 if (!command_prompt)
89 return MSG_HANDLED;
91 cmd = input_get_ctext (lc_cmdline);
93 /* Any initial whitespace should be removed at this point */
94 while (whiteness (*cmd))
95 cmd++;
97 if (*cmd == '\0')
98 return MSG_HANDLED;
100 if (strncmp (cmd, "cd", 2) == 0 && (cmd[2] == '\0' || whitespace (cmd[2])))
102 cd_to (cmd + 2);
103 input_clean (lc_cmdline);
104 return MSG_HANDLED;
106 else if (strcmp (cmd, "exit") == 0)
108 input_assign_text (lc_cmdline, "");
109 if (!quiet_quit_cmd ())
110 return MSG_NOT_HANDLED;
112 else
114 GString *command;
115 size_t i;
117 if (!vfs_current_is_local ())
119 message (D_ERROR, MSG_ERROR, _("Cannot execute commands on non-local filesystems"));
120 return MSG_NOT_HANDLED;
122 #ifdef ENABLE_SUBSHELL
123 /* Check this early before we clean command line
124 * (will be checked again by shell_execute) */
125 if (mc_global.tty.use_subshell && subshell_state != INACTIVE)
127 message (D_ERROR, MSG_ERROR, _("The shell is already running a command"));
128 return MSG_NOT_HANDLED;
130 #endif
131 command = g_string_sized_new (32);
133 for (i = 0; cmd[i] != '\0'; i++)
135 if (cmd[i] != '%')
136 g_string_append_c (command, cmd[i]);
137 else
139 char *s;
141 s = expand_format (NULL, cmd[++i], TRUE);
142 if (s != NULL)
144 g_string_append (command, s);
145 g_free (s);
150 input_clean (lc_cmdline);
151 shell_execute (command->str, 0);
152 g_string_free (command, TRUE);
154 #ifdef ENABLE_SUBSHELL
155 if ((quit & SUBSHELL_EXIT) != 0)
157 if (quiet_quit_cmd ())
158 return MSG_HANDLED;
160 quit = 0;
161 /* restart subshell */
162 if (mc_global.tty.use_subshell)
163 init_subshell ();
166 if (mc_global.tty.use_subshell)
167 do_load_prompt ();
168 #endif
170 return MSG_HANDLED;
173 /* --------------------------------------------------------------------------------------------- */
176 * Default command line callback
178 * @param w Widget object
179 * @param msg message for handling
180 * @param parm extra parameter such as key code
182 * @return MSG_NOT_HANDLED on fail else MSG_HANDLED
185 static cb_ret_t
186 command_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
188 switch (msg)
190 case MSG_KEY:
191 /* Special case: we handle the enter key */
192 if (parm == '\n')
193 return enter (INPUT (w));
194 MC_FALLTHROUGH;
196 default:
197 return input_callback (w, sender, msg, parm, data);
201 /* --------------------------------------------------------------------------------------------- */
202 /*** public functions ****************************************************************************/
203 /* --------------------------------------------------------------------------------------------- */
205 WInput *
206 command_new (int y, int x, int cols)
208 WInput *cmd;
209 Widget *w;
211 cmd = input_new (y, x, command_colors, cols, "", "cmdline",
212 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES
213 | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS |
214 INPUT_COMPLETE_SHELL_ESC);
215 w = WIDGET (cmd);
216 /* Don't set WOP_SELECTABLE up, otherwise panels will be unselected */
217 widget_set_options (w, WOP_SELECTABLE, FALSE);
218 /* Add our hooks */
219 w->callback = command_callback;
221 return cmd;
224 /* --------------------------------------------------------------------------------------------- */
226 * Set colors for the command line.
229 void
230 command_set_default_colors (void)
232 command_colors[WINPUTC_MAIN] = DEFAULT_COLOR;
233 command_colors[WINPUTC_MARK] = COMMAND_MARK_COLOR;
234 command_colors[WINPUTC_UNCHANGED] = DEFAULT_COLOR;
235 command_colors[WINPUTC_HISTORY] = COMMAND_HISTORY_COLOR;
238 /* --------------------------------------------------------------------------------------------- */
240 * Insert quoted text in input line. The function is meant for the
241 * command line, so the percent sign is quoted as well.
243 * @param in WInput object
244 * @param text string for insertion
245 * @param insert_extra_space add extra space
248 void
249 command_insert (WInput *in, const char *text, gboolean insert_extra_space)
251 char *quoted_text;
253 quoted_text = name_quote (text, TRUE);
254 if (quoted_text != NULL)
256 input_insert (in, quoted_text, insert_extra_space);
257 g_free (quoted_text);
261 /* --------------------------------------------------------------------------------------------- */