### Working with files

```scala
package laughedelic.literator

import java.io._
import java.nio.file.Path

import lib.LanguageMap._
import lib.FileUtils._

package object lib {

  implicit class FileLiterator(root: File) {
```

Checks that the file has a known source format

```scala
    def isSource: Boolean = langMap.isDefinedAt(root.ext)
    def isMarkdown: Boolean = root.ext match {
      case "md" | "mkd" | "mdown" | "markdown" => true
      case _ => false
    }
```

This is the key function. If the source file is a directory, it traverses it, takes all 
children, parses each and writes a correcponding markdown file. If parser encounters some 
errors, it returns them in a list. 


```scala
    def literate(
          destBase: Option[File] = None
        , withIndex: Boolean = true
        ): List[String] = {
```

First we can generate index section

```scala
      val index = root getFileTree { f => f.isDirectory || f.isSource } match {
          case Some(ix) if withIndex => Seq("------", "### Index", ix) mkString "\n\n"
          case _ => ""
        }
```

Then we start with traversing list of source files

```scala
      val fileList = root getFileList { f => f.isSource || f.isMarkdown }

      def writeResult(source: File, name: String, text: String): Unit = {
        destBase map { base =>
          val relative: Path = source.getCanonicalFile.getParentFile.relativePath(root)
          val destDir: File = new File(base.getCanonicalFile, relative.toString)
          if (!destDir.exists) destDir.mkdirs
          new File(destDir, name).write(text) 
        }
      }

      // TODO: this code is bad structured: look at all those } } } in the end... 
      fileList flatMap { child =>
```

And for each of them we generate a block of relative links

```scala
        val linksList = fileList map { f =>
            "["+f.relativePath(root).toString+"]: "+f.relativePath(child).toString+".md"
          } mkString("\n")

        child.ext match {
          case "md" | "mkd" | "mdown" | "markdown" => {
            val text = Seq(child.read, linksList) mkString "\n\n"
            writeResult(child, child.name, text)
            None
          }
          case _ => {

            langMap.get(child.ext) flatMap { lang =>
```

Knowing the language of the source we can parse it

```scala
              val literator = LiteratorParsers(lang)
              val parsed = literator.parseAll(literator.markdown, child.read) 

              parsed match {
                case literator.NoSuccess(msg, _) => Some(s"${child} ${parsed}")
                case literator.Success(result, _) => {
                  val text = Seq(result, index, linksList) mkString "\n\n"
```

And if we parsed something, we write it to the file

```scala
                  writeResult(child, child.name+".md", text)
                  None
                }
              }
            }
          }
        }
      }
    }
  }
}


```


------

### Index

+ scala
  + lib
    + [FileUtils.scala][lib/FileUtils.scala]
    + [LanguageMap.scala][lib/LanguageMap.scala]
    + [LiteratorParsers.scala][lib/LiteratorParsers.scala]
    + [package.scala][lib/package.scala]
  + plugin
    + [LiteratorPlugin.scala][plugin/LiteratorPlugin.scala]

[lib/FileUtils.scala]: FileUtils.scala.md
[lib/LanguageMap.scala]: LanguageMap.scala.md
[lib/LiteratorParsers.scala]: LiteratorParsers.scala.md
[lib/package.scala]: package.scala.md
[plugin/LiteratorPlugin.scala]: ../plugin/LiteratorPlugin.scala.md
[Readme.md]: ../Readme.md.md