emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Ihor Radchenko <yantar92@posteo.net>
To: Nathaniel Nicandro <nathanielnicandro@gmail.com>
Cc: emacs-orgmode <emacs-orgmode@gnu.org>
Subject: Re: [PATCH] Highlight ANSI sequences in the whole buffer  (was [PATCH] ANSI color on example blocks and fixed width elements)
Date: Fri, 14 Apr 2023 08:49:48 +0000	[thread overview]
Message-ID: <877cueonkj.fsf@localhost> (raw)
In-Reply-To: <878rev1q0k.fsf@gmail.com>

Nathaniel Nicandro <nathanielnicandro@gmail.com> writes:

>> Ideally, fontifying ANSI sequences should be fully controlled by users:
>> 1. We may not want to touch src blocks by default, when
>>    `org-src-fontify-natively' is set to t. Only, maybe, provide an
>>    option. Or you may better publish a minor mode that does this for
>>    shell scripts.
>> 2. We may allow all the ANSI sequences to be fontified in the whole
>>    buffer.
>
> I've updated my patch to be a combination of (1) and (2), see the
> attached patch.  Essentially every sequence is fontified except those in
> source blocks and a minor mode has been created to allow users to
> disable or enable fontification whenever they want.
>
> I've also attached an example Org file with some ANSI sequences in it
> for testing purposes that you can try out.

Thanks!

> One issue that remains is how to handle sequences within inline source
> blocks.  Those don't have a src-block property so any sequences within
> an inline source block are currently fontified.

You should not use 'src-block property at all. There are scenarios when
jit-lock defers source block fontification (in particular, when source
block spans beyond the screen) and 'src-block property is not yet
applied.

Instead, you should query `org-element-at-point' or
`org-element-context'.

> +*** ANSI escape sequences are now highlighted in the whole buffer
> +
> +A new customization ~org-fontify-ansi-sequences~ is available which
> +tells Org to highlight all ANSI sequences in the buffer if non-nil and
> +the new minor mode ~org-ansi-mode~ is enabled.
> +
> +To disable highlighting of the sequences you can either
> +disable ~org-ansi-mode~ or set ~org-fontify-ansi-sequences~ to ~nil~
> +and =M-x revert-buffer RET=.  Doing the latter will disable
> +highlighting of sequences in all newly opened Org buffers whereas
> +doing the former disables highlighting locally to the current buffer.

Rather than asking to use revert-buffer, we usually suggest M-x
org-mode-restart.

> +(defun org-fontify-ansi-sequences (limit)
> +  "Fontify ANSI sequences."
> +  (when (and org-fontify-ansi-sequences org-ansi-mode)
> +    (let (end)
> +      (while (/= (point) limit)

Instead of this strict condition and later juggle with
`narrow-to-region', just use the usual (while (< (point) limit) ...).

> +        (cond
> +         ((get-text-property (point) 'src-block)

As I mentioned above, please use `org-element-at-point'. This function
will also give you information about the block boundaries.

> +            (ansi-color-apply-on-region (point) end t)

We should probably limit ANSI colour pairs to a single Org element. It
does not make much sense to have text in-between the quotes below
coloured:

#+begin_quote
... <opening ANSI def> ...
#+end_quote

....

#+begin_quote
... <closing ANSI def> ...
#+end_quote

> +            ;; Reset the context before every fontification cycle.  This
> +            ;; avoids issues where `ansi-color-apply-on-region' attempts to
> +            ;; use an old starting point that may be from a different part
> +            ;; of the buffer, leading to "wrong side of point" errors.
> +            (setq ansi-color-context-region nil)

This looks fragile. AFAIU, `ansi-color-context-region' is used to track
currently active ANSI colour settings. Since your fontification function
may be called with various LIMITs, depending on what is displayed on the
user screen, the fontification results might be unpredictable for ANSI
defs spanning across multiple screens.

> +(defvar org-ansi-colors
> +  '(black red green yellow blue purple cyan white))
> +
> +(defun org-ansi-highlight (beg end seq)
> +  (save-excursion
> +    (goto-char end)
> +    (insert "\e")
> +    (insert "[0m")
> +    (goto-char beg)
> +    (insert "\e")
> +    (insert (format "[%sm" seq))))
> +
> +(defun org-ansi-highlight-foreground (beg end color)
> +  "Highlight the foreground between BEG and END with COLOR."
> +  (interactive
> +   (let ((bounds (car (region-bounds))))
> +     (list (car bounds) (cdr bounds) 
> +           (completing-read "Color: " org-ansi-colors nil t))))
> +  (let ((n (- (length org-ansi-colors)
> +              (length (memq color org-ansi-colors)))))
> +    (org-ansi-highlight beg end (+ 30 n))))
> +
> +(defun org-ansi-highlight-background (beg end color)
> +  "Highlight the background between BEG and END with COLOR."
> +  (interactive
> +   (let ((bounds (car (region-bounds))))
> +     (list (car bounds) (cdr bounds) 
> +           (completing-read "Color: " org-ansi-colors nil t))))
> +  (let ((n (- (length org-ansi-colors)
> +              (length (memq color org-ansi-colors)))))
> +    (org-ansi-highlight beg end (+ 40 n))))

The above has no relation to fontification and does not belong to Org in
general. Org syntax has no notion of ANSI escapes. We may support them
as a useful feature, but no more. Editing ANSI escapes would make more
sense in shell-script-mode or similar.

> +  :lighter " OANSI"
> +  (cond
> +   ((and org-fontify-ansi-sequences org-ansi-mode)
> +    (remove-text-properties (point-min) (point-max) '(fontified t))
> +    (font-lock-ensure))

Just use `org-restart-font-lock'.

> +   (t
> +    (dolist (ov (overlays-in (point-min) (point-max)))
> +      ;; Attempt to find ANSI specific overlays.  See
> +      ;; `ansi-color-make-extent'.
> +      (when (eq (car-safe (overlay-get ov 'insert-behind-hooks))
> +                'ansi-color-freeze-overlay)

This is extremely awkward and relies on internal implementation details
of ansi-color. Moreover, we must avoid overlays, if possible - they do
not scale well. I recommend re-defining `ansi-color-apply-face-function'
to something that uses text properties. Using text properties will also
make restarting font-lock sufficient to clear the fontification.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


  reply	other threads:[~2023-04-14  8:48 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-05 12:03 [PATCH] ANSI color on example blocks and fixed width elements Nathaniel Nicandro
2023-04-05 13:43 ` Ihor Radchenko
2023-04-13 20:18   ` [PATCH] Highlight ANSI sequences in the whole buffer (was [PATCH] ANSI color on example blocks and fixed width elements) Nathaniel Nicandro
2023-04-14  8:49     ` Ihor Radchenko [this message]
2023-04-25 20:33       ` Nathaniel Nicandro
2023-05-10 10:27         ` Ihor Radchenko
2023-05-15  0:18           ` Nathaniel Nicandro
2023-05-18 19:45             ` Ihor Radchenko
2023-05-23  0:55               ` Nathaniel Nicandro
2023-08-08 11:02                 ` Ihor Radchenko
2023-11-08  9:56                   ` Ihor Radchenko
2023-11-08 15:35                   ` Nathaniel Nicandro
2023-11-10 10:25                     ` Ihor Radchenko
2023-11-17 21:18               ` Nathaniel Nicandro
2023-12-14 14:34                 ` Ihor Radchenko
2023-12-24 12:49                   ` Nathaniel Nicandro
2024-01-17  0:02                   ` Nathaniel Nicandro
2024-01-17 12:36                     ` Ihor Radchenko
2024-03-26 14:02                       ` Nathaniel Nicandro
2024-03-28  8:52                         ` Ihor Radchenko
2023-12-14 14:37                 ` Ihor Radchenko
2023-12-15 12:50                   ` Matt
2023-12-25  2:20                     ` Nathaniel Nicandro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877cueonkj.fsf@localhost \
    --to=yantar92@posteo.net \
    --cc=emacs-orgmode@gnu.org \
    --cc=nathanielnicandro@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).