allegro-cl archives 1997-10-7 | home index prev H thread-prev K thread next J next L |
From: Erik Naggum Subject: Re: xemacs lisp listener buffer max size Date: 1997-10-7 18:27 | This proposal is simple, provided one is willing to do a little elisp | programming, but consider this thought experiment: | | (defun tailify-buffer (lines) | "Truncate the current buffer to the last n LINES." | (interactive "nNumber of lines: ") | (let (beg end) | (save-excursion | (end-of-buffer) | (forward-line (- lines)) | (setq end (point)) | (beginning-of-buffer) | (setq beg (point))) | (delete-region beg end))) as an Emacs maintainer, it pains me to see this code. Hans Chalupsky's advice (pun intended) is much to be preferred, but see below. both `end-of-buffer' and `beginning-of-buffer' have a strong warning in their documentation not to use them in Lisp programs. ("Don't use this command in Lisp programs!") instead, use (goto-char (point-min)) and (goto-char (point-max)), respectively. (but this is also unnecessary in this case.) we need to be careful about a few things when deleting text from the start of a buffer. first, when deleting text, Emacs moves the "gap" to the deletion point and then it is moved again when the next insertion arrives at the end. the "gap" is just that, a gap between two halves of a buffer where all editing operations are performed. moving it or expanding it unnecessarily is the major source of CPU usage in badly written Emacs Lisp code. (not that anybody gives any guidance to Emacs Lisp programmers about it, however.) it's therefore prudent to do something like Hans Chalupsky's 90%-full solution. there is no guarantee that the buffer will actually shrink from this exercise, either, and many small deletions may yet cause Emacs to grow without bound over time. second, the undo list is a user feature, and should not have stuff like this added to it. ideally, the undo list should not affect process output to a buffer, but this is on our to-do list. until an Emacs-wide solution is made available, programmers of functions that insert text into buffers from inferior processes must take care to bind `buffer-undo-list' to t dynamically over their insertion. third, a user may have narrowed the buffer by the time these functions are called. (this problem also applies to Hans Chalupsky's code.) this code, replacing the meat of Hans' code, takes care of these problems (save-excursion (set-buffer buffer) (if (< max-acl-buffer-size (buffer-size)) (save-restriction (widen) (let ((buffer-undo-list t)) (delete-region (point-min) (- (point-max) (truncate max-acl-buffer-size 1.1111111))))))) | Emacs is very reticent to throw anything away. well. `undo-limit' (20000) and `undo-strong-limit' (30000) are the upper limits to how much undo information is kept, in bytes. see their documentation. | You can control this, assuming you don't really need undo | to be available in this buffer. See buffer-disable-undo. hm. the FI package should not introduce process output to the undo list to begin with. continuous output to the Lisp process buffer will be made into one, giant undo item. once past `undo-strong-limit' in length, it will be nuked during garbage collection. in any case, (buffer-disable-undo) is exactly like (setq buffer-undo-list t). process filters have a nasty habit of changing this value if not written super-correctly, so it wouldn't hurt to "reinforce" the binding. | I believe to buffer-disable-undo appearently flushes all undo information | (but check -- undo informtion is kept in a buffer-local variable -- see | buffer-local-variables). It need be called just once, but is probably | harmless to call repeatedly. the undo information is kept in `buffer-undo-list'. undo information is added to the head of the list in this variable, unless it is t, in which case undo information is discarded. | See the emacs-lisp source file fi-subproc.el. There is an undocumented | hook variable fi::subprocess-filter-insert-output-hook which I believe is | unused except by the "presenting listener" in Composer. It could | probably be used in the initial lisp listener to call tailify-buffer, | something like this, after the ACL has started in the buffer: this is cool. this is even better than Hans Chalupsky's advice. | (save-excursion | (set-buffer "*common-lisp*") | (buffer-disable-undo) | ;; This will be called each time CL output is inserted into the buffer, | ;; just before the output is inserted. | (setq fi::subprocess-filter-insert-output-hook 'tailify-1000)) but _please_ don't nuke hooks. hooks are magic, and should be added to with `add-hook' and removed from with `remove-hook', which keeps magic working. | None of this is checked, and anyone who uses it would have to take the | responsibility for debugging it, supporting it, and keeping up with | future versions. new releases of "comint" in the standard Emacs distribution obey a variable `comint-buffer-maximum-size' if `comint-truncate-buffer' is on the filter functions list. I would suggest that the FI package adopt the newer "comint" version and only add to it where absolutely necessary. #\Erik |