purcell / whole-line-or-region

In Emacs, operate on current line if no region is active
116 stars 12 forks source link

Rewrite internals #13

Closed purcell closed 3 years ago

purcell commented 3 years ago

Plan would be to release this as v2.0

purcell commented 3 years ago

save column position, move to the beginning of the line, insert the text, restore column position

Yes, that's reasonable, and I can get that working sanely here, but the issue of mark position after C-w C-w C-y is still there. Can you share the code for your yank-handler?

gusbrs commented 3 years ago

Sure:

(defun gb/kill-dwim-whole-line-yank-handler (str)
  "Yank-handler for `gb/kill-dwim-base-call'."
  (let ((saved-column (current-column))
        (whole-line))
    ;; A whole-line killed from end of file may not have a trailing newline,
    ;; add one if missing.
    (unless (string-match "\n\\'" str)
      (setq str (concat str "\n")))
    ;; Check for active region and delsel before moving to BOL.
    ;; But we cannot check if the region is empty here, because
    ;; 'delete-selection-pre-hook' has already deleted the selection at this
    ;; stage, so that '(region-beginning)' and '(region-end)' will always be
    ;; equal.
    (unless (and (region-active-p) delete-selection-mode)
      (setq whole-line t)
      (beginning-of-line))
    (let ((beg-pos (point))
          (end-pos))
      ;; So we can honor the behavior of "C-u" to 'yank'.
      (push-mark (point) t)
      (insert str)
      (setq end-pos (point))
      ;; Remove excluded properties from yanked text.  It is necessary to use
      ;; the 'NOEXCLUDE' argument of 'yank-handler' and do this here, because
      ;; the handler moves point after inserting the text (see
      ;; 'image-file-yank-handler' for an example, and the docstring of
      ;; 'yank').
      (remove-yank-excluded-properties beg-pos end-pos)
      ;; Set yank-undo-function in order to support yank-pop properly (from
      ;; 'whole-line-or-region.el')
      (setq yank-undo-function
            (lambda (_beg _end) (delete-region beg-pos end-pos))))
    (when whole-line
      (move-to-column saved-column))))
purcell commented 3 years ago

I pushed some changes to use that approach, and now I feel like my yank handler is functionally identical to yours. But still, if I add the final assertion (should (equal (point-min) (mark))) to the wlr-consecutive-kill-region-combines-them test, the mark is not left in the desired place. So I'm not really sure what the issue is there.

purcell commented 3 years ago

Also I realised yesterday I'm not doing anything to test my handling of delete-selection-mode, which is annoying to use in tests because it's a global mode.

gusbrs commented 3 years ago

Try:

(defmacro whole-line-or-region-filter-with-yank-handler (&rest body)
  "Execute BODY with `filter-buffer-substring-function' bound.
The binding ensure killed strings have a yank handler attached."
  (let ((orig (cl-gensym)))
    `(let* ((,orig filter-buffer-substring-function)
            (filter-buffer-substring-function
             (lambda (&rest args)
               (let ((s (apply ,orig args)))
                 (put-text-property 0 (length s) 'yank-handler
                                    '(whole-line-or-region-yank-handler nil t)
                                    s)
                 s))))
       ,@body)))

But don't ask me why.... :shrug:

purcell commented 3 years ago

O M G

gusbrs commented 3 years ago

O M G

:smile: That's called "coding by luck".

I essentially tried to see what was different here. And that was it.

Again, I have no idea why propertize didn't work...

purcell commented 3 years ago

It looks like propertize adds the property to a copy of the original string, but it's indeed hard to see why that should make a difference.

Anyhow, I'm going to merge this now and tag it as 2.0. Thanks so much!

gusbrs commented 3 years ago

Anyhow, I'm going to merge this now and tag it as 2.0. Thanks so much!

Great! Thank you!

andersjohansson commented 3 years ago

This happened quickly! I offered to help testing changes in #9, but this seemed to involve many subtleties beyond my experience of Emacs’ killing and yanking functionality. And all this sorted out while I hadn’t even got to trying out the new code :slightly_smiling_face:. I’ll gladly try out 2.0 now and report any issues. Thank you!

purcell commented 3 years ago

And all this sorted out while I hadn’t even got to trying out the new code 🙂. I’ll gladly try out 2.0 now and report any issues. Thank you!

I cheated by doing most of the work months ago and switching to it locally over the last month before quickly releasing it. I'm a compulsive tidier.