Merge pull request #533 from gradha/pr_helper_procs
Adds some helper procs
This commit is contained in:
commit
3ae6043e7e
2 changed files with 87 additions and 4 deletions
|
|
@ -836,9 +836,11 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
|
||||||
##
|
##
|
||||||
## If this fails, `EOS` is raised. On the Windows platform this proc will
|
## If this fails, `EOS` is raised. On the Windows platform this proc will
|
||||||
## copy the source file's attributes into dest. On other platforms you need
|
## copy the source file's attributes into dest. On other platforms you need
|
||||||
## to use getFilePermissions and setFilePermissions to copy them by hand,
|
## to use getFilePermissions and setFilePermissions to copy them by hand (or
|
||||||
## otherwise `dest` will inherit the default permissions of a newly created
|
## use the convenience copyFileWithPermissions() proc), otherwise `dest` will
|
||||||
## file for the user.
|
## inherit the default permissions of a newly created file for the user. If
|
||||||
|
## `dest` already exists, the file attributes will be preserved and the
|
||||||
|
## content overwritten.
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
let s = newWideCString(source)
|
let s = newWideCString(source)
|
||||||
|
|
@ -1383,6 +1385,26 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
|
||||||
var res2 = SetFileAttributesA(filename, res)
|
var res2 = SetFileAttributesA(filename, res)
|
||||||
if res2 == - 1'i32: OSError(OSLastError())
|
if res2 == - 1'i32: OSError(OSLastError())
|
||||||
|
|
||||||
|
proc copyFileWithPermissions*(source, dest: string,
|
||||||
|
ignorePermissionErrors = true) =
|
||||||
|
## Copies a file from `source` to `dest` preserving file permissions.
|
||||||
|
##
|
||||||
|
## This is a wrapper proc around copyFile, getFilePermissions and
|
||||||
|
## setFilePermissions on non Windows platform. On windows this proc is just a
|
||||||
|
## wrapper for copyFile since that proc already copies attributes.
|
||||||
|
##
|
||||||
|
## On non windows systems permissions are copied after the file itself has
|
||||||
|
## been copied, which won't happen atomically and could lead to a race
|
||||||
|
## condition. If ignorePermissionErrors is true, errors while reading/setting
|
||||||
|
## file attributes will be ignored, otherwise will raise `OSError`.
|
||||||
|
copyFile(source, dest)
|
||||||
|
when not defined(Windows):
|
||||||
|
try:
|
||||||
|
setFilePermissions(dest, getFilePermissions(source))
|
||||||
|
except:
|
||||||
|
if not ignorePermissionErrors:
|
||||||
|
raise
|
||||||
|
|
||||||
proc inclFilePermissions*(filename: string,
|
proc inclFilePermissions*(filename: string,
|
||||||
permissions: set[TFilePermission]) {.
|
permissions: set[TFilePermission]) {.
|
||||||
rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
|
rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
|
||||||
|
|
@ -1403,6 +1425,9 @@ proc exclFilePermissions*(filename: string,
|
||||||
|
|
||||||
proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
|
proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
|
||||||
## Returns the home directory of the current user.
|
## Returns the home directory of the current user.
|
||||||
|
##
|
||||||
|
## This proc is wrapped by the expandTilde proc for the convenience of
|
||||||
|
## processing paths coming from user configuration files.
|
||||||
when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
|
when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
|
||||||
else: return string(getEnv("HOME")) & "/"
|
else: return string(getEnv("HOME")) & "/"
|
||||||
|
|
||||||
|
|
@ -1580,5 +1605,26 @@ proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} =
|
||||||
if ExistsFile(x): return x
|
if ExistsFile(x): return x
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
|
proc expandTilde*(path: string): string =
|
||||||
|
## Expands a path starting with ``~/`` to a full path.
|
||||||
|
##
|
||||||
|
## If `path` starts with the tilde character and is followed by `/` or `\\`
|
||||||
|
## this proc will return the reminder of the path appended to the result of
|
||||||
|
## the getHomeDir() proc, otherwise the input path will be returned without
|
||||||
|
## modification.
|
||||||
|
##
|
||||||
|
## The behaviour of this proc is the same on the Windows platform despite not
|
||||||
|
## having this convention. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## let configFile = expandTilde("~" / "appname.cfg")
|
||||||
|
## echo configFile
|
||||||
|
## # --> C:\Users\amber\appname.cfg
|
||||||
|
|
||||||
|
if len(path) > 1 and path[0] == '~' and (path[1] == '/' or path[1] == '\\'):
|
||||||
|
result = getHomeDir() / path[2..len(path)-1]
|
||||||
|
else:
|
||||||
|
result = path
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ type
|
||||||
PXmlAttributes* = PStringTable ## an alias for a string to string mapping
|
PXmlAttributes* = PStringTable ## an alias for a string to string mapping
|
||||||
|
|
||||||
TXmlNode {.pure, final, acyclic.} = object
|
TXmlNode {.pure, final, acyclic.} = object
|
||||||
case k: TXmlNodeKind
|
case k: TXmlNodeKind # private, use the kind() proc to read this field.
|
||||||
of xnText, xnComment, xnCData, xnEntity:
|
of xnText, xnComment, xnCData, xnEntity:
|
||||||
fText: string
|
fText: string
|
||||||
of xnElement:
|
of xnElement:
|
||||||
|
|
@ -297,3 +297,40 @@ proc attr*(n: PXmlNode, name: string): string =
|
||||||
assert n.kind == xnElement
|
assert n.kind == xnElement
|
||||||
if n.attrs == nil: return ""
|
if n.attrs == nil: return ""
|
||||||
return n.attrs[name]
|
return n.attrs[name]
|
||||||
|
|
||||||
|
proc findAll*(n: PXmlNode, tag: string, result: var seq[PXmlNode]) =
|
||||||
|
## Iterates over all the children of `n` returning those matching `tag`.
|
||||||
|
##
|
||||||
|
## Found nodes satisfying the condition will be appended to the `result`
|
||||||
|
## sequence, which can't be nil or the proc will crash. Usage example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## var
|
||||||
|
## html: PXmlNode
|
||||||
|
## tags: seq[PXmlNode] = @[]
|
||||||
|
##
|
||||||
|
## html = buildHtml()
|
||||||
|
## findAll(html, "img", tags)
|
||||||
|
## for imgTag in tags:
|
||||||
|
## process(imgTag)
|
||||||
|
assert isNil(result) == false
|
||||||
|
assert n.k == xnElement
|
||||||
|
for child in n.items():
|
||||||
|
if child.k != xnElement:
|
||||||
|
continue
|
||||||
|
if child.tag == tag:
|
||||||
|
result.add(child)
|
||||||
|
elif child.k == xnElement:
|
||||||
|
child.findAll(tag, result)
|
||||||
|
|
||||||
|
proc findAll*(n: PXmlNode, tag: string): seq[PXmlNode] =
|
||||||
|
## Shortcut version to assign in let blocks. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## var html: PXmlNode
|
||||||
|
##
|
||||||
|
## html = buildHtml(html)
|
||||||
|
## for imgTag in html.findAll("img"):
|
||||||
|
## process(imgTag)
|
||||||
|
newSeq(result, 0)
|
||||||
|
findAll(n, tag, result)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue