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: Enable a limited set of colon commands. This does not
|
||||||
//config: provide an "ex" mode.
|
//config: provide an "ex" mode.
|
||||||
//config:
|
//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:config FEATURE_VI_YANKMARK
|
||||||
//config: bool "Enable yank/put commands and mark cmds"
|
//config: bool "Enable yank/put commands and mark cmds"
|
||||||
//config: default y
|
//config: default y
|
||||||
@ -347,6 +355,9 @@ struct globals {
|
|||||||
// [don't make smallint!]
|
// [don't make smallint!]
|
||||||
int last_status_cksum; // hash of current status line
|
int last_status_cksum; // hash of current status line
|
||||||
char *current_filename;
|
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 *screenbegin; // index into text[], of top line on the screen
|
||||||
char *screen; // pointer to the virtual screen buffer
|
char *screen; // pointer to the virtual screen buffer
|
||||||
int screensize; // and its size
|
int screensize; // and its size
|
||||||
@ -471,6 +482,7 @@ struct globals {
|
|||||||
#define have_status_msg (G.have_status_msg )
|
#define have_status_msg (G.have_status_msg )
|
||||||
#define last_status_cksum (G.last_status_cksum )
|
#define last_status_cksum (G.last_status_cksum )
|
||||||
#define current_filename (G.current_filename )
|
#define current_filename (G.current_filename )
|
||||||
|
#define alt_filename (G.alt_filename )
|
||||||
#define screen (G.screen )
|
#define screen (G.screen )
|
||||||
#define screensize (G.screensize )
|
#define screensize (G.screensize )
|
||||||
#define screenbegin (G.screenbegin )
|
#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;
|
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
|
// read text from file or create an empty buf
|
||||||
// will also update current_filename
|
// will also update current_filename
|
||||||
static int init_text_buffer(char *fn)
|
static int init_text_buffer(char *fn)
|
||||||
@ -2209,10 +2256,7 @@ static int init_text_buffer(char *fn)
|
|||||||
text_size = 10240;
|
text_size = 10240;
|
||||||
screenbegin = dot = end = text = xzalloc(text_size);
|
screenbegin = dot = end = text = xzalloc(text_size);
|
||||||
|
|
||||||
if (fn != current_filename) {
|
update_filename(fn);
|
||||||
free(current_filename);
|
|
||||||
current_filename = xstrdup(fn);
|
|
||||||
}
|
|
||||||
rc = file_insert(fn, text, 1);
|
rc = file_insert(fn, text, 1);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
// file doesnt exist. Start empty buf with dummy line
|
// file doesnt exist. Start empty buf with dummy line
|
||||||
@ -2556,6 +2600,43 @@ static void setops(char *args, int flg_no)
|
|||||||
}
|
}
|
||||||
# endif
|
# 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 */
|
#endif /* FEATURE_VI_COLON */
|
||||||
|
|
||||||
// buf must be no longer than MAX_INPUT_LEN!
|
// buf must be no longer than MAX_INPUT_LEN!
|
||||||
@ -2620,7 +2701,7 @@ static void colon(char *buf)
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
char c, *buf1, *q, *r;
|
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 i, l, li, b, e;
|
||||||
int useforce;
|
int useforce;
|
||||||
|
|
||||||
@ -2708,9 +2789,12 @@ static void colon(char *buf)
|
|||||||
else if (cmd[0] == '!') { // run a cmd
|
else if (cmd[0] == '!') { // run a cmd
|
||||||
int retcode;
|
int retcode;
|
||||||
// :!ls run the <cmd>
|
// :!ls run the <cmd>
|
||||||
|
exp = expand_args(buf + 1);
|
||||||
|
if (exp == NULL)
|
||||||
|
goto ret;
|
||||||
go_bottom_and_clear_to_eol();
|
go_bottom_and_clear_to_eol();
|
||||||
cookmode();
|
cookmode();
|
||||||
retcode = system(buf + 1); // run the cmd
|
retcode = system(exp); // run the cmd
|
||||||
if (retcode)
|
if (retcode)
|
||||||
printf("\nshell returned %i\n\n", retcode);
|
printf("\nshell returned %i\n\n", retcode);
|
||||||
rawmode();
|
rawmode();
|
||||||
@ -2739,7 +2823,9 @@ static void colon(char *buf)
|
|||||||
}
|
}
|
||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
// the user supplied a file name
|
// the user supplied a file name
|
||||||
fn = args;
|
fn = exp = expand_args(args);
|
||||||
|
if (exp == NULL)
|
||||||
|
goto ret;
|
||||||
} else if (current_filename == NULL) {
|
} else if (current_filename == NULL) {
|
||||||
// no user file name, no current name- punt
|
// no user file name, no current name- punt
|
||||||
status_line_bold("No current filename");
|
status_line_bold("No current filename");
|
||||||
@ -2763,7 +2849,7 @@ static void colon(char *buf)
|
|||||||
status_line("'%s'%s"
|
status_line("'%s'%s"
|
||||||
IF_FEATURE_VI_READONLY("%s")
|
IF_FEATURE_VI_READONLY("%s")
|
||||||
" %uL, %uC",
|
" %uL, %uC",
|
||||||
current_filename,
|
fn,
|
||||||
(size < 0 ? " [New file]" : ""),
|
(size < 0 ? " [New file]" : ""),
|
||||||
IF_FEATURE_VI_READONLY(
|
IF_FEATURE_VI_READONLY(
|
||||||
((readonly_mode) ? " [Readonly]" : ""),
|
((readonly_mode) ? " [Readonly]" : ""),
|
||||||
@ -2777,8 +2863,10 @@ static void colon(char *buf)
|
|||||||
}
|
}
|
||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
// user wants a new filename
|
// user wants a new filename
|
||||||
free(current_filename);
|
exp = expand_args(args);
|
||||||
current_filename = xstrdup(args);
|
if (exp == NULL)
|
||||||
|
goto ret;
|
||||||
|
update_filename(exp);
|
||||||
} else {
|
} else {
|
||||||
// user wants file status info
|
// user wants file status info
|
||||||
last_status_cksum = 0; // force status update
|
last_status_cksum = 0; // force status update
|
||||||
@ -2862,7 +2950,10 @@ static void colon(char *buf)
|
|||||||
|
|
||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
// the user supplied a file name
|
// 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) {
|
} else if (current_filename == NULL) {
|
||||||
// no user file name, no current name- punt
|
// no user file name, no current name- punt
|
||||||
status_line_bold("No current filename");
|
status_line_bold("No current filename");
|
||||||
@ -3042,12 +3133,16 @@ static void colon(char *buf)
|
|||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (!useforce && (fn == NULL || strcmp(fn, args) != 0) &&
|
exp = expand_args(args);
|
||||||
stat(args, &statbuf) == 0) {
|
if (exp == NULL)
|
||||||
|
goto ret;
|
||||||
|
if (!useforce && (fn == NULL || strcmp(fn, exp) != 0) &&
|
||||||
|
stat(exp, &statbuf) == 0) {
|
||||||
status_line_bold("File exists (:w! overrides)");
|
status_line_bold("File exists (:w! overrides)");
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
fn = args;
|
fn = exp;
|
||||||
|
init_filename(fn);
|
||||||
}
|
}
|
||||||
# if ENABLE_FEATURE_VI_READONLY
|
# if ENABLE_FEATURE_VI_READONLY
|
||||||
else if (readonly_mode && !useforce && fn) {
|
else if (readonly_mode && !useforce && fn) {
|
||||||
@ -3109,6 +3204,9 @@ static void colon(char *buf)
|
|||||||
not_implemented(cmd);
|
not_implemented(cmd);
|
||||||
}
|
}
|
||||||
ret:
|
ret:
|
||||||
|
# if ENABLE_FEATURE_VI_COLON_EXPAND
|
||||||
|
free(exp);
|
||||||
|
# endif
|
||||||
dot = bound_dot(dot); // make sure "dot" is valid
|
dot = bound_dot(dot); // make sure "dot" is valid
|
||||||
return;
|
return;
|
||||||
# if ENABLE_FEATURE_VI_SEARCH
|
# if ENABLE_FEATURE_VI_SEARCH
|
||||||
|
Loading…
Reference in New Issue
Block a user