├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── NAMESPACE ├── NEWS ├── R ├── before.R ├── copy_path.R ├── expand_path.R ├── file_ext.R ├── file_path.R ├── front.R ├── indent_path.R ├── index.R ├── is.global.R ├── manipulate_class.R ├── normalize.R ├── open_path.R ├── parse_path.R ├── pathr-package.R ├── swap.R ├── tree.R ├── utils.R └── win_fix.R ├── README.Rmd ├── README.md ├── data └── files.rda ├── inst ├── CITATION ├── build.R ├── extra_statdoc │ └── readme.R └── staticdocs │ └── index.R ├── man ├── before.Rd ├── copy_path.Rd ├── expand_path.Rd ├── file_ext.Rd ├── file_path.Rd ├── files.Rd ├── front.Rd ├── indent_path.Rd ├── index.Rd ├── is.global.Rd ├── normalize.Rd ├── open_path.Rd ├── parse_path.Rd ├── pathr.Rd ├── print.indent_path.Rd ├── print.manipulate.Rd ├── print.parse_path.Rd ├── print.tree.Rd ├── reexports.Rd ├── swap.Rd ├── tree.Rd └── win_fix.Rd ├── tests ├── testthat.R └── testthat │ ├── test-before.R │ ├── test-class_manipulate.R │ ├── test-copy_path.R │ ├── test-file_path.R │ ├── test-front.R │ ├── test-indent_path.R │ ├── test-index.R │ ├── test-is.global.R │ ├── test-normalize.R │ ├── test-parse_path.R │ ├── test-swap.R │ └── test-win_fix.R └── tools └── pathr_logo ├── r_pathr.png ├── r_pathr.pptx ├── r_pathra.png └── resize_icon.txt /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.gitignore 4 | NEWS.md 5 | FAQ.md 6 | NEWS.html 7 | FAQ.html 8 | ^\.travis\.yml$ 9 | travis-tool.sh 10 | inst/web 11 | contributors.geojson 12 | inst/build.R 13 | ^.*\.Rprofile$ 14 | README.Rmd 15 | README.R 16 | travis.yml 17 | tools/pathr_logo/r_pathra.png 18 | tools/pathr_logo/r_pathr.pptx 19 | tools/pathr_logo/resize_icon.txt 20 | Thumbs.db 21 | inst/staticdocs 22 | inst/extra_statdoc 23 | inst/maintenance.R 24 | inst/build.R 25 | pathr.R 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | 4 | # Example code in package build process 5 | *-Ex.R 6 | 7 | .Rprofile 8 | .Rproj.user 9 | pathr.Rproj 10 | inst/maintenance.R 11 | Thumbs.db 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | 3 | sudo: false 4 | 5 | # Install xclip 6 | addons: 7 | apt: 8 | packages: 9 | - xclip 10 | 11 | # Ensure xclip can still run headlessly 12 | before_script: 13 | - sh -e /etc/init.d/xvfb start 14 | - sleep 3 15 | 16 | r_github_packages: 17 | - jimhester/covr 18 | 19 | notifications: 20 | email: 21 | on_success: change 22 | on_failure: change 23 | 24 | after_success: 25 | - Rscript -e 'covr::coveralls()' 26 | 27 | r_build_args: "--resave-data=best" 28 | r_check_args: "--as-cran" 29 | 30 | env: 31 | global: 32 | - DISPLAY=:99.0 33 | - BOOTSTRAP_LATEX=1 34 | 35 | 36 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: pathr 2 | Title: Easy Manipulation and Piping of File Paths 3 | Version: 0.0.1 4 | Authors@R: c(person("Tyler", "Rinker", email = "tyler.rinker@gmail.com", role = c("aut", 5 | "cre"))) 6 | Maintainer: Tyler Rinker 7 | Description: Tools to extract and reconfigure elements of file paths. 8 | Depends: R (>= 3.2.2) 9 | Imports: clipr, data.tree, magrittr, methods, tools, utils 10 | Suggests: testthat 11 | SystemRequirements: xclip (http://sourceforge.net/projects/xclip/) or xsel 12 | (http://www.vergenet.net/~conrad/software/xsel/) for accessing the X11 clipboard 13 | Date: 2017-04-14 14 | URL: https://github.com/trinker/pathr 15 | BugReports: http://github.com/trinker/pathr/issues 16 | License: GPL-2 17 | LazyData: TRUE 18 | Roxygen: list(wrap = FALSE) 19 | RoxygenNote: 6.0.1 20 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,indent_path) 4 | S3method(print,manipulate) 5 | S3method(print,parse_path) 6 | S3method(print,tree) 7 | export("%>%") 8 | export(after) 9 | export(back) 10 | export(before) 11 | export(copy_path) 12 | export(expand_path) 13 | export(file_ext) 14 | export(file_path) 15 | export(front) 16 | export(indent_path) 17 | export(index) 18 | export(is.global) 19 | export(no_file_ext) 20 | export(normalize) 21 | export(open_path) 22 | export(parse_path) 23 | export(swap) 24 | export(swap_index) 25 | export(swap_regex) 26 | export(tree) 27 | export(win_fix) 28 | importFrom(magrittr,"%>%") 29 | importFrom(tools,file_ext) 30 | importFrom(tools,file_path_sans_ext) 31 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | NEWS 2 | ==== 3 | 4 | Versioning 5 | ---------- 6 | 7 | Releases will be numbered with the following semantic versioning format: 8 | 9 | .. 10 | 11 | And constructed with the following guidelines: 12 | 13 | * Breaking backward compatibility bumps the major (and resets the minor 14 | and patch) 15 | * New additions without breaking backward compatibility bumps the minor 16 | (and resets the patch) 17 | * Bug fixes and misc changes bumps the patch 18 | 19 | 20 | pathr 0.0.1 21 | ---------------------------------------------------------------- 22 | 23 | This package is... 24 | -------------------------------------------------------------------------------- /R/before.R: -------------------------------------------------------------------------------- 1 | #' Extract the Elements of a Path Before/After a Regex Occurrence 2 | #' 3 | #' Extract the elements of a path before/after a regex occurrence. 4 | #' Stands in contrast to \code{front},\code{back}, and index in that with the 5 | #' later three are element number/index focused whereas 6 | #' \code{before}/\code{after} are content focused. 7 | #' 8 | #' @param x A \code{parse_path} object. 9 | #' @param pattern A character string containing a regular expression (or 10 | #' character string for \code{fixed = TRUE}) to be matched in the given character 11 | #' vector. Note that under the hood \code{\link[base]{grep}} is used to locate 12 | #' the indices of path elements that match the regex condition. Only the first 13 | #' match will be used. The argument \code{perl = TRUE} is hard coded. 14 | #' @param include logical. If \code{TRUE} the element with the regex match will 15 | #' be included in the reconstructed sub-path. 16 | #' @param collapse logical. If \code{TRUE} the path elements will be collapsed 17 | #' with the \code{"/"} separator. 18 | #' @param \ldots ignored. 19 | #' @return Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 20 | #' \code{character} path elements) of sub-paths. 21 | #' @export 22 | #' @rdname before 23 | #' @family sub-path manipulation functions 24 | #' @examples 25 | #' (parsed <- list(c("a", "really", "boring", "path", "for", "R"))) 26 | #' before(parsed, "^bor") 27 | #' before(parsed, "^bor", include = TRUE) 28 | #' 29 | #' after(parsed, "^bor") 30 | #' after(parsed, "^bor", include = TRUE) 31 | #' 32 | #' library(magrittr) 33 | #' files %>% 34 | #' parse_path() %>% 35 | #' after("^qdap$") 36 | #' 37 | #' files %>% 38 | #' parse_path() %>% 39 | #' after("^qdap$", include = TRUE) 40 | #' 41 | #' files %>% 42 | #' parse_path() %>% 43 | #' before("\\.R$") 44 | before <- function(x, pattern, include = FALSE, collapse = TRUE, ...){ 45 | x <- manipulate_parsed(x) 46 | y <- lapply(x, function(z) { 47 | ind <- grep(pattern, z, perl=TRUE, ...)[1] 48 | if (!include) ind <- ind - 1 49 | if (is.na(ind) || ind < 1 || length(ind) == 0) return(NA) 50 | utils::head(z, ind) 51 | }) 52 | class_manipulate(y, collapse) 53 | } 54 | 55 | #' @export 56 | #' @rdname before 57 | after <- function(x, pattern, include = FALSE, collapse = TRUE, ...){ 58 | x <- manipulate_parsed(x) 59 | y <- lapply(x, function(z) { 60 | ind <- length(z) - grep(pattern, z, perl=TRUE, ...)[1] 61 | if (include) ind <- ind + 1 62 | if (is.na(ind) || ind > length(z) || length(ind) == 0) return(NA) 63 | utils::tail(z, ind) 64 | }) 65 | class_manipulate(y, collapse) 66 | } 67 | 68 | -------------------------------------------------------------------------------- /R/copy_path.R: -------------------------------------------------------------------------------- 1 | #' Pipeable Clipboard Copying 2 | #' 3 | #' This convenience function wraps \code{\link[clipr]{write_clip}} to copy the 4 | #' previous output in the chain to the clipboard. 5 | #' 6 | #' @param x An object to be written to the system clipboard. 7 | #' @param \ldots Other arguments passed to \code{\link[clipr]{write_clip}}. 8 | #' @return Returns \code{x} but attempts to copy content to the clipboard. 9 | #' @export 10 | #' @examples 11 | #' \dontrun{ 12 | #' library(magrittr) 13 | #' files %>% 14 | #' parse_path() %>% 15 | #' swap_regex("^(P|R)", "oops") %>% 16 | #' copy_path() 17 | #' } 18 | copy_path <- function(x, ...){ 19 | clipr::write_clip(x, ...) 20 | x 21 | } 22 | -------------------------------------------------------------------------------- /R/expand_path.R: -------------------------------------------------------------------------------- 1 | #' Expand Tilde Path 2 | #' 3 | #' A wrapper for \code{\link[base]{path.expand}} that expands a tilde prefixed 4 | #' path, replacing the leading tilde by the user's home directory (if defined on 5 | #' that platform). 6 | #' 7 | #' @param x A tilde prefixed path. 8 | #' @return Returns a vector of expanded paths. 9 | #' @export 10 | #' @seealso \code{\link[base]{file.path}} 11 | #' @examples 12 | #' library(magrittr) 13 | #' file_path("~/mydir", paste0("file", 1:2, ".pdf")) %>% 14 | #' expand_path() 15 | expand_path <- function(x){ 16 | class_manipulate(manipulate_parsed(parse_path(path.expand(x))), TRUE) 17 | } 18 | -------------------------------------------------------------------------------- /R/file_ext.R: -------------------------------------------------------------------------------- 1 | #' Reimport/Renaming of tools Package's File Extension Functions 2 | #' 3 | #' The \pkg{tools} package has \code{\link[tools]{file_ext}} related functions 4 | #' but the package has to be explicitly loaded (though comes standard with R) and 5 | #' the \code{\link[tools]{file_path_sans_ext}} is longer to type. The functions 6 | #' have been reimported and renamed to aid in their availablity with other path 7 | #' parsing tools to make their integration seamless (particularly in a pipeable 8 | #' form). 9 | #' 10 | #' @param x A character vector giving file paths. 11 | #' @param compression logical. Should compression extension \file{.gz}, 12 | #' \file{.bz2} or \file{.xz} be removed first? 13 | 14 | #' @return Returns a character string with just the file extension (\code{file_ext}) 15 | #' or the path without the file extension (\code{no_file_ext}). 16 | #' @rdname file_ext 17 | #' @export 18 | #' @importFrom tools file_ext file_path_sans_ext 19 | #' @examples 20 | #' \dontrun{ 21 | #' library(magrittr) 22 | #' (r_files <- dir(file.path(R.home(), "doc/manual"), full.names = TRUE)) 23 | #' 24 | #' file_ext(r_files) 25 | #' no_file_ext(r_files) 26 | #' 27 | #' r_files %>% 28 | #' parse_path() %>% 29 | #' back() %>% 30 | #' no_file_ext() 31 | #' } 32 | file_ext <- tools::file_ext 33 | 34 | 35 | #' @rdname file_ext 36 | #' @export 37 | no_file_ext <- tools::file_path_sans_ext 38 | -------------------------------------------------------------------------------- /R/file_path.R: -------------------------------------------------------------------------------- 1 | #' Construct Path to File 2 | #' 3 | #' A wrapper for \code{\link[base]{file.path}} that normalizes the path separator 4 | #' between elements. 5 | #' 6 | #' @param \ldots Atomic vectors of elements to construct a path from. 7 | #' @return Returns a vector of paths. 8 | #' @export 9 | #' @seealso \code{\link[base]{file.path}} 10 | #' @examples 11 | #' file_path("mydir", paste0("file", 1:2, ".pdf")) 12 | file_path <- function(...) { 13 | out <- file.path(..., fsep = .Platform[["file.sep"]]) 14 | class_manipulate(manipulate_parsed(parse_path(out)), TRUE) 15 | } 16 | -------------------------------------------------------------------------------- /R/front.R: -------------------------------------------------------------------------------- 1 | #' Extract the First/Last N Elements of a Path 2 | #' 3 | #' \code{front} - Extract the first n elements of a path. Similar to 4 | #' \code{\link[utils]{head}} (uses \code{\link[utils]{head}} under the hood). 5 | #' Compare the defualt settings to \code{\link[base]{basename}} and 6 | #' \code{\link[base]{dirname}}. 7 | #' 8 | #' @param x A \code{parse_path} object. 9 | #' @param n A single integer. If positive, size for the resulting object: number 10 | #' of elements for a vector. If negative, all but the \code{n} last/first number 11 | #' of elements of \code{x}. 12 | #' @param collapse logical. If \code{TRUE} the path elements will be collapsed 13 | #' with the \code{"/"} separator. 14 | #' @param \ldots ignored. 15 | #' @return Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 16 | #' \code{character} path elements) of sub-paths. 17 | #' @export 18 | #' @seealso \code{\link[base]{basename}}, 19 | #' \code{\link[base]{dirname}} 20 | #' @rdname front 21 | #' @family sub-path manipulation functions 22 | #' @examples 23 | #' front(list(1:8), 3) 24 | #' front(list(1:8), -3) 25 | #' 26 | #' back(list(1:8), 3) 27 | #' back(list(1:8), -3) 28 | #' 29 | #' library(magrittr) 30 | #' files %>% 31 | #' parse_path() %>% 32 | #' front() 33 | #' 34 | #' files %>% 35 | #' parse_path() %>% 36 | #' front(3) 37 | #' 38 | #' files %>% 39 | #' parse_path() %>% 40 | #' back() 41 | #' 42 | #' files %>% 43 | #' parse_path() %>% 44 | #' back(3) 45 | #' 46 | #' ## Compare to basename/dirname 47 | #' (fls <- file.path("","p1","p2","p3", c("file.pdf", "file.txt", "file.Rmd"))) 48 | #' 49 | #' basename(fls) 50 | #' fls %>% 51 | #' parse_path() %>% 52 | #' back() 53 | #' 54 | #' dirname(fls) 55 | #' fls %>% 56 | #' parse_path() %>% 57 | #' front() 58 | front <- function(x, n=-1, collapse = TRUE, ...){ 59 | x <- manipulate_parsed(x) 60 | y <- lapply(x, utils::head, n=n) 61 | class_manipulate(y, collapse) 62 | } 63 | 64 | 65 | #' Extract the Beginning/Ending Directories/Files of a Path 66 | #' 67 | #' \code{back} - Extract the first n elements of a path. Similar to 68 | #' \code{\link[utils]{tail}} (uses \code{\link[utils]{tail}} under the hood). 69 | #' 70 | #' @export 71 | #' @rdname front 72 | back <- function(x, n=1, collapse = TRUE, ...){ 73 | x <- manipulate_parsed(x) 74 | y <- lapply(x, utils::tail, n=n) 75 | class_manipulate(y, collapse) 76 | } 77 | 78 | -------------------------------------------------------------------------------- /R/indent_path.R: -------------------------------------------------------------------------------- 1 | #' Separate and Indent Path Elements 2 | #' 3 | #' Separate a path into hierarchical drectories and files for indented reading. 4 | #' 5 | #' @param path A path to the file/directory. If \code{NULL} \code{indent_path} 6 | #' attempts to use \code{\link[clipr]{read_clip}} to read and fix Windows paths. 7 | #' @param copy2clip logical. If \code{TRUE} attempts to copy to the clipboard 8 | #' using \code{\link[clipr]{write_clip}}. Default copies to the clipboard if 9 | #' used interactively. 10 | #' @param symbol The prefix symbol to use before the path element. 11 | #' @export 12 | #' @examples 13 | #' indent_path("C:/Users/Tyler/Desktop/guy") 14 | #' indent_path("C:/Users/Tyler/Desktop/guy", symbol="--") 15 | #' indent_path("C:/Users/Tyler/Desktop/guy", symbol=".") 16 | #' indent_path("C:/Users/Tyler/Desktop/guy", symbol="") 17 | indent_path <- function(path = NULL, copy2clip = is.global(2), symbol = "->"){ 18 | if (is.null(path)) path <- indent_path() 19 | m <- parse_path(path)[[1]] 20 | o <- paste0(lapply(2*0:c(length(m)-1), function(i) { 21 | paste(rep(" ", i), collapse="") 22 | }), sprintf("%s ", symbol), m) 23 | if (copy2clip) clipr::write_clip(o) 24 | out <- paste(o, collapse="\n") 25 | class(out) <- c("indent_path", class(out)) 26 | out 27 | } 28 | 29 | 30 | 31 | #' Prints an indent_path object 32 | #' 33 | #' Prints an indent_path object. 34 | #' 35 | #' @param x An \code{indent_path} object. 36 | #' @param \ldots Other arguments passed to \code{\link[base]{cat}}. 37 | #' @export 38 | #' @method print indent_path 39 | print.indent_path <- function(x, ...){ 40 | cat(x, "\n", ...) 41 | } 42 | -------------------------------------------------------------------------------- /R/index.R: -------------------------------------------------------------------------------- 1 | #' Extract an Index of Elements of a Path 2 | #' 3 | #' Extract the indices of a path. Stands in contrast to \code{front}/\code{back} 4 | #' in that with the later two the user wants the ends of the path elements (front 5 | #' or bacK) whereas with \code{index} the user wants the middle elements of a path. 6 | #' 7 | #' @param x A \code{parse_path} object. 8 | #' @param inds A vector of indices to select from. 9 | #' @param collapse logical. If \code{TRUE} the path elements will be collapsed 10 | #' with the \code{"/"} separator. 11 | #' @param \ldots ignored. 12 | #' @return Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 13 | #' \code{character} path elements) of sub-paths. 14 | #' @export 15 | #' @family sub-path manipulation functions 16 | #' @examples 17 | #' index(list(1:8), 3) 18 | #' index(list(1:8), 4:6) 19 | #' index(list(1:8), c(1, 3)) 20 | #' 21 | #' library(magrittr) 22 | #' files %>% 23 | #' parse_path() %>% 24 | #' index(c(2, 4:5)) 25 | #' 26 | #' files %>% 27 | #' parse_path() %>% 28 | #' index(3) 29 | index <- function(x, inds, collapse = TRUE, ...){ 30 | x <- manipulate_parsed(x) 31 | y <- lapply(x, function(z) z[inds]) 32 | class_manipulate(y, collapse) 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /R/is.global.R: -------------------------------------------------------------------------------- 1 | #' Test If Environment is Global 2 | #' 3 | #' A logical test to determine if the current environment is the global 4 | #' environment. 5 | #' 6 | #' @param n The number of generations to go back. If used as a function 7 | #' argument n should be set to 2. 8 | #' @return A logical response. 9 | #' @references \url{http://stackoverflow.com/questions/18637656/detect-if-environment-is-global-enviroment} 10 | #' @export 11 | #' @author Simon O'Hanlon and Tyler Rinker 12 | #' @seealso \code{\link[base]{globalenv}}, 13 | #' \code{\link[base]{parent.frame}} 14 | #' @examples 15 | #' is.global() 16 | #' lapply(1:3, function(i) is.global()) 17 | #' FUN <- function() is.global(); FUN() 18 | #' 19 | #' FUN2 <- function(x = is.global(2)) x 20 | #' FUN2() 21 | #' FUN3 <- function() FUN2(); FUN3() 22 | is.global <- function(n = 1) { 23 | identical(parent.frame(n = n) , globalenv()) 24 | } 25 | -------------------------------------------------------------------------------- /R/manipulate_class.R: -------------------------------------------------------------------------------- 1 | class_manipulate <-function(x, normalize){ 2 | y <- x 3 | if (isTRUE(normalize)) y <- normalize(y) 4 | class(y) <- unique(c("manipulate", class(y))) 5 | attributes(y)[["parsed"]] <- x 6 | y 7 | } 8 | 9 | manipulate_parsed <- function(x){ 10 | if (!methods::is(x, "manipulate")) return(x) 11 | attributes(x)[["parsed"]] 12 | } 13 | 14 | #' Prints a manipulate Object 15 | #' 16 | #' Prints a manipulate object 17 | #' 18 | #' @param x A manipulate object 19 | #' @param \ldots ignored. 20 | #' @method print manipulate 21 | #' @export 22 | print.manipulate <- function(x, ...){ 23 | class(x) <- class(x)[!class(x) %in% "manipulate"] 24 | attributes(x)[["parsed"]] <- NULL 25 | print(x) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /R/normalize.R: -------------------------------------------------------------------------------- 1 | #' Ensure Number and Direction of Slash Separators Are Consistent 2 | #' 3 | #' Replace path separators with a single foward slash. 4 | #' 5 | #' @param x A \code{parse_path} object. 6 | #' @return Returns an atomic vector of normalized paths. 7 | #' @export 8 | #' @examples 9 | #' library(magrittr) 10 | #' c("C:\\Users\\Tyler\\AppData\\Local\\Temp\\Rtmp2Ll9d9", "C:/R/R-3.2.2") %>% 11 | #' parse_path() %>% 12 | #' normalize() 13 | normalize <- function (x) { 14 | unlist(lapply(x, function(x){ 15 | if (length(x) == 1 && is.na(x)) return(NA) 16 | paste(x, collapse = "/") 17 | })) 18 | } 19 | 20 | -------------------------------------------------------------------------------- /R/open_path.R: -------------------------------------------------------------------------------- 1 | #' Open Path (Directories & Files) 2 | #' 3 | #' Use the operating system defaults to open directories and files. 4 | #' 5 | #' @param x A vector (typically of length one) of paths to directories of files. 6 | #' @references \url{http://stackoverflow.com/q/12135732/1000343} 7 | #' @note This function is operating system and setting dependant. Results may 8 | #' not be consistent across operating systems. Depending upon the default 9 | #' programs for file types the results may vary as well. Some files may not be 10 | #' able to be opened. 11 | #' @export 12 | #' @author Dason Kurkiewicz and Tyler Rinker . 13 | #' @examples 14 | #' \dontrun{ 15 | #' open_path() 16 | #' } 17 | open_path <- function(x = "."){ 18 | if (.Platform['OS.type'] == "windows"){ 19 | invisible(lapply(x, shell.exec)) 20 | } else { 21 | invisible(lapply(x, function(x) {system(paste(Sys.getenv("R_BROWSER"), x))})) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /R/parse_path.R: -------------------------------------------------------------------------------- 1 | #' Parse Path(s) 2 | #' 3 | #' Parses the individual directories, sub-directories, and files in a path into 4 | #' individual elements. 5 | #' 6 | #' @param x A vector of paths. 7 | #' @return Returns a list of vectors of parsed paths. 8 | #' @export 9 | #' @examples 10 | #' parse_path(files) 11 | parse_path <- function(x){ 12 | out <- strsplit(x, "(\\\\|/)+") 13 | class(out) <- c("parse_path") 14 | out 15 | } 16 | 17 | #' Prints a parse_path Object 18 | #' 19 | #' Prints a parse_path object 20 | #' 21 | #' @param x A parse_path object 22 | #' @param \ldots ignored. 23 | #' @method print parse_path 24 | #' @export 25 | print.parse_path <- function(x, ...){ 26 | class(x) <- 'list' 27 | print(x) 28 | } 29 | -------------------------------------------------------------------------------- /R/pathr-package.R: -------------------------------------------------------------------------------- 1 | #' Easy Manipulation and Piping of File Paths 2 | #' 3 | #' Tools to extract and reconfigure elements of file paths. 4 | #' @docType package 5 | #' @name pathr 6 | #' @aliases pathr package-pathr 7 | NULL 8 | 9 | 10 | 11 | #' A Vector of File Paths 12 | #' 13 | #' A dataset containing a character vector of file paths. 14 | #' 15 | #' @docType data 16 | #' @keywords datasets 17 | #' @name files 18 | #' @usage data(files) 19 | #' @format A character vector with 203 elements 20 | NULL 21 | -------------------------------------------------------------------------------- /R/swap.R: -------------------------------------------------------------------------------- 1 | #' Replace Elements of a Path 2 | #' 3 | #' Replace the elements of a path. Note either a index (use \code{inds}) or regex 4 | #' (use \code{pattern}) based approach is used to identify the indices to replace. 5 | #' The more specific \code{swap_index} or \code{swap_regex} can be used to be 6 | #' more targetted, transparent, pipeable, and efficient. 7 | #' 8 | #' @param x A \code{parse_path} object. 9 | #' @param inds Indices to replace. 10 | #' @param replacement A value to replace the indentified indices with. 11 | #' @param pattern A character string containing a regular expression (or 12 | #' character string for \code{fixed = TRUE}) to be matched in the given character 13 | #' vector. Note that under the hood \code{\link[base]{grep}} is used to locate 14 | #' the indices of path elements that match the regex condition. Only the first 15 | #' match will be used. The argument \code{perl = TRUE} is hard coded. 16 | #' @param collapse logical. If \code{TRUE} the path elements will be collapsed 17 | #' with the \code{"/"} separator. 18 | #' @param \ldots ignored. 19 | #' @return Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 20 | #' \code{character} path elements) of swapped paths. 21 | #' @export 22 | #' @rdname swap 23 | #' @family sub-path manipulation functions 24 | #' @examples 25 | #' swap(list(1:8), inds = c(2, 4), "REPLACED VALUE") 26 | #' swap(list(1:8), pattern = "[238]", replacement = "REPLACED VALUE") 27 | #' 28 | #' library(magrittr) 29 | #' files %>% 30 | #' parse_path() %>% 31 | #' swap(1, "MyFile") 32 | #' 33 | #' files %>% 34 | #' parse_path() %>% 35 | #' swap_index(3, "textMining") 36 | #' 37 | #' files %>% 38 | #' parse_path() %>% 39 | #' swap_regex("^qdap$", "textMining") 40 | #' 41 | #' files %>% 42 | #' parse_path() %>% 43 | #' swap_regex("\\.R$", "function.R") 44 | #' 45 | #' files %>% 46 | #' parse_path() %>% 47 | #' swap_regex("^(P|R)", "oops") 48 | swap <- function(x, inds, replacement, pattern = NULL, collapse = TRUE, ...) { 49 | x <- manipulate_parsed(x) 50 | if (is.null(pattern)){ 51 | y <- lapply(x, function(z) { 52 | z[inds] <- replacement 53 | z 54 | }) 55 | } else { 56 | y <- lapply(x, function(z) { 57 | z[grepl(pattern, z, perl=TRUE, ...)] <- replacement 58 | z 59 | }) 60 | } 61 | class_manipulate(y, collapse) 62 | } 63 | 64 | #' @export 65 | #' @rdname swap 66 | swap_index <- function(x, inds, replacement, collapse = TRUE, ...) { 67 | x <- manipulate_parsed(x) 68 | y <- lapply(x, function(z) { 69 | z[inds] <- replacement 70 | z 71 | }) 72 | class_manipulate(y, collapse) 73 | } 74 | 75 | 76 | #' @export 77 | #' @rdname swap 78 | swap_regex <- function(x, pattern, replacement, collapse = TRUE, ...) { 79 | x <- manipulate_parsed(x) 80 | y <- lapply(x, function(z) { 81 | z[grepl(pattern, z, perl=TRUE, ...)] <- replacement 82 | z 83 | }) 84 | class_manipulate(y, collapse) 85 | } 86 | 87 | -------------------------------------------------------------------------------- /R/tree.R: -------------------------------------------------------------------------------- 1 | #' Generate a Directory Tree 2 | #' 3 | #' Given a directory, generate a directory tree diagram. 4 | #' 5 | #' @param path A path to the directory. 6 | #' @param include.files logical. If \code{TRUE} files and drectories will be 7 | #' included. 8 | #' @param all.files logical. If \code{FALSE}, only the names of visible files 9 | #' are returned. If \code{TRUE}, all file names will be returned. 10 | #' @param use.data.tree logical. If \code{TRUE} the \pkg{data.tree} package is 11 | #' used to make the tree, otherwise \code{system} is invoked with the extrenal 12 | #' \pkg{tree} program. The former produces a \code{"R6"}, \code{"Node"} object 13 | #' that can be manipulated accordingly. The latter will be faster in most cases. 14 | #' @param out An optional outfile (typically .txt) to print to. 15 | #' @param additional Additonal arguments passed to 16 | #' href{https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/tree.mspx?mfr=true}{\code{tree}} 17 | #' (Windows) or \href{http://www.computerhope.com/unix/tree.htm}{tree} (Unix). 18 | #' @param copy2clip logical. If \code{TRUE} attempts to copy to the clipboard 19 | #' via \code{\link[clipr]{write_clip}}. 20 | #' @export 21 | #' @note The \pkg{tree} program must be installed to use \code{use.data.tree = FALSE}. 22 | #' @examples 23 | #' tree(system.file("", package = "base"), use.data.tree = TRUE) 24 | #' \dontrun{ 25 | #' tree() 26 | #' tree(.libPaths()) 27 | #' } 28 | tree <- function(path = ".", include.files = TRUE, all.files = TRUE, 29 | use.data.tree = FALSE, out = NULL, additional = NULL, copy2clip = FALSE){ 30 | 31 | if (isTRUE(use.data.tree)){ 32 | dir_tree_dt(path = path, include.files = include.files, 33 | all.files = all.files, copy2clip = copy2clip) 34 | } else { 35 | dir_tree_sys(path = path, out = out, include.files = include.files, 36 | additional = additional, copy2clip = copy2clip) 37 | 38 | } 39 | 40 | } 41 | 42 | 43 | dir_tree_dt <- function(path = ".", include.files = TRUE, all.files = TRUE, 44 | copy2clip = FALSE){ 45 | 46 | if (isTRUE(include.files)){ 47 | fls <- dir(path, all.files = all.files, full.names = TRUE, recursive = TRUE) 48 | } else { 49 | fls <- list.files(path, all.files = all.files) 50 | } 51 | parsed <- parse_path(fls) 52 | contents <- back(parsed, -(-1 + length(unlist(parse_path(path))))) 53 | y <- attributes(back(contents, -1))[["parsed"]] 54 | z <- data.frame(matrix(NA, ncol = max(sapply(y, length)), nrow = length(y))) 55 | for (i in seq_along(y)){ 56 | z[i, 1:length(y[[i]])] <- y[[i]] 57 | } 58 | z[["pathString"]] <- contents 59 | 60 | out <- data.tree::as.Node(z) 61 | out2 <- utils::capture.output(out)[-1] 62 | out2 <- gsub("^\\d+\\s+", "", out2) 63 | out2[-1] <- paste0(" ", out2[-1]) 64 | #cat(paste(out2, collapse="\n"), "\n") 65 | if (copy2clip) clipr::write_clip(out2) 66 | out 67 | 68 | } 69 | 70 | 71 | dir_tree_sys <- function(path = ".", out = NULL, include.files = TRUE, 72 | additional = NULL, copy2clip = FALSE){ 73 | 74 | if (!file.exists(path)) stop("`path` does not exist") 75 | if (Sys.which("tree") == "" && .Platform$OS.type != "windows") { 76 | message( 77 | sprintf( 78 | "`tree` not found, try using `%s install tree`", 79 | ifelse(Sys.info()[['sysname']] == "Darwin", "brew", "sudo apt-get") 80 | ) 81 | ) 82 | } 83 | 84 | if (is.null(out)){ 85 | tmp <- tempdir() 86 | out <- file.path(tmp, paste0(gsub(":|\\s+", "_", Sys.time()), ".txt")) 87 | } 88 | 89 | if(.Platform$OS.type == "windows") { 90 | command <- shell 91 | fls <- ifelse(include.files, "/f", "") 92 | a <- "/a >" 93 | cmd <- paste("tree", shQuote(path), fls, a, additional, shQuote(out)) 94 | 95 | } else { 96 | command <- system 97 | fls <- ifelse(include.files, "-o", "") 98 | a <- "-a " 99 | cmd <- paste("tree", shQuote(path), a, fls, additional, shQuote(out)) 100 | 101 | } 102 | 103 | command(cmd) 104 | out <- readLines(out) 105 | 106 | if (copy2clip) clipr::write_clip(out) 107 | out <- paste(out, collapse="\n") 108 | class(out) <- c("tree", class(out)) 109 | out 110 | } 111 | 112 | 113 | #' Prints a tree object 114 | #' 115 | #' Prints a tree object. 116 | #' 117 | #' @param x A \code{tree} object. 118 | #' @param \ldots Other arguments passed to \code{\link[base]{cat}}. 119 | #' @export 120 | #' @method print tree 121 | print.tree <- function(x, ...){ 122 | cat(x, "\n", ...) 123 | } 124 | 125 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | #' @importFrom magrittr %>% 2 | #' @export 3 | magrittr::`%>%` 4 | -------------------------------------------------------------------------------- /R/win_fix.R: -------------------------------------------------------------------------------- 1 | #' Fix Single Windows Backslashes 2 | #' 3 | #' Fix single Windows based backslashes in paths with a single foward slash. By 4 | #' defaukt copying a path from a Windows machine has R unfriendly single 5 | #' backslashes. This function copies a single Windows path from the clipboard 6 | #' maes the necessary single foward slash correction. 7 | #' 8 | #' @param clip logical. If \code{TRUE} the path is copied from the clipboard 9 | #' via the \pkg{clipr} package. 10 | #' @param quote logical. If \code{TRUE} the returned path is wrapped with quotes. 11 | #' @param copy2clip logical. If \code{TRUE} the returned path is copied to the 12 | #' clipboard. 13 | #' @return Returns an R friendly path. 14 | #' @export 15 | #' @examples 16 | #' ## copy this line to clipboard... 17 | #' ## ~\Packages\qdap\R\cm_code.overlap.R 18 | #' ## Now run... 19 | #' ## win_fix() 20 | win_fix <- function (clip = TRUE, quote = TRUE, copy2clip = interactive()) { 21 | if (!clip) { 22 | message("Please enter the path:\n\n") 23 | path <- readline() 24 | } else { 25 | path <- clipr::read_clip() 26 | } 27 | z <- chartr("\\", "/", path) 28 | if (quote) { 29 | x <- paste0("\"", z, "\"") 30 | } else { 31 | x <- z 32 | } 33 | if (copy2clip) { 34 | clipr::write_clip(x) 35 | } 36 | return(z) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "pathr" 3 | date: "`r format(Sys.time(), '%d %B, %Y')`" 4 | output: 5 | md_document: 6 | toc: true 7 | --- 8 | 9 | ```{r, echo=FALSE} 10 | desc <- suppressWarnings(readLines("DESCRIPTION")) 11 | regex <- "(^Version:\\s+)(\\d+\\.\\d+\\.\\d+)" 12 | loc <- grep(regex, desc) 13 | ver <- gsub(regex, "\\2", desc[loc]) 14 | verbadge <- sprintf('Version

', ver, ver) 15 | ```` 16 | 17 | ```{r, echo=FALSE} 18 | library(knitr) 19 | knit_hooks$set(htmlcap = function(before, options, envir) { 20 | if(!before) { 21 | paste('

',options$htmlcap,"

",sep="") 22 | } 23 | }) 24 | library(pathr) 25 | knitr::opts_knit$set(self.contained = TRUE, cache = FALSE) 26 | knitr::opts_chunk$set(fig.path = "tools/figure/") 27 | curwd <- getwd() 28 | parsedwd <- parse_path(curwd) 29 | ``` 30 | 31 | [![Project Status: Active - The project has reached a stable, usable state and is being actively developed.](http://www.repostatus.org/badges/0.1.0/active.svg)](http://www.repostatus.org/#active) 32 | [![Build Status](https://travis-ci.org/trinker/pathr.svg?branch=master)](https://travis-ci.org/trinker/pathr) 33 | [![Coverage Status](https://coveralls.io/repos/trinker/pathr/badge.svg?branch=master)](https://coveralls.io/r/trinker/pathr?branch=master) 34 | `r verbadge` 35 | 36 | ![](tools/pathr_logo/r_pathr.png) 37 | 38 | **pathr** is a collection of tools to extract, examine, and reconfigure elements of file paths. The package is born out of a frustration with finding the right base **R** tools to grab certain parts of a path. Often these functions are located in packages that are base install but not loaded by default (e.g., `tools::file_ext`). Additionally, many names of path manipulation functions in base **R** are longer and thus often difficult to remember and require more time to type. Still, other path manipulation tasks had me building my own custom manipulation tools via `strsplit` and `file.path`. **pathr** is designed to be a consistent set of tools that allow the user to solve most path related needs simply by remembering 7 basic sets of parsing and manipulation tools (the first seven rows in the table of function usage found in the [Function Usage](#function-usage) section). The package is designed to be pipeable (easily used within a **magrittr**/**pipeR** pipeline) but is not required. 39 | 40 | # Functions 41 | 42 | Functions typically fall into the task category of (1) parsing, (2) manipulating, (3) examining, & (4) action. The main functions, task category, & descriptions are summarized in the table below: 43 | 44 | 45 | | Function | Task | Description | 46 | |---------------------------|------------|-----------------------------------------------------------| 47 | | `parse_path` | parsing | Parse path into elements (sub-directories & files) | 48 | | `front`/`back` | manipulate | Get first/last n elements of a path | 49 | | `index` | manipulate | Get indexed elements of a path | 50 | | `before`/`after` | manipulate | Get n elements before/after a regex occurrence | 51 | | `swap`/`swap_index`/`swap_regex` | manipulate | Replace elements of a path | 52 | | `file_path` | manipulate | Combine file paths | 53 | | `expand_path` | manipulate | Expand tilde prefixed file path | 54 | | `normalize` | manipulate | Make all path separators forward slashes | 55 | | `win_fix` | manipulate | Replace single backslash with a forward slash | 56 | | `file_ext`/`no_file_ext` | manipulate | Get/remove file extensions | 57 | | `tree` | examine | View path structure as an ASCII style tree (experimental) | 58 | | `indent_path` | examine | View path hierarchy as an indented list | 59 | | `copy_path` | action | Copy path(s) to clipboard | 60 | | `open_path` | action | Open path(s) (directories & file) | 61 | 62 | 63 | # Installation 64 | 65 | To download the development version of **pathr**: 66 | 67 | Download the [zip ball](https://github.com/trinker/pathr/zipball/master) or [tar ball](https://github.com/trinker/pathr/tarball/master), decompress and run `R CMD INSTALL` on it, or use the **pacman** package to install the development version: 68 | 69 | ```r 70 | if (!require("pacman")) install.packages("pacman") 71 | pacman::p_load_gh("trinker/pathr") 72 | ``` 73 | 74 | # Contact 75 | 76 | You are welcome to: 77 | * submit suggestions and bug-reports at: 78 | * send a pull request on: 79 | * compose a friendly e-mail to: 80 | 81 | # Demonstration 82 | 83 | ## Load the Packages/Data 84 | 85 | ```{r, message=FALSE} 86 | if (!require("pacman")) install.packages("pacman") 87 | 88 | pacman::p_load(pathr, magrittr) 89 | 90 | data(files) 91 | set.seed(11); (myfiles <- sample(files, 10)) 92 | ``` 93 | 94 | 95 | 96 | ## Parsing 97 | 98 | The `parse_path` function simply splits an atomic vector of paths into a list of paths split on the slash separator. For example, my current working directory, `r curwd`, becomes: 99 | 100 | ```{r} 101 | getwd() %>% 102 | parse_path() 103 | ``` 104 | 105 | While this isn't earth shattering it allows the **pathr** manipulation functions to extract, replace, and recombine parts of the *path* *elements* into a *sub-path*. Here I use *path* to mean the original path, `r curwd`. A path is simply a slash separated mapping of the location of a file or directory within a hierarchical order of sub-directories. These sub-directories are the *elements* of the path. The final output from one of the manipulation functions is a *sub-path* of the original at most the same number of elements as the original. 106 | 107 | In this example I parse a multi-path vector: 108 | 109 | ```{r} 110 | myfiles %>% 111 | parse_path() 112 | ``` 113 | 114 | ## Manipulating 115 | 116 | Once the path has been parsed the individual elements can be extracted and/or replaced to form sub-paths. In this section I break the manipulation functions into (1) extracting (2) replacing, (3) combining, and (4) expanding types. There are a few miscellaneous **pathr** functions that are not an extracting, replacing, combining, or expanding tool which will be discussed at the end of the Manipulating section. 117 | 118 | ### Extracting 119 | 120 | Extracting can replace path elements by their numeric index or by their content relative to a matched regular expression. There are three sets of extracting functions (1) `front`/`back`, (2) `index`, and (3) `before`/`after`. The first two rely on matching elements to their numeric position while the latter set uses extraction relative to a regular expression match. 121 | 122 | #### Front & Back 123 | 124 | The `front`/`back` set of functions works like `head`/`tail` (in fact these functions are used under the hood). The user can select the first `n` elements using `front` or the last `n` elements using `back`. These functions require that users want either the first or last element of the path in their sub-path. 125 | 126 | Here I replicate base **R**'s `dirname` & `basename` functions using the default settings of `front` & `back` as `dirname` is taking `head(x, -1)` elements (or all but the last element) and `basename` is taking `tail(x, 1)` (or the last element). 127 | 128 | ```{r} 129 | myfiles %>% 130 | parse_path() %>% 131 | front() 132 | 133 | myfiles %>% 134 | dirname() 135 | ``` 136 | 137 | ```{r} 138 | myfiles %>% 139 | parse_path() %>% 140 | back() 141 | 142 | myfiles %>% 143 | basename() 144 | ``` 145 | 146 | But the `front`/`back` set is more versatile still as demonstrated below: 147 | 148 | 149 | ```{r} 150 | myfiles %>% 151 | parse_path() %>% 152 | front(3) 153 | 154 | myfiles %>% 155 | parse_path() %>% 156 | back(3) 157 | ``` 158 | 159 | #### Indices 160 | 161 | The `index` function compliments the `front`/`back` set by allowing the user to select the middle elements of a path. Unlike `front`/`back`, the `index` function does not require elements to be sequential. The user will get a sub-path equal in length to the length of the `inds` argument. 162 | 163 | ```{r} 164 | myfiles %>% 165 | parse_path() %>% 166 | index(4) 167 | 168 | myfiles %>% 169 | parse_path() %>% 170 | index(2:4) 171 | 172 | myfiles %>% 173 | parse_path() %>% 174 | index(c(2, 4)) 175 | ``` 176 | 177 | #### Before & After Regex 178 | 179 | The `before`/`after` differ from the previous sets of manipulation functions in that it allows the user to select elements based on their content rather than numeric position. The user provides a regular expression to match against. All elements `before` or `after` this regex match will be selected for use in the sub-path. The user may include the regex matched element by setting `include = TRUE`. 180 | 181 | Here I extract all elements after the element containing the regex `"^qdap$"`. 182 | 183 | ```{r} 184 | myfiles %>% 185 | parse_path() %>% 186 | after("^qdap$") 187 | ``` 188 | 189 | The user can include the element that matched the regex as well using `include = TRUE`: 190 | 191 | ```{r} 192 | myfiles %>% 193 | parse_path() %>% 194 | after("^qdap$", include = TRUE) 195 | ``` 196 | 197 | 198 | Here I use `before` to extract all elements before the regex match to paths that contain an element with a file that ends in `.R`. If a path does not contain that element match `NA` is returned. 199 | 200 | ```{r} 201 | myfiles %>% 202 | parse_path() %>% 203 | before("\\.R$") 204 | ``` 205 | 206 | ### Replacing 207 | 208 | Often the user will want to replace elements of a path with another. The `swap` function allows the user to match with a numeric index or a regular expression to determine the element locations to be replaced. The `swap_index` & `swap_regex` functions are less flexible than the more inclusive function but are also more explicit, transparent and pipeable. Preference is typically given to the later `swap_xxx` functions in chained usage. 209 | 210 | 211 | #### `swap` 212 | 213 | In this scenario I replace the root tilde with `MyRoot`: 214 | 215 | ```{r} 216 | myfiles %>% 217 | parse_path() %>% 218 | swap(1, "MyRoot") 219 | ``` 220 | 221 | #### `swap_index` & `swap_regex` 222 | 223 | In the next use I replace `qdap` with `textMining` by referencing the third element: 224 | 225 | ```{r} 226 | myfiles %>% 227 | parse_path() %>% 228 | swap_index(3, "textMining") 229 | ``` 230 | 231 | When the element position is unknown `swap_regex` provides a means to replace elements: 232 | 233 | ```{r} 234 | myfiles %>% 235 | parse_path() %>% 236 | swap_regex("^qdap$", "textMining") 237 | 238 | myfiles %>% 239 | parse_path() %>% 240 | swap_regex("\\.R$", "function.R") 241 | ``` 242 | 243 | ### Combining 244 | 245 | While the above tools work to produce sub-paths with an equal or less length of elements `file_path` is a means to combine/construct file paths that may be greater in length than the original path/elements supplied. `file_path` is wrapper for `base::file.path` that uses the underscore naming convention and normalizes the separator to be a single forward slash. 246 | 247 | 248 | ```{r} 249 | file_path("root", "mydir", paste0("file", 1:2, ".pdf")) 250 | ``` 251 | 252 | This is especially useful when combined with extraction/replacement techniques to form new paths as shown below: 253 | 254 | ```{r} 255 | myfiles %>% 256 | parse_path() %>% 257 | after("R$", include = TRUE) %>% 258 | na.omit() %>% 259 | file_path("Root", "newPackage", .) 260 | ``` 261 | 262 | ### Expanding 263 | 264 | Like `file_path` above, `expand_path` produces a path that is longer than the input path. `expand_path` is wrapper for `base::path.expand` used to expand tilde prefixed paths by replacing the leading tilde with the user's home directory. 265 | 266 | 267 | ```{r} 268 | expand_path("~/mydir/subdir/myfile.pdf") 269 | ``` 270 | 271 | The user may have noticed that in the example [above](#extracting), demonstrating `front`'s ability to mimic `dirname`, is incomplete. That is the outputs from `front` and `dirname` are not identical. This is because `dirname`, by default, expands the tilde in the example `myfiles` whereas `front` does not. Simply adding `expand_path` on the end of the chain replicates `dirname` exactly. 272 | 273 | ```{r} 274 | myfiles %>% 275 | parse_path() %>% 276 | front() %>% 277 | expand_path() 278 | ``` 279 | 280 | ### Miscellaneous 281 | 282 | As noted above, **pathr** contains a few functions that are not an extracting, replacing, combining, or extracting tool. 283 | 284 | #### Normalizing 285 | 286 | `normalize` replaces all path slash separators with an **R** friendly forward slash. 287 | 288 | ```{r} 289 | c("C:\\Users\\Tyler\\AppData\\Local\\Temp\\Rtmp2Ll9d9", "C:/R/R-3.2.2") %>% 290 | parse_path() %>% 291 | normalize() 292 | ``` 293 | 294 | #### Windows Fix (single backslashes) 295 | 296 | `win_fix` reads an **R** unfriendly Windows path (single backslashes) and replaces with friendly forward slashes. This functionality can't be demonstrated within a knitr document because the single backslashes can't be parsed or copied to the clipboard from within R. 297 | 298 | If the user were to copy the following path, `~\Packages\qdap\R\cm_code.overlap.R`, to the clipboard and run `win_fix()` the result would be: `"~/Packages/qdap/R/cm_code.overlap.R"` 299 | 300 | 301 | ## Examination 302 | 303 | Functions of this class are designed to allow the user to examine structural aspects of a path and contents. 304 | 305 | ### Tree 306 | 307 | `tree` allows the user to see the hierarchical structure of a path's contents (all the sub-directories and files contained within a parent directory) as a tree. This function is (with default `use.data.tree = FALSE`) OS dependent, and requires that the tree program ([tree for Windows](https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/tree.mspx?mfr=true) or [tree for Unix](http://www.computerhope.com/unix/tree.htm)) be installed. 308 | 309 | On my Windows system this is the tree structure for the **pathr** package as installed in **R** library: 310 | 311 | ```{r} 312 | file_path(.libPaths(), "pathr") %>% 313 | tree() 314 | ``` 315 | 316 | Users concerned with OS dependence can use a **data.tree** implementation of `tree`. This version is slower but is uniform and requires no outside dependencies to be installed. Additionally, the output is a **data.tree** `"Node"` class and can be manipulated accordingly. 317 | 318 | 319 | ```{r} 320 | file_path(.libPaths(), "pathr") %>% 321 | tree(use.data.tree = TRUE) 322 | ``` 323 | 324 | ### Indented Elements 325 | 326 | `indent_path` on the other hand, works on individual paths (not contents) to visualize the hierarchical structure of a path's elements. 327 | 328 | ```{r} 329 | file_path(.libPaths(), "pathr/DESCRIPTION") %>% 330 | indent_path() 331 | ``` 332 | 333 | ## Action 334 | 335 | The last type of functions in **pathr** use the operating system to do some sort of action. 336 | 337 | ### Opening 338 | 339 | `open_path` uses the operating system defaults to open directories and files. This function is operating system and setting dependent. Results may not be consistent across operating systems. Depending upon the default programs for file types the results may vary as well. Some files may not be able to be opened. 340 | 341 | #### Opening Directories 342 | 343 | ```{r, eval=FALSE} 344 | open_path() 345 | 346 | file_path(.libPaths(), "pathr") %>% 347 | open_path() 348 | ``` 349 | 350 | #### Opening Files 351 | 352 | ```{r, eval=FALSE} 353 | file_path(R.home(), "doc/html/about.html") %>% 354 | open_path() 355 | ``` 356 | 357 | ### Copying 358 | 359 | `copy_path` uses the [**clipr**]() package's `write_clip` function to write the current vector, `x`, to the clipboard but still returns `x`. This makes the copying pipeable, allowing the contents to be copied yet be passed along in the chain. 360 | 361 | 362 | ```{r} 363 | pacman::p_load(clipr) 364 | 365 | R.home() %>% 366 | list.files(full.names = TRUE) %>% 367 | copy_path() %>% 368 | parse_path() %>% 369 | back(1) 370 | 371 | ## What was copied to the clipboard 372 | clipr::read_clip() 373 | ``` 374 | 375 | 376 | 377 | 378 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pathr [![Follow](https://img.shields.io/twitter/follow/tylerrinker.svg?style=social)](https://twitter.com/intent/follow?screen_name=tylerrinker) 2 | ============ 3 | 4 | 5 | [![Project Status: Active - The project has reached a stable, usable 6 | state and is being actively 7 | developed.](http://www.repostatus.org/badges/0.1.0/active.svg)](http://www.repostatus.org/#active) 8 | [![Build 9 | Status](https://travis-ci.org/trinker/pathr.svg?branch=master)](https://travis-ci.org/trinker/pathr) 10 | [![Coverage 11 | Status](https://coveralls.io/repos/trinker/pathr/badge.svg?branch=master)](https://coveralls.io/r/trinker/pathr?branch=master) 12 | Version 13 |

14 | 15 | ![](tools/pathr_logo/r_pathr.png) 16 | 17 | **pathr** is a collection of tools to extract, examine, and reconfigure 18 | elements of file paths. The package is born out of a frustration with 19 | finding the right base **R** tools to grab certain parts of a path. 20 | Often these functions are located in packages that are base install but 21 | not loaded by default (e.g., `tools::file_ext`). Additionally, many 22 | names of path manipulation functions in base **R** are longer and thus 23 | often difficult to remember and require more time to type. Still, other 24 | path manipulation tasks had me building my own custom manipulation tools 25 | via `strsplit` and `file.path`. **pathr** is designed to be a consistent 26 | set of tools that allow the user to solve most path related needs simply 27 | by remembering 7 basic sets of parsing and manipulation tools (the first 28 | seven rows in the table of function usage found in the [Function 29 | Usage](#function-usage) section). The package is designed to be pipeable 30 | (easily used within a **magrittr**/**pipeR** pipeline) but is not 31 | required. 32 | 33 | 34 | Table of Contents 35 | ============ 36 | 37 | - [Functions](#functions) 38 | - [Installation](#installation) 39 | - [Contact](#contact) 40 | - [Demonstration](#demonstration) 41 | - [Load the Packages/Data](#load-the-packagesdata) 42 | - [Parsing](#parsing) 43 | - [Manipulating](#manipulating) 44 | - [Extracting](#extracting) 45 | - [Replacing](#replacing) 46 | - [Combining](#combining) 47 | - [Expanding](#expanding) 48 | - [Miscellaneous](#miscellaneous) 49 | - [Examination](#examination) 50 | - [Tree](#tree) 51 | - [Indented Elements](#indented-elements) 52 | - [Action](#action) 53 | - [Opening](#opening) 54 | - [Copying](#copying) 55 | 56 | Functions 57 | ============ 58 | 59 | 60 | Functions typically fall into the task category of (1) parsing, (2) 61 | manipulating, (3) examining, & (4) action. The main functions, task 62 | category, & descriptions are summarized in the table below: 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 |
FunctionTaskDescription
parse_pathparsingParse path into elements (sub-directories & files)
front/backmanipulateGet first/last n elements of a path
indexmanipulateGet indexed elements of a path
before/aftermanipulateGet n elements before/after a regex occurrence
swap/swap_index/swap_regexmanipulateReplace elements of a path
file_pathmanipulateCombine file paths
expand_pathmanipulateExpand tilde prefixed file path
normalizemanipulateMake all path separators forward slashes
win_fixmanipulateReplace single backslash with a forward slash
file_ext/no_file_extmanipulateGet/remove file extensions
treeexamineView path structure as an ASCII style tree (experimental)
indent_pathexamineView path hierarchy as an indented list
copy_pathactionCopy path(s) to clipboard
open_pathactionOpen path(s) (directories & file)
145 | 146 | Installation 147 | ============ 148 | 149 | To download the development version of **pathr**: 150 | 151 | Download the [zip ball](https://github.com/trinker/pathr/zipball/master) 152 | or [tar ball](https://github.com/trinker/pathr/tarball/master), 153 | decompress and run `R CMD INSTALL` on it, or use the **pacman** package 154 | to install the development version: 155 | 156 | if (!require("pacman")) install.packages("pacman") 157 | pacman::p_load_gh("trinker/pathr") 158 | 159 | Contact 160 | ======= 161 | 162 | You are welcome to: 163 | - submit suggestions and bug-reports at: 164 | - send a pull request on: 165 | - compose a friendly e-mail to: 166 | 167 | Demonstration 168 | ============= 169 | 170 | Load the Packages/Data 171 | ---------------------- 172 | 173 | if (!require("pacman")) install.packages("pacman") 174 | 175 | pacman::p_load(pathr, magrittr) 176 | 177 | data(files) 178 | set.seed(11); (myfiles <- sample(files, 10)) 179 | 180 | ## [1] "~/Packages/qdap/R/cm_range2long.R" 181 | ## [2] "~/Packages/qdap/contributors.geojson" 182 | ## [3] "~/Packages/qdap/R/mcsv_r.R" 183 | ## [4] "~/Packages/qdap/DESCRIPTION" 184 | ## [5] "~/Packages/qdap/README.md" 185 | ## [6] "~/Packages/qdap/R/wfm.R" 186 | ## [7] "~/Packages/qdap/R/adjacency_matrix.R" 187 | ## [8] "~/Packages/qdap/R/xnoy.R" 188 | ## [9] "~/Packages/qdap/R/termco.R" 189 | ## [10] "~/Packages/qdap/R/bag_o_words.R" 190 | 191 | Parsing 192 | ------- 193 | 194 | The `parse_path` function simply splits an atomic vector of paths into a 195 | list of paths split on the slash separator. For example, my current 196 | working directory, C:/Users/Tyler/GitHub/pathr, becomes: 197 | 198 | getwd() %>% 199 | parse_path() 200 | 201 | ## [[1]] 202 | ## [1] "C:" "Users" "Tyler" "GitHub" "pathr" 203 | 204 | While this isn't earth shattering it allows the **pathr** manipulation 205 | functions to extract, replace, and recombine parts of the *path* 206 | *elements* into a *sub-path*. Here I use *path* to mean the original 207 | path, C:/Users/Tyler/GitHub/pathr. A path is simply a slash separated 208 | mapping of the location of a file or directory within a hierarchical 209 | order of sub-directories. These sub-directories are the *elements* of 210 | the path. The final output from one of the manipulation functions is a 211 | *sub-path* of the original at most the same number of elements as the 212 | original. 213 | 214 | In this example I parse a multi-path vector: 215 | 216 | myfiles %>% 217 | parse_path() 218 | 219 | ## [[1]] 220 | ## [1] "~" "Packages" "qdap" "R" 221 | ## [5] "cm_range2long.R" 222 | ## 223 | ## [[2]] 224 | ## [1] "~" "Packages" "qdap" 225 | ## [4] "contributors.geojson" 226 | ## 227 | ## [[3]] 228 | ## [1] "~" "Packages" "qdap" "R" "mcsv_r.R" 229 | ## 230 | ## [[4]] 231 | ## [1] "~" "Packages" "qdap" "DESCRIPTION" 232 | ## 233 | ## [[5]] 234 | ## [1] "~" "Packages" "qdap" "README.md" 235 | ## 236 | ## [[6]] 237 | ## [1] "~" "Packages" "qdap" "R" "wfm.R" 238 | ## 239 | ## [[7]] 240 | ## [1] "~" "Packages" "qdap" 241 | ## [4] "R" "adjacency_matrix.R" 242 | ## 243 | ## [[8]] 244 | ## [1] "~" "Packages" "qdap" "R" "xnoy.R" 245 | ## 246 | ## [[9]] 247 | ## [1] "~" "Packages" "qdap" "R" "termco.R" 248 | ## 249 | ## [[10]] 250 | ## [1] "~" "Packages" "qdap" "R" 251 | ## [5] "bag_o_words.R" 252 | 253 | Manipulating 254 | ------------ 255 | 256 | Once the path has been parsed the individual elements can be extracted 257 | and/or replaced to form sub-paths. In this section I break the 258 | manipulation functions into (1) extracting (2) replacing, (3) combining, 259 | and (4) expanding types. There are a few miscellaneous **pathr** 260 | functions that are not an extracting, replacing, combining, or expanding 261 | tool which will be discussed at the end of the Manipulating section. 262 | 263 | ### Extracting 264 | 265 | Extracting can replace path elements by their numeric index or by their 266 | content relative to a matched regular expression. There are three sets 267 | of extracting functions (1) `front`/`back`, (2) `index`, and (3) 268 | `before`/`after`. The first two rely on matching elements to their 269 | numeric position while the latter set uses extraction relative to a 270 | regular expression match. 271 | 272 | #### Front & Back 273 | 274 | The `front`/`back` set of functions works like `head`/`tail` (in fact 275 | these functions are used under the hood). The user can select the first 276 | `n` elements using `front` or the last `n` elements using `back`. These 277 | functions require that users want either the first or last element of 278 | the path in their sub-path. 279 | 280 | Here I replicate base **R**'s `dirname` & `basename` functions using the 281 | default settings of `front` & `back` as `dirname` is taking 282 | `head(x, -1)` elements (or all but the last element) and `basename` is 283 | taking `tail(x, 1)` (or the last element). 284 | 285 | myfiles %>% 286 | parse_path() %>% 287 | front() 288 | 289 | ## [1] "~/Packages/qdap/R" "~/Packages/qdap" "~/Packages/qdap/R" 290 | ## [4] "~/Packages/qdap" "~/Packages/qdap" "~/Packages/qdap/R" 291 | ## [7] "~/Packages/qdap/R" "~/Packages/qdap/R" "~/Packages/qdap/R" 292 | ## [10] "~/Packages/qdap/R" 293 | 294 | myfiles %>% 295 | dirname() 296 | 297 | ## [1] "C:/Users/Tyler/Documents/Packages/qdap/R" 298 | ## [2] "C:/Users/Tyler/Documents/Packages/qdap" 299 | ## [3] "C:/Users/Tyler/Documents/Packages/qdap/R" 300 | ## [4] "C:/Users/Tyler/Documents/Packages/qdap" 301 | ## [5] "C:/Users/Tyler/Documents/Packages/qdap" 302 | ## [6] "C:/Users/Tyler/Documents/Packages/qdap/R" 303 | ## [7] "C:/Users/Tyler/Documents/Packages/qdap/R" 304 | ## [8] "C:/Users/Tyler/Documents/Packages/qdap/R" 305 | ## [9] "C:/Users/Tyler/Documents/Packages/qdap/R" 306 | ## [10] "C:/Users/Tyler/Documents/Packages/qdap/R" 307 | 308 | myfiles %>% 309 | parse_path() %>% 310 | back() 311 | 312 | ## [1] "cm_range2long.R" "contributors.geojson" "mcsv_r.R" 313 | ## [4] "DESCRIPTION" "README.md" "wfm.R" 314 | ## [7] "adjacency_matrix.R" "xnoy.R" "termco.R" 315 | ## [10] "bag_o_words.R" 316 | 317 | myfiles %>% 318 | basename() 319 | 320 | ## [1] "cm_range2long.R" "contributors.geojson" "mcsv_r.R" 321 | ## [4] "DESCRIPTION" "README.md" "wfm.R" 322 | ## [7] "adjacency_matrix.R" "xnoy.R" "termco.R" 323 | ## [10] "bag_o_words.R" 324 | 325 | But the `front`/`back` set is more versatile still as demonstrated 326 | below: 327 | 328 | myfiles %>% 329 | parse_path() %>% 330 | front(3) 331 | 332 | ## [1] "~/Packages/qdap" "~/Packages/qdap" "~/Packages/qdap" 333 | ## [4] "~/Packages/qdap" "~/Packages/qdap" "~/Packages/qdap" 334 | ## [7] "~/Packages/qdap" "~/Packages/qdap" "~/Packages/qdap" 335 | ## [10] "~/Packages/qdap" 336 | 337 | myfiles %>% 338 | parse_path() %>% 339 | back(3) 340 | 341 | ## [1] "qdap/R/cm_range2long.R" 342 | ## [2] "Packages/qdap/contributors.geojson" 343 | ## [3] "qdap/R/mcsv_r.R" 344 | ## [4] "Packages/qdap/DESCRIPTION" 345 | ## [5] "Packages/qdap/README.md" 346 | ## [6] "qdap/R/wfm.R" 347 | ## [7] "qdap/R/adjacency_matrix.R" 348 | ## [8] "qdap/R/xnoy.R" 349 | ## [9] "qdap/R/termco.R" 350 | ## [10] "qdap/R/bag_o_words.R" 351 | 352 | #### Indices 353 | 354 | The `index` function compliments the `front`/`back` set by allowing the 355 | user to select the middle elements of a path. Unlike `front`/`back`, the 356 | `index` function does not require elements to be sequential. The user 357 | will get a sub-path equal in length to the length of the `inds` 358 | argument. 359 | 360 | myfiles %>% 361 | parse_path() %>% 362 | index(4) 363 | 364 | ## [1] "R" "contributors.geojson" "R" 365 | ## [4] "DESCRIPTION" "README.md" "R" 366 | ## [7] "R" "R" "R" 367 | ## [10] "R" 368 | 369 | myfiles %>% 370 | parse_path() %>% 371 | index(2:4) 372 | 373 | ## [1] "Packages/qdap/R" 374 | ## [2] "Packages/qdap/contributors.geojson" 375 | ## [3] "Packages/qdap/R" 376 | ## [4] "Packages/qdap/DESCRIPTION" 377 | ## [5] "Packages/qdap/README.md" 378 | ## [6] "Packages/qdap/R" 379 | ## [7] "Packages/qdap/R" 380 | ## [8] "Packages/qdap/R" 381 | ## [9] "Packages/qdap/R" 382 | ## [10] "Packages/qdap/R" 383 | 384 | myfiles %>% 385 | parse_path() %>% 386 | index(c(2, 4)) 387 | 388 | ## [1] "Packages/R" "Packages/contributors.geojson" 389 | ## [3] "Packages/R" "Packages/DESCRIPTION" 390 | ## [5] "Packages/README.md" "Packages/R" 391 | ## [7] "Packages/R" "Packages/R" 392 | ## [9] "Packages/R" "Packages/R" 393 | 394 | #### Before & After Regex 395 | 396 | The `before`/`after` differ from the previous sets of manipulation 397 | functions in that it allows the user to select elements based on their 398 | content rather than numeric position. The user provides a regular 399 | expression to match against. All elements `before` or `after` this regex 400 | match will be selected for use in the sub-path. The user may include the 401 | regex matched element by setting `include = TRUE`. 402 | 403 | Here I extract all elements after the element containing the regex 404 | `"^qdap$"`. 405 | 406 | myfiles %>% 407 | parse_path() %>% 408 | after("^qdap$") 409 | 410 | ## [1] "R/cm_range2long.R" "contributors.geojson" "R/mcsv_r.R" 411 | ## [4] "DESCRIPTION" "README.md" "R/wfm.R" 412 | ## [7] "R/adjacency_matrix.R" "R/xnoy.R" "R/termco.R" 413 | ## [10] "R/bag_o_words.R" 414 | 415 | The user can include the element that matched the regex as well using 416 | `include = TRUE`: 417 | 418 | myfiles %>% 419 | parse_path() %>% 420 | after("^qdap$", include = TRUE) 421 | 422 | ## [1] "qdap/R/cm_range2long.R" "qdap/contributors.geojson" 423 | ## [3] "qdap/R/mcsv_r.R" "qdap/DESCRIPTION" 424 | ## [5] "qdap/README.md" "qdap/R/wfm.R" 425 | ## [7] "qdap/R/adjacency_matrix.R" "qdap/R/xnoy.R" 426 | ## [9] "qdap/R/termco.R" "qdap/R/bag_o_words.R" 427 | 428 | Here I use `before` to extract all elements before the regex match to 429 | paths that contain an element with a file that ends in `.R`. If a path 430 | does not contain that element match `NA` is returned. 431 | 432 | myfiles %>% 433 | parse_path() %>% 434 | before("\\.R$") 435 | 436 | ## [1] "~/Packages/qdap/R" NA "~/Packages/qdap/R" 437 | ## [4] NA NA "~/Packages/qdap/R" 438 | ## [7] "~/Packages/qdap/R" "~/Packages/qdap/R" "~/Packages/qdap/R" 439 | ## [10] "~/Packages/qdap/R" 440 | 441 | ### Replacing 442 | 443 | Often the user will want to replace elements of a path with another. The 444 | `swap` function allows the user to match with a numeric index or a 445 | regular expression to determine the element locations to be replaced. 446 | The `swap_index` & `swap_regex` functions are less flexible than the 447 | more inclusive function but are also more explicit, transparent and 448 | pipeable. Preference is typically given to the later `swap_xxx` 449 | functions in chained usage. 450 | 451 | #### `swap` 452 | 453 | In this scenario I replace the root tilde with `MyRoot`: 454 | 455 | myfiles %>% 456 | parse_path() %>% 457 | swap(1, "MyRoot") 458 | 459 | ## [1] "MyRoot/Packages/qdap/R/cm_range2long.R" 460 | ## [2] "MyRoot/Packages/qdap/contributors.geojson" 461 | ## [3] "MyRoot/Packages/qdap/R/mcsv_r.R" 462 | ## [4] "MyRoot/Packages/qdap/DESCRIPTION" 463 | ## [5] "MyRoot/Packages/qdap/README.md" 464 | ## [6] "MyRoot/Packages/qdap/R/wfm.R" 465 | ## [7] "MyRoot/Packages/qdap/R/adjacency_matrix.R" 466 | ## [8] "MyRoot/Packages/qdap/R/xnoy.R" 467 | ## [9] "MyRoot/Packages/qdap/R/termco.R" 468 | ## [10] "MyRoot/Packages/qdap/R/bag_o_words.R" 469 | 470 | #### `swap_index` & `swap_regex` 471 | 472 | In the next use I replace `qdap` with `textMining` by referencing the 473 | third element: 474 | 475 | myfiles %>% 476 | parse_path() %>% 477 | swap_index(3, "textMining") 478 | 479 | ## [1] "~/Packages/textMining/R/cm_range2long.R" 480 | ## [2] "~/Packages/textMining/contributors.geojson" 481 | ## [3] "~/Packages/textMining/R/mcsv_r.R" 482 | ## [4] "~/Packages/textMining/DESCRIPTION" 483 | ## [5] "~/Packages/textMining/README.md" 484 | ## [6] "~/Packages/textMining/R/wfm.R" 485 | ## [7] "~/Packages/textMining/R/adjacency_matrix.R" 486 | ## [8] "~/Packages/textMining/R/xnoy.R" 487 | ## [9] "~/Packages/textMining/R/termco.R" 488 | ## [10] "~/Packages/textMining/R/bag_o_words.R" 489 | 490 | When the element position is unknown `swap_regex` provides a means to 491 | replace elements: 492 | 493 | myfiles %>% 494 | parse_path() %>% 495 | swap_regex("^qdap$", "textMining") 496 | 497 | ## [1] "~/Packages/textMining/R/cm_range2long.R" 498 | ## [2] "~/Packages/textMining/contributors.geojson" 499 | ## [3] "~/Packages/textMining/R/mcsv_r.R" 500 | ## [4] "~/Packages/textMining/DESCRIPTION" 501 | ## [5] "~/Packages/textMining/README.md" 502 | ## [6] "~/Packages/textMining/R/wfm.R" 503 | ## [7] "~/Packages/textMining/R/adjacency_matrix.R" 504 | ## [8] "~/Packages/textMining/R/xnoy.R" 505 | ## [9] "~/Packages/textMining/R/termco.R" 506 | ## [10] "~/Packages/textMining/R/bag_o_words.R" 507 | 508 | myfiles %>% 509 | parse_path() %>% 510 | swap_regex("\\.R$", "function.R") 511 | 512 | ## [1] "~/Packages/qdap/R/function.R" 513 | ## [2] "~/Packages/qdap/contributors.geojson" 514 | ## [3] "~/Packages/qdap/R/function.R" 515 | ## [4] "~/Packages/qdap/DESCRIPTION" 516 | ## [5] "~/Packages/qdap/README.md" 517 | ## [6] "~/Packages/qdap/R/function.R" 518 | ## [7] "~/Packages/qdap/R/function.R" 519 | ## [8] "~/Packages/qdap/R/function.R" 520 | ## [9] "~/Packages/qdap/R/function.R" 521 | ## [10] "~/Packages/qdap/R/function.R" 522 | 523 | ### Combining 524 | 525 | While the above tools work to produce sub-paths with an equal or less 526 | length of elements `file_path` is a means to combine/construct file 527 | paths that may be greater in length than the original path/elements 528 | supplied. `file_path` is wrapper for `base::file.path` that uses the 529 | underscore naming convention and normalizes the separator to be a single 530 | forward slash. 531 | 532 | file_path("root", "mydir", paste0("file", 1:2, ".pdf")) 533 | 534 | ## [1] "root/mydir/file1.pdf" "root/mydir/file2.pdf" 535 | 536 | This is especially useful when combined with extraction/replacement 537 | techniques to form new paths as shown below: 538 | 539 | myfiles %>% 540 | parse_path() %>% 541 | after("R$", include = TRUE) %>% 542 | na.omit() %>% 543 | file_path("Root", "newPackage", .) 544 | 545 | ## [1] "Root/newPackage/R/cm_range2long.R" 546 | ## [2] "Root/newPackage/R/mcsv_r.R" 547 | ## [3] "Root/newPackage/R/wfm.R" 548 | ## [4] "Root/newPackage/R/adjacency_matrix.R" 549 | ## [5] "Root/newPackage/R/xnoy.R" 550 | ## [6] "Root/newPackage/R/termco.R" 551 | ## [7] "Root/newPackage/R/bag_o_words.R" 552 | 553 | ### Expanding 554 | 555 | Like `file_path` above, `expand_path` produces a path that is longer 556 | than the input path. `expand_path` is wrapper for `base::path.expand` 557 | used to expand tilde prefixed paths by replacing the leading tilde with 558 | the user's home directory. 559 | 560 | expand_path("~/mydir/subdir/myfile.pdf") 561 | 562 | ## [1] "C:/Users/Tyler/Documents/mydir/subdir/myfile.pdf" 563 | 564 | The user may have noticed that in the example [above](#extracting), 565 | demonstrating `front`'s ability to mimic `dirname`, is incomplete. That 566 | is the outputs from `front` and `dirname` are not identical. This is 567 | because `dirname`, by default, expands the tilde in the example 568 | `myfiles` whereas `front` does not. Simply adding `expand_path` on the 569 | end of the chain replicates `dirname` exactly. 570 | 571 | myfiles %>% 572 | parse_path() %>% 573 | front() %>% 574 | expand_path() 575 | 576 | ## [1] "C:/Users/Tyler/Documents/Packages/qdap/R" 577 | ## [2] "C:/Users/Tyler/Documents/Packages/qdap" 578 | ## [3] "C:/Users/Tyler/Documents/Packages/qdap/R" 579 | ## [4] "C:/Users/Tyler/Documents/Packages/qdap" 580 | ## [5] "C:/Users/Tyler/Documents/Packages/qdap" 581 | ## [6] "C:/Users/Tyler/Documents/Packages/qdap/R" 582 | ## [7] "C:/Users/Tyler/Documents/Packages/qdap/R" 583 | ## [8] "C:/Users/Tyler/Documents/Packages/qdap/R" 584 | ## [9] "C:/Users/Tyler/Documents/Packages/qdap/R" 585 | ## [10] "C:/Users/Tyler/Documents/Packages/qdap/R" 586 | 587 | ### Miscellaneous 588 | 589 | As noted above, **pathr** contains a few functions that are not an 590 | extracting, replacing, combining, or extracting tool. 591 | 592 | #### Normalizing 593 | 594 | `normalize` replaces all path slash separators with an **R** friendly 595 | forward slash. 596 | 597 | c("C:\\Users\\Tyler\\AppData\\Local\\Temp\\Rtmp2Ll9d9", "C:/R/R-3.2.2") %>% 598 | parse_path() %>% 599 | normalize() 600 | 601 | ## [1] "C:/Users/Tyler/AppData/Local/Temp/Rtmp2Ll9d9" 602 | ## [2] "C:/R/R-3.2.2" 603 | 604 | #### Windows Fix (single backslashes) 605 | 606 | `win_fix` reads an **R** unfriendly Windows path (single backslashes) 607 | and replaces with friendly forward slashes. This functionality can't be 608 | demonstrated within a knitr document because the single backslashes 609 | can't be parsed or copied to the clipboard from within R. 610 | 611 | If the user were to copy the following path, 612 | `~\Packages\qdap\R\cm_code.overlap.R`, to the clipboard and run 613 | `win_fix()` the result would be: `"~/Packages/qdap/R/cm_code.overlap.R"` 614 | 615 | Examination 616 | ----------- 617 | 618 | Functions of this class are designed to allow the user to examine 619 | structural aspects of a path and contents. 620 | 621 | ### Tree 622 | 623 | `tree` allows the user to see the hierarchical structure of a path's 624 | contents (all the sub-directories and files contained within a parent 625 | directory) as a tree. This function is (with default 626 | `use.data.tree = FALSE`) OS dependent, and requires that the tree 627 | program ([tree for 628 | Windows](https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/tree.mspx?mfr=true) 629 | or [tree for Unix](http://www.computerhope.com/unix/tree.htm)) be 630 | installed. 631 | 632 | On my Windows system this is the tree structure for the **pathr** 633 | package as installed in **R** library: 634 | 635 | file_path(.libPaths(), "pathr") %>% 636 | tree() 637 | 638 | ## Folder PATH listing for volume Windows 639 | ## Volume serial number is 70BF-5124 640 | ## C:\R\R-3.3.3\LIBRARY\PATHR 641 | ## | build.R 642 | ## | CITATION 643 | ## | DESCRIPTION 644 | ## | INDEX 645 | ## | maintenance.R 646 | ## | NAMESPACE 647 | ## | NEWS 648 | ## | 649 | ## +---data 650 | ## | Rdata.rdb 651 | ## | Rdata.rds 652 | ## | Rdata.rdx 653 | ## | 654 | ## +---extra_statdoc 655 | ## | readme.R 656 | ## | 657 | ## +---help 658 | ## | aliases.rds 659 | ## | AnIndex 660 | ## | pathr.rdb 661 | ## | pathr.rdx 662 | ## | paths.rds 663 | ## | 664 | ## +---html 665 | ## | 00Index.html 666 | ## | R.css 667 | ## | 668 | ## +---Meta 669 | ## | data.rds 670 | ## | hsearch.rds 671 | ## | links.rds 672 | ## | nsInfo.rds 673 | ## | package.rds 674 | ## | Rd.rds 675 | ## | 676 | ## +---R 677 | ## | pathr 678 | ## | pathr.rdb 679 | ## | pathr.rdx 680 | ## | 681 | ## +---staticdocs 682 | ## | index.R 683 | ## | 684 | ## \---tests 685 | ## | testthat.R 686 | ## | 687 | ## \---testthat 688 | ## test-before.R 689 | ## test-class_manipulate.R 690 | ## test-copy_path.R 691 | ## test-file_path.R 692 | ## test-front.R 693 | ## test-indent_path.R 694 | ## test-index.R 695 | ## test-is.global.R 696 | ## test-normalize.R 697 | ## test-parse_path.R 698 | ## test-swap.R 699 | ## test-win_fix.R 700 | ## 701 | 702 | Users concerned with OS dependence can use a **data.tree** 703 | implementation of `tree`. This version is slower but is uniform and 704 | requires no outside dependencies to be installed. Additionally, the 705 | output is a **data.tree** `"Node"` class and can be manipulated 706 | accordingly. 707 | 708 | file_path(.libPaths(), "pathr") %>% 709 | tree(use.data.tree = TRUE) 710 | 711 | ## levelName 712 | ## 1 pathr 713 | ## 2 ¦--build.R 714 | ## 3 ¦--CITATION 715 | ## 4 ¦--data 716 | ## 5 ¦ ¦--Rdata.rdb 717 | ## 6 ¦ ¦--Rdata.rds 718 | ## 7 ¦ °--Rdata.rdx 719 | ## 8 ¦--DESCRIPTION 720 | ## 9 ¦--extra_statdoc 721 | ## 10 ¦ °--readme.R 722 | ## 11 ¦--help 723 | ## 12 ¦ ¦--aliases.rds 724 | ## 13 ¦ ¦--AnIndex 725 | ## 14 ¦ ¦--pathr.rdb 726 | ## 15 ¦ ¦--pathr.rdx 727 | ## 16 ¦ °--paths.rds 728 | ## 17 ¦--html 729 | ## 18 ¦ ¦--00Index.html 730 | ## 19 ¦ °--R.css 731 | ## 20 ¦--INDEX 732 | ## 21 ¦--maintenance.R 733 | ## 22 ¦--Meta 734 | ## 23 ¦ ¦--data.rds 735 | ## 24 ¦ ¦--hsearch.rds 736 | ## 25 ¦ ¦--links.rds 737 | ## 26 ¦ ¦--nsInfo.rds 738 | ## 27 ¦ ¦--package.rds 739 | ## 28 ¦ °--Rd.rds 740 | ## 29 ¦--NAMESPACE 741 | ## 30 ¦--NEWS 742 | ## 31 ¦--R 743 | ## 32 ¦ ¦--pathr 744 | ## 33 ¦ ¦--pathr.rdb 745 | ## 34 ¦ °--pathr.rdx 746 | ## 35 ¦--staticdocs 747 | ## 36 ¦ °--index.R 748 | ## 37 °--tests 749 | ## 38 ¦--testthat.R 750 | ## 39 °--testthat 751 | ## 40 ¦--test-before.R 752 | ## 41 ¦--test-class_manipulate.R 753 | ## 42 ¦--test-copy_path.R 754 | ## 43 ¦--test-file_path.R 755 | ## 44 ¦--test-front.R 756 | ## 45 ¦--test-indent_path.R 757 | ## 46 ¦--test-index.R 758 | ## 47 ¦--test-is.global.R 759 | ## 48 ¦--test-normalize.R 760 | ## 49 ¦--test-parse_path.R 761 | ## 50 ¦--test-swap.R 762 | ## 51 °--test-win_fix.R 763 | 764 | ### Indented Elements 765 | 766 | `indent_path` on the other hand, works on individual paths (not 767 | contents) to visualize the hierarchical structure of a path's elements. 768 | 769 | file_path(.libPaths(), "pathr/DESCRIPTION") %>% 770 | indent_path() 771 | 772 | ## -> C: 773 | ## -> R 774 | ## -> R-3.3.3 775 | ## -> library 776 | ## -> pathr 777 | ## -> DESCRIPTION 778 | 779 | Action 780 | ------ 781 | 782 | The last type of functions in **pathr** use the operating system to do 783 | some sort of action. 784 | 785 | ### Opening 786 | 787 | `open_path` uses the operating system defaults to open directories and 788 | files. This function is operating system and setting dependent. Results 789 | may not be consistent across operating systems. Depending upon the 790 | default programs for file types the results may vary as well. Some files 791 | may not be able to be opened. 792 | 793 | #### Opening Directories 794 | 795 | open_path() 796 | 797 | file_path(.libPaths(), "pathr") %>% 798 | open_path() 799 | 800 | #### Opening Files 801 | 802 | file_path(R.home(), "doc/html/about.html") %>% 803 | open_path() 804 | 805 | ### Copying 806 | 807 | `copy_path` uses the [**clipr**]() package's `write_clip` function to 808 | write the current vector, `x`, to the clipboard but still returns `x`. 809 | This makes the copying pipeable, allowing the contents to be copied yet 810 | be passed along in the chain. 811 | 812 | pacman::p_load(clipr) 813 | 814 | R.home() %>% 815 | list.files(full.names = TRUE) %>% 816 | copy_path() %>% 817 | parse_path() %>% 818 | back(1) 819 | 820 | ## [1] "bin" "CHANGES" "COPYING" "doc" 821 | ## [5] "etc" "include" "library" "MD5" 822 | ## [9] "modules" "README" "README.R-3.3.3" "share" 823 | ## [13] "src" "Tcl" "tests" "unins000.dat" 824 | ## [17] "unins000.exe" 825 | 826 | ## What was copied to the clipboard 827 | clipr::read_clip() 828 | 829 | ## [1] "C:/R/R-33~1.3/bin" "C:/R/R-33~1.3/CHANGES" 830 | ## [3] "C:/R/R-33~1.3/COPYING" "C:/R/R-33~1.3/doc" 831 | ## [5] "C:/R/R-33~1.3/etc" "C:/R/R-33~1.3/include" 832 | ## [7] "C:/R/R-33~1.3/library" "C:/R/R-33~1.3/MD5" 833 | ## [9] "C:/R/R-33~1.3/modules" "C:/R/R-33~1.3/README" 834 | ## [11] "C:/R/R-33~1.3/README.R-3.3.3" "C:/R/R-33~1.3/share" 835 | ## [13] "C:/R/R-33~1.3/src" "C:/R/R-33~1.3/Tcl" 836 | ## [15] "C:/R/R-33~1.3/tests" "C:/R/R-33~1.3/unins000.dat" 837 | ## [17] "C:/R/R-33~1.3/unins000.exe" -------------------------------------------------------------------------------- /data/files.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trinker/pathr/5af67db469ca3aa196d9da1c781715bb9c7fa699/data/files.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite pathr in publications, please use:") 2 | 3 | 4 | citEntry(entry = "manual", 5 | title = "{pathr}: Easy Manipulation and Piping of File Paths", 6 | author = "Tyler W. Rinker", 7 | organization = "University at Buffalo/SUNY", 8 | address = "Buffalo, New York", 9 | note = "version 0.0.1", 10 | year = "2015", 11 | url = "http://github.com/trinker/pathr", 12 | textVersion = paste("Rinker, T. W. (2015).", 13 | "pathr: Easy Manipulation and Piping of File Paths", 14 | "version 0.0.1. University at Buffalo. Buffalo, New York.", 15 | "http://github.com/trinker/pathr") 16 | ) 17 | -------------------------------------------------------------------------------- /inst/build.R: -------------------------------------------------------------------------------- 1 | root <- Sys.getenv("USERPROFILE") 2 | pack <- basename(getwd()) 3 | 4 | quick <- TRUE 5 | pdf <- TRUE 6 | 7 | unlink(paste0(pack, ".pdf"), recursive = TRUE, force = TRUE) 8 | devtools::document() 9 | devtools::install(quick = quick, build_vignettes = FALSE, dependencies = TRUE) 10 | 11 | if(pdf){ 12 | path <- find.package(pack) 13 | system(paste(shQuote(file.path(R.home("bin"), "R")), "CMD", "Rd2pdf", shQuote(path))) 14 | file.copy(paste0(pack, '.pdf'), file.path(root,"Desktop", paste0(pack, '.pdf'))) 15 | while (file.exists(paste0(pack, ".pdf"))) {unlink(paste0(pack, ".pdf"), recursive = TRUE, force = TRUE)} 16 | empts <- grep("^\\.Rd", dir(all.files = TRUE), value = TRUE) 17 | unlink(empts, recursive = TRUE, force = TRUE) 18 | } 19 | 20 | message("Done!") 21 | -------------------------------------------------------------------------------- /inst/extra_statdoc/readme.R: -------------------------------------------------------------------------------- 1 |


2 |

pathr is a...

3 |

Download the development version of pathr here 4 | -------------------------------------------------------------------------------- /inst/staticdocs/index.R: -------------------------------------------------------------------------------- 1 | library(staticdocs) 2 | 3 | sd_section("", 4 | "Function for...", 5 | c( 6 | "myfun" 7 | ) 8 | ) -------------------------------------------------------------------------------- /man/before.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/before.R 3 | \name{before} 4 | \alias{before} 5 | \alias{after} 6 | \title{Extract the Elements of a Path Before/After a Regex Occurrence} 7 | \usage{ 8 | before(x, pattern, include = FALSE, collapse = TRUE, ...) 9 | 10 | after(x, pattern, include = FALSE, collapse = TRUE, ...) 11 | } 12 | \arguments{ 13 | \item{x}{A \code{parse_path} object.} 14 | 15 | \item{pattern}{A character string containing a regular expression (or 16 | character string for \code{fixed = TRUE}) to be matched in the given character 17 | vector. Note that under the hood \code{\link[base]{grep}} is used to locate 18 | the indices of path elements that match the regex condition. Only the first 19 | match will be used. The argument \code{perl = TRUE} is hard coded.} 20 | 21 | \item{include}{logical. If \code{TRUE} the element with the regex match will 22 | be included in the reconstructed sub-path.} 23 | 24 | \item{collapse}{logical. If \code{TRUE} the path elements will be collapsed 25 | with the \code{"/"} separator.} 26 | 27 | \item{\ldots}{ignored.} 28 | } 29 | \value{ 30 | Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 31 | \code{character} path elements) of sub-paths. 32 | } 33 | \description{ 34 | Extract the elements of a path before/after a regex occurrence. 35 | Stands in contrast to \code{front},\code{back}, and index in that with the 36 | later three are element number/index focused whereas 37 | \code{before}/\code{after} are content focused. 38 | } 39 | \examples{ 40 | (parsed <- list(c("a", "really", "boring", "path", "for", "R"))) 41 | before(parsed, "^bor") 42 | before(parsed, "^bor", include = TRUE) 43 | 44 | after(parsed, "^bor") 45 | after(parsed, "^bor", include = TRUE) 46 | 47 | library(magrittr) 48 | files \%>\% 49 | parse_path() \%>\% 50 | after("^qdap$") 51 | 52 | files \%>\% 53 | parse_path() \%>\% 54 | after("^qdap$", include = TRUE) 55 | 56 | files \%>\% 57 | parse_path() \%>\% 58 | before("\\\\.R$") 59 | } 60 | \seealso{ 61 | Other sub-path manipulation functions: \code{\link{front}}, 62 | \code{\link{index}}, \code{\link{swap}} 63 | } 64 | -------------------------------------------------------------------------------- /man/copy_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/copy_path.R 3 | \name{copy_path} 4 | \alias{copy_path} 5 | \title{Pipeable Clipboard Copying} 6 | \usage{ 7 | copy_path(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object to be written to the system clipboard.} 11 | 12 | \item{\ldots}{Other arguments passed to \code{\link[clipr]{write_clip}}.} 13 | } 14 | \value{ 15 | Returns \code{x} but attempts to copy content to the clipboard. 16 | } 17 | \description{ 18 | This convenience function wraps \code{\link[clipr]{write_clip}} to copy the 19 | previous output in the chain to the clipboard. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | library(magrittr) 24 | files \%>\% 25 | parse_path() \%>\% 26 | swap_regex("^(P|R)", "oops") \%>\% 27 | copy_path() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /man/expand_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/expand_path.R 3 | \name{expand_path} 4 | \alias{expand_path} 5 | \title{Expand Tilde Path} 6 | \usage{ 7 | expand_path(x) 8 | } 9 | \arguments{ 10 | \item{x}{A tilde prefixed path.} 11 | } 12 | \value{ 13 | Returns a vector of expanded paths. 14 | } 15 | \description{ 16 | A wrapper for \code{\link[base]{path.expand}} that expands a tilde prefixed 17 | path, replacing the leading tilde by the user's home directory (if defined on 18 | that platform). 19 | } 20 | \examples{ 21 | library(magrittr) 22 | file_path("~/mydir", paste0("file", 1:2, ".pdf")) \%>\% 23 | expand_path() 24 | } 25 | \seealso{ 26 | \code{\link[base]{file.path}} 27 | } 28 | -------------------------------------------------------------------------------- /man/file_ext.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/file_ext.R 3 | \name{file_ext} 4 | \alias{file_ext} 5 | \alias{no_file_ext} 6 | \title{Reimport/Renaming of tools Package's File Extension Functions} 7 | \usage{ 8 | file_ext(x) 9 | 10 | no_file_ext(x, compression = FALSE) 11 | } 12 | \arguments{ 13 | \item{x}{A character vector giving file paths.} 14 | 15 | \item{compression}{logical. Should compression extension \file{.gz}, 16 | \file{.bz2} or \file{.xz} be removed first?} 17 | } 18 | \value{ 19 | Returns a character string with just the file extension (\code{file_ext}) 20 | or the path without the file extension (\code{no_file_ext}). 21 | } 22 | \description{ 23 | The \pkg{tools} package has \code{\link[tools]{file_ext}} related functions 24 | but the package has to be explicitly loaded (though comes standard with R) and 25 | the \code{\link[tools]{file_path_sans_ext}} is longer to type. The functions 26 | have been reimported and renamed to aid in their availablity with other path 27 | parsing tools to make their integration seamless (particularly in a pipeable 28 | form). 29 | } 30 | \examples{ 31 | \dontrun{ 32 | library(magrittr) 33 | (r_files <- dir(file.path(R.home(), "doc/manual"), full.names = TRUE)) 34 | 35 | file_ext(r_files) 36 | no_file_ext(r_files) 37 | 38 | r_files \%>\% 39 | parse_path() \%>\% 40 | back() \%>\% 41 | no_file_ext() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /man/file_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/file_path.R 3 | \name{file_path} 4 | \alias{file_path} 5 | \title{Construct Path to File} 6 | \usage{ 7 | file_path(...) 8 | } 9 | \arguments{ 10 | \item{\ldots}{Atomic vectors of elements to construct a path from.} 11 | } 12 | \value{ 13 | Returns a vector of paths. 14 | } 15 | \description{ 16 | A wrapper for \code{\link[base]{file.path}} that normalizes the path separator 17 | between elements. 18 | } 19 | \examples{ 20 | file_path("mydir", paste0("file", 1:2, ".pdf")) 21 | } 22 | \seealso{ 23 | \code{\link[base]{file.path}} 24 | } 25 | -------------------------------------------------------------------------------- /man/files.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pathr-package.R 3 | \docType{data} 4 | \name{files} 5 | \alias{files} 6 | \title{A Vector of File Paths} 7 | \format{A character vector with 203 elements} 8 | \usage{ 9 | data(files) 10 | } 11 | \description{ 12 | A dataset containing a character vector of file paths. 13 | } 14 | \keyword{datasets} 15 | -------------------------------------------------------------------------------- /man/front.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/front.R 3 | \name{front} 4 | \alias{front} 5 | \alias{back} 6 | \title{Extract the First/Last N Elements of a Path} 7 | \usage{ 8 | front(x, n = -1, collapse = TRUE, ...) 9 | 10 | back(x, n = 1, collapse = TRUE, ...) 11 | } 12 | \arguments{ 13 | \item{x}{A \code{parse_path} object.} 14 | 15 | \item{n}{A single integer. If positive, size for the resulting object: number 16 | of elements for a vector. If negative, all but the \code{n} last/first number 17 | of elements of \code{x}.} 18 | 19 | \item{collapse}{logical. If \code{TRUE} the path elements will be collapsed 20 | with the \code{"/"} separator.} 21 | 22 | \item{\ldots}{ignored.} 23 | } 24 | \value{ 25 | Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 26 | \code{character} path elements) of sub-paths. 27 | } 28 | \description{ 29 | \code{front} - Extract the first n elements of a path. Similar to 30 | \code{\link[utils]{head}} (uses \code{\link[utils]{head}} under the hood). 31 | Compare the defualt settings to \code{\link[base]{basename}} and 32 | \code{\link[base]{dirname}}. 33 | 34 | \code{back} - Extract the first n elements of a path. Similar to 35 | \code{\link[utils]{tail}} (uses \code{\link[utils]{tail}} under the hood). 36 | } 37 | \examples{ 38 | front(list(1:8), 3) 39 | front(list(1:8), -3) 40 | 41 | back(list(1:8), 3) 42 | back(list(1:8), -3) 43 | 44 | library(magrittr) 45 | files \%>\% 46 | parse_path() \%>\% 47 | front() 48 | 49 | files \%>\% 50 | parse_path() \%>\% 51 | front(3) 52 | 53 | files \%>\% 54 | parse_path() \%>\% 55 | back() 56 | 57 | files \%>\% 58 | parse_path() \%>\% 59 | back(3) 60 | 61 | ## Compare to basename/dirname 62 | (fls <- file.path("","p1","p2","p3", c("file.pdf", "file.txt", "file.Rmd"))) 63 | 64 | basename(fls) 65 | fls \%>\% 66 | parse_path() \%>\% 67 | back() 68 | 69 | dirname(fls) 70 | fls \%>\% 71 | parse_path() \%>\% 72 | front() 73 | } 74 | \seealso{ 75 | \code{\link[base]{basename}}, 76 | \code{\link[base]{dirname}} 77 | 78 | Other sub-path manipulation functions: \code{\link{before}}, 79 | \code{\link{index}}, \code{\link{swap}} 80 | } 81 | -------------------------------------------------------------------------------- /man/indent_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/indent_path.R 3 | \name{indent_path} 4 | \alias{indent_path} 5 | \title{Separate and Indent Path Elements} 6 | \usage{ 7 | indent_path(path = NULL, copy2clip = is.global(2), symbol = "->") 8 | } 9 | \arguments{ 10 | \item{path}{A path to the file/directory. If \code{NULL} \code{indent_path} 11 | attempts to use \code{\link[clipr]{read_clip}} to read and fix Windows paths.} 12 | 13 | \item{copy2clip}{logical. If \code{TRUE} attempts to copy to the clipboard 14 | using \code{\link[clipr]{write_clip}}. Default copies to the clipboard if 15 | used interactively.} 16 | 17 | \item{symbol}{The prefix symbol to use before the path element.} 18 | } 19 | \description{ 20 | Separate a path into hierarchical drectories and files for indented reading. 21 | } 22 | \examples{ 23 | indent_path("C:/Users/Tyler/Desktop/guy") 24 | indent_path("C:/Users/Tyler/Desktop/guy", symbol="--") 25 | indent_path("C:/Users/Tyler/Desktop/guy", symbol=".") 26 | indent_path("C:/Users/Tyler/Desktop/guy", symbol="") 27 | } 28 | -------------------------------------------------------------------------------- /man/index.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{index} 4 | \alias{index} 5 | \title{Extract an Index of Elements of a Path} 6 | \usage{ 7 | index(x, inds, collapse = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{x}{A \code{parse_path} object.} 11 | 12 | \item{inds}{A vector of indices to select from.} 13 | 14 | \item{collapse}{logical. If \code{TRUE} the path elements will be collapsed 15 | with the \code{"/"} separator.} 16 | 17 | \item{\ldots}{ignored.} 18 | } 19 | \value{ 20 | Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 21 | \code{character} path elements) of sub-paths. 22 | } 23 | \description{ 24 | Extract the indices of a path. Stands in contrast to \code{front}/\code{back} 25 | in that with the later two the user wants the ends of the path elements (front 26 | or bacK) whereas with \code{index} the user wants the middle elements of a path. 27 | } 28 | \examples{ 29 | index(list(1:8), 3) 30 | index(list(1:8), 4:6) 31 | index(list(1:8), c(1, 3)) 32 | 33 | library(magrittr) 34 | files \%>\% 35 | parse_path() \%>\% 36 | index(c(2, 4:5)) 37 | 38 | files \%>\% 39 | parse_path() \%>\% 40 | index(3) 41 | } 42 | \seealso{ 43 | Other sub-path manipulation functions: \code{\link{before}}, 44 | \code{\link{front}}, \code{\link{swap}} 45 | } 46 | -------------------------------------------------------------------------------- /man/is.global.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/is.global.R 3 | \name{is.global} 4 | \alias{is.global} 5 | \title{Test If Environment is Global} 6 | \usage{ 7 | is.global(n = 1) 8 | } 9 | \arguments{ 10 | \item{n}{The number of generations to go back. If used as a function 11 | argument n should be set to 2.} 12 | } 13 | \value{ 14 | A logical response. 15 | } 16 | \description{ 17 | A logical test to determine if the current environment is the global 18 | environment. 19 | } 20 | \examples{ 21 | is.global() 22 | lapply(1:3, function(i) is.global()) 23 | FUN <- function() is.global(); FUN() 24 | 25 | FUN2 <- function(x = is.global(2)) x 26 | FUN2() 27 | FUN3 <- function() FUN2(); FUN3() 28 | } 29 | \references{ 30 | \url{http://stackoverflow.com/questions/18637656/detect-if-environment-is-global-enviroment} 31 | } 32 | \seealso{ 33 | \code{\link[base]{globalenv}}, 34 | \code{\link[base]{parent.frame}} 35 | } 36 | \author{ 37 | Simon O'Hanlon and Tyler Rinker 38 | } 39 | -------------------------------------------------------------------------------- /man/normalize.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/normalize.R 3 | \name{normalize} 4 | \alias{normalize} 5 | \title{Ensure Number and Direction of Slash Separators Are Consistent} 6 | \usage{ 7 | normalize(x) 8 | } 9 | \arguments{ 10 | \item{x}{A \code{parse_path} object.} 11 | } 12 | \value{ 13 | Returns an atomic vector of normalized paths. 14 | } 15 | \description{ 16 | Replace path separators with a single foward slash. 17 | } 18 | \examples{ 19 | library(magrittr) 20 | c("C:\\\\Users\\\\Tyler\\\\AppData\\\\Local\\\\Temp\\\\Rtmp2Ll9d9", "C:/R/R-3.2.2") \%>\% 21 | parse_path() \%>\% 22 | normalize() 23 | } 24 | -------------------------------------------------------------------------------- /man/open_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/open_path.R 3 | \name{open_path} 4 | \alias{open_path} 5 | \title{Open Path (Directories & Files)} 6 | \usage{ 7 | open_path(x = ".") 8 | } 9 | \arguments{ 10 | \item{x}{A vector (typically of length one) of paths to directories of files.} 11 | } 12 | \description{ 13 | Use the operating system defaults to open directories and files. 14 | } 15 | \note{ 16 | This function is operating system and setting dependant. Results may 17 | not be consistent across operating systems. Depending upon the default 18 | programs for file types the results may vary as well. Some files may not be 19 | able to be opened. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | open_path() 24 | } 25 | } 26 | \references{ 27 | \url{http://stackoverflow.com/q/12135732/1000343} 28 | } 29 | \author{ 30 | Dason Kurkiewicz and Tyler Rinker . 31 | } 32 | -------------------------------------------------------------------------------- /man/parse_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse_path.R 3 | \name{parse_path} 4 | \alias{parse_path} 5 | \title{Parse Path(s)} 6 | \usage{ 7 | parse_path(x) 8 | } 9 | \arguments{ 10 | \item{x}{A vector of paths.} 11 | } 12 | \value{ 13 | Returns a list of vectors of parsed paths. 14 | } 15 | \description{ 16 | Parses the individual directories, sub-directories, and files in a path into 17 | individual elements. 18 | } 19 | \examples{ 20 | parse_path(files) 21 | } 22 | -------------------------------------------------------------------------------- /man/pathr.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pathr-package.R 3 | \docType{package} 4 | \name{pathr} 5 | \alias{pathr} 6 | \alias{package-pathr} 7 | \alias{pathr-package} 8 | \title{Easy Manipulation and Piping of File Paths} 9 | \description{ 10 | Tools to extract and reconfigure elements of file paths. 11 | } 12 | -------------------------------------------------------------------------------- /man/print.indent_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/indent_path.R 3 | \name{print.indent_path} 4 | \alias{print.indent_path} 5 | \title{Prints an indent_path object} 6 | \usage{ 7 | \method{print}{indent_path}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An \code{indent_path} object.} 11 | 12 | \item{\ldots}{Other arguments passed to \code{\link[base]{cat}}.} 13 | } 14 | \description{ 15 | Prints an indent_path object. 16 | } 17 | -------------------------------------------------------------------------------- /man/print.manipulate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/manipulate_class.R 3 | \name{print.manipulate} 4 | \alias{print.manipulate} 5 | \title{Prints a manipulate Object} 6 | \usage{ 7 | \method{print}{manipulate}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{A manipulate object} 11 | 12 | \item{\ldots}{ignored.} 13 | } 14 | \description{ 15 | Prints a manipulate object 16 | } 17 | -------------------------------------------------------------------------------- /man/print.parse_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse_path.R 3 | \name{print.parse_path} 4 | \alias{print.parse_path} 5 | \title{Prints a parse_path Object} 6 | \usage{ 7 | \method{print}{parse_path}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{A parse_path object} 11 | 12 | \item{\ldots}{ignored.} 13 | } 14 | \description{ 15 | Prints a parse_path object 16 | } 17 | -------------------------------------------------------------------------------- /man/print.tree.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tree.R 3 | \name{print.tree} 4 | \alias{print.tree} 5 | \title{Prints a tree object} 6 | \usage{ 7 | \method{print}{tree}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{A \code{tree} object.} 11 | 12 | \item{\ldots}{Other arguments passed to \code{\link[base]{cat}}.} 13 | } 14 | \description{ 15 | Prints a tree object. 16 | } 17 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \docType{import} 4 | \name{reexports} 5 | \alias{reexports} 6 | \alias{\%>\%} 7 | \title{Objects exported from other packages} 8 | \keyword{internal} 9 | \description{ 10 | These objects are imported from other packages. Follow the links 11 | below to see their documentation. 12 | 13 | \describe{ 14 | \item{magrittr}{\code{\link[magrittr]{\%>\%}}} 15 | }} 16 | 17 | -------------------------------------------------------------------------------- /man/swap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/swap.R 3 | \name{swap} 4 | \alias{swap} 5 | \alias{swap_index} 6 | \alias{swap_regex} 7 | \title{Replace Elements of a Path} 8 | \usage{ 9 | swap(x, inds, replacement, pattern = NULL, collapse = TRUE, ...) 10 | 11 | swap_index(x, inds, replacement, collapse = TRUE, ...) 12 | 13 | swap_regex(x, pattern, replacement, collapse = TRUE, ...) 14 | } 15 | \arguments{ 16 | \item{x}{A \code{parse_path} object.} 17 | 18 | \item{inds}{Indices to replace.} 19 | 20 | \item{replacement}{A value to replace the indentified indices with.} 21 | 22 | \item{pattern}{A character string containing a regular expression (or 23 | character string for \code{fixed = TRUE}) to be matched in the given character 24 | vector. Note that under the hood \code{\link[base]{grep}} is used to locate 25 | the indices of path elements that match the regex condition. Only the first 26 | match will be used. The argument \code{perl = TRUE} is hard coded.} 27 | 28 | \item{collapse}{logical. If \code{TRUE} the path elements will be collapsed 29 | with the \code{"/"} separator.} 30 | 31 | \item{\ldots}{ignored.} 32 | } 33 | \value{ 34 | Returns a vector (either \code{atomic} or \code{\link[base]{list}} of 35 | \code{character} path elements) of swapped paths. 36 | } 37 | \description{ 38 | Replace the elements of a path. Note either a index (use \code{inds}) or regex 39 | (use \code{pattern}) based approach is used to identify the indices to replace. 40 | The more specific \code{swap_index} or \code{swap_regex} can be used to be 41 | more targetted, transparent, pipeable, and efficient. 42 | } 43 | \examples{ 44 | swap(list(1:8), inds = c(2, 4), "REPLACED VALUE") 45 | swap(list(1:8), pattern = "[238]", replacement = "REPLACED VALUE") 46 | 47 | library(magrittr) 48 | files \%>\% 49 | parse_path() \%>\% 50 | swap(1, "MyFile") 51 | 52 | files \%>\% 53 | parse_path() \%>\% 54 | swap_index(3, "textMining") 55 | 56 | files \%>\% 57 | parse_path() \%>\% 58 | swap_regex("^qdap$", "textMining") 59 | 60 | files \%>\% 61 | parse_path() \%>\% 62 | swap_regex("\\\\.R$", "function.R") 63 | 64 | files \%>\% 65 | parse_path() \%>\% 66 | swap_regex("^(P|R)", "oops") 67 | } 68 | \seealso{ 69 | Other sub-path manipulation functions: \code{\link{before}}, 70 | \code{\link{front}}, \code{\link{index}} 71 | } 72 | -------------------------------------------------------------------------------- /man/tree.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tree.R 3 | \name{tree} 4 | \alias{tree} 5 | \title{Generate a Directory Tree} 6 | \usage{ 7 | tree(path = ".", include.files = TRUE, all.files = TRUE, 8 | use.data.tree = FALSE, out = NULL, additional = NULL, 9 | copy2clip = FALSE) 10 | } 11 | \arguments{ 12 | \item{path}{A path to the directory.} 13 | 14 | \item{include.files}{logical. If \code{TRUE} files and drectories will be 15 | included.} 16 | 17 | \item{all.files}{logical. If \code{FALSE}, only the names of visible files 18 | are returned. If \code{TRUE}, all file names will be returned.} 19 | 20 | \item{use.data.tree}{logical. If \code{TRUE} the \pkg{data.tree} package is 21 | used to make the tree, otherwise \code{system} is invoked with the extrenal 22 | \pkg{tree} program. The former produces a \code{"R6"}, \code{"Node"} object 23 | that can be manipulated accordingly. The latter will be faster in most cases.} 24 | 25 | \item{out}{An optional outfile (typically .txt) to print to.} 26 | 27 | \item{additional}{Additonal arguments passed to 28 | href{https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/tree.mspx?mfr=true}{\code{tree}} 29 | (Windows) or \href{http://www.computerhope.com/unix/tree.htm}{tree} (Unix).} 30 | 31 | \item{copy2clip}{logical. If \code{TRUE} attempts to copy to the clipboard 32 | via \code{\link[clipr]{write_clip}}.} 33 | } 34 | \description{ 35 | Given a directory, generate a directory tree diagram. 36 | } 37 | \note{ 38 | The \pkg{tree} program must be installed to use \code{use.data.tree = FALSE}. 39 | } 40 | \examples{ 41 | tree(system.file("", package = "base"), use.data.tree = TRUE) 42 | \dontrun{ 43 | tree() 44 | tree(.libPaths()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /man/win_fix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/win_fix.R 3 | \name{win_fix} 4 | \alias{win_fix} 5 | \title{Fix Single Windows Backslashes} 6 | \usage{ 7 | win_fix(clip = TRUE, quote = TRUE, copy2clip = interactive()) 8 | } 9 | \arguments{ 10 | \item{clip}{logical. If \code{TRUE} the path is copied from the clipboard 11 | via the \pkg{clipr} package.} 12 | 13 | \item{quote}{logical. If \code{TRUE} the returned path is wrapped with quotes.} 14 | 15 | \item{copy2clip}{logical. If \code{TRUE} the returned path is copied to the 16 | clipboard.} 17 | } 18 | \value{ 19 | Returns an R friendly path. 20 | } 21 | \description{ 22 | Fix single Windows based backslashes in paths with a single foward slash. By 23 | defaukt copying a path from a Windows machine has R unfriendly single 24 | backslashes. This function copies a single Windows path from the clipboard 25 | maes the necessary single foward slash correction. 26 | } 27 | \examples{ 28 | ## copy this line to clipboard... 29 | ## ~\\Packages\\qdap\\R\\cm_code.overlap.R 30 | ## Now run... 31 | ## win_fix() 32 | } 33 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | library("pathr") 3 | 4 | test_check("pathr") -------------------------------------------------------------------------------- /tests/testthat/test-before.R: -------------------------------------------------------------------------------- 1 | context("Checking before") 2 | 3 | test_that("before get the paths before a regex",{ 4 | 5 | parsed <- list(c("a", "really", "boring", "path", "for", "R")) 6 | expect_equal(as.character(before(parsed, "^bor")), "a/really") 7 | expect_equal(as.character(before(parsed, "^bor", include = TRUE)), "a/really/boring") 8 | expect_equal(before(parsed, "^bor", collapse=FALSE), structure(list(c("a", "really")), class = c("manipulate", "list" 9 | ), parsed = list(c("a", "really")))) 10 | }) 11 | 12 | test_that("after gets the paths after a regex",{ 13 | 14 | parsed <- list(c("a", "really", "boring", "path", "for", "R")) 15 | 16 | expect_equal(as.character(after(parsed, "^bor")), "path/for/R") 17 | expect_equal(as.character(after(parsed, "^bor", include = TRUE)), "boring/path/for/R") 18 | expect_equal(after(parsed, "^bor", collapse=FALSE), structure(list(c("path", "for", "R")), class = c("manipulate", 19 | "list"), parsed = list(c("path", "for", "R")))) 20 | 21 | }) 22 | -------------------------------------------------------------------------------- /tests/testthat/test-class_manipulate.R: -------------------------------------------------------------------------------- 1 | context("Checking class_manipulate") 2 | 3 | test_that("class_manipulate adds class and normalization",{ 4 | 5 | expect_equal( 6 | class_manipulate(list(c("th", "rt")), TRUE), 7 | structure("th/rt", class = c("manipulate", "character"), 8 | parsed = list( c("th", "rt"))) 9 | ) 10 | 11 | expect_equal( 12 | class_manipulate(list(c("th", "rt")), FALSE), structure(list(c("th", "rt")), 13 | class = c("manipulate", "list"), parsed = list(c("th", "rt"))) 14 | ) 15 | }) 16 | 17 | -------------------------------------------------------------------------------- /tests/testthat/test-copy_path.R: -------------------------------------------------------------------------------- 1 | context("Checking copy") 2 | 3 | test_that("copy_path copies to clipboard",{ 4 | 5 | x <- copy_path("foo/bar") 6 | expect_equal(x, "foo/bar") 7 | expect_equal(clipr::read_clip(), "foo/bar") 8 | 9 | }) 10 | 11 | -------------------------------------------------------------------------------- /tests/testthat/test-file_path.R: -------------------------------------------------------------------------------- 1 | context("Checking file_path") 2 | 3 | test_that("file_path creates a file path",{ 4 | 5 | expect_equal( 6 | as.character(file_path("mydir", paste0("file", 1:2, ".pdf"))), 7 | c("mydir/file1.pdf", "mydir/file2.pdf") 8 | ) 9 | 10 | }) 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/test-front.R: -------------------------------------------------------------------------------- 1 | context("Checking front") 2 | 3 | test_that("front gets n after beginning",{ 4 | 5 | expect_equal(as.character(front(list(1:8), 3)), "1/2/3") 6 | expect_equal(as.character(front(list(1:8), -3)), "1/2/3/4/5") 7 | 8 | }) 9 | 10 | test_that("back gets n before end",{ 11 | 12 | expect_equal(as.character(back(list(1:8), 3)), "6/7/8") 13 | expect_equal(as.character(back(list(1:8), -3)), "4/5/6/7/8") 14 | 15 | }) 16 | -------------------------------------------------------------------------------- /tests/testthat/test-indent_path.R: -------------------------------------------------------------------------------- 1 | context("Checking indent_path") 2 | 3 | test_that("indent_path ...",{ 4 | 5 | expect_equal( 6 | indent_path("C:/Users/Tyler/Desktop/guy", copy2clip = TRUE), 7 | structure( 8 | "-> C:\n -> Users\n -> Tyler\n -> Desktop\n -> guy", 9 | class = c("indent_path", "character") 10 | ) 11 | ) 12 | 13 | expect_equal( 14 | paste(clipr::read_clip(), 15 | collapse="|"), "-> C:| -> Users| -> Tyler| -> Desktop| -> guy" 16 | ) 17 | 18 | expect_equal( 19 | indent_path("C:/Users/Tyler/Desktop/guy", symbol="--"), 20 | structure( 21 | "-- C:\n -- Users\n -- Tyler\n -- Desktop\n -- guy", 22 | class = c("indent_path", "character") 23 | ) 24 | ) 25 | 26 | expect_equal( 27 | indent_path("C:/Users/Tyler/Desktop/guy", copy2clip = FALSE), 28 | structure( 29 | "-> C:\n -> Users\n -> Tyler\n -> Desktop\n -> guy", 30 | class = c("indent_path", "character") 31 | ) 32 | ) 33 | 34 | }) 35 | 36 | test_that("indent_path prints",{ 37 | expect_true( 38 | grepl("-> Desktop", paste(capture.output(print(indent_path("C:/Users/Tyler/Desktop/guy", copy2clip = FALSE))),collapse=" ")) 39 | ) 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-index.R: -------------------------------------------------------------------------------- 1 | context("Checking index") 2 | 3 | test_that("index grabs indices",{ 4 | 5 | expect_equal(as.character(index(list(1:8), 3)), "3") 6 | expect_equal(as.character(index(list(1:8), 4:6)), "4/5/6") 7 | expect_equal(as.character(index(list(1:8), c(1, 3))), "1/3") 8 | 9 | }) 10 | 11 | -------------------------------------------------------------------------------- /tests/testthat/test-is.global.R: -------------------------------------------------------------------------------- 1 | context("Checking is.global") 2 | 3 | test_that("is.global checks if in global environment",{ 4 | 5 | expect_false(is.global()) 6 | }) 7 | 8 | -------------------------------------------------------------------------------- /tests/testthat/test-normalize.R: -------------------------------------------------------------------------------- 1 | context("Checking normalize") 2 | 3 | test_that("normalize adds single forward slash",{ 4 | 5 | parsed_paths <- structure(list(c("C:", "Users", "Tyler", "AppData", "Local", 6 | "Temp", "Rtmp2Ll9d9"), c("C:", "R", "R-3.2.2")), class = "parse_path") 7 | 8 | expect_equal( 9 | normalize(parsed_paths), 10 | c("C:/Users/Tyler/AppData/Local/Temp/Rtmp2Ll9d9", "C:/R/R-3.2.2") 11 | ) 12 | 13 | }) 14 | 15 | -------------------------------------------------------------------------------- /tests/testthat/test-parse_path.R: -------------------------------------------------------------------------------- 1 | context("Checking parse_path") 2 | 3 | test_that("parse_path parses both forard and double backslash separators",{ 4 | 5 | paths <- c("C:\\Users\\Tyler\\AppData\\Local\\Temp\\Rtmp2Ll9d9", "C:/R/R-3.2.2") 6 | 7 | expect_equal( 8 | parse_path(paths), 9 | structure(list(c("C:", "Users", "Tyler", "AppData", "Local", 10 | "Temp", "Rtmp2Ll9d9"), c("C:", "R", "R-3.2.2")), class = "parse_path") 11 | 12 | ) 13 | }) 14 | 15 | test_that("parse_path prints",{ 16 | 17 | paths <- c("C:\\Users\\Tyler\\AppData\\Local\\Temp\\Rtmp2Ll9d9", "C:/R/R-3.2.2") 18 | 19 | expect_true( 20 | grepl("AppData", paste(capture.output(print(parse_path(paths))), collapse = " ")) 21 | ) 22 | }) 23 | -------------------------------------------------------------------------------- /tests/testthat/test-swap.R: -------------------------------------------------------------------------------- 1 | context("Checking swap") 2 | 3 | test_that("swap swaps on index and regex",{ 4 | 5 | expect_equal( 6 | as.character(swap(list(1:8), inds = c(2, 4), "REPLACED VALUE")), 7 | "1/REPLACED VALUE/3/REPLACED VALUE/5/6/7/8" 8 | ) 9 | 10 | expect_equal( 11 | as.character(swap(list(1:8), pattern = "[238]", replacement = "REPLACED VALUE")), 12 | "1/REPLACED VALUE/REPLACED VALUE/4/5/6/7/REPLACED VALUE" 13 | ) 14 | }) 15 | 16 | test_that("swap_index swaps on index",{ 17 | 18 | expect_equal( 19 | as.character(swap_index(list(1:8), c(2, 4), "REPLACED VALUE")), 20 | "1/REPLACED VALUE/3/REPLACED VALUE/5/6/7/8" 21 | ) 22 | }) 23 | 24 | test_that("swap_regex swaps on regex",{ 25 | 26 | expect_equal( 27 | as.character(swap_regex(list(1:8), "[238]", replacement = "REPLACED VALUE")), 28 | "1/REPLACED VALUE/REPLACED VALUE/4/5/6/7/REPLACED VALUE" 29 | ) 30 | }) 31 | 32 | -------------------------------------------------------------------------------- /tests/testthat/test-win_fix.R: -------------------------------------------------------------------------------- 1 | context("Checking win_fix") 2 | 3 | test_that("win_fix reads from clipboard and fixes backslashes",{ 4 | 5 | clipr::write_clip("~\\Packages\\qdap\\R\\cm_code.overlap.R") 6 | expect_equal(win_fix(copy2clip = TRUE), "~/Packages/qdap/R/cm_code.overlap.R") 7 | expect_equal(clipr::read_clip(), "\"~/Packages/qdap/R/cm_code.overlap.R\"") 8 | 9 | clipr::write_clip("~\\Packages\\qdap\\R\\cm_code.overlap.R") 10 | expect_equal(win_fix(copy2clip = FALSE), "~/Packages/qdap/R/cm_code.overlap.R") 11 | 12 | clipr::write_clip("~\\Packages\\qdap\\R\\cm_code.overlap.R") 13 | win_fix(quote = FALSE, copy2clip = TRUE) 14 | expect_equal(clipr::read_clip(), "~/Packages/qdap/R/cm_code.overlap.R") 15 | }) 16 | 17 | -------------------------------------------------------------------------------- /tools/pathr_logo/r_pathr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trinker/pathr/5af67db469ca3aa196d9da1c781715bb9c7fa699/tools/pathr_logo/r_pathr.png -------------------------------------------------------------------------------- /tools/pathr_logo/r_pathr.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trinker/pathr/5af67db469ca3aa196d9da1c781715bb9c7fa699/tools/pathr_logo/r_pathr.pptx -------------------------------------------------------------------------------- /tools/pathr_logo/r_pathra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trinker/pathr/5af67db469ca3aa196d9da1c781715bb9c7fa699/tools/pathr_logo/r_pathra.png -------------------------------------------------------------------------------- /tools/pathr_logo/resize_icon.txt: -------------------------------------------------------------------------------- 1 | cd C:\Users\Tyler\GitHub\pathr\tools\pathr_logo 2 | ffmpeg -i r_pathra.png -vf scale=200:-1 r_pathr.png --------------------------------------------------------------------------------