📄 ops.c
字号:
}
/*
* display the contents of the yank registers
*/
void
do_dis(arg)
char_u *arg;
{
int i, n;
long j;
char_u *p;
struct yankreg *yb;
char_u name;
int attr;
if (arg != NULL && *arg == NUL)
arg = NULL;
attr = hl_attr(HLF_8);
/* Highlight title */
MSG_PUTS_TITLE("\n--- Registers ---");
for (i = -1; i < NUM_REGISTERS; ++i)
{
if (i == -1)
{
if (y_previous != NULL)
yb = y_previous;
else
yb = &(y_regs[0]);
}
else
yb = &(y_regs[i]);
name = get_register_name(i);
if (yb->y_array != NULL && (arg == NULL ||
vim_strchr(arg, name) != NULL))
{
msg_putchar('\n');
msg_putchar('"');
msg_putchar(name);
MSG_PUTS(" ");
n = (int)Columns - 6;
for (j = 0; j < yb->y_size && n > 1; ++j)
{
if (j)
{
MSG_PUTS_ATTR("^J", attr);
n -= 2;
}
for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
msg_outtrans_len(p, 1);
}
if (n > 1 && yb->y_type == MLINE)
MSG_PUTS_ATTR("^J", attr);
out_flush(); /* show one line at a time */
}
}
/*
* display last inserted text
*/
if ((p = get_last_insert()) != NULL &&
(arg == NULL || vim_strchr(arg, '.') != NULL))
{
MSG_PUTS("\n\". ");
dis_msg(p, TRUE);
}
/*
* display last command line
*/
if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL))
{
MSG_PUTS("\n\": ");
dis_msg(last_cmdline, FALSE);
}
/*
* display current file name
*/
if (curbuf->b_fname != NULL &&
(arg == NULL || vim_strchr(arg, '%') != NULL))
{
MSG_PUTS("\n\"% ");
dis_msg(curbuf->b_fname, FALSE);
}
/*
* display alternate file name
*/
if (arg == NULL || vim_strchr(arg, '%') != NULL)
{
char_u *fname;
linenr_t dummy;
if (buflist_name_nr(0, &fname, &dummy) != FAIL)
{
MSG_PUTS("\n\"# ");
dis_msg(fname, FALSE);
}
}
#ifdef WANT_EVAL
/*
* display last used expression
*/
if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL))
{
MSG_PUTS("\n\"= ");
dis_msg(expr_line, FALSE);
}
#endif
}
/*
* display a string for do_dis()
* truncate at end of screen line
*/
void
dis_msg(p, skip_esc)
char_u *p;
int skip_esc; /* if TRUE, ignore trailing ESC */
{
int n;
n = (int)Columns - 6;
while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
(n -= charsize(*p)) >= 0)
msg_outtrans_len(p++, 1);
}
/*
* join 'count' lines (minimal 2), including u_save()
*/
void
do_do_join(count, insert_space, redraw)
long count;
int insert_space;
int redraw; /* can redraw, curwin->w_wcol valid */
{
if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
(linenr_t)(curwin->w_cursor.lnum + count)) == FAIL)
return;
if (count > 10)
redraw = FALSE; /* don't redraw each small change */
while (--count > 0)
{
line_breakcheck();
if (got_int || do_join(insert_space, redraw) == FAIL)
{
beep_flush();
break;
}
}
redraw_later(VALID_TO_CURSCHAR);
/*
* Need to update the screen if the line where the cursor is became too
* long to fit on the screen.
*/
update_topline_redraw();
}
/*
* Join two lines at the cursor position.
* "redraw" is TRUE when the screen should be updated.
*
* return FAIL for failure, OK ohterwise
*/
int
do_join(insert_space, redraw)
int insert_space;
int redraw;
{
char_u *curr;
char_u *next;
char_u *newp;
int endcurr1, endcurr2;
int currsize; /* size of the current line */
int nextsize; /* size of the next line */
int spaces; /* number of spaces to insert */
int rows_to_del = 0;/* number of rows on screen to delete */
linenr_t t;
if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
return FAIL; /* can't join on last line */
if (redraw)
{
/*
* Check if we can really redraw: w_cline_row and w_cline_height need
* to be valid. Try to make them valid by calling may_validate_crow()
*/
if (may_validate_crow() == OK)
rows_to_del = plines_m(curwin->w_cursor.lnum,
curwin->w_cursor.lnum + 1);
else
redraw = FALSE;
}
curr = ml_get_curline();
currsize = STRLEN(curr);
endcurr1 = endcurr2 = NUL;
if (currsize > 0)
{
endcurr1 = *(curr + currsize - 1);
if (currsize > 1)
endcurr2 = *(curr + currsize - 2);
}
next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
spaces = 0;
if (insert_space)
{
next = skipwhite(next);
if (*next != ')' && currsize != 0 && endcurr1 != TAB)
{
/* don't add a space if the line is inding in a space */
if (endcurr1 == ' ')
endcurr1 = endcurr2;
else
++spaces;
/* extra space when 'joinspaces' set and line ends in '.' */
if ( p_js
&& (endcurr1 == '.'
|| (vim_strchr(p_cpo, CPO_JOINSP) == NULL
&& (endcurr1 == '?' || endcurr1 == '!'))))
++spaces;
}
}
nextsize = STRLEN(next);
newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
if (newp == NULL)
return FAIL;
/*
* Insert the next line first, because we already have that pointer.
* Curr has to be obtained again, because getting next will have
* invalidated it.
*/
mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
curr = ml_get_curline();
mch_memmove(newp, curr, (size_t)currsize);
copy_spaces(newp + currsize, (size_t)spaces);
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
#ifdef SYNTAX_HL
/* recompute syntax hl. for current line */
syn_changed(curwin->w_cursor.lnum);
#endif
/*
* Delete the following line. To do this we move the cursor there
* briefly, and then move it back. After del_lines() the cursor may
* have moved up (last line deleted), so the current lnum is kept in t.
*/
t = curwin->w_cursor.lnum;
++curwin->w_cursor.lnum;
del_lines(1L, FALSE, FALSE);
curwin->w_cursor.lnum = t;
/*
* the number of rows on the screen is reduced by the difference
* in number of rows of the two old lines and the one new line
*/
if (redraw)
{
rows_to_del -= plines(curwin->w_cursor.lnum);
if (rows_to_del > 0)
win_del_lines(curwin, curwin->w_cline_row + curwin->w_cline_height,
rows_to_del, TRUE, TRUE);
}
/*
* go to first character of the joined line
*/
if (currsize == 0)
curwin->w_cursor.col = 0;
else
{
curwin->w_cursor.col = currsize - 1;
(void)oneright();
}
changed();
return OK;
}
/*
* Return TRUE if the two comment leaders given are the same. The cursor is
* in the first line. White-space is ignored. Note that the whole of
* 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
*/
static int
same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
int leader1_len;
char_u *leader1_flags;
int leader2_len;
char_u *leader2_flags;
{
int idx1 = 0, idx2 = 0;
char_u *p;
char_u *line1;
char_u *line2;
if (leader1_len == 0)
return (leader2_len == 0);
/*
* If first leader has 'f' flag, the lines can be joined only if the
* second line does not have a leader.
* If first leader has 'e' flag, the lines can never be joined.
* If fist leader has 's' flag, the lines can only be joined if there is
* some text after it and the second line has the 'm' flag.
*/
if (leader1_flags != NULL)
{
for (p = leader1_flags; *p && *p != ':'; ++p)
{
if (*p == COM_FIRST)
return (leader2_len == 0);
if (*p == COM_END)
return FALSE;
if (*p == COM_START)
{
if (*(ml_get_curline() + leader1_len) == NUL)
return FALSE;
if (leader2_flags == NULL || leader2_len == 0)
return FALSE;
for (p = leader2_flags; *p && *p != ':'; ++p)
if (*p == COM_MIDDLE)
return TRUE;
return FALSE;
}
}
}
/*
* Get current line and next line, compare the leaders.
* The first line has to be saved, only one line can be locked at a time.
*/
line1 = vim_strsave(ml_get_curline());
if (line1 != NULL)
{
for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
;
line2 = ml_get(curwin->w_cursor.lnum + 1);
for (idx2 = 0; idx2 < leader2_len; ++idx2)
{
if (!vim_iswhite(line2[idx2]))
{
if (line1[idx1++] != line2[idx2])
break;
}
else
while (vim_iswhite(line1[idx1]))
++idx1;
}
vim_free(line1);
}
return (idx2 == leader2_len && idx1 == leader1_len);
}
/*
* implementation of the format operator 'gq'
*/
void
op_format(oap)
OPARG *oap;
{
long old_line_count = curbuf->b_ml.ml_line_count;
int is_not_par; /* current line not part of parag. */
int next_is_not_par; /* next line not part of paragraph */
int is_end_par; /* at end of paragraph */
int prev_is_end_par = FALSE;/* prev. line not part of parag. */
int leader_len = 0; /* leader len of current line */
int next_leader_len; /* leader len of next line */
char_u *leader_flags = NULL; /* flags for leader of current line */
char_u *next_leader_flags; /* flags for leader of next line */
int advance = TRUE;
int second_indent = -1;
int do_second_indent;
int first_par_line = TRUE;
int smd_save;
long count;
int need_set_indent = TRUE; /* set indent of next paragraph */
int force_format = FALSE;
int max_len;
int screenlines = -1;
if (u_save((linenr_t)(oap->start.lnum - 1),
(linenr_t)(oap->end.lnum + 1)) == FAIL)
return;
/* When formatting less than a screenfull, will try to speed up redrawing
* by inserting/deleting screen lines */
if (oap->end.lnum - oap->start.lnum < Rows)
screenlines = plines_m(oap->start.lnum, oap->end.lnum);
/* length of a line to force formatting: 3 * 'tw' */
max_len = comp_textwidth(TRUE) * 3;
/* Set '[ mark at the start of the formatted area */
curbuf->b_op_start = oap->start;
/* check for 'q' and '2' in 'formatoptions' */
fo_do_comments = has_format_option(FO_Q_COMS);
do_second_indent = has_format_option(FO_Q_SECOND);
/*
* Get info about the previous and current line.
*/
if (curwin->w_cursor.lnum > 1)
is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1,
&leader_len, &leader_flags);
else
is_not_par = TRUE;
next_is_not_par = fmt_check_par(curwin->w_cursor.lnum,
&next_leader_len, &next_leader_flags);
is_end_par = (is_not_par || next_is_not_par);
curwin->w_cursor.lnum--;
for (count = oap->line_count; count > 0 && !got_int; --count)
{
/*
* Advance to next paragraph.
*/
if (advance)
{
curwin->w_cursor.lnum++;
prev_is_end_par = is_end_par;
is_not_par = next_is_not_par;
leader_len = next_leader_len;
leader_flags = next_leader_flags;
}
/*
* The last line to be formatted.
*/
if (count == 1)
{
next_is_not_par = TRUE;
next_leader_len = 0;
next_leader_flags = NULL;
}
else
next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1,
&next_leader_len, &next_leader_flags);
advance = TRUE;
is_end_par = (is_not_par || next_is_not_par);
/*
* Skip lines that are not in a paragraph.
*/
if (!is_not_par)
{
/*
* For the first line of a paragraph, check indent of second line.
* Don't do this for comments and empty lines.
*/
if (first_par_line
&& do_second_indent
&& prev_is_end_par
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
&& leader_len == 0
&& next_leader_len == 0
&& !lineempty(curwin->w_cursor.lnum + 1))
second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
/*
* When the comment leader changes, it's the end of the paragraph.
*/
if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
|| !same_leader(leader_len, leader_flags,
next_leader_len, next_leader_flags))
is_end_par = TRUE;
/*
* If we have got to the end of a paragraph, or the line is
* getting long, format it.
*/
if (is_end_par || force_format)
{
if (need_set_indent)
/* replace indent in first line with minimal number of
* tabs and spaces, according to current options */
set_indent(get_indent(), TRUE);
/* put cursor on last non-space */
coladvance(MAXCOL);
while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
dec_cursor();
#ifdef SYNTAX_HL
/* recompute syntax hl., starting with current line */
syn_changed(curwin->w_cursor.lnum);
#endif
/* do the formatting, without 'showmode' */
State = INSERT; /* for open_line() */
smd_save = p_smd;
p_smd = FALSE;
insertchar(NUL, TRUE, second_indent, FALSE);
State = NORMAL;
p_smd = smd_save;
second_indent = -1;
/* at end of par.: need to set indent of next par. */
need_set_indent = is_end_par;
if (is_end_par)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -