This vignette explains in detail each of these features.
Package summary
Turbokit Introduction
Setup
Shortcuts
Options
Turbokit design philosophy
Turbokit introduces quality of life features reducing redundancy in day-to-day coding tasks in R and increasing the accessibility of stylish R code. It does so by re-thinking how frequently used functions are written by users, minimizing the number of key presses and reducing time spent on formatting tasks. Turbokit leverages snippets, infix operators, custom shortcuts, fuzzy matching, add-ins and the tidyverse manifesto to do so.
Turbokit includes the following features:
%>%
or +
based on document context.see vignette("turbo")
Shortcut button for a curated list of (1500+) functions.
Shortcut buttons for extremely frequent functions.
see vignette("chaining")
Pipemath: Shorthand notation for writing chains of functions in a pipe format.
Superpipe: %>>%
operator to convert pipemath instructions to a full-length snippet.
Dynamic snippets: adaptive snippets of formatted complex pipes described by pipemath and constructed by the superpipe.
Quasi-comments: Non-evaluated syntax highlighted R code.
A stigma yet clings to R - It is hard to use.
Historically, naming conventions used in R packages were problematic. Dots, camelCase, snake_case and function parameter names, many were unpredictable. This forced users to apply trial-and-error style probing to find out or remember what the function name is in a given package. The result: typos and deviation from that what matters: data science for all stakeholders present.
Inputting code takes time, and this time cost increases the longer or harder to remember a function name is. Systems are in place to aid the user, but often come with hurdles to overcome or drawbacks when used.
+-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | System | Benefit | Drawback | +=================+=================================================================================================================================================+=============================================================================================================================================================================================+ | Auto-completion | Visual cues and menuing for fuzzy matches, shorthand function notation. Covers all possible functions. Prompt speed and wait time customizable. | Packages have to be attached to be searched. Output differs depending on typing speed. User has to slow down to be fast for most functions. Unpredictable position of match in search list. | +-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Shortcuts | One-stop-shop for complicated input at a button press. | Requires package add-in (long setup time) and shortcut overload as each button is tied to a unique key. | +-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Snippet | Insert arbitrarily long code chunks, and jump from location to location. | Requires special syntax and menuing to set up. | +-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Pipe | Passing once process to another | Requires special syntax and code navigation. | +-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | NSE | metaprogramming and easing code input in functions and expressions. | Requires extensive programming knowledge to execute well. Not predictable what is, and what isn't implemented using NSE. | +-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
While powerful in their own right, the systems available do not play very well with each other. There thus exists a gap - user-friendly, fast paced, predictable output for complicated functions.
The turbokit package provides quality of life features that makes existing systems and the tidy design philosophy easily accessible, more consistent and speedier to use.
Turbokit is somewhat different from most packages, as many of its features are available without the need to call library(turbokit)
. However, to use turbokit to its full potential, the user has to invest some time in setting up turbokit to their preference.
Several turbokit functions are exported as add-in that can be bound to a shortcut key. Here, shortcuts are meant to be used as a quick insertion of a particular verb that work well with the smart pipe. These shortcuts will place the cursor between the brackets of the verb inserted at the cursor location. The smart pipe, when called, will relocate the cursor to the end of the line, and insert an operator based on the context of the pipe at that point.
Turbokit shortcut add-ins all start with "Turbo".
Tools > Addins > Browse Addins > Keyboard Shortcuts > Turbo ___
The following table is a suggestion for mapping turbokit shortcut keys. Some of these recommended shortcuts may overlap with default shortcuts. Recommended shortcuts are such that hand travel distance is minimized and shortcuts have a link to the function name.
Naturally, users are encouraged experiment with the shortcut setup to find their favorite setup that works best for them.
tabl <- " | Function | Shortcut |---------------|:-------------:| | switch pipe | *ctrl + shift + ,* | | switch mode | *ctrl + shift + right* | | insert pipe | *ctrl + shift + .* | | insert superpipe | *ctrl + shift + `* | | turbo | *ctrl + shift + /* | | select | *ctrl + shift + s* | | filter | *ctrl + shift + f* | | mutate | *ctrl + shift + m* | | summarise | *ctrl + shift + z* | | everything | *ctrl + shift + e* | | across | *ctrl + shift + a* | | starts_with | *ctrl + shift + 1* | | ends_with | *ctrl + shift + 2* | " cat(tabl)
Besides the two pipe operators, all of the output of the insert_ functions, can be achieved through pipemath and superpipe combination as well as the turbo function. It is thus recommended to only bind those functions that the user very frequently uses.
Turbokit has several options that can change the output of its operators and functions to the users desire or requirement. As turbokit deals with snippets and shortcuts, it inevitably has to deal with different operating systems and use cases.
Changes to options are not stored permanently, and must be rerun after restarting an R session. A way to permanently can be done by editing an Rprofile file, by usethis::edit_r_profile()
or file.edit(file.path("~", ".Rprofile"))
. If multiple Rprofiles are present, use file.edit(".Rprofile")
to edit the project level file. In the .Rprofile file, insert options("turbokit-optionname = TRUE")
or options("turbokit-optionname = FALSE").
A wrapper function, configure_turbokit()
is available to quickly toggle options during an R session. Multiple options can be selected at once by holdingt the ctrl
key, and clicking on the options.
Turbokit provides powerful features for starting the package automatically, and reduce redundant pre-analysis tasks such as library calls. However, changing a users' namespace is not always wanted. By default, this options is turned off.
getOption("turbokit-boot")
A message is printed if verbose is set to TRUE
.
Up, or user preference, is an option that determines the output of several of turbokits' functions. It specifies a maximum of 9 different packages to search when using the construct_complex function. Additionally, it determines the prefix to abbreviations to call a function. To get the current options.
getOption("turbokit-up")
to change its option, there is a function available. See the Custom bindings in the Use turbo section.
read(package_name)
To undo the read functions' doings, another function is shipped with the package, which returns the default option list.
default()
Turbokit can automatically insert the snippet. By default, this option is set to TRUE
, and directly inserts the freshly made snippet when calling %>>%.
To check your settings, use
getOption("turbokit-autoinsert")
to disable, use
options("turbokit-autoinsert" = FALSE)
The smart pipe shortcut chooses between %>%
and +
pipe operators based on the context of the text and applies indentation. The option smartpipe changes the behavior of the shortcut where the pipe is inserted. When set to TRUE
, the pipe is inserted at the end of the line, and the shortcut can thus be called while the cursor is located within brackets of a function. When set to FALSE
, the operator will be inserted at the cursor location.
The default option is is set to TRUE
. To check your settings, use
getOption("turbokit-smartpipe")
to disable, use
options("turbokit-smartpipe" = FALSE)
The directory where snippets are stored is likely to be untouched by many R users. However, when run in a cloud environment or when the directory has been manually changed, users may want to change this option so that turbokit can find the proper location of the snippet file to change.
The default for this is the value returned by an internal get_snippets_path()
function. When called from a Windows PC, this will return
%appdata%/Roaming/RStudio/snippets/r.snippets
For unix platform users, i.e. macOS and all Linux distributions, it will return
~/.config/rstudio/snippets/r.snippets
Users can change this behavior by setting a directory manually in the form of a character vector. If unsure about how to produce this, it is recommended to run
file.path(file.choose())
and navigate to the location of a r.snippets
file. Other language snippets are not supported by the turbokit package, but do notice - no checks are run on the filepath, make sure you don't accidentally overwrite other language files.
Some users may not want to be updated regularly on the changes in behavior of functions. To turn of the chatty behavior of the package,
getOption("turbokit-verbose")
to disable, use
options("turbokit-verbose" = FALSE)
How many functions are typed, how many backspaces hit every day, every month, every year, per career, per R user? What is the total redundant hand travel distance?
Do not Repeat Yourself (Hunt & Davis, 1999)
Once these questions are asked, several problems becomes clear.
Much of a function name is redundant for the developer.
It deosn't mttaer in waht oredr the ltteers in a wrod are, hmuans can udnertsand it.
Thinking of code is faster than writing code.
Existing systems are powerful, but unpredictable output or inflexible input.
Consider the following piece of legacy code:
transform(iris[which(iris$Species == "versicolor"),], new = Sepal.Length*2)
In baseR such a call would take roughly 76 keystrokes, given that there are no mistakes. Such code is rarely written these days, as R has seen many years of active development. In recent years, package developers started from scratch, and thought deeply about how code is written, introducing the tidyverse.
The goal of the tidyverse is to discover the minimal set of chunks needed to do data science and have some sense of the priority of the remainder.
-Tidyverse design guide / Tidyverse team
Convergence by the user-base toward acceptance of human-centered, consistent, composable and inclusive unifying principles of the tidyverse and increasingly widespread usage of its style guide is great for making R (and data science!) easier.
The tidyverse packages provide an alternative way to write code in a nice format, which is adopted by other package families, such as tidymodels. It heavily relies on the pipe, %>%
or +
.
iris %>% select(starts_with("Sepal"), Species) %>% filter(str_detect(Species, "v")) %>% group_by(Species) %>% summarise(across(everything(), mean)) %>% ggplot(aes(Sepal.Length, Sepal.Width)) + geom_density_2d_filled()
What the current design philosophy does not do, however, is heavily reduce the keypresses required to arrive at this code. The above example takes roughly 75 keystrokes.
Turbokit is implemented with the following principles in mind.
Adults read about 270-300 words per minute, but type only about 40-70 words per minute given fluency in a language. Introduce some syntax, like operators, parenthesis, brackets et cetera, and a problem becomes clear. We think and read much faster than we write.
R is very strict. It will not recognize wrongly typed words if executed. Any error in the code input process is thus magnified, and extra care must be placed on things like a missing brackets, quotes, and capital letters.
Code input should target the code writing bottleneck.
Every user is different. Typing speed, language fluency, environment, R usage history and use cases differ per user.
Code input methods should be adaptive to user preferences, use case, and stakeholders requirements.
For most code input, it is the end result that counts, not the methodology to arrive at that result. It does not matter if a user fully types out a function call, how many times a piece of code is rewritten, or if the code itself is the result of a function.
When only a single stakeholder (the code writer), is present, then the method of input does not matter much, it depends on the preferences of the writer. It results in an equilibrium of convenience to use and input speed, mediated by number of words to type, and errors. Many methods exist to aid in speediness of code writing, such as TAB-completion, static snippets and shortcuts. These, however, don't play very well with each other, and are generated to be valid for every use case, instead of the use case at hand.
Turbokit seeks to bring these input paradigms closer, to enable overlap.
Consider a situation where multiple people are looking at an R script, for example a classroom or webinar. Stakeholders would be the writer, who was to perform under some pressure, the onlookers, who want to get an insight into process of data science, and third, any future user of the script.
Humans thrive when the near-future can be predicted. However, in a group setting, it becomes harder to correctly input code, and to anticipate the stakeholder needs. What is often the result, is pre-made scripts, where the logic of the time of writing is forgotten. Consider the following code.
"~s>g>z" %>>% 1|Recap[Basic_structure] "~s*sw>g>p" %>>% 2|Introduce[starts_with()]
The focus can be shifted to the content input, while preserving the niceties of pre-made scripts, with extra clarity of structure of the talk, lesson or script. It allows users to anticipate next content early, and keeping the novelty when the point is reached.
Using style guides and naming conventions are a matter of taste. However, there are similarities in all naming conventions. Often names are chunks by separators such as underscores, capital letter or dots that specify verbs and nouns and some metadata of a function. To memorise which function in which package uses what naming convention is a big hurdle in learning any programming language. This extends to function parameters. Non-standard evaluation (NSE) enables different forms of input. Should a parameter be quoted, unquoted, a list or a vector?
Code input methods should reduce the cognitive load by being predictable.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.