In RStudio, [Ctrl] + [Enter] runs the currently highlighted code part, but with echo. [Ctrl] [Shift] + [S] sources the whole file without echo.
Is it possible to run the highlighted/selected code part without having the input clutter the console? Or is this an implicit requirement when running code instead of sourcing? (There seem to be subtle differences mentioned in other SO posts)
In conclusion: Is there a Hotkey to press to get exactly what [Ctrl]+[Enter] does, but without cluttering the console with my script code?
I don't believe there is a built-in way to do that. However, you can create an Addin that will source() the code and sink() results to a text file, which can be openend automatically.
In RStudio, create a New Project > R Package.
Create a new R script called runSelected:
#' runSelected
#'
#' RStudio addin to run selected code and show results in
#' default text editor.
#'
#' #export
runSelection <- function() {
context <- rstudioapi::getActiveDocumentContext()
selection <- rstudioapi::primary_selection(context)
tmp_code <- tempfile()
f <- file(tmp_code)
writeChar(object = selection$text, con = f)
close(f)
tmp_results <- tempfile()
sink(tmp_results)
source(tmp_code)
sink()
shell.exec(tmp_results)
}
In the package's directory, create file inst/rstudio/addins.dcf:
Name: Run Selection
Description: Run selected text and see results in text editor
Binding: runSelection
Interactive: false
Generate documentation with roxygen2, build and voilà!
Related
I use it a lot on Rmarkdow for referring to code, so I created an Addin, but wanted to know if there's a shortcut. If it isn't the case, how could I do to configure the addin so when calling it, the position of the caret or cursor stands between both symbols, exactly as it happens when using "" or () in RStudio.
insertInAddin <- function() { rstudioapi::insertText("``") } is the code I used for the Add-in
I'm looking help understanding how to setup
rstudioapi::setCursorPosition()
and document_position() inside the location argument of insertText.
You can use the shrtcts package for this task. It lets you assign Keyboard Shortcuts to arbitrary R Code.
Create a new R Markdown Snippet which can also be used on its own by typing e.g. in (for inline code font) and press Shift+Tab:
snippet in
`${1}`$0
Use the command shrtcts::edit_shortcuts() in the RStudio Console to open the file where you define your custom shortcuts.
Paste the following code inside that file (set your preferred keybinding in the #shortcut line). Note that the inserted text in the second line of the function must match the new Snippet from Step 1:
#' Code Font
#'
#' #description
#' If Editor has selection, transform current selection to code font.
#' If Editor has no selection, write between backticks.
#' #interactive
#' #shortcut Cmd+E
function() {
if (rstudioapi::selectionGet()$value == "") {
rstudioapi::insertText("in")
rstudioapi::executeCommand("insertSnippet") |>
capture.output() |>
invisible()
} else {
# Gets The Active Document
ctx <- rstudioapi::getActiveDocumentContext()
# Checks that a document is active
if (!is.null(ctx)) {
# Extracts selection as a string
selected_text <- ctx$selection[[1]]$text
# modify string
selected_text <- stringr::str_glue("`{selected_text}`")
# replaces selection with string
rstudioapi::modifyRange(ctx$selection[[1]]$range, selected_text)
}
}
}
This solution uses the native pipe |> and thus requires R 4.1.
You can of course just define separate variables in each line or use the magrittr pipe if you use earlier versions of R.
Further the stringr::str_glue() command can be easily replaced with a base R solution to avoid dependencies.
Use the command shrtcts::add_rstudio_shortcuts(set_keyboard_shortcuts = TRUE) in the RStudio Console to add the new shortcut with its assigned keybinding. Then restart RStudio.
Now you can use e.g. cmd+e without selection to place your cursor within backticks and press Tab to continue writing after the second backtick.
Or you can select text and then press cmd+e to surround the selected text by backticks.
The solution above can be easily generalized for bold and italic text in RMarkdown documents or to write within Dollar signs to add Inline Latex Math.
You can check RMarkdown Code Chunks and RStudio Shortcuts.
The shortcut you're looking for is: Ctrl+Alt+I.
Or you can create your own Code Snippet. To do this, follow the instructions on this page: Code Snippets in the RStudio IDE.
My R workflow is usually such that I have a file open into which I type R commands, and I’d like to execute those commands in a separately opened R shell.
The easiest way of doing this is to say source('the-file.r') inside R. However, this always reloads the whole file which may take considerable time if big amounts of data are processed. It also requires me to specify the filename again.
Ideally, I’d like to source only a specific line (or lines) from the file (I’m working on a terminal where copy&paste doesn’t work).
source doesn’t seem to offer this functionality. Is there another way of achieving this?
Here's another way with just R:
source2 <- function(file, start, end, ...) {
file.lines <- scan(file, what=character(), skip=start-1, nlines=end-start+1, sep='\n')
file.lines.collapsed <- paste(file.lines, collapse='\n')
source(textConnection(file.lines.collapsed), ...)
}
Using the right tool for the job …
As discussed in the comments, the real solution is to use an IDE that allows sourcing specific parts of a file. There are many existing solutions:
For Vim, there’s Nvim-R.
For Emacs, there’s ESS.
And of course there’s the excellent stand-alone RStudio IDE.
As a special point of note, all of the above solutions work both locally and on a server (accessed via an SSH connection, say). R can even be run on an HPC cluster — it can still communicate with the IDEs if set up properly.
… or … not.
If, for whatever reason, none of the solutions above work, here’s a small module[gist] that can do the job. I generally don’t recommend using it, though.1
#' (Re-)source parts of a file
#'
#' \code{rs} loads, parses and executes parts of a file as if entered into the R
#' console directly (but without implicit echoing).
#'
#' #param filename character string of the filename to read from. If missing,
#' use the last-read filename.
#' #param from first line to parse.
#' #param to last line to parse.
#' #return the value of the last evaluated expression in the source file.
#'
#' #details If both \code{from} and \code{to} are missing, the default is to
#' read the whole file.
rs = local({
last_file = NULL
function (filename, from, to = if (missing(from)) -1 else from) {
if (missing(filename)) filename = last_file
stopifnot(! is.null(filename))
stopifnot(is.character(filename))
force(to)
if (missing(from)) from = 1
source_lines = scan(filename, what = character(), sep = '\n',
skip = from - 1, n = to - from + 1,
encoding = 'UTF-8', quiet = TRUE)
result = withVisible(eval.parent(parse(text = source_lines)))
last_file <<- filename # Only save filename once successfully sourced.
if (result$visible) result$value else invisible(result$value)
}
})
Usage example:
# Source the whole file:
rs('some_file.r')
# Re-soure everything (same file):
rs()
# Re-source just the fifth line:
rs(from = 5)
# Re-source lines 5–10
rs(from = 5, to = 10)
# Re-source everything up until line 7:
rs(to = 7)
1 Funny story: I recently found myself on a cluster with a messed-up configuration that made it impossible to install the required software, but desperately needing to debug an R workflow due to a looming deadline. I literally had no choice but to copy and paste lines of R code into the console manually. This is a situation in which the above might come in handy. And yes, that actually happened.
Currently in RStudio keybinding CTRL/CMD + SHIFT + B perform the following job
devtools::install().
How can I change it to have this behaviour:
devtools::install(build_vignettes = TRUE)
If not, is it possible to create the entirely new keybinding for it?
You can execute anything by using an add-in. See https://rstudio.github.io/rstudioaddins/ for details. In summary, you create a small R package containing a function like
installWithVignettes <- function() devtools::install(build_vignettes = TRUE)
then set up a special file in the package inst/rstudio/addins.dcf that names this as an add-in. After that you can assign a shortcut to it.
Is there a way to test-out and peek at the output of a selected portion of markdown in RStudio? It seems you either run R code or have to compile the entire RMD page in order to see the output.
This is a Windows-only solution and it uses the clipboard instead of the current selection:
Define the following function:
preview <- function() {
output <- tempfile(fileext = ".html")
input <- tempfile(fileext = ".Rmd")
writeLines(text = readClipboard(), con = input)
rmarkdown::render(input = input, output_file = output)
rstudioapi::viewer(output)
}
Then, copy the markdown you want to preview and run preview(). Note that the output might be different from the output in the final document because
the code is evaluated in the current environment
only the copied markdown is evaluated, meaning that the snippet has no context whatsoever.
A solution without using the clipboard will most likely employ rstudioapi::getActiveDocumentContext(). It boils down to something along the lines of a modified preview function
preview2 <- function() {
code <- rstudioapi::getActiveDocumentContext()$selection
# drop first line
# compile document (as in preview())
# stop execution (THIS is the problem)
}
which could be used by running preview() followed by the markdown to render:
preview2()
The value of pi is `r pi`.
The problem is, I don't see how the execution could be halted after calling preview2() to prevent R from trying to parse The value of …. See this related discussion.
For the past few months I've been building a simulation in R I hope to package. It consists of two usable functions, and many internal ones which one of the two usable functions call while looping, to perform the stages of simulation.
A simple conceptual example is:
# Abstract representation 1st Usable function, generates object containing settings for simulation.
settings <- function(){
matrix(c(1:4),nrow=2,ncol=2)
}
# Abstract representation of one of many internal functions, does some action in simulation.
int.func <- function(x){
out <- x*2
return(out)
}
# Abstract representation of second usable function, takes settings & invokes internal functions generates results & saves as R object files.
sim.func <- function(x){
ans <- int.func(x)
ans2 <- ans-2
save(ans2, file="outtest")
}
With my package so far, using it is done like so after loading and attaching the package with library():
INPUT <- settings()
fix(settings) # If you want to change from the defaults.
sim.func(INPUT)
Nothing needs returning from the simulation function because results and data-dumps get saved as an object with save() commands and the objects can be read in afterwards.
Now I'd like it to have a simple GUI which can be used in conjunction with command line - think Rcmdr but much more simple, to allow my co-workes who have never touched R to use it.
The gui needs to be able to edit the settings - like with the fix command above, to save a settings object to file, and to read in setting from an object file. I've built this with gWidgets:
gui <- function(){
INPUT <- matrix(c(1:4),nrow=2,ncol=2)
mainwin <- gwindow("MainWindow")
button1 <- gbutton("Edit Settings", cont=mainwin, handler=
function(h,...){
fix(INPUT)
print("Settings Edited")
})
button2 <- gbutton("RUN", cont=mainwin, handler=
function(h,...){
sim.func(INPUT)
print("The run is done")
})
savebutton <- gbutton("Write Settings to File",cont=mainwin, handler=
function(h,...){
setfilename <- ginput("Please enter the filename")
save(INPUT, file=setfilename)
})
loadutton <- gbutton("Load Settings from File", cont=mainwin,
handler=function(h,...){
fname <- gfile(test="Choose a file",
type="open",
action="print",
handler =
function(h,...){
do.call(h$action, list(h$file))
}
)
load(fname)})
}
Note the job of the settings function from before is now done on the first line of this gui function.
I add this to the same R file as the three functions above, add gui to the namespace as an export, set gWidgets and gWidgetstcltk as imports, and rebuild, then I library() the package and do gui().
The interface shows up. However I have a few issues:
The gui shows up fine, but if I click button1 ("Edit Settings") to edit settings through fix(INPUT), change the values, close the editor and click the button again to see if the changes have persisted and been stored in INPUT, they have not.
Same goes for reading in an object, it does not overwrite the INPUT object generated by default in the first line of function gui().
I think this has something to do with environments of functions but I'm not too sure. In the gui-less version of my package, the user generates the object containing settings, which is in workspace and feeds it to the simulation function as an argument. However since with the gui version, everything is run inside the function gui() and gWidgets handlers makes use of functions(h,...) I can't help but feel as if environments are the issue here. It's odd that when clicking on button 1, it will find INPUT from the gui() environment, but won't make the changes back there.
Can anybody help out with this and suggest what it is I need to do?
Apologies for a long question, but I've tried to explain clearly. Code is reproducible, as is the issue, just by having library(gWidgets, gWidgetstcltk)
and copying and pasting the code I've provided here, to define the functions and then running gui(). Then click the "Edit Settings" button, change the cells, exit, then click the button again to see if the changes persisted (they don't). The abstract example I've provided faithfully reproduces the same issues I have with my proper simulation functions so if I can't get it working, I won't get the real thing working.
Thanks,
Ben W.
UEA
The Sainsbury Laboratory.
[EDIT] Here is a fix/workaround using .GlobalEnv:
gui <- function(){
INPUT <- matrix(c(1:4),nrow=2,ncol=2)
.GlobalEnv$INPUT <- INPUT
mainwin <- gwindow("MainWindow")
button1 <- gbutton("Set", cont=mainwin, handler=
function(h,...){
INPUT <- .GlobalEnv$INPUT
fix(INPUT)
print("Settings have been edited...")
})
button2 <- gbutton("RUN", cont=mainwin, handler=
function(h,...){
sim.func(.GlobalEnv$INPUT)
print("The run is done")
})
writebutton <- gbutton("Write Settings to File",cont=mainwin, handler=
function(h,...){
setfilename <- ginput("Please enter the filename")
INPUT <- .GlobalEnv$INPUT
save(INPUT, file=setfilename)
})
loadutton <- gbutton("Load Settings from File", cont=mainwin,
handler=function(h,...){
fname <- gfile(test="Choose a file",
type="open",
action="print",
handler =
function(h,...){
do.call(h$action, list(h$file))
}
)
load(fname)
.GlobalEnv$INPUT <- INPUT})
}