I have the following utilsnips script that I use for Vim:
snippet - "assignment"
<-
endsnippet
I use it for R to expand a dash to the assignment operator. I would like to make it so that a space is put both before and after the <- on expansion. However, when I put a space before it in the snippet like <-, it won't expand on hitting Tab. How should I modify the script to have spaces around the operator? Desired result: <-.
You could use r option to include head and trailing spaces around snippets. r will treat snippet as a python regular expression and you should define your snippet within quotes when using this flag.
snippet " -" "assignment" r
<-
endsnippet
Note that there is a space before and after <- in snippet definition.
As a bonus, It's more interesting to define the snippet like the following:
snippet " - " "assignment" rA
<-
endsnippet
A is autoexpansion. so now you dont need to hit tab anymore! just type - and as soon as you type space after - it will expand to <- Automatically.
Related
I know that functions are supposed to look like this:
my_function <- function(x) {
Body
}
My issue is that I can't get the symbol "{" and the symbol "}" on different lines. When I type start typing "my_function <- function(x) {" in the console, the closing brace immediately appears, and if I press enter at any point, I just get a new line.
To answer this specific question, if you delete the closing curly brace it adds before typing enter you can write multi-line functions like that. Also, if you copy/paste from another editor that will also work.
Also, you can disable the auto-brace adding feature by going to Tools->Global Options->Code->Editing and unchecking "Insert matching parens/quotes"
is it possible to indent output in R?
e.g.
cat("text1\n")
indent.switch(indent=4)
cat("random text\n")
print("another random text")
indent.switch(indent=0)
cat("text2\n")
resulting in
text1
random text
another random text
text2
I searched for this a few months ago, found nothing and am now searching again.
My current idea is to "overwrite" (I forgot the special term) the functions cat and/or print with an additional argument like:
cat("random text", indent=4)
Only I'm stuck with this and I dont like this procedure very much.
Any ideas?
Edit:
I should be more particular, nevertheless thank you for the \t (omg, i totally forgot this -.-) and that I can format it inside cat.
The given solutions work, but only solve my second-choice-path.
A switch as shown in my first codeexample does not exist I suppose?
My problem is that I have parts of a bigger program which have multiple subscripts, and the output of each subscript should be indented. This is absolutely possible with the "\t" or just blanks inside cat() but has to be done in every command, which I dont like very much.
Solution
I used Chris C's code and extended it in a very easy way. (Thank you very much Chris!)
define.catt <- function(ntab = NULL, nspace=NULL){
catt <- function(input = NULL){
if(!is.null(ntab)) cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
if(!is.null(nspace)) cat(paste0(paste(rep(" ", nspace), collapse = ""), input))
if(is.null(ntab) && is.null(nspace)) cat(input)
}
return(catt)
}
The same way you used \n to print a newline, you can use \t to print a tab.
E.g.
cat("Parent level \n \t Child level \n \t \t Double Child \n \t Child \n Parent level")
Evaluates to
Parent level
Child level
Double Child
Child
Parent level
As an alternative, you can create a derivative of cat called catt and alter options depending on the script. For example.
define.catt <- function(ntab = NULL){
catt <- function(input = NULL){
cat(paste0(paste(rep("\t", ntab), collapse = ""), input))
}
return(catt)
}
You would then set catt with however many tabs you wanted by
catt <- define.catt(ntab = 1)
catt("hi")
hi
catt <- define.catt(ntab = 2)
catt("hi")
hi
And just use catt() instead of cat().
You may consider the very versatile function capture.output(...), which evaluates the '...' list of expressions provided as main input arguments, and stores the text output (as if it would be displayed in the console) into a character vector instead. Then, you simply have to modify the strings as desired: here you want to add some leading spaces to each string. Finally, you write the strings to the console.
These can be done all in one line of nested calls. For example:
writeLines(paste(" ", capture.output(print(head(iris))), sep=""))
I therefore recommend you all to read the help of the capture.output function, and then try to use it for various purposes. Indeed, since the main input has the usual flexibility of the '...' list-like structure, you are free to include, for instance, a call to one home-made function, and thus do almost anything. As for indentation, that is simply done with paste function, once the former has done its magic.
I tend to use a lot of line breaks in my code like the following:
# Data =========================================================================
Where the entire comment is always 80 characters long (including the hashtag). What I would like to do is write a code snippet for Rstudio that will insert the hashtag, then a space, then allow the user to type out a series of words, then insert another space, and finally fill in a bunch of "=" until the 80 character limit is reached.
I'm not familiar with how snippets work at all so I'm not sure how difficult this is.
I have this much:
snippet lb
# ${1:name}
but I have no idea how to add a dynamic number of "=" signs. Also, lb = linebreak.
You can't do this with snippets, unfortunately; a snippet is a text template that contains fixed text with slots for user-inserted text.
There is a command built into RStudio to do something very similar, however; from the Code menu, choose Insert Section (or Ctrl+Shift+R). This will do exactly what you're describing, with two small differences:
The line will extend to 5 characters before the print margin (you can adjust the print margin in Tools -> Global Options -> Code.
The line is composed of - rather than = characters.
One advantage to sections marked in this way is that you can use them to fold and navigate inside the file (look at the editor status bar after adding one).
You can use the rstudioapi (which can return column position) inside the snippet to get something like what you want.
Below is a snippet I use called endhead. I use it by commenting my header title and then applying the snippet, eg:
# Section name endhead
which results in:
# Section name -----------------------------------------------------------------
snippet endhead
`r paste0(rep.int("-", 88 - rstudioapi::primary_selection(rstudioapi::getActiveDocumentContext())$range$start[2]), collapse = "")`
You can write a snippet to manipulate text (somewhat). I wrote the snippet below to do something similar to what you want to do. I'm still ironing out the issues (just asked this question).
snippet comm
`r paste0(
"#######################################><###################\n## ",
date(),
" -------------------------------\n## ",
eval(
paste0(
gsub(
".{1,51}\\s?\\K\\b",
"\n## ",
gsub("\\.", " ", paste0(text)),
perl = T
)
)
),
"###################################><###################\n"
)`
I think if you write an R code snippet using an anonymous function that accepts text input via $$, counts the nchar in the text, calculates the number of -'s needed at the end, and then uses eval(paste0()) to insert the comment you should be able to make it work. I'll post a comment or answer here if I figure it out. Please do the same on my question if you get it to work. Thanks. (P.S. Go Badgers!)
Inspired by nick's answer above I designed two snippets that allow the user to choose what level section to insert.
The first will fill-in the rest of the line with #, =, or -.
snippet end
`r strrep(ifelse(substr("$$", 1, 1) %in% c("-", "="), substr("$$", 1, 1), "#"), 84 - rstudioapi::primary_selection(rstudioapi::getActiveDocumentContext())$range$start[2])`
Just specify the character you want to use after end (will default to # if nothing or any other character is given). For example:
## Level 1 Header end<shift+tab>
## Level 2 Header end=<shift+tab>
## Level 3 Header end-<shift+tab>
end<shift+tab>
end=<shift+tab>
end-<shift+tab>
Produces the following lines:
## Level 1 Header ##############################################################
## Level 2 Header =============================================================
## Level 3 Header -------------------------------------------------------------
################################################################################
===============================================================================
-------------------------------------------------------------------------------
Similarly to what Josh was suggesting, the following snippet uses th $$ notation to pass the text following the snippet as described here.
snippet !
`r paste("##", substr("$$", 4, nchar("$$")), strrep(substr("$$", 2, 2), 79-nchar("$$")))`
Again this allows user to select the section level (#, =, or -). The first character after !# should be the header level character you want followed by a space and the header text. For example:
!## Level 1 Header<shift+tab>
!#= Level 2 Header<shift+tab>
!#- Level 3 Header<shift+tab>
Produces the following lines:
## Level 1 Header ##############################################################
## Level 2 Header ==============================================================
## Level 3 Header --------------------------------------------------------------
I prefer the end snippet above because it is more robust and only allows the characters #, =, or - to be inserted where as ! will allow anything, but it is shorter and, I think, easier to understand than calls to the rstudioapi.
!loon<shift+tab>
## n ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
I am using R from the command line and noticed that autocompletion of list names does not work when inside square brackets. Consider this example:
myList <- list(firstElement=sample(1:10), secondElement=sample(1:10))
Typing out myList$f and then pressing tab gives myList$firstElement
But does not work here (at myList$s inside the brackets):
myList$firstElement[myList$secondElement > 5]
My question is - why it does not work and is there something one can do to make it work?
Putting the term inside round brackets seems to work
myList$firstElement[(myList$
No idea why it doesn't autocomplete without this though.
I have tried using "reindent lines" after highlighting the lines but that doesn't work (in fact it removes indentation). For example I want a quick way to
take a script like this
#parameters
b=2
c=1
d=4
q=3
and turn it into this
#parameters
b=2
c=1
d=4
q=3
in Rstudio
Highlighting the code of interest and hitting tab should add another level of indentation. Shift-tab will remove a level of indentation.
You could use a shortcut. First, highlight the lines you want to indent, and then press: Ctrl + } (at least, that is the combination on my keyboard).
If you want to move in the other direction, then press: Ctrl + {.
RStudio will let you use Regex in Find and Replace. You can search for \n and replace with \n\t, which will do what (I think) you want.
The automatic indent is designed to format your code so that there is indenting where appropriate (inside a pair of brackets, for example). 'Reindent' is for when there has been automatic indenting applied which is no longer appropriate (eg brackets have been removed).
re format code and reindent works for me. But, for your example, I think it is more based on the space a tab creates. Also, the below link is a good way to write good codes
https://google-styleguide.googlecode.com/svn/trunk/Rguide.xml
http://r-pkgs.had.co.nz/r.html