├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── .travis └── covrpage.sh ├── CHANGELOG ├── DESCRIPTION ├── NAMESPACE ├── R ├── import.R ├── rstudio.R ├── utils.R └── zzz.R ├── README.Rmd ├── README.md ├── codecov.yml ├── docs ├── articles │ ├── index.html │ └── namespace-shorthands.html ├── authors.html ├── docsearch.css ├── docsearch.js ├── index.html ├── link.svg ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── colon-colon.html │ ├── importAs.html │ ├── index.html │ └── null-default.html └── tools │ └── environment.png ├── importAs.Rproj ├── man ├── colon-colon.Rd └── importAs.Rd ├── tests ├── README.html ├── README.md ├── _covrpage.Rmd ├── testthat.R └── testthat │ ├── test-debug.R │ ├── test-functional.R │ ├── test-infix.R │ ├── test-package.R │ └── test-shared.R ├── tools └── environment.png └── vignettes ├── .gitignore └── namespace-shorthands.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^importAs\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^CHANGELOG$ 5 | ^\.travis\.yml$ 6 | ^codecov\.yml$ 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | sudo: false 5 | cache: packages 6 | 7 | r_github_packages: 8 | - yonicd/covrpage 9 | 10 | after_sucess: 11 | - Rscript -e 'covr::codecov()' 12 | - bash .travis/covrpage.sh 13 | after_failure: 14 | - bash .travis/covrpage.sh 15 | deploy: 16 | provider: pages 17 | skip-cleanup: true 18 | github-token: $GH_PAT 19 | keep-history: true 20 | local-dir: docs 21 | on: 22 | branch: master 23 | -------------------------------------------------------------------------------- /.travis/covrpage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | if [ $TRAVIS_BRANCH == "master" ] ; then 5 | 6 | git config --global user.email "travis@travis-ci.org" 7 | git config --global user.name "Travis CI" 8 | 9 | git checkout -b test 10 | 11 | Rscript -e "devtools::install() ; covrpage::covrpage_ci()" 12 | 13 | git add . 14 | git commit --message "Travis build: $TRAVIS_BUILD_NUMBER [skip ci]" 15 | 16 | git remote add deploy https://jono:${GH_PAT}@github.com/.git 17 | git push -f deploy test -v 18 | 19 | else 20 | echo "Not deploying, since this branch is not master." 21 | fi 22 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | importAs 0.2.5 2 | 3 | * importing functions now print a message 4 | * unit tests 5 | * coverage/covrpage 6 | 7 | importAs 0.2.4 8 | 9 | * moved README content to vignette 10 | * pkgdown site 11 | 12 | importAs 0.2.3 13 | 14 | * debug option: options(importAs.debug = TRUE) (#6) 15 | 16 | importAs 0.2.2 17 | 18 | * clean description is provided in RStudio 19 | Environment pane (#7) 20 | 21 | importAs 0.2.1 22 | 23 | * a symbol used as a shorthand now stores 24 | a class which identifies it as an importedNamespace 25 | (and displays a message when printed) (#5) 26 | 27 | importAs 0.2.0 28 | 29 | * infix %importAs% (#1, @sa-lee) 30 | * NSE throughout (#2) 31 | * check for collisions (#3) 32 | 33 | importAs 0.1.0 34 | 35 | * basic implementation 36 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: importAs 2 | Version: 0.2.5 3 | Title: Idiomatic Python Shorthand Imports 4 | Description: Import namespaces as s5orthand symbols rather 5 | than full package names, in a python-esque fashion. 6 | Authors@R: person("Jonathan", "Carroll", 7 | email = "rpkg@jcarroll.com.au", 8 | role = c("aut", "cre"), 9 | comment = c(ORCID = "0000-0002-1404-5264")) 10 | Maintainer: Jonathan Carroll 11 | License: GPL(>=2) 12 | Encoding: UTF-8 13 | LazyData: true 14 | ByteCompile: true 15 | RoxygenNote: 6.0.1 16 | URL: https://github.com/jonocarroll/importAs 17 | BugReports: https://github.com/jonocarroll/importAs/issues 18 | Suggests: 19 | knitr, 20 | rmarkdown, 21 | testthat, 22 | covr, 23 | dplyr 24 | VignetteBuilder: knitr 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,importedNamespace) 4 | export("%importAs%") 5 | export("::") 6 | export(.rs.describeObject) 7 | export(importAs) 8 | -------------------------------------------------------------------------------- /R/import.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | print.importedNamespace <- function(x, ...) { 3 | message("Namespace '", c(x), "' can be referenced as '", attr(x, "symbol"), "'") 4 | print(c(x)) 5 | return(invisible(NULL)) 6 | } 7 | 8 | #' Overwrite :: Operator 9 | #' 10 | #' @md 11 | #' @usage pkg::name 12 | #' 13 | #' @param pkg package name: symbol or literal character string. 14 | #' @param name variable name: symbol or literal character string. 15 | #' 16 | #' Works with symbols which point to strings representing packages 17 | #' 18 | #' @section Debugging: 19 | #' 20 | #' To turn on debug mode, in which a message is printed whenever 21 | #' shorthand namespacing is in effect, set the option 22 | #' `options(importAs.debug = TRUE)` 23 | #' 24 | #' @export 25 | #' 26 | #' @examples 27 | #' ## shorthand namespacing 28 | #' # d <- "dplyr" 29 | #' # d::select 30 | #' 31 | #' ## regular namespacing still works 32 | #' # dplyr::select 33 | #' #"dplyr"::select 34 | `::` <- function (pkg, name) { 35 | charpkg <- as.character(substitute(pkg)) 36 | name <- as.character(substitute(name)) 37 | ## if pkg refers to an installed package, that will be used 38 | installed <- tryCatch(isNamespace(asNamespace(charpkg)), error = function(e) e) 39 | pkgobj <- if (!inherits(installed, "error")) charpkg else pkg 40 | if (!identical(pkgobj, charpkg) && (getOption("importAs.debug") %||% FALSE)) { 41 | message("DEBUG: ", substitute(name), " retrieved from namespace: ", pkgobj) 42 | } 43 | getExportedValue(pkgobj, name) 44 | } 45 | 46 | #' Represent A Package With A Symbol 47 | #' 48 | #' @md 49 | #' @param pkg (character or symbol) name of a (hopefully installed) package 50 | #' @param as (character or symbol) symbol into which the package name should be assigned 51 | #' 52 | #' @return the symbol represented by `as` is assigned the character string `pkg` 53 | #' 54 | #' @description 55 | #' This is merely a convenience function which signals to a reader that shorthand 56 | #' (python-esque) namespacing is occurring. This is equivalent to 57 | #' 58 | #' `d <- "dplyr"` 59 | #' 60 | #' but demonstrates that this is to be explicitly used in a shorthand namespace 61 | #' prefixing operation, such as `d::select()` 62 | #' 63 | #' @section Debugging: 64 | #' 65 | #' To turn on debug mode, in which a message is printed whenever 66 | #' shorthand namespacing is in effect, set the option 67 | #' `options(importAs.debug = TRUE)` 68 | #' 69 | #' @export 70 | #' 71 | #' @examples 72 | #' importAs("dplyr", "d") 73 | importAs <- function(pkg = NULL, as = NULL) { 74 | !is.null(substitute(pkg)) || stop("\"pkg\" is required", call. = FALSE) 75 | !is.null(substitute(as)) || stop("\"as\" is required", call. = FALSE) 76 | 77 | .importAs(substitute(pkg), substitute(as)) 78 | return(invisible(NULL)) 79 | 80 | } 81 | 82 | #' @rdname importAs 83 | #' @export 84 | #' @examples 85 | #' dplyr %importAs% d 86 | `%importAs%` <- function(pkg, as) { 87 | .importAs(substitute(pkg), substitute(as)) 88 | return(invisible(NULL)) 89 | } 90 | 91 | #' @keywords internal 92 | #' @noRd 93 | .importAs <- function(pkg, as) { 94 | ## if name already refers to an installed package, that will have precedence 95 | already_installed <- tryCatch(isNamespace(asNamespace(as)), error = function(e) e) 96 | if (!inherits(already_installed, "error")) { 97 | warning(pkg, " is itself a valid namespace and takes precedence.", call. = FALSE) 98 | return(invisible(NULL)) 99 | } 100 | message("Namespace '", as.character(pkg), "' can be referenced as '", as.character(as), "'") 101 | assign(as.character(as), 102 | structure(as.character(pkg), 103 | class = c("importedNamespace", "character"), 104 | symbol = as.character(as)), 105 | envir = .GlobalEnv) 106 | return(invisible(NULL)) 107 | } 108 | -------------------------------------------------------------------------------- /R/rstudio.R: -------------------------------------------------------------------------------- 1 | #' Show Clean Description in RStudio 2 | #' @export 3 | #' @noRd 4 | .rs.describeObject <- function(env, objName) { 5 | existing <- get(".rs.describeObject", 6 | envir = as.environment('tools:rstudio'))(objName = objName, 7 | env = env) 8 | if (inherits(get(objName), "importedNamespace")) { 9 | savedattr <- attr(existing$value, "class") 10 | existing$value <- paste0("Namespace shorthand for ", c(get(objName))) 11 | attr(existing$value, "class") <- savedattr 12 | } 13 | existing 14 | } 15 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | #' Default value for `NULL`. 2 | #' 3 | #' This infix function makes it easy to replace `NULL`s with a 4 | #' default value. It's inspired by the way that Ruby's or operation (`||`) 5 | #' works. 6 | #' 7 | #' @noRd 8 | #' @param x,y If `x` is NULL, will return `y`; otherwise returns 9 | #' `x`. 10 | #' @name null-default 11 | #' @examples 12 | #' 1 %||% 2 13 | #' NULL %||% 2 14 | `%||%` <- function(x, y) { 15 | if (is.null(x)) { 16 | y 17 | } else { 18 | x 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | op <- options() 3 | op.importAs <- list( 4 | importAs.debug = FALSE 5 | ) 6 | toset <- !(names(op.importAs) %in% names(op)) 7 | if (any(toset)) options(op.importAs[toset]) 8 | 9 | invisible() 10 | } 11 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | editor_options: 4 | chunk_output_type: console 5 | --- 6 | 7 | 8 | 9 | ```{r setup, include = FALSE} 10 | knitr::opts_chunk$set( 11 | collapse = TRUE, 12 | comment = "#>", 13 | fig.path = "man/figures/README-", 14 | out.width = "100%" 15 | ) 16 | library(importAs) 17 | ``` 18 | 19 | # importAs 20 | 21 | [![Travis build status](https://travis-ci.org/jonocarroll/importAs.svg?branch=master)](https://travis-ci.org/jonocarroll/importAs) 22 | [![Coverage status](https://codecov.io/gh/jonocarroll/importAs/branch/master/graph/badge.svg)](https://codecov.io/github/jonocarroll/importAs?branch=master) 23 | [![Covrpage Summary](https://img.shields.io/badge/covrpage-Last_Build_2018_10_10-brightgreen.svg)](http://tinyurl.com/ybwc9qt4) 24 | 25 | This package helps mimic the idiomatic python importing of packages such as 26 | 27 | ```{} 28 | import dplyr as d 29 | ``` 30 | 31 | In order to mimic this as closely as possible, the function `importAs` takes a 32 | package name and a (short?) name for that and creates a linkage. Helpful information 33 | is provided when printing and within the RStudio Environment pane 34 | 35 | ```{r} 36 | importAs(dplyr, d) 37 | 38 | ## or ## 39 | 40 | dplyr %importAs% d 41 | 42 | d 43 | ``` 44 | 45 | ![](./tools/environment.png) 46 | 47 | 48 | ```{r} 49 | d::filter(mtcars, cyl == 4, am == 1) 50 | ``` 51 | 52 | For full details, see the vignette ['namespace-shorthands'](https://jonocarroll.github.io/importAs/articles/namespace-shorthands.html). 53 | 54 | ## Installation 55 | 56 | You can install the development version of `importAs` with 57 | 58 | ```{r, eval = FALSE} 59 | ## install.packages("devtools") 60 | devtools::install_github("jonocarroll/importAs") 61 | ``` 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # importAs 5 | 6 | [![Travis build 7 | status](https://travis-ci.org/jonocarroll/importAs.svg?branch=master)](https://travis-ci.org/jonocarroll/importAs) 8 | [![Coverage 9 | status](https://codecov.io/gh/jonocarroll/importAs/branch/master/graph/badge.svg)](https://codecov.io/github/jonocarroll/importAs?branch=master) 10 | [![Covrpage 11 | Summary](https://img.shields.io/badge/covrpage-Last_Build_2018_10_10-brightgreen.svg)](http://tinyurl.com/ybwc9qt4) 12 | 13 | This package helps mimic the idiomatic python importing of packages such 14 | as 15 | 16 | import dplyr as d 17 | 18 | In order to mimic this as closely as possible, the function `importAs` 19 | takes a package name and a (short?) name for that and creates a linkage. 20 | Helpful information is provided when printing and within the RStudio 21 | Environment pane 22 | 23 | ``` r 24 | importAs(dplyr, d) 25 | #> Namespace 'dplyr' can be referenced as 'd' 26 | 27 | ## or ## 28 | 29 | dplyr %importAs% d 30 | #> Namespace 'dplyr' can be referenced as 'd' 31 | 32 | d 33 | #> Namespace 'dplyr' can be referenced as 'd' 34 | #> [1] "dplyr" 35 | ``` 36 | 37 | ![](./tools/environment.png) 38 | 39 | ``` r 40 | d::filter(mtcars, cyl == 4, am == 1) 41 | #> mpg cyl disp hp drat wt qsec vs am gear carb 42 | #> 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 43 | #> 2 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 44 | #> 3 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 45 | #> 4 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 46 | #> 5 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 47 | #> 6 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 48 | #> 7 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 49 | #> 8 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 50 | ``` 51 | 52 | For full details, see the vignette 53 | [‘namespace-shorthands’](https://jonocarroll.github.io/importAs/articles/namespace-shorthands.html). 54 | 55 | ## Installation 56 | 57 | You can install the development version of `importAs` with 58 | 59 | ``` r 60 | ## install.packages("devtools") 61 | devtools::install_github("jonocarroll/importAs") 62 | ``` 63 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 111 | 112 |
113 |

All vignettes

114 |

115 | 116 | 119 |
120 |
121 |
122 | 123 |
124 | 127 | 128 |
129 |

Site built with pkgdown.

130 |
131 | 132 |
133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/articles/namespace-shorthands.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Namespace Shortcuts • importAs 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 |
22 |
73 | 74 | 75 | 76 |
77 |
78 | 88 | 89 | 90 | 91 |
92 |

93 | importAs

94 |

This package helps mimic the idiomatic python importing of packages such as

95 | 96 |

In order to mimic this as closely as possible, the function importAs takes a package name and a (short?) name for that and creates a linkage

97 | 108 |

or

109 | 114 |

This is merely a convenience, however. In reality a variable d is created with the value "dplyr" (and a class so we can dispatch on it). We could also do this manually for another package, creating a simple character object

115 | 118 |

The importAs function is merely a signal to a reader that this magic is going to be performed. The class means it is clearer that the shorthand is being used.

119 |

A custom description is provided within the RStudio Environment pane which identifies each shorthand and the namespace to which it refers.

120 |

121 |

As a further convenience, this can be specified using an infix operator (h/t @sa-lee)

122 | 127 |

At this point nothing magical has happened. The magic comes from overwriting the :: operator. To – at least, my – surprise, :: can happily take a character argument for the left-hand side, so

128 | 135 |

works. The magic part is rewriting this function to look deeper if provided with a symbol which already resolves to a character string representing an installed package. The result is that we can shorthand the namespace referencing

136 | 148 |

without interfering with any existing functionality

149 | 161 |
162 |

163 | Collisions

164 |

If the symbol you are trying to use as a shorthand already exists as an available namespace, then that will take precedence. This prevents accidentally overwriting a namespace reference

165 | 169 |

and the existing namespace will still be found

170 | 176 |
177 | 206 |
207 |

208 | Installation

209 |

You can install the development version of importAs with

210 | 212 |
213 |
214 |
215 | 216 | 231 | 232 |
233 | 234 | 235 |
238 | 239 |
240 |

Site built with pkgdown.

241 |
242 | 243 |
244 |
245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 111 | 112 |
    113 |
  • 114 |

    Jonathan Carroll. Author, maintainer. 115 |

    116 |
  • 117 |
118 | 119 |
120 | 121 |
122 | 123 | 124 |
125 | 128 | 129 |
130 |

Site built with pkgdown.

131 |
132 | 133 |
134 |
135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /docs/docsearch.css: -------------------------------------------------------------------------------- 1 | /* Docsearch -------------------------------------------------------------- */ 2 | /* 3 | Source: https://github.com/algolia/docsearch/ 4 | License: MIT 5 | */ 6 | 7 | .algolia-autocomplete { 8 | display: block; 9 | -webkit-box-flex: 1; 10 | -ms-flex: 1; 11 | flex: 1 12 | } 13 | 14 | .algolia-autocomplete .ds-dropdown-menu { 15 | width: 100%; 16 | min-width: none; 17 | max-width: none; 18 | padding: .75rem 0; 19 | background-color: #fff; 20 | background-clip: padding-box; 21 | border: 1px solid rgba(0, 0, 0, .1); 22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); 23 | } 24 | 25 | @media (min-width:768px) { 26 | .algolia-autocomplete .ds-dropdown-menu { 27 | width: 175% 28 | } 29 | } 30 | 31 | .algolia-autocomplete .ds-dropdown-menu::before { 32 | display: none 33 | } 34 | 35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { 36 | padding: 0; 37 | background-color: rgb(255,255,255); 38 | border: 0; 39 | max-height: 80vh; 40 | } 41 | 42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions { 43 | margin-top: 0 44 | } 45 | 46 | .algolia-autocomplete .algolia-docsearch-suggestion { 47 | padding: 0; 48 | overflow: visible 49 | } 50 | 51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header { 52 | padding: .125rem 1rem; 53 | margin-top: 0; 54 | font-size: 1.3em; 55 | font-weight: 500; 56 | color: #00008B; 57 | border-bottom: 0 58 | } 59 | 60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper { 61 | float: none; 62 | padding-top: 0 63 | } 64 | 65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { 66 | float: none; 67 | width: auto; 68 | padding: 0; 69 | text-align: left 70 | } 71 | 72 | .algolia-autocomplete .algolia-docsearch-suggestion--content { 73 | float: none; 74 | width: auto; 75 | padding: 0 76 | } 77 | 78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before { 79 | display: none 80 | } 81 | 82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { 83 | padding-top: .75rem; 84 | margin-top: .75rem; 85 | border-top: 1px solid rgba(0, 0, 0, .1) 86 | } 87 | 88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { 89 | display: block; 90 | padding: .1rem 1rem; 91 | margin-bottom: 0.1; 92 | font-size: 1.0em; 93 | font-weight: 400 94 | /* display: none */ 95 | } 96 | 97 | .algolia-autocomplete .algolia-docsearch-suggestion--title { 98 | display: block; 99 | padding: .25rem 1rem; 100 | margin-bottom: 0; 101 | font-size: 0.9em; 102 | font-weight: 400 103 | } 104 | 105 | .algolia-autocomplete .algolia-docsearch-suggestion--text { 106 | padding: 0 1rem .5rem; 107 | margin-top: -.25rem; 108 | font-size: 0.8em; 109 | font-weight: 400; 110 | line-height: 1.25 111 | } 112 | 113 | .algolia-autocomplete .algolia-docsearch-footer { 114 | width: 110px; 115 | height: 20px; 116 | z-index: 3; 117 | margin-top: 10.66667px; 118 | float: right; 119 | font-size: 0; 120 | line-height: 0; 121 | } 122 | 123 | .algolia-autocomplete .algolia-docsearch-footer--logo { 124 | background-image: url("data:image/svg+xml;utf8,"); 125 | background-repeat: no-repeat; 126 | background-position: 50%; 127 | background-size: 100%; 128 | overflow: hidden; 129 | text-indent: -9000px; 130 | width: 100%; 131 | height: 100%; 132 | display: block; 133 | transform: translate(-8px); 134 | } 135 | 136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight { 137 | color: #FF8C00; 138 | background: rgba(232, 189, 54, 0.1) 139 | } 140 | 141 | 142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { 143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) 144 | } 145 | 146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { 147 | background-color: rgba(192, 192, 192, .15) 148 | } 149 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Idiomatic Python Shorthand Imports • importAs 9 | 10 | 11 | 12 | 13 | 15 | 16 | 20 | 21 | 22 |
23 |
74 | 75 | 76 | 77 |
78 |
79 | 80 | 81 | 82 | 83 | 84 |
85 | 87 |

Coverage statusCovrpage Summary

88 |

This package helps mimic the idiomatic python importing of packages such as

89 | 90 |

In order to mimic this as closely as possible, the function importAs takes a package name and a (short?) name for that and creates a linkage. Helpful information is provided when printing and within the RStudio Environment pane

91 | 102 |

103 | 113 |

For full details, see the vignette ‘namespace-shorthands’.

114 |
115 |

116 | Installation

117 |

You can install the development version of importAs with

118 | 120 |
121 |
122 |
123 | 124 | 148 | 149 |
150 | 151 | 152 |
155 | 156 |
157 |

Site built with pkgdown.

158 |
159 | 160 |
161 |
162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body > .container { 21 | display: flex; 22 | height: 100%; 23 | flex-direction: column; 24 | 25 | padding-top: 60px; 26 | } 27 | 28 | body > .container .row { 29 | flex: 1 0 auto; 30 | } 31 | 32 | footer { 33 | margin-top: 45px; 34 | padding: 35px 0 36px; 35 | border-top: 1px solid #e5e5e5; 36 | color: #666; 37 | display: flex; 38 | flex-shrink: 0; 39 | } 40 | footer p { 41 | margin-bottom: 0; 42 | } 43 | footer div { 44 | flex: 1; 45 | } 46 | footer .pkgdown { 47 | text-align: right; 48 | } 49 | footer p { 50 | margin-bottom: 0; 51 | } 52 | 53 | img.icon { 54 | float: right; 55 | } 56 | 57 | img { 58 | max-width: 100%; 59 | } 60 | 61 | /* Typographic tweaking ---------------------------------*/ 62 | 63 | .contents h1.page-header { 64 | margin-top: calc(-60px + 1em); 65 | } 66 | 67 | /* Section anchors ---------------------------------*/ 68 | 69 | a.anchor { 70 | margin-left: -30px; 71 | display:inline-block; 72 | width: 30px; 73 | height: 30px; 74 | visibility: hidden; 75 | 76 | background-image: url(./link.svg); 77 | background-repeat: no-repeat; 78 | background-size: 20px 20px; 79 | background-position: center center; 80 | } 81 | 82 | .hasAnchor:hover a.anchor { 83 | visibility: visible; 84 | } 85 | 86 | @media (max-width: 767px) { 87 | .hasAnchor:hover a.anchor { 88 | visibility: hidden; 89 | } 90 | } 91 | 92 | 93 | /* Fixes for fixed navbar --------------------------*/ 94 | 95 | .contents h1, .contents h2, .contents h3, .contents h4 { 96 | padding-top: 60px; 97 | margin-top: -40px; 98 | } 99 | 100 | /* Static header placement on mobile devices */ 101 | @media (max-width: 767px) { 102 | .navbar-fixed-top { 103 | position: absolute; 104 | } 105 | .navbar { 106 | padding: 0; 107 | } 108 | } 109 | 110 | 111 | /* Sidebar --------------------------*/ 112 | 113 | #sidebar { 114 | margin-top: 30px; 115 | } 116 | #sidebar h2 { 117 | font-size: 1.5em; 118 | margin-top: 1em; 119 | } 120 | 121 | #sidebar h2:first-child { 122 | margin-top: 0; 123 | } 124 | 125 | #sidebar .list-unstyled li { 126 | margin-bottom: 0.5em; 127 | } 128 | 129 | .orcid { 130 | height: 16px; 131 | vertical-align: middle; 132 | } 133 | 134 | /* Reference index & topics ----------------------------------------------- */ 135 | 136 | .ref-index th {font-weight: normal;} 137 | 138 | .ref-index td {vertical-align: top;} 139 | .ref-index .alias {width: 40%;} 140 | .ref-index .title {width: 60%;} 141 | 142 | .ref-index .alias {width: 40%;} 143 | .ref-index .title {width: 60%;} 144 | 145 | .ref-arguments th {text-align: right; padding-right: 10px;} 146 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 147 | .ref-arguments .name {width: 20%;} 148 | .ref-arguments .desc {width: 80%;} 149 | 150 | /* Nice scrolling for wide elements --------------------------------------- */ 151 | 152 | table { 153 | display: block; 154 | overflow: auto; 155 | } 156 | 157 | /* Syntax highlighting ---------------------------------------------------- */ 158 | 159 | pre { 160 | word-wrap: normal; 161 | word-break: normal; 162 | border: 1px solid #eee; 163 | } 164 | 165 | pre, code { 166 | background-color: #f8f8f8; 167 | color: #333; 168 | } 169 | 170 | pre code { 171 | overflow: auto; 172 | word-wrap: normal; 173 | white-space: pre; 174 | } 175 | 176 | pre .img { 177 | margin: 5px 0; 178 | } 179 | 180 | pre .img img { 181 | background-color: #fff; 182 | display: block; 183 | height: auto; 184 | } 185 | 186 | code a, pre a { 187 | color: #375f84; 188 | } 189 | 190 | a.sourceLine:hover { 191 | text-decoration: none; 192 | } 193 | 194 | .fl {color: #1514b5;} 195 | .fu {color: #000000;} /* function */ 196 | .ch,.st {color: #036a07;} /* string */ 197 | .kw {color: #264D66;} /* keyword */ 198 | .co {color: #888888;} /* comment */ 199 | 200 | .message { color: black; font-weight: bolder;} 201 | .error { color: orange; font-weight: bolder;} 202 | .warning { color: #6A0366; font-weight: bolder;} 203 | 204 | /* Clipboard --------------------------*/ 205 | 206 | .hasCopyButton { 207 | position: relative; 208 | } 209 | 210 | .btn-copy-ex { 211 | position: absolute; 212 | right: 0; 213 | top: 0; 214 | visibility: hidden; 215 | } 216 | 217 | .hasCopyButton:hover button.btn-copy-ex { 218 | visibility: visible; 219 | } 220 | 221 | /* mark.js ----------------------------*/ 222 | 223 | mark { 224 | background-color: rgba(255, 255, 51, 0.5); 225 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 226 | padding: 1px; 227 | } 228 | 229 | /* vertical spacing after htmlwidgets */ 230 | .html-widget { 231 | margin-bottom: 10px; 232 | } 233 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $("#sidebar") 6 | .stick_in_parent({offset_top: 40}) 7 | .on('sticky_kit:bottom', function(e) { 8 | $(this).parent().css('position', 'static'); 9 | }) 10 | .on('sticky_kit:unbottom', function(e) { 11 | $(this).parent().css('position', 'relative'); 12 | }); 13 | 14 | $('body').scrollspy({ 15 | target: '#sidebar', 16 | offset: 60 17 | }); 18 | 19 | $('[data-toggle="tooltip"]').tooltip(); 20 | 21 | var cur_path = paths(location.pathname); 22 | var links = $("#navbar ul li a"); 23 | var max_length = -1; 24 | var pos = -1; 25 | for (var i = 0; i < links.length; i++) { 26 | if (links[i].getAttribute("href") === "#") 27 | continue; 28 | var path = paths(links[i].pathname); 29 | 30 | var length = prefix_length(cur_path, path); 31 | if (length > max_length) { 32 | max_length = length; 33 | pos = i; 34 | } 35 | } 36 | 37 | // Add class to parent
  • , and enclosing
  • if in dropdown 38 | if (pos >= 0) { 39 | var menu_anchor = $(links[pos]); 40 | menu_anchor.parent().addClass("active"); 41 | menu_anchor.closest("li.dropdown").addClass("active"); 42 | } 43 | }); 44 | 45 | function paths(pathname) { 46 | var pieces = pathname.split("/"); 47 | pieces.shift(); // always starts with / 48 | 49 | var end = pieces[pieces.length - 1]; 50 | if (end === "index.html" || end === "") 51 | pieces.pop(); 52 | return(pieces); 53 | } 54 | 55 | function prefix_length(needle, haystack) { 56 | if (needle.length > haystack.length) 57 | return(0); 58 | 59 | // Special case for length-0 haystack, since for loop won't run 60 | if (haystack.length === 0) { 61 | return(needle.length === 0 ? 1 : 0); 62 | } 63 | 64 | for (var i = 0; i < haystack.length; i++) { 65 | if (needle[i] != haystack[i]) 66 | return(i); 67 | } 68 | 69 | return(haystack.length); 70 | } 71 | 72 | /* Clipboard --------------------------*/ 73 | 74 | function changeTooltipMessage(element, msg) { 75 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 76 | element.setAttribute('data-original-title', msg); 77 | $(element).tooltip('show'); 78 | element.setAttribute('data-original-title', tooltipOriginalTitle); 79 | } 80 | 81 | if(Clipboard.isSupported()) { 82 | $(document).ready(function() { 83 | var copyButton = ""; 84 | 85 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 86 | 87 | // Insert copy buttons: 88 | $(copyButton).prependTo(".hasCopyButton"); 89 | 90 | // Initialize tooltips: 91 | $('.btn-copy-ex').tooltip({container: 'body'}); 92 | 93 | // Initialize clipboard: 94 | var clipboardBtnCopies = new Clipboard('[data-clipboard-copy]', { 95 | text: function(trigger) { 96 | return trigger.parentNode.textContent; 97 | } 98 | }); 99 | 100 | clipboardBtnCopies.on('success', function(e) { 101 | changeTooltipMessage(e.trigger, 'Copied!'); 102 | e.clearSelection(); 103 | }); 104 | 105 | clipboardBtnCopies.on('error', function() { 106 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 107 | }); 108 | }); 109 | } 110 | })(window.jQuery || window.$) 111 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.2.1 2 | pkgdown: 1.1.0 3 | pkgdown_sha: ~ 4 | articles: 5 | namespace-shorthands: namespace-shorthands.html 6 | 7 | -------------------------------------------------------------------------------- /docs/reference/colon-colon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Overwrite :: Operator — :: • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 48 | 49 | 50 | 51 | 52 |
    53 |
    54 | 105 | 106 | 107 |
    108 | 109 |
    110 |
    111 | 116 | 117 |
    118 | 119 |

    Overwrite :: Operator

    120 | 121 |
    122 | 123 |
    pkg::name
    124 | 125 |

    Arguments

    126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 136 | 137 |
    pkg

    package name: symbol or literal character string.

    name

    variable name: symbol or literal character string.

    135 |

    Works with symbols which point to strings representing packages

    138 | 139 |

    Debugging

    140 | 141 | 142 |

    To turn on debug mode, in which a message is printed whenever 143 | shorthand namespacing is in effect, set the option 144 | options(importAs.debug = TRUE)

    145 | 146 | 147 |

    Examples

    148 |
    ## shorthand namespacing 149 | d <- "dplyr" 150 | d::select
    #> function (.data, ...) 151 | #> { 152 | #> UseMethod("select") 153 | #> } 154 | #> <environment: namespace:dplyr>
    155 | ## regular namespacing still works 156 | dplyr::select
    #> function (.data, ...) 157 | #> { 158 | #> UseMethod("select") 159 | #> } 160 | #> <environment: namespace:dplyr>
    "dplyr"::select
    #> function (.data, ...) 161 | #> { 162 | #> UseMethod("select") 163 | #> } 164 | #> <environment: namespace:dplyr>
    165 |
    166 | 177 |
    178 | 179 |
    180 | 183 | 184 |
    185 |

    Site built with pkgdown.

    186 |
    187 | 188 |
    189 |
    190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /docs/reference/importAs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Represent A Package With A Symbol — importAs • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 |
    57 |
    58 | 109 | 110 | 111 |
    112 | 113 |
    114 |
    115 | 120 | 121 |
    122 | 123 |

    This is merely a convenience function which signals to a reader that shorthand 124 | (python-esque) namespacing is occurring. This is equivalent to

    125 |

    d <- "dplyr"

    126 |

    but demonstrates that this is to be explicitly used in a shorthand namespace 127 | prefixing operation, such as d::select()

    128 | 129 |
    130 | 131 |
    importAs(pkg = NULL, as = NULL)
    132 | 
    133 | pkg %importAs% as
    134 | 135 |

    Arguments

    136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 |
    pkg

    (character or symbol) name of a (hopefully installed) package

    as

    (character or symbol) symbol into which the package name should be assigned

    147 | 148 |

    Value

    149 | 150 |

    the symbol represented by as is assigned the character string pkg

    151 | 152 |

    Debugging

    153 | 154 | 155 |

    To turn on debug mode, in which a message is printed whenever 156 | shorthand namespacing is in effect, set the option 157 | options(importAs.debug = TRUE)

    158 | 159 | 160 |

    Examples

    161 |
    importAs("dplyr", "d")
    #> Namespace 'dplyr' can be referenced as 'd'
    dplyr %importAs% d
    #> Namespace 'dplyr' can be referenced as 'd'
    162 |
    163 | 176 |
    177 | 178 |
    179 | 182 | 183 |
    184 |

    Site built with pkgdown.

    185 |
    186 | 187 |
    188 |
    189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 |
    50 |
    51 | 102 | 103 | 104 |
    105 | 106 |
    107 |
    108 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 126 | 127 | 128 | 129 | 132 | 133 | 134 | 135 | 138 | 139 | 140 | 141 |
    123 |

    All functions

    124 |

    125 |
    130 |

    `::`()

    131 |

    Overwrite :: Operator

    136 |

    importAs() `%importAs%`

    137 |

    Represent A Package With A Symbol

    142 |
    143 | 144 | 150 |
    151 | 152 |
    153 | 156 | 157 |
    158 |

    Site built with pkgdown.

    159 |
    160 | 161 |
    162 |
    163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/reference/null-default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Default value for `NULL`. — null-default • importAs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 |
    55 |
    56 | 107 | 108 | 109 |
    110 | 111 |
    112 |
    113 | 118 | 119 |
    120 | 121 |

    This infix function makes it easy to replace `NULL`s with a 122 | default value. It's inspired by the way that Ruby's or operation (`||`) 123 | works.

    124 | 125 |
    126 | 127 |
    x %||% y
    128 | 129 |

    Arguments

    130 | 131 | 132 | 133 | 134 | 136 | 137 |
    x, y

    If `x` is NULL, will return `y`; otherwise returns 135 | `x`.

    138 | 139 | 140 |

    Examples

    141 |
    1 %||% 2
    #> [1] 1
    NULL %||% 2
    #> [1] 2
    142 |
    143 | 152 |
    153 | 154 |
    155 | 158 | 159 |
    160 |

    Site built with pkgdown.

    161 |
    162 | 163 |
    164 |
    165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/tools/environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonocarroll/importAs/4b4394f020b847f60feef17da4a9593eaf7158c5/docs/tools/environment.png -------------------------------------------------------------------------------- /importAs.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /man/colon-colon.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/import.R 3 | \name{::} 4 | \alias{::} 5 | \title{Overwrite :: Operator} 6 | \usage{ 7 | pkg::name 8 | } 9 | \arguments{ 10 | \item{pkg}{package name: symbol or literal character string.} 11 | 12 | \item{name}{variable name: symbol or literal character string. 13 | 14 | Works with symbols which point to strings representing packages} 15 | } 16 | \description{ 17 | Overwrite :: Operator 18 | } 19 | \section{Debugging}{ 20 | 21 | 22 | To turn on debug mode, in which a message is printed whenever 23 | shorthand namespacing is in effect, set the option 24 | \code{options(importAs.debug = TRUE)} 25 | } 26 | 27 | \examples{ 28 | ## shorthand namespacing 29 | # d <- "dplyr" 30 | # d::select 31 | 32 | ## regular namespacing still works 33 | # dplyr::select 34 | #"dplyr"::select 35 | } 36 | -------------------------------------------------------------------------------- /man/importAs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/import.R 3 | \name{importAs} 4 | \alias{importAs} 5 | \alias{\%importAs\%} 6 | \title{Represent A Package With A Symbol} 7 | \usage{ 8 | importAs(pkg = NULL, as = NULL) 9 | 10 | pkg \%importAs\% as 11 | } 12 | \arguments{ 13 | \item{pkg}{(character or symbol) name of a (hopefully installed) package} 14 | 15 | \item{as}{(character or symbol) symbol into which the package name should be assigned} 16 | } 17 | \value{ 18 | the symbol represented by \code{as} is assigned the character string \code{pkg} 19 | } 20 | \description{ 21 | This is merely a convenience function which signals to a reader that shorthand 22 | (python-esque) namespacing is occurring. This is equivalent to 23 | 24 | \code{d <- "dplyr"} 25 | 26 | but demonstrates that this is to be explicitly used in a shorthand namespace 27 | prefixing operation, such as \code{d::select()} 28 | } 29 | \section{Debugging}{ 30 | 31 | 32 | To turn on debug mode, in which a message is printed whenever 33 | shorthand namespacing is in effect, set the option 34 | \code{options(importAs.debug = TRUE)} 35 | } 36 | 37 | \examples{ 38 | importAs("dplyr", "d") 39 | dplyr \%importAs\% d 40 | } 41 | -------------------------------------------------------------------------------- /tests/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 588 | 598 | 599 | 600 | 601 | 602 | 603 |

    Tests and Coverage

    604 |

    10 October, 2018 21:01:06

    605 |

    This output is created by covrpage.

    606 |

    Coverage

    607 |

    Coverage summary is created using the covr package.

    608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 |
    ObjectCoverage (%)
    importAs37.78
    R/rstudio.R0.00
    R/utils.R0.00
    R/zzz.R0.00
    R/import.R62.96
    638 |
    639 | 640 |

    Unit Tests

    641 |

    Unit Test summary is created using the testthat package.

    642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 |
    filentimeerrorfailedskippedwarning
    test-debug.R20.0390000
    test-functional.R70.0110000
    test-infix.R70.0110000
    test-package.R30.0040000
    test-shared.R40.0060000
    702 |
    703 | 704 | Show Detailed Test Results 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 |
    filecontextteststatusntime
    test-debug.RdebugmessagingPASS20.039
    test-functional.Rfunctional form usageimport – functionalPASS10.002
    test-functional.Rfunctional form usagestructural components – functionalPASS30.003
    test-functional.Rfunctional form usagemessaging – functionalPASS10.001
    test-functional.Rfunctional form usageretrieval – functionalPASS20.005
    test-infix.Rinfix form usageimport – infixPASS10.002
    test-infix.Rinfix form usagestructural components – infixPASS30.004
    test-infix.Rinfix form usagemessaging – infixPASS10.001
    test-infix.Rinfix form usageretrieval – infixPASS20.004
    test-package.Rpackagepackage option is set on package loadPASS10.001
    test-package.Rpackageresetting package option after unloadPASS10.001
    test-package.Rpackageoption remains set after reloading packagePASS10.002
    test-shared.RsharedequivalencePASS20.003
    test-shared.RsharedprecedencePASS20.003
    833 |
    834 | 835 |
    836 | 837 | Session Info 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 |
    FieldValue
    VersionR version 3.4.4 (2018-03-15)
    Platformx86_64-pc-linux-gnu (64-bit)
    RunningPop!_OS 18.04 LTS
    Languageen_AU
    TimezoneAustralia/Adelaide
    869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 |
    PackageVersion
    testthat2.0.0
    covr3.2.0
    covrpage0.0.60
    891 |
    892 | 893 | 894 | 895 | 896 | 897 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | Tests and Coverage 2 | ================ 3 | 10 October, 2018 21:01:06 4 | 5 | This output is created by 6 | [covrpage](https://github.com/yonicd/covrpage). 7 | 8 | ## Coverage 9 | 10 | Coverage summary is created using the 11 | [covr](https://github.com/r-lib/covr) package. 12 | 13 | | Object | Coverage (%) | 14 | | :---------------------------- | :----------: | 15 | | importAs | 37.78 | 16 | | [R/rstudio.R](../R/rstudio.R) | 0.00 | 17 | | [R/utils.R](../R/utils.R) | 0.00 | 18 | | [R/zzz.R](../R/zzz.R) | 0.00 | 19 | | [R/import.R](../R/import.R) | 62.96 | 20 | 21 |
    22 | 23 | ## Unit Tests 24 | 25 | Unit Test summary is created using the 26 | [testthat](https://github.com/r-lib/testthat) 27 | package. 28 | 29 | | file | n | time | error | failed | skipped | warning | 30 | | :---------------------------------------------- | -: | ----: | ----: | -----: | ------: | ------: | 31 | | [test-debug.R](testthat/test-debug.R) | 2 | 0.039 | 0 | 0 | 0 | 0 | 32 | | [test-functional.R](testthat/test-functional.R) | 7 | 0.011 | 0 | 0 | 0 | 0 | 33 | | [test-infix.R](testthat/test-infix.R) | 7 | 0.011 | 0 | 0 | 0 | 0 | 34 | | [test-package.R](testthat/test-package.R) | 3 | 0.004 | 0 | 0 | 0 | 0 | 35 | | [test-shared.R](testthat/test-shared.R) | 4 | 0.006 | 0 | 0 | 0 | 0 | 36 | 37 |
    38 | 39 | Show Detailed Test Results 40 | 41 | 42 | | file | context | test | status | n | time | 43 | | :-------------------------------------------------- | :-------------------- | :----------------------------------------- | :----- | -: | ----: | 44 | | [test-debug.R](testthat/test-debug.R#L8) | debug | messaging | PASS | 2 | 0.039 | 45 | | [test-functional.R](testthat/test-functional.R#L6) | functional form usage | import – functional | PASS | 1 | 0.002 | 46 | | [test-functional.R](testthat/test-functional.R#L10) | functional form usage | structural components – functional | PASS | 3 | 0.003 | 47 | | [test-functional.R](testthat/test-functional.R#L16) | functional form usage | messaging – functional | PASS | 1 | 0.001 | 48 | | [test-functional.R](testthat/test-functional.R#L21) | functional form usage | retrieval – functional | PASS | 2 | 0.005 | 49 | | [test-infix.R](testthat/test-infix.R#L6) | infix form usage | import – infix | PASS | 1 | 0.002 | 50 | | [test-infix.R](testthat/test-infix.R#L10) | infix form usage | structural components – infix | PASS | 3 | 0.004 | 51 | | [test-infix.R](testthat/test-infix.R#L16) | infix form usage | messaging – infix | PASS | 1 | 0.001 | 52 | | [test-infix.R](testthat/test-infix.R#L21) | infix form usage | retrieval – infix | PASS | 2 | 0.004 | 53 | | [test-package.R](testthat/test-package.R#L4) | package | package option is set on package load | PASS | 1 | 0.001 | 54 | | [test-package.R](testthat/test-package.R#L11) | package | resetting package option after unload | PASS | 1 | 0.001 | 55 | | [test-package.R](testthat/test-package.R#L17) | package | option remains set after reloading package | PASS | 1 | 0.002 | 56 | | [test-shared.R](testthat/test-shared.R#L7) | shared | equivalence | PASS | 2 | 0.003 | 57 | | [test-shared.R](testthat/test-shared.R#L12) | shared | precedence | PASS | 2 | 0.003 | 58 | 59 |
    60 | 61 |
    62 | 63 | Session Info 64 | 65 | | Field | Value | 66 | | :------- | :---------------------------- | 67 | | Version | R version 3.4.4 (2018-03-15) | 68 | | Platform | x86\_64-pc-linux-gnu (64-bit) | 69 | | Running | Pop\!\_OS 18.04 LTS | 70 | | Language | en\_AU | 71 | | Timezone | Australia/Adelaide | 72 | 73 | | Package | Version | 74 | | :------- | :------ | 75 | | testthat | 2.0.0 | 76 | | covr | 3.2.0 | 77 | | covrpage | 0.0.60 | 78 | 79 |
    80 | 81 | 82 | -------------------------------------------------------------------------------- /tests/_covrpage.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Tests and Coverage" 3 | date: "`r format(Sys.time(), '%d %B, %Y %H:%M:%S')`" 4 | --- 5 | 6 | This output is created by [covrpage](https://github.com/yonicd/covrpage). 7 | 8 | ```{r load,include=FALSE} 9 | library(covr , warn.conflicts = FALSE , quietly = TRUE) 10 | library(knitr , warn.conflicts = FALSE , quietly = TRUE) 11 | library(magrittr , warn.conflicts = FALSE , quietly = TRUE) 12 | 13 | ``` 14 | 15 | ```{r tests, include=FALSE} 16 | #test_x <- testthat::test_dir('testthat') 17 | this_pkg <- basename(normalizePath('..')) 18 | test_x <- testthat::test_check(this_pkg,reporter = testthat::default_reporter(),stop_on_failure = FALSE,stop_on_warning = FALSE) 19 | 20 | skip <- length(test_x)>0 21 | ``` 22 | 23 | ```{r maps, include=FALSE} 24 | test_m <- covrpage::map_testthat('testthat') 25 | ``` 26 | 27 | 28 | ```{r, include=FALSE} 29 | test_x_short <- test_x%>% 30 | covrpage::testthat_summary(type='short') 31 | 32 | test_x_long <- test_x%>% 33 | covrpage::testthat_summary(type='long') 34 | 35 | ``` 36 | 37 | ```{r, include=FALSE,eval=skip} 38 | test_skip <- test_x_long[test_x_long$status!='PASS',c('file','test')] 39 | 40 | test_skip$file <- gsub('#(.*?)$','',basename(test_skip$file)) 41 | 42 | test_skip <- merge(test_skip,test_m) 43 | 44 | failed <- nrow(test_skip)>0 45 | 46 | ``` 47 | 48 | ```{r, include=FALSE,eval=!skip} 49 | 50 | test_skip <- test_m 51 | 52 | ``` 53 | 54 | ## Coverage 55 | 56 | Coverage summary is created using the [covr](https://github.com/r-lib/covr) package. 57 | 58 | ```{r,include=FALSE} 59 | cvr <- covrpage::coverage_skip(test_path = '../tests/testthat', test_skip = test_skip) 60 | ``` 61 | 62 | ```{r,echo=FALSE,eval=failed} 63 | cat(sprintf('%s Tests Failed\n Coverage statistics are approximations of the non-failing tests.\n Use with caution\n\n For further investigation check in testthat summary tables.',covrpage:::emos[['WARNING']])) 64 | ``` 65 | 66 | ```{r,echo=FALSE} 67 | cvr%>% 68 | covrpage::covr_summary(failed = failed)%>% 69 | knitr::kable(digits = 2, 70 | col.names = c('Object','Coverage (%)'),align = c('l','c')) 71 | 72 | ``` 73 | 74 |
    75 | 76 | ## Unit Tests 77 | 78 | Unit Test summary is created using the [testthat](https://github.com/r-lib/testthat) package. 79 | 80 | ```{r,echo=FALSE,warning=FALSE,message=FALSE,eval=!skip} 81 | cat('All tests were skipped') 82 | ``` 83 | 84 | ```{r,echo=FALSE,warning=FALSE,message=FALSE,eval=skip} 85 | 86 | test_x_short%>% 87 | knitr::kable() 88 | 89 | ``` 90 | 91 |
    92 | Show Detailed Test Results 93 | 94 | ```{r,echo=FALSE,warning=FALSE,message=FALSE,eval=!skip} 95 | cat('All tests were skipped') 96 | ``` 97 | 98 | ```{r,echo=FALSE,warning=FALSE,message=FALSE,eval=skip} 99 | 100 | test_x_long%>% 101 | knitr::kable() 102 | 103 | ``` 104 | 105 | ```{r,echo=FALSE} 106 | if(names(test_x_long)[1]=='icon') 107 | knitr::kable(t(c('Failed' = covrpage:::emos[['FAILED']],'Warning' = covrpage:::emos[['WARNING']], 'Skipped' = covrpage:::emos[['SKIPPED']]))) 108 | ``` 109 | 110 |
    111 | 112 |
    113 | Session Info 114 | 115 | ```{r,echo=FALSE,warning=FALSE,message=FALSE} 116 | 117 | x <- covrpage:::sinfo() 118 | 119 | x$info%>% 120 | knitr::kable() 121 | 122 | x$pkgs%>% 123 | knitr::kable() 124 | 125 | ``` 126 | 127 |
    128 | 129 | `r sprintf('', test_to_badge(test_x_short))` 130 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(importAs) 3 | 4 | test_check("importAs") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-debug.R: -------------------------------------------------------------------------------- 1 | context("debug") 2 | 3 | options(importAs.debug = TRUE) 4 | importAs(stats, s) 5 | stats %importAs% s2 6 | 7 | test_that("messaging", { 8 | expect_message(s::median(c(2, 3, 4, 5)), , "Namespace 'stats' can be referenced as 's'") 9 | expect_message(s2::median(c(2, 3, 4, 5)), , "Namespace 'stats' can be referenced as 's2'") 10 | }) 11 | -------------------------------------------------------------------------------- /tests/testthat/test-functional.R: -------------------------------------------------------------------------------- 1 | context("functional form usage") 2 | 3 | options(importAs.debug = FALSE) 4 | 5 | test_that("import -- functional", { 6 | expect_message(importAs(stats, s), "Namespace 'stats' can be referenced as 's'") 7 | }) 8 | 9 | test_that("structural components -- functional", { 10 | expect_equal(c(s), "stats") 11 | expect_equal(class(s), c("importedNamespace", "character")) 12 | expect_equal(attr(s, "symbol"), "s") 13 | }) 14 | 15 | test_that("messaging -- functional", { 16 | expect_message(print(s), "Namespace 'stats' can be referenced as 's'") 17 | # expect_equal(c(.rs.describeObject(objName = "s", env = .GlobalEnv)$value), "Namespace shorthand for stats") 18 | }) 19 | 20 | test_that("retrieval -- functional", { 21 | expect_equal(stats::median(c(2, 3, 4, 5)), s::median(c(2, 3, 4, 5))) 22 | expect_equal("stats"::median(c(2, 3, 4, 5)), s::median(c(2, 3, 4, 5))) 23 | }) 24 | -------------------------------------------------------------------------------- /tests/testthat/test-infix.R: -------------------------------------------------------------------------------- 1 | context("infix form usage") 2 | 3 | options(importAs.debug = FALSE) 4 | 5 | test_that("import -- infix", { 6 | expect_message(stats %importAs% s2, "Namespace 'stats' can be referenced as 's2'") 7 | }) 8 | 9 | test_that("structural components -- infix", { 10 | expect_equal(c(s2), "stats") 11 | expect_equal(class(s2), c("importedNamespace", "character")) 12 | expect_equal(attr(s2, "symbol"), "s2") 13 | }) 14 | 15 | test_that("messaging -- infix", { 16 | expect_message(print(s2), "Namespace 'stats' can be referenced as 's2'") 17 | # expect_equal(c(.rs.describeObject(objName = "s2", env = .GlobalEnv)$value), "Namespace shorthand for stats") 18 | }) 19 | 20 | test_that("retrieval -- infix", { 21 | expect_equal(stats::median(c(2, 3, 4, 5)), s2::median(c(2, 3, 4, 5))) 22 | expect_equal("stats"::median(c(2, 3, 4, 5)), s2::median(c(2, 3, 4, 5))) 23 | }) 24 | 25 | options(importAs.debug = FALSE) 26 | 27 | -------------------------------------------------------------------------------- /tests/testthat/test-package.R: -------------------------------------------------------------------------------- 1 | context("package") 2 | 3 | test_that("package option is set on package load", { 4 | expect_equal(getOption("importAs.debug"), FALSE) 5 | }) 6 | 7 | unloadNamespace("importAs") 8 | options(importAs.debug = TRUE) 9 | 10 | test_that("resetting package option after unload", { 11 | expect_equal(getOption("importAs.debug"), TRUE) 12 | }) 13 | 14 | loadNamespace("importAs") 15 | 16 | test_that("option remains set after reloading package", { 17 | expect_equal(getOption("importAs.debug"), TRUE) 18 | }) 19 | -------------------------------------------------------------------------------- /tests/testthat/test-shared.R: -------------------------------------------------------------------------------- 1 | context("shared") 2 | 3 | importAs(stats, s) 4 | stats %importAs% s2 5 | 6 | test_that("equivalence", { 7 | expect_equal(c(s), c(s2)) 8 | expect_equal(class(s), class(s2)) 9 | }) 10 | 11 | test_that("precedence", { 12 | expect_warning(importAs(base, stats), regexp = "base is itself a valid namespace and takes precedence.") 13 | expect_true(length(ls(pattern = "stats")) == 0L) 14 | }) 15 | 16 | -------------------------------------------------------------------------------- /tools/environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonocarroll/importAs/4b4394f020b847f60feef17da4a9593eaf7158c5/tools/environment.png -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/namespace-shorthands.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Namespace Shortcuts" 3 | author: "Jonathan Carroll" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Vignette Title} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | # importAs 20 | 21 | This package helps mimic the idiomatic python importing of packages such as 22 | 23 | ```{} 24 | import dplyr as d 25 | ``` 26 | 27 | In order to mimic this as closely as possible, the function `importAs` takes a 28 | package name and a (short?) name for that and creates a linkage 29 | 30 | ```{r} 31 | library(importAs) 32 | importAs(dplyr, d) 33 | d 34 | ``` 35 | 36 | or 37 | 38 | ```{r} 39 | importAs("dplyr", "d") 40 | d 41 | ``` 42 | 43 | This is merely a convenience, however. In reality a variable `d` is created 44 | with the value `"dplyr"` (and a class so we can dispatch on it). We could also 45 | do this manually for another package, creating a simple character object 46 | 47 | ```{r} 48 | s <- "stringr" 49 | s 50 | ``` 51 | 52 | The `importAs` function is merely a signal to a reader that this magic is going to 53 | be performed. The class means it is clearer that the shorthand is being used. 54 | 55 | A custom description is provided within the RStudio Environment pane which 56 | identifies each shorthand and the namespace to which it refers. 57 | 58 | ![](../tools/environment.png) 59 | 60 | As a further convenience, this [can be specified using an infix operator](https://github.com/jonocarroll/importAs/issues/1) (h/t @sa-lee) 61 | 62 | ```{r} 63 | dplyr %importAs% d 64 | d 65 | ``` 66 | 67 | At this point nothing magical has happened. The magic comes from overwriting the `::` 68 | operator. To -- at least, my -- surprise, `::` can happily take a character argument 69 | for the left-hand side, so 70 | 71 | ```{r} 72 | ## equivalent to "dplyr"::filter 73 | base::`::`("dplyr", filter) 74 | ``` 75 | 76 | works. The magic part is rewriting this function to look deeper if provided with a 77 | symbol which already resolves to a character string representing an installed 78 | package. The result is that we can shorthand the namespace referencing 79 | 80 | ```{r} 81 | d::filter(mtcars, cyl == 4, am == 1) 82 | s::str_extract("a1b2c3", "[a-z]2") 83 | ``` 84 | 85 | without interfering with any existing functionality 86 | 87 | ```{r} 88 | dplyr::filter(mtcars, cyl == 4, am == 1) 89 | stringr::str_extract("a1b2c3", "[a-z]2") 90 | ``` 91 | 92 | ## Collisions 93 | 94 | If the symbol you are trying to use as a shorthand _already_ exists as an available 95 | namespace, then that will take precedence. This prevents accidentally overwriting 96 | a namespace reference 97 | 98 | ```{r, error = TRUE, warning = TRUE} 99 | importAs(stringr, dplyr) 100 | dplyr::str_extract 101 | ``` 102 | 103 | and the existing namespace will still be found 104 | 105 | ```{r} 106 | dplyr::select 107 | ``` 108 | 109 | ## Debugging 110 | 111 | If you want to be clear about where your shorthands point to, you can set the 112 | debug option 113 | 114 | ```{r} 115 | options(importAs.debug = TRUE) 116 | ``` 117 | 118 | which will turn on messaging whenever a shorthand is accessed. For example, using 119 | `dplyr` normally does not 120 | 121 | ```{r} 122 | dplyr::filter(mtcars, cyl == 4 & am == 1) 123 | ``` 124 | 125 | but using the shorthand, we are reminded as to where that refers 126 | 127 | ```{r} 128 | d::filter(mtcars, cyl == 4 & am == 1) 129 | ``` 130 | 131 | ```{r, include = FALSE} 132 | options(importAs.debug = FALSE) 133 | ``` 134 | 135 | ## Installation 136 | 137 | You can install the development version of `importAs` with 138 | 139 | ```{r, eval = FALSE} 140 | ## install.packages("devtools") 141 | devtools::install_github("jonocarroll/importAs") 142 | ``` 143 | --------------------------------------------------------------------------------