Merge branch '323_editor_macros'

* 323_editor_macros:
  (mc_config_init): don't drop file name if file is not exist.
  added examples     added rules for misc/macros.d/*. in the process of installation, example scripts will be copied into share/mc/examples/macros.d
  added check for instruction "#interactive" in the script. if the external script contain #interactive then do show prompt.
  changed mcedit.1.in
  Fix cursor position after execution of external script.
  Changed engine of external macros execution
  added a new action "Record and Repeat commands", added menu entry (Record/Repeat actions) for this.
  Removed unneeded menu entries.
  Added lookup_key_by_code, now parameter is string.
  Ticket #323 (reimplimented editor macros)
This commit is contained in:
Ilia Maslakov 2011-03-03 20:53:34 +00:00
commit 0cfbe19d96
35 changed files with 858 additions and 527 deletions

View File

@ -529,6 +529,7 @@ contrib/dist/prototype
misc/Makefile
misc/skins/Makefile
misc/macros.d/Makefile
misc/mc.ext
src/Makefile

View File

@ -97,38 +97,116 @@ or
.BR "Escape Tab" )
completes the word under the cursor using the words used earlier in the
file.
.SH MACRO
.PP
To define a macro, press
.B Ctrl\-R
and then type out the keys you want to be executed. Press
.B Ctrl\-R
again when finished. You can then assign the macro to any key you like
by pressing that key. The macro is executed when you press
.B Ctrl\-A
and then the assigned key. The macro is also executed if you press
Meta, Ctrl, or Esc and the assigned key, provided that the key is not
used for any other function. The macro commands are stored in the file
.BR ~/.local/share/mc/mcedit/mcedit.macros .
Do NOT edit this file if you are going to use macros again in the same
editing session, because
.B mcedit
caches macro key defines in memory.
.B mcedit
now overwrites a macro if a macro with the same key already exists,
so you won't have to edit this file. You will also have to restart
other running editors for macros to take effect.
.P
.B F19
will format C, C++, Java or HTML code when it is highlighted. An executable
file called
.B ~/.local/share/mc/mcedit/edit.indent.rc
will be created for you from the default template. Feel free to edit it
if you need.
again when finished. The macro can be assigned to any key by pressing that key.
The macro is executed when you press the assigned key.
.PP
.B C\-p
will run ispell on a block of text in a similar way. The script file
will be called
.BR ~/.local/share/mc/mcedit/edit.spell.rc .
The macro commands are stored in section
.B [editor]
it the file
.BR ~/.local/share/mc/mc.macros .
.PP
External scripts (filters) can be assigned into the any hotkey by edit
.B mc.macros
like following:
.PP
.nf
[editor]
ctrl\-W=EditPipeBlock:25;
.fi
.PP
This means that ctrl\-W hotkey initiates the
.I EditPipeBlock(25)
action, next the editor handler translates this into execution of
.B ~/.local/share/mc/mcedit/macros.d/macro.25.sh
shell script.
.PP
External scripts stored into
.B ~/.local/share/mc/mcedit/macros.d/
directory and must named
.B macro.XXXX.sh
where
.B XXXX
is the number from 0 to 9999.
See
.B Menu File Edit
for more detail about format of the script.
.PP
Following macro definition and directives can be used:
.TP
.I #interactive
If this directive is set, then script starts in subshell.
.TP
.I %c
The cursor column position number.
.TP
.I %i
The indent of blank space, equal the cursor column.
.TP
.I %y
The syntax type of current file.
.TP
.I %b
The block file name.
.TP
.I %f
The current file name.
.TP
.I %n
Only the current file name without extension.
.TP
.I %x
The extension of current file name.
.TP
.I %d
The current directory name.
.TP
.I %F
The current file in the unselected panel.
.TP
.I %D
The directory name of the unselected panel.
.TP
.I %t
The currently tagged files.
.TP
.I %T
The tagged files in the unselected panel.
.TP
.I %u
and
.I %U
Similar to the
.I %t
and
.I %T
macros, but in addition the files are untagged. You can use this macro
only once per menu file entry or extension file entry, because next time
there will be no tagged files.
.TP
.I %s
and
.I %S
The selected files: The tagged files if there are any. Otherwise the
current file.
.PP
Feel free to edit this files, if you need.
Here is a sample external script:
.PP
.nf
l comment selection
TMPFILE=`mktemp ${MC_TMPDIR:\-/tmp}/up.XXXXXX` || exit 1
echo #if 0 > $TMPFILE
cat %b >> $TMPFILE
echo #endif >> $TMPFILE
cat $TMPFILE > %b
rm \-f $TMPFILE
.fi
.PP
If some keys don't work, you can use
.B Learn Keys

View File

@ -29,6 +29,7 @@
#define GLOBAL_KEYMAP_FILE "mc.keymap"
#define CHARSETS_LIST "mc.charsets"
#define MC_LIB_EXT "mc.ext"
#define MC_MACRO_FILE "mc.macros"
#define FISH_PREFIX "fish"
@ -65,9 +66,9 @@
#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_MACRO_FILE EDIT_DIR PATH_SEP_STR "mcedit.macros"
#define EDIT_BLOCK_FILE EDIT_DIR PATH_SEP_STR "mcedit.block"
#define EDIT_TEMP_FILE EDIT_DIR PATH_SEP_STR "mcedit.temp"

View File

@ -43,6 +43,7 @@
/*** file scope variables ************************************************************************/
static name_keymap_t command_names[] = {
{"InsertChar", CK_Insert_Char},
#ifdef USE_INTERNAL_EDIT
{"EditNoCommand", CK_Ignore_Key},
{"EditIgnoreKey", CK_Ignore_Key},
@ -133,6 +134,7 @@ static name_keymap_t command_names[] = {
{"EditUserMenu", CK_User_Menu},
{"EditBeginRecordMacro", CK_Begin_Record_Macro},
{"EditEndRecordMacro", CK_End_Record_Macro},
{"EditBeginEndRepeat", CK_Begin_End_Repeat},
{"EditDeleteMacro", CK_Delete_Macro},
{"EditToggleBookmark", CK_Toggle_Bookmark},
{"EditFlushBookmarks", CK_Flush_Bookmarks},
@ -185,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},
@ -199,6 +200,7 @@ static name_keymap_t command_names[] = {
{"EditSaveMode", CK_Edit_Save_Mode},
{"EditChooseSyntax", CK_Choose_Syntax},
{"EditAbout", CK_About},
{"EditPipeBlock", CK_Pipe_Block (0)},
#if 0
{"EditFocusNext", CK_Focus_Next},
@ -617,6 +619,20 @@ keybind_lookup_action (const char *name)
/* --------------------------------------------------------------------------------------------- */
const char *
keybind_lookup_actionname (unsigned long action)
{
size_t i;
for (i = 0; command_names[i].name != NULL; i++)
if (command_names[i].val == action)
return command_names[i].name;
return NULL;
}
/* --------------------------------------------------------------------------------------------- */
const char *
keybind_lookup_keymap_shortcut (const global_keymap_t * keymap, unsigned long action)
{

View File

@ -200,8 +200,10 @@
#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
#define CK_End_Record_Repeat 856
/* help */
#define CK_HelpHelp 1001
@ -498,18 +500,8 @@
#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) (1000+(i))
#define SHELL_COMMANDS_i {"/edit.indent.rc", "/edit.spell.rc", /* and so on */ 0 }
#define CK_Macro(i) (2000+(i))
#define CK_Pipe_Block(i) (10000+(i))
#define CK_Macro(i) (20000+(i))
#define CK_Last_Macro CK_Macro(0x7FFF)
/*** enums ***************************************************************************************/
@ -544,6 +536,7 @@ typedef struct global_keymap_t
void keybind_cmd_bind (GArray * keymap, const char *keybind, unsigned long action);
unsigned long keybind_lookup_action (const char *name);
const char *keybind_lookup_actionname (unsigned long action);
const char *keybind_lookup_keymap_shortcut (const global_keymap_t * keymap, unsigned long action);
unsigned long keybind_lookup_keymap_command (const global_keymap_t * keymap, long key);

View File

@ -112,14 +112,12 @@ mc_config_init (const gchar * ini_path)
g_free (mc_config);
return NULL;
}
if (!ini_path || !exist_file (ini_path))
{
if (ini_path == NULL)
return mc_config;
}
if (!mc_stat (ini_path, &st) && st.st_size)
if (exist_file (ini_path) && mc_stat (ini_path, &st) == 0 && st.st_size != 0)
{
/* file present and not empty */
/* file exists and not empty */
g_key_file_load_from_file (mc_config->handle, ini_path, G_KEY_FILE_KEEP_COMMENTS, NULL);
}

View File

@ -66,7 +66,6 @@ static const struct
{ "hotlist", &xdg_config, MC_HOTLIST_FILE},
{ "mc.keymap", &xdg_config, GLOBAL_KEYMAP_FILE},
/* data */
{ "skins", &xdg_data, MC_SKINS_SUBDIR},
{ "fish", &xdg_data, FISH_PREFIX},
@ -75,7 +74,6 @@ static const struct
{ "bashrc", &xdg_data, "bashrc"},
{ "inputrc", &xdg_data, "inputrc"},
{ "extfs.d", &xdg_data, MC_EXTFS_DIR},
{ "cedit" PATH_SEP_STR "cooledit.macros", &xdg_data, EDIT_MACRO_FILE},
{ "cedit" PATH_SEP_STR "Syntax", &xdg_data, EDIT_SYNTAX_FILE},
{ "cedit" PATH_SEP_STR "menu", &xdg_data, EDIT_HOME_MENU},
{ "cedit" PATH_SEP_STR "edit.indent.rc", &xdg_data, EDIT_DIR PATH_SEP_STR "edit.indent.rc"},

View File

@ -251,6 +251,13 @@ typedef struct SelectList
struct SelectList *next;
} SelectList;
typedef enum KeySortType
{
KEY_NOSORT = 0,
KEY_SORTBYNAME,
KEY_SORTBYCODE
} KeySortType;
#ifdef __QNXNTO__
typedef int (*ph_dv_f) (void *, void *);
typedef int (*ph_ov_f) (void *);
@ -524,11 +531,11 @@ static Display *x11_display;
static Window x11_window;
#endif /* HAVE_TEXTMODE_X11_SUPPORT */
static const size_t key_name_conv_tab_size = sizeof (key_name_conv_tab) /
sizeof (key_name_conv_tab[0]) - 1;
static KeySortType has_been_sorted = KEY_NOSORT;
static const key_code_name_t *key_name_conv_tab_sorted[sizeof (key_name_conv_tab) /
sizeof (key_name_conv_tab[0]) - 1];
static const size_t key_conv_tab_size = G_N_ELEMENTS (key_name_conv_tab) - 1;
static const key_code_name_t *key_conv_tab_sorted[G_N_ELEMENTS (key_name_conv_tab) - 1];
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
@ -1144,7 +1151,7 @@ s_dispose (SelectList * sel)
/* --------------------------------------------------------------------------------------------- */
static int
key_code_name_comparator (const void *p1, const void *p2)
key_code_comparator_by_name (const void *p1, const void *p2)
{
const key_code_name_t *n1 = *(const key_code_name_t **) p1;
const key_code_name_t *n2 = *(const key_code_name_t **) p2;
@ -1154,21 +1161,37 @@ key_code_name_comparator (const void *p1, const void *p2)
/* --------------------------------------------------------------------------------------------- */
static inline void
sort_key_name_conv_tab (void)
static int
key_code_comparator_by_code (const void *p1, const void *p2)
{
static gboolean has_been_sorted = FALSE;
const key_code_name_t *n1 = *(const key_code_name_t **) p1;
const key_code_name_t *n2 = *(const key_code_name_t **) p2;
if (!has_been_sorted)
return n1->code - n2->code;
}
/* --------------------------------------------------------------------------------------------- */
static inline void
sort_key_conv_tab (enum KeySortType type_sort)
{
if (has_been_sorted != type_sort)
{
size_t i;
for (i = 0; i < key_name_conv_tab_size; i++)
key_name_conv_tab_sorted[i] = &key_name_conv_tab[i];
for (i = 0; i < key_conv_tab_size; i++)
key_conv_tab_sorted[i] = &key_name_conv_tab[i];
qsort (key_name_conv_tab_sorted,
key_name_conv_tab_size, sizeof (key_name_conv_tab_sorted[0]),
&key_code_name_comparator);
has_been_sorted = TRUE;
if (type_sort == KEY_SORTBYNAME)
{
qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
&key_code_comparator_by_name);
}
else if (type_sort == KEY_SORTBYCODE)
{
qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
&key_code_comparator_by_code);
}
has_been_sorted = type_sort;
}
}
@ -1189,15 +1212,14 @@ lookup_keyname (const char *name, int *idx)
return (int) name[0];
}
sort_key_name_conv_tab ();
sort_key_conv_tab (KEY_SORTBYNAME);
res = bsearch (&keyp, key_name_conv_tab_sorted,
key_name_conv_tab_size,
sizeof (key_name_conv_tab_sorted[0]), key_code_name_comparator);
res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_name);
if (res != NULL)
{
*idx = (int) (res - (key_code_name_t **) key_name_conv_tab_sorted);
*idx = (int) (res - (key_code_name_t **) key_conv_tab_sorted);
return (*res)->code;
}
}
@ -1206,6 +1228,33 @@ lookup_keyname (const char *name, int *idx)
return 0;
}
/* --------------------------------------------------------------------------------------------- */
static gboolean
lookup_keycode (const long code, int *idx)
{
if (code != 0)
{
const key_code_name_t key = { code, NULL, NULL, NULL };
const key_code_name_t *keyp = &key;
key_code_name_t **res;
sort_key_conv_tab (KEY_SORTBYCODE);
res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_code);
if (res != NULL)
{
*idx = (int) (res - (key_code_name_t **) key_conv_tab_sorted);
return TRUE;
}
}
*idx = -1;
return FALSE;
}
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
@ -1413,12 +1462,12 @@ lookup_key (const char *name, char **label)
if (use_meta != -1)
{
g_string_append (s, key_name_conv_tab_sorted[use_meta]->shortcut);
g_string_append (s, key_conv_tab_sorted[use_meta]->shortcut);
g_string_append_c (s, '-');
}
if (use_ctrl != -1)
{
g_string_append (s, key_name_conv_tab_sorted[use_ctrl]->shortcut);
g_string_append (s, key_conv_tab_sorted[use_ctrl]->shortcut);
g_string_append_c (s, '-');
}
if (use_shift != -1)
@ -1427,21 +1476,21 @@ lookup_key (const char *name, char **label)
g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
else
{
g_string_append (s, key_name_conv_tab_sorted[use_shift]->shortcut);
g_string_append (s, key_conv_tab_sorted[use_shift]->shortcut);
g_string_append_c (s, '-');
g_string_append (s, key_name_conv_tab_sorted[lc_index]->shortcut);
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
}
}
else if (k < 128)
{
if ((k >= 'A') || (lc_index < 0)
|| (key_name_conv_tab_sorted[lc_index]->shortcut == NULL))
|| (key_conv_tab_sorted[lc_index]->shortcut == NULL))
g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) k));
else
g_string_append (s, key_name_conv_tab_sorted[lc_index]->shortcut);
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
}
else if ((lc_index != -1) && (key_name_conv_tab_sorted[lc_index]->shortcut != NULL))
g_string_append (s, key_name_conv_tab_sorted[lc_index]->shortcut);
else if ((lc_index != -1) && (key_conv_tab_sorted[lc_index]->shortcut != NULL))
g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
else
g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) key));
@ -1470,6 +1519,82 @@ lookup_key (const char *name, char **label)
return (long) k;
}
/* --------------------------------------------------------------------------------------------- */
char *
lookup_key_by_code (const int keycode)
{
/* code without modifier */
unsigned int k = keycode & ~KEY_M_MASK;
/* modifier */
unsigned int mod = keycode & KEY_M_MASK;
int use_meta = -1;
int use_ctrl = -1;
int use_shift = -1;
int key_idx = -1;
GString *s;
int idx;
s = g_string_sized_new (8);
if (lookup_keycode (k, &key_idx) || (k > 0 && k < 256))
{
if (mod & KEY_M_ALT)
{
if (lookup_keycode (KEY_M_ALT, &idx))
{
use_meta = idx;
g_string_append (s, key_conv_tab_sorted[use_meta]->name);
g_string_append_c (s, '-');
}
}
if (mod & KEY_M_CTRL)
{
/* non printeble chars like a CTRL-[A..Z] */
if (k < 32)
k += 64;
if (lookup_keycode (KEY_M_CTRL, &idx))
{
use_ctrl = idx;
g_string_append (s, key_conv_tab_sorted[use_ctrl]->name);
g_string_append_c (s, '-');
}
}
if (mod & KEY_M_SHIFT)
{
if (lookup_keycode (KEY_M_ALT, &idx))
{
use_shift = idx;
if (k < 127)
g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
else
{
g_string_append (s, key_conv_tab_sorted[use_shift]->name);
g_string_append_c (s, '-');
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
}
}
}
else if (k < 128)
{
if ((k >= 'A') || (key_idx < 0)
|| (key_conv_tab_sorted[key_idx]->name == NULL))
g_string_append_c (s, (gchar) k);
else
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
}
else if ((key_idx != -1) && (key_conv_tab_sorted[key_idx]->name != NULL))
g_string_append (s, key_conv_tab_sorted[key_idx]->name);
else
g_string_append_c (s, (gchar) keycode);
}
return g_string_free (s, s->len == 0);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Return TRUE on success, FALSE on error.

View File

@ -68,7 +68,7 @@ void init_key_input_fd (void);
void done_key (void);
long lookup_key (const char *name, char **label);
char *lookup_key_by_code (const int keycode);
/* mouse support */
int tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block);
gboolean is_idle (void);

View File

@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in.
SUBDIRS = skins syntax
SUBDIRS = macros.d skins syntax
LIBFILES_OUT = mc.ext
@ -23,7 +23,6 @@ LIBFILES_CONST = \
mc.menu \
mc.menu.sr
CLEANFILES = $(SCRIPTS_OUT)
cfgdir = $(sysconfdir)/@PACKAGE@

11
misc/macros.d/Makefile.am Normal file
View File

@ -0,0 +1,11 @@
macrodir = $(pkgdatadir)/examples/macros.d
macro_DATA = \
macro.0.sh \
macro.1.sh \
macro.3.sh \
macro.4.sh \
macro.5.sh
EXTRA_DIST = \
$(macro_DATA)

6
misc/macros.d/macro.0.sh Normal file
View File

@ -0,0 +1,6 @@
#interactive
m make
TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1
make 2> $TMPFILE
mcedit $TMPFILE
rm $TMPFILE

5
misc/macros.d/macro.1.sh Normal file
View File

@ -0,0 +1,5 @@
u Upper case selection
TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1
cat %b > $TMPFILE
cat $TMPFILE| sed 's/\(.*\)/\U\1/' >%b
rm -f $TMPFILE

5
misc/macros.d/macro.2.sh Normal file
View File

@ -0,0 +1,5 @@
l Lower case selection
TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1
cat %b > $TMPFILE
cat $TMPFILE| sed 's/\(.*\)/\L\1/' >%b
rm -f $TMPFILE

5
misc/macros.d/macro.3.sh Normal file
View File

@ -0,0 +1,5 @@
S Sort selection
TMPFILE=`mktemp ${MC_TMPDIR:-/tmp}/up.XXXXXX` || exit 1
cat %b > $TMPFILE
cat $TMPFILE| sort >%b
rm -f $TMPFILE

2
misc/macros.d/macro.4.sh Normal file
View File

@ -0,0 +1,2 @@
t Indent `C' formatter
indent -gnu -fc1 -i4 -bli0 -nut -bap -l100 %b 1>/dev/null 2> %e

41
misc/macros.d/macro.5.sh Normal file
View File

@ -0,0 +1,41 @@
s snippets
a=`cat %b`
if [ "$a" = "fori" ]; then
echo "for (i = 0; i _; i++)" > %b
fi
if [ "$a" = "ife" ]; then
cat <<EOF > %b
if ( )
{
}
else
{
}
EOF
fi
if [ "$a" = "GPL" ]; then
cat >>%b <<EOF
/*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
EOF
fi
if [ "$a" = "type" ]; then
cat <<EOF > %b
typedef struct {
;
} ?;
EOF
fi

View File

@ -160,6 +160,8 @@ EditFindDefinition = alt-enter
EditLoadPrevFile = alt-minus
EditLoadNextFile = alt-plus
EditBeginEndRepeat =
SelectCodepage = alt-e
[viewer]

View File

@ -157,6 +157,8 @@ EditFindDefinition = alt-enter
EditLoadPrevFile = alt-minus
EditLoadNextFile = alt-plus
EditBeginEndRepeat =
SelectCodepage = alt-e
EditExtMode = ctrl-x

9
misc/mc.macros Normal file
View File

@ -0,0 +1,9 @@
#see ./macros.d/*
[editor]
#autocomplete "ife", "GPL", "fori"
ctrl-space=EditWordLeftHighlight:-1;EditPipeBlock:5;EditUnmark:-1;
#run make
ctrl-f9=EditPipeBlock:0;
#indent current selection
meta-ctrl-F=EditPipeBlock:4;

View File

@ -184,12 +184,6 @@ typedef struct edit_stack_type
char *filename;
} edit_stack_type;
struct macro
{
unsigned long command;
int ch;
};
struct Widget;
struct WMenuBar;
@ -221,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);
@ -295,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);
@ -311,9 +306,10 @@ int edit_sort_cmd (WEdit * edit);
int edit_ext_cmd (WEdit * edit);
void edit_help_cmd (WEdit * edit);
int edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n);
int edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k);
int edit_store_macro_cmd (WEdit * edit);
gboolean edit_load_macro_cmd (WEdit * edit);
void edit_delete_macro_cmd (WEdit * edit);
gboolean edit_repeat_macro_cmd (WEdit * edit);
int edit_copy_to_X_buf_cmd (WEdit * edit);
int edit_cut_to_X_buf_cmd (WEdit * edit);
@ -321,8 +317,9 @@ 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);
void edit_paste_from_history (WEdit * edit);

View File

@ -12,7 +12,6 @@
/*** typedefs(not structures) and defined constants **********************************************/
#define MAX_MACRO_LENGTH 1024
#define N_LINE_CACHES 32
/*** enums ***************************************************************************************/
@ -132,11 +131,6 @@ struct WEdit
GTree *defines; /* List of defines */
gboolean is_case_insensitive; /* selects language case sensitivity */
/* macro stuff */
int macro_i; /* index to macro[], -1 if not recording a macro */
int macro_depth; /* depth of the macro recursion */
struct macro macro[MAX_MACRO_LENGTH];
/* user map stuff */
GIConv converter;

View File

@ -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,9 +165,7 @@ static const char *const shell_cmd[] = SHELL_COMMANDS_i;
/* --------------------------------------------------------------------------------------------- */
static void user_menu (WEdit * edit);
static int left_of_four_spaces (WEdit * edit);
static inline void edit_execute_macro (WEdit * edit, struct macro macro[], int n);
/* --------------------------------------------------------------------------------------------- */
@ -558,7 +554,6 @@ edit_purge_widget (WEdit * edit)
size_t len = sizeof (WEdit) - sizeof (Widget);
char *start = (char *) edit + sizeof (Widget);
memset (start, 0, len);
edit->macro_i = -1; /* not recording a macro */
}
/* --------------------------------------------------------------------------------------------- */
@ -1663,46 +1658,30 @@ edit_goto_matching_bracket (WEdit * edit)
}
/* --------------------------------------------------------------------------------------------- */
static void
edit_execute_macro (WEdit * edit, struct macro macro[], int n)
{
int i = 0;
if (edit->macro_depth++ > 256)
{
edit_error_dialog (_("Error"), _("Macro recursion is too deep"));
edit->macro_depth--;
return;
}
edit->force |= REDRAW_PAGE;
for (; i < n; i++)
{
edit_execute_cmd (edit, macro[i].command, macro[i].ch);
}
edit_update_screen (edit);
edit->macro_depth--;
}
/*** 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;
long curs;
long start_mark, end_mark;
struct stat status;
block_file = concat_dir_and_file (mc_config_get_cache_path (), EDIT_BLOCK_FILE);
curs = edit->curs1;
nomark = eval_marks (edit, &start_mark, &end_mark);
if (nomark == 0)
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;
@ -1724,14 +1703,13 @@ user_menu (WEdit * edit)
if (fd != NULL)
fclose (fd);
}
edit_cursor_move (edit, curs - edit->curs1);
edit_refresh_cmd (edit);
edit->force |= REDRAW_COMPLETELY;
g_free (block_file);
}
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
int
@ -2225,7 +2203,7 @@ edit_init (WEdit * edit, int lines, int columns, const char *filename, long line
}
edit_set_keymap ();
edit_load_macro_cmd (edit);
return edit;
}
@ -2266,7 +2244,6 @@ edit_clean (WEdit * edit)
g_free (edit->redo_stack);
g_free (edit->filename);
g_free (edit->dir);
mc_search_free (edit->search);
edit->search = NULL;
@ -3404,23 +3381,35 @@ edit_find_bracket (WEdit * edit)
void
edit_execute_key_command (WEdit * edit, unsigned long command, int char_for_insertion)
{
if (command == CK_Begin_Record_Macro)
if (command == CK_Begin_Record_Macro || command == CK_Begin_Record_Repeat
|| (macro_index < 0 && (command == CK_Begin_End_Macro || command == CK_Begin_End_Repeat)))
{
edit->macro_i = 0;
macro_index = 0;
edit->force |= REDRAW_CHAR_ONLY | REDRAW_LINE;
return;
}
if (command == CK_End_Record_Macro && edit->macro_i != -1)
if (macro_index != -1)
{
edit->force |= REDRAW_COMPLETELY;
edit_save_macro_cmd (edit, edit->macro, edit->macro_i);
edit->macro_i = -1;
if (command == CK_End_Record_Macro || command == CK_Begin_End_Macro)
{
edit_store_macro_cmd (edit);
macro_index = -1;
return;
}
if (edit->macro_i >= 0 && edit->macro_i < MAX_MACRO_LENGTH - 1)
else if (command == CK_End_Record_Repeat || command == CK_Begin_End_Repeat)
{
edit->macro[edit->macro_i].command = command;
edit->macro[edit->macro_i++].ch = char_for_insertion;
edit_repeat_macro_cmd (edit);
macro_index = -1;
return;
}
}
if (macro_index >= 0 && macro_index < MAX_MACRO_LENGTH - 1)
{
record_macro_buf[macro_index].action = command;
record_macro_buf[macro_index++].ch = char_for_insertion;
}
/* record the beginning of a set of editing actions initiated by a key press */
if (command != CK_Undo && command != CK_Ext_Mode)
@ -4115,7 +4104,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);
@ -4135,12 +4124,12 @@ 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;
case CK_Begin_End_Repeat:
edit_begin_end_repeat_cmd (edit);
break;
case CK_Ext_Mode:
edit->extmod = 1;
break;
@ -4149,15 +4138,8 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
}
/* CK_Pipe_Block */
if ((command / 1000) == 1) /* a shell command */
edit_block_process_cmd (edit, shell_cmd[command - 1000], 1);
if (command > CK_Macro (0) && command <= CK_Last_Macro)
{ /* a macro command */
struct macro m[MAX_MACRO_LENGTH];
int nm;
if (edit_load_macro_cmd (edit, m, &nm, command - 2000))
edit_execute_macro (edit, m, nm);
}
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)

View File

@ -445,126 +445,6 @@ edit_get_save_file_as (WEdit * edit)
#undef DLG_HEIGHT
}
/* {{{ Macro stuff starts here */
/* --------------------------------------------------------------------------------------------- */
/** creates a macro file if it doesn't exist */
static FILE *
edit_open_macro_file (const char *r)
{
gchar *filename;
FILE *fd;
int file;
filename = concat_dir_and_file (mc_config_get_data_path (), EDIT_MACRO_FILE);
file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (file == -1)
{
g_free (filename);
return 0;
}
close (file);
fd = fopen (filename, r);
g_free (filename);
return fd;
}
#define MAX_MACROS 1024
static int saved_macro[MAX_MACROS + 1];
static int saved_macros_loaded = 0;
/* --------------------------------------------------------------------------------------------- */
/**
This is just to stop the macro file be loaded over and over for keys
that aren't defined to anything. On slow systems this could be annoying.
*/
static int
macro_exists (int k)
{
int i;
for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
if (saved_macro[i] == k)
return i;
return -1;
}
/* --------------------------------------------------------------------------------------------- */
/** returns 1 on error */
static int
edit_delete_macro (WEdit * edit, int k)
{
gchar *tmp, *tmp2;
struct macro macro[MAX_MACRO_LENGTH];
FILE *f, *g;
int s, i, n, j = 0;
(void) edit;
if (saved_macros_loaded)
{
j = macro_exists (k);
if (j < 0)
return 0;
}
tmp = concat_dir_and_file (mc_config_get_cache_path (), EDIT_TEMP_FILE);
g = fopen (tmp, "w");
g_free (tmp);
if (!g)
{
edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open temp file")));
return 1;
}
f = edit_open_macro_file ("r");
if (!f)
{
edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open macro file")));
fclose (g);
return 1;
}
for (;;)
{
n = fscanf (f, ("key '%d 0': "), &s);
if (!n || n == EOF)
break;
n = 0;
while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
n++;
{
int ret;
ret = fscanf (f, ";\n");
}
if (s != k)
{
fprintf (g, ("key '%d 0': "), s);
for (i = 0; i < n; i++)
fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
fprintf (g, ";\n");
}
}
fclose (f);
fclose (g);
tmp = concat_dir_and_file (mc_config_get_cache_path (), EDIT_TEMP_FILE);
tmp2 = concat_dir_and_file (mc_config_get_data_path (), EDIT_MACRO_FILE);
if (rename (tmp, tmp2) == -1)
{
edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot overwrite macro file")));
g_free (tmp);
g_free (tmp2);
return 1;
}
g_free (tmp);
g_free (tmp2);
if (saved_macros_loaded)
memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
return 0;
}
/* }}} */
/* --------------------------------------------------------------------------------------------- */
/** returns 1 on success */
static int
@ -1498,42 +1378,88 @@ edit_save_as_cmd (WEdit * edit)
/* {{{ Macro stuff starts here */
/* --------------------------------------------------------------------------------------------- */
static int
edit_macro_comparator (gconstpointer *macro1, gconstpointer *macro2)
{
const macros_t *m1 = (const macros_t *) macro1;
const macros_t *m2 = (const macros_t *) macro2;
return m1->hotkey - m2->hotkey;
}
/* --------------------------------------------------------------------------------------------- */
/** returns 0 on error */
int
edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
static void
edit_macro_sort_by_hotkey (void)
{
FILE *f;
int s, i;
if (macros_list != NULL && macros_list->len != 0)
g_array_sort (macros_list, (GCompareFunc) edit_macro_comparator);
}
edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
s = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
edit->force |= REDRAW_COMPLETELY;
if (s)
/* --------------------------------------------------------------------------------------------- */
static gboolean
edit_get_macro (WEdit * edit, int hotkey, const macros_t **macros, guint *indx)
{
if (edit_delete_macro (edit, s))
return 0;
f = edit_open_macro_file ("a+");
if (f)
const macros_t *array_start = &g_array_index (macros_list, struct macros_t, 0);
macros_t *result;
macros_t search_macro;
(void) edit;
search_macro.hotkey = hotkey;
result = bsearch (&search_macro, macros_list->data, macros_list->len,
sizeof (macros_t), (GCompareFunc) edit_macro_comparator);
if (result != NULL && result->macro != NULL)
{
fprintf (f, ("key '%d 0': "), s);
for (i = 0; i < n; i++)
fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
fprintf (f, ";\n");
fclose (f);
if (saved_macros_loaded)
*indx = (result - array_start);
*macros = result;
return TRUE;
}
*indx = 0;
return FALSE;
}
/* --------------------------------------------------------------------------------------------- */
/** returns FALSE on error */
static gboolean
edit_delete_macro (WEdit * edit, int hotkey)
{
for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
saved_macro[i] = s;
mc_config_t *macros_config = NULL;
const char *section_name = "editor";
gchar *macros_fname;
guint indx;
char *keyname;
const macros_t *macros = NULL;
/* clear array of actions for current hotkey */
while (edit_get_macro (edit, hotkey, &macros, &indx))
{
if (macros->macro != NULL)
g_array_free (macros->macro, TRUE);
macros = NULL;
g_array_remove_index (macros_list, indx);
edit_macro_sort_by_hotkey ();
}
return 1;
}
else
edit_error_dialog (_("Save macro"), get_sys_error (_("Cannot open macro file")));
}
return 0;
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);
if (macros_config == NULL)
return FALSE;
keyname = lookup_key_by_code (hotkey);
while (mc_config_del_key (macros_config, section_name, keyname))
;
g_free (keyname);
mc_config_save_file (macros_config, NULL);
mc_config_deinit (macros_config);
return TRUE;
}
/* --------------------------------------------------------------------------------------------- */
@ -1541,74 +1467,260 @@ edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
void
edit_delete_macro_cmd (WEdit * edit)
{
int command;
int hotkey;
command = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
hotkey = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
if (command != 0)
edit_delete_macro (edit, command);
if (hotkey != 0 && !edit_delete_macro (edit, hotkey))
message (D_ERROR, _("Delete macro"), _("Macro not deleted"));
}
/* --------------------------------------------------------------------------------------------- */
/** return 0 on error */
int
edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
/** returns FALSE on error */
gboolean
edit_execute_macro (WEdit * edit, int hotkey)
{
FILE *f;
int s, i = 0, found = 0;
gboolean res = FALSE;
if (hotkey != 0)
{
const macros_t *macros;
guint indx;
if (edit_get_macro (edit, hotkey, &macros, &indx) &&
macros->macro != NULL && macros->macro->len != 0)
{
guint i;
edit->force |= REDRAW_PAGE;
for (i = 0; i < macros->macro->len; i++)
{
const macro_action_t *m_act;
m_act = &g_array_index (macros->macro, struct macro_action_t, i);
edit_execute_cmd (edit, m_act->action, m_act->ch);
res = TRUE;
}
}
}
edit_update_screen (edit);
return res;
}
/* --------------------------------------------------------------------------------------------- */
/** returns FALSE on error */
gboolean
edit_store_macro_cmd (WEdit * edit)
{
int i;
int hotkey;
GString *marcros_string;
mc_config_t *macros_config = NULL;
const char *section_name = "editor";
gchar *macros_fname;
GArray *macros; /* current macro */
int tmp_act;
gboolean have_macro = FALSE;
char *keyname = NULL;
hotkey = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
if (hotkey == ESC_CHAR)
return FALSE;
tmp_act = keybind_lookup_keymap_command (editor_map, hotkey);
/* return FALSE if try assign macro into restricted hotkeys */
if (tmp_act == CK_Begin_Record_Macro
|| tmp_act == CK_End_Record_Macro
|| tmp_act == CK_Begin_End_Macro)
return FALSE;
edit_delete_macro (edit, hotkey);
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);
if (macros_config == NULL)
return FALSE;
edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
marcros_string = g_string_sized_new (250);
macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
keyname = lookup_key_by_code (hotkey);
for (i = 0; i < macro_index; i++)
{
macro_action_t m_act;
const char *action_name;
action_name = keybind_lookup_actionname (record_macro_buf[i].action);
if (action_name == NULL)
break;
m_act.action = record_macro_buf[i].action;
m_act.ch = record_macro_buf[i].ch;
g_array_append_val (macros, m_act);
have_macro = TRUE;
g_string_append_printf (marcros_string, "%s:%i;", action_name, (int) record_macro_buf[i].ch);
}
if (have_macro)
{
macros_t macro;
macro.hotkey = hotkey;
macro.macro = macros;
g_array_append_val (macros_list, macro);
mc_config_set_string (macros_config, section_name, keyname, marcros_string->str);
}
else
mc_config_del_key (macros_config, section_name, keyname);
g_free (keyname);
edit_macro_sort_by_hotkey ();
g_string_free (marcros_string, TRUE);
mc_config_save_file (macros_config, NULL);
mc_config_deinit (macros_config);
return TRUE;
}
/* --------------------------------------------------------------------------------------------- */
gboolean
edit_repeat_macro_cmd (WEdit * edit)
{
int i, j;
char *f;
long count_repeat;
char *error = NULL;
f = input_dialog (_("Repeat last commands"), _("Repeat times:"), MC_HISTORY_EDIT_REPEAT, NULL);
if (f == NULL || *f == '\0')
{
g_free (f);
return FALSE;
}
count_repeat = strtol (f, &error, 0);
if (*error != '\0')
{
g_free (f);
return FALSE;
}
g_free (f);
edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
edit->force |= REDRAW_PAGE;
for (j = 0; j < count_repeat; j++)
for (i = 0; i < macro_index; i++)
edit_execute_cmd (edit, record_macro_buf[i].action, record_macro_buf[i].ch);
edit_update_screen (edit);
return TRUE;
}
/* --------------------------------------------------------------------------------------------- */
/** return FALSE on error */
gboolean
edit_load_macro_cmd (WEdit * edit)
{
mc_config_t *macros_config = NULL;
gchar **profile_keys, **keys;
gchar **values, **curr_values;
gsize len, values_len;
const char *section_name = "editor";
gchar *macros_fname;
int hotkey;
(void) edit;
if (saved_macros_loaded)
if (macro_exists (k) < 0)
return 0;
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);
f = edit_open_macro_file ("r");
if (f != NULL)
if (macros_config == NULL)
return FALSE;
profile_keys = keys = mc_config_get_keys (macros_config, section_name, &len);
while (*profile_keys != NULL)
{
struct macro dummy;
do
gboolean have_macro;
GArray *macros;
macros_t macro;
macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
curr_values = values = mc_config_get_string_list (macros_config, section_name,
*profile_keys, &values_len);
hotkey = lookup_key (*profile_keys, NULL);
have_macro = FALSE;
while (*curr_values != NULL && *curr_values[0] != '\0')
{
int u;
u = fscanf (f, ("key '%d 0': "), &s);
if (!u || u == EOF)
break;
if (!saved_macros_loaded)
saved_macro[i++] = s;
if (!found)
char **macro_pair = NULL;
macro_pair = g_strsplit (*curr_values, ":", 2);
if (macro_pair != NULL)
{
*n = 0;
while (*n < MAX_MACRO_LENGTH
&& 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
(*n)++;
}
macro_action_t m_act;
if (macro_pair[0] == NULL || macro_pair[0][0] == '\0')
m_act.action = 0;
else
{
while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
}
{
int ret;
ret = fscanf (f, ";\n");
}
if (s == k)
found = 1;
}
while (!found || !saved_macros_loaded);
if (!saved_macros_loaded)
{
saved_macro[i] = 0;
saved_macros_loaded = 1;
}
fclose (f);
return found;
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')
m_act.ch = -1;
else
edit_error_dialog (_("Load macro"), get_sys_error (_("Cannot open macro file")));
return 0;
{
m_act.ch = strtol (macro_pair[1], NULL, 0);
g_free (macro_pair[1]);
macro_pair[1] = NULL;
}
if (m_act.action != 0)
{
/* a shell command */
if ((m_act.action / CK_Pipe_Block (0)) == 1)
{
m_act.action = CK_Pipe_Block (0) + (m_act.ch > 0 ? m_act.ch : 0);
m_act.ch = -1;
}
g_array_append_val (macros, m_act);
have_macro = TRUE;
}
g_strfreev (macro_pair);
macro_pair = NULL;
}
curr_values++;
}
if (have_macro)
{
macro.hotkey = hotkey;
macro.macro = macros;
g_array_append_val (macros_list, macro);
}
profile_keys++;
g_strfreev (values);
}
g_strfreev (keys);
mc_config_deinit (macros_config);
edit_macro_sort_by_hotkey ();
return TRUE;
}
/* }}} Macro stuff starts here */
/* }}} Macro stuff end here */
/* --------------------------------------------------------------------------------------------- */
/** returns 1 on success */
@ -1634,7 +1746,6 @@ edit_save_confirm_cmd (WEdit * edit)
return edit_save_cmd (edit);
}
/* --------------------------------------------------------------------------------------------- */
/** returns 1 on success */
@ -2741,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);
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;
/* 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);
}
/* --------------------------------------------------------------------------------------------- */
@ -3027,26 +3026,25 @@ edit_insert_literal_cmd (WEdit * edit)
/* --------------------------------------------------------------------------------------------- */
void
edit_execute_macro_cmd (WEdit * edit)
edit_begin_end_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 is a pointer to the widget */
if (edit != NULL)
{
unsigned long command = macro_index < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
edit_execute_key_command (edit, command, -1);
}
}
/* --------------------------------------------------------------------------------------------- */
void
edit_begin_end_macro_cmd (WEdit * edit)
edit_begin_end_repeat_cmd (WEdit * edit)
{
/* edit is a pointer to the widget */
if (edit)
if (edit != NULL)
{
unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
unsigned long command = macro_index < 0 ? CK_Begin_Record_Repeat : CK_End_Record_Repeat;
edit_execute_key_command (edit, command, -1);
}
}

View File

@ -145,7 +145,7 @@ status_string (WEdit * edit, char *s, int w)
"%c%c%c%c %3ld %5ld/%ld %6ld/%ld %s %s",
edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
edit->modified ? 'M' : '-',
edit->macro_i < 0 ? '-' : 'R',
macro_index < 0 ? '-' : 'R',
edit->overwrite == 0 ? '-' : 'O',
edit->curs_col + edit->over_col,
edit->curs_line + 1,
@ -161,7 +161,7 @@ status_string (WEdit * edit, char *s, int w)
"[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb) %s %s",
edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
edit->modified ? 'M' : '-',
edit->macro_i < 0 ? '-' : 'R',
macro_index < 0 ? '-' : 'R',
edit->overwrite == 0 ? '-' : 'O',
edit->curs_col + edit->over_col,
edit->start_line + 1,

View File

@ -47,7 +47,7 @@
#include "lib/charsets.h" /* convert_from_input_c() */
#include "edit-impl.h"
#include "edit-widget.h" /* edit->macro_i */
#include "edit-widget.h" /* WEdit */
#include "editcmd_dialogs.h"
#include "src/keybind-defaults.h" /* keybind_lookup_keymap_command() */

View File

@ -168,12 +168,9 @@ create_command_menu (void)
entries = g_list_append (entries, menu_separator_create ());
entries =
g_list_append (entries,
menu_entry_create (_("&Start record macro"), CK_Begin_Record_Macro));
entries =
g_list_append (entries,
menu_entry_create (_("Finis&h record macro..."), CK_End_Record_Macro));
entries = g_list_append (entries, menu_entry_create (_("&Execute macro..."), CK_Execute_Macro));
menu_entry_create (_("&Start/Stop record macro"), CK_Begin_End_Macro));
entries = g_list_append (entries, menu_entry_create (_("Delete macr&o..."), CK_Delete_Macro));
entries = g_list_append (entries, menu_entry_create (_("Record/Repeat &actions"), CK_Begin_End_Repeat));
entries = g_list_append (entries, menu_separator_create ());
entries =
g_list_append (entries, menu_entry_create (_("'ispell' s&pell check"), CK_Pipe_Block (1)));

View File

@ -315,7 +315,9 @@ edit_callback (Widget * w, widget_msg_t msg, int parm)
cb_ret_t ret = MSG_NOT_HANDLED;
/* The user may override the access-keys for the menu bar. */
if (edit_translate_key (e, parm, &cmd, &ch))
if (macro_index == -1 && edit_execute_macro (e, parm))
ret = MSG_HANDLED;
else if (edit_translate_key (e, parm, &cmd, &ch))
{
edit_execute_key_command (e, cmd, ch);
edit_update_screen (e);

View File

@ -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);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -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 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);
if (!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;
@ -860,16 +868,27 @@ user_menu_cmd (struct WEdit *edit_widget)
int selected, old_patterns;
Listbox *listbox;
gboolean res = FALSE;
gboolean interactive = FALSE;
if (!vfs_current_is_local ())
{
message (D_ERROR, MSG_ERROR, "%s", _("Cannot execute commands on non-local filesystems"));
return FALSE;
}
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);
@ -936,6 +955,9 @@ user_menu_cmd (struct WEdit *edit_widget)
{
if (*p == '#')
{
/* show prompt if first line of external script is #interactive */
if (selected_entry >= 0 && strncmp (p, "#interactive", 12) == 0)
interactive = TRUE;
/* A commented menu entry */
accept_entry = 1;
}
@ -1005,6 +1027,10 @@ user_menu_cmd (struct WEdit *edit_widget)
res = FALSE;
}
else
{
if (selected_entry >= 0)
selected = selected_entry;
else
{
max_cols = min (max (max_cols, col), MAX_ENTRY_LEN);
@ -1022,9 +1048,10 @@ user_menu_cmd (struct WEdit *edit_widget)
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], interactive);
res = TRUE;
}

View File

@ -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 **);

View File

@ -16,6 +16,7 @@
#define MC_HISTORY_EDIT_GOTO_LINE "mc.edit.goto-line"
#define MC_HISTORY_EDIT_SORT "mc.edit.sort"
#define MC_HISTORY_EDIT_PASTE_EXTCMD "mc.edit.paste-extcmd"
#define MC_HISTORY_EDIT_REPEAT "mc.edit.repeat-action"
#define MC_HISTORY_FM_VIEW_FILE "mc.fm.view-file"
#define MC_HISTORY_FM_MKDIR "mc.fm.mkdir"

View File

@ -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 */

View File

@ -133,6 +133,9 @@ int print_last_revert = FALSE;
/* If set, then print to the given file the last directory we were at */
char *last_wd_string = NULL;
/* index to record_macro_buf[], -1 if not recording a macro */
int macro_index = -1;
/*** file scope macro definitions ****************************************************************/
/*** file scope type declarations ****************************************************************/
@ -482,6 +485,8 @@ main (int argc, char *argv[])
load_keymap_defs ();
macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t));
tty_init_colors (mc_args__disable_colors, mc_args__force_colors);
{
@ -587,6 +592,19 @@ main (int argc, char *argv[])
done_key ();
if (macros_list != NULL)
{
guint i;
macros_t *macros;
for (i = 0; i < macros_list->len; i++)
{
macros = &g_array_index (macros_list, struct macros_t, i);
if (macros != NULL && macros->macro != NULL)
g_array_free (macros->macro, FALSE);
}
g_array_free (macros_list, TRUE);
}
str_uninit_strings ();
g_free (mc_run_param0);

View File

@ -9,6 +9,8 @@
/*** typedefs(not structures) and defined constants **********************************************/
#define MAX_MACRO_LENGTH 1024
/*** enums ***************************************************************************************/
/* run mode and params */
@ -26,9 +28,23 @@ enum cd_enum
cd_exact
};
/*** structures declarations (and typedefs of structures)*****************************************/
typedef struct macro_action_t
{
unsigned long action;
int ch;
} macro_action_t;
typedef struct macros_t
{
int hotkey;
GArray *macro;
} macros_t;
/* macro stuff */
struct macro_action_t record_macro_buf[MAX_MACRO_LENGTH];
struct mc_fhl_struct;
/*** global variables defined in .c file *********************************************************/
@ -81,6 +97,10 @@ extern const char *mc_prompt;
extern char *mc_sysconfig_dir;
extern char *mc_share_data_dir;
GArray *macros_list;
/* index to record_macro_buf[], -1 if not recording a macro */
extern int macro_index;
/*** declarations of public functions ************************************************************/
#ifdef HAVE_SUBSHELL_SUPPORT