Re: Show/Don't show lines based on pattern...
"Stephen J. Turnbull" <[email protected]> Tue, 10 May 2005 12:18:45 +0900
| Newsgroups | gmane.emacs.xemacs.design |
|---|---|
| Organization | The XEmacs Project |
| Message-ID | <[email protected]> |
Since you expressed willingness to repost, I'll just forward this to xemacs-design (which is where new features should be discussed). If you think this is a good direction, feel free to discuss there. Since your current platform is GNU Emacs, feel free to add emacs-devel at any time. (I think they're in the process of beating a release into shape, so they may ask you to wait a bit on a new feature. For that reason you may want to get your proposal into shape before posting there, but that's up to you.) Any oddity is due to my cutting context, not Matthew's post! >>>>> "Matthew" == Matthew Miner <[email protected]> writes: Matthew> I'd already found hideshow and outline mode. The problem Matthew> is that they work very well with structured files (i.e., Matthew> those whose content and syntax is "well understood"), but Matthew> not-at-all with unstructured (e.g., text) files. Nothing is going to work with _truly_ unstructured text (e.g., James Joyce's _Ulysses_), if you see what I mean. The log files you're talking about have "record-per-line" structure, and you want to filter on a field in the record. I don't know if it matters that there is structure internal to the line; you might think about that (eg, for the purpose of hiding the date field---if you've already filtered down to one date, it's redundant, right?) Matthew> selectively display relevant lines (or hide irrelevant Matthew> lines), expand and contract hidden sections, etc. Thus Matthew> minimizing clutter, but providing context where desired. I'm not sure how to implement (ie, user interface and efficiency) the expand/contract feature, but basically what you want is the "invisible" text property. Here's a primitive implementation for XEmacs (in GNU Emacs you would use overlays or text properties): (defun filter-matching-lines (regexp mode tag) "Hide or restrict to lines matching REGEXP according to MODE. REGEXP is a regular expression which should be anchored at both ends. Ie, to hide \"hideme\", use \"^.*hideme.*$\". MODE is one of the symbols 'hide or 'restrict-to. [with obvious semantics] If MODE is nil, an appropriate extent will be tagged, but no action taken. TAG is a symbol which will be added to the 'filter-matching-lines-tagset property of matching extents. If TAG is nil, then MODE will be applied globally regardless of existing filtering. (interactive "sFilter (a regexp): \nSMode: \nSTag: ") (unless (string-match "^\\^[^^$]*\\$$" regexp) ;; GNU Emacs doesn't have structured errors (error 'invalid-regexp "must be anchored" regexp)) ;; I guess we should respect narrowing ... please let me know (save-excursion ; oops, forgot this, so indent is missing (goto-char (point-min)) (while (not (eobp)) (let ((bol (point)) (eol (let ((x (point-at-eol))) (if (< x (point-max) (1+ x) x)))) (e (extent-at bol nil 'filter-matching-lines-tagset)) (match-p (looking-at regexp))) (if e ;; canonicalize in case it used to be unterminate line at buffer end (set-extent-endpoints e bol eol) (setq e (make-extent bol eol)) ;; I don't know if this placeholder is needed (set-extent-property e 'filter-matching-lines-tagset (nil))) (when tag (let ((set (extent-property e 'filter-matching-lines-tagset))) (set-extent-property e 'filter-matching-lines-tagset (cons tag e (delq nil (delq tag set)))))) (if (not match-p) (cond ((eq mode 'hide) (set-extent-property e 'invisible nil)) ((eq mode 'restrict-to) (set-extent-property e 'invisible t))) (cond ((eq mode 'restrict-to) (set-extent-property e 'invisible nil)) ((eq mode 'hide) (set-extent-property e 'invisible t))))) (forward-line)))) (defun filter-lines (predicate mode) "Hide or restrict display to lines satisfying PREDICATE according to MODE. PREDICATE is function taking one argument, a list of symbols. MODE is a symbol, one of 'hide or 'restrict-to." (interactive "xFilter (a lambda expr): \nMode: ") (save-excursion (goto-char (point-min)) (while (not (eobp)) (let* ((e (extent-at bol nil 'filter-matching-lines-tagset)) ;; kludge -- will do the wrong thing if no property is set ;; but can't just error (suppose just one new line?) (ts (when e (extent-property e 'filter-matching-lines-tagset)))) (if (not (funcall predicate ts)) (cond ((eq mode 'hide) (set-extent-property e 'invisible nil)) ((eq mode 'restrict-to) (set-extent-property e 'invisible t))) (cond ((eq mode 'restrict-to) (set-extent-property e 'invisible nil)) ((eq mode 'hide) (set-extent-property e 'invisible t))))) (forward-line)))) Untested, but it might work. Very preliminary, but I think it should be clear where this is going. Also, the Gnus package has code for "washing" article buffers. There are functions for hiding quoted lines, etc. I don't know how generic they are, though. And I find Gnus code hard to abstract, so I just wrote up the above. However, if this is a useful facility to abstract, we might want to propose that Gnus use it, too. Matthew> If you feel this (or the next) is appropriate for group Matthew> posting, feel free or tell me and I'll repost. In general you should always reply to the group. If the person who responded first doesn't feel like answering again, somebody else may pick up the thread. Matthew> I often need the name of the current buffer name (or file Matthew> name) for use in a keystroke macro. I don't know of any standard way to do that kind of thing. Matthew> I finally wrote: Matthew> (defun insert-buffer-name-into-kill-ring () Using the kill ring in keyboard macros is kind of hazardous. Why not (defun insert-buffer-name () (interactive) (insert (buffer-name))) ? -- School of Systems and Information Engineering http://turnbull.sk.tsukuba.ac.jp University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN Ask not how you can "do" free software business; ask what your business can "do for" free software.