Ticket #4210: PeriodicCommand.patch

File PeriodicCommand.patch, 11.0 KB (added by psprint, 3 years ago)
  • lib/keybind.c

    From 966909bac29c6092c8944e5f50b344dd9de210cb Mon Sep 17 00:00:00 2001
    From: Sebastian Gniazdowski <sgniazdowski@gmail.com>
    Date: Fri, 19 Feb 2021 12:05:41 -0600
    Subject: Feature: support for periodic shell command run in background.
    
    ---
     lib/keybind.c                                 |   1 +
     lib/keybind.h                                 |   1 +
     src/editor/Makefile.am                        |   1 +
     src/editor/editwidget.c                       |   3 +
     src/editor/periodic_command.c                 | 167 ++++++++++++++++++
     .../filenot.h => editor/periodic_command.h}   |  28 +--
     src/history.h                                 |   1 +
     src/keybind-defaults.c                        |   1 +
     8 files changed, 191 insertions(+), 12 deletions(-)
     create mode 100644 src/editor/periodic_command.c
     copy src/{filemanager/filenot.h => editor/periodic_command.h} (63%)
    
    diff --git a/lib/keybind.c b/lib/keybind.c
    index abd44d3e2..c8dce295d 100644
    a b static name_keymap_t command_names[] = { 
    137137    ADD_KEYMAP_NAME (MarkToEnd), 
    138138    ADD_KEYMAP_NAME (ToggleNavigation), 
    139139    ADD_KEYMAP_NAME (Sort), 
     140    ADD_KEYMAP_NAME (PeriodicCommand), 
    140141    ADD_KEYMAP_NAME (Options), 
    141142    ADD_KEYMAP_NAME (LearnKeys), 
    142143    ADD_KEYMAP_NAME (Bookmark), 
  • lib/keybind.h

    diff --git a/lib/keybind.h b/lib/keybind.h
    index af019df09..894c4b81e 100644
    a b enum 
    125125    CK_MarkToEnd, 
    126126    CK_ToggleNavigation, 
    127127    CK_Sort, 
     128    CK_PeriodicCommand, 
    128129    CK_Options, 
    129130    CK_LearnKeys, 
    130131    CK_Bookmark, 
  • src/editor/Makefile.am

    diff --git a/src/editor/Makefile.am b/src/editor/Makefile.am
    index 235ed76af..6de160a1a 100644
    a b libedit_la_SOURCES = \ 
    1818        editmenu.c \ 
    1919        editoptions.c \ 
    2020        editwidget.c editwidget.h \ 
     21        periodic_command.c periodic_command.h \ 
    2122        etags.c etags.h \ 
    2223        format.c \ 
    2324        syntax.c 
  • src/editor/editwidget.c

    diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c
    index 18ac00e66..799c17379 100644
    a b edit_dialog_command_execute (WDialog * h, long command) 
    465465    case CK_WindowPrev: 
    466466        group_select_prev_widget (g); 
    467467        break; 
     468    case CK_PeriodicCommand: 
     469        edit_periodic_command_cmd(h); 
     470        break; 
    468471    case CK_Options: 
    469472        edit_options_dialog (h); 
    470473        break; 
  • new file src/editor/periodic_command.c

    diff --git a/src/editor/periodic_command.c b/src/editor/periodic_command.c
    new file mode 100644
    index 000000000..6a843fda5
    - +  
     1/* 
     2   Periodic background shell command support. 
     3 
     4   Copyright (C) 2021 
     5   Free Software Foundation, Inc. 
     6 
     7   Written by: 
     8   Sebastian Gniazdowski <sgniazdowski@gmail.com>, 2021 
     9 
     10   This file is part of the Midnight Commander. 
     11 
     12   The Midnight Commander is free software: you can redistribute it 
     13   and/or modify it under the terms of the GNU General Public License as 
     14   published by the Free Software Foundation, either version 3 of the License, 
     15   or (at your option) any later version. 
     16 
     17   The Midnight Commander is distributed in the hope that it will be useful, 
     18   but WITHOUT ANY WARRANTY; without even the implied warranty of 
     19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     20   GNU General Public License for more details. 
     21 
     22   You should have received a copy of the GNU General Public License 
     23   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     24 */ 
     25 
     26/** \file periodic_command.c 
     27 *  \brief Periodic background shell command support. 
     28 *  \author Sebastian Gniazdowski 
     29 *  \date 2021 
     30 * 
     31 *  Periodic running of a specified shell command, after either: 
     32 *  - specified interval passes, 
     33 *  - specified # of chars will be inserted. 
     34 * 
     35 *  The command is being run in background. 
     36 */ 
     37 
     38#include <config.h> 
     39 
     40 
     41#include "lib/global.h" 
     42#include "lib/widget.h" 
     43#include "src/history.h" 
     44#include "periodic_command.h" 
     45 
     46/*** global variables ****************************************************************************/ 
     47 
     48periodic_config_t periodic_config = {0}; 
     49 
     50/*** file scope macro definitions ****************************************************************/ 
     51 
     52/*** file scope type declarations ****************************************************************/ 
     53 
     54/*** file scope variables ************************************************************************/ 
     55 
     56/*** file scope functions ************************************************************************/ 
     57/* --------------------------------------------------------------------------------------------- */ 
     58 
     59static void 
     60periodic_idle_hook(void *data) 
     61{ 
     62    periodic_config_t * config = (periodic_config_t *) data; 
     63    gboolean should_run = FALSE; 
     64    gint64 cur_time; 
     65 
     66    if (config == NULL || !config->periodic_enable) 
     67        return; 
     68 
     69    if (!hook_present(idle_hook, periodic_idle_hook)) 
     70        add_hook(&idle_hook, periodic_idle_hook, data); 
     71 
     72    /* Events exceeded? */ 
     73    config->cur_event_count ++; 
     74    if (config->event_lim <= config->cur_event_count) 
     75        should_run = TRUE; 
     76 
     77    /* Limit time passed? */ 
     78    cur_time = g_get_real_time(); 
     79    if (cur_time - config->last_run_time >= config->interval) 
     80        should_run = TRUE; 
     81 
     82    /* Should run? */ 
     83    if (should_run) 
     84    { 
     85        gboolean ret; 
     86        GError *error = NULL; 
     87        char *command_esc, *cline; 
     88 
     89        config->last_run_time = cur_time; 
     90        config->cur_event_count = 0; 
     91 
     92        command_esc = g_strescape(config->command_str, NULL); 
     93        cline = g_strdup_printf("sh -c \"%s >/dev/null 2>&1\"", command_esc); 
     94        ret = g_spawn_command_line_async(cline, &error); 
     95 
     96        if (!ret) 
     97        { 
     98            config->periodic_enable = FALSE; 
     99            message(D_ERROR, _("Periodic command warning"), 
     100                _("Error running periodic command: %s. Periodic command stopped."), 
     101                 error != NULL ? error->message : _("<no error message available>")); 
     102            g_error_free(error); 
     103        } 
     104    } 
     105} 
     106 
     107/* --------------------------------------------------------------------------------------------- */ 
     108/*** public functions ****************************************************************************/ 
     109/* --------------------------------------------------------------------------------------------- */ 
     110 
     111void 
     112edit_periodic_command_cmd(WDialog *h) 
     113{ 
     114    char *interval = NULL, *event_lim = NULL; 
     115    const char *pwd_dirs[3] = {N_("&Run where .git is located"), 
     116                                N_("&Run where TAGS file is placed"), 
     117                                N_("&Run in mcedit start dir")}; 
     118    gboolean was_enabled; 
     119 
     120    quick_widget_t quick_widgets[] = { 
     121        /* *INDENT-OFF* */ 
     122        QUICK_LABELED_INPUT (_("Command"), input_label_above, INPUT_LAST_TEXT, 
     123                    MC_HISTORY_PERIODIC_COMMAND, &periodic_config.command_str, 
     124                     NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS), 
     125        QUICK_LABELED_INPUT (_("Interval [sec]"), input_label_above, INPUT_LAST_TEXT, 
     126                     "periodic-interval", &interval, 
     127                     NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS), 
     128        QUICK_LABELED_INPUT (_("Change limit trigger [number]"), input_label_above, INPUT_LAST_TEXT, 
     129                     "periodic-change-limit", &event_lim, 
     130                     NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS), 
     131        QUICK_SEPARATOR (TRUE), 
     132        QUICK_CHECKBOX (N_("&Enable periodic command"), &periodic_config.periodic_enable, NULL), 
     133        QUICK_SEPARATOR (TRUE), 
     134        QUICK_RADIO (3, pwd_dirs, &periodic_config.pwd_type_idx, NULL), 
     135        QUICK_BUTTONS_OK_CANCEL, 
     136        QUICK_END 
     137        /* *INDENT-ON* */ 
     138    }; 
     139 
     140    quick_dialog_t qdlg = { 
     141        -1, -1, 50, 
     142        N_("Periodic command"), "[Periodic command]", 
     143        quick_widgets, dlg_default_callback, NULL 
     144    }; 
     145    was_enabled = periodic_config.periodic_enable; 
     146 
     147    if (quick_dialog (&qdlg) != B_CANCEL) 
     148    { 
     149        periodic_config.last_run_time = g_get_real_time(); 
     150        periodic_config.cur_event_count = 0; 
     151 
     152        errno = 0; 
     153        periodic_config.interval = strtol(interval, NULL, 10) * 1000000; 
     154        periodic_config.event_lim = strtol(event_lim, NULL, 10); 
     155        if (errno != 0) 
     156        { 
     157            message(D_ERROR, _("Periodic command warning"), 
     158                     _("Provided values are not numeric (%s)"), g_strerror(errno)); 
     159            periodic_config.periodic_enable = FALSE; 
     160        } 
     161        else if (periodic_config.periodic_enable && !hook_present(idle_hook, periodic_idle_hook)) 
     162            add_hook(&idle_hook, periodic_idle_hook, &periodic_config); 
     163    } else 
     164    { 
     165        periodic_config.periodic_enable = was_enabled; 
     166    } 
     167} 
  • .h

    diff --git a/src/filemanager/filenot.h b/src/editor/periodic_command.h
    similarity index 63%
    copy from src/filemanager/filenot.h
    copy to src/editor/periodic_command.h
    index 33991e839..1cfbb4f9c 100644
    old new  
    1 /** \file  file.h 
    2  *  \brief Header: File and directory operation routines 
    3  */ 
    4  
    5 #ifndef MC__FILENOT_H 
    6 #define MC__FILENOT_H 
    7  
    8 #include "lib/global.h" 
     1#ifndef MC__PERIODIC_COMMAND_H 
     2#define MC__PERIODIC_COMMAND_H 
    93 
    104/*** typedefs(not structures) and defined constants **********************************************/ 
    115 
     
    137 
    148/*** structures declarations (and typedefs of structures)*****************************************/ 
    159 
     10typedef struct 
     11{ 
     12    gboolean periodic_enable; 
     13    char *command_str; 
     14    gint64 interval; 
     15    int event_lim; 
     16    int pwd_type_idx; 
     17 
     18    int cur_event_count; 
     19    gint64 last_run_time; 
     20} periodic_config_t; 
     21 
    1622/*** global variables defined in .c file *********************************************************/ 
    1723 
    1824/*** declarations of public functions ************************************************************/ 
    1925 
    20 /* Misc Unix functions */ 
    21 int my_mkdir (const vfs_path_t * vpath, mode_t mode); 
    22 int my_rmdir (const char *path); 
     26void edit_periodic_command_cmd(WDialog *h); 
    2327 
    2428/*** inline functions ****************************************************************************/ 
    2529 
    26 #endif /* MC__FILE_H */ 
     30#endif /* MC__PERIODIC_COMMAND_H */ 
  • src/history.h

    diff --git a/src/history.h b/src/history.h
    index 7a8d73fa2..a1c1b6248 100644
    a b  
    3131 
    3232#define MC_HISTORY_ESC_TIMEOUT        "mc.esc.timeout" 
    3333 
     34#define MC_HISTORY_PERIODIC_COMMAND   "mc.periodic.cmd" 
    3435#define MC_HISTORY_VIEW_GOTO          "mc.view.goto" 
    3536#define MC_HISTORY_VIEW_GOTO_LINE     "mc.view.goto-line" 
    3637#define MC_HISTORY_VIEW_GOTO_ADDR     "mc.view.goto-addr" 
  • src/keybind-defaults.c

    diff --git a/src/keybind-defaults.c b/src/keybind-defaults.c
    index 7b87c2f5a..bcb6b32e1 100644
    a b static const global_keymap_ini_t default_editor_keymap[] = { 
    469469    {"FilePrev", "alt-minus"}, 
    470470    {"FileNext", "alt-plus"}, 
    471471    {"Sort", "alt-t"}, 
     472    {"PeriodicCommand", "alt-i"}, 
    472473    {"Mail", "alt-m"}, 
    473474    {"ExternalCommand", "alt-u"}, 
    474475#ifdef HAVE_ASPELL