简体   繁体   English

在RStudio中记录R包中的R6类和方法

[英]Documenting R6 classes and methods within R package in RStudio

I am struggling with the documentation of an R6 class and its methods. 我正在努力学习R6类及其方法的文档。 My goal is to get the autocompletion in RStudio for the methods. 我的目标是在RStudio中获取方法的自动完成。 At the moment, I only get the name of the method but no the help information I normally get using roxygen2 documenting a function with parameters etc. 目前,我只获取方法的名称,但没有通常使用roxygen2记录带参数的函数的帮助信息。

At the moment, this is my class: 目前,这是我的班级:

#' @importFrom R6 R6Class
MQParameters <- R6::R6Class(
  'MQParameters',
  public=list(
    initialize=function(file_path=NA) {
      private$location <- file_path
      mq_parameters <- read.delim(file_path, stringsAsFactors=FALSE)
      mq_parameters <-
        setNames(mq_parameters$Value, mq_parameters$Parameter)
      private$mq_version <- unname(mq_parameters['Version'])
      private$fasta_file <-
        gsub('\\\\', '/', strsplit(mq_parameters['Fasta file'], ';')[[1]])
    },
    # this method returns the version
    getVersion=function() {
      private$mq_version
    },
    # this methods returns the fastafile.
    # @param new_param it is possible to rewrite the basedir.
    getFastaFile=function(new_basedir=NA) {
      if(is.na(new_basedir)) {
        private$fasta_file
      } else {
        file.path(new_basedir, basename(private$fasta_file))
      }
    }
  ),
  private=list(
    location=NULL,
    mq_version=NULL,
    fasta_file=NULL
  )
)

If you are interested to test this class, here is a little reproducible example: 如果您有兴趣测试这个类,这里​​有一个可重复的例子:

df <- data.frame(Parameter=c('Version', 'Fasta file'),
                 Value=c('1.5.2.8','c:\\a\\b.fasta'))
write.table(df, 'jnk.txt', sep='\t', row.names=F)

p <- MQParameters$new('jnk.txt')
p$getVersion()
# [1] "1.5.2.8"
p$getFastaFile()
# [1] "c:/a/b.fasta"
p$getFastaFile(new_basedir='.')
# [1] "./b.fasta"

I don't know how to document parameters, because the parameters are actually belong to the creator but not to the class. 我不知道如何记录参数,因为参数实际上属于创建者但不属于类。 What about the parameters to other methods within the function? 函数中其他方法的参数怎么样?
What is the preferred way to document a class with it's methods? 使用它的方法记录类的首选方法是什么?

I would love to get the "normal" functionality from RStudio, like hitting F1 to get directly to the help page. 我很乐意从RStudio获得“正常”功能,比如点击F1直接进入帮助页面。

By searching the internet, I saw already some reports on Github about this topic, but they more than a year old. 通过搜索互联网,我已经看到一些关于Github的关于这个主题的报告,但是他们已经有一年多了。

Update 更新

Thanks to the answer of mikeck I now have a nice documentation for the class and it's methods. 感谢mikeck的回答,我现在有一个很好的文档类和它的方法。 But what I am still lacking is the possibility to get the hint of function/method and its arguments like in this screenshot for a common function: 但我仍然缺乏的是获得函数/方法及其参数的提示的可能性,如此屏幕截图中的常见函数:

rStudio有关功能的帮助

I am wondering if I can somehow register my function manually, but since it doesn't have a specific name (it is always coupled with the variable objectname you use for the object OBJECTNAME$methodeCall() ) I don't know how to do this. 我想知道我是否可以以某种方式手动注册我的函数,但因为它没有特定的名称(它总是与您用于对象OBJECTNAME$methodeCall()的变量objectname耦合)我不知道该怎么做这个。

My understanding is that it is easiest to document a NULL object with the same @name as your class, as this provides maximum flexibility. 我的理解是,使用与您的类相同的@name来记录NULL对象是最容易的,因为这提供了最大的灵活性。 I use an R6 class in one of my packages; 我在我的一个包中使用了R6类; you can view the roxygen here . 你可以在这里查看roxygen。 I've included a small sample below: 我在下面列了一个小样本:

#' Python Environment
#' 
#' The Python Environment Class. Provides an interface to a Python process.
#' 
#' 
#' @section Usage:
#' \preformatted{py = PythonEnv$new(port, path)
#'
#' py$start()
#' 
#' py$running
#' 
#' py$exec(..., file = NULL)
#' py$stop(force = FALSE)
#' 
#' }
#'
#' @section Arguments:
#' \code{port} The port to use for communication with Python.
#' 
#' \code{path} The path to the Python executable.
#' 
#' \code{...} Commands to run or named variables to set in the Python process.
#'
#' \code{file} File containing Python code to execute.
#' 
#' \code{force} If \code{TRUE}, force the Python process to terminate
#'   using a sytem call.
#' 
#' @section Methods:
#' \code{$new()} Initialize a Python interface. The Python process is not 
#'   started automatically.
#'   
#' \code{$start()} Start the Python process. The Python process runs 
#'   asynchronously.
#'
#' \code{$running} Check if the Python process is running.
#'   
#' \code{$exec()} Execute the specified Python 
#'   commands and invisibly return printed Python output (if any).
#'   Alternatively, the \code{file} argument can be used to specify
#'   a file containing Python code. Note that there will be no return 
#'   value unless an explicit Python \code{print} statement is executed.
#' 
#' \code{$stop()} Stop the Python process by sending a request to the 
#'   Python process. If \code{force = TRUE}, the process will be 
#'   terminated using a system call instead.
#'
#' @name PythonEnv
#' @examples
#' pypath = Sys.which('python')
#' if(nchar(pypath) > 0) { 
#'   py = PythonEnv$new(path = pypath, port = 6011)
#'   py$start()
#'   py$running
#'   py$stop(force = TRUE)
#' } else 
#' message("No Python distribution found!")
NULL

#' @export
PythonEnv = R6::R6Class("PythonEnv", cloneable = FALSE,
  # actual class definition...

There are other alternative (but similar) implementations; 还有其他替代(但类似)的实现; this example uses @docType class which might suit you better: 这个例子使用了@docType class ,它可能更适合你:

#' Class providing object with methods for communication with lightning-viz server
#'
#' @docType class
#' @importFrom R6 R6Class
#' @importFrom RCurl postForm
#' @importFrom RJSONIO fromJSON toJSON
#' @importFrom httr POST
#' @export
#' @keywords data
#' @return Object of \code{\link{R6Class}} with methods for communication with lightning-viz server.
#' @format \code{\link{R6Class}} object.
#' @examples
#' Lightning$new("http://localhost:3000/")
#' Lightning$new("http://your-lightning.herokuapp.com/")
#' @field serveraddress Stores address of your lightning server.
#' @field sessionid Stores id of your current session on the server.
#' @field url Stores url of the last visualization created by this object.
#' @field autoopen Checks if the server is automatically opening the visualizations.
#' @field notebook Checks if the server is in the jupyter notebook mode.
#' #' @section Methods:
#' \describe{
#'   \item{Documentation}{For full documentation of each method go to https://github.com/lightning-viz/lightining-r/}
#'   \item{\code{new(serveraddress)}}{This method is used to create object of this class with \code{serveraddress} as address of the server object is connecting to.}
#'
#'   \item{\code{sethost(serveraddress)}}{This method changes server that you are contacting with to \code{serveraddress}.}
#'   \item{\code{createsession(sessionname = "")}}{This method creates new session on the server with optionally given name in \code{sessionname}.}
#'   \item{\code{usesession(sessionid)}}{This method changes currently used session on the server to the one with id given in \code{sessionid} parameter.}
#'   \item{\code{openviz(vizid = NA)}}{This method by default opens most recently created by this object visualization. If \code{vizid} parameter is given, it opens a visualization with given id instead.}
#'   \item{\code{enableautoopening()}}{This method enables auto opening of every visualisation that you create since that moment. Disabled by default.}
#'   \item{\code{disableautoopening()}}{This method disables auto opening of every visualisation that you create since that moment. Disabled by default.}
#'   \item{\code{line(series, index = NA, color = NA, label = NA, size = NA, xaxis = NA, yaxis = NA, logScaleX = "false", logScaleY = "false")}}{This method creates a line visualization for vector/matrix with each row representing a line, given in \code{series}.}
#'   \item{\code{scatter(x, y, color = NA, label = NA, size = NA, alpha = NA, xaxis = NA, yaxis = NA)}}{This method creates a scatterplot for points with coordinates given in vectors \code{x, y}.}
#'   \item{\code{linestacked(series, color = NA, label = NA, size = NA)}}{This method creates a plot of multiple lines given in matrix \code{series}, with an ability to hide and show every one of them.}
#'   \item{\code{force(matrix, color = NA, label = NA, size = NA)}}{This method creates a force plot for matrix given in \code{matrix}.}
#'   \item{\code{graph(x, y, matrix, color = NA, label = NA, size = NA)}}{This method creates a graph of points with coordinates given in \code{x, y} vectors, with connection given in \code{matrix} connectivity matrix.}
#'   \item{\code{map(regions, weights, colormap)}}{This method creates a world (or USA) map, marking regions given as a vector of abbreviations (3-char for countries, 2-char for states) in \code{regions} with weights given in \code{weights} vector and with \code{colormap} color (string from colorbrewer).}
#'   \item{\code{graphbundled(x, y, matrix, color = NA, label = NA, size = NA)}}{This method creates a bundled graph of points with coordinates given in \code{x, y} vectors, with connection given in \code{matrix} connectivity matrix. Lines on this graph are stacked a bit more than in the \code{graph} function.}
#'   \item{\code{matrix(matrix, colormap)}}{This method creates a visualization of matrix given in \code{matrix} parameter, with its contents used as weights for the colormap given in \code{colormap} (string from colorbrewer).}
#'   \item{\code{adjacency(matrix, label = NA)}}{This method creates a visualization for adjacency matrix given in \code{matrix} parameter.}
#'   \item{\code{scatterline(x, y, t, color = NA, label = NA, size = NA)}}{This method creates a scatterplot for coordinates in vectors \code{x, y} and assignes a line plot to every point on that plot. Each line is given as a row in \code{t} matrix.}
#'   \item{\code{scatter3(x, y, z, color = NA, label = NA, size = NA, alpha = NA)}}{This method creates a 3D scatterplot for coordinates given in vectors \code{x, y, z}.}
#'   \item{\code{image(imgpath)}}{This method uploads image from file \code{imgpath} to the server and creates a visualisation of it.}
#'   \item{\code{gallery(imgpathvector)}}{This method uploads images from vector of file paths \code{imgpathvector} to the server and creates a gallery of these images.}}


Lightning <- R6Class("Lightning",
...
)

EDIT 编辑

If you are looking for a way to get the RStudio tooltips to show up when trying to use a class method... unfortunately I don't think you will find a solution that doesn't require coding your classes in a way that eliminates the convenience and functionality of R6 classes. 如果您正在寻找一种方法来在尝试使用类方法时显示RStudio工具提示...遗憾的是,我认为您不会找到一种解决方案,不需要以消除类的方式对您的类进行编码R6类的便利性和功能性。

@f-privé has provided an answer that will do what you want---just extend that logic to ALL methods. @ f-privé提供了一个可以满足你想要的答案 - 只需将该逻辑扩展到所有方法。 For example, myclass$my_method is instead accessed by 例如, myclass$my_method被访问

my_method = function(r6obj) {
  r6obj$my_method()
}
obj$my_method()
my_method(obj)      # equivalent

In other words, you would need to create a wrapper for each method. 换句话说,您需要为每个方法创建一个包装器。 This obviously is less convenient to program than just using the obj$my_method() , and probably kills the usefulness of using an R6 class in the first place. 这显然比使用obj$my_method()更不方便编程,并且可能首先杀死了使用R6类的有用性。

The issue here is really RStudio. 这里的问题实际上是RStudio。 The IDE doesn't have a good way of identifying R6 classes by analyzing the code, and can't distinguish between methods of a defined class and elements of a list or environment. IDE没有通过分析代码识别R6类的好方法,也无法区分已定义类的方法和列表或环境的元素。 Furthermore, RStudio can't provide help on arbitrary functions, like: 此外,RStudio无法提供任意功能的帮助,例如:

na.omit()         # tooltip shows up when cursor is within the parentheses
foo = na.omit
foo()             # no tooltip

which is fairly analogous to calling methods of a particular R6 object. 这与调用特定R6对象的方法非常类似。

I think R people don't want to use $new(...) to get an instance of a new class. 我认为R人不想使用$new(...)来获取新类的实例。 They prefer to have a function with the same name of the class to construct an instance of it. 他们更喜欢使用具有相同名称的函数来构造它的实例。

So, what you could do is rename your R6ClassGenerator MQParameters_R6Class and create another function 那么,你可以做的是重命名你的R6ClassGenerator MQParameters_R6Class并创建另一个函数

MQParameters <- function(file_path = NA) {
  MQParameters_R6Class$new(file_path)
}

Then, document this function as any other function and you will get "the little yellow window showing the function call with its arguments" from RStudio. 然后,将此函数记录为任何其他函数,您将从RStudio获得“显示函数调用及其参数的小黄色窗口”。 And happy R users. 和快乐的R用户。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM