diff --git a/lib/fileloc.h b/lib/fileloc.h
index 12133aaef..6f80db82b 100644
--- a/lib/fileloc.h
+++ b/lib/fileloc.h
@@ -66,6 +66,7 @@
 #define EDIT_DIR                "mcedit"
 
 /* file names */
+#define MC_EXTMACRO_FILE        EDIT_DIR PATH_SEP_STR "macros.d" PATH_SEP_STR "macro"
 #define EDIT_SYNTAX_FILE        EDIT_DIR PATH_SEP_STR "Syntax"
 #define EDIT_CLIP_FILE          EDIT_DIR PATH_SEP_STR "mcedit.clip"
 #define EDIT_BLOCK_FILE         EDIT_DIR PATH_SEP_STR "mcedit.block"
diff --git a/lib/keybind.c b/lib/keybind.c
index 5b7c6a5b5..a4f409395 100644
--- a/lib/keybind.c
+++ b/lib/keybind.c
@@ -187,7 +187,6 @@ static name_keymap_t command_names[] = {
     {"EditSelectionHistory", CK_Selection_History},
     {"EditShell", CK_Shell},
     {"EditInsertLiteral", CK_Insert_Literal},
-    {"EditExecuteMacro", CK_Execute_Macro},
     {"EditBeginOrEndMacro", CK_Begin_End_Macro},
     {"EditExtMode", CK_Ext_Mode},
     {"EditToggleLineState", CK_Toggle_Line_State},
diff --git a/lib/keybind.h b/lib/keybind.h
index 20bf4244a..7a7f1b80f 100644
--- a/lib/keybind.h
+++ b/lib/keybind.h
@@ -200,7 +200,6 @@
 #define CK_Ext_Mode                      820
 
 #define CK_Insert_Literal                851
-#define CK_Execute_Macro                 852
 #define CK_Begin_End_Macro               853
 #define CK_Begin_End_Repeat              854
 #define CK_Begin_Record_Repeat           855
@@ -501,17 +500,7 @@
 #define CK_DiffContinueSearch           9037
 #define CK_DiffOptions                  9038
 
-/*
-   Process a block through a shell command: CK_Pipe_Block(i) executes shell_cmd[i].
-   shell_cmd[i] must process the file ~/cooledit.block and output ~/cooledit.block
-   which is then inserted into the text in place of the original block. shell_cmd[i] must
-   also produce a file homedir/cooledit.error . If this file is not empty an error will
-   have been assumed to have occured, and the block will not be replaced.
-   TODO: bring up a viewer to display the error message instead of inserting
-   it into the text, which is annoying.
- */
 #define CK_Pipe_Block(i) (10000+(i))
-#define SHELL_COMMANDS_i {"/edit.indent.rc", "/edit.spell.rc", /* and so on */ 0 }
 #define CK_Macro(i)      (20000+(i))
 #define CK_Last_Macro    CK_Macro(0x7FFF)
 
diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h
index 5b49e316c..05019d208 100644
--- a/src/editor/edit-impl.h
+++ b/src/editor/edit-impl.h
@@ -215,6 +215,7 @@ extern gboolean search_create_bookmark;
 
 int edit_drop_hotkey_menu (WEdit * e, int key);
 void edit_menu_cmd (WEdit * e);
+void user_menu (WEdit * edit, const char *menu_file, int selected_entry);
 void edit_init_menu (struct WMenuBar *menubar);
 void menu_save_mode_cmd (void);
 int edit_translate_key (WEdit * edit, long x_key, int *cmd, int *ch);
@@ -289,7 +290,7 @@ int edit_insert_column_of_text_from_file (WEdit * edit, int file);
 long edit_insert_file (WEdit * edit, const char *filename);
 int edit_load_back_cmd (WEdit * edit);
 int edit_load_forward_cmd (WEdit * edit);
-void edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block);
+void edit_block_process_cmd (WEdit * edit, int macro_number);
 void edit_refresh_cmd (WEdit * edit);
 void edit_date_cmd (WEdit * edit);
 void edit_goto_cmd (WEdit * edit);
@@ -316,7 +317,6 @@ void edit_paste_from_X_buf_cmd (WEdit * edit);
 
 void edit_select_codepage_cmd (WEdit * edit);
 void edit_insert_literal_cmd (WEdit * edit);
-void edit_execute_macro_cmd (WEdit * edit);
 gboolean edit_execute_macro (WEdit * edit, int hotkey);
 void edit_begin_end_macro_cmd (WEdit * edit);
 void edit_begin_end_repeat_cmd (WEdit * edit);
diff --git a/src/editor/edit.c b/src/editor/edit.c
index 84b1e3813..90dfa63cb 100644
--- a/src/editor/edit.c
+++ b/src/editor/edit.c
@@ -132,8 +132,6 @@ static const struct edit_filters
 
 static long last_bracket = -1;
 
-static const char *const shell_cmd[] = SHELL_COMMANDS_i;
-
 /*** file scope functions ************************************************************************/
 /* --------------------------------------------------------------------------------------------- */
 
@@ -167,7 +165,6 @@ static const char *const shell_cmd[] = SHELL_COMMANDS_i;
 
 /* --------------------------------------------------------------------------------------------- */
 
-static void user_menu (WEdit * edit);
 static int left_of_four_spaces (WEdit * edit);
 
 /* --------------------------------------------------------------------------------------------- */
@@ -1661,10 +1658,13 @@ edit_goto_matching_bracket (WEdit * edit)
 }
 
 /* --------------------------------------------------------------------------------------------- */
+/*** public functions ****************************************************************************/
+/* --------------------------------------------------------------------------------------------- */
+
 /** User edit menu, like user menu (F2) but only in editor. */
 
-static void
-user_menu (WEdit * edit)
+void
+user_menu (WEdit * edit, const char *menu_file, int selected_entry)
 {
     char *block_file;
     int nomark;
@@ -1678,7 +1678,9 @@ user_menu (WEdit * edit)
         edit_save_block (edit, block_file, start_mark, end_mark);
 
     /* run shell scripts from menu */
-    if (user_menu_cmd (edit) && (mc_stat (block_file, &status) == 0) && (status.st_size != 0))
+    if (user_menu_cmd (edit, menu_file, selected_entry)
+        && (mc_stat (block_file, &status) == 0)
+        && (status.st_size != 0))
     {
         int rc = 0;
         FILE *fd;
@@ -1706,8 +1708,6 @@ user_menu (WEdit * edit)
     g_free (block_file);
 }
 
-/* --------------------------------------------------------------------------------------------- */
-/*** public functions ****************************************************************************/
 /* --------------------------------------------------------------------------------------------- */
 
 int
@@ -4102,7 +4102,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
         edit_goto_matching_bracket (edit);
         break;
     case CK_User_Menu:
-        user_menu (edit);
+        user_menu (edit, NULL, -1);
         break;
     case CK_Sort:
         edit_sort_cmd (edit);
@@ -4122,9 +4122,6 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
     case CK_Insert_Literal:
         edit_insert_literal_cmd (edit);
         break;
-    case CK_Execute_Macro:
-        edit_execute_macro_cmd (edit);
-        break;
     case CK_Begin_End_Macro:
         edit_begin_end_macro_cmd (edit);
         break;
@@ -4139,8 +4136,8 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
     }
 
     /* CK_Pipe_Block */
-    if ((command / 10000) == 1)  /* a shell command */
-        edit_block_process_cmd (edit, shell_cmd[command - 10000], 1);
+    if ((command / CK_Pipe_Block (0)) == 1)
+        edit_block_process_cmd (edit, command - CK_Pipe_Block (0));
 
     /* keys which must set the col position, and the search vars */
     switch (command)
diff --git a/src/editor/editcmd.c b/src/editor/editcmd.c
index e763b4b40..728683cd8 100644
--- a/src/editor/editcmd.c
+++ b/src/editor/editcmd.c
@@ -1446,7 +1446,7 @@ edit_delete_macro (WEdit * edit, int hotkey)
         edit_macro_sort_by_hotkey ();
     }
 
-    macros_fname = g_build_filename (mc_config_get_path (), MC_MACRO_FILE, NULL);
+    macros_fname = g_build_filename (mc_config_get_data_path (), MC_MACRO_FILE, (char *) NULL);
     macros_config = mc_config_init (macros_fname);
     g_free (macros_fname);
 
@@ -1540,7 +1540,7 @@ edit_store_macro_cmd (WEdit * edit)
 
     edit_delete_macro (edit, hotkey);
 
-    macros_fname = g_build_filename (mc_config_get_path (), MC_MACRO_FILE, NULL);
+    macros_fname = g_build_filename (mc_config_get_data_path (), MC_MACRO_FILE, (char *) NULL);
     macros_config = mc_config_init (macros_fname);
     g_free (macros_fname);
 
@@ -1643,7 +1643,7 @@ edit_load_macro_cmd (WEdit * edit)
 
     (void) edit;
 
-    macros_fname = g_build_filename (mc_config_get_path (), MC_MACRO_FILE, NULL);
+    macros_fname = g_build_filename (mc_config_get_data_path (), MC_MACRO_FILE, (char *) NULL);
     macros_config = mc_config_init (macros_fname);
     g_free (macros_fname);
 
@@ -1673,19 +1673,19 @@ edit_load_macro_cmd (WEdit * edit)
             if (macro_pair != NULL)
             {
                 macro_action_t m_act;
-                if (macro_pair [0] == NULL || macro_pair [0][0] == '\0')
+                if (macro_pair[0] == NULL || macro_pair[0][0] == '\0')
                     m_act.action = 0;
                 else
                 {
-                    m_act.action = keybind_lookup_action (macro_pair [0]);
+                    m_act.action = keybind_lookup_action (macro_pair[0]);
                     g_free (macro_pair[0]);
                     macro_pair[0] = NULL;
                 }
-                if (macro_pair [1] == NULL || macro_pair [1][0] == '\0')
+                if (macro_pair[1] == NULL || macro_pair[1][0] == '\0')
                     m_act.ch = -1;
                 else
                 {
-                    m_act.ch = strtol (macro_pair [1], NULL, 0);
+                    m_act.ch = strtol (macro_pair[1], NULL, 0);
                     g_free (macro_pair[1]);
                     macro_pair[1] = NULL;
                 }
@@ -2852,129 +2852,17 @@ edit_ext_cmd (WEdit * edit)
    command, that just produces some output which is to be inserted */
 
 void
-edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
+edit_block_process_cmd (WEdit * edit, int macro_number)
 {
-    long start_mark, end_mark;
-    char buf[BUFSIZ];
-    FILE *script_home = NULL;
-    FILE *block_file = NULL;
-    gchar *o, *h, *b, *tmp;
-    char *quoted_name = NULL;
+    char *fname;
+    char *macros_fname = NULL;
 
-    o = g_strconcat (mc_sysconfig_dir, shell_cmd, (char *) NULL);        /* original source script */
-    h = g_strconcat (mc_config_get_data_path (), PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL);     /* home script */
-    b = concat_dir_and_file (mc_config_get_cache_path (), EDIT_BLOCK_FILE);     /* block file */
-
-    script_home = fopen (h, "r");
-    if (script_home == NULL)
-    {
-        FILE *script_src = NULL;
-
-        script_home = fopen (h, "w");
-        if (script_home == NULL)
-        {
-            tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
-            edit_error_dialog ("", get_sys_error (tmp));
-            g_free (tmp);
-            goto edit_block_process_cmd__EXIT;
-        }
-
-        script_src = fopen (o, "r");
-        if (script_src == NULL)
-        {
-            o = g_strconcat (mc_share_data_dir, shell_cmd, (char *) NULL);
-            script_src = fopen (o, "r");
-            if (script_src == NULL)
-            {
-                fclose (script_home);
-                unlink (h);
-                tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
-                edit_error_dialog ("", get_sys_error (tmp));
-                g_free (tmp);
-                goto edit_block_process_cmd__EXIT;
-            }
-        }
-        while (fgets (buf, sizeof (buf), script_src))
-            fputs (buf, script_home);
-        fclose (script_src);
-
-        if (fclose (script_home))
-        {
-            tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
-            edit_error_dialog ("", get_sys_error (tmp));
-            g_free (tmp);
-            goto edit_block_process_cmd__EXIT;
-        }
-        chmod (h, 0700);
-        tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
-        edit_error_dialog ("", get_sys_error (tmp));
-        g_free (tmp);
-    }
-
-    open_error_pipe ();
-
-    if (block)
-    {                           /* for marked block run indent formatter */
-        if (eval_marks (edit, &start_mark, &end_mark))
-        {
-            edit_error_dialog (_("Process block"), _("You must first highlight a block of text"));
-            goto edit_block_process_cmd__EXIT;
-        }
-        edit_save_block (edit, b, start_mark, end_mark);
-        quoted_name = name_quote (edit->filename, 0);
-        /*
-         * Run script.
-         * Initial space is to avoid polluting bash history.
-         * Arguments:
-         *   $1 - name of the edited file (to check its extension etc).
-         *   $2 - file containing the current block.
-         *   $3 - file where error messages should be put
-         *        (for compatibility with old scripts).
-         */
-        tmp =
-            g_strconcat (" ", mc_config_get_cache_path (), PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
-                         quoted_name, " ", mc_config_get_cache_path (),
-                         PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
-    }
-    else
-    {
-        /*
-         * No block selected, just execute the command for the file.
-         * Arguments:
-         *   $1 - name of the edited file.
-         */
-        tmp = g_strconcat (" ", mc_config_get_cache_path (), PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
-                           quoted_name, (char *) NULL);
-    }
-
-    if (system (tmp) == -1)
-    {
-        edit_error_dialog (_("Process block"), _("Error calling program"));
-    }
-    else
-    {
-
-        g_free (quoted_name);
-        close_error_pipe (D_NORMAL, NULL);
-
-        edit_refresh_cmd (edit);
-        edit->force |= REDRAW_COMPLETELY;
-
-        /* insert result block */
-        if (block && !edit_block_delete_cmd (edit))
-        {
-            edit_insert_file (edit, b);
-            block_file = fopen (b, "w");
-            if (block_file != NULL)
-                fclose (block_file);
-        }
-    }
-    g_free (tmp);
-
-  edit_block_process_cmd__EXIT:
-    g_free (b);
-    g_free (h);
-    g_free (o);
+    fname = g_strdup_printf ("%s.%i.sh", MC_EXTMACRO_FILE, macro_number);
+    macros_fname = g_build_filename (mc_config_get_data_path (), fname, (char *) NULL);
+    user_menu (edit, macros_fname, 0);
+    g_free (fname);
+    g_free (macros_fname);
+    edit->force |= REDRAW_COMPLETELY;
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -3137,20 +3025,6 @@ edit_insert_literal_cmd (WEdit * edit)
 
 /* --------------------------------------------------------------------------------------------- */
 
-void
-edit_execute_macro_cmd (WEdit * edit)
-{
-    int command =
-        CK_Macro (editcmd_dialog_raw_key_query (_("Execute macro"), _("Press macro hotkey:"),
-                                                1));
-    if (command == CK_Macro (0))
-        command = CK_Insert_Char;
-
-    edit_execute_key_command (edit, command, -1);
-}
-
-/* --------------------------------------------------------------------------------------------- */
-
 void
 edit_begin_end_macro_cmd (WEdit * edit)
 {
diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c
index a5d504e7f..42d58e910 100644
--- a/src/filemanager/cmd.c
+++ b/src/filemanager/cmd.c
@@ -1340,7 +1340,7 @@ help_cmd (void)
 void
 user_file_menu_cmd (void)
 {
-    (void) user_menu_cmd (NULL);
+    (void) user_menu_cmd (NULL, NULL, -1);
 }
 
 /* --------------------------------------------------------------------------------------------- */
diff --git a/src/filemanager/usermenu.c b/src/filemanager/usermenu.c
index 67b89f444..36c404da6 100644
--- a/src/filemanager/usermenu.c
+++ b/src/filemanager/usermenu.c
@@ -404,7 +404,7 @@ test_line (WEdit * edit_widget, char *p, int *result)
 /** FIXME: recode this routine on version 3.0, it could be cleaner */
 
 static void
-execute_menu_command (WEdit * edit_widget, const char *commands)
+execute_menu_command (WEdit * edit_widget, const char *commands, gboolean dont_show_prompt)
 {
     FILE *cmd_file;
     int cmd_file_fd;
@@ -534,7 +534,15 @@ execute_menu_command (WEdit * edit_widget, const char *commands)
         /* execute the command indirectly to allow execution even
          * on no-exec filesystems. */
         char *cmd = g_strconcat ("/bin/sh ", file_name, (char *) NULL);
-        shell_execute (cmd, EXECUTE_HIDE);
+        if (dont_show_prompt)
+        {
+            if (system (cmd) == -1)
+                message (D_ERROR, MSG_ERROR, "%s", _("Error calling program"));
+        }
+        else
+        {
+            shell_execute (cmd, EXECUTE_HIDE);
+        }
         g_free (cmd);
     }
     unlink (file_name);
@@ -851,7 +859,7 @@ expand_format (struct WEdit *edit_widget, char c, gboolean do_quote)
  */
 
 gboolean
-user_menu_cmd (struct WEdit *edit_widget)
+user_menu_cmd (struct WEdit *edit_widget, const char *menu_file, int selected_entry)
 {
     char *p;
     char *data, **entries;
@@ -866,10 +874,20 @@ user_menu_cmd (struct WEdit *edit_widget)
         message (D_ERROR, MSG_ERROR, "%s", _("Cannot execute commands on non-local filesystems"));
         return FALSE;
     }
-
-    menu = g_strdup (edit_widget ? EDIT_LOCAL_MENU : MC_LOCAL_MENU);
+    if (menu_file != NULL)
+        menu = g_strdup (menu_file);
+    else
+        menu = g_strdup (edit_widget ? EDIT_LOCAL_MENU : MC_LOCAL_MENU);
     if (!exist_file (menu) || !menu_file_own (menu))
     {
+        if (menu_file != NULL)
+        {
+            message (D_ERROR, MSG_ERROR, _("Cannot open file%s\n%s"), menu, unix_error_string (errno));
+            g_free (menu);
+            menu = NULL;
+            return FALSE;
+        }
+
         g_free (menu);
         if (edit_widget)
             menu = concat_dir_and_file (mc_config_get_data_path (), EDIT_HOME_MENU);
@@ -1006,25 +1024,30 @@ user_menu_cmd (struct WEdit *edit_widget)
     }
     else
     {
-        max_cols = min (max (max_cols, col), MAX_ENTRY_LEN);
-
-        /* Create listbox */
-        listbox = create_listbox_window (menu_lines, max_cols + 2, _("User menu"),
-                                         "[Menu File Edit]");
-        /* insert all the items found */
-        for (i = 0; i < menu_lines; i++)
+        if (selected_entry >= 0)
+            selected = selected_entry;
+        else
         {
-            p = entries[i];
-            LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
-                                 extract_line (p, p + MAX_ENTRY_LEN), p);
-        }
-        /* Select the default entry */
-        listbox_select_entry (listbox->list, selected);
+            max_cols = min (max (max_cols, col), MAX_ENTRY_LEN);
 
-        selected = run_listbox (listbox);
+            /* Create listbox */
+            listbox = create_listbox_window (menu_lines, max_cols + 2, _("User menu"),
+                                             "[Menu File Edit]");
+            /* insert all the items found */
+            for (i = 0; i < menu_lines; i++)
+            {
+                p = entries[i];
+                LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
+                                     extract_line (p, p + MAX_ENTRY_LEN), p);
+            }
+            /* Select the default entry */
+            listbox_select_entry (listbox->list, selected);
+
+            selected = run_listbox (listbox);
+        }
         if (selected >= 0)
         {
-            execute_menu_command (edit_widget, entries[selected]);
+            execute_menu_command (edit_widget, entries[selected], (selected_entry >= 0));
             res = TRUE;
         }
 
diff --git a/src/filemanager/usermenu.h b/src/filemanager/usermenu.h
index 9cbefccb2..9596d788a 100644
--- a/src/filemanager/usermenu.h
+++ b/src/filemanager/usermenu.h
@@ -19,7 +19,7 @@ struct WEdit;
 
 /*** declarations of public functions ************************************************************/
 
-gboolean user_menu_cmd (struct WEdit *edit_widget);
+gboolean user_menu_cmd (struct WEdit *edit_widget, const char * menu_file, int selected_entry);
 char *expand_format (struct WEdit *edit_widget, char c, gboolean do_quote);
 int check_format_view (const char *);
 int check_format_var (const char *, char **);
diff --git a/src/keybind-defaults.c b/src/keybind-defaults.c
index 381e44e5b..2b2626261 100644
--- a/src/keybind-defaults.c
+++ b/src/keybind-defaults.c
@@ -293,7 +293,6 @@ const global_keymap_t default_editor_keymap[] = {
     {XCTRL ('r'), CK_Begin_End_Macro, "C-r"},
     {XCTRL ('r'), CK_Begin_Record_Macro, "C-r"},
     {XCTRL ('r'), CK_End_Record_Macro, "C-r"},
-    {XCTRL ('a'), CK_Execute_Macro, "C-a"},
     {XCTRL ('f'), CK_Save_Block, "C-f"},
     /* Spell check */
     {XCTRL ('p'), CK_Pipe_Block (1), "C-p"},
@@ -361,7 +360,6 @@ const global_keymap_t default_editor_keymap[] = {
 /* emacs keyboard layout emulation */
 const global_keymap_t default_editor_x_keymap[] = {
     {'k', CK_New, "k"},
-    {'e', CK_Execute_Macro, "e"},
     {0, CK_Ignore_Key, ""}
 };
 #endif /* USE_INTERNAL_EDIT */