all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Paul Pogonyshev <pogonyshev@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Emacs developers <emacs-devel@gnu.org>
Subject: Re: Signal `quit' in a `font-lock-fontify-region-function'
Date: Sun, 30 Jun 2019 01:49:46 +0200	[thread overview]
Message-ID: <CAG7Bpaq3_LkrDQ3qrd19pKtJcWT0GOa0YJTjnGopYrJc8K-hwQ@mail.gmail.com> (raw)
In-Reply-To: <jwv36jsm72h.fsf-monnier+emacs@gnu.org>

On Sat, 29 Jun 2019 at 23:26, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>
> > I'm not sure if this is flexible enough.  I don't like the idea of C-g
> > already invoking some code (that e.g. disables font-locking).
>
> [...] It definitely wouldn't disable font-locking right away.
>
> The disabling would only be in response to a "large" number of C-g,
> which presumably should only be needed in extreme circumstances
> (basically when currently the user ends up killing Emacs instead).

So, basically, as I understand, C-g handler in your proposal would
look like (I know it is in C code, but...), simplified:

    (defun handle-C-g (...)
      (when registered-many-C-g-callback  ; variable set by e.g.
font-locking code
        (setq num-C-g-presses (1+ num-C-g-presses))
        (when (> num-C-g-presses 3)
          (funcall registered-many-C-g-callback))))

and font-locking code would be roughly

    (let ((registered-many-C-g-callback (lambda () (setq font-lock-mode nil))))
      ; call fontification function, process its result etc.
      )

That's what I meant: here `handle-C-g' already invokes some callback
that higher level (in this case font-locking) registers.

I propose that instead font-locking code simply says "I will process
multiple C-g presses somehow, please count them" by let-binding
`count-C-g-presses' to t.  The idea is to not invoke the "abort"
callback immediately when the 3rd C-g is pressed, but instead let the
iteration finish gracefully and _then_ let the higher-level code
(font-locking) abort or not based on all the information it has by
now.  Usually this information would be just result of
`(too-many-C-g-recently)', but could be anything in the future, so we
are more flexible.

> > So, I'd like to be able to _handle_ `quit' signal in the function
> > itself and stop extending the region and return immediately, so that I
> > don't throw away work on a considerable region of text that has been
> > done already.
>
> I don't understand why you say "don't throw away work on a considerable
> region of text that has been done already": if you're in the middle of
> extending the region, presumably no "work" has been done yet.

For example, my function decides to fontify 1000 lines of text and by
the time C-g is pressed (triggering the signal) it has already
fontified 500 of them (this is already more than what font-locking
code wanted, because I extended the requested region).  I'd like to be
able to notify font-locking code about the work that has been done,
even if I planned to do even more.  If I raise `quit' signal or let
C-g raise it by default, all this work is thrown away.

> Could `while-no-input` be usable in this case?

This macro uses `with-local-quit', which, as I understand will rethrow
signal `quit' after the body.  As a result, font-locking code will
still see my function terminate non-locally, deem the whole invocation
failed and set property `fontified' to nil.  So no, to achive what I
want I need to let my function return normally somehow.

>
> > I'm not sure if it is the best solution, but I'd propose C-g to be
> > counted not when `quit' signal is caught, but when it would be
> > emitted, even if `inhibit-quit' is t.  And font-locking code would
> > look something like this: [...]
>
> I think if C-g resulted in (signal 'quit ...), then presumably we exited
> this code, so the only really interesting case should be the one where
> we just have `quit-flag` set to t.

Yes, but the point is in that I want to avoid C-g resulting in the
signal by binding `inhibit-quit' inside my fontification function.
But still have C-g handler note that C-g is pressed and let
fontification code find if it is being pressed too often.

> Maybe we should change the C-g code so it sets `quit-flag` to the
> number of C-g that are pending.

This generally sounds like a good idea: I'm always in favour of having
more information.  However, in my case it is not enough.

I guess it is easier to explain by pseudocode of my fontification
function:

    (defun my--fontify-region (region-start region-end _loudly)
      ;; Very fast, so always work on large regions to avoid setup overhead.
      (setq region-end (+ region-start 50000))
      ;; Here comes some internal setup.
      ...
      (let ((fontified-up-to region-start)
            (inhibit-quit    t))
        ;; While `quit' is inhibitted, the below loop will still be
aborted on C-g.
        (while (and (< fontified-up-to region-end) (null quit-flag))
          ...  ; do some work on the next small chunk of text; this is
very fast,
               ; but as the region is quite big, the loop is iterated many times
          )
        ;; Always exit normally.  Font-locking code will find out if
we suppressed
        ;; a C-g through other means, i.e. using (too-many-C-g-recently).
        (setq quit-flag nil)
        `(jit-lock-bounds ,region-start . ,fontified-up-to)))

Note that the function doesn't suppress any other signals/errors.

Paul



  reply	other threads:[~2019-06-29 23:49 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-29 17:50 Signal `quit' in a `font-lock-fontify-region-function' Paul Pogonyshev
2019-06-29 21:26 ` Stefan Monnier
2019-06-29 23:49   ` Paul Pogonyshev [this message]
2019-06-30  0:18     ` Stefan Monnier
2019-06-30 10:51       ` Paul Pogonyshev
  -- strict thread matches above, loose matches on Subject: below --
2019-05-28 16:24 Paul Pogonyshev
2019-05-28 17:50 ` Stefan Monnier
2019-05-28 18:14   ` Paul Pogonyshev
2019-05-28 18:24     ` Stefan Monnier
2019-05-16 22:20 Paul Pogonyshev
2019-05-16 23:20 ` Stefan Monnier

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

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

  git send-email \
    --in-reply-to=CAG7Bpaq3_LkrDQ3qrd19pKtJcWT0GOa0YJTjnGopYrJc8K-hwQ@mail.gmail.com \
    --to=pogonyshev@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.