> I will try to include a few patches that have been pending for a while. > I don't have much time available, thus I will only include things that > take a few hours of my time. That basically means patches that are > ready to be included.
Hi Bram, I resend my fixes of test29 and also a patch replacing O(n2) algorithm of line join by O(n) one. There are no significant changes in those patches since I published them on this list in past, they are just updated to current vim73 sources from mercurial. A fix of test29 is straigthforward, it is clear that (and how) it was wrong. A line join algorithm replacement may be considered as a feature but it was tested for a long time by all users of git branch vim-extended with no negative report for all that time. May you include them in vim 7.3, please? Milan Vancura -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php
# HG changeset patch # User Milan Vancura <[email protected]> # Date 1274036792 -7200 # Branch fixjoin # Node ID 2964caf8577d3aec67815d9c9b0e6e492be292ab # Parent c6f1aa1e9f32e9d32156d246dc7d913fd5ef8d6f 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 -r c6f1aa1e9f32 -r 2964caf8577d src/ex_docmd.c --- a/src/ex_docmd.c Sun May 16 15:46:46 2010 +0200 +++ b/src/ex_docmd.c Sun May 16 21:06:32 2010 +0200 @@ -8378,7 +8378,7 @@ } ++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 -r c6f1aa1e9f32 -r 2964caf8577d src/normal.c --- a/src/normal.c Sun May 16 15:46:46 2010 +0200 +++ b/src/normal.c Sun May 16 21:06:32 2010 +0200 @@ -1900,7 +1900,7 @@ 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; @@ -9093,7 +9093,7 @@ { 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 -r c6f1aa1e9f32 -r 2964caf8577d src/ops.c --- a/src/ops.c Sun May 16 15:46:46 2010 +0200 +++ b/src/ops.c Sun May 16 21:06:32 2010 +0200 @@ -4140,35 +4140,159 @@ } /* - * join 'count' lines (minimal 2), including u_save() + * 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 */ - void + int do_do_join(count, insert_space) long count; int insert_space; { - colnr_T col = MAXCOL; + 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 sumsize=0; /* size of the new (big) line */ + linenr_T t; + colnr_T col = 0; if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), - (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) - return; - - while (--count > 0) + (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) + return FAIL; + + /* + * 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++) { - line_breakcheck(); - if (got_int || do_join(insert_space) == FAIL) + curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); + if (insert_space && t > 0) { - beep_flush(); + 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 + ) + { + /* 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]; + } + } + currsize = (int)STRLEN(curr); + sumsize += currsize + spaces[t]; + endcurr1 = endcurr2 = NUL; + if (insert_space && currsize > 0) + { +#ifdef FEAT_MBYTE + 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 +#endif + { + endcurr1 = *(curr + currsize - 1); + if (currsize > 1) + endcurr2 = *(curr + currsize - 2); + } + } + } + + /* 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; + + /* + * 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. + */ + 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; - } - if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) - col = curwin->w_cursor.col; + curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); + if (insert_space && t > 1) + curr = skipwhite(curr); + currsize = (int)STRLEN(curr); } - - /* Vi compatible: use the column of the first join */ - if (col != MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) - curwin->w_cursor.col = col; - + 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 + * the deleted line. */ + changed_lines(curwin->w_cursor.lnum, currsize, + curwin->w_cursor.lnum + 1, 0L); + + /* + * 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. + */ + t = curwin->w_cursor.lnum; + ++curwin->w_cursor.lnum; + del_lines(count - 1, FALSE); + curwin->w_cursor.lnum = t; + + /* + * Cursor column setting + * Vi compatible: use the column of the first join + * vim: use the column of the last join + */ + 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 @@ -4176,6 +4300,10 @@ */ update_topline_redraw(); #endif + + /* free the local array of space strings lengths and return */ + vim_free(spaces); + return OK; } /* @@ -4189,123 +4317,7 @@ do_join(insert_space) int insert_space; { - char_u *curr; - char_u *next, *next_start; - 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 */ - linenr_T t; - - if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) - return FAIL; /* can't join on last line */ - - curr = ml_get_curline(); - currsize = (int)STRLEN(curr); - endcurr1 = endcurr2 = NUL; - if (insert_space && currsize > 0) - { -#ifdef FEAT_MBYTE - if (has_mbyte) - { - next = curr + currsize; - mb_ptr_back(curr, next); - endcurr1 = (*mb_ptr2char)(next); - if (next > curr) - { - mb_ptr_back(curr, next); - endcurr2 = (*mb_ptr2char)(next); - } - } - else -#endif - { - 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; - 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 = (int)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); - - /* Only report the change in the first line here, del_lines() will report - * the deleted line. */ - changed_lines(curwin->w_cursor.lnum, currsize, - curwin->w_cursor.lnum + 1, 0L); - - /* - * 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. - * - * 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); - curwin->w_cursor.lnum = t; - - /* - * go to first character of the joined line - */ - curwin->w_cursor.col = currsize; - check_cursor_col(); -#ifdef FEAT_VIRTUALEDIT - curwin->w_cursor.coladd = 0; -#endif - curwin->w_set_curswant = TRUE; - - return OK; + return do_do_join(2, insert_space); } #ifdef FEAT_COMMENTS diff -r c6f1aa1e9f32 -r 2964caf8577d src/proto/ops.pro --- a/src/proto/ops.pro Sun May 16 15:46:46 2010 +0200 +++ b/src/proto/ops.pro Sun May 16 21:06:32 2010 +0200 @@ -36,7 +36,7 @@ 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));
# HG changeset patch # User Milan Vancura <[email protected]> # Date 1274037330 -7200 # Branch fixjoin # Node ID d05d08017cd7c7467f1920a5dd0a9fb2ceeabf03 # Parent 2964caf8577d3aec67815d9c9b0e6e492be292ab The duality do_join() + do_do_join() removed. Only one function do_join accepting number of lines to join is here now. diff -r 2964caf8577d -r d05d08017cd7 src/edit.c --- a/src/edit.c Sun May 16 21:06:32 2010 +0200 +++ b/src/edit.c Sun May 16 21:15:30 2010 +0200 @@ -8322,7 +8322,7 @@ 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; @@ -8503,7 +8503,7 @@ ptr[len - 1] = NUL; } - (void)do_join(FALSE); + (void)do_join(2,FALSE); if (temp == NUL && gchar_cursor() != NUL) inc_cursor(); } diff -r 2964caf8577d -r d05d08017cd7 src/ex_docmd.c --- a/src/ex_docmd.c Sun May 16 21:06:32 2010 +0200 +++ b/src/ex_docmd.c Sun May 16 21:15:30 2010 +0200 @@ -8378,7 +8378,7 @@ } ++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 -r 2964caf8577d -r d05d08017cd7 src/normal.c --- a/src/normal.c Sun May 16 21:06:32 2010 +0200 +++ b/src/normal.c Sun May 16 21:15:30 2010 +0200 @@ -1900,7 +1900,7 @@ 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; @@ -9093,7 +9093,7 @@ { 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 -r 2964caf8577d -r d05d08017cd7 src/ops.c --- a/src/ops.c Sun May 16 21:06:32 2010 +0200 +++ b/src/ops.c Sun May 16 21:15:30 2010 +0200 @@ -1949,7 +1949,7 @@ ); curwin->w_cursor = curpos; /* restore curwin->w_cursor */ - (void)do_join(FALSE); + (void)do_join(2,FALSE); } } @@ -4147,7 +4147,7 @@ * return FAIL for failure, OK otherwise */ int -do_do_join(count, insert_space) +do_join(count, insert_space) long count; int insert_space; { @@ -4306,20 +4306,6 @@ 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 @@ -4738,7 +4724,7 @@ (long)-next_leader_len); #endif curwin->w_cursor.lnum--; - if (do_join(TRUE) == FAIL) + if (do_join(2,TRUE) == FAIL) { beep_flush(); break; diff -r 2964caf8577d -r d05d08017cd7 src/proto/ops.pro --- a/src/proto/ops.pro Sun May 16 21:06:32 2010 +0200 +++ b/src/proto/ops.pro Sun May 16 21:15:30 2010 +0200 @@ -36,8 +36,7 @@ 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));
# HG changeset patch # User Milan Vancura <[email protected]> # Date 1274045843 -7200 # Branch fixjoin # Node ID d54a96e95c4f9708d75712e7f525dff3183910ef # Parent d05d08017cd7c7467f1920a5dd0a9fb2ceeabf03 Test for joining lines (test29) improved. It tests both lines joining and marks in that lines properly in all combinations of setting 'compatible' option, 'joinspaces' option and 'j' flag in 'cpoptions' option. diff -r d05d08017cd7 -r d54a96e95c4f src/testdir/test29.in --- a/src/testdir/test29.in Sun May 16 21:15:30 2010 +0200 +++ b/src/testdir/test29.in Sun May 16 23:37:23 2010 +0200 @@ -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 @@ 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 -r d05d08017cd7 -r d54a96e95c4f src/testdir/test29.ok --- a/src/testdir/test29.ok Sun May 16 21:15:30 2010 +0200 +++ b/src/testdir/test29.ok Sun May 16 23:37:23 2010 +0200 @@ -12,6 +12,9 @@ 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 +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
# HG changeset patch # User Milan Vancura <[email protected]> # Date 1274046016 -7200 # Branch fixjoin # Node ID 790df24718cf37dc6ade598d3e3b3d54db65597a # Parent d54a96e95c4f9708d75712e7f525dff3183910ef set 'nocompatible' at start of test29 (after 03-test29_improve.patch) As tests are run in 'compatible' mode by default, we must switch it at the test beginning. And fix the file containing expected output as well. diff -r d54a96e95c4f -r 790df24718cf src/testdir/test29.in --- a/src/testdir/test29.in Sun May 16 23:37:23 2010 +0200 +++ b/src/testdir/test29.in Sun May 16 23:40:16 2010 +0200 @@ -4,6 +4,7 @@ and with 'cpoptions' flag 'j' set or not STARTTEST +:set nocompatible :set nojoinspaces :set cpoptions-=j /firstline/ diff -r d54a96e95c4f -r 790df24718cf src/testdir/test29.ok --- a/src/testdir/test29.ok Sun May 16 23:37:23 2010 +0200 +++ b/src/testdir/test29.ok Sun May 16 23:40:16 2010 +0200 @@ -12,8 +12,8 @@ asdfasdf asdf asdfasdf asdf asdfasdf asdf -zx cvn. as dfg? hjkl iop! ert asnop -zx cvn. as dfg? hjkl iop! ert asnop +zx cvn. as dfg? hjkl iop! ert ernop +zx cvn. as dfg? hjkl iop! ert ernop asdfasdf. asdf asdfasdf. asdf @@ -29,8 +29,8 @@ asdfasdf asdf asdfasdf asdf asdfasdf asdf -zx cvn. as dfg? hjkl iop! ert anop -zx cvn. as dfg? hjkl iop! ert anop +zx cvn. as dfg? hjkl iop! ert enop +zx cvn. as dfg? hjkl iop! ert ernop asdfasdf. asdf asdfasdf. asdf
