help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: buffer substring of only visible text


From: Felix Dietrich
Subject: Re: buffer substring of only visible text
Date: Wed, 21 Sep 2022 13:34:24 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.1 (gnu/linux)

Hello Samuel,

Samuel Wales <samologist@gmail.com> writes:

> i want to copy visible text from a region in a buffer, into a string.
> if any invisible regions are in the region, i want them to not be in
> the string.  that is, i want the visible intervals in the copied
> region to be merely appended.  when i INSERT the resulting string into
> the new buffer, i want any text properties that i specify to still
> exist.  htmlize.el has a function, buffer-substring-no-invisible,
> which does not include any text properties at all.  it works, but i'd
> like to include at least one text property, which i want to specify.
>
> i am looking for a know a cookbook formula to do this really
> straightforwardly.

I do not know any cookbook solution for this problem, but you have
already found a (fairly short and straightforward) function that almost
does what you described; with a few minor modifications you should be
able to get what you want (almost untested):

#+begin_src emacs-lisp
  (defun my/buffer-substring-with-properties (start end props)
    ;; Copy the specified property from the specified region of the
    ;; buffer to the target string.  We cannot rely on Emacs to copy the
    ;; property because we want to handle properties coming from both
    ;; text properties and overlays.
    (let ((text (buffer-substring-no-properties start end)))
      (dolist (p props)
        (htmlize-copy-prop p start end text))
      text))
  
  
  (defun my/buffer-substring-no-invisible (beg end &optional props)
    ;; Like buffer-substring-no-properties, but don't copy invisible
    ;; parts of the region.  Where buffer-substring-no-properties
    ;; mandates an ellipsis to be shown, htmlize-ellipsis is inserted.
    (let ((pos beg)
          visible-list invisible show last-show next-change)
      ;; Iterate over the changes in the `invisible' property and filter
      ;; out the portions where it's non-nil, i.e. where the text is
      ;; invisible.
      (while (< pos end)
        (setq invisible (get-char-property pos 'invisible)
              next-change (htmlize-next-change pos 'invisible end)
              show (htmlize-decode-invisibility-spec invisible))
        (cond ((eq show t)
               (push (my/buffer-substring-with-properties pos next-change
                                                          props)
                     visible-list))
              ((and (eq show 'ellipsis)
                    (not (eq last-show 'ellipsis))
                    ;; Conflate successive ellipses.
                    (push htmlize-ellipsis visible-list))))
        (setq pos next-change last-show show))
      (htmlize-concat (nreverse visible-list))))
#+end_src

The function ‘my/buffer-substring-no-invisible’ only adds an additional
parameter PROPS to ‘htmlize-buffer-substring-no-invisible’ and replaces
the call to ‘htmlize-get-text-with-display’ with a call to
‘my/buffer-substring-with-properties’ that takes the PROPS parameter to
copy not only the two fixed properties ‘display’ and ‘htmlize-link’, as
does ‘htmlize-get-text-with-display’, but allow specifying the desired
properties to copy when calling the function.

Text that has the ‘invisible’ property may be replaced with an ellipsis
(depending on ‘buffer-invisibility-spec’).  If you preferred there
rather be no ellipsis, adjust the cond-form or bind ‘htmlize-ellipsis’
to the empty string "".

As the comment at the top of ‘htmlize-copy-prop’ suggests, Emacs may
provide more efficient means to copy text properties if you do not need
the overlay properties.  I cannot help you with the details of that,
though, but maybe the sections on text and overlay properties in the
Emacs Lisp handbook can provide you with the necessary clues [1][2].

Footnotes:
[1]  (info "(elisp) Text Properties")
     
<https://www.gnu.org/software/emacs/manual/html_node/elisp/Text-Properties.html>

[2]  (info "(elisp) Overlay Properties")
     
<https://www.gnu.org/software/emacs/manual/html_node/elisp/Overlay-Properties.html>

-- 
Felix Dietrich



reply via email to

[Prev in Thread] Current Thread [Next in Thread]