Skip to content

Instantly share code, notes, and snippets.

@panesofglass
Created June 11, 2012 02:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panesofglass/2908284 to your computer and use it in GitHub Desktop.
Save panesofglass/2908284 to your computer and use it in GitHub Desktop.
Better than a REPL - Reload!
// 1. Watch source files for changes.
// 2. When a change is detected, recompile.
// 3. When assembly changes are detected, reload. (katana?)
// 4. Allow editing of files in a gui (dropbox integration?)
#if INTERACTIVE
#r @"..\packages\FAKE.1.64.6\tools\FakeLib.dll"
#endif
open System
open System.IO
open Fake
let (+/) path1 path2 = Path.Combine(path1, path2)
type Agent<'a> = MailboxProcessor<'a>
let runner = Agent.Start(fun inbox -> async {
while true do
let! path, target = inbox.Receive()
match Shell.Exec(path+/target, dir = path) with
| 0 -> ()
| code -> printfn "The program compiled but failed to run with exit code %d" code
})
let compiler = Agent.Start(fun inbox -> async {
let fsc = @"C:\Program Files (x86)\Microsoft F#\v4.0\Fsc.exe"
while true do
let! path, files, target = inbox.Receive()
match Shell.Exec(fsc, files + " --out:" + target + " --target:exe --standalone --staticlink:mscorlib --tailcalls+ --optimize+ --nologo --sig:test.fsi", path) with
| 0 -> runner.Post (path, target)
| code -> printfn "Compilation failed with exit code %d" code
})
let main args =
// TODO: Move to a command line arg.
let path = @"G:\OSS\test"
let files = "test.fs"
let target = "test.exe"
if not <| Directory.Exists path then Directory.CreateDirectory path |> ignore
let watcher = new FileSystemWatcher(path, "*.fs", EnableRaisingEvents = true, NotifyFilter = NotifyFilters.LastWrite)
let handle (args: FileSystemEventArgs) =
tracefn "%s\%s changed (%A)" args.FullPath args.Name args.ChangeType
compiler.Post (path, files, target)
// Could benefit from Distinct and Throttle from System.Reactive
let events =
watcher.Created
|> Observable.merge watcher.Changed
|> Observable.merge watcher.Deleted
let subscriptions = [|
yield events |> Observable.subscribe handle
yield watcher.Renamed |> Observable.subscribe handle
|]
Console.WriteLine("Press any key to stop watching.")
Console.ReadKey() |> ignore
subscriptions |> Array.iter (fun subscription -> subscription.Dispose())
#if INTERACTIVE
main [||]
#else
[<EntryPoint>]
let entryPoint args =
main args
0
#endif
@panesofglass
Copy link
Author

I should really add this to FSharpKoans and WebApiKoans.

@panesofglass
Copy link
Author

Rather than invoking fsc, we could run MsBuild, NAnt, FAKE, or any other tool.

@panesofglass
Copy link
Author

Would be nice to replace the compiler above with use of FSharp.Compiler.Service.

@panesofglass
Copy link
Author

Better yet, just use the FscHelper built into FAKE. :)

@panesofglass
Copy link
Author

Looks like FAKE has completely replaced the need for this thing: File Watcher

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment