Is there a way to make R wait for console input before continuing?
Let's say I source two scripts like this in a main script called run.R:
# some more R Code here
source("script1.R")
source("script2.R")
# some more R Code there
Script1 contains some readLine statement that asks the user for a username.
Unfortunately if I just run the entire run.R file R doesn't wait for the username to be entered. It starts script2.R before the username is entered which leads to an error because the 2nd script needs the username.
I have an ugly workaround for this using R Studio's .rs.askForPassword which actually waits for the the input, but covers the password. Which is cool for passwords, but not so much for usernames. Plus it's an RStudio feature, not R.
readline can only be used in interactive sessions. In non-interactive use of readline the result is an empty string. On the help page of ?interactive you find the following about interactive sessions:
GUI consoles will arrange to start R in an interactive session. When R
is run in a terminal (via Rterm.exe on Windows), it assumes that it is
interactive if ‘stdin’ is connected to a (pseudo-)terminal and not if
‘stdin’ is redirected to a file or pipe. Command-line options
--interactive (Unix) and --ess (Windows, Rterm.exe) override the default assumption.
Try scan function.
This is test.R file:
y <- 2
cat('y=',y)
cat("\nEnter username")
x <- scan(what=character(),nmax=1,quiet=TRUE)
"ala ma kota"
y <- 2*2
cat('y=',y)
cat('\nx=',x)
and then I run this:
> source("test.R")
y= 2
Enter username
1: login
y= 4
x= login
--edit--
To read only one character quietly run this:
> x <- scan(what=character(),nmax=1,quiet=TRUE)
1: username
> x
[1] "username"
what sets the type, nmax sets the maximal numbers of elements to read and quiet determine if print a line, saying how many items have been read.
Why not putting
source("script2.R")
into the file script1.R?
Related
I have a readline() function in a for loop
For Simplicity let's say I have this code:
x <- character()
for (i in 1:500) x[i] <- readline('Enter Value')
How can I automatically enter input instead of manually entering it at the console 500 times?
readline() isn't intended for automatic input. From ?readline:
Description
readline reads a line from the terminal (in interactive use).
and:
Details
The prompt string will be truncated to a maximum allowed length,
normally 256 chars (but can be changed in the source code).
This can only be used in an interactive session.
Looking at ?interactive we can read the following:
An interactive R session is one in which it is assumed that there is a
human operator to interact with, so for example R can prompt for
corrections to incorrect input or ask what to do next or if it is OK
to move to the next plot.
So, basically you are trying to use readline for something it isn't intended for.
You can vectorize this command, assuming you're looking to fill the column with the same value. If that's not what you're trying to do, I'm confused as to what you want. Run my example below and say whether that's the kind of thing you're looking for
working <- iris
head(working)
working$like <- readline("Do you like this flower? ")
head(working)
I am creating a package and would like to store settings data locally, since it is unique for each user of the package and so that the setting does not have to be set each time the package is loaded.
How can I do this in the best way?
You could save your necessary data in an object and save it using saveRDS()
whenever a change it made or when user is leaving or giving command for saving.
It saves the R object as it is under a file name in the specified path.
saveRDS(<obj>, "path/to/filename.rds")
And you can load it next time when package is starting using loadRDS().
The good thing of loadRDS() is that you can assign a new name to the obj. (So you don't have to remember its old obj name. However the old obj name is also loaded with the object and will eventually pollute your namespace.
newly.assigned.name <- loadRDS("path/to/filename.rds")
# or also possible:
loadRDS("path/to/filename.rds") # and use its old name
Where to store
Windows
Maybe here:
You can use %systemdrive%%homepath% environment variable to accomplish
this.
The two command variables when concatenated gives you the desired
user's home directory path as below:
Running echo %systemdrive% on command prompt gives:
C:
Running echo %homepath% on command prompt gives:
\Users\
When used together it becomes:
C:\Users\
Linux/OsX
Either in the package location of the user,
path.to.package <- find.package("name.of.your.pacakge",
lib.loc = NULL, quiet = FALSE,
verbose = getOption("verbose"))
# and then construct with
destination.folder.path <- file.path(path.to.package,
"subfoldername", "filename")`
# the path to the final destination
# You should use `file.path()` to construct such paths, because it detects automatically the correct ('/' or '\') separators for the file paths in Unix-derived systems (Linux/Mac Os X) versus Windows.
Or use the $HOME variable of the user and there in a file - the name of which beginning with "." - this is convention in Unix-systems (Linux/Mac OS X) for such kind of file which save configurations of software programs.
e.g. ".your-packages-name.rds".
If anybody has a better solution, please help!
Consider the two lines below:
Sys.setenv(R_IMPORT_PATH = "/path/to/my/r_import")
foo <- modules::import("foo")
If I execute this code from within an already-established interactive R session, it works fine.
But if I put the same two lines in my .Rprofile and start a new interactive R session, the modules::import line fails with
Error in module_init_files(module, module_path) :
could not find function "setNames"
If I then attempt the following fix/hack
Sys.setenv(R_IMPORT_PATH = "/path/to/my/r_import")
library(stats)
foo <- modules::import("foo")
...then the modules::import line still fails, but with the following
Error in lapply(x, f) : could not find function "lsf.str"
So the idea of patching the missing names seems like it will be an unmaintainable nightmare...
The crucial issue is this: It appears that the search path right after an interactive search session starts is different from the one that an .Rprofile script sees.
Q1: Is there a way that I can tell R to make the search path exactly as it will be when the first > prompt appears in the interactive session?
Q2: Alternatively, is there a way for the .Rprofile to schedule some code to run after the session's default search path is in place?
NB: Solutions like the following:
Sys.setenv(R_IMPORT_PATH = "/path/to/my/r_import")
library(stats)
library(utils)
foo <- modules::import("foo")
...are liable to break every time that the (third-party) modules package is modified.
I am working on a small Rscript that has a readLines function:
n <- readLines("stdin",n=1);
if (n =="y"){ ... }
I want to know if there is a way for R to go to the next part of the script without waiting for me to hit the ENTER button after I gave the input. In my script I only care whether I type in "n" or not.
I am working on a little interactive shell-like tool in R that uses readline to prompt stdin, like this:
console <- function(){
while(nchar(input <- readline(">>> "))) {
message("You typed: ", input)
}
}
It works but the only thing that bothers me is that lines entered this way do not get pushed upon the history stack. Pressing the up-arrow in R gives the last R command that was entered before starting the console.
Is there any way I can manually push the input lines upon the history stack, such that pressing the up-arrow will show the latest line entered in the console function?
I use this in rite to add commands to the command history. In essence, you can just savehistory and loadhistory from a local file. I do:
tmphistory <- tempfile()
savehistory(tmphistory)
histcon <- file(tmphistory, open="a")
writeLines(code, histcon)
close(histcon)
loadhistory(tmphistory)
unlink(tmphistory)
Note: Mac doesn't use history in the same way as other OS's, so be careful with this.