Skip to content

Commit

Permalink
Fix 14340 - Prompt issues between VS and fsi. (#14383)
Browse files Browse the repository at this point in the history
Co-authored-by: Petr Pokorny <petr@innit.cz>
Co-authored-by: Vlad Zarytovskii <vzaritovsky@hotmail.com>
  • Loading branch information
3 people authored Nov 30, 2022
1 parent 8e3b97b commit 186d3f6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 19 deletions.
2 changes: 1 addition & 1 deletion VisualFSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FCSBenchmarks", "FCSBenchma
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fsharp.ProfilingStartpointProject", "tests\benchmarks\Fsharp.ProfilingStartpointProject\Fsharp.ProfilingStartpointProject.fsproj", "{FE23BB65-276A-4E41-8CC7-F7752241DEBA}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Editor.Tests", "vsintegration\tests\FSharp.Editor.Tests\FSharp.Editor.Tests.fsproj", "{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}"
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Editor.Tests", "vsintegration\tests\FSharp.Editor.Tests\FSharp.Editor.Tests.fsproj", "{CBC96CC7-65AB-46EA-A82E-F6A788DABF80}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
42 changes: 37 additions & 5 deletions src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1127,15 +1127,38 @@ type internal FsiConsolePrompt(fsiOptions: FsiCommandLineOptions, fsiConsoleOutp
// A prompt gets "printed ahead" at start up. Tells users to start type while initialisation completes.
// A prompt can be skipped by "silent directives", e.g. ones sent to FSI by VS.
let mutable dropPrompt = 0
let mutable showPrompt = true

// NOTE: SERVER-PROMPT is not user displayed, rather it's a prefix that code elsewhere
// uses to identify the prompt, see service\FsPkgs\FSharp.VS.FSI\fsiSessionToolWindow.fs
let prompt = if fsiOptions.UseServerPrompt then "SERVER-PROMPT>\n" else "> "

member _.Print() = if dropPrompt = 0 then fsiConsoleOutput.uprintf "%s" prompt else dropPrompt <- dropPrompt - 1
let prompt =
if fsiOptions.UseServerPrompt then
"SERVER-PROMPT>" + Environment.NewLine
else
"> "

member _.Print() =
if showPrompt then
if dropPrompt = 0 then
fsiConsoleOutput.uprintf "%s" prompt
else
dropPrompt <- dropPrompt - 1

member _.PrintAhead() =
if showPrompt then
dropPrompt <- dropPrompt + 1
fsiConsoleOutput.uprintf "%s" prompt

member _.PrintAhead() = dropPrompt <- dropPrompt + 1; fsiConsoleOutput.uprintf "%s" prompt
// Can be turned off when executing blocks of code using:
// # silentPrompt
member _.ShowPrompt
with get () = showPrompt
and set (value) = showPrompt <- value

member _.SkipNext() = dropPrompt <- dropPrompt + 1
member _.SkipNext() =
if showPrompt then
dropPrompt <- dropPrompt + 1

member _.FsiOptions = fsiOptions

Expand Down Expand Up @@ -2772,6 +2795,15 @@ type FsiInteractionProcessor
fsiConsolePrompt.SkipNext() (* "silent" directive *)
istate, Completed None

| ParsedHashDirective("interactiveprompt", ParsedHashDirectiveArguments ["show" | "hide" | "skip" as showPrompt], m) ->
match showPrompt with
| "show" -> fsiConsolePrompt.ShowPrompt <- true
| "hide" -> fsiConsolePrompt.ShowPrompt <- false
| "skip" -> fsiConsolePrompt.SkipNext()
| _ -> error(Error((FSComp.SR.fsiInvalidDirective("prompt", String.concat " " [showPrompt])), m))

istate, Completed None

| ParsedHashDirective("dbgbreak", [], _) ->
let istate = {istate with debugBreak = true}
istate, Completed None
Expand Down Expand Up @@ -3072,7 +3104,7 @@ type FsiInteractionProcessor

// After we've unblocked and got something to run we switch
// over to the run-thread (e.g. the GUI thread)
let res = istate |> runCodeOnMainThread (fun ctok istate -> ExecuteParsedInteractionOnMainThread (ctok, diagnosticsLogger, action, istate, cancellationToken))
let res = istate |> runCodeOnMainThread (fun ctok istate -> ExecuteParsedInteractionOnMainThread (ctok, diagnosticsLogger, action, istate, cancellationToken))

if progress then fprintfn fsiConsoleOutput.Out "Just called runCodeOnMainThread, res = %O..." res
res)
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Service/ServiceLexing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, maxLength: int option, fi
| true, "savedll"
| true, "nosavedll"
#endif
| true, "interactiveprompt"
| true, "silentCd"
| true, "q"
| true, "quit"
Expand Down
25 changes: 12 additions & 13 deletions vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs
Original file line number Diff line number Diff line change
Expand Up @@ -534,17 +534,16 @@ type internal FsiToolWindow() as this =
executeTextNoHistory null text
with _ -> ()

let executeInteraction dbgBreak dir (filename: string) topLine text =
// Preserving previous functionality, including the #directives...
let interaction =
"\n"
+ (sprintf "# silentCd @\"%s\" ;; " dir) + "\n"
+ (if dbgBreak then "# dbgbreak\n" else "")
+ (sprintf "# %d @\"%s\" " topLine filename) + "\n"
+ text + "\n"
+ "# 1 \"stdin\"" + "\n" (* stdin line number reset code *)
+ ";;" + "\n"

let executeInteraction dbgBreak dir filename topLine (text:string) =
let interaction = $"""
#interactiveprompt "hide"
#silentCd @"{dir}";;
{if dbgBreak then "#dbgbreak" else ""}
#{topLine} @"{filename}"
{text.ToString()}
#1 "stdin"
#interactiveprompt "show";;
"""
executeTextNoHistory filename interaction

let sendSelectionToFSI action =
Expand All @@ -555,8 +554,8 @@ type internal FsiToolWindow() as this =
| DebugSelection -> true, false

try
let dte = provider.GetService(typeof<DTE>) :?> DTE
let activeD = dte.ActiveDocument
let dte = provider.GetService(typeof<DTE>) :?> DTE
let activeD = dte.ActiveDocument
match activeD.Selection with
| :? TextSelection as selection when selectLine || selection.Text = "" ->
selection.SelectLine()
Expand Down

0 comments on commit 186d3f6

Please sign in to comment.