vi: expand '%' and '#' in colon commands
Track the current and alternate filenames. The placeholders '%' and '#' can be used in arguments to colon commands to represent the current and alternate filenames respectively. Backslash can be used to allow literal '%' and '#' characters to be entered. This feature is controlled by the configuration option FEATURE_VI_COLON_EXPAND. function old new delta expand_args - 198 +198 colon 3751 3927 +176 update_filename - 70 +70 init_filename - 48 +48 .rodata 105218 105239 +21 get_one_char 115 124 +9 edit_file 835 838 +3 do_cmd 4724 4727 +3 init_text_buffer 190 172 -18 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 5/1 up/down: 528/-18) Total: 510 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
852ffbee34
commit
acd3079fd1
126
editors/vi.c
126
editors/vi.c
@ -53,6 +53,14 @@
|
||||
//config: Enable a limited set of colon commands. This does not
|
||||
//config: provide an "ex" mode.
|
||||
//config:
|
||||
//config:config FEATURE_VI_COLON_EXPAND
|
||||
//config: bool "Expand \"%\" and \"#\" in colon commands"
|
||||
//config: default y
|
||||
//config: depends on FEATURE_VI_COLON
|
||||
//config: help
|
||||
//config: Expand the special characters \"%\" (current filename)
|
||||
//config: and \"#\" (alternate filename) in colon commands.
|
||||
//config:
|
||||
//config:config FEATURE_VI_YANKMARK
|
||||
//config: bool "Enable yank/put commands and mark cmds"
|
||||
//config: default y
|
||||
@ -347,6 +355,9 @@ struct globals {
|
||||
// [don't make smallint!]
|
||||
int last_status_cksum; // hash of current status line
|
||||
char *current_filename;
|
||||
#if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||
char *alt_filename;
|
||||
#endif
|
||||
char *screenbegin; // index into text[], of top line on the screen
|
||||
char *screen; // pointer to the virtual screen buffer
|
||||
int screensize; // and its size
|
||||
@ -471,6 +482,7 @@ struct globals {
|
||||
#define have_status_msg (G.have_status_msg )
|
||||
#define last_status_cksum (G.last_status_cksum )
|
||||
#define current_filename (G.current_filename )
|
||||
#define alt_filename (G.alt_filename )
|
||||
#define screen (G.screen )
|
||||
#define screensize (G.screensize )
|
||||
#define screenbegin (G.screenbegin )
|
||||
@ -2198,6 +2210,41 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
|
||||
return p;
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||
static void init_filename(char *fn)
|
||||
{
|
||||
char *copy = xstrdup(fn);
|
||||
|
||||
if (current_filename == NULL) {
|
||||
current_filename = copy;
|
||||
} else {
|
||||
free(alt_filename);
|
||||
alt_filename = copy;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define init_filename(f) ((void)(0))
|
||||
#endif
|
||||
|
||||
static void update_filename(char *fn)
|
||||
{
|
||||
#if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||
if (fn == NULL)
|
||||
return;
|
||||
|
||||
if (current_filename == NULL || strcmp(fn, current_filename) != 0) {
|
||||
free(alt_filename);
|
||||
alt_filename = current_filename;
|
||||
current_filename = xstrdup(fn);
|
||||
}
|
||||
#else
|
||||
if (fn != current_filename) {
|
||||
free(current_filename);
|
||||
current_filename = xstrdup(fn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// read text from file or create an empty buf
|
||||
// will also update current_filename
|
||||
static int init_text_buffer(char *fn)
|
||||
@ -2209,10 +2256,7 @@ static int init_text_buffer(char *fn)
|
||||
text_size = 10240;
|
||||
screenbegin = dot = end = text = xzalloc(text_size);
|
||||
|
||||
if (fn != current_filename) {
|
||||
free(current_filename);
|
||||
current_filename = xstrdup(fn);
|
||||
}
|
||||
update_filename(fn);
|
||||
rc = file_insert(fn, text, 1);
|
||||
if (rc < 0) {
|
||||
// file doesnt exist. Start empty buf with dummy line
|
||||
@ -2556,6 +2600,43 @@ static void setops(char *args, int flg_no)
|
||||
}
|
||||
# endif
|
||||
|
||||
# if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||
static char *expand_args(char *args)
|
||||
{
|
||||
char *s, *t;
|
||||
const char *replace;
|
||||
|
||||
args = xstrdup(args);
|
||||
for (s = args; *s; s++) {
|
||||
if (*s == '%') {
|
||||
replace = current_filename;
|
||||
} else if (*s == '#') {
|
||||
replace = alt_filename;
|
||||
} else {
|
||||
if (*s == '\\' && s[1] != '\0') {
|
||||
for (t = s++; *t; t++)
|
||||
*t = t[1];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (replace == NULL) {
|
||||
free(args);
|
||||
status_line_bold("No previous filename");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*s = '\0';
|
||||
t = xasprintf("%s%s%s", args, replace, s+1);
|
||||
s = t + (s - args) + strlen(replace);
|
||||
free(args);
|
||||
args = t;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
# else
|
||||
# define expand_args(a) (a)
|
||||
# endif
|
||||
#endif /* FEATURE_VI_COLON */
|
||||
|
||||
// buf must be no longer than MAX_INPUT_LEN!
|
||||
@ -2620,7 +2701,7 @@ static void colon(char *buf)
|
||||
#else
|
||||
|
||||
char c, *buf1, *q, *r;
|
||||
char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args;
|
||||
char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL;
|
||||
int i, l, li, b, e;
|
||||
int useforce;
|
||||
|
||||
@ -2708,9 +2789,12 @@ static void colon(char *buf)
|
||||
else if (cmd[0] == '!') { // run a cmd
|
||||
int retcode;
|
||||
// :!ls run the <cmd>
|
||||
exp = expand_args(buf + 1);
|
||||
if (exp == NULL)
|
||||
goto ret;
|
||||
go_bottom_and_clear_to_eol();
|
||||
cookmode();
|
||||
retcode = system(buf + 1); // run the cmd
|
||||
retcode = system(exp); // run the cmd
|
||||
if (retcode)
|
||||
printf("\nshell returned %i\n\n", retcode);
|
||||
rawmode();
|
||||
@ -2739,7 +2823,9 @@ static void colon(char *buf)
|
||||
}
|
||||
if (args[0]) {
|
||||
// the user supplied a file name
|
||||
fn = args;
|
||||
fn = exp = expand_args(args);
|
||||
if (exp == NULL)
|
||||
goto ret;
|
||||
} else if (current_filename == NULL) {
|
||||
// no user file name, no current name- punt
|
||||
status_line_bold("No current filename");
|
||||
@ -2763,7 +2849,7 @@ static void colon(char *buf)
|
||||
status_line("'%s'%s"
|
||||
IF_FEATURE_VI_READONLY("%s")
|
||||
" %uL, %uC",
|
||||
current_filename,
|
||||
fn,
|
||||
(size < 0 ? " [New file]" : ""),
|
||||
IF_FEATURE_VI_READONLY(
|
||||
((readonly_mode) ? " [Readonly]" : ""),
|
||||
@ -2777,8 +2863,10 @@ static void colon(char *buf)
|
||||
}
|
||||
if (args[0]) {
|
||||
// user wants a new filename
|
||||
free(current_filename);
|
||||
current_filename = xstrdup(args);
|
||||
exp = expand_args(args);
|
||||
if (exp == NULL)
|
||||
goto ret;
|
||||
update_filename(exp);
|
||||
} else {
|
||||
// user wants file status info
|
||||
last_status_cksum = 0; // force status update
|
||||
@ -2862,7 +2950,10 @@ static void colon(char *buf)
|
||||
|
||||
if (args[0]) {
|
||||
// the user supplied a file name
|
||||
fn = args;
|
||||
fn = exp = expand_args(args);
|
||||
if (exp == NULL)
|
||||
goto ret;
|
||||
init_filename(fn);
|
||||
} else if (current_filename == NULL) {
|
||||
// no user file name, no current name- punt
|
||||
status_line_bold("No current filename");
|
||||
@ -3042,12 +3133,16 @@ static void colon(char *buf)
|
||||
if (args[0]) {
|
||||
struct stat statbuf;
|
||||
|
||||
if (!useforce && (fn == NULL || strcmp(fn, args) != 0) &&
|
||||
stat(args, &statbuf) == 0) {
|
||||
exp = expand_args(args);
|
||||
if (exp == NULL)
|
||||
goto ret;
|
||||
if (!useforce && (fn == NULL || strcmp(fn, exp) != 0) &&
|
||||
stat(exp, &statbuf) == 0) {
|
||||
status_line_bold("File exists (:w! overrides)");
|
||||
goto ret;
|
||||
}
|
||||
fn = args;
|
||||
fn = exp;
|
||||
init_filename(fn);
|
||||
}
|
||||
# if ENABLE_FEATURE_VI_READONLY
|
||||
else if (readonly_mode && !useforce && fn) {
|
||||
@ -3109,6 +3204,9 @@ static void colon(char *buf)
|
||||
not_implemented(cmd);
|
||||
}
|
||||
ret:
|
||||
# if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||
free(exp);
|
||||
# endif
|
||||
dot = bound_dot(dot); // make sure "dot" is valid
|
||||
return;
|
||||
# if ENABLE_FEATURE_VI_SEARCH
|
||||
|
Loading…
Reference in New Issue
Block a user