0

I want to write an advice on original code. But don't know how to write it in my case. I just did some modification, and do an diff. Hope the you can understand what I need.

Here is the diff screenshot output:

enter image description here

And diff:

*** /tmp/org-babel-expand-1.el  2018-02-14 11:54:36.225719891 +0800
--- /tmp/org-babel-expand-2.el  2018-02-14 11:54:42.471852389 +0800
***************
*** 10,16 ****
                             (lambda (var)
                               (format "%S (quote %S)" (car var) (cdr var)))
                             vars "\n      ")
!                           "]\n" body ")")))))
      (if (or (member "code" result-params)
              (member "pp" result-params))
          (format "(clojure.pprint/pprint (do %s))" body)
--- 10,29 ----
                             (lambda (var)
                               (format "%S (quote %S)" (car var) (cdr var)))
                             vars "\n      ")
!                           "]\n" body ")"))))
!          (directory (and (buffer-file-name)
!                          (file-name-directory (buffer-file-name))))
!          (out-file (cdr (assq :file params)))
!          (add-to-body (lambda (code)
!                         (setq body (concat code "\n" body))))
!          )
!     (when directory
!       (funcall add-to-body (format "(System/setProperty 'user.dir' '%s')" directory)))
!     (when out-file
!       (funcall
!        add-to-body
!        (format "(save ob-clojure-incanter-plot '%s')" ; use static variable as convention.
!                (concat directory out-file))))
      (if (or (member "code" result-params)
              (member "pp" result-params))
          (format "(clojure.pprint/pprint (do %s))" body)
  • That's just not how advice works. I suspect you should simply redefine the function (as you have shown). Use with-eval-after-load to avoid your definition being evaluated until after the library in question has been loaded (as otherwise it would clobber your definition with the original definition, instead of the other way around). – phils Feb 14 '18 at 5:32
2

If you want to replace the full body of a function an :override advice is appropriate. I give a general example for replacing the functionality of fun with that of override-fun:

(defun override-fun (args as for fun)
  "Implement here the new functionality of fun."
  ...)

(advice-add 'fun :override #'override-fun)

But in your case maybe even a :filter-args advice fits better your purpose since you just want to modify the argument "body".

(defun filter-args-org-babel-expand-body:clojure (args)
  "Enrich BODY in ARGS with directory and out-file.
This can be used as :filter-args advice of `org-babel-expand-body:clojure'."
  (let* ((body (nth 0 args))
         (params (nth 1 args))
         (directory (and (buffer-file-name)
                         (file-name-directory (buffer-file-name))))
         (out-file (cdr (assq :file params)))
         (add-to-body (lambda (code)
                        (setq body (concat code "\n" body))))
         )
    (when directory
      (funcall add-to-body (format "(System/setProperty 'user.dir' '%s')" directory)))
    (when out-file
      (funcall
       add-to-body
       (format "(save ob-clojure-incanter-plot '%s')" ; use static variable as convention.
               (concat directory out-file))))
    (list body params) ;; return modified argument list
    ))

(advice-add 'org-babel-expand-body:clojure :filter-args #'filter-args-org-babel-expand-body:clojure)

As the documentation string for add-function explains the :filter-args: advice is applied as:

(apply #'org-babel-expand-body:clojure (filter-args-org-babel-expand-body:clojure (list body params)))

Remarks:

  • Advices are better than re-definitions (as suggested by phils) since the load order is not relevant and you can remove advices with advice-remove if they cause trouble.
  • You can also instrument the advice function for debugging to see how it works.
  • The code is untested (I don't have clojure.) Please, test it if you want to use it. -- I think the information about the principles is the most important part of this answer.
  • Another advantage of :override advice over redefinition is that it gets hyperlinked in the *Help* buffer. – Basil Feb 14 '18 at 14:12
  • Regarding the previous comment, as the source for the redefined function would also be hyperlinked in the help buffer, that's not actually another advantage. The fact that the source of the original definition also remains hyperlinked can be useful, however. – phils Feb 15 '18 at 1:19
  • Note that body was also used in the function code before it was manipulated, so your filter-args suggest may not be valid. – phils Feb 15 '18 at 1:22
  • I did a test, works for my need. Thanks guys. – stardiviner Feb 15 '18 at 3:47

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.