7 people like it.
Like the snippet!
Line Counter for FS/FSX files
Simple (and inaccurate) command line LOC counter mainly for .fs and .fsx files.
Extended from: http://www.fssnip.net/b6/title/How-many-lines-of-code-does-your-project-contain
Searches current directory and subdirectories (can be changed to only search current dir).
Can be changed to whatever filetype is needed.
Can be either run as a script (with fsi) or compiled (with fsc).
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
|
open System
open System.IO
type Count =
{ LOC:int
comments:int
emptyLines:int }
/// Add or remove the file extensions you want.
/// Set to both .fs and .fsx files by default.
let fileExtentions =
["fs";"fsx"]
|> Seq.map (fun s -> "*." + s)
let printCount count =
printfn "Total LOC: %A" count.LOC
printfn "Total comment lines: %A" count.comments
printfn "Total empty lines: %A" count.emptyLines
printfn "Total LOC + comments: %A" (count.LOC + count.comments)
printfn "Total lines: %A" (count.LOC + count.comments + count.emptyLines)
let printFileList fileList =
printfn "Total files counted: %A" (Seq.length fileList)
printfn "List of files counted:"
fileList
|> Seq.iter (printfn " %s")
let getFiles path wildcards recurse =
wildcards
|> Seq.map (fun wildcard ->
Directory.EnumerateFiles(
path,
wildcard,
if recurse then
SearchOption.AllDirectories
else
SearchOption.TopDirectoryOnly
)
)
|> Seq.concat
let lineCount file =
let isEmpty (line:string) =
line.Trim() = ""
let isComment (line:string) =
line.Trim()
|> fun s ->
s.StartsWith("//")
|| s.StartsWith("(*")
|| s.EndsWith("*)")
let isCode (line:string) =
not (isEmpty line) && not (isComment line)
let getNumLines lineType file =
File.ReadAllLines file
|> Seq.filter lineType
|> Seq.length
let LOC = getNumLines isCode file
let comments = getNumLines isComment file
let emptyLines = getNumLines isEmpty file
//return
{LOC=LOC;comments=comments;emptyLines=emptyLines}
let countLines files =
files
|> Seq.map lineCount
|> Seq.reduce(fun acc elem ->
{ LOC = acc.LOC + elem.LOC
comments = acc.comments + elem.comments
emptyLines = acc.emptyLines + elem.emptyLines })
let runCounter fileType =
let files = getFiles Environment.CurrentDirectory fileType true
printFileList files
countLines files
|> printCount
printfn "Hit enter to continue..."
stdin.ReadLine()
|> ignore
#if COMPILED
[<EntryPoint>]
let main _ =
runCounter fileExtentions
0
#else
runCounter fileExtentions
#endif
|
namespace System
namespace System.IO
type Count =
{LOC: int;
comments: int;
emptyLines: int;}
Full name: Script.Count
Count.LOC: int
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
Count.comments: int
Count.emptyLines: int
val fileExtentions : seq<string>
Full name: Script.fileExtentions
Add or remove the file extensions you want.
Set to both .fs and .fsx files by default.
module Seq
from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val s : string
val printCount : count:Count -> unit
Full name: Script.printCount
val count : Count
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val printFileList : fileList:seq<string> -> unit
Full name: Script.printFileList
val fileList : seq<string>
val length : source:seq<'T> -> int
Full name: Microsoft.FSharp.Collections.Seq.length
val iter : action:('T -> unit) -> source:seq<'T> -> unit
Full name: Microsoft.FSharp.Collections.Seq.iter
val getFiles : path:string -> wildcards:seq<string> -> recurse:bool -> seq<string>
Full name: Script.getFiles
val path : string
val wildcards : seq<string>
val recurse : bool
val wildcard : string
type Directory =
static member CreateDirectory : path:string -> DirectoryInfo + 1 overload
static member Delete : path:string -> unit + 1 overload
static member EnumerateDirectories : path:string -> IEnumerable<string> + 2 overloads
static member EnumerateFileSystemEntries : path:string -> IEnumerable<string> + 2 overloads
static member EnumerateFiles : path:string -> IEnumerable<string> + 2 overloads
static member Exists : path:string -> bool
static member GetAccessControl : path:string -> DirectorySecurity + 1 overload
static member GetCreationTime : path:string -> DateTime
static member GetCreationTimeUtc : path:string -> DateTime
static member GetCurrentDirectory : unit -> string
...
Full name: System.IO.Directory
Directory.EnumerateFiles(path: string) : Collections.Generic.IEnumerable<string>
Directory.EnumerateFiles(path: string, searchPattern: string) : Collections.Generic.IEnumerable<string>
Directory.EnumerateFiles(path: string, searchPattern: string, searchOption: SearchOption) : Collections.Generic.IEnumerable<string>
type SearchOption =
| TopDirectoryOnly = 0
| AllDirectories = 1
Full name: System.IO.SearchOption
field SearchOption.AllDirectories = 1
field SearchOption.TopDirectoryOnly = 0
val concat : sources:seq<#seq<'T>> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.concat
val lineCount : file:string -> Count
Full name: Script.lineCount
val file : string
val isEmpty : (string -> bool)
val line : string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
String.Trim() : string
String.Trim([<ParamArray>] trimChars: char []) : string
val isComment : (string -> bool)
String.StartsWith(value: string) : bool
String.StartsWith(value: string, comparisonType: StringComparison) : bool
String.StartsWith(value: string, ignoreCase: bool, culture: Globalization.CultureInfo) : bool
String.EndsWith(value: string) : bool
String.EndsWith(value: string, comparisonType: StringComparison) : bool
String.EndsWith(value: string, ignoreCase: bool, culture: Globalization.CultureInfo) : bool
val isCode : (string -> bool)
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
val getNumLines : ((string -> bool) -> string -> int)
val lineType : (string -> bool)
type File =
static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
static member AppendAllText : path:string * contents:string -> unit + 1 overload
static member AppendText : path:string -> StreamWriter
static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
static member Create : path:string -> FileStream + 3 overloads
static member CreateText : path:string -> StreamWriter
static member Decrypt : path:string -> unit
static member Delete : path:string -> unit
static member Encrypt : path:string -> unit
static member Exists : path:string -> bool
...
Full name: System.IO.File
File.ReadAllLines(path: string) : string []
File.ReadAllLines(path: string, encoding: Text.Encoding) : string []
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.filter
val LOC : int
val comments : int
val emptyLines : int
val countLines : files:seq<string> -> Count
Full name: Script.countLines
val files : seq<string>
val reduce : reduction:('T -> 'T -> 'T) -> source:seq<'T> -> 'T
Full name: Microsoft.FSharp.Collections.Seq.reduce
val acc : Count
val elem : Count
val runCounter : fileType:seq<string> -> unit
Full name: Script.runCounter
val fileType : seq<string>
type Environment =
static member CommandLine : string
static member CurrentDirectory : string with get, set
static member Exit : exitCode:int -> unit
static member ExitCode : int with get, set
static member ExpandEnvironmentVariables : name:string -> string
static member FailFast : message:string -> unit + 1 overload
static member GetCommandLineArgs : unit -> string[]
static member GetEnvironmentVariable : variable:string -> string + 1 overload
static member GetEnvironmentVariables : unit -> IDictionary + 1 overload
static member GetFolderPath : folder:SpecialFolder -> string + 1 overload
...
nested type SpecialFolder
nested type SpecialFolderOption
Full name: System.Environment
property Environment.CurrentDirectory: string
val stdin<'T> : TextReader
Full name: Microsoft.FSharp.Core.Operators.stdin
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
More information