diff options
Diffstat (limited to 'doc/lispref/text.texi')
| -rw-r--r-- | doc/lispref/text.texi | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 18f0ee88fe5..8774801f41f 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi | |||
| @@ -6375,3 +6375,151 @@ hooks during a series of changes (typically for performance reasons), | |||
| 6375 | use @code{combine-change-calls} or @code{combine-after-change-calls} | 6375 | use @code{combine-change-calls} or @code{combine-after-change-calls} |
| 6376 | instead. | 6376 | instead. |
| 6377 | @end defvar | 6377 | @end defvar |
| 6378 | |||
| 6379 | @node Tracking changes | ||
| 6380 | @subsection Tracking changes | ||
| 6381 | @cindex track-changes | ||
| 6382 | @cindex change tracker | ||
| 6383 | |||
| 6384 | Using @code{before-change-functions} and @code{after-change-functions} | ||
| 6385 | can be difficult in practice because of a number of pitfalls, such as | ||
| 6386 | the fact that the two calls are not always properly paired, or some | ||
| 6387 | calls may be missing, either because some Emacs primitives failed to | ||
| 6388 | properly pair them or because of incorrect use of | ||
| 6389 | @code{inhibit-modification-hooks}. Furthermore, | ||
| 6390 | many restrictions apply to those hook functions, such as the fact that | ||
| 6391 | they basically should never modify the current buffer, nor use an | ||
| 6392 | operation that may block, and they proceed quickly because | ||
| 6393 | some commands may call these hooks a large number of times. | ||
| 6394 | |||
| 6395 | The Track-Changes library fundamentally provides an alternative API, | ||
| 6396 | built on top of those hooks. Compared to @code{after-change-functions}, | ||
| 6397 | the first important difference is that, instead of providing the bounds | ||
| 6398 | of the change and the previous length, it provides the bounds of the | ||
| 6399 | change and the actual previous content of that region. The need to | ||
| 6400 | extract information from the original contents of the buffer is one of | ||
| 6401 | the main reasons why some packages need to use both | ||
| 6402 | @code{before-change-functions} and @code{after-change-functions} and | ||
| 6403 | then try to match them up. | ||
| 6404 | |||
| 6405 | The second difference is that it decouples the notification of a change | ||
| 6406 | from the act of processing it, and it automatically combines into | ||
| 6407 | a single change operation all the changes that occur between the first | ||
| 6408 | change and the actual processing. This makes it natural and easy to | ||
| 6409 | process the changes at a larger granularity, such as once per command, | ||
| 6410 | and eliminates most of the restrictions that apply to the usual change | ||
| 6411 | hook functions, making it possible to use blocking operations or to | ||
| 6412 | modify the buffer. | ||
| 6413 | |||
| 6414 | To start tracking changes, you have to call | ||
| 6415 | @code{track-changes-register}, passing it a @var{signal} function as | ||
| 6416 | argument. This returns a tracker @var{id} which is used to identify | ||
| 6417 | your change tracker to the other functions of the library. | ||
| 6418 | When the buffer is modified, the library calls the @var{signal} | ||
| 6419 | function to inform you of that change and immediately starts | ||
| 6420 | accumulating subsequent changes into a single combined change. | ||
| 6421 | The @var{signal} function serves only to warn that a modification | ||
| 6422 | occurred but does not receive a description of the change. Also the | ||
| 6423 | library will not call it again until after you retrieved the change. | ||
| 6424 | |||
| 6425 | To retrieve changes, you need to call @code{track-changes-fetch}, which | ||
| 6426 | provides you with the bounds of the changes accumulated since the | ||
| 6427 | last call, as well as the previous content of that region. It also | ||
| 6428 | ``re-arms'' the @var{signal} function so that the library will call it | ||
| 6429 | again after the next buffer modification. | ||
| 6430 | |||
| 6431 | @defun track-changes-register signal &key nobefore disjoint immediate | ||
| 6432 | This function creates a new @dfn{change tracker}. Change trackers are kept | ||
| 6433 | abstract, so we refer to them as mere identities, and the function thus | ||
| 6434 | returns the tracker's @var{id}. | ||
| 6435 | |||
| 6436 | @var{signal} is a function that the library will call to notify of | ||
| 6437 | a change. It will sometimes call it with a single argument and | ||
| 6438 | sometimes with two. Upon the first change to the buffer since this | ||
| 6439 | tracker last called @code{track-changes-fetch}, the library calls this | ||
| 6440 | @var{signal} function with a single argument holding the @var{id} of | ||
| 6441 | the tracker. | ||
| 6442 | |||
| 6443 | By default, the call to the @var{signal} function does not happen | ||
| 6444 | immediately, but is instead postponed with a 0 seconds timer | ||
| 6445 | (@pxref{Timers}). This is usually desired to make sure the @var{signal} | ||
| 6446 | function is not called too frequently and runs in a permissive context, | ||
| 6447 | freeing the client from performance concerns or worries about which | ||
| 6448 | operations might be problematic. If a client wants to have more | ||
| 6449 | control, they can provide a non-@code{nil} value as the @var{immediate} | ||
| 6450 | argument in which case the library calls the @var{signal} function | ||
| 6451 | directly from @code{after-change-functions}. Beware that it means that | ||
| 6452 | the @var{signal} function has to be careful not to modify the buffer or | ||
| 6453 | use operations that may block. | ||
| 6454 | |||
| 6455 | If you're not interested in the actual previous content of the buffer, | ||
| 6456 | but are using this library only for its ability to combine many small | ||
| 6457 | changes into a larger one and to delay the processing to a more | ||
| 6458 | convenient time, you can specify a non-@code{nil} value for the | ||
| 6459 | @var{nobefore} argument. In that case, @code{track-change-fetch} | ||
| 6460 | provides you only with the length of the previous content, just like | ||
| 6461 | @code{after-change-functions}. It also allows the library to save | ||
| 6462 | some work. | ||
| 6463 | |||
| 6464 | While you may like to accumulate many small changes into larger ones, | ||
| 6465 | you may not want to do that if the changes are too far apart. If you | ||
| 6466 | specify a non-@code{nil} value for the @var{disjoint} argument, the library | ||
| 6467 | will let you know when a change is about to occur ``far'' from the | ||
| 6468 | currently pending ones by calling the @var{signal} function right away, | ||
| 6469 | passing it two arguments this time: the @var{id} of the tracker, and the | ||
| 6470 | number of characters that separates the upcoming change from the | ||
| 6471 | already pending changes. This in itself does not prevent combining this | ||
| 6472 | new change with the previous ones, so if you think the upcoming change | ||
| 6473 | is indeed too far, you need to call @code{track-change-fetch} | ||
| 6474 | right away. | ||
| 6475 | Beware that when the @var{signal} function is called because of | ||
| 6476 | a disjoint change, this happens directly from | ||
| 6477 | @code{before-change-functions}, so the usual restrictions apply about | ||
| 6478 | modifying the buffer or using operations that may block. | ||
| 6479 | @end defun | ||
| 6480 | |||
| 6481 | @defun track-changes-fetch id func | ||
| 6482 | This is the function that lets you find out what has changed in the | ||
| 6483 | buffer. By providing the tracker @var{id} you let the library figure | ||
| 6484 | out which changes have already been seen by your tracker. Instead of | ||
| 6485 | returning a description of the changes, @code{track-changes-fetch} calls | ||
| 6486 | the @var{func} function with that description in the form of | ||
| 6487 | 3 arguments: @var{beg}, @var{end}, and @var{before}, where | ||
| 6488 | @code{@var{beg}..@var{end}} delimit the region that was modified and | ||
| 6489 | @var{before} describes the previous content of that region. | ||
| 6490 | Usually @var{before} is a string containing the previous text of the | ||
| 6491 | modified region, but if you specified a non-@code{nil} @var{nobefore} argument | ||
| 6492 | to @code{track-changes-register}, then it is replaced by the number of | ||
| 6493 | characters of that previous text. | ||
| 6494 | |||
| 6495 | In case no changes occurred since the last call, | ||
| 6496 | @code{track-changes-fetch} simply does not call @var{func} and returns | ||
| 6497 | @code{nil}. If changes did occur, it calls @var{func} and returns the value | ||
| 6498 | returned by @var{func}. But note that @var{func} is called just once | ||
| 6499 | regardless of how many changes occurred: those are summarized into | ||
| 6500 | a single @var{beg}/@var{end}/@var{before} triplet. | ||
| 6501 | |||
| 6502 | In some cases, the library is not properly notified of all changes, | ||
| 6503 | for example because of a bug in the low-level C code or because of an | ||
| 6504 | improper use of @code{inhibit-modification-hooks}. When it detects such | ||
| 6505 | a problem, @var{func} receives a @code{@var{beg}..@var{end}} region | ||
| 6506 | which covers the whole buffer and the @var{before} argument is the | ||
| 6507 | symbol @code{error} to indicate that the library was unable to determine | ||
| 6508 | what was changed. | ||
| 6509 | |||
| 6510 | Once @var{func} finishes, @code{track-changes-fetch} re-enables the | ||
| 6511 | @var{signal} function so that it will be called the next time a change | ||
| 6512 | occurs. This is the reason why it calls @var{func} instead of returning | ||
| 6513 | a description: it lets you process the change without worrying about the | ||
| 6514 | risk that the @var{signal} function gets triggered in the middle of it, | ||
| 6515 | because the @var{signal} is re-enabled only after @var{func} finishes. | ||
| 6516 | @end defun | ||
| 6517 | |||
| 6518 | @defun track-changes-unregister id | ||
| 6519 | This function tells the library that the tracker @var{id} does not need | ||
| 6520 | to know about buffer changes any more. Most clients will never want to | ||
| 6521 | stop tracking changes, but for clients such as minor modes, it is | ||
| 6522 | important to call this function when the minor mode is disabled, | ||
| 6523 | otherwise the tracker will keep accumulating changes and consume more | ||
| 6524 | and more resources. | ||
| 6525 | @end defun | ||