1

I want to detect line change event (arrow-,arrow- or mouse click) to trigger my function call.

Below example handled arrow- arrow- but can not handle mouse click or C-n C-p line change event.

(defun myup(n)
  (interactive "p")
  (previous-line)
  (showme))

(defun mynext(n)
  (interactive "p")
  (next-line)
  (showme))

(defun showme()
  (let ((line (thing-at-point 'line t)))
    (when (string-match  "\\[\\([0-9a-f]+\\)\\]" line)
      (setq sha1 (match-string 1 line))
      (setq bufname "differ")
      (when (= (length (window-list)) 1)
        (split-window-vertically (floor (* 0.2 (window-height))))
        )
      (setq buffer (get-buffer-create bufname))
      (switch-to-buffer-other-window buffer)
      (erase-buffer)
      (insert sha1)
      (goto-char (point-min))
      (other-window 1))))

(define-key diff-mode-map  (kbd "<down>") 'mynext)
(define-key diff-mode-map  (kbd "<up>") 'myup)

What's right way to handle this case?

2

The answer to “I want to detect (…) event” is usually to use the appropriate hook. The manual has a list of standard hooks. There's no hook that triggers on a line change, so the next thing is to look for a hook that triggers on any motion. There's no hook specifically for that either, to you're down to a hook that runs every command.

Keep track of the current line number in a variable, and run the desired code whenever that value changes. Untested proof-of-concept:

(defvar showme-last-position nil)
(make-variable-buffer-local 'showme-last-line)
(defun showme-is-on-different-line (marker)
  "Returns true if MARKER and point are on different lines."
  (save-excursion
    (if (< showme-last-position (point))
        (progn
          (beginning-of-line)
          (< showme-last-position (point)))
      (end-of-line)
      (> showme-last-position (point)))))
(defun showme-if-needed ()
  ;; Create marker if needed
  (if (null showme-last-position)
      (setq showme-last-position (make-marker)))
  ;; Is marker on a different line from point, or uninitialized?
  (when (or (null (marker-position showme-last-position))
            (showme-is-on-different-line showme-last-position))
      ;; Update marker and run showme
      (set-marker-position showme-last-position (point))
      (showme)))

(Note that my way of detecting a line change is faster than recomputing the line number — line-number-at-pos can be slow in a large file.)

I haven't reviewed your code, there may be a better trigger than a change in the line number. You may want to preprocess the buffer and add overlays. Font Lock mode has facilities for that, and can do the job lazily based on what parts of the buffer get shown so that opening a large file doesn't take forever.

One thing I do notice in your code is that the way you return to the original buffer and window is unreliable: other-window might not do the right thing depending on the window configuration. Whenever you want to move and then return to the original place, use save-excursion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.