1

Functions from some packages perform actions, but instead of returning the result directly, they display it in the message area using the message function. This appears to make composing such functions harder. The general question here is how to capture the message-emitted content without modifying the function itself (which would be messy).

An example is the git-link package and its git-link function. See git-link--new, called at the end of git-link:

(defun git-link--new (link)
  (kill-new link)
  ;; prevent URL escapes from being interpreted as format strings
  (message (replace-regexp-in-string "%" "%%" link t t))
  (setq deactivate-mark t)
  (when git-link-open-in-browser
    (browse-url link)))

I'm trying to make a wrapper for the git-link function to have git-link output into MacOS pbcopy - to have the git link automatically go into the MacOS copy buffer.

The git-link function however doesn't have a return value and it is difficult to work with its output without modifying the git-link package. Is it possible to capture what the function prints in the message area from a wrapper function, without modifying the original function itself?

Edit: based on the answer below and this gist this appears to do the job

(defun paste-to-osx (text)
    (let ((process-connection-type nil))
      (let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
        (process-send-string proc text)
        (process-send-eof proc))))

(defun pbcopy-git-link ()
  (interactive)
  (call-interactively 'git-link)
  (paste-to-osx (current-kill 0))
)

The other answer (that uses function advising) appears to be a solution for the general case.

4
  • IMO, scraping the text of a log message (the actual text as opposed to a status) to base your future processing on is a bad idea - sometimes that's a necessary evil, but it should be avoided if at all possible. In this case, the log message is a mangled version of what really matters, which is the link variable: the function gratuitously modifies that link (for no good reason actually) in order to use it in the log message, so if you copy that you have lost information. Getting the link out of the kill ring is probably the best (or maybe I should say the least worst) that you can do.
    – NickD
    Commented Jan 11, 2023 at 12:54
  • That's a good point. That's a critique of the git-link library (it must be a gentle one since it's free). Anyway, should the (git-link)[github.com/sshaw/git-link/blob/master/git-link.el#L730] function have just returned the link variable?
    – anon2328
    Commented Jan 11, 2023 at 14:11
  • Instead of mangling the link, they could do (message "%s" link) in order to avoid the problem. But I didn't mean it as a criticism of git-link: it was more a recommendation addressed to your request for capturing the message output. All I'm saying is: if you can get whatever you need in a way other than log scraping, you should probably go that way. It's not a panacea (e.g. using current-kill depends on the function doing kill-new so if that ever changes, it's going to break your function). And none of this is to be taken as an absolute prohibition: you do what you have to do...
    – NickD
    Commented Jan 11, 2023 at 14:19
  • Right, the current pattern is similar to a "format string vulnerability", whereby the mangling fixes the issues from the bug. Adding "%s" would remove the need for any mangling.
    – anon2328
    Commented Jan 11, 2023 at 18:55

2 Answers 2

2

Since it calls kill-new to insert the link into the kill-ring, you could just call current-kill to retrieve it.

1

You should be able to advise the git-link--new function with one that copies the current message to the kill ring. Like this:

(defun test-message-foo nil
  (message "foo"))

(defun kill-test-message-foo nil
  (kill-new (current-message)))

(advice-add 'test-message-foo :after 'kill-test-message-foo)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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