Add src/execute.c:execute_external_editor_or_viewer() function.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2013-01-10 20:20:58 +03:00
parent 2406284762
commit 2a2bc56221
6 changed files with 319 additions and 28 deletions

View File

@ -63,6 +63,9 @@ int pause_after_run = pause_on_dumb_terminals;
/*** file scope functions ************************************************************************/
void do_execute (const char *shell, const char *command, int flags);
void do_executev (const char *shell, int flags, char *const argv[]);
char *execute_get_external_cmd_opts_from_config (const char *command,
const vfs_path_t * filename_vpath, int start_line);
/* --------------------------------------------------------------------------------------------- */
@ -164,7 +167,8 @@ do_suspend_cmd (void)
/* --------------------------------------------------------------------------------------------- */
static gboolean
execute_prepare_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath, time_t *mtime)
execute_prepare_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath,
time_t * mtime)
{
struct stat st;
@ -196,7 +200,8 @@ execute_prepare_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** l
/* --------------------------------------------------------------------------------------------- */
static void
execute_cleanup_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath, time_t *mtime)
execute_cleanup_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** localcopy_vpath,
time_t * mtime)
{
if (*localcopy_vpath != NULL)
{
@ -218,8 +223,23 @@ execute_cleanup_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** l
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
char *
execute_get_external_cmd_opts_from_config (const char *command, const vfs_path_t * filename_vpath,
int start_line)
{
(void) command;
(void) start_line;
if (filename_vpath == NULL)
return g_strdup ("");
return g_strdup (vfs_path_get_last_path_str (filename_vpath));
}
/* --------------------------------------------------------------------------------------------- */
void
do_execute (const char *shell, const char *command, int flags)
do_executev (const char *shell, int flags, char *const argv[])
{
#ifdef ENABLE_SUBSHELL
vfs_path_t *new_dir_vpath = NULL;
@ -236,24 +256,24 @@ do_execute (const char *shell, const char *command, int flags)
if (mc_global.tty.console_flag != '\0')
handle_console (CONSOLE_RESTORE);
if (!mc_global.tty.use_subshell && command && !(flags & EXECUTE_INTERNAL))
if (!mc_global.tty.use_subshell && *argv != NULL && (flags & EXECUTE_INTERNAL) == 0)
{
printf ("%s%s\n", mc_prompt, command);
printf ("%s%s\n", mc_prompt, *argv);
fflush (stdout);
}
#ifdef ENABLE_SUBSHELL
if (mc_global.tty.use_subshell && !(flags & EXECUTE_INTERNAL))
if (mc_global.tty.use_subshell && (flags & EXECUTE_INTERNAL) == 0)
{
do_update_prompt ();
/* We don't care if it died, higher level takes care of this */
invoke_subshell (command, VISIBLY, old_vfs_dir_vpath != NULL ? NULL : &new_dir_vpath);
invoke_subshell (*argv, VISIBLY, old_vfs_dir_vpath != NULL ? NULL : &new_dir_vpath);
}
else
#endif /* ENABLE_SUBSHELL */
my_system (flags, shell, command);
my_systemv_flags (flags, shell, argv);
if (!(flags & EXECUTE_INTERNAL))
if ((flags & EXECUTE_INTERNAL) == 0)
{
if ((pause_after_run == pause_always
|| (pause_after_run == pause_on_dumb_terminals && !mc_global.tty.xterm_flag
@ -270,13 +290,10 @@ do_execute (const char *shell, const char *command, int flags)
printf ("\r\n");
fflush (stdout);
}
if (mc_global.tty.console_flag != '\0')
if (mc_global.tty.console_flag != '\0' && output_lines != 0 && mc_global.keybar_visible)
{
if (output_lines && mc_global.keybar_visible)
{
putchar ('\n');
fflush (stdout);
}
putchar ('\n');
fflush (stdout);
}
}
@ -311,6 +328,22 @@ do_execute (const char *shell, const char *command, int flags)
/* --------------------------------------------------------------------------------------------- */
void
do_execute (const char *shell, const char *command, int flags)
{
GPtrArray *args_array;
args_array = g_ptr_array_new ();
g_ptr_array_add (args_array, (char *) command);
g_ptr_array_add (args_array, NULL);
do_executev (shell, flags, (char *const *) args_array->pdata);
g_ptr_array_free (args_array, TRUE);
}
/* --------------------------------------------------------------------------------------------- */
/** Set up the terminal before executing a program */
void
@ -527,3 +560,45 @@ execute_with_vfs_arg (const char *command, const vfs_path_t * filename_vpath)
}
/* --------------------------------------------------------------------------------------------- */
/**
* Execute external editor or viewer.
*
* @param command editor/viewer to run
* @param filename_vpath path for edit/view
* @param start_line cursor will be placed at the 'start_line' position after opening file
*/
void
execute_external_editor_or_viewer (const char *command, const vfs_path_t * filename_vpath,
int start_line)
{
vfs_path_t *localcopy_vpath = NULL;
const vfs_path_t *do_execute_vpath;
char *extern_cmd_options;
time_t mtime;
if (!execute_prepare_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime))
return;
do_execute_vpath = (localcopy_vpath == NULL) ? filename_vpath : localcopy_vpath;
extern_cmd_options =
execute_get_external_cmd_opts_from_config (command, do_execute_vpath, start_line);
if (extern_cmd_options != NULL)
{
char **argv_cmd_options;
int argv_count;
g_shell_parse_argv (extern_cmd_options, &argv_count, &argv_cmd_options, NULL);
g_free (extern_cmd_options);
do_executev (command, EXECUTE_INTERNAL, argv_cmd_options);
g_strfreev (argv_cmd_options);
}
execute_cleanup_with_vfs_arg (filename_vpath, &localcopy_vpath, &mtime);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -43,6 +43,8 @@ gboolean execute_suspend (const gchar * event_group_name, const gchar * event_na
/* Execute command on a filename that can be on VFS */
void execute_with_vfs_arg (const char *command, const vfs_path_t * filename_vpath);
void execute_external_editor_or_viewer (const char *command, const vfs_path_t * filename_vpath,
int start_line);
void post_exec (void);
void pre_exec (void);

View File

@ -669,7 +669,7 @@ view_file_at_line (const vfs_path_t * filename_vpath, int plain_view, int intern
viewer = "view";
}
execute_with_vfs_arg (viewer, filename_vpath);
execute_external_editor_or_viewer (viewer, filename_vpath, start_line);
}
return ret;
@ -769,8 +769,6 @@ do_edit_at_line (const vfs_path_t * what_vpath, gboolean internal, int start_lin
if (internal)
edit_file (what_vpath, start_line);
else
#else
(void) start_line;
#endif /* USE_INTERNAL_EDIT */
{
if (editor == NULL)
@ -779,7 +777,7 @@ do_edit_at_line (const vfs_path_t * what_vpath, gboolean internal, int start_lin
if (editor == NULL)
editor = get_default_editor ();
}
execute_with_vfs_arg (editor, what_vpath);
execute_external_editor_or_viewer (editor, what_vpath, start_line);
}
if (mc_global.mc_run_mode == MC_RUN_FULL)

View File

@ -20,9 +20,14 @@ endif
EXTRA_DIST = execute__common.c
TESTS = \
execute__execute_with_vfs_arg
execute__execute_with_vfs_arg \
execute__execute_external_editor_or_viewer
check_PROGRAMS = $(TESTS)
execute__execute_with_vfs_arg_SOURCES = \
execute__execute_with_vfs_arg.c
execute__execute_external_editor_or_viewer_SOURCES = \
execute__execute_external_editor_or_viewer.c

View File

@ -110,14 +110,14 @@ mc_getlocalcopy (const vfs_path_t * pathname_vpath)
}
static void
mc_getlocalcopy__init ()
mc_getlocalcopy__init (void)
{
mc_getlocalcopy__pathname_vpath__captured = NULL;
mc_getlocalcopy__return_value = NULL;
}
static void
mc_getlocalcopy__deinit ()
mc_getlocalcopy__deinit (void)
{
vfs_path_free (mc_getlocalcopy__pathname_vpath__captured);
}
@ -151,7 +151,7 @@ message (int flags, const char *title, const char *text, ...)
}
static void
message__init ()
message__init (void)
{
message_flags__captured = 0;
message_title__captured = NULL;
@ -159,7 +159,7 @@ message__init ()
}
static void
message__deinit ()
message__deinit (void)
{
g_free (message_title__captured);
g_free (message_text__captured);
@ -184,13 +184,13 @@ mc_stat (const vfs_path_t * vpath, struct stat *stat_ignored)
static void
mc_stat__init ()
mc_stat__init (void)
{
mc_stat__vpath__captured = g_ptr_array_new ();
}
static void
mc_stat__deinit ()
mc_stat__deinit (void)
{
g_ptr_array_foreach (mc_stat__vpath__captured, (GFunc) vfs_path_free, NULL);
g_ptr_array_free (mc_stat__vpath__captured, TRUE);
@ -218,14 +218,14 @@ mc_ungetlocalcopy (const vfs_path_t * pathname_vpath, const vfs_path_t * local_v
}
static void
mc_ungetlocalcopy__init ()
mc_ungetlocalcopy__init (void)
{
mc_ungetlocalcopy__pathname_vpath__captured = NULL;
mc_ungetlocalcopy__local_vpath__captured = NULL;
}
static void
mc_ungetlocalcopy__deinit ()
mc_ungetlocalcopy__deinit (void)
{
vfs_path_free (mc_ungetlocalcopy__pathname_vpath__captured);
vfs_path_free (mc_ungetlocalcopy__local_vpath__captured);

View File

@ -0,0 +1,211 @@
/*
src - tests for execute_external_editor_or_viewer() function
Copyright (C) 2013
The Free Software Foundation, Inc.
Written by:
Slava Zanko <slavazanko@gmail.com>, 2013
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/>.
*/
#define TEST_SUITE_NAME "/src"
#include <config.h>
#include <check.h>
#include "lib/global.h"
#include "execute__common.c"
/* --------------------------------------------------------------------------------------------- */
char *execute_get_external_cmd_opts_from_config (const char *command,
const vfs_path_t * filename_vpath, int start_line);
/* @CapturedValue */
static char *execute_external_cmd_opts__command__captured;
/* @CapturedValue */
static vfs_path_t *execute_external_cmd_opts__filename_vpath__captured;
/* @CapturedValue */
static int execute_external_cmd_opts__start_line__captured;
/* @ThenReturnValue */
static char *execute_external_cmd_opts__return_value;
/* @Mock */
char *
execute_get_external_cmd_opts_from_config (const char *command, const vfs_path_t * filename_vpath,
int start_line)
{
execute_external_cmd_opts__command__captured = g_strdup (command);
execute_external_cmd_opts__filename_vpath__captured = vfs_path_clone (filename_vpath);
execute_external_cmd_opts__start_line__captured = start_line;
return execute_external_cmd_opts__return_value;
}
static void
execute_get_external_cmd_opts_from_config__init (void)
{
execute_external_cmd_opts__command__captured = NULL;
execute_external_cmd_opts__filename_vpath__captured = NULL;
execute_external_cmd_opts__start_line__captured = 0;
}
static void
execute_get_external_cmd_opts_from_config__deinit (void)
{
g_free (execute_external_cmd_opts__command__captured);
vfs_path_free (execute_external_cmd_opts__filename_vpath__captured);
}
/* --------------------------------------------------------------------------------------------- */
void do_executev (const char *lc_shell, int flags, char *const argv[]);
/* @CapturedValue */
static char *do_executev__lc_shell__captured;
/* @CapturedValue */
static int do_executev__flags__captured;
/* @CapturedValue */
static GPtrArray *do_executev__argv__captured;
/* @Mock */
void
do_executev (const char *lc_shell, int flags, char *const argv[])
{
do_executev__lc_shell__captured = g_strdup (lc_shell);
do_executev__flags__captured = flags;
for (; argv != NULL && *argv != NULL; argv++)
g_ptr_array_add (do_executev__argv__captured, g_strdup (*argv));
}
static void
do_executev__init (void)
{
do_executev__lc_shell__captured = NULL;
do_executev__argv__captured = g_ptr_array_new ();
do_executev__flags__captured = 0;
}
static void
do_executev__deinit (void)
{
g_free (do_executev__lc_shell__captured);
g_ptr_array_foreach (do_executev__argv__captured, (GFunc) g_free, NULL);
g_ptr_array_free (do_executev__argv__captured, TRUE);
}
/* --------------------------------------------------------------------------------------------- */
/* @Before */
static void
my_setup (void)
{
setup ();
execute_get_external_cmd_opts_from_config__init ();
do_executev__init ();
}
/* --------------------------------------------------------------------------------------------- */
/* @After */
static void
my_teardown (void)
{
do_executev__deinit ();
execute_get_external_cmd_opts_from_config__deinit ();
teardown ();
}
/* --------------------------------------------------------------------------------------------- */
/* @Test */
/* *INDENT-OFF* */
START_TEST (do_open_external_editor_or_viewer)
/* *INDENT-ON* */
{
/* given */
vfs_path_t *filename_vpath;
filename_vpath = vfs_path_from_str ("/path/to/file.txt");
vfs_file_is_local__return_value = TRUE;
execute_external_cmd_opts__return_value =
g_strdup
(" 'param 1 with spaces' \"param 2\" -a -b -cdef /path/to/file.txt +123");
/* when */
execute_external_editor_or_viewer ("editor_or_viewer", filename_vpath, 123);
/* then */
/* check call to execute_get_external_cmd_opts_from_config() */
g_assert_cmpstr (execute_external_cmd_opts__command__captured, ==, "editor_or_viewer");
ck_assert_int_eq (vfs_path_cmp
(execute_external_cmd_opts__filename_vpath__captured, filename_vpath), 0);
ck_assert_int_eq (execute_external_cmd_opts__start_line__captured, 123);
/* check call to do_executev() */
g_assert_cmpstr (do_executev__lc_shell__captured, ==, "editor_or_viewer");
ck_assert_int_eq (do_executev__flags__captured, EXECUTE_INTERNAL);
ck_assert_int_eq (do_executev__argv__captured->len, 7);
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 0), ==, "param 1 with spaces");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 1), ==, "param 2");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 2), ==, "-a");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 3), ==, "-b");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 4), ==, "-cdef");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 5), ==, "/path/to/file.txt");
g_assert_cmpstr (g_ptr_array_index (do_executev__argv__captured, 6), ==, "+123");
vfs_path_free (filename_vpath);
}
/* *INDENT-OFF* */
END_TEST
/* *INDENT-ON* */
/* --------------------------------------------------------------------------------------------- */
int
main (void)
{
int number_failed;
Suite *s = suite_create (TEST_SUITE_NAME);
TCase *tc_core = tcase_create ("Core");
SRunner *sr;
tcase_add_checked_fixture (tc_core, my_setup, my_teardown);
/* Add new tests here: *************** */
tcase_add_test (tc_core, do_open_external_editor_or_viewer);
/* *********************************** */
suite_add_tcase (s, tc_core);
sr = srunner_create (s);
srunner_set_log (sr, "execute__execute_external_editor_or_viewer.log");
srunner_run_all (sr, CK_NORMAL);
number_failed = srunner_ntests_failed (sr);
srunner_free (sr);
return (number_failed == 0) ? 0 : 1;
}
/* --------------------------------------------------------------------------------------------- */