Here is my fix. It seems to work manually testing it with a few cases.
Here is the timing of vim installed with my Ubuntu:
% yes | head -100000 > yes.tmp
% time vim -u NONE -c '%join|q!' yes.tmp
17.2u 0.0s 0:17.24 99.8% 0+0k 0+8io 0pf+0w
And with my patch:
% time ./vim -u NONE -c '%join|q!' yes.tmp
0.2u 0.0s 0:00.29 96.5% 0+0k 0+8io 0pf+0w
Below is the patch (a diff of ops_orig.c and ops.c). It needs a bit of
cleaning up (eg putting the function prototype where it belongs) and
checking that the error handling is done in a correct way (I've tried
to be consistent with existing code but don't really understand how it
all works, eg with the magic of undo).
lee
P.S. I posted something else which hasn't shown up yet - maybe due
to moderation. I'm doing this via e-mail as I have not yet handed
over all my personal details to Google.
*** ops_orig.c 2008-12-10 15:15:08.000000000 +1100
--- ops.c 2008-12-11 17:10:15.000000000 +1100
***************
*** 4102,4107 ****
--- 4102,4109 ----
ui_breakcheck();
}
+ int do_do_join_rec(long, int); /* MOVE/FIX this */
+
/*
* join 'count' lines (minimal 2), including u_save()
*/
***************
*** 4110,4130 ****
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;
}
--- 4112,4140 ----
long count;
int insert_space;
{
+ int failflag = OK;
colnr_T col = MAXCOL;
if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
(linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
return;
! /* Its simplest to call do_join() count-1 times in a while loop
! * but this leads to O(count^2) complexity.
! * Better to use a divide and conquer strategy, leading to
! * O(count log count) complexity. Here we use D&Q for first
! * count-1 lines (count-2 joins); the last join is done separately
! * so we can set the new column for the cursor correctly.
! */
! if (count > 2)
! failflag = do_do_join_rec(count-2, insert_space);
! if (failflag == OK)
{
line_breakcheck();
if (got_int || do_join(insert_space) == FAIL)
{
beep_flush();
! } else if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL)
col = curwin->w_cursor.col;
}
***************
*** 4142,4147 ****
--- 4152,4192 ----
}
/*
+ * join 'count'+1 lines ('count' join ops), using recursive divide
+ * and conquer strategy
+ */
+ int
+ do_do_join_rec(count, insert_space)
+ long count;
+ int insert_space;
+ {
+ if (count == 0)
+ /* base case: nothing to do */
+ return OK;
+ else {
+
+ /* join all lines in first ~half */
+ if (got_int || do_do_join_rec((count-1)/2, insert_space) == FAIL)
+ return FAIL;
+
+ /* go to next line and join all lines in second ~half;
+ * we want a total of count-1 joins at this point
+ */
+ ++curwin->w_cursor.lnum;
+ if (got_int ||
+ do_do_join_rec(count-1-(count-1)/2, insert_space) == FAIL)
+ return FAIL;
+
+ /* go back to first (joined) line and join with the second */
+ --curwin->w_cursor.lnum;
+ line_breakcheck();
+ if (got_int || do_join(insert_space) == FAIL)
+ return FAIL;
+ return OK;
+ }
+ }
+
+ /*
* Join two lines at the cursor position.
* "redraw" is TRUE when the screen should be updated.
* Caller must have setup for undo.
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---