Here's a patch which allows me to use Emacs even for large single line JSON file without slowing it down. The idea is to limit Emacs search for new line to MAX_NEWLINE_DISTANCE. With fundamental mode and word-wrap on, I'm able to browse the file via page scroll, beginning/ end of line, beginning/ end of buffer and parenthesis matching. Only the up-down cursor movement is jarring. Warning: It might or might not work for other scenarios. diff --git a/src/insdel.c b/src/insdel.c index 21acf0e61d..164c78fbda 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -36,6 +36,7 @@ static void insert_from_buffer_1 (struct buffer *, ptrdiff_t, ptrdiff_t, bool); static void gap_left (ptrdiff_t, ptrdiff_t, bool); static void gap_right (ptrdiff_t, ptrdiff_t); +/* const int MAX_NEWLINE_DISTANCE = 256; */ /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT) describing changes which happened while combine_after_change_calls @@ -2053,7 +2054,7 @@ invalidate_buffer_caches (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) set_buffer_internal (buf); - line_beg = find_newline_no_quit (start, start_byte, -1, + line_beg = find_before_next_newline (start, start - 256, -1, &start_byte); set_buffer_internal (old); } diff --git a/src/search.c b/src/search.c index 7389fbef0e..631f657b19 100644 --- a/src/search.c +++ b/src/search.c @@ -653,7 +653,7 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, struct region_cache *newline_cache; struct buffer *cache_buffer; - if (!end) + if (end <= 0) { if (count > 0) end = ZV, end_byte = ZV_BYTE; diff --git a/src/xdisp.c b/src/xdisp.c index cbdef7ad11..eeebb74321 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -427,6 +427,8 @@ #define IT_DISPLAYING_WHITESPACE(it) \ && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \ || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) +const int MAX_NEWLINE_DISTANCE = 256; + /* If all the conditions needed to print the fill column indicator are met, return the (nonnegative) column number, else return a negative value. */ @@ -6575,7 +6577,7 @@ back_to_previous_line_start (struct it *it) ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); DEC_BOTH (cp, bp); - IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)); + IT_CHARPOS (*it) = find_before_next_newline (cp, cp - MAX_NEWLINE_DISTANCE, -1, &IT_BYTEPOS (*it)); } @@ -6607,7 +6609,6 @@ forward_to_next_line_start (struct it *it, bool *skipped_p, ptrdiff_t old_selective; bool newline_found_p = false; int n; - const int MAX_NEWLINE_DISTANCE = 500; /* If already on a newline, just consume it to avoid unintended skipping over invisible text below. */ @@ -6647,63 +6648,7 @@ forward_to_next_line_start (struct it *it, bool *skipped_p, short-cut. */ if (!newline_found_p) { - ptrdiff_t bytepos, start = IT_CHARPOS (*it); - ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it), - 1, &bytepos); - Lisp_Object pos; - - eassert (!STRINGP (it->string)); - - /* If there isn't any `display' property in sight, and no - overlays, we can just use the position of the newline in - buffer text. */ - if (it->stop_charpos >= limit - || ((pos = Fnext_single_property_change (make_fixnum (start), - Qdisplay, Qnil, - make_fixnum (limit)), - NILP (pos)) - && next_overlay_change (start) == ZV)) - { - if (!it->bidi_p) - { - IT_CHARPOS (*it) = limit; - IT_BYTEPOS (*it) = bytepos; - } - else - { - struct bidi_it bprev; - - /* Help bidi.c avoid expensive searches for display - properties and overlays, by telling it that there are - none up to `limit'. */ - if (it->bidi_it.disp_pos < limit) - { - it->bidi_it.disp_pos = limit; - it->bidi_it.disp_prop = 0; - } - do { - bprev = it->bidi_it; - bidi_move_to_visually_next (&it->bidi_it); - } while (it->bidi_it.charpos != limit); - IT_CHARPOS (*it) = limit; - IT_BYTEPOS (*it) = it->bidi_it.bytepos; - if (bidi_it_prev) - *bidi_it_prev = bprev; - } - *skipped_p = newline_found_p = true; - } - else - { - while (!newline_found_p) - { - if (!get_next_display_element (it)) - break; - newline_found_p = ITERATOR_AT_END_OF_LINE_P (it); - if (newline_found_p && it->bidi_p && bidi_it_prev) - *bidi_it_prev = it->bidi_it; - set_iterator_to_next (it, false); - } - } + *skipped_p = true; } it->selective = old_selective; @@ -8227,8 +8172,9 @@ get_visually_first_element (struct it *it) if (string_p) it->bidi_it.charpos = it->bidi_it.bytepos = 0; else - it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it), - IT_BYTEPOS (*it), -1, + it->bidi_it.charpos = find_before_next_newline (IT_CHARPOS (*it), + IT_CHARPOS (*it) - MAX_NEWLINE_DISTANCE, + -1, &it->bidi_it.bytepos); bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); do @@ -10057,7 +10003,7 @@ move_it_vertically_backward (struct it *it, int dy) ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); DEC_BOTH (cp, bp); - cp = find_newline_no_quit (cp, bp, -1, NULL); + cp = find_before_next_newline (cp, cp - MAX_NEWLINE_DISTANCE, -1, NULL); move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); } bidi_unshelve_cache (it3data, true); @@ -24069,7 +24015,7 @@ DEFUN ("bidi-find-overridden-directionality", itb.bytepos = from_bpos; } else - itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos), + itb.charpos = find_before_next_newline (from_pos, from_pos - MAX_NEWLINE_DISTANCE, -1, &itb.bytepos); itb.paragraph_dir = NEUTRAL_DIR; itb.string.s = NULL;