vim-patch:8.2.0674: some source files are too big (#19959)

Problem:    Some source files are too big.
Solution:   Move text formatting functions to a new file. (Yegappan
            Lakshmanan, closes vim/vim#6021)
11abd09521

Cherry-pick set_can_cindent() from patch 8.1.2062.
Cherry-pick global old_indent from patch 8.2.2127.
This commit is contained in:
zeertzjq
2022-08-26 22:37:20 +08:00
committed by GitHub
parent 2ecb4076df
commit 0b72e23bf1
11 changed files with 1176 additions and 1159 deletions

View File

@@ -56,6 +56,7 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
#include "nvim/textformat.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -108,8 +109,6 @@ static int did_restart_edit; // "restart_edit" when calling edit()
static bool can_cindent; // may do cindenting on this line
static int old_indent = 0; // for ^^D command in insert mode
static int revins_on; // reverse insert mode on
static int revins_chars; // how much to skip after edit
static int revins_legal; // was the last char 'legal'?
@@ -119,8 +118,6 @@ static bool ins_need_undo; // call u_save() before inserting a
// char. Set when edit() is called.
// after that arrow_used is used.
static bool did_add_space = false; // auto_format() added an extra space
// under the cursor
static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo
// for the next left/right cursor key
@@ -1561,7 +1558,7 @@ void display_dollar(colnr_T col)
* Call this function before moving the cursor from the normal insert position
* in insert mode.
*/
static void undisplay_dollar(void)
void undisplay_dollar(void)
{
if (dollar_vcol >= 0) {
dollar_vcol = -1;
@@ -2012,9 +2009,6 @@ static void insert_special(int c, int allow_modmask, int ctrlv)
*/
#define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
#define WHITECHAR(cc) (ascii_iswhite(cc) \
&& !utf_iscomposing(utf_ptr2char((char *)get_cursor_pos_ptr() + 1)))
///
/// "flags": INSCHAR_FORMAT - force formatting
/// INSCHAR_CTRLV - char typed just after CTRL-V
@@ -2213,597 +2207,6 @@ void insertchar(int c, int flags, int second_indent)
}
}
/// Format text at the current insert position.
///
/// If the INSCHAR_COM_LIST flag is present, then the value of second_indent
/// will be the comment leader length sent to open_line().
///
/// @param c character to be inserted (can be NUL)
static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c)
{
int cc;
int save_char = NUL;
bool haveto_redraw = false;
const bool fo_ins_blank = has_format_option(FO_INS_BLANK);
const bool fo_multibyte = has_format_option(FO_MBYTE_BREAK);
const bool fo_rigor_tw = has_format_option(FO_RIGOROUS_TW);
const bool fo_white_par = has_format_option(FO_WHITE_PAR);
bool first_line = true;
colnr_T leader_len;
bool no_leader = false;
int do_comments = (flags & INSCHAR_DO_COM);
int has_lbr = curwin->w_p_lbr;
// make sure win_lbr_chartabsize() counts correctly
curwin->w_p_lbr = false;
/*
* When 'ai' is off we don't want a space under the cursor to be
* deleted. Replace it with an 'x' temporarily.
*/
if (!curbuf->b_p_ai
&& !(State & VREPLACE_FLAG)) {
cc = gchar_cursor();
if (ascii_iswhite(cc)) {
save_char = cc;
pchar_cursor('x');
}
}
/*
* Repeat breaking lines, until the current line is not too long.
*/
while (!got_int) {
int startcol; // Cursor column at entry
int wantcol; // column at textwidth border
int foundcol; // column for start of spaces
int end_foundcol = 0; // column for start of word
colnr_T len;
colnr_T virtcol;
int orig_col = 0;
char_u *saved_text = NULL;
colnr_T col;
colnr_T end_col;
bool did_do_comment = false;
virtcol = get_nolist_virtcol()
+ char2cells(c != NUL ? c : gchar_cursor());
if (virtcol <= (colnr_T)textwidth) {
break;
}
if (no_leader) {
do_comments = false;
} else if (!(flags & INSCHAR_FORMAT)
&& has_format_option(FO_WRAP_COMS)) {
do_comments = true;
}
// Don't break until after the comment leader
if (do_comments) {
char_u *line = get_cursor_line_ptr();
leader_len = get_leader_len((char *)line, NULL, false, true);
if (leader_len == 0 && curbuf->b_p_cin) {
// Check for a line comment after code.
int comment_start = check_linecomment(line);
if (comment_start != MAXCOL) {
leader_len = get_leader_len((char *)line + comment_start, NULL, false, true);
if (leader_len != 0) {
leader_len += comment_start;
}
}
}
} else {
leader_len = 0;
}
// If the line doesn't start with a comment leader, then don't
// start one in a following broken line. Avoids that a %word
// moved to the start of the next line causes all following lines
// to start with %.
if (leader_len == 0) {
no_leader = true;
}
if (!(flags & INSCHAR_FORMAT)
&& leader_len == 0
&& !has_format_option(FO_WRAP)) {
break;
}
if ((startcol = curwin->w_cursor.col) == 0) {
break;
}
// find column of textwidth border
coladvance((colnr_T)textwidth);
wantcol = curwin->w_cursor.col;
curwin->w_cursor.col = startcol;
foundcol = 0;
int skip_pos = 0;
/*
* Find position to break at.
* Stop at first entered white when 'formatoptions' has 'v'
*/
while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
|| (flags & INSCHAR_FORMAT)
|| curwin->w_cursor.lnum != Insstart.lnum
|| curwin->w_cursor.col >= Insstart.col) {
if (curwin->w_cursor.col == startcol && c != NUL) {
cc = c;
} else {
cc = gchar_cursor();
}
if (WHITECHAR(cc)) {
// remember position of blank just before text
end_col = curwin->w_cursor.col;
// find start of sequence of blanks
int wcc = 0; // counter for whitespace chars
while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) {
dec_cursor();
cc = gchar_cursor();
// Increment count of how many whitespace chars in this
// group; we only need to know if it's more than one.
if (wcc < 2) {
wcc++;
}
}
if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) {
break; // only spaces in front of text
}
// Don't break after a period when 'formatoptions' has 'p' and
// there are less than two spaces.
if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2) {
continue;
}
// Don't break until after the comment leader
if (curwin->w_cursor.col < leader_len) {
break;
}
if (has_format_option(FO_ONE_LETTER)) {
// do not break after one-letter words
if (curwin->w_cursor.col == 0) {
break; // one-letter word at begin
}
// do not break "#a b" when 'tw' is 2
if (curwin->w_cursor.col <= leader_len) {
break;
}
col = curwin->w_cursor.col;
dec_cursor();
cc = gchar_cursor();
if (WHITECHAR(cc)) {
continue; // one-letter, continue
}
curwin->w_cursor.col = col;
}
inc_cursor();
end_foundcol = end_col + 1;
foundcol = curwin->w_cursor.col;
if (curwin->w_cursor.col <= (colnr_T)wantcol) {
break;
}
} else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte) {
int ncc;
bool allow_break;
// Break after or before a multi-byte character.
if (curwin->w_cursor.col != startcol) {
// Don't break until after the comment leader
if (curwin->w_cursor.col < leader_len) {
break;
}
col = curwin->w_cursor.col;
inc_cursor();
ncc = gchar_cursor();
allow_break = utf_allow_break(cc, ncc);
// If we have already checked this position, skip!
if (curwin->w_cursor.col != skip_pos && allow_break) {
foundcol = curwin->w_cursor.col;
end_foundcol = foundcol;
if (curwin->w_cursor.col <= (colnr_T)wantcol) {
break;
}
}
curwin->w_cursor.col = col;
}
if (curwin->w_cursor.col == 0) {
break;
}
ncc = cc;
col = curwin->w_cursor.col;
dec_cursor();
cc = gchar_cursor();
if (WHITECHAR(cc)) {
continue; // break with space
}
// Don't break until after the comment leader.
if (curwin->w_cursor.col < leader_len) {
break;
}
curwin->w_cursor.col = col;
skip_pos = curwin->w_cursor.col;
allow_break = utf_allow_break(cc, ncc);
// Must handle this to respect line break prohibition.
if (allow_break) {
foundcol = curwin->w_cursor.col;
end_foundcol = foundcol;
}
if (curwin->w_cursor.col <= (colnr_T)wantcol) {
const bool ncc_allow_break = utf_allow_break_before(ncc);
if (allow_break) {
break;
}
if (!ncc_allow_break && !fo_rigor_tw) {
// Enable at most 1 punct hang outside of textwidth.
if (curwin->w_cursor.col == startcol) {
// We are inserting a non-breakable char, postpone
// line break check to next insert.
end_foundcol = foundcol = 0;
break;
}
// Neither cc nor ncc is NUL if we are here, so
// it's safe to inc_cursor.
col = curwin->w_cursor.col;
inc_cursor();
cc = ncc;
ncc = gchar_cursor();
// handle insert
ncc = (ncc != NUL) ? ncc : c;
allow_break = utf_allow_break(cc, ncc);
if (allow_break) {
// Break only when we are not at end of line.
end_foundcol = foundcol = ncc == NUL? 0 : curwin->w_cursor.col;
break;
}
curwin->w_cursor.col = col;
}
}
}
if (curwin->w_cursor.col == 0) {
break;
}
dec_cursor();
}
if (foundcol == 0) { // no spaces, cannot break line
curwin->w_cursor.col = startcol;
break;
}
// Going to break the line, remove any "$" now.
undisplay_dollar();
// Offset between cursor position and line break is used by replace
// stack functions. MODE_VREPLACE does not use this, and backspaces
// over the text instead.
if (State & VREPLACE_FLAG) {
orig_col = startcol; // Will start backspacing from here
} else {
replace_offset = startcol - end_foundcol;
}
/*
* adjust startcol for spaces that will be deleted and
* characters that will remain on top line
*/
curwin->w_cursor.col = foundcol;
while ((cc = gchar_cursor(), WHITECHAR(cc))
&& (!fo_white_par || curwin->w_cursor.col < startcol)) {
inc_cursor();
}
startcol -= curwin->w_cursor.col;
if (startcol < 0) {
startcol = 0;
}
if (State & VREPLACE_FLAG) {
// In MODE_VREPLACE state, we will backspace over the text to be
// wrapped, so save a copy now to put on the next line.
saved_text = vim_strsave(get_cursor_pos_ptr());
curwin->w_cursor.col = orig_col;
saved_text[startcol] = NUL;
// Backspace over characters that will move to the next line
if (!fo_white_par) {
backspace_until_column(foundcol);
}
} else {
// put cursor after pos. to break line
if (!fo_white_par) {
curwin->w_cursor.col = foundcol;
}
}
/*
* Split the line just before the margin.
* Only insert/delete lines, but don't really redraw the window.
*/
open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
+ (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
+ (do_comments ? OPENLINE_DO_COM : 0)
+ OPENLINE_FORMAT
+ ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0),
((flags & INSCHAR_COM_LIST) ? second_indent : old_indent),
&did_do_comment);
if (!(flags & INSCHAR_COM_LIST)) {
old_indent = 0;
}
// If a comment leader was inserted, may also do this on a following
// line.
if (did_do_comment) {
no_leader = false;
}
replace_offset = 0;
if (first_line) {
if (!(flags & INSCHAR_COM_LIST)) {
// This section is for auto-wrap of numeric lists. When not
// in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
// flag will be set and open_line() will handle it (as seen
// above). The code here (and in get_number_indent()) will
// recognize comments if needed...
if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) {
second_indent = get_number_indent(curwin->w_cursor.lnum - 1);
}
if (second_indent >= 0) {
if (State & VREPLACE_FLAG) {
change_indent(INDENT_SET, second_indent, false, NUL, true);
} else if (leader_len > 0 && second_indent - leader_len > 0) {
int padding = second_indent - leader_len;
// We started at the first_line of a numbered list
// that has a comment. the open_line() function has
// inserted the proper comment leader and positioned
// the cursor at the end of the split line. Now we
// add the additional whitespace needed after the
// comment leader for the numbered list.
for (int i = 0; i < padding; i++) {
ins_str((char_u *)" ");
}
changed_bytes(curwin->w_cursor.lnum, leader_len);
} else {
(void)set_indent(second_indent, SIN_CHANGED);
}
}
}
first_line = false;
}
if (State & VREPLACE_FLAG) {
// In MODE_VREPLACE state we have backspaced over the text to be
// moved, now we re-insert it into the new line.
ins_bytes((char *)saved_text);
xfree(saved_text);
} else {
/*
* Check if cursor is not past the NUL off the line, cindent
* may have added or removed indent.
*/
curwin->w_cursor.col += startcol;
len = (colnr_T)STRLEN(get_cursor_line_ptr());
if (curwin->w_cursor.col > len) {
curwin->w_cursor.col = len;
}
}
haveto_redraw = true;
can_cindent = true;
// moved the cursor, don't autoindent or cindent now
did_ai = false;
did_si = false;
can_si = false;
can_si_back = false;
line_breakcheck();
}
if (save_char != NUL) { // put back space after cursor
pchar_cursor((char_u)save_char);
}
curwin->w_p_lbr = has_lbr;
if (!format_only && haveto_redraw) {
update_topline(curwin);
redraw_curbuf_later(UPD_VALID);
}
}
/// Called after inserting or deleting text: When 'formatoptions' includes the
/// 'a' flag format from the current line until the end of the paragraph.
/// Keep the cursor at the same position relative to the text.
/// The caller must have saved the cursor line for undo, following ones will be
/// saved here.
///
/// @param trailblank when true also format with trailing blank
/// @param prev_line may start in previous line
void auto_format(bool trailblank, bool prev_line)
{
pos_T pos;
colnr_T len;
char_u *old;
char_u *new, *pnew;
int wasatend;
int cc;
if (!has_format_option(FO_AUTO)) {
return;
}
pos = curwin->w_cursor;
old = get_cursor_line_ptr();
// may remove added space
check_auto_format(false);
// Don't format in Insert mode when the cursor is on a trailing blank, the
// user might insert normal text next. Also skip formatting when "1" is
// in 'formatoptions' and there is a single character before the cursor.
// Otherwise the line would be broken and when typing another non-white
// next they are not joined back together.
wasatend = (pos.col == (colnr_T)STRLEN(old));
if (*old != NUL && !trailblank && wasatend) {
dec_cursor();
cc = gchar_cursor();
if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
&& has_format_option(FO_ONE_LETTER)) {
dec_cursor();
}
cc = gchar_cursor();
if (WHITECHAR(cc)) {
curwin->w_cursor = pos;
return;
}
curwin->w_cursor = pos;
}
// With the 'c' flag in 'formatoptions' and 't' missing: only format
// comments.
if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
&& get_leader_len((char *)old, NULL, false, true) == 0) {
return;
}
/*
* May start formatting in a previous line, so that after "x" a word is
* moved to the previous line if it fits there now. Only when this is not
* the start of a paragraph.
*/
if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) {
curwin->w_cursor.lnum--;
if (u_save_cursor() == FAIL) {
return;
}
}
/*
* Do the formatting and restore the cursor position. "saved_cursor" will
* be adjusted for the text formatting.
*/
saved_cursor = pos;
format_lines((linenr_T) - 1, false);
curwin->w_cursor = saved_cursor;
saved_cursor.lnum = 0;
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
// "cannot happen"
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
coladvance(MAXCOL);
} else {
check_cursor_col();
}
// Insert mode: If the cursor is now after the end of the line while it
// previously wasn't, the line was broken. Because of the rule above we
// need to add a space when 'w' is in 'formatoptions' to keep a paragraph
// formatted.
if (!wasatend && has_format_option(FO_WHITE_PAR)) {
new = get_cursor_line_ptr();
len = (colnr_T)STRLEN(new);
if (curwin->w_cursor.col == len) {
pnew = vim_strnsave(new, (size_t)len + 2);
pnew[len] = ' ';
pnew[len + 1] = NUL;
ml_replace(curwin->w_cursor.lnum, (char *)pnew, false);
// remove the space later
did_add_space = true;
} else {
// may remove added space
check_auto_format(false);
}
}
check_cursor();
}
/// When an extra space was added to continue a paragraph for auto-formatting,
/// delete it now. The space must be under the cursor, just after the insert
/// position.
///
/// @param end_insert true when ending Insert mode
static void check_auto_format(bool end_insert)
{
int c = ' ';
int cc;
if (did_add_space) {
cc = gchar_cursor();
if (!WHITECHAR(cc)) {
// Somehow the space was removed already.
did_add_space = false;
} else {
if (!end_insert) {
inc_cursor();
c = gchar_cursor();
dec_cursor();
}
if (c != NUL) {
// The space is no longer at the end of the line, delete it.
del_char(false);
did_add_space = false;
}
}
}
}
/// Find out textwidth to be used for formatting:
/// if 'textwidth' option is set, use it
/// else if 'wrapmargin' option is set, use curwin->w_width_inner-'wrapmargin'
/// if invalid value, use 0.
/// Set default to window width (maximum 79) for "gq" operator.
///
/// @param ff force formatting (for "gq" command)
int comp_textwidth(bool ff)
{
int textwidth = (int)curbuf->b_p_tw;
if (textwidth == 0 && curbuf->b_p_wm) {
// The width is the window width minus 'wrapmargin' minus all the
// things that add to the margin.
textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm;
if (cmdwin_type != 0) {
textwidth -= 1;
}
textwidth -= win_fdccol_count(curwin);
textwidth -= win_signcol_count(curwin);
if (curwin->w_p_nu || curwin->w_p_rnu) {
textwidth -= 8;
}
}
if (textwidth < 0) {
textwidth = 0;
}
if (ff && textwidth == 0) {
textwidth = curwin->w_width_inner - 1;
if (textwidth > 79) {
textwidth = 79;
}
}
return textwidth;
}
/*
* Put a character in the redo buffer, for when just after a CTRL-V.
*/
@@ -5665,6 +5068,11 @@ bool get_can_cindent(void)
return can_cindent;
}
void set_can_cindent(bool val)
{
can_cindent = val;
}
/// Trigger "event" and take care of fixing undo.
int ins_apply_autocmds(event_T event)
{