I'm translating my bulk code detector from c# to f#, to learn f#.
It's a linqpad c# program that recurses a directory tree organizing
code
- by
- highest line count
- highest line count by directory
- highest line count by base filename (the stuff before the .)
- includes
- non-whitespace count
- potential magic numbers count
- " count
//path returns string
let path :string=
let userPath=Util.ReadLine("SourceDirectory?",@"D:\projects\")
let exists=System.IO.Directory.Exists(userPath)
if not(exists) then //guard clause
raise(DirectoryNotFoundException(userPath))
userPath
let doTestFileExclude = false
//fileExclude= Func<string,bool> a=>
let fileExclude (a:string):bool =
a.EndsWith("designer.cs",StringComparison.CurrentCultureIgnoreCase)||
a.StartsWith("jquery-",StringComparison.CurrentCultureIgnoreCase)||
a.StartsWith("AssemblyInfo");
let pathExclude (a:string) :bool =
a.Contains(@"\Database\")||
a.Contains("Service References")||
a.Contains("Web References") ||
a.Contains("PackageTmp") ||
a.StartsWith(@"~\Web\Scripts\Mvc3")
//record, class, struct, or discriminated union?
type CountSettings = {
Path: string
Patterns: IEnumerable<string>
FileExclude: string -> bool
PathExclude: string-> bool
}
//instance of above type
let currentSettings:CountSettings= {
Path=path
Patterns=["*.cs";"*.js"]
FileExclude=fileExclude
PathExclude=pathExclude
}
//demonstrating access modifier
let private testFileExclude() =
let testCases = ["test";"test.designer.cs";"test.Designer.cs"]
let mapped = testCases |>
List.map(fun (fn:string) ->
(fn,currentSettings.FileExclude(fn))
)
mapped.Dump("testFileExclude done")
if doTestFileExclude then
do testFileExclude()
//set cwd (not a functional call, imperative?)
System.Environment.CurrentDirectory=currentSettings.Path
//public ~IEnumerable<T> visitDir(string dir,T1 dirFilter, T2 patterns, T3 fileFilter)
let rec visitAll (dir:string) patterns=seq{
for pattern in patterns do
yield! Directory.EnumerateFiles(dir,pattern)
for subdir in Directory.EnumerateDirectories(dir) do
yield! visitAll subdir patterns
}
visitAll currentSettings.Path currentSettings.Patterns
|> Seq.length
|> fun x->x.Dump("LengthAll")
let rec visitDir (dir:string) dirFilter patterns fileFilter=
seq{
for pattern in patterns do
for file in Directory.EnumerateFiles(dir,pattern) do
if not(fileFilter(file)) then
yield file
for subdir in Directory.EnumerateDirectories(dir) do
if not(dirFilter(subdir)) then
yield! visitDir subdir dirFilter patterns fileFilter
}
let visitDirResult=
visitDir currentSettings.Path currentSettings.PathExclude
currentSettings.Patterns
currentSettings.FileExclude
visitDirResult |> Seq.length |> fun x->x.Dump("visitDirLength")
visitDirResult |> fun x ->x.Dump("visitDirResult")
//Extension method on string
type System.String with
member x.Right(index) = x.Substring(x.Length - index)
No comments:
Post a Comment