Skip to content

Instantly share code, notes, and snippets.

@atsapura
Created September 20, 2020 15:50
Show Gist options
  • Save atsapura/6c1a7c7c00766f086fa2b9735c43b4f8 to your computer and use it in GitHub Desktop.
Save atsapura/6c1a7c7c00766f086fa2b9735c43b4f8 to your computer and use it in GitHub Desktop.
Count fsharp lines of code in your project!
open System
open System.IO
type FSharpCodeLine =
| NamespaceDeclaration
| Open
| Comment
| Source
| Brace
type Report =
{
TotalFiles: int
CodeLines: Map<FSharpCodeLine, int>
}
let braces = ['{'; '}'; '('; ')'; '['; ']'; '|'; '|'] |> System.Collections.Generic.HashSet
let getFsharpSourceFiles path =
let dir = DirectoryInfo(path)
dir.GetFiles("*.fs", SearchOption.AllDirectories)
let readAllLines (file: FileInfo) =
async {
use f = file.OpenText()
let! text = f.ReadToEndAsync() |> Async.AwaitTask
return
match text with
| null | "" -> [||]
| text ->
text.Split([|"\n"|], StringSplitOptions.RemoveEmptyEntries)
}
let codeLine str =
match str with
| null | "" -> None
| str when String.IsNullOrWhiteSpace str -> None
| str ->
let line = str.Trim()
if line.StartsWith("//") then Comment
elif line.StartsWith("namespace") then NamespaceDeclaration
elif line.StartsWith("open") then Open
elif String.forall braces.Contains line then Brace
else Source
|> Some
let countCodeLines file =
async {
let! lines = readAllLines file
let codeLines = lines |> Array.choose codeLine
return
codeLines
|> Array.countBy id
|> Map.ofSeq
}
let mergeMaps left right =
let add left k v =
match Map.tryFind k left with
| None -> left.Add(k,v)
| Some vl -> left.Add(k, v + vl)
Map.fold add left right
let countCodeLinesInFolder path =
async {
let files = getFsharpSourceFiles path
let! result =
files
|> Array.map countCodeLines
|> Async.Parallel
return
{
CodeLines = result |> Array.fold mergeMaps Map.empty
TotalFiles = files.Length
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment