⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex_cmds.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
    prepare_viminfo_history(forceit ? 9999 : 0);
    eof = vim_fgets(line, LSIZE, fp);
    while (!eof && line[0] != '>')
    {
	switch (line[0])
	{
		/* Characters reserved for future expansion, ignored now */
	    case '+': /* "+40 /path/dir file", for running vim without args */
	    case '|': /* to be defined */
	    case '-': /* to be defined */
	    case '!': /* to be defined */
	    case '^': /* to be defined */
	    case '*': /* to be defined */
	    case '<': /* to be defined */
		/* A comment */
	    case NUL:
	    case '\r':
	    case '\n':
	    case '#':
		eof = vim_fgets(line, LSIZE, fp);
		break;
	    case '%': /* entry for buffer list */
		eof = read_viminfo_bufferlist(line, fp, writing);
		break;
	    case '"':
		eof = read_viminfo_register(line, fp, forceit);
		break;
	    case '/':	    /* Search string */
	    case '&':	    /* Substitute search string */
	    case '~':	    /* Last search string, followed by '/' or '&' */
		eof = read_viminfo_search_pattern(line, fp, forceit);
		break;
	    case '$':
		eof = read_viminfo_sub_string(line, fp, forceit);
		break;
	    case ':':
	    case '?':
	    case '=':
	    case '@':
		eof = read_viminfo_history(line, fp);
		break;
	    case '\'':
		/* How do we have a file mark when the file is not in the
		 * buffer list?
		 */
		eof = read_viminfo_filemark(line, fp, forceit);
		break;
	    default:
		if (viminfo_error("Illegal starting char", line))
		    eof = TRUE;
		else
		    eof = vim_fgets(line, LSIZE, fp);
		break;
	}
    }
    finish_viminfo_history();
    return eof;
}

/*
 * check string read from viminfo file
 * remove '\n' at the end of the line
 * - replace CTRL-V CTRL-V with CTRL-V
 * - replace CTRL-V 'n'    with '\n'
 */
    void
viminfo_readstring(p)
    char_u	*p;
{
    while (*p != NUL && *p != '\n')
    {
	if (*p == Ctrl('V'))
	{
	    if (p[1] == 'n')
		p[0] = '\n';
	    mch_memmove(p + 1, p + 2, STRLEN(p));
	}
	++p;
    }
    *p = NUL;
}

/*
 * write string to viminfo file
 * - replace CTRL-V with CTRL-V CTRL-V
 * - replace '\n'   with CTRL-V 'n'
 * - add a '\n' at the end
 */
    void
viminfo_writestring(fd, p)
    FILE    *fd;
    char_u  *p;
{
    int	    c;

    while ((c = *p++) != NUL)
    {
	if (c == Ctrl('V') || c == '\n')
	{
	    putc(Ctrl('V'), fd);
	    if (c == '\n')
		c = 'n';
	}
	putc(c, fd);
    }
    putc('\n', fd);
}
#endif /* VIMINFO */

/*
 * Implementation of ":fixdel", also used by get_stty().
 *  <BS>    resulting <Del>
 *   ^?		^H
 * not ^?	^?
 */
    void
do_fixdel()
{
    char_u  *p;

    p = find_termcode((char_u *)"kb");
    add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ?
					 (char_u *)"\010" : (char_u *)"\177");
}

    void
print_line_no_prefix(lnum, use_number)
    linenr_t	lnum;
    int		use_number;
{
    char_u	numbuf[20];

    if (curwin->w_p_nu || use_number)
    {
	sprintf((char *)numbuf, "%7ld ", (long)lnum);
	msg_puts_attr(numbuf, hl_attr(HLF_N));	/* Highlight line nrs */
    }
    msg_prt_line(ml_get(lnum));
}

/*
 * Print a text line.  Also in silent mode ("ex -s").
 */
    void
print_line(lnum, use_number)
    linenr_t	lnum;
    int		use_number;
{
    int		save_silent = silent_mode;

    silent_mode = FALSE;
    msg_start();
    print_line_no_prefix(lnum, use_number);
    if (save_silent)
    {
	msg_putchar('\n');
	cursor_on();		/* msg_start() switches it off */
	out_flush();
	silent_mode = save_silent;
    }
}

/*
 * Implementation of ":file[!] [fname]".
 */
    void
do_file(arg, forceit)
    char_u  *arg;
    int	    forceit;
{
    char_u	*fname, *sfname, *xfname;
    BUF		*buf;

    if (*arg != NUL)
    {
#ifdef AUTOCMD
	buf = curbuf;
	apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
	/* buffer changed, don't change name now */
	if (buf != curbuf)
	    return;
#endif
	/*
	 * The name of the current buffer will be changed.
	 * A new buffer entry needs to be made to hold the old
	 * file name, which will become the alternate file name.
	 */
	fname = curbuf->b_ffname;
	sfname = curbuf->b_sfname;
	xfname = curbuf->b_fname;
	curbuf->b_ffname = NULL;
	curbuf->b_sfname = NULL;
	if (setfname(arg, NULL, TRUE) == FAIL)
	{
	    curbuf->b_ffname = fname;
	    curbuf->b_sfname = sfname;
	    return;
	}
	curbuf->b_notedited = TRUE;
	buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, FALSE);
	if (buf != NULL)
	    curwin->w_alt_fnum = buf->b_fnum;
	vim_free(fname);
	vim_free(sfname);
#ifdef AUTOCMD
	apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
#endif
    }
    /* print full file name if :cd used */
    fileinfo(FALSE, FALSE, forceit);
}


/*
 * Do the Ex mode :insert and :append commands.
 * "getline" can be NULL, in which case a line is obtained from the user.
 */
    void
do_append(lnum, getline, cookie)
    linenr_t	lnum;
    char_u	*(*getline) __ARGS((int, void *, int));
    void	*cookie;		/* argument for getline() */
{
    char_u	*theline;
    int		did_undo = FALSE;
    int		lfirst = lnum;

    State = INSERT;		    /* behave like in Insert mode */
    while (1)
    {
	msg_scroll = TRUE;
	need_wait_return = FALSE;
	if (getline == NULL)
	    theline = getcmdline(NUL, 0L, 0);
	else
	    theline = getline(NUL, cookie, 0);
	lines_left = Rows - 1;
	if (theline == NULL || (theline[0] == '.' && theline[1] == NUL))
	    break;

	if (!did_undo && u_save(lnum, lnum + 1) == FAIL)
	    break;
	did_undo = TRUE;
	mark_adjust(lnum + 1, (linenr_t)MAXLNUM, 1L, 0L);
	ml_append(lnum, theline, (colnr_t)0, FALSE);
	changed();

	vim_free(theline);
	++lnum;
    }
    State = NORMAL;

    /* "start" is set to lfirst+1 unless that position is invalid (when
     * lfirst pointed to the end of the buffer and nothig was appended)
     * "end" is set to lnum when something has been appended, otherwise
     * it is the same than "start"  -- Acevedo */
    curbuf->b_op_start.lnum = (lfirst < curbuf->b_ml.ml_line_count) ?
	lfirst + 1 : curbuf->b_ml.ml_line_count;
    curbuf->b_op_end.lnum = (lfirst < lnum) ? lnum : curbuf->b_op_start.lnum;
    curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
    curwin->w_cursor.lnum = lnum;
    check_cursor_lnum();
    beginline(BL_SOL | BL_FIX);
    changed_line_abv_curs();
    invalidate_botline();

    dont_wait_return = TRUE;	    /* don't use wait_return() now */
    need_wait_return = FALSE;
    update_screen(NOT_VALID);
}

/*
 * Do the Ex mode :change command.
 * "getline" can be NULL, in which case a line is obtained from the user.
 */
    void
do_change(start, end, getline, cookie)
    linenr_t	start;
    linenr_t	end;
    char_u	*(*getline) __ARGS((int, void *, int));
    void	*cookie;		/* argument for getline() */
{
    if (end >= start && u_save(start - 1, end + 1) == FAIL)
	return;

    mark_adjust(start, end, (long)MAXLNUM, (long)(start - end - 1));
    while (end >= start)
    {
	if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to delete */
	    break;
	ml_delete(start, FALSE);
	changed();
	end--;
    }
    do_append(start - 1, getline, cookie);
}

    void
do_z(line, arg)
    linenr_t	line;
    char_u	*arg;
{
    char_u	*x;
    int		bigness = curwin->w_height - 3;
    char_u	kind;
    int		minus = 0;
    linenr_t	start, end, curs, i;

    if (bigness < 1)
	bigness = 1;

    x = arg;
    if (*x == '-' || *x == '+' || *x == '=' || *x == '^' || *x == '.')
	x++;

    if (*x != 0)
    {
	if (!isdigit(*x))
	{
	    EMSG("non-numeric argument to :z");
	    return;
	}
	else
	    bigness = atoi((char *)x);
    }

    kind = *arg;

    switch (kind)
    {
	case '-':
	    start = line - bigness;
	    end = line;
	    curs = line;
	    break;

	case '=':
	    start = line - bigness / 2 + 1;
	    end = line + bigness / 2 - 1;
	    curs = line;
	    minus = 1;
	    break;

	case '^':
	    start = line - bigness * 2;
	    end = line - bigness;
	    curs = line - bigness;
	    break;

	case '.':
	    start = line - bigness / 2;
	    end = line + bigness / 2;
	    curs = end;
	    break;

	default:  /* '+' */
	    start = line;
	    end = line + bigness;
	    curs = end;
	    break;
    }

    if (start < 1)
	start = 1;

    if (end > curbuf->b_ml.ml_line_count)
	end = curbuf->b_ml.ml_line_count;

    if (curs > curbuf->b_ml.ml_line_count)
	curs = curbuf->b_ml.ml_line_count;

    for (i = start; i <= end; i++)
    {
	int j;

	if (minus && (i == line))
	{
	    msg_putchar('\n');

	    for (j = 1; j < Columns; j++)
		msg_putchar('-');
	}

	print_line(i, FALSE);

	if (minus && (i == line))
	{
	    msg_putchar('\n');

	    for (j = 1; j < Columns; j++)
		msg_putchar('-');
	}
    }

    curwin->w_cursor.lnum = curs;
}

/*
 * Check if the restricted flag is set.
 * If so, give an error message and return TRUE.
 * Otherwise, return FALSE.
 */
    int
check_restricted()
{
    if (restricted)
    {
	EMSG("Shell commands not allowed in rvim");
	return TRUE;
    }
    return FALSE;
}

/*
 * Check if the secure flag is set (.exrc or .vimrc in current directory).
 * If so, give an error message and return TRUE.
 * Otherwise, return FALSE.
 */
    int
check_secure()
{
    if (secure)
    {
	secure = 2;
	emsg(e_curdir);
	return TRUE;
    }
    return FALSE;
}

static char_u	    *old_sub = NULL;	/* previous substitute pattern */

/*
 * When ":global" is used to number of substitutions and changed lines is
 * accumulated until it's finished.
 */
static long	    sub_nsubs;	    /* total number of substitutions */
static linenr_t	    sub_nlines;	    /* total number of lines changed */

/* do_sub()
 *
 * Perform a substitution from line eap->line1 to line eap->line2 using the
 * command pointed to by eap->arg which should be of the form:
 *
 * /pattern/substitution/{flags}
 *
 * The usual escapes are supported as described in the regexp docs.
 */
    void
do_sub(eap)
    EXARG	*eap;
{
    linenr_t	    lnum;
    long	    i;
    char_u	   *ptr;
    char_u	   *old_line;
    vim_regexp	   *prog;
    static int	    do_all = FALSE;	/* do multiple substitutions per line */
    static int	    do_ask = FALSE;	/* ask for confirmation */
    int		    do_error = TRUE;	/* if false, ignore errors */
    int		    do_print = FALSE;	/* print last line with subst. */
    int		    do_ic = 0;		/* ignore case flag */
    char_u	   *pat = NULL, *sub = NULL;	/* init for GCC */
    int		    delimiter;
    int		    sublen;
    int		    got_quit = FALSE;
    int		    got_match = FALSE;
    int		    temp;
    int		    which_pat;
    char_u	    *cmd;
    int		    save_reg_ic;
    int		    save_State;

    cmd = eap->arg;
    if (!global_busy)
    {
	sub_nsubs = 0;
	sub_nlines = 0;
    }

#ifdef FKMAP		    /* reverse the flow of the Farsi characters */
    if (p_altkeymap && curwin->w_p_rl)
	lrF_sub(cmd);
#endif

    if (eap->cmdidx == CMD_tilde)
	which_pat = RE_LAST;	/* use last used regexp */
    else
	which_pat = RE_SUBST;	/* use last substitute regexp */

				/* new pattern and substitution */
    if (eap->cmd[0] == 's' && *cmd != NUL && !vim_iswhite(*cmd)
		    && vim_strchr((char_u *)"0123456789gcr|\"", *cmd) == NULL)
    {
				/* don't accept alphanumeric for separator */
	if (isalpha(*cmd))
	{
	    EMSG("Regular expressions can't be delimited by letters");
	    return;
	}
	/*
	 * undocumented vi feature:
	 *  "\/sub/" and "\?sub?" use last used search pattern (almost like
	 *  //sub/r).  "\&sub&" use last substitute pattern (like //sub/).
	 */
	if (*cmd == '\\')
	{
	    ++cmd;
	    if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
	    {
		emsg(e_backslash);
		return;
	    }
	    if (*cmd != '&')
		which_pat = RE_SEARCH;	    /* use last '/' pattern */
	    pat = (char_u *)"";		    /* empty search pattern */
	    delimiter = *cmd++;		    /* remember delimiter character */
	}
	else		/* find the end of the regexp */
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -