mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-15 07:43:26 +00:00
Merge pull request #533 from gradha/pr_helper_procs
Adds some helper procs
This commit is contained in:
@@ -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
|
||||
## copy the source file's attributes into dest. On other platforms you need
|
||||
## to use getFilePermissions and setFilePermissions to copy them by hand,
|
||||
## otherwise `dest` will inherit the default permissions of a newly created
|
||||
## file for the user.
|
||||
## to use getFilePermissions and setFilePermissions to copy them by hand (or
|
||||
## use the convenience copyFileWithPermissions() proc), otherwise `dest` will
|
||||
## 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 useWinUnicode:
|
||||
let s = newWideCString(source)
|
||||
@@ -1383,6 +1385,26 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
|
||||
var res2 = SetFileAttributesA(filename, res)
|
||||
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,
|
||||
permissions: set[TFilePermission]) {.
|
||||
rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
|
||||
@@ -1403,6 +1425,9 @@ proc exclFilePermissions*(filename: string,
|
||||
|
||||
proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
|
||||
## 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")) & "\\"
|
||||
else: return string(getEnv("HOME")) & "/"
|
||||
|
||||
@@ -1580,5 +1605,26 @@ proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} =
|
||||
if ExistsFile(x): return x
|
||||
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.}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ type
|
||||
PXmlAttributes* = PStringTable ## an alias for a string to string mapping
|
||||
|
||||
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:
|
||||
fText: string
|
||||
of xnElement:
|
||||
@@ -297,3 +297,40 @@ proc attr*(n: PXmlNode, name: string): string =
|
||||
assert n.kind == xnElement
|
||||
if n.attrs == nil: return ""
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user