1. Write a script that is loaded when the FSI starts.
2. Modify the source of FSI.exe (which can be found at http://fsharppowerpack.codeplex.com/).
3. Create an alternate F# Interactive Window VSIX that starts the FSI.exe as a new process as well as provides new commands.
In this post, I'll explore the first of these options.
Building the Script:
There are 3 steps to accomplishing the desired goal with option 1.
1. Create a F# script that has the ability to retrieve packages from NuGet and interact with Visual Studio. The script that I used to accomplish this can be found here.
Note: NuGet must be installed on the machine. Additionally, you will need to change the path to the NuGet.Core.dll reference if running a 32-bit version of Windows. This will be evident if you receive an error like the following when starting the F# Interactive Window - "error FS0084: Assembly reference 'C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\NuGet.Core.dll' was not found or is invalid".
2. Update the FSI command line options in Visual Studio by going to Tools | Options | F# Tools | F# Interactive. Add "--use:<Path>\FsiExtension.fsx" to the "F# Interactive Options" value (see example below). Note: A full list of available FSI options can be found at http://msdn.microsoft.com/en-us/library/dd233172.aspx.
3. Open the F# Interactive Window (or reset the session if the window is already opened).
Taking it for a Test Drive:
Now that you are setup, it's time to try out the new functionality.
1. Create a new F# project and add a F# Script File (if one doesn't currently exist).
2. Add some code (such as the following example from the Getting Started with F# PowerPack - Part 2 blog post) to the F# Script File:
open Microsoft.FSharp.Control let rec job = async { for i in 1 .. 20 do printfn "doing some work" do! Async.Sleep 300 worker.ReportProgress i } and worker : AsyncWorker<_> = AsyncWorker(job) worker.ProgressChanged.Add(fun jobNumber -> printfn "job %d completed" jobNumber) worker.Error.Add(fun err -> printfn "Error: %A" err.Message) worker.Completed.Add(fun _ -> printfn "All jobs have completed") worker.Canceled.Add(fun _ -> printfn "Jobs have been canceled") worker.RunAsync() |> ignore
3. In the F# Interactive Window, type InstallPackage "FSPowerPack.Core.Community";; and execute it. This will fire off the process to retrieve the FSPowerPack.Core.Community NuGet package from NuGet Gallery. The F# Interactive Window should look like the following once the process is complete:
This does two things:
1. It retrieves the specified NuGet package.
2. It adds any appropriate references to the fsx file. Your code will now look something like this:
#r @"C:\git\TestFsDte\packages\FSPowerPack.Core.Community.2.0.0.0\Lib\Net40\FSharp.PowerPack.dll" open Microsoft.FSharp.Control let rec job = async { for i in 1 .. 20 do printfn "doing some work" do! Async.Sleep 300 worker.ReportProgress i } and worker : AsyncWorker<_> = AsyncWorker(job) worker.ProgressChanged.Add(fun jobNumber -> printfn "job %d completed" jobNumber) worker.Error.Add(fun err -> printfn "Error: %A" err.Message) worker.Completed.Add(fun _ -> printfn "All jobs have completed") worker.Canceled.Add(fun _ -> printfn "Jobs have been canceled") worker.RunAsync() |> ignore4. You can also see what packages are installed by typing ShowInstalledPackages();;
Conclusion:
While this is hardly a perfect solution, hopefully it will at least spawn a few ideas. This implementation has several known issues (and probably several that are unknown). Let me know if you have ideas on better approaches or improvements.
No comments:
Post a Comment