File: getRelativePath.R

package info (click to toggle)
r-cran-bbmisc 1.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,256 kB
  • sloc: ansic: 176; sh: 9; makefile: 5
file content (44 lines) | stat: -rw-r--r-- 1,498 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#' @title Construct a path relative to another
#'
#' @description
#' Constructs a relative path from path \code{from} to path \code{to}.
#' If this is not possible (i.e. different drive letters on windows systems),
#' \code{NA} is returned.
#'
#' @param to [\code{character(1)}]\cr
#'  Where the relative path should point to.
#' @param from [\code{character(1)}]\cr
#'  From which part to start.
#'  Default is \code{\link[base]{getwd}}.
#' @param ignore.case [\code{logical(1)}]\cr
#'  Should path comparisons be made case insensitve?
#'  Default is \code{TRUE} on Windows systems and \code{FALSE} on other systems.
#' @return [character(1)]: A relative path.
#' @export
getRelativePath = function(to, from = getwd(), ignore.case = isWindows()) {
  numberCommonParts = function(p1, p2) {
    for (i in seq_len(min(length(p1), length(p2)))) {
      if (p1[i] != p2[i])
        return(i - 1L)
    }
    return(if (is.null(i)) 0L else i)
  }

  from = splitPath(from)
  to = splitPath(to)
  assertFlag(ignore.case)
  if (length(from$drive) != length(to$drive))
    return(NA_character_)
  if (length(from$drive) > 0L && length(to$drive) > 0L && from$drive != to$drive)
    return(NA_character_)

  if (ignore.case)
    i = numberCommonParts(tolower(from$path), tolower(to$path))
  else
    i = numberCommonParts(from$path, to$path)

  res = c(rep.int("..", length(from$path) - i), tail(to$path, ifelse(i == 0L, Inf, -i)))
  if (length(res) == 0L)
    res = "."
  collapse(res, .Platform$file.sep)
}