📄 ex_cmds.c
字号:
*p++ = ' '; /* not really needed? Not with sh, ksh or bash */
sprintf((char *)p, (char *)p_srr, (char *)otmp);
}
else
sprintf((char *)IObuff + STRLEN(IObuff),
#ifndef RISCOS
" %s%s", /* " %s %s" causes problems on Amiga */
#else
" %s %s", /* But is needed for RISC OS */
#endif
(char *)p_srr, (char *)otmp);
}
windgoto((int)Rows - 1, 0);
cursor_on();
/*
* When not redirecting the output the command can write anything to the
* screen. If 'shellredir' is equal to ">", screen may be messed up by
* stderr output of external command. Clear the screen later.
* If do_in is FALSE, this could be something like ":r !cat", which may
* also mess up the screen, clear it later.
*/
if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
must_redraw = CLEAR;
else
redraw_later(NOT_VALID);
/*
* When call_shell() fails wait_return() is called to give the user a
* chance to read the error messages. Otherwise errors are ignored, so you
* can see the error messages from the command that appear on stdout; use
* 'u' to fix the text
* Switch to cooked mode when not redirecting stdin, avoids that something
* like ":r !cat" hangs.
* Pass on the SHELL_DOOUT flag when the output is being redirected.
*/
if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED |
(do_out ? SHELL_DOOUT : 0)))
{
must_redraw = CLEAR;
wait_return(FALSE);
}
need_check_timestamps = TRUE;
if (do_out)
{
if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
{
goto error;
}
if (readfile(otmp, NULL, line2, (linenr_t)0, (linenr_t)MAXLNUM,
READ_FILTER) == FAIL)
{
msg_putchar('\n');
emsg2(e_notread, otmp);
goto error;
}
#ifdef AUTOCMD
if (curbuf != old_curbuf)
goto filterend;
#endif
if (do_in)
{
/*
* Put cursor on first filtered line for ":range!cmd".
* Adjust '[ and '] (set by buf_write()).
*/
curwin->w_cursor.lnum = line1;
del_lines(linecount, TRUE, TRUE);
curbuf->b_op_start.lnum -= linecount; /* adjust '[ */
curbuf->b_op_end.lnum -= linecount; /* adjust '] */
write_lnum_adjust(-linecount); /* adjust last line
for next write */
}
else
{
/*
* Put cursor on last new line for ":r !cmd".
*/
curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
}
beginline(BL_WHITE | BL_FIX); /* cursor on first non-blank */
--no_wait_return;
if (linecount > p_report)
{
if (do_in)
{
sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
if (msg(msg_buf) && !msg_scroll)
{
keep_msg = msg_buf; /* display message after redraw */
keep_msg_attr = 0;
}
}
else
msgmore((long)linecount);
}
}
else
{
error:
/* put cursor back in same position for ":w !cmd" */
curwin->w_cursor = cursor_save;
--no_wait_return;
wait_return(FALSE);
}
filterend:
#ifdef AUTOCMD
if (curbuf != old_curbuf)
{
--no_wait_return;
EMSG("*Filter* Autocommands must not change current buffer");
}
#endif
if (itmp != NULL)
mch_remove(itmp);
if (otmp != NULL)
mch_remove(otmp);
vim_free(itmp);
vim_free(otmp);
}
#ifdef VIMINFO
static int no_viminfo __ARGS((void));
static int viminfo_errcnt;
static int
no_viminfo()
{
/* "vim -i NONE" does not read or write a viminfo file */
return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
}
/*
* Report an error for reading a viminfo file.
* Count the number of errors. When there are more than 10, return TRUE.
*/
int
viminfo_error(message, line)
char *message;
char_u *line;
{
sprintf((char *)IObuff, "viminfo: %s in line: ", message);
STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
emsg(IObuff);
if (++viminfo_errcnt >= 10)
{
EMSG("viminfo: Too many errors, skipping rest of file");
return TRUE;
}
return FALSE;
}
/*
* read_viminfo() -- Read the viminfo file. Registers etc. which are already
* set are not over-written unless force is TRUE. -- webb
*/
int
read_viminfo(file, want_info, want_marks, forceit)
char_u *file;
int want_info;
int want_marks;
int forceit;
{
FILE *fp;
if (no_viminfo())
return FAIL;
file = viminfo_filename(file); /* may set to default if NULL */
if ((fp = fopen((char *)file, READBIN)) == NULL)
return FAIL;
if (p_verbose > 0)
smsg((char_u *)"Reading viminfo file \"%s\"%s%s", file,
want_info ? " info" : "",
want_marks ? " marks" : "");
viminfo_errcnt = 0;
do_viminfo(fp, NULL, want_info, want_marks, forceit);
fclose(fp);
return OK;
}
/*
* write_viminfo() -- Write the viminfo file. The old one is read in first so
* that effectively a merge of current info and old info is done. This allows
* multiple vims to run simultaneously, without losing any marks etc. If
* forceit is TRUE, then the old file is not read in, and only internal info is
* written to the file. -- webb
*/
void
write_viminfo(file, forceit)
char_u *file;
int forceit;
{
FILE *fp_in = NULL; /* input viminfo file, if any */
FILE *fp_out = NULL; /* output viminfo file */
char_u *tempname = NULL; /* name of temp viminfo file */
struct stat st_new; /* stat() of potential new file */
char_u *wp;
#ifdef UNIX
int shortname = FALSE; /* use 8.3 file name */
mode_t umask_save;
struct stat st_old; /* stat() of existing viminfo file */
#endif
if (no_viminfo())
return;
file = viminfo_filename(file); /* may set to default if NULL */
file = vim_strsave(file); /* make a copy, don't want NameBuff */
if (file != NULL)
{
fp_in = fopen((char *)file, READBIN);
if (fp_in == NULL)
{
/* if it does exist, but we can't read it, don't try writing */
if (stat((char *)file, &st_new) == 0)
goto end;
#ifdef UNIX
/*
* For Unix we create the .viminfo non-accessible for others,
* because it may contain text from non-accessible documents.
*/
umask_save = umask(077);
#endif
fp_out = fopen((char *)file, WRITEBIN);
#ifdef UNIX
(void)umask(umask_save);
#endif
}
else
{
/*
* There is an existing viminfo file. Create a temporary file to
* write the new viminfo into, in the same directory as the
* existing viminfo file, which will be renamed later.
*/
#ifdef UNIX
/*
* For Unix we check the owner of the file. It's not very nice to
* overwrite a user's viminfo file after a "su root", with a
* viminfo file that the user can't read.
*/
st_old.st_dev = st_old.st_ino = 0;
st_old.st_mode = 0600;
if (stat((char *)file, &st_old) == 0 && getuid() &&
!(st_old.st_uid == getuid()
? (st_old.st_mode & 0200)
: (st_old.st_gid == getgid()
? (st_old.st_mode & 0020)
: (st_old.st_mode & 0002))))
{
int tt;
/* avoid a wait_return for this message, it's annoying */
tt = msg_didany;
EMSG2("Viminfo file is not writable: %s", file);
msg_didany = tt;
goto end;
}
#endif
/*
* Make tempname.
* May try twice: Once normal and once with shortname set, just in
* case somebody puts his viminfo file in an 8.3 filesystem.
*/
for (;;)
{
tempname = buf_modname(
#ifdef UNIX
shortname,
#else
# ifdef SHORT_FNAME
TRUE,
# else
# ifdef USE_GUI_WIN32
gui_is_win32s(),
# else
FALSE,
# endif
# endif
#endif
file,
#ifdef VMS
(char_u *)"-tmp",
#else
# ifdef RISCOS
(char_u *)"/tmp",
# else
(char_u *)".tmp",
# endif
#endif
FALSE);
if (tempname == NULL) /* out of memory */
break;
/*
* Check if tempfile already exists. Never overwrite an
* existing file!
*/
if (stat((char *)tempname, &st_new) == 0)
{
#ifdef UNIX
/*
* Check if tempfile is same as original file. May happen
* when modname gave the same file back. E.g. silly
* link, or file name-length reached. Try again with
* shortname set.
*/
if (!shortname && st_new.st_dev == st_old.st_dev &&
st_new.st_ino == st_old.st_ino)
{
vim_free(tempname);
tempname = NULL;
shortname = TRUE;
continue;
}
#endif
/*
* Try another name. Change one character, just before
* the extension. This should also work for an 8.3
* file name, when after adding the extension it still is
* the same file as the original.
*/
wp = tempname + STRLEN(tempname) - 5;
if (wp < gettail(tempname)) /* empty file name? */
wp = gettail(tempname);
for (*wp = 'z'; stat((char *)tempname, &st_new) == 0; --*wp)
{
/*
* They all exist? Must be something wrong! Don't
* write the viminfo file then.
*/
if (*wp == 'a')
{
vim_free(tempname);
tempname = NULL;
break;
}
}
}
break;
}
if (tempname != NULL)
{
fp_out = fopen((char *)tempname, WRITEBIN);
/*
* If we can't create in the same directory, try creating a
* "normal" temp file.
*/
if (fp_out == NULL)
{
vim_free(tempname);
if ((tempname = vim_tempname('o')) != NULL)
fp_out = fopen((char *)tempname, WRITEBIN);
}
#ifdef UNIX
/*
* Set file protection same as original file, but strip s-bit
* and make sure the owner can read/write it.
*/
if (fp_out != NULL)
{
(void)mch_setperm(tempname,
(long)((st_old.st_mode & 0777) | 0600));
/* this only works for root: */
(void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
}
#endif
}
}
}
/*
* Check if the new viminfo file can be written to.
*/
if (file == NULL || fp_out == NULL)
{
EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
fp_in == NULL ? file : tempname);
if (fp_in != NULL)
fclose(fp_in);
goto end;
}
if (p_verbose > 0)
smsg((char_u *)"Writing viminfo file \"%s\"", file);
viminfo_errcnt = 0;
do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
fclose(fp_out); /* errors are ignored !? */
if (fp_in != NULL)
{
fclose(fp_in);
/*
* In case of an error, don't overwrite the original viminfo file.
*/
if (viminfo_errcnt || vim_rename(tempname, file) == -1)
mch_remove(tempname);
}
end:
vim_free(file);
vim_free(tempname);
}
/*
* Get the viminfo file name to use.
* If "file" is given and not empty, use it (has already been expanded by
* cmdline functions).
* Otherwise use "-i file_name", value from 'viminfo' or the default, and
* expand environment variables.
*/
static char_u *
viminfo_filename(file)
char_u *file;
{
if (file == NULL || *file == NUL)
{
if (use_viminfo != NULL)
file = use_viminfo;
else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
{
#ifdef VIMINFO_FILE2
/* don't use $HOME when not defined (turned into "c:/"!). */
if (mch_getenv((char_u *)"HOME") == NULL)
{
/* don't use $VIM when not available. */
expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
if (STRCMP("$VIM", NameBuff) != 0) /* $VIM was expanded */
file = (char_u *)VIMINFO_FILE2;
else
file = (char_u *)VIMINFO_FILE;
}
else
#endif
file = (char_u *)VIMINFO_FILE;
}
expand_env(file, NameBuff, MAXPATHL);
return NameBuff;
}
return file;
}
/*
* do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
*/
static void
do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
FILE *fp_in;
FILE *fp_out;
int want_info;
int want_marks;
int force_read;
{
int count = 0;
int eof = FALSE;
char_u *line;
if ((line = alloc(LSIZE)) == NULL)
return;
if (fp_in != NULL)
{
if (want_info)
eof = read_viminfo_up_to_marks(line, fp_in, force_read,
fp_out != NULL);
else
/* Skip info, find start of marks */
while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
;
}
if (fp_out != NULL)
{
/* Write the info: */
fprintf(fp_out, "# This viminfo file was generated by vim\n");
fprintf(fp_out, "# You may edit it if you're careful!\n\n");
write_viminfo_search_pattern(fp_out);
write_viminfo_sub_string(fp_out);
write_viminfo_history(fp_out);
write_viminfo_registers(fp_out);
write_viminfo_filemarks(fp_out);
write_viminfo_bufferlist(fp_out);
count = write_viminfo_marks(fp_out);
}
if (fp_in != NULL && want_marks)
copy_viminfo_marks(line, fp_in, fp_out, count, eof);
vim_free(line);
}
/*
* read_viminfo_up_to_marks() -- Only called from do_viminfo(). Reads in the
* first part of the viminfo file which contains everything but the marks that
* are local to a file. Returns TRUE when end-of-file is reached. -- webb
*/
static int
read_viminfo_up_to_marks(line, fp, forceit, writing)
char_u *line;
FILE *fp;
int forceit;
int writing;
{
int eof;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -