In my quest to learn F# better so that I might figure out when this tool makes sense, I have been trying to use the language whenever possible/feasible. Just such an opportunity happened while delving into Google App Engine. I found I could get rid of a little warning in the GAE development environment by converting all files from Windows style CRLF (rn) to a more Unix like LF (n). Out came F# to solve this little problem! This application was moderately frustrating to write because of the puzzling syntax errors. I’m still working on getting the feel for F# and am trying to use it as my preferred hammer (realizing full well that “when all you have is a hammer, everything looks like a nail”). I have to admit, it was a fun little application to write!
1 #light
2 open System
3 open System.IO
4
5 // Read the command line.
6 let args = Environment.GetCommandLineArgs()
7
8 // Figure out the directory to use. With 1 arguments, we only
9 // have the app. 2 or more arguments means a directory was passed in.
10 let directory =
11 match args.GetLength(0) with
12 | 1 -> Environment.CurrentDirectory
13 | n -> (string) (args.GetValue(1))
14
15 // Figure out if the directory is real.
16 let directoryExists = Directory.Exists(directory)
17
18 // Recursive function to process the files in a directory
19 let rec processDirectory (dirInfo: DirectoryInfo ) =
20 for file in dirInfo.GetFiles() do
21 printfn “Writing file %s” file.FullName
22 let fileContents = File.ReadAllText(file.FullName)
23 let modifiedContents = fileContents.Replace(“rn”, “n”)
24 File.WriteAllText(file.FullName, modifiedContents)
25 for dir in dirInfo.GetDirectories() do
26 processDirectory(dir)
27
28 // Kick off the work
29 let processFiles =
30 match directoryExists with
31 | false -> printf “Could not find %s” directory
32 | true -> processDirectory(new DirectoryInfo(directory))
For those of you who are used to C# development, debugging these things can be tricky. If you build and run the code as an EXE, instead of using the interactive environment, here are a couple pointers/reminders. First, code like that shown above lives in a static class named after the file containing the code. In my case, the class is named Program. Second, all the class values are static properties on that class. To watch those values, either add the Program class to the Watch window or request values off of Program from the Immediate Window.