Hello Bram, I'm sending the fixed set of patches. It contains three parts now:
01-new_algorithm_for_join.patch 02-remove_join_functions_duality.patch 03-test29_improve.patch > > I haven't looked into the details, but you should at least use spaces > > like in the rest of the code. Fixed. > > Did you do "make test"? Test 29 should be extended with joining > > multiple lines. Currently it does one line at a time only. > > Up to this moment I did manual tests for different cases of joins: > > + called via do_join and do_do_join > + with 'compatible' set and not set > + with different line endings to check proper spacing (after '.','?' and '?' > etc.) > + with and without marks set in the range of joined lines > > ++ combinations of all above The patched test29 does exactly all of that. Can you look at new patches, Bram? Thank you, Milan -- Milan Vancura, Prague, Czech Republic, Europe --~--~---------~--~----~------------~-------~--~----~ You received this message from the "vim_dev" maillist. For more information, visit http://www.vim.org/maillist.php -~----------~----~----~----~------~----~------~--~---
From: Milan Vancura <mvanc...@suse.cz> Date: Tue, 6 Jan 2009 17:38:37 +0100 Subject: [PATCH] New algorithm of joining lines instead of calling do_join() n-times for n lines, new function do_do_join() do the whole work and accepts number of lines to join directly. That means do_join() function is just a container calling do_do_join() and can be deleted in the future. diff --git a/src/ex_docmd.c b/src/ex_docmd.c index b060e63..640d0a2 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8282,7 +8282,7 @@ ex_join(eap) } ++eap->line2; } - do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit); + (void)do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit); beginline(BL_WHITE | BL_FIX); ex_may_print(eap); } diff --git a/src/normal.c b/src/normal.c index 0557833..12eb2cf 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1912,7 +1912,7 @@ do_pending_operator(cap, old_col, gui_yank) beep_flush(); else { - do_do_join(oap->line_count, oap->op_type == OP_JOIN); + (void)do_do_join(oap->line_count, oap->op_type == OP_JOIN); auto_format(FALSE, TRUE); } break; @@ -9082,7 +9082,7 @@ nv_join(cap) { prep_redo(cap->oap->regname, cap->count0, NUL, cap->cmdchar, NUL, NUL, cap->nchar); - do_do_join(cap->count0, cap->nchar == NUL); + (void)do_do_join(cap->count0, cap->nchar == NUL); } } } diff --git a/src/ops.c b/src/ops.c index 557985c..953f805 100644 --- a/src/ops.c +++ b/src/ops.c @@ -4103,138 +4103,129 @@ dis_msg(p, skip_esc) } /* - * join 'count' lines (minimal 2), including u_save() - */ - void -do_do_join(count, insert_space) - long count; - int insert_space; -{ - colnr_T col = MAXCOL; - - if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), - (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) - return; - - while (--count > 0) - { - line_breakcheck(); - if (got_int || do_join(insert_space) == FAIL) - { - beep_flush(); - break; - } - if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) - col = curwin->w_cursor.col; - } - - /* Vi compatible: use the column of the first join */ - if (col != MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) - curwin->w_cursor.col = col; - -#if 0 - /* - * Need to update the screen if the line where the cursor is became too - * long to fit on the screen. - */ - update_topline_redraw(); -#endif -} - -/* - * Join two lines at the cursor position. + * Join 'count' lines (minimal 2) at cursor position, including u_save() * "redraw" is TRUE when the screen should be updated. * Caller must have setup for undo. * * return FAIL for failure, OK otherwise */ int -do_join(insert_space) - int insert_space; +do_do_join(count, insert_space) + long count; + int insert_space; { - char_u *curr; - char_u *next, *next_start; + char_u *curr, *cend; char_u *newp; + char_u *spaces; /* array of spaces added between lines */ 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 sumsize=0; /* size of the new (big) line */ linenr_T t; + colnr_T col = 0; - if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) - return FAIL; /* can't join on last line */ + if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), + (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) + return FAIL; - curr = ml_get_curline(); - currsize = (int)STRLEN(curr); - endcurr1 = endcurr2 = NUL; - if (insert_space && currsize > 0) + /* + * Allocate the local array of space strings lengths. + * We will use it to pre-compute the length of the new line + * and the proper placement of each original line in the new one. + */ + spaces=lalloc_clear((long_u)count, TRUE); + if (spaces == NUL) + return FAIL; + + /* + * Don't move anything, just compute the final line length + * and setup the array of space strings lengths + */ + for (t = 0; t < count; t++) { -#ifdef FEAT_MBYTE - if (has_mbyte) + curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); + if (insert_space && t > 0) { - next = curr + currsize; - mb_ptr_back(curr, next); - endcurr1 = (*mb_ptr2char)(next); - if (next > curr) + curr = skipwhite(curr); + if (*curr != ')' && currsize != 0 && endcurr1 != TAB +#ifdef FEAT_MBYTE + && (!has_format_option(FO_MBYTE_JOIN) + || (mb_ptr2char(curr) < 0x100 && endcurr1 < 0x100)) + && (!has_format_option(FO_MBYTE_JOIN2) + || mb_ptr2char(curr) < 0x100 || endcurr1 < 0x100) +#endif + ) { - mb_ptr_back(curr, next); - endcurr2 = (*mb_ptr2char)(next); + /* don't add a space if the line is ending in a space */ + if (endcurr1 == ' ') + endcurr1 = endcurr2; + else + ++spaces[t]; + /* extra space when 'joinspaces' set and line ends in '.' */ + if ( p_js + && (endcurr1 == '.' + || (vim_strchr(p_cpo, CPO_JOINSP) == NULL + && (endcurr1 == '?' || endcurr1 == '!')))) + ++spaces[t]; } } - else -#endif + currsize = (int)STRLEN(curr); + sumsize += currsize + spaces[t]; + endcurr1 = endcurr2 = NUL; + if (insert_space && currsize > 0) { - endcurr1 = *(curr + currsize - 1); - if (currsize > 1) - endcurr2 = *(curr + currsize - 2); - } - } - - next = next_start = ml_get((linenr_T)(curwin->w_cursor.lnum + 1)); - spaces = 0; - if (insert_space) - { - next = skipwhite(next); - if (*next != ')' && currsize != 0 && endcurr1 != TAB #ifdef FEAT_MBYTE - && (!has_format_option(FO_MBYTE_JOIN) - || (mb_ptr2char(next) < 0x100 && endcurr1 < 0x100)) - && (!has_format_option(FO_MBYTE_JOIN2) - || mb_ptr2char(next) < 0x100 || endcurr1 < 0x100) -#endif - ) - { - /* don't add a space if the line is ending in a space */ - if (endcurr1 == ' ') - endcurr1 = endcurr2; + if (has_mbyte) + { + cend = curr + currsize; + mb_ptr_back(curr, cend); + endcurr1 = (*mb_ptr2char)(cend); + if (cend > curr) + { + mb_ptr_back(curr, cend); + endcurr2 = (*mb_ptr2char)(cend); + } + } 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; +#endif + { + endcurr1 = *(curr + currsize - 1); + if (currsize > 1) + endcurr2 = *(curr + currsize - 2); + } } } - nextsize = (int)STRLEN(next); - newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1)); - if (newp == NULL) - return FAIL; + /* store the column position before last line */ + col = sumsize - currsize - spaces[count - 1]; + + /* Allocate the space for the new line */ + newp = alloc_check((unsigned)(sumsize + 1)); + cend = newp + sumsize; + *cend = 0; /* - * Insert the next line first, because we already have that pointer. - * Curr has to be obtained again, because getting next will have - * invalidated it. + * Move affected lines to the new long one. + * + * Move marks from each deleted line to the joined line, adjusting the + * column. This is not Vi compatible, but Vi deletes the marks, thus that + * should not really be a problem. */ - 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); - + for (t = count - 1;; t--) + { + cend -= (currsize + spaces[t]); + mch_memmove(cend + spaces[t], curr, (size_t)currsize); + if (spaces[t]) + copy_spaces(cend, (size_t)(spaces[t])); + mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, + (long)(cend - newp + spaces[t])); + if (t == 0) + break; + curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); + if (insert_space && t > 1) + curr = skipwhite(curr); + currsize = (int)STRLEN(curr); + } + mch_memmove(cend, curr, (size_t)currsize); ml_replace(curwin->w_cursor.lnum, newp, FALSE); /* Only report the change in the first line here, del_lines() will report @@ -4243,34 +4234,55 @@ do_join(insert_space) curwin->w_cursor.lnum + 1, 0L); /* - * Delete the following line. To do this we move the cursor there + * Delete following lines. 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. - * - * Move marks from the deleted line to the joined line, adjusting the - * column. This is not Vi compatible, but Vi deletes the marks, thus that - * should not really be a problem. */ t = curwin->w_cursor.lnum; - mark_col_adjust(t + 1, (colnr_T)0, (linenr_T)-1, - (long)(currsize + spaces - (next - next_start))); ++curwin->w_cursor.lnum; - del_lines(1L, FALSE); + del_lines(count - 1, FALSE); curwin->w_cursor.lnum = t; /* - * go to first character of the joined line + * Cursor column setting + * Vi compatible: use the column of the first join + * vim: use the column of the last join */ - curwin->w_cursor.col = currsize; + curwin->w_cursor.col = + (vim_strchr(p_cpo, CPO_JOINCOL) != NULL ? currsize : col); check_cursor_col(); + #ifdef FEAT_VIRTUALEDIT curwin->w_cursor.coladd = 0; #endif curwin->w_set_curswant = TRUE; +#if 0 + /* + * Need to update the screen if the line where the cursor is became too + * long to fit on the screen. + */ + update_topline_redraw(); +#endif + /* free the local array of space strings lengths and return */ + vim_free(spaces); return OK; } +/* + * Join two lines at the cursor position. + * "redraw" is TRUE when the screen should be updated. + * Caller must have setup for undo. + * + * return FAIL for failure, OK otherwise + */ + int +do_join(insert_space) + int insert_space; +{ + return do_do_join(2, insert_space); +} + #ifdef FEAT_COMMENTS /* * Return TRUE if the two comment leaders given are the same. "lnum" is diff --git a/src/proto/ops.pro b/src/proto/ops.pro index 37c3194..1e89509 100644 --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -36,7 +36,7 @@ void adjust_cursor_eol __ARGS((void)); int preprocs_left __ARGS((void)); int get_register_name __ARGS((int num)); void ex_display __ARGS((exarg_T *eap)); -void do_do_join __ARGS((long count, int insert_space)); +int do_do_join __ARGS((long count, int insert_space)); int do_join __ARGS((int insert_space)); void op_format __ARGS((oparg_T *oap, int keep_cursor)); void op_formatexpr __ARGS((oparg_T *oap));
From: Milan Vancura <mvanc...@suse.cz> Date: Tue, 6 Jan 2009 17:47:05 +0100 Subject: [PATCH] The duality do_join() + do_do_join() removed. Only one function do_join accepting number of lines to join is here now. diff --git a/src/edit.c b/src/edit.c index 714d320..3d82eac 100644 --- a/src/edit.c +++ b/src/edit.c @@ -8206,7 +8206,7 @@ ins_del() if (!can_bs(BS_EOL) /* only if "eol" included */ || u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + 2)) == FAIL - || do_join(FALSE) == FAIL) + || do_join(2,FALSE) == FAIL) vim_beep(); else curwin->w_cursor.col = temp; @@ -8386,7 +8386,7 @@ ins_bs(c, mode, inserted_space_p) ptr[len - 1] = NUL; } - (void)do_join(FALSE); + (void)do_join(2,FALSE); if (temp == NUL && gchar_cursor() != NUL) inc_cursor(); } diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 640d0a2..47c632c 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8282,7 +8282,7 @@ ex_join(eap) } ++eap->line2; } - (void)do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit); + (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit); beginline(BL_WHITE | BL_FIX); ex_may_print(eap); } diff --git a/src/normal.c b/src/normal.c index 12eb2cf..b353c60 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1912,7 +1912,7 @@ do_pending_operator(cap, old_col, gui_yank) beep_flush(); else { - (void)do_do_join(oap->line_count, oap->op_type == OP_JOIN); + (void)do_join(oap->line_count, oap->op_type == OP_JOIN); auto_format(FALSE, TRUE); } break; @@ -9082,7 +9082,7 @@ nv_join(cap) { prep_redo(cap->oap->regname, cap->count0, NUL, cap->cmdchar, NUL, NUL, cap->nchar); - (void)do_do_join(cap->count0, cap->nchar == NUL); + (void)do_join(cap->count0, cap->nchar == NUL); } } } diff --git a/src/ops.c b/src/ops.c index 953f805..284bcdb 100644 --- a/src/ops.c +++ b/src/ops.c @@ -1919,7 +1919,7 @@ op_delete(oap) ); curwin->w_cursor = curpos; /* restore curwin->w_cursor */ - (void)do_join(FALSE); + (void)do_join(2,FALSE); } } @@ -4110,7 +4110,7 @@ dis_msg(p, skip_esc) * return FAIL for failure, OK otherwise */ int -do_do_join(count, insert_space) +do_join(count, insert_space) long count; int insert_space; { @@ -4269,20 +4269,6 @@ do_do_join(count, insert_space) return OK; } -/* - * Join two lines at the cursor position. - * "redraw" is TRUE when the screen should be updated. - * Caller must have setup for undo. - * - * return FAIL for failure, OK otherwise - */ - int -do_join(insert_space) - int insert_space; -{ - return do_do_join(2, insert_space); -} - #ifdef FEAT_COMMENTS /* * Return TRUE if the two comment leaders given are the same. "lnum" is @@ -4716,7 +4702,7 @@ format_lines(line_count, avoid_fex) (long)-next_leader_len); #endif curwin->w_cursor.lnum--; - if (do_join(TRUE) == FAIL) + if (do_join(2,TRUE) == FAIL) { beep_flush(); break; diff --git a/src/proto/ops.pro b/src/proto/ops.pro index 1e89509..fc1d471 100644 --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -36,8 +36,7 @@ void adjust_cursor_eol __ARGS((void)); int preprocs_left __ARGS((void)); int get_register_name __ARGS((int num)); void ex_display __ARGS((exarg_T *eap)); -int do_do_join __ARGS((long count, int insert_space)); -int do_join __ARGS((int insert_space)); +int do_join __ARGS((long count, int insert_space)); void op_format __ARGS((oparg_T *oap, int keep_cursor)); void op_formatexpr __ARGS((oparg_T *oap)); int fex_format __ARGS((linenr_T lnum, long count, int c));
From: Milan Vancura <mvanc...@suse.cz> Date: Wed, 7 Jan 2009 11:41:27 +0100 Subject: [PATCH] Test for joining lines (test29) improved. It tests both lines joining and marks in that lines in compatible and nocompatible modes and with 'joinspaces' set or not and with 'cpoptions' flag 'j' set or not. diff --git a/src/testdir/test29.in b/src/testdir/test29.in index de93ccc..7cefa5e 100644 --- a/src/testdir/test29.in +++ b/src/testdir/test29.in @@ -1,10 +1,17 @@ -Test for joining lines with 'joinspaces' set or not +Test for joining lines and marks in them + in compatible and nocompatible modes + and with 'joinspaces' set or not + and with 'cpoptions' flag 'j' set or not STARTTEST :set nojoinspaces +:set cpoptions-=j /firstline/ -jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:set joinspaces -jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:?firstline?+1,$w! test.out +j"tdGpJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j +j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j joinspaces +j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j +j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j nojoinspaces compatible +j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj4Jy3l$pjdG:?firstline?+1,$w! test.out :qa! ENDTEST @@ -37,31 +44,12 @@ asdfasdf asdf asdfasdf asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf. -asdf -asdfasdf -asdf -asdfasdf -asdf -asdfasdf -asdf -asdfasdf -asdf -asdfasdf -asdf -asdfasdf -asdf -asdfasdf -asdf +zx cvn. +as dfg? +hjkl iop! +ert +zx cvn. +as dfg? +hjkl iop! +ert + diff --git a/src/testdir/test29.ok b/src/testdir/test29.ok index 076f77c..bf2ea4e 100644 --- a/src/testdir/test29.ok +++ b/src/testdir/test29.ok @@ -12,6 +12,9 @@ asdfasdf asdf asdfasdf asdf asdfasdf asdf asdfasdf asdf +zx cvn. as dfg? hjkl iop! ert asnop +zx cvn. as dfg? hjkl iop! ert asnop + asdfasdf. asdf asdfasdf. asdf asdfasdf. asdf @@ -26,3 +29,21 @@ asdfasdf asdf asdfasdf asdf asdfasdf asdf asdfasdf asdf +zx cvn. as dfg? hjkl iop! ert anop +zx cvn. as dfg? hjkl iop! ert anop + +asdfasdf. asdf +asdfasdf. asdf +asdfasdf. asdf +asdfasdf. asdf +asdfasdf. asdf +asdfasdf. asdf +asdfasdf. asdf +asdfasdf asdf +asdfasdf asdf +asdfasdf asdf +asdfasdf asdf +asdfasdf asdf +asdfasdf asdf +asdfasdf asdf +zx cvn. as dfg? hjkl iop! ert a