diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b4b3cb163aa..b88fedf9d7d 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -70,6 +70,7 @@ QuickInfo\QuickInfoProvider.fs + @@ -91,6 +92,11 @@ FSharp.LanguageService.Compiler True + + FSharp.VS.FSI + {991dcf75-c2eb-42b6-9a0d-aa1d2409d519} + True + diff --git a/vsintegration/src/FSharp.Editor/FsiCommandService.fs b/vsintegration/src/FSharp.Editor/FsiCommandService.fs new file mode 100644 index 00000000000..95c50ba7a82 --- /dev/null +++ b/vsintegration/src/FSharp.Editor/FsiCommandService.fs @@ -0,0 +1,87 @@ +namespace Microsoft.VisualStudio.FSharp.Editor + +open System +open Microsoft.VisualStudio.Text.Editor +open Microsoft.VisualStudio.OLE.Interop +open System.ComponentModel.Composition +open Microsoft.VisualStudio +open Microsoft.VisualStudio.Editor +open Microsoft.VisualStudio.TextManager.Interop +open Microsoft.VisualStudio.Utilities +open Microsoft.VisualStudio.Shell +open Microsoft.VisualStudio.Shell.Interop +open Microsoft.VisualStudio.FSharp.Interactive +open EnvDTE + +type FsiCommandFilter(serviceProvider: System.IServiceProvider) = + let projectSystemPackage = + lazy( + let shell = serviceProvider.GetService(typeof) :?> IVsShell + let packageToBeLoadedGuid = ref (Guid "{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}") // FSharp ProjectSystem guid + match shell.LoadPackage packageToBeLoadedGuid with + | VSConstants.S_OK, pkg -> + pkg :?> Package + | _ -> null) + + let mutable nextTarget = null + + member x.AttachToViewAdapter (viewAdapter: IVsTextView) = + match viewAdapter.AddCommandFilter x with + | VSConstants.S_OK, next -> + nextTarget <- next + | errorCode, _ -> + ErrorHandler.ThrowOnFailure errorCode |> ignore + + interface IOleCommandTarget with + member x.Exec (pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut) = + if pguidCmdGroup = VSConstants.VsStd11 then + if nCmdId = uint32 VSConstants.VSStd11CmdID.ExecuteSelectionInInteractive then + Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.ExecuteSelection null null + elif nCmdId = uint32 VSConstants.VSStd11CmdID.ExecuteLineInInteractive then + Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.ExecuteLine null null + VSConstants.S_OK + elif pguidCmdGroup = Guids.guidInteractive then + if nCmdId = uint32 Guids.cmdIDDebugSelection then + Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.DebugSelection null null + VSConstants.S_OK + elif isNotNull nextTarget then + nextTarget.Exec(&pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut) + else + VSConstants.E_FAIL + + member x.QueryStatus (pguidCmdGroup, cCmds, prgCmds, pCmdText) = + if pguidCmdGroup = VSConstants.VsStd11 then + for i = 0 to int cCmds-1 do + if prgCmds.[i].cmdID = uint32 VSConstants.VSStd11CmdID.ExecuteSelectionInInteractive then + prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED) + elif prgCmds.[i].cmdID = uint32 VSConstants.VSStd11CmdID.ExecuteLineInInteractive then + prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED ||| OLECMDF.OLECMDF_DEFHIDEONCTXTMENU) + VSConstants.S_OK + elif pguidCmdGroup = Guids.guidInteractive then + for i = 0 to int cCmds-1 do + if prgCmds.[i].cmdID = uint32 Guids.cmdIDDebugSelection then + let dbgState = Hooks.GetDebuggerState projectSystemPackage.Value + if dbgState = FsiDebuggerState.AttachedNotToFSI then + prgCmds.[i].cmdf <- uint32 OLECMDF.OLECMDF_INVISIBLE + else + prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED) + VSConstants.S_OK + elif isNotNull nextTarget then + nextTarget.QueryStatus(&pguidCmdGroup, cCmds, prgCmds, pCmdText) + else + VSConstants.E_FAIL + +[)>] +[] +[] +type FsiCommandFilterProvider [] + ([)>] serviceProvider: System.IServiceProvider, + editorFactory: IVsEditorAdaptersFactoryService) = + interface IWpfTextViewCreationListener with + member __.TextViewCreated(textView) = + match editorFactory.GetViewAdapter(textView) with + | null -> () + | textViewAdapter -> + let commandFilter = FsiCommandFilter serviceProvider + commandFilter.AttachToViewAdapter textViewAdapter + \ No newline at end of file diff --git a/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs b/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs index 6fa80ea3d1c..5a8ab326cc3 100644 --- a/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs +++ b/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs @@ -9,6 +9,7 @@ open Microsoft.VisualStudio.Shell [] +[] [] [] []