I am trying to override the tidy.source
function of the knitr
package. The problem is that tidy.source
is defined in the formatR
package, which is imported by the knitr
package.
If I run:
get("tidy.source", envir=asNamespace("knitr"))
I get the original code.
So I am tempted to override tidy.source
with:
assignInNamespace ("tidy.source", function()print("My tidy.source"), "knitr")
,
but I get:
Error in bindingIsLocked(x, ns) : no binding for "tidy.source"
.
In fact tidy.source
is defined in formatR
and inherited by knitr
. With:
assignInNamespace ("tidy.source", function()print("My tidy.source"), "formatR")
everything is apparently smooth, but checking again get("tidy.source", envir=asNamespace("knitr"))
shows that inside knitr
nothing has changed.
Any help?
This question is partly obsolete due to the new development release of knitr/formatR. Many thanks to Yihui for noticing this discussion and for deciding to update his package. See:
https://github.com/yihui/formatR/commit/6f70360f359caa8d2bb33190a1c89530defb0e98
I can definitely switch from Sweave to knitr.
The general question concerning the overriding of an imported package function remains anyway open. Since it is not related to knitr/formatR package anymore, I restate it in more general terms.
Suppose you have a package main importing the package imp. If you load the former, "package:main"
shows in the list of the attached packages and both "main"
and "sub"
show among the names of the loaded namespaces.
Assume that main imports the exported sub function exp.sub.func, which calls in turns the non-exported sub function prv.sub.func. If you want to change/customise exp.sub.func with your exp.sub.func.mod, you may think of using:
assign("exp.sub.func", exp.sub.func.mod, asNamespace ("sub"))
As a result, by running sub::exp.sub.func
you will get your patched version (that is exp.sub.func.mod).
Unfortunately, as far as your exp.sub.func.mod keeps on relying on prv.sub.func, you get the error:
Error in [...] : object 'prv.sub.func' not found
In fact:
environment(sub::exp.sub.func)
returns now: <environment: R_GlobalEnv>
while it was <environment: namespace:sub>
before patching.
The question is: how to move the patched function to the proper namespace?
To implement the problem above you can use whatever packages of course; in my case I used knitr and formatR as main and imported namespace and tidy.source() as patched function.
Changing the function in the formatR namespace doesn't change what knitr uses because knitr is already loaded. So, you could unload and reload it.
assignInNamespace("tidy.source", function()print("My tidy.source"), "formatR")
detach('package:knitr', unload=TRUE)
library(knitr)
get("tidy.source", envir=asNamespace("knitr"))
#function()print("My tidy.source")
If all you want is comments after function arguments, I have added the support in the development version, and you can install it from Github.
Normally it is a bad idea to modify packages using assignInNamespace()
, as its documentation shows.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With