Skip to content

Commit

Permalink
[ospaths] simplify getConfigDir and introduce normalizePathEnd to make
Browse files Browse the repository at this point in the history
sure path endings are normalized with 0 or 1 trailing sep, taking care
of edge cases
  • Loading branch information
timotheecour committed Aug 23, 2018
1 parent 35e37fd commit a2f9c47
Showing 1 changed file with 47 additions and 4 deletions.
51 changes: 47 additions & 4 deletions lib/pure/ospaths.nim
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,31 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
elif defined(posix):
result = path[0] == '/'


proc normalizePathEnd(path: var string, trailingSep = false) =
## ensures ``path`` has exactly 0 or 1 trailing `DirSep`, depending on
## ``trailingSep``, and taking care of edge cases: it preservers whether
## a path is absolute or relative, and makes sure trailing sep is `DirSep`,
## not `AltSep`.
if path.len == 0: return
var i = path.len
while i >= 1 and path[i-1] in {DirSep, AltSep}: dec(i)
if trailingSep:
# foo// => foo
path.setLen(i)
# foo => foo/
path.add DirSep
elif i>0:
# foo// => foo
path.setLen(i)
else:
# // => / (empty case was already taken care of)
path = $DirSep

proc normalizePathEnd(path: string, trailingSep = false): string =
result = path
result.normalizePathEnd(trailingSep)

proc unixToNativePath*(path: string, drive=""): string {.
noSideEffect, rtl, extern: "nos$1".} =
## Converts an UNIX-like path to a native one.
Expand Down Expand Up @@ -530,12 +555,12 @@ proc getConfigDir*(): string {.rtl, extern: "nos$1",
## "~/.config/", otherwise.
##
## An OS-dependent trailing slash is always present at the end of the
## returned string; `\\` on Windows and `/` on all other OSs.
## returned string; `\` on Windows and `/` on all other OSs.
when defined(windows):
result = string(getEnv("APPDATA")) & "\\"
result = string(getEnv("APPDATA"))
else:
result = string(getEnv("XDG_CONFIG_HOME", "")) & "/"
if result == "/": result = string(getEnv("HOME")) & "/.config/"
result = getEnv("XDG_CONFIG_HOME", getEnv("HOME") / ".config").string
result.normalizePathEnd(trailingSep = true)

proc getTempDir*(): string {.rtl, extern: "nos$1",
tags: [ReadEnvEffect, ReadIOEffect].} =
Expand Down Expand Up @@ -649,3 +674,21 @@ when isMainModule:

when defined(posix):
assert quoteShell("") == "''"

block normalizePathEndTest:
# handle edge cases correctly: shouldn't affect whether path is
# absolute/relative
doAssert "".normalizePathEnd(true) == ""
doAssert "".normalizePathEnd(false) == ""
doAssert "/".normalizePathEnd(true) == $DirSep
doAssert "/".normalizePathEnd(false) == $DirSep

when defined(posix):
doAssert "//".normalizePathEnd(false) == "/"
doAssert "foo.bar//".normalizePathEnd == "foo.bar"
doAssert "bar//".normalizePathEnd(trailingSep = true) == "bar/"
when defined(Windows):
doAssert r"C:\foo\\".normalizePathEnd == r"C:\foo"
doAssert r"C:\foo".normalizePathEnd(trailingSep = true) == r"C:\foo\"
doAssert r"C:\".normalizePathEnd == r"C:\"
doAssert "/".normalizePathEnd == r"\"

0 comments on commit a2f9c47

Please sign in to comment.