File: repromptAny.R

package info (click to toggle)
r-cran-rdpack 2.6.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,156 kB
  • sloc: sh: 13; makefile: 4
file content (260 lines) | stat: -rw-r--r-- 13,083 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
## 2018-02-07 new
ereprompt <- function(..., edit = TRUE, filename = TRUE){
    reprompt(..., filename = filename, edit = edit)
}

## 2018-02-07 new argument `edit'
reprompt <- function(object, infile = NULL, Rdtext = NULL, final = TRUE,
                     type = NULL, package = NULL, methods = NULL, #  for the call to promptMethods
                     verbose = TRUE, filename = NULL, sec_copy = TRUE, edit = FALSE, ...){
    objmis <- missing(object)
    tidyflag <- from_infile <- FALSE
                                     # If 'object' is a string ending in ".Rd" and containing
                                     # at least one "/", it is taken to be "infile"; a
                                     # (somewhat dubious) convenience feature for the common
                                     # mistake of omitting the name of the "infile" argument.
    if(is.null(infile)  &&  length(object) == 1  &&  is.character(object)
                        && grepl("/.*[.][Rr]d$", object) )
        infile <- object

    if(!is.null(Rdtext)){                                         # process Rdtext, if present
        if(is.null(infile)){
            infile <- tempfile()
            cat(Rdtext, file = infile, sep = "\n")            # save parsed Rdtext to 'infile'
            on.exit(unlink(infile))
        }else
            cat("both 'infile' and 'Rdtext' are given, ignoring Rdtext\n")
    }

    if(!objmis && inherits(object, "Rd")){
        if(verbose) cat("Processing the Rd object...\n")
        if(!is.null(infile))
            cat("ignoring 'infile' and/or 'Rdtext' since 'object' is of class 'Rd'\n")
        rdo <- object
    }else if(!is.null(infile)){
        if(verbose) cat("\nParsing the Rd documentation in file", infile, "...\n")
        else cat("\n", basename(infile), ": ")

        if(!file.exists(infile)){ # 2018-02-07 new
            wrk <- try(rprojroot::find_root_file("man", basename(infile),
                                                 criterion = rprojroot::is_r_package),
                       silent = TRUE)
            if(inherits(wrk, "try-error"))
                stop("Input file ", infile, " not found")
            else infile <- wrk
        }
        rdo <- permissive_parse_Rd(infile)
        from_infile <- TRUE
    }else{
        if(verbose) cat("Rd source not supplied, looking for installed documentation.\n")

        fnam <- if(is.character(object)) object else deparse(substitute(object))

        rdo <- .capture_installed_help(fnam, type = type, package=package)
        if(inherits(rdo,"try-error"))
            cat("Rd source not supplied and installed documentation not found.\n")
        else{
            if(verbose) cat("Installed documentation found, processing it...\n")

            rdo <- .order_sections(rdo) # the sections may not be in canonical order in
            tidyflag <- TRUE            # instaled help
        }
    }

    if(inherits(rdo, "Rd")){                # do the main job: inspect the documentation object
        res <- inspect_Rd(rdo, package = package)
    }else{                                # documentation not found, try to generate fresh one
        if(verbose)
            cat("Trying a 'prompt' function to generate documentation for the object.\n")

                                                    # 2012-11-04 arg. type, package
        res <- .capture_promptAny(fnam, type = type, package = package,
                                  final = final, methods = methods)

        if(inherits(res,"try-error"))
            stop("unsuccessful attempt to create Rd doc. using a 'prompt' function.")
        else if (verbose)
            cat("\tsuccess: documentation generated using a 'prompt' function.\n")
    }

    if(tidyflag)
        res <- .Rd_tidy(res)   # tidy() could do more,

    if(is.null(filename)){   # generate appropriate file name; todo: may need some mangling?
        filename <- if(is.null(infile))
                         paste(res[[ Rdo_which_tag_eq(res, "\\name") ]],
                               ".Rd", sep="")
                    else basename(infile)         # do not overwrite unless in the current dir
    }else if(isTRUE(filename)){ # 2018-02-07 new
        filename <- if(is.null(infile))
                        paste(res[[ Rdo_which_tag_eq(res, "\\name") ]],
                              ".Rd", sep="")
                    else infile         # will overwrite
    }
                                                                        # todo: error checking
    if(is.character(filename) || identical(filename, FALSE)){              # convert to Rdtext
        res <- Rdo2Rdf(res, ex_restore = TRUE,
                       file = if(is.character(filename)) filename else NULL,
                       srcfile = if(from_infile && sec_copy) infile else NULL )
        if(is.character(filename))
            res <- invisible(filename) # return only the file name in this case
    }

    if(edit && is.character(filename)){ ## 2018-02-07 new argument `edit'
        file.edit(res) # TODO: check that it is a filename
        res
    }else
        res
}
                           # (promptMethods) todo: filename = FALSE is a useful
                           # alternative. In that case the text is returned in a named list
                           # containing one element for each Rd section (multiple occurences
                           # of sections like '\alias' are grouped together.
                                                    # 2012-11-04 new arg. type, package
.capture_promptAny <- function(fnam, type, package, final, ..., methods){
              # 2012-11-04 promenyam za da raboti is replacement methods, e.g. "[<--methods"
              #
              # if(grepl("^([^-]+)-.*", fnam)){                 # fnam is of the form xxxx-yyy
              #     fname  <- gsub("^([^-]+)-.*", "\\1", fnam)
              #     type   <- gsub("^([^-]+)-(.*)", "\\2", fnam)   # without "-"
              #     ## suffix <- gsub("^([^-]+)(-.*)", "\\2", fnam)   # with "-"
              # }else{
              #     fname <- fnam
              #     type = ""
              # }

           # 2012-11-04 replacing with the code after the comments
           #
           # namreg <- "^(.+)-([^-]+)$"
           # if(grepl(namreg, fnam)){           # fnam is of the form xxxx-yyy (non-empty rhs)
           #     fname  <- gsub(namreg, "\\1", fnam)
           #     namtype   <- gsub(namreg, "\\2", fnam)   # without "-"
           #     ## suffix <- gsub("^([^-]+)(-.*)", "\\2", fnam)   # with "-"
           # }else{
           #     fname <- fnam
           #     namtype = ""
           # }

    wrknam <- .parse_long_name(fnam)
    fname <- wrknam["name"]
    namtype <- wrknam["type"]

    if(missing(type) || is.null(type))
        type <- namtype
    else if(namtype != ""  &&  !identical(type, namtype)){
        cat("The name and type arguments give conflicting 'type' information.\n")
        cat("\tUsing argument 'type'.\n")
    }# else 'type'  has the value needed.

    ## 2019-04-26 print a message since otherwise the error is not clear,
    ##        e.g. if the call has 'type = class' (note: no quotes around class)
    if(!is.character(type) || length(type) != 1L)
        print("!!! if not missing, 'type' must be a character string")

    wrk <- try(switch(type,
                      methods = {
                          if(is.null(methods) && !is.null(package))
                              methods <- findMethods(fname, where = asNamespace(package))

                          if(is.null(methods)) promptMethods(f=fname, filename = NA)
                          else          promptMethods(f=fname, filename = NA, methods=methods)
                      },
                      class   = promptClass(clName=fname, filename = NA),
                      package = promptPackageSexpr(fname, filename = NA),
                      ## default

                      # v tozi variant ima problemi za funktsii ot Rdpack, za koito parviyat
                      # "if" dava TRUE i sled tova stava greshka. Za funktsii ot drugi paketi
                      # tova ne e problem, ponezhe za tyach "if"-at dava FALSE, ako sa
                      # nevidimi.
                      #
                      # Tay kato tazi situatsiya mozhe da vaznikne po razlichni nachini,
                      # promenyam koda. Tryabva oste rabota za sluchaya kogato ima poveche ot
                      # edno ime...
                      ### if(exists(fname, envir = parent.frame())){
                      ###     prompt(object=fname, filename = NA, force.function=TRUE, ...)
                      ### }else{ # todo: needs more work here
                      ###     x0 <- do.call(getAnywhere,list(fname))
                      ###     browser()
                      ###     prompt(object=x0$objs[[1]], filename = NA, force.function=TRUE,
                      ###            name = fname, ...)
                      ### }
                      {
                          wrk0 <- try(prompt(name=fname, filename = NA, ...), silent=TRUE)
                          if(inherits(wrk0,"try-error")){
                              x0 <- do.call(getAnywhere,list(fname))
                              wrk0 <- prompt(object=x0$objs[[1]], filename=NA, name = fname,
                                             # force.function=TRUE,
                                             ...)
                          }
                          wrk0 # todo: needs more work here. IN particular, there should be a
                           #       package argument to avoid taking blindly whatever comes up.
                      }   )
               , silent = TRUE)

    if(inherits(wrk,"try-error"))
        res <- wrk
    else{
        res <- .parse_Rdlines(wrk)
                                          # if successful, res is not inspected here
                                          # since it is generated from the actual definitions.
        if(final && type != "package"){ # put dummy title and description
                                        # to avoid errors when installing a package
            wrk <- char2Rdpiece("~~ Dummy title ~~", "title")
            res <- Rdo_replace_section(res, wrk)

            wrk <- char2Rdpiece("~~ Dummy description ~~", "description")
            res <- Rdo_replace_section(res, wrk)

                                       # tidy a bit, e.g. to start each section on new line,
                                       # which may not be the case for installed documentation
            res <- .Rd_tidy(res)   # tidy() could do more; e.g. reorder sections
        }
    }

    res
}

.capture_installed_help <- function(fnam, type = NULL, package = NULL, suffix = NULL){
                         # this does not work, package seems not evaluated or deparsed
                         #      hlp <- help(paste(fnam, "-methods", sep=""), package=package)
                         # TODO: the last example in "help()" amy be helpful here.
                         #
    namreg <- "^(.+)-([^-]+)$"                             # 2012-11-04 new namreg and related
    fullname <- if(grepl(namreg, fnam))   # fnam is of the form xxxx-yyy
                    fnam
                else if(!is.null(type) && is.character(type) && type!="")
                    paste(fnam, "-", type, sep="")
                else if(!is.null(suffix))
                    paste(fnam, suffix, sep="")
                else
                    fnam

    hlp <- help(fullname)                                                   # todo: more care!
    hlpfile <- as.vector(hlp) # removes attributes
                                    # todo: but may be of length > 1,  e.g. for "initialize"
                                    #   cat("hlpfile has ", length(hlpfile), " element(s):\n")
                                    #   print(hlpfile)
    if(!is.null(package)){                  # try first "/package/" to avoid surprise matches;
                             # see what happens with package = "methods", without the slashes;
                             # also, 'package' may be part of the name of another package.
        indx <- which( grepl(paste("/", package, "/", sep=""), hlpfile))
        if(length(indx)==0)             # ... but if nothing matched, try without the slashes.
            indx <- which(grepl(package, hlpfile))
        hlpfile <- hlpfile[ indx ]
    }

    if(length(hlpfile) > 1){    # todo: mozhe da se napravi v loop to collect a bunch of sig's
        hlpfile <- hlpfile[1]
        cat("length(hlpfile)>1, taking the first element.\n")
    }

    try(utilsdotdotdot.getHelpFile(hlpfile), silent=TRUE)
}

                                 # 'usage' may be an "f_usage" object obtained e.g. by a
                                 # previous call to get_usage() or generated programmatically.
promptUsage <- function (..., usage){                          # todo: add formatting options?
    if(missing(usage)) get_usage(..., out.format="text")
    else               as.character(usage)
}