From Heather.Turner at warwick.ac.uk  Mon Jun  9 16:35:09 2008
From: Heather.Turner at warwick.ac.uk (Dr Heather Turner)
Date: Mon, 09 Jun 2008 15:35:09 +0100
Subject: [Rd] Posting Guide - help.request() function?
In-Reply-To: <971536df0806071024x688e1bcfvac6a1c8a43182170@mail.gmail.com>
References: <971536df0806061030i75474172xff100ece76a23eec@mail.gmail.com>	<971536df0806070638w48afb954y77278659edd37802@mail.gmail.com>
	<971536df0806071024x688e1bcfvac6a1c8a43182170@mail.gmail.com>
Message-ID: <484D3F9D.7010404@warwick.ac.uk>

Whilst it is a good idea to improve the posting guide, it seems to me 
that it would be useful to have a function along the lines of 
bug.report(), to help a potential questioner make sure they have done 
their homework and have the relevant information to put into a post to 
R-help.

Even those of us who know what ought to go into a post can sometimes 
forget to check something obvious - I recently got caught out by not 
checking an error was reproducible in the patched version for example.

So I have written a help.request() function (see below), which
- prompts the user to check the relevant resources, stopping and opening 
the relevant url where necessary
- checks their R version is up-to-date (in a rather messy way - please 
suggest improvements!)
- prompts them to prepare appropriate example code and test it in a 
fresh R session
- prompts them to give a meaningful subject line
- automatically adds system info to the post (as in bug.report)
- sends the message for them (ensuring a fresh thread is started)

Is this an idea worth taking further? I would be happy to make 
improvements as suggested and write a help file if so.

Heather

------------------------------------------------------------

help.request <- function (subject = "",
                           ccaddress = Sys.getenv("USER"),
                           method = getOption("mailer"),
                           address = "r-help at R-project.org",
                           file = "R.help.request")
{
     no <- function(answer) answer == "n"
     yes <- function(answer) answer == "y"
     go <- function(url) {
         cat("Please do this first - the site has been loaded in your 
web browser\n")
         browseURL(url)
     }
     cat("Checklist:\n")
     post <- readline("Have you read the posting guide? (y/n) ")
     if (no(post)) return(go("http://www.r-project.org/posting-guide.html"))
     FAQ <- readline("Have you checked the FAQ? (y/n) ")
     if (no(FAQ)) return(go("http://cran.r-project.org/faqs.html"))
     intro <- readline("Have you checked An Introduction to R? (y/n) ")
     if (no(intro)) 
return(go("http://cran.r-project.org/doc/manuals/R-intro.html"))
     NEWS <- readline("Have you checked the NEWS of the latest 
development release? (y/n) ")
     if (no(NEWS)) return(go("https://svn.r-project.org/R/trunk/NEWS"))
     rsitesearch <- readline("Have you looked on RSiteSearch? (y/n) ")
     if (no(rsitesearch)) {
         cat("Please do this first - the site has been loaded in your 
web browser\n")
         return(RSiteSearch(subject))
     }
     inf <- sessionInfo()
     if ("otherPkgs" %in% names(inf)){
         other <- readline("You have packages other than the base 
packages loaded.",
                           "\nIf your query relates to one of these, 
have you ",
                           "checked any corresponding books/manuals \nand ",
                           "considered contacting the package 
maintainer? (y/n/NA) ")
         if(no(other)) return("Please do this first.")
     }

     man <- url("http://cran.r-project.org/manuals.html")
     ver <- scan(man, what = character(0), sep = "\n", skip = 13, nlines 
= 1, quiet = TRUE)
     major <- as.numeric(substr(ver, start = 18, stop = 18))
     minor <- as.numeric(substr(ver, start = 20, stop = 22))
     if (major < as.numeric(R.Version()$major) ||
         minor < as.numeric(R.Version()$major)) {
         update <- readline("Your R version is out-of-date, would you 
like to update now? (y/n) ")
         if (yes(update)) {
             return(go(getOption("repos")))
         }
     }
     ## To get long prompt!
     cat("Have you written example code that is\n",
         "- minimal\n - reproducible\n - self-contained\n - commented",
         "\nusing data that is either\n",
         "- constructed by the code\n - loaded by data()\n",
         "- reproduced using dump(\"mydata\", file = \"\")\n")
     code <- readline(paste("have you checked this code in a fresh R 
session",
                            "\n(invoking R with the --vanilla option if 
possible)",
                            "\nand is this code copied to the clipboard? 
(y/n) "))
     if (no(code))
         return(cat("\nIf your query is not directly related to code",
                "(e.g. a general query \nabout R's capabilities),",
                "email R-help at r-project.org directly. ",
                "\nOtherwise prepare some example code first.\n"))
     change <- readline(paste("Would you like to change your subject 
line:\n",
                              subject, "\nto something more meaningful? 
(y/n) "))
     if (yes(change))
         subject <- readline("Enter subject: \n")

     methods <- c("mailx", "gnudoit", "none", "ess")
     method <- if (is.null(method))
         "none"
     else methods[pmatch(method, methods)]
     body <- paste("\\n<<Write your query here, using your example code 
to illustrate>>",
                   "\\n<<End with your name and affiliation>>\\n\\n\\n\\n",
                   "--please do not edit the information below--\\n\\n",
                   "Version:\\n ", paste(names(R.version), R.version, 
sep = " = ",
                                         collapse = "\\n "), if 
(nzchar(Sys.getenv("R_GUI_APP_VERSION")))
                   paste("\\n\\nGUI:\\n R-GUI ", 
Sys.getenv("R_GUI_APP_VERSION"),
                         " (", Sys.getenv("R_GUI_APP_REVISION"), ")",
                         sep = "")
                                         else "", "\\n\\n", 
"Locale:\\n", Sys.getlocale(), "\\n\\n",
                   "Search Path:\\n ", paste(search(), collapse = ", "),
                   "\\n", sep = "", collapse = "")
     if (method == "gnudoit") {
         cmd <- paste("gnudoit -q '", "(mail nil \"", address,
                      "\")", "(insert \"", body, "\")", 
"(search-backward \"Subject:\")",
                      "(end-of-line)'", sep = "")
         system(cmd)
     }
     else if (method == "none") {
         disclaimer <- paste("# Your mailer is set to \"none\" (default 
on Windows),\n",
             "# hence we cannot send the help request directly from R.\n",
             "# Please copy the help request (after finishing it) to\n",
             "# your favorite email program and send it to\n#\n",
             "#       ", address, "\n#\n", 
"######################################################\n",
             "\n\n", sep = "")
         cat(disclaimer, file = file)
         body <- gsub("\\\\n", "\n", body)
         cat(body, file = file, append = TRUE)
         cat("Please edit the help request.\n")
         system(paste(getOption("editor"), file))
         cat("The unsent help request can be found in file", file,
             "\n")
     }
     else if (method == "mailx") {
         if (missing(subject))
             stop("'subject' missing")
         body <- gsub("\\\\n", "\n", body)
         cat(body, file = file, append = FALSE)
         cat("Please edit the help request.\n")
         system(paste(getOption("editor"), file))
         if (is.character(ccaddress) && nzchar(ccaddress)) {
             cmdargs <- paste("-s '", subject, "' -c", ccaddress,
                 address, "<", file, "2>/dev/null")
         }
         else cmdargs <- paste("-s '", subject, "'", address,
             "<", file, "2>/dev/null")
         status <- 1
         cat("Submit the help request? ")
         answer <- readline()
         answer <- grep("y", answer, ignore.case = TRUE)
         if (length(answer) > 0) {
             cat("Sending email ...\n")
             status <- system(paste("mailx", cmdargs))
             if (status > 0)
                 status <- system(paste("Mail", cmdargs))
             if (status > 0)
                 status <- system(paste("/usr/ucb/mail", cmdargs))
             if (status == 0)
                 unlink(file)
             else {
                 cat("Sending email failed!\n")
                 cat("The unsent help request can be found in file",
                   file, "\n")
             }
         }
         else cat("The unsent help request can be found in file",
             file, "\n")
     }
     else if (method == "ess") {
         body <- gsub("\\\\n", "\n", body)
         cat(body)
     }
}

-----------------------------------------------------------------------

Gabor Grothendieck wrote:
> Here is another update.  I have added the following:
> 
> - info about using a fresh R session.  (In that case ls() output is less
>   essential; however, the developers of sessionInfo() might consider
>   adding that as a default or as an option.)
> 
> - questioner should consider use of functions.
> 
> - for data use dump(x, file = "") to reproducibly display data or use
>   builtin datasets listed by data()
> 
> - minimal versions of slow code should be presented in cases where
>   questioner is looking for faster code.
> 
> - we still need to add links to illustrative sample questions in r-help
> 
> The following were not added for the reason cited:
> 
> - guide is not just for questioners.  Important to distinguish roles
>   of questioner, responder and reader.
> 
> - what is to be provided ought to be given a name to make it easier
>   to refer to.  An unlabelled set of points is too vague.  Test
>   framework seems appropriately descriptive.  By giving it a name
>   one can request that a questioner "provide a test framework as
>   defined in the posting guide summary".
> 
> - self contained is not implied by reproducible.  Reproducible
>   only means that info is available somewhere -- not that its all
>   available right in the questioner's post and all in a manner that
>   is readily accessible.
> 
> - focus should be on making data minimal.  Don't like attachments
>   since responder must save them and read them in.  It encourages
>   use of large rather than minimal data sets.
> 
> Summary
> 
> Surprisingly, the main problem for responders is not to answer the
> question but to quickly figure out what the question is, reproduce it
> in their own R session and test their answer.
> 
> Test Framework.  To faciliate this provide a test framework of:
> 
>   (1) minimal reproducible self-contained commented code and data
>       that has been run in a fresh R session.  That means code and
>       data have been cut down as far as possible to the essentials
>       needed to illustrate the problem and were run are just after
> 	  starting up R.  Also it means that its possible for responders
>       to just copy the code and data section from the questioner's
>       post to the clipboard and paste it into their session to see
>       the same output without having to enter even one R command.
>       In some cases there may be an advantage to present the code as
>       a function and in the case of needing a speedup be sure to post
>       a minimal version of the slow code.  Use builtin data sets such
>       as those listed by data() to illustrate problem or reduce your
>       data to a minimum and present it reproducibly by using:
>          dump("mydata", file = "")
> 
>   (2) comments/explanation of what the code is intended to produce
> 	  -- Don't assume its obvious!
> 
>   (3) versions of all software used, e.g. sessionInfo(),
> 	  or R.version.string; packageDescription("zoo")$Version
> 
> Without self-contained reproducible code the responder must not only
> understand the question but must also create a test framework and that
> typically takes more time than answering the question!  Its not fair
> to ask the responder to provide all that on top of answering the
> question.  Do NOT assume the problem is so simple that it is not
> necessary.
> 
> Effort. The effort taken to reduce the problem to its essentials and
> produce a test framework often solves the problem avoiding the need
> for a post in the first place.  It at the least shows that the
> questioner tried to solve it themself.
> 
> Subscribers.  The questioner should ensure that the thread is complete
> and that it has an appropriate Subject.  The purpose of the post is
> not only to help the questioner but also the other list subscribers
> and those later searching the archives.
> 
> 
> 
> 
> 
> On Sat, Jun 7, 2008 at 9:38 AM, Gabor Grothendieck
> <ggrothendieck at gmail.com> wrote:
>> Here is a second version of the summary.  Its been rearranged to
>> place most important info at top.  Also shortened it a bit.
>>
>> It still needs links to example posts, as suggested.  Anyone?
>>
>> Summary
>>
>> Surprisingly, the main problem for responders is not to answer the
>> posted questions but to quickly figure out what the question is, reproduce
>> it in their own R session and test their answer.
>>
>> Test Framework.  To faciliate that provide a test framework of:
>>
>>  (1) reproducible self-contained minimal code and data.  That means
>>      responders can copy it from the questioner's post and paste it
>>      into their session to see the same output without having to
>>      enter even one R command.
>>      NB. dput(mydata) produces mydata in reproducible form.
>>  (2) comments/explanations of what the code is intended to produce and
>>  (3) versions of all software used, e.g. sessionInfo().
>>
>> Without self-contained reproducible code the responder must not only
>> understand the question but must also create a test framework and that
>> typically takes more time than answering the question!  Its not fair
>> to ask the responder to provide all that on top of answering the
>> question.  Do NOT assume the problem is so simple that it is not
>> necessary.
>>
>> Effort. The effort taken to reduce the problem to its essentials and
>> produce a test framework often solves the problem avoiding the need
>> for a post in the first place.  It at the least shows that the
>> questioner tried to solve it themself.
>>
>> Subscribers.  The questioner should ensure that the thread is complete
>> and that it has an appropriate Subject.  The purpose of the post is
>> not only to help the questioner but also the other list subscribers
>> and those later searching the archives.
>>
>>
>>
>> On Fri, Jun 6, 2008 at 1:30 PM, Gabor Grothendieck
>> <ggrothendieck at gmail.com> wrote:
>>> People read the posting guide yet they are still unable to create an acceptable
>>> post. e.g.
>>> https://stat.ethz.ch/pipermail/r-help/2008-June/164092.html
>>>
>>> I think the problem is that the guide is not clear or concise enough.
>>> I suggest we add a summary at the beginning which gets to the heart
>>> of what a poster is expected to provide:
>>>
>>> Summary
>>>
>>> To maximize your change of getting a response when posting provide (1)
>>> commented,
>>> (2) minimal, (3) self-contained and (4) reproducible code.  (This one
>>> line summary
>>> also appears at the end of each message to r-help.)
>>>
>>> "Self-contained" and "reproducible" mean that a responder can copy the
>>> questioner's code to
>>> the clipboard, paste it into their R session and see the same problem
>>> you as the questioner
>>> see.  Note that dput(mydata) will display mydata in a reproducible way.
>>> Self-contained and reproducible are needed because:
>>> (1) Self-Effort. It shows that the questioner tried to solve the
>>> problem by themself first.
>>> (2) Test framework. Often the responder needs to play with the code a
>>> bit in order to respond
>>> or at least to give the best answer.  They can't do that without a
>>> test framework that includes
>>> the data and the code to run it and its not fair to ask them to not
>>> only answer the question but
>>> also to come up with test data and to complete incomplete code.
>>> (3) Archives. Questions and answers go into the archives so they are
>>> not only for the benefit of
>>> of the questioner but also for the benefit of all future searchers of
>>> the archive.  That means
>>> that its not finished if you have solved the problem for yourself.
>>> You still need to ensure that
>>> the thread has a complete solution. (For that reason its also
>>> important to give a meaningful
>>> subject to each post.)
>>>
>>> "Commented" and "minimal" also reduce the time it takes to understand
>>> the problem.
>>> Don't just dump your code as is into the message since you are just
>>> wasting your own
>>> time. Its not likely anyone will answer a message if the questioner
>>> has not taken the
>>> time to reduce it to its essential elements.  Surprisingly, quite
>>> often understanding what
>>> the problem is takes the responder most of the time -- not solving the
>>> problem. Once the
>>> question is actually understood its often quite fast to answer.  Thus
>>> in addition to posting
>>> it in a minimal form, comment on it sufficiently so that the responder
>>> knows what the code
>>> does and is intended to produce.  It may be obvious to the questioner
>>> who is embroiled in
>>> the problem but that does not mean its obvious to others.
>>>
>>> Introduction
>>>
>>> .... rest of posting guide ...
>>>
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
Dr H Turner
Research Fellow
Dept. of Statistics
The University of Warwick
Coventry
CV4 7AL

Tel: 024 76575870
Fax: 024 76524532
Url: www.warwick.ac.uk/go/heatherturner



[Rd] Posting Guide - help.request() function?
Dr Heather Turner