diff options
| author | Dmitry Antipov | 2012-07-19 12:56:53 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2012-07-19 12:56:53 +0400 |
| commit | 9cd47b72e021f76a6e2481d986ce4b0cb0b859d3 (patch) | |
| tree | 73912e8be2147fe90acf8f5dd20bb1c238d354df /src | |
| parent | 1d6fc0df363db43f2c1db696fad40f068287500b (diff) | |
| download | emacs-9cd47b72e021f76a6e2481d986ce4b0cb0b859d3.tar.gz emacs-9cd47b72e021f76a6e2481d986ce4b0cb0b859d3.zip | |
Compact buffers when idle.
* lisp/compact.el: New file.
* src/buffer.c (compact_buffer, Fcompact_buffer): New function.
(syms_of_buffer): Register Fcompact_buffer.
* src/alloc.c (Fgarbage_collect): Use compact_buffer.
* src/buffer.h (compact_buffer): New prototype.
(struct buffer_text): New member.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/alloc.c | 28 | ||||
| -rw-r--r-- | src/buffer.c | 61 | ||||
| -rw-r--r-- | src/buffer.h | 4 |
4 files changed, 67 insertions, 35 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 73632c26bff..7a0942f9c7e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,14 @@ | |||
| 1 | 2012-07-19 Dmitry Antipov <dmantipov@yandex.ru> | 1 | 2012-07-19 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 2 | ||
| 3 | Buffer compaction primitive which may be used from Lisp. | ||
| 4 | * buffer.c (compact_buffer, Fcompact_buffer): New function. | ||
| 5 | (syms_of_buffer): Register Fcompact_buffer. | ||
| 6 | * alloc.c (Fgarbage_collect): Use compact_buffer. | ||
| 7 | * buffer.h (compact_buffer): New prototype. | ||
| 8 | (struct buffer_text): New member. | ||
| 9 | |||
| 10 | 2012-07-19 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 11 | |||
| 3 | New macro to iterate over all buffers, miscellaneous cleanups. | 12 | New macro to iterate over all buffers, miscellaneous cleanups. |
| 4 | * lisp.h (all_buffers): Remove declaration. | 13 | * lisp.h (all_buffers): Remove declaration. |
| 5 | * buffer.h (all_buffers): Add declaration, with comment. | 14 | * buffer.h (all_buffers): Add declaration, with comment. |
diff --git a/src/alloc.c b/src/alloc.c index 166f5b72449..233137e368e 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5413,33 +5413,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5413 | /* Don't keep undo information around forever. | 5413 | /* Don't keep undo information around forever. |
| 5414 | Do this early on, so it is no problem if the user quits. */ | 5414 | Do this early on, so it is no problem if the user quits. */ |
| 5415 | for_each_buffer (nextb) | 5415 | for_each_buffer (nextb) |
| 5416 | { | 5416 | compact_buffer (nextb); |
| 5417 | /* If a buffer's undo list is Qt, that means that undo is | ||
| 5418 | turned off in that buffer. Calling truncate_undo_list on | ||
| 5419 | Qt tends to return NULL, which effectively turns undo back on. | ||
| 5420 | So don't call truncate_undo_list if undo_list is Qt. */ | ||
| 5421 | if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) | ||
| 5422 | && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) | ||
| 5423 | truncate_undo_list (nextb); | ||
| 5424 | |||
| 5425 | /* Shrink buffer gaps, but skip indirect and dead buffers. */ | ||
| 5426 | if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name)) | ||
| 5427 | && ! nextb->text->inhibit_shrinking) | ||
| 5428 | { | ||
| 5429 | /* If a buffer's gap size is more than 10% of the buffer | ||
| 5430 | size, or larger than 2000 bytes, then shrink it | ||
| 5431 | accordingly. Keep a minimum size of 20 bytes. */ | ||
| 5432 | int size = min (2000, max (20, (nextb->text->z_byte / 10))); | ||
| 5433 | |||
| 5434 | if (nextb->text->gap_size > size) | ||
| 5435 | { | ||
| 5436 | struct buffer *save_current = current_buffer; | ||
| 5437 | current_buffer = nextb; | ||
| 5438 | make_gap (-(nextb->text->gap_size - size)); | ||
| 5439 | current_buffer = save_current; | ||
| 5440 | } | ||
| 5441 | } | ||
| 5442 | } | ||
| 5443 | 5417 | ||
| 5444 | t1 = current_emacs_time (); | 5418 | t1 = current_emacs_time (); |
| 5445 | 5419 | ||
diff --git a/src/buffer.c b/src/buffer.c index 40370460b9f..0fc5dd0b9c3 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -1434,14 +1434,59 @@ No argument or nil as argument means do this for the current buffer. */) | |||
| 1434 | return Qnil; | 1434 | return Qnil; |
| 1435 | } | 1435 | } |
| 1436 | 1436 | ||
| 1437 | /* | 1437 | /* Truncate undo list and shrink the gap of BUFFER. */ |
| 1438 | DEFVAR_LISP ("kill-buffer-hook", ..., "\ | 1438 | |
| 1439 | Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ | 1439 | int |
| 1440 | The buffer being killed will be current while the hook is running.\n\ | 1440 | compact_buffer (struct buffer *buffer) |
| 1441 | { | ||
| 1442 | /* Skip dead buffers, indirect buffers and buffers | ||
| 1443 | which aren't changed since last compaction. */ | ||
| 1444 | if (!NILP (buffer->BUFFER_INTERNAL_FIELD (name)) | ||
| 1445 | && (buffer->base_buffer == NULL) | ||
| 1446 | && (buffer->text->compact != buffer->text->modiff)) | ||
| 1447 | { | ||
| 1448 | /* If a buffer's undo list is Qt, that means that undo is | ||
| 1449 | turned off in that buffer. Calling truncate_undo_list on | ||
| 1450 | Qt tends to return NULL, which effectively turns undo back on. | ||
| 1451 | So don't call truncate_undo_list if undo_list is Qt. */ | ||
| 1452 | if (!EQ (buffer->BUFFER_INTERNAL_FIELD (undo_list), Qt)) | ||
| 1453 | truncate_undo_list (buffer); | ||
| 1454 | |||
| 1455 | /* Shrink buffer gaps. */ | ||
| 1456 | if (!buffer->text->inhibit_shrinking) | ||
| 1457 | { | ||
| 1458 | /* If a buffer's gap size is more than 10% of the buffer | ||
| 1459 | size, or larger than 2000 bytes, then shrink it | ||
| 1460 | accordingly. Keep a minimum size of 20 bytes. */ | ||
| 1461 | int size = min (2000, max (20, (buffer->text->z_byte / 10))); | ||
| 1462 | |||
| 1463 | if (buffer->text->gap_size > size) | ||
| 1464 | { | ||
| 1465 | struct buffer *save_current = current_buffer; | ||
| 1466 | current_buffer = buffer; | ||
| 1467 | make_gap (-(buffer->text->gap_size - size)); | ||
| 1468 | current_buffer = save_current; | ||
| 1469 | } | ||
| 1470 | } | ||
| 1471 | buffer->text->compact = buffer->text->modiff; | ||
| 1472 | return 1; | ||
| 1473 | } | ||
| 1474 | return 0; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | DEFUN ("compact-buffer", Fcompact_buffer, Scompact_buffer, 0, 1, 0, | ||
| 1478 | doc: /* Compact BUFFER by truncating undo list and shrinking the gap. | ||
| 1479 | If buffer is nil, compact current buffer. Compaction is performed | ||
| 1480 | only if buffer was changed since last compaction. Return t if | ||
| 1481 | buffer compaction was performed, and nil otherwise. */) | ||
| 1482 | (Lisp_Object buffer) | ||
| 1483 | { | ||
| 1484 | if (NILP (buffer)) | ||
| 1485 | XSETBUFFER (buffer, current_buffer); | ||
| 1486 | CHECK_BUFFER (buffer); | ||
| 1487 | return compact_buffer (XBUFFER (buffer)) ? Qt : Qnil; | ||
| 1488 | } | ||
| 1441 | 1489 | ||
| 1442 | Functions run by this hook are supposed to not change the current | ||
| 1443 | buffer. See `kill-buffer'." | ||
| 1444 | */ | ||
| 1445 | DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", | 1490 | DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", |
| 1446 | doc: /* Kill the buffer specified by BUFFER-OR-NAME. | 1491 | doc: /* Kill the buffer specified by BUFFER-OR-NAME. |
| 1447 | The argument may be a buffer or the name of an existing buffer. | 1492 | The argument may be a buffer or the name of an existing buffer. |
| @@ -5992,7 +6037,6 @@ and `bury-buffer-internal'. */); | |||
| 5992 | defsubr (&Smake_indirect_buffer); | 6037 | defsubr (&Smake_indirect_buffer); |
| 5993 | defsubr (&Sgenerate_new_buffer_name); | 6038 | defsubr (&Sgenerate_new_buffer_name); |
| 5994 | defsubr (&Sbuffer_name); | 6039 | defsubr (&Sbuffer_name); |
| 5995 | /*defsubr (&Sbuffer_number);*/ | ||
| 5996 | defsubr (&Sbuffer_file_name); | 6040 | defsubr (&Sbuffer_file_name); |
| 5997 | defsubr (&Sbuffer_base_buffer); | 6041 | defsubr (&Sbuffer_base_buffer); |
| 5998 | defsubr (&Sbuffer_local_value); | 6042 | defsubr (&Sbuffer_local_value); |
| @@ -6004,6 +6048,7 @@ and `bury-buffer-internal'. */); | |||
| 6004 | defsubr (&Srename_buffer); | 6048 | defsubr (&Srename_buffer); |
| 6005 | defsubr (&Sother_buffer); | 6049 | defsubr (&Sother_buffer); |
| 6006 | defsubr (&Sbuffer_enable_undo); | 6050 | defsubr (&Sbuffer_enable_undo); |
| 6051 | defsubr (&Scompact_buffer); | ||
| 6007 | defsubr (&Skill_buffer); | 6052 | defsubr (&Skill_buffer); |
| 6008 | defsubr (&Sbury_buffer_internal); | 6053 | defsubr (&Sbury_buffer_internal); |
| 6009 | defsubr (&Sset_buffer_major_mode); | 6054 | defsubr (&Sset_buffer_major_mode); |
diff --git a/src/buffer.h b/src/buffer.h index 8c596835fcc..6f090479a24 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -436,6 +436,9 @@ struct buffer_text | |||
| 436 | 436 | ||
| 437 | EMACS_INT overlay_modiff; /* Counts modifications to overlays. */ | 437 | EMACS_INT overlay_modiff; /* Counts modifications to overlays. */ |
| 438 | 438 | ||
| 439 | EMACS_INT compact; /* Set to modiff each time when compact_buffer | ||
| 440 | is called for this buffer. */ | ||
| 441 | |||
| 439 | /* Minimum value of GPT - BEG since last redisplay that finished. */ | 442 | /* Minimum value of GPT - BEG since last redisplay that finished. */ |
| 440 | ptrdiff_t beg_unchanged; | 443 | ptrdiff_t beg_unchanged; |
| 441 | 444 | ||
| @@ -903,6 +906,7 @@ extern struct buffer buffer_local_symbols; | |||
| 903 | 906 | ||
| 904 | extern void delete_all_overlays (struct buffer *); | 907 | extern void delete_all_overlays (struct buffer *); |
| 905 | extern void reset_buffer (struct buffer *); | 908 | extern void reset_buffer (struct buffer *); |
| 909 | extern int compact_buffer (struct buffer *); | ||
| 906 | extern void evaporate_overlays (ptrdiff_t); | 910 | extern void evaporate_overlays (ptrdiff_t); |
| 907 | extern ptrdiff_t overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, | 911 | extern ptrdiff_t overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, |
| 908 | ptrdiff_t *len_ptr, ptrdiff_t *next_ptr, | 912 | ptrdiff_t *len_ptr, ptrdiff_t *next_ptr, |