How come a count of a range becomes 0 before a foreach?

ikelaiah iwan.kelaiah at gmail.com
Sun Apr 9 01:38:45 UTC 2023


Hi,

I've written a file that converts Rmd (R Markdown file), to a 
MarkDown file.

All works well if and only if line 73 is commented out.

I marked line 72 in the code below.

If line 73 is not commented out, `foreach` does not execute as 
the `rmdFiles.walklength` in line 82 becomes `0`.

How does `rmdFiles.walkLength` becomes `0` before the `foreach`? 
I'm a but confused.

Can someone clarify? Thank you.


```d
module rmd2md;

import std.algorithm;
import std.stdio;
import file = std.file;
import std.conv;
import std.regex;
import std.getopt;
import std.path;
import std.datetime;
import std.parallelism;
import std.range;

void main(string[] args)
{
     // Set variables for the main program
     string programName = "Rmd2md";

     // Setup Regex for capturing Rmd code snippet header
     Regex!char re = regex(r"`{3}\{r[a-zA-Z0-9= ]*\}", "g");

     // Set default values for the arguments
     string inputPath = file.getcwd();
     string fileEndsWith = ".Rmd";
     string outputPath = file.getcwd();

     // Set GetOpt variables
     auto helpInformation = getopt(
         args,
         "path|p", "Path of Rmd files. Default: current working 
directory.", &inputPath,
         "fext|e", "Extension of Rmd files. Default: `.Rmd`", 
&fileEndsWith,
         "fout|o", "Output folder to save the MD files. Default: 
current working directory.", &outputPath
     );

     if (helpInformation.helpWanted)
     {
         defaultGetoptPrinter("Rmd to Markdown (md) file 
converter.",
             helpInformation.options);
         return;
     }

     // is the path valid?
     if (!std.path.isValidPath(inputPath))
     {
         writeln(programName ~ ": invalid input path");
         return;
     }

     // is output path valid?
     if (!std.path.isValidPath(outputPath))
     {
         writeln(programName ~ ": invalid output path");
         return;
     }

     // is file extension valid?
     if (!startsWith(fileEndsWith, "."))
     {
         writeln(programName ~ ": invalid extension given");
         return;
     }

     writeln(programName ~ ": input directory is " ~ inputPath);
     writeln(programName ~ ": output directory is " ~ outputPath);
     writeln(programName ~ ": ...");

     // Get files in specified inputPath variable with a specific 
extension
     auto rmdFiles = file.dirEntries(inputPath, 
file.SpanMode.shallow)
         .filter!(f => f.isFile)
         .filter!(f => f.name.endsWith(fileEndsWith));

     // LINE 72 -- WARNING -- If we count the range here, later it 
will become 0 in line 82
     writeln(programName ~ ": number of files found " ~ 
to!string(rmdFiles.walkLength));

     // Get start time
     auto stattime = Clock.currTime();

     // Process each Rmd file
     int fileWrittenCount = 0;

     // LINE 81 -- WARNING -- if line 73 is not commented out, the 
walkLength returns 0
     writeln(programName ~ ": number of files found " ~ 
to!string(rmdFiles.walkLength));

     foreach (file.DirEntry item; parallel(rmdFiles))
     {
         writeln(programName ~ ": processing " ~ item.name);

         try
         {
             // Read content as string
             string content = file.readText(item.name);
             // Replace ```{r} or ```{r option1=value} with ```R
             string modified = replaceAll(content, re, "```R");
             // Set the Markdown output file
             string outputFile = replaceAll(baseName(item.name), 
regex(r".Rmd"), ".md");
             // Build an output path, using output path and 
baseName(item.name)
             string outputFilenamePath = buildPath(outputPath, 
outputFile);
             // Save output Markdown file
             file.write(outputFilenamePath, modified);
             writeln(programName ~ ": written " ~ 
outputFilenamePath);
             // Increase counter to indicate number of files 
processed
             fileWrittenCount++;
         }
         catch (file.FileException e)
         {
             writeln(programName ~ ": " ~ e.msg);
         }
     }

     writeln(programName ~ ": ...");

     // Gett end clock
     auto endttime = Clock.currTime();
     auto duration = endttime - stattime;
     writeln("Duration: ", duration);

     // Console output a summary
     writeln(programName ~ ": written " ~ 
to!string(fileWrittenCount) ~ " files");
}
```


For testing, you can create a text file, save as `.Rmd` in the 
same folder as the D file. Run the script as:

```bash
rdmd rmd2md.d
```

It will find the `.Rmd` file in current path and save it in the 
current path.


More information about the Digitalmars-d-learn mailing list