summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/advopt.txt1
-rw-r--r--doc/nimrodc.txt52
-rw-r--r--lib/pure/os.nim65
3 files changed, 106 insertions, 12 deletions
diff --git a/doc/advopt.txt b/doc/advopt.txt
index 08465e457..7a11e9041 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -12,6 +12,7 @@ Advanced commands:
                             module dependency graph
   //dump                    dump all defined conditionals and search paths
   //check                   checks the project for syntax and semantic
+  //pretty                  homogenizes source code style
   //idetools                compiler support for IDEs: possible options:
     --track:FILE,LINE,COL   track a file/cursor position
     --trackDirty:DIRTY_FILE,ORIG_FILE,LINE,COL
diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index 428c42f39..90fad7f9c 100644
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -540,6 +540,58 @@ in C/C++).
 **Note**: This pragma will not exist for the LLVM backend.

 
 
+Source code style
+=================
+
+Nimrod allows you to `mix freely case and underscores as identifier separators
+<manual.html#identifiers-keywords>`_, so variables named ``MyPrecioussInt`` and
+``my_preciouss_int`` are equivalent:
+
+.. code-block:: Nimrod
+  var MyPrecioussInt = 3
+  # Following line compiles fine!
+  echo my_preciouss_int
+
+Since this can lead to many variants of the same source code (you can use
+`nimgrep <nimgrep.html>`_ instead of your typical ``grep`` to ignore style
+problems) the compiler provides the command ``pretty`` to help unifying the
+style of source code.  Running ``nimrod pretty ugly_test.nim`` with this
+example will generate a secondary file named ``ugly_test.pretty.nim`` with the
+following content:
+
+.. code-block:: Nimrod
+  var MyPrecioussInt = 3
+  # Following line compiles fine!
+  echo MyPrecioussInt
+
+During execution the ``pretty`` command will also run on Nimrod's standard
+library, since it doesn't differentiate the standard library as something
+special, and hence will warn of many *errors* which are out of your hand to
+fix, creating respective ``.pretty.nim`` files all the way. You can ignore
+these errors if they don't belong to your source and simply compare your
+original version to the new pretty one. In fact, running ``pretty`` on our test
+file will show the following::
+
+  Hint: ugly_test [Processing]
+  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
+  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
+
+At the moment ``pretty`` will homogenize the style of symbols but will leave
+important changes for you to review. In this case the command is warning that a
+variable name should not start with a capital letter, which is usually reserved
+to `object types <tut2.html#objects>`_. To learn about the accepted `camel case
+style <https://en.wikipedia.org/wiki/Camelcase>`_ read `Coding Guidelines in
+the Internals of Nimrod Compiler <intern.html#coding-guidelines>`_ or `Coding
+Guidelines <https://github.com/Araq/Nimrod/wiki/Coding-Guidelines>`_ and `NEP 1
+: Style Guide for Nimrod Code
+<https://github.com/Araq/Nimrod/wiki/NEP-1-:-Style-Guide-for-Nimrod-Code>`_
+from the Nimrod `GitHub wiki<https://github.com/Araq/Nimrod/wiki>`_.
+
+This command is safe to run because it will never attempt to overwrite your
+existing sources, but the respective ``.pretty.nim`` files **will** be
+overwritten without notice.
+
+
 DynlibOverride
 ==============
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index a7f4f7d91..a70bfa7f1 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -955,11 +955,12 @@ 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 (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.
+  ## to use `getFilePermissions() <#getFilePermissions>`_ and
+  ## `setFilePermissions() <#setFilePermissions>`_ to copy them by hand (or use
+  ## the convenience `copyFileWithPermissions() <#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)
@@ -1363,7 +1364,13 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
 
 proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
   tags: [FWriteIO, FReadIO].} =
-  ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised.
+  ## Copies a directory from `source` to `dest`.
+  ##
+  ## If this fails, `EOS` is raised. On the Windows platform this proc will
+  ## copy the attributes from `source` into `dest`. On other platforms created
+  ## files and directories will inherit the default permissions of a newly
+  ## created file/directory for the user. To preserve attributes recursively on
+  ## these platforms use `copyDirWithPermissions() <#copyDirWithPermissions>`_.
   createDir(dest)
   for kind, path in walkDir(source):
     var noSource = path.substr(source.len()+1)
@@ -1507,14 +1514,17 @@ 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.
+  ## This is a wrapper proc around `copyFile() <#copyFile>`_,
+  ## `getFilePermissions() <#getFilePermissions>`_ and `setFilePermissions()
+  ## <#setFilePermissions>`_ on non Windows platform. On Windows this proc is
+  ## just a wrapper for `copyFile() <#copyFile>`_ since that proc already
+  ## copies attributes.
   ##
-  ## On non windows systems permissions are copied after the file itself has
+  ## 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`.
+  ## 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:
@@ -1523,6 +1533,37 @@ proc copyFileWithPermissions*(source, dest: string,
       if not ignorePermissionErrors:
         raise
 
+proc copyDirWithPermissions*(source, dest: string,
+    ignorePermissionErrors = true) {.rtl, extern: "nos$1",
+    tags: [FWriteIO, FReadIO].} =
+  ## Copies a directory from `source` to `dest` preserving file permissions.
+  ##
+  ## If this fails, `EOS` is raised. This is a wrapper proc around `copyDir()
+  ## <#copyDir>`_ and `copyFileWithPermissions() <#copyFileWithPermissions>`_
+  ## on non Windows platforms. On Windows this proc is just a wrapper for
+  ## `copyDir() <#copyDir>`_ since that proc already copies attributes.
+  ##
+  ## On non Windows systems permissions are copied after the file or directory
+  ## 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`.
+  createDir(dest)
+  when not defined(Windows):
+    try:
+      setFilePermissions(dest, getFilePermissions(source))
+    except:
+      if not ignorePermissionErrors:
+        raise
+  for kind, path in walkDir(source):
+    var noSource = path.substr(source.len()+1)
+    case kind
+    of pcFile:
+      copyFileWithPermissions(path, dest / noSource, ignorePermissionErrors)
+    of pcDir:
+      copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors)
+    else: discard
+
 proc inclFilePermissions*(filename: string,
                           permissions: set[TFilePermission]) {.
   rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =