─────────────────┨ What is this? ┠─────────────────

Nomenus-rex is a CLI utility for the file mass-renaming.

─────────────────┨   Installing  ┠─────────────────
You can download the source from the GitHub:

git clone https://github.com/ANGulchenko/nomenus-rex.git

Nomenus-rex was created to be assembled with CMake, so just run these commands
from the directory with CMakeLists.txt:

cmake ./
make

─────────────────┨  How to use?  ┠─────────────────

Nomenus-rex is a typical CLI (command line interface) utility and has such
parameters:

 -h  --help          Prints short help
 -s  --source        sets the path to the source directory
 -d  --destination   sets the path to the destination directory
 -c  --config        sets the path to the configuration file
 -e  --example       Prints out the example configuration
 -y  --yes           Process files without confirmation
 -l  --laconic       Print only error messages (don't affect process confirmation);
 -p  --print_limit   Limit the amount of bijections printed.

The only mandatory parameter is "-c"/"--config". Source and destination paths
can be omitted if they're present in the configuration file. If paths are set in
the command line and in the configuration file then command-line data has higher
priority.
It is possible to use "~" char if you have a "HOME" environment variable set
in your system. Also you can omit the full path to the config file. In this case
the config would be searched in XDG_CONFIG_HOME/nomenus-rex/ directory or
(in the case of the absense of XDG_CONFIG_HOME environment variable) in the
HOME/.config/nomenus-rex/
-e/--example parameter is very convenient for the one-off configurations. Just
move to the desired directory and enter the command like:
nomenus-rex -e > example.conf
This will create the basic config with already filled-in source/destination paths.

Here is an example of the configuration file (decorative borders aren't
included):

─────────────────┨ Start config ┠─────────────────

source_dir = "/home/user/work/source";
destination_dir = "/home/user/work/destination";

keep_dir_structure = false;
copy_or_rename = "copy";
sort_mode = "az";

rules = (
    {
        type        = "date";
        date_format = "%Y-%m-%d";
    },
    {
        type        = "text";
        text        = "_";
    },
    {
        type        = "dir";
        // mode     = "whole path"|"parent dir only"
        mode        = "whole path";
        separator   = "-";

    },
    {
        type        = "text";
        text        = "_";
    },
    {
        type        = "integer";
        // mode     = "global"|"local at every dir"
        mode        = "local at every dir";
        start       = 0;
        step        = 1;
        padding     = 5;
    },
    {
        type        = "extension";
        // leave the "ext" variable empty to use an original extension
        ext         = "";
        // mode     = "lowercase"|"uppercase"|"sic";
        mode        = "lowercase";
    }
);

─────────────────┨  End config  ┠─────────────────

// is a single-line comment.
/*
  Multi-line comment.
*/

"Source/destination directories" are self-explanatory. You should make them
identical if you want to rename files, but not copy or move. It is possible
to use "~" char if you have a "HOME" environment variable set in your system.

"keep_dir_structure" can be true or false. While "false", no subdirectories are
created in the destination directory. "True" keeps the subdirectory structure
identical to the source.

"copy_or_rename" can be "copy" or "rename". In "copy" mode files are copying, in
"rename" they are renaming or moving.

"sort_mode" controls the sorting of the filenames before processing. Can be "sic"
for no sorting at all, "az" for ascending alphabetical sorting, and "za" for descending
alphabetical sorting.

"rules" is an array of small templates, each of which is responsible for a particle
of the resulting filename. These templates-rules are processed in the same order
as they are described in the "rules" array. For example, the aforecited config
will copy
"/home/user/work/source/TestDir2/file2.txt"
to something like
"/home/user/work/destination/2022-03-16_TestDir2_00000.txt"

Rules can be of this types:

  "date"     : date_format is the same as in STRFTIME(3)
             ────┨  Example  ┠────────────────
             {
                 type        = "date";
                 date_format = "%Y-%m-%d";
             }

  "filedate" : this is the time of last modification. "date_format" is the same as in STRFTIME(3)
             ────┨  Example  ┠────────────────
             {
                 type        = "filedate";
                 date_format = "%Y-%m-%d";
             }

  "text"     : just any text
             ────┨  Example  ┠────────────────
             {
                 type        = "text";
                 text        = "_";
             }

  "dir"      : mode "whole path" inserts the whole path with subdirs separated
               with "separator".
               mode "parent dir only" inserts only the nearest parent dir to
               the file.
               Only works with subdirectories to the source directory.
              ────┨  Example  ┠────────────────
              {
                  type        = "dir";
                  // mode     = "whole path"|"parent dir only"
                  mode        = "whole path";
                  separator   = "-";
              }

  "integer"  : inserts the number which starts from "start" and iterates with
               "step".
               "padding" dictates the length of the result: integer will be padded
               with zeros.
               mode "global" uses one counter for all files.
               mode "local at every dir" uses separate counters for ever subdir.
               ────┨  Example  ┠────────────────
               {
                   type        = "integer";
                   // mode     = "global"|"local at every dir"
                   mode        = "local at every dir";
                   start       = 0;
                   step        = 1;
                   padding     = 5;
               }

  "extension": inserts the file extension. By default, it uses the file's
               extension or you can provide your own extension through the "ext"
               variable.
               mode "lowercase" transforms the extension to lowercase.
               mode "uppercase" transforms the extension to uppercase.
               mode "sic" uses the original case.
               ────┨  Example  ┠────────────────
               {
                   type        = "extension";
                   // leave the "ext" variable empty to use an original extension
                   ext         = "";
                   // mode     = "lowercase"|"uppercase"|"sic";
                   mode        = "lowercase";
               }

  "filename" : mode "lowercase" transforms the filename to lowercase.
               mode "uppercase" transforms the filename to uppercase.
               mode "sic" uses the original case.
               ────┨  Example  ┠────────────────
               {
                   type        = "filename";
                   // mode     = "lowercase"|"uppercase"|"sic";
                   mode        = "lowercase";
               }

  "filesize" : the "dimension" can be "B","KiB","MiB", or "GiB".
               the dimension can be hidden with a help of "show_dimension" var.
               you can set any decimal separator. The dot wasn't a good idea because
               of the messing with file's extension.
               ────┨  Example  ┠────────────────
               {
                   type              = "filesize";
                   // dimension      = "B"|"KiB"|"MiB"|"GiB"
                   dimension         = "KiB";
                   show_dimension    = true;
                   decimal_separator = ",";
               }

  "replace"  : replaces all occurences of "what" substring to "to" substring.
               The replacement occurs in the current generating filename. For
               example, if you want to rename a "BlaBla001.txt" to "Ololo001.txt"
               you can use a "filename" rule first to set the current precessing
               filename into the "BlaBla001", then use "replace" rule with
               what="BlaBla" and to="Ololo" parameters and don't forget about
               extension rule in the end.
               ────┨  Example  ┠────────────────
               {
                   type        = "replace";
                   what        = "BlaBla";
                   to          = "Ololo";
               }

   "exec"    : Runs the command (FILE *popen(const char *command, const char *type))
               where all occurences of the placeholder are substituted with a filename.
               Result of the rule is the stdout output of the command.
               ────┨  Example  ┠────────────────
               {
                  type        = "exec";
                  command     = "echo '<Placeholder>' | grep -Eo '[0-9]+'";
                  placeholder = "<Placeholder>";
               }


