Subject: bug#56374: 27.2; Occur with non-contiguous regions

From: Magnus Nilsson <[email-masked]>
Date: Mon, 4 Jul 2022 09:12:03 +0200

Thanks for the swift reply Juri.

If "artificial resctrictions (...) should be lifted" means that rectangular
regions could start working with occur, that sounds great.

Regarding your question, I'm not aware of the possible dependencies between
perform-replace and occur. My intended use case is to have a separate
function to extract a non-contiguous region of my liking (i.e., in the form
of a list of cons cells of buffer positions) and have occur operate on that
list by passing it in as the "region" argument. That way, occur wouldn't
return any matches in the parts of the buffer I'm not interested in. I
interpreted the documentation of occur to support passing in region like
that, in particular from this formulation:
"REGION must be a list of (START . END) positions as returned by
`region-bounds'."

In elisp-code, this is how I changed occur to also support non-contiguous
regions according to my interpretation of the documentation:
------------ begin elisp-code ----------------------
    (defun my-occur (regexp &optional nlines region)
      "My fix to occur, which does not handle non-contiguous regions
    now. I filed a bug report for this."
      (interactive
       (nconc (occur-read-primary-args)
              (and (use-region-p) (list (region-bounds)))))
      (let ((bufs (list))
            (once t))
        (while (or region once)
          (let* ((start (and (caar region) (max (caar region) (point-min))))
                 (end (and (cdar region) (min (cdar region) (point-max))))
                 (in-region (or start end))
                 (buf (if (not in-region) (current-buffer)
                        (let ((ol (make-overlay
                                   (or start (point-min))
                                   (or end (point-max)))))
                          (overlay-put ol 'occur--orig-point (point))
                          ol))))
            (push buf bufs))
          (setq once nil)
          (setq region (cdr region)))
        (occur-1 regexp nlines bufs)))

    (defalias 'occur 'my-occur)
-------------- end elisp-code -----------------------------------------

Anyway, I'll leave it up to you to interpret the documentation and if it or
the code requires a fix.

Thanks again,
Magnus

Den mån 4 juli 2022 kl 08:35 skrev Juri Linkov <[email-masked]>:

> > In the help text for 'occur' it indicates that it should be able to work
> > on non-contiguous regions (i.e., a list of cons cells on the form (START
> > . END)). However, when I tried this in both Emacs 27 and 28, this
> > doesn't work when I mark a rectangular region. It only catches
> > occurrances found within the bounds of the first cons cell.
>
> Like bug#14013 now has a patch that implements support for any regexp
> including "^.*$" on a non-contiguous region, occur should be improved
> to use the same search function.  (Also all artificial restrictions
> on handling only the first cons cell in occur should be lifted.)
>
> > My intention was to override (region-bounds) within a let statement to
> > return a non-contiguous region of interest (in the form of a list of
> > cons cells) and let 'occur' work on that non-contiguous
> > region. Unfortunately, this didn't work out as I planned. It would be
> > neat if this could be fixed for upcoming versions.
>
> Do you expect that 'occur' should accept a non-contiguous region
> in its argument REGION?  This is not how perform-replace works.
> The query-replace commands send the boolean value of
> '(region-noncontiguous-p)' to perform-replace argument
> 'region-noncontiguous-p', then perform-replace extracts it with
> '(funcall region-extract-function 'bounds)'.
>
> Do you agree that 'occur' could do the same?
>