diff options
Diffstat (limited to 'src/filemanager/command.c')
-rw-r--r-- | src/filemanager/command.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/filemanager/command.c b/src/filemanager/command.c new file mode 100644 index 0000000..47d2d75 --- /dev/null +++ b/src/filemanager/command.c @@ -0,0 +1,255 @@ +/* + Command line widget. + This widget is derived from the WInput widget, it's used to cope + with all the magic of the command input line, we depend on some + help from the program's callback. + + Copyright (C) 1995-2023 + Free Software Foundation, Inc. + + Written by: + Slava Zanko <slavazanko@gmail.com>, 2013 + Andrew Borodin <aborodin@vmail.ru>, 2011-2022 + + This file is part of the Midnight Commander. + + The Midnight Commander is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file command.c + * \brief Source: command line widget + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> + +#include "lib/global.h" +#include "lib/vfs/vfs.h" /* vfs_current_is_local() */ +#include "lib/skin.h" /* DEFAULT_COLOR */ +#include "lib/util.h" /* whitespace() */ +#include "lib/widget.h" + +#include "src/setup.h" /* quit */ +#ifdef ENABLE_SUBSHELL +#include "src/subshell/subshell.h" +#endif +#include "src/execute.h" /* shell_execute() */ +#include "src/usermenu.h" /* expand_format() */ + +#include "filemanager.h" /* quiet_quit_cmd(), layout.h */ +#include "cd.h" /* cd_to() */ + +#include "command.h" + +/*** global variables ****************************************************************************/ + +/* This holds the command line */ +WInput *cmdline; + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +/*** forward declarations (file scope functions) *************************************************/ + +/*** file scope variables ************************************************************************/ + +/* Color styles command line */ +static input_colors_t command_colors; + +/* --------------------------------------------------------------------------------------------- */ +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +/** Handle Enter on the command line + * + * @param lc_cmdline string for handling + * @return MSG_HANDLED on success else MSG_NOT_HANDLED + */ + +static cb_ret_t +enter (WInput * lc_cmdline) +{ + const char *cmd; + + if (!command_prompt) + return MSG_HANDLED; + + cmd = input_get_ctext (lc_cmdline); + + /* Any initial whitespace should be removed at this point */ + while (whiteness (*cmd)) + cmd++; + + if (*cmd == '\0') + return MSG_HANDLED; + + if (strncmp (cmd, "cd", 2) == 0 && (cmd[2] == '\0' || whitespace (cmd[2]))) + { + cd_to (cmd + 2); + input_clean (lc_cmdline); + return MSG_HANDLED; + } + else if (strcmp (cmd, "exit") == 0) + { + input_assign_text (lc_cmdline, ""); + if (!quiet_quit_cmd ()) + return MSG_NOT_HANDLED; + } + else + { + GString *command; + size_t i; + + if (!vfs_current_is_local ()) + { + message (D_ERROR, MSG_ERROR, _("Cannot execute commands on non-local filesystems")); + return MSG_NOT_HANDLED; + } +#ifdef ENABLE_SUBSHELL + /* Check this early before we clean command line + * (will be checked again by shell_execute) */ + if (mc_global.tty.use_subshell && subshell_state != INACTIVE) + { + message (D_ERROR, MSG_ERROR, _("The shell is already running a command")); + return MSG_NOT_HANDLED; + } +#endif + command = g_string_sized_new (32); + + for (i = 0; cmd[i] != '\0'; i++) + { + if (cmd[i] != '%') + g_string_append_c (command, cmd[i]); + else + { + char *s; + + s = expand_format (NULL, cmd[++i], TRUE); + g_string_append (command, s); + g_free (s); + } + } + + input_clean (lc_cmdline); + shell_execute (command->str, 0); + g_string_free (command, TRUE); + +#ifdef ENABLE_SUBSHELL + if ((quit & SUBSHELL_EXIT) != 0) + { + if (quiet_quit_cmd ()) + return MSG_HANDLED; + + quit = 0; + /* restart subshell */ + if (mc_global.tty.use_subshell) + init_subshell (); + } + + if (mc_global.tty.use_subshell) + do_load_prompt (); +#endif + } + return MSG_HANDLED; +} + +/* --------------------------------------------------------------------------------------------- */ + +/** + * Default command line callback + * + * @param w Widget object + * @param msg message for handling + * @param parm extra parameter such as key code + * + * @return MSG_NOT_HANDLED on fail else MSG_HANDLED + */ + +static cb_ret_t +command_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) +{ + switch (msg) + { + case MSG_KEY: + /* Special case: we handle the enter key */ + if (parm == '\n') + return enter (INPUT (w)); + MC_FALLTHROUGH; + + default: + return input_callback (w, sender, msg, parm, data); + } +} + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +WInput * +command_new (int y, int x, int cols) +{ + WInput *cmd; + Widget *w; + + cmd = input_new (y, x, command_colors, cols, "", "cmdline", + INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES + | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_COMMANDS | + INPUT_COMPLETE_SHELL_ESC); + w = WIDGET (cmd); + /* Don't set WOP_SELECTABLE up, otherwise panels will be unselected */ + widget_set_options (w, WOP_SELECTABLE, FALSE); + /* Add our hooks */ + w->callback = command_callback; + + return cmd; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Set colors for the command line. + */ + +void +command_set_default_colors (void) +{ + command_colors[WINPUTC_MAIN] = DEFAULT_COLOR; + command_colors[WINPUTC_MARK] = COMMAND_MARK_COLOR; + command_colors[WINPUTC_UNCHANGED] = DEFAULT_COLOR; + command_colors[WINPUTC_HISTORY] = COMMAND_HISTORY_COLOR; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Insert quoted text in input line. The function is meant for the + * command line, so the percent sign is quoted as well. + * + * @param in WInput object + * @param text string for insertion + * @param insert_extra_space add extra space + */ + +void +command_insert (WInput * in, const char *text, gboolean insert_extra_space) +{ + char *quoted_text; + + quoted_text = name_quote (text, TRUE); + input_insert (in, quoted_text, insert_extra_space); + g_free (quoted_text); +} + +/* --------------------------------------------------------------------------------------------- */ |