From 278178093e2120703ef7bdb17abb7eaa63e47877 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Fri, 11 Jan 2013 00:00:00 +0300 Subject: [PATCH] Add support of reading parameters for external editor/viewer from main config. for example, the config file may contain strings: [External editor or viewer parameters] vim = %filename +%lineno mcedit = %filename:%lineno And these external editors will open a file at the previously saved position. Signed-off-by: Slava Zanko --- lib/mcconfig.h | 1 + src/execute.c | 48 ++++- tests/src/Makefile.am | 10 +- ...te__execute_get_external_cmd_opts_from_config.c | 216 +++++++++++++++++++++ 4 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 tests/src/execute__execute_get_external_cmd_opts_from_config.c diff --git a/lib/mcconfig.h b/lib/mcconfig.h index bc4588471..5cb2ddf86 100644 --- a/lib/mcconfig.h +++ b/lib/mcconfig.h @@ -9,6 +9,7 @@ #define CONFIG_PANELS_SECTION "Panels" #define CONFIG_LAYOUT_SECTION "Layout" #define CONFIG_MISC_SECTION "Misc" +#define CONFIG_EXT_EDITOR_VIEWER_SECTION "External editor or viewer parameters" /*** enums ***************************************************************************************/ diff --git a/src/execute.c b/src/execute.c index 0d13222f1..6dff4565a 100644 --- a/src/execute.c +++ b/src/execute.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -38,6 +39,7 @@ #include "lib/vfs/vfs.h" #include "lib/mcconfig.h" #include "lib/util.h" +#include "lib/strutil.h" /* str_replace_all_substrings() */ #include "lib/widget.h" #include "filemanager/midnight.h" @@ -220,6 +222,33 @@ execute_cleanup_with_vfs_arg (const vfs_path_t * filename_vpath, vfs_path_t ** l } /* --------------------------------------------------------------------------------------------- */ + +static char * +execute_get_opts_from_cfg (const char *command, const char *default_str) +{ + char *str_from_config; + + str_from_config = + mc_config_get_string_raw (mc_main_config, CONFIG_EXT_EDITOR_VIEWER_SECTION, command, NULL); + + if (str_from_config == NULL) + { + mc_config_t *cfg; + + cfg = mc_config_init (global_profile_name, TRUE); + if (cfg == NULL) + return g_strdup (default_str); + + str_from_config = + mc_config_get_string_raw (cfg, CONFIG_EXT_EDITOR_VIEWER_SECTION, command, default_str); + + mc_config_deinit (cfg); + } + + return str_from_config; +} + +/* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -227,13 +256,26 @@ 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; + char *str_from_config, *return_str; + char *parameter; if (filename_vpath == NULL) return g_strdup (""); - return g_strdup (vfs_path_get_last_path_str (filename_vpath)); + str_from_config = execute_get_opts_from_cfg (command, "%filename"); + + parameter = g_shell_quote (vfs_path_get_last_path_str (filename_vpath)); + return_str = str_replace_all (str_from_config, "%filename", parameter); + g_free (parameter); + g_free (str_from_config); + str_from_config = return_str; + + parameter = g_strdup_printf ("%d", start_line); + return_str = str_replace_all (str_from_config, "%lineno", parameter); + g_free (parameter); + g_free (str_from_config); + + return return_str; } /* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/Makefile.am b/tests/src/Makefile.am index cff096de5..d42885062 100644 --- a/tests/src/Makefile.am +++ b/tests/src/Makefile.am @@ -21,7 +21,8 @@ EXTRA_DIST = execute__common.c TESTS = \ execute__execute_with_vfs_arg \ - execute__execute_external_editor_or_viewer + execute__execute_external_editor_or_viewer \ + execute__execute_get_external_cmd_opts_from_config check_PROGRAMS = $(TESTS) @@ -30,4 +31,9 @@ execute__execute_with_vfs_arg_SOURCES = \ execute__execute_external_editor_or_viewer_SOURCES = \ - execute__execute_external_editor_or_viewer.c \ No newline at end of file + execute__execute_external_editor_or_viewer.c + + +execute__execute_get_external_cmd_opts_from_config_SOURCES = \ + execute__execute_get_external_cmd_opts_from_config.c + diff --git a/tests/src/execute__execute_get_external_cmd_opts_from_config.c b/tests/src/execute__execute_get_external_cmd_opts_from_config.c new file mode 100644 index 000000000..8bdf3883b --- /dev/null +++ b/tests/src/execute__execute_get_external_cmd_opts_from_config.c @@ -0,0 +1,216 @@ +/* + src - tests for execute_external_editor_or_viewer() function + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 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 . + */ + +#define TEST_SUITE_NAME "/src" + +#include + +#include + +#include "lib/global.h" +#include "lib/mcconfig.h" +#include "lib/strutil.h" +#include "lib/vfs/path.h" +#include "src/vfs/local/local.c" + +char *execute_get_external_cmd_opts_from_config (const char *command, + const vfs_path_t * filename_vpath, int start_line); + +/* --------------------------------------------------------------------------------------------- */ + +/* @CapturedValue */ +static GPtrArray *mc_config_get_string__group__captured; +/* @CapturedValue */ +static GPtrArray *mc_config_get_string__param__captured; +/* @CapturedValue */ +static GPtrArray *mc_config_get_string__default_value__captured; +/* @ThenReturnValue */ +static GPtrArray *mc_config_get_string__return_value; + +/* @Mock */ +gchar * +mc_config_get_string_raw (const mc_config_t * config_ignored, const gchar * group, + const gchar * param, const gchar * default_value) +{ + char *return_value; + (void) config_ignored; + + g_ptr_array_add (mc_config_get_string__group__captured, g_strdup (group)); + g_ptr_array_add (mc_config_get_string__param__captured, g_strdup (param)); + g_ptr_array_add (mc_config_get_string__default_value__captured, g_strdup (default_value)); + + return_value = g_ptr_array_index (mc_config_get_string__return_value, 0); + g_ptr_array_remove_index (mc_config_get_string__return_value, 0); + return return_value; +} + +static void +mc_config_get_string__init (void) +{ + mc_config_get_string__group__captured = g_ptr_array_new (); + mc_config_get_string__param__captured = g_ptr_array_new (); + mc_config_get_string__default_value__captured = g_ptr_array_new (); + + mc_config_get_string__return_value = g_ptr_array_new (); +} + +static void +mc_config_get_string__deinit (void) +{ + g_ptr_array_foreach (mc_config_get_string__group__captured, (GFunc) g_free, NULL); + g_ptr_array_free (mc_config_get_string__group__captured, TRUE); + + g_ptr_array_foreach (mc_config_get_string__param__captured, (GFunc) g_free, NULL); + g_ptr_array_free (mc_config_get_string__param__captured, TRUE); + + g_ptr_array_foreach (mc_config_get_string__default_value__captured, (GFunc) g_free, NULL); + g_ptr_array_free (mc_config_get_string__default_value__captured, TRUE); + + g_ptr_array_foreach (mc_config_get_string__return_value, (GFunc) g_free, NULL); + g_ptr_array_free (mc_config_get_string__return_value, TRUE); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + vfs_init (); + init_localfs (); + vfs_setup_work_dir (); + + mc_config_get_string__init (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + mc_config_get_string__deinit (); + + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("check_subtitute_ds") */ +/* *INDENT-OFF* */ +static const struct check_subtitute_ds +{ + const char *config_opts_string; + const char *app_name; + const char *file_name; + int start_line; + const char *expected_result; +} check_subtitute_ds[] = +{ + { + "-a -b -c %filename \\%filename %filename:%lineno \\%lineno +%lineno", + "some-editor", + "/path/to/file", + 1234, + "-a -b -c '/path/to/file' %filename '/path/to/file':1234 %lineno +1234", + }, + { + "%filename:\\\\\\\\\\\\%lineno", + "some-editor", + "/path/to/'f i\" l e \t\t\n", + 1234, + "'/path/to/'\\''f i\" l e \t\t\n':\\\\\\\\\\\\1234", + }, +}; +/* *INDENT-ON* */ + +/* @Test(dataSource = "check_subtitute_ds") */ +/* *INDENT-OFF* */ +START_TEST (check_if_filename_and_lineno_will_be_subtituted) +/* *INDENT-ON* */ +{ + /* given */ + const struct check_subtitute_ds *data = &check_subtitute_ds[_i]; + char *actual_result; + vfs_path_t *filename_vpath; + + g_ptr_array_add (mc_config_get_string__return_value, g_strdup (data->config_opts_string)); + filename_vpath = vfs_path_from_str (data->file_name); + + /* when */ + actual_result = + execute_get_external_cmd_opts_from_config (data->app_name, filename_vpath, + data->start_line); + + /* then */ + + /* check returned value */ + g_assert_cmpstr (actual_result, ==, data->expected_result); + + /* check calls to mc_config_get_string() function */ + g_assert_cmpstr (g_ptr_array_index (mc_config_get_string__group__captured, 0), ==, + CONFIG_EXT_EDITOR_VIEWER_SECTION); + g_assert_cmpstr (g_ptr_array_index (mc_config_get_string__param__captured, 0), ==, + data->app_name); + g_assert_cmpstr (g_ptr_array_index (mc_config_get_string__default_value__captured, 0), ==, + NULL); + + 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, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_loop_test (tc_core, check_if_filename_and_lineno_will_be_subtituted, 0, + sizeof (check_subtitute_ds) / sizeof (check_subtitute_ds[0])); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "execute__execute_get_external_cmd_opts_from_config.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ -- 2.11.4.GIT