From dfdc70f8978d5ea445ec77458fa1ee745a2b0214 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 24 Nov 2024 12:25:15 +0300 Subject: [PATCH] (subshell_chdir): move to src/subshell/common.c, make public. (do_subshell_chdir): make static. Signed-off-by: Andrew Borodin --- src/filemanager/panel.c | 20 +-- src/subshell/common.c | 264 ++++++++++++++++++++-------------------- src/subshell/subshell.h | 2 +- 3 files changed, 141 insertions(+), 145 deletions(-) diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c index 44b25bd41..f7e0d2363 100644 --- a/src/filemanager/panel.c +++ b/src/filemanager/panel.c @@ -62,7 +62,7 @@ #include "src/keymap.h" /* global_keymap_t */ #include "src/history.h" #ifdef ENABLE_SUBSHELL -#include "src/subshell/subshell.h" /* do_subshell_chdir() */ +#include "src/subshell/subshell.h" /* subshell_chdir() */ #endif #include "src/usermenu.h" @@ -3440,20 +3440,6 @@ get_parent_dir_name (const vfs_path_t *cwd_vpath, const vfs_path_t *lwd_vpath) return (p != lwd || IS_PATH_SEP (*p)) ? p + 1 : p; } -/* --------------------------------------------------------------------------------------------- */ -/** Wrapper for do_subshell_chdir, check for availability of subshell */ - -static void -subshell_chdir (const vfs_path_t *vpath) -{ -#ifdef ENABLE_SUBSHELL - if (mc_global.tty.use_subshell && vfs_current_is_local ()) - do_subshell_chdir (vpath, FALSE); -#else /* ENABLE_SUBSHELL */ - (void) vpath; -#endif /* ENABLE_SUBSHELL */ -} - /* --------------------------------------------------------------------------------------------- */ /** * Changes the current directory of the panel. @@ -3489,7 +3475,9 @@ panel_do_cd_int (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum cd vfs_release_path (olddir_vpath); +#ifdef ENABLE_SUBSHELL subshell_chdir (panel->cwd_vpath); +#endif /* ENABLE_SUBSHELL */ /* Reload current panel */ panel_clean_dir (panel); @@ -3890,8 +3878,10 @@ panel_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *dat cd_error_message (cwd); g_free (cwd); } +#ifdef ENABLE_SUBSHELL else subshell_chdir (panel->cwd_vpath); +#endif /* ENABLE_SUBSHELL */ update_xterm_title_path (); update_terminal_cwd (); diff --git a/src/subshell/common.c b/src/subshell/common.c index 148770dfe..d259a0a20 100644 --- a/src/subshell/common.c +++ b/src/subshell/common.c @@ -1309,10 +1309,140 @@ clear_cwd_pipe (void) } } -/* --------------------------------------------------------------------------------------------- */ -/*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +static void +do_subshell_chdir (const vfs_path_t *vpath, gboolean update_prompt) +{ + char *pcwd; + + pcwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_RECODE); + + if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0)) + { + /* We have to repaint the subshell prompt if we read it from + * the main program. Please note that in the code after this + * if, the cd command that is sent will make the subshell + * repaint the prompt, so we don't have to paint it. */ + if (update_prompt) + do_update_prompt (); + g_free (pcwd); + return; + } + + /* If we are using a shell that doesn't support persistent command buffer, we need to clear + * the command prompt before we send the cd command. */ + if (!use_persistent_buffer) + { + write_all (mc_global.tty.subshell_pty, "\003", 1); + subshell_state = RUNNING_COMMAND; + if (mc_global.shell->type != SHELL_FISH) + if (!feed_subshell (QUIETLY, TRUE)) + { + subshell_state = ACTIVE; + return; + } + } + + /* A quick and dirty fix for fish shell. For some reason, fish does not + * execute all the commands sent to it from Midnight Commander :( + * An example of such buggy behavior is presented in ticket #4521. + * TODO: Find the real cause and fix it "the right way" */ + if (mc_global.shell->type == SHELL_FISH) + { + write_all (mc_global.tty.subshell_pty, "\n", 1); + subshell_state = RUNNING_COMMAND; + feed_subshell (QUIETLY, TRUE); + } + + /* The initial space keeps this out of the command history (in bash + because we set "HISTCONTROL=ignorespace") */ + write_all (mc_global.tty.subshell_pty, " cd ", 4); + + if (vpath == NULL) + write_all (mc_global.tty.subshell_pty, "/", 1); + else + { + const char *translate; + + translate = vfs_translate_path (vfs_path_as_str (vpath)); + if (translate == NULL) + write_all (mc_global.tty.subshell_pty, ".", 1); + else + { + GString *temp; + + temp = subshell_name_quote (translate); + write_all (mc_global.tty.subshell_pty, temp->str, temp->len); + g_string_free (temp, TRUE); + } + } + + write_all (mc_global.tty.subshell_pty, "\n", 1); + + subshell_state = RUNNING_COMMAND; + if (!feed_subshell (QUIETLY, TRUE)) + { + subshell_state = ACTIVE; + return; + } + + if (subshell_alive) + { + gboolean bPathNotEq; + + bPathNotEq = strcmp (subshell_cwd, pcwd) != 0; + + if (bPathNotEq && mc_global.shell->type == SHELL_TCSH) + { + char rp_subshell_cwd[PATH_MAX]; + char rp_current_panel_cwd[PATH_MAX]; + char *p_subshell_cwd, *p_current_panel_cwd; + + p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd); + p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd); + + if (p_subshell_cwd == NULL) + p_subshell_cwd = subshell_cwd; + if (p_current_panel_cwd == NULL) + p_current_panel_cwd = pcwd; + bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd) != 0; + } + + if (bPathNotEq && !DIR_IS_DOT (pcwd)) + { + char *cwd; + + cwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_STRIP_PASSWORD); + vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd); + g_free (cwd); + } + } + + /* Really escape Zsh/Fish history */ + if (mc_global.shell->type == SHELL_ZSH || mc_global.shell->type == SHELL_FISH) + { + /* Per Zsh documentation last command prefixed with space lingers in the internal history + * until the next command is entered before it vanishes. To make it vanish right away, + * type a space and press return. + * + * Fish shell now also provides the same behavior: + * https://github.com/fish-shell/fish-shell/commit/9fdc4f903b8b421b18389a0f290d72cc88c128bb + * */ + write_all (mc_global.tty.subshell_pty, " \n", 2); + subshell_state = RUNNING_COMMAND; + feed_subshell (QUIETLY, TRUE); + } + + update_subshell_prompt = FALSE; + + g_free (pcwd); + /* Make sure that MC never stores the CWD in a silly format */ + /* like /usr////lib/../bin, or the strcmp() above will fail */ +} + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ /** * Fork the subshell, and set up many, many things. @@ -1695,135 +1825,11 @@ exit_subshell (void) /* --------------------------------------------------------------------------------------------- */ -/** If it actually changed the directory it returns true */ void -do_subshell_chdir (const vfs_path_t *vpath, gboolean update_prompt) +subshell_chdir (const vfs_path_t *vpath) { - char *pcwd; - - pcwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_RECODE); - - if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0)) - { - /* We have to repaint the subshell prompt if we read it from - * the main program. Please note that in the code after this - * if, the cd command that is sent will make the subshell - * repaint the prompt, so we don't have to paint it. */ - if (update_prompt) - do_update_prompt (); - g_free (pcwd); - return; - } - - /* If we are using a shell that doesn't support persistent command buffer, we need to clear - * the command prompt before we send the cd command. */ - if (!use_persistent_buffer) - { - write_all (mc_global.tty.subshell_pty, "\003", 1); - subshell_state = RUNNING_COMMAND; - if (mc_global.shell->type != SHELL_FISH) - if (!feed_subshell (QUIETLY, TRUE)) - { - subshell_state = ACTIVE; - return; - } - } - - /* A quick and dirty fix for fish shell. For some reason, fish does not - * execute all the commands sent to it from Midnight Commander :( - * An example of such buggy behavior is presented in ticket #4521. - * TODO: Find the real cause and fix it "the right way" */ - if (mc_global.shell->type == SHELL_FISH) - { - write_all (mc_global.tty.subshell_pty, "\n", 1); - subshell_state = RUNNING_COMMAND; - feed_subshell (QUIETLY, TRUE); - } - - /* The initial space keeps this out of the command history (in bash - because we set "HISTCONTROL=ignorespace") */ - write_all (mc_global.tty.subshell_pty, " cd ", 4); - - if (vpath == NULL) - write_all (mc_global.tty.subshell_pty, "/", 1); - else - { - const char *translate; - - translate = vfs_translate_path (vfs_path_as_str (vpath)); - if (translate == NULL) - write_all (mc_global.tty.subshell_pty, ".", 1); - else - { - GString *temp; - - temp = subshell_name_quote (translate); - write_all (mc_global.tty.subshell_pty, temp->str, temp->len); - g_string_free (temp, TRUE); - } - } - - write_all (mc_global.tty.subshell_pty, "\n", 1); - - subshell_state = RUNNING_COMMAND; - if (!feed_subshell (QUIETLY, TRUE)) - { - subshell_state = ACTIVE; - return; - } - - if (subshell_alive) - { - gboolean bPathNotEq; - - bPathNotEq = strcmp (subshell_cwd, pcwd) != 0; - - if (bPathNotEq && mc_global.shell->type == SHELL_TCSH) - { - char rp_subshell_cwd[PATH_MAX]; - char rp_current_panel_cwd[PATH_MAX]; - char *p_subshell_cwd, *p_current_panel_cwd; - - p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd); - p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd); - - if (p_subshell_cwd == NULL) - p_subshell_cwd = subshell_cwd; - if (p_current_panel_cwd == NULL) - p_current_panel_cwd = pcwd; - bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd) != 0; - } - - if (bPathNotEq && !DIR_IS_DOT (pcwd)) - { - char *cwd; - - cwd = vfs_path_to_str_flags (subshell_get_cwd (), 0, VPF_STRIP_PASSWORD); - vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd); - g_free (cwd); - } - } - - /* Really escape Zsh/Fish history */ - if (mc_global.shell->type == SHELL_ZSH || mc_global.shell->type == SHELL_FISH) - { - /* Per Zsh documentation last command prefixed with space lingers in the internal history - * until the next command is entered before it vanishes. To make it vanish right away, - * type a space and press return. - * - * Fish shell now also provides the same behavior: - * https://github.com/fish-shell/fish-shell/commit/9fdc4f903b8b421b18389a0f290d72cc88c128bb - * */ - write_all (mc_global.tty.subshell_pty, " \n", 2); - subshell_state = RUNNING_COMMAND; - feed_subshell (QUIETLY, TRUE); - } - - update_subshell_prompt = FALSE; - - g_free (pcwd); - /* Make sure that MC never stores the CWD in a silly format */ - /* like /usr////lib/../bin, or the strcmp() above will fail */ + if (mc_global.tty.use_subshell && vfs_current_is_local ()) + do_subshell_chdir (vpath, FALSE); } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/subshell/subshell.h b/src/subshell/subshell.h index bde19c469..b032f7da9 100644 --- a/src/subshell/subshell.h +++ b/src/subshell/subshell.h @@ -46,7 +46,7 @@ gboolean flush_subshell (int max_wait_length, int how); gboolean read_subshell_prompt (void); void do_update_prompt (void); gboolean exit_subshell (void); -void do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt); +void subshell_chdir (const vfs_path_t * vpath); void subshell_get_console_attributes (void); void sigchld_handler (int sig);