anchor.diff:                  | U2.Case1 opts -> window.createTerminal opts
                   | U2.Case2 opts -> window.createTerminal opts
   
  -            terminal.show (true)
  -            return terminal
  +            // Wait for the new terminal to be ready
  +            let! newTerminal =
  +                Promise.create (fun resolve reject ->
  +                    window.onDidOpenTerminal.Invoke(fun (terminal: Terminal) ->
  +                        if terminal.name = fsiNetCoreName || terminal.name = fsiNetFrameworkName then
  +                            // It can happens that a new terminal is created before the old one is closed
  +                            // In that case, we need to close the old one first
  +                            // This case occures when user invoke "FSI: Start" commands with an existing FSI terminal
  +                            match fsiTerminal with
  +                            | Some fsiOutput -> fsiOutput.dispose ()
  +                            | None -> ()
  +
  +                            // Return the new terminal
  +                            resolve terminal
  +
  +                        None)
  +                    |> ignore)
  +
  +            newTerminal.show true
  +
  +            // Set up the new terminal state
  +            let! terminalId = Promise.ofThenable newTerminal.processId
  +
  +            fsiTerminalPID <- Option.map int terminalId
  +
  +            // Reset global information
  +            lastCd <- None
  +            lastCurrentFile <- None
  +            fsiTerminal <- Some terminal
  +
  +            // initially have to set up the terminal to be in the correct start directory
  +            sendCd newTerminal window.activeTextEditor
  +
  +            return newTerminal
           }
           |> Promise.onFail (fun _ ->
               window.showErrorMessage ("Failed to spawn FSI, please ensure it's in PATH")
               |> ignore)
   
  -    let private chunkStringBySize (size: int) (str: string) =
  -        let mutable i1 = 0
  -
  -        [ while i1 < str.Length do
  -              let i2 = min (i1 + size) (str.Length)
  -              yield str.[i1 .. i2 - 1]
  -              i1 <- i2 ]
  -
  -    let private send (msg: string) =
  -        let msgWithNewline = msg + (if msg.Contains "//" then "\n" else "") + ";;\n"
  -
  -        match fsiOutput with
  -        | None -> start ()
  -        | Some fo -> Promise.lift fo
  -        |> Promise.onSuccess (fun fp ->
  -            fp.show true
  -            fp.sendText (msgWithNewline, false)
  -            lastSelectionSent <- Some msg)
  +    let private getTerminal () =
  +        promise {
  +
  +            let! terminal =
  +                match fsiTerminal with
  +                // No terminal found, spawn a new one
  +                | None -> start ()
  +                // A terminal already exists, re-use it
  +                | Some terminal -> Promise.lift terminal
  +
  +            terminal.show true
  +
  +            return terminal
  +        }
  +
  +    let private send (terminal: Terminal) (msg: string) =
  +        let msgWithNewline = msg + (if msg.Contains "//" then "\n" else "") + ";;\n" // TODO: Useful ??
  +
  +        promise {
  +            terminal.sendText (msgWithNewline, false)
  +            lastSelectionSent <- Some msg
  +        }
           |> Promise.onFail (fun _ -> window.showErrorMessage ("Failed to send text to FSI") |> ignore)
  +        |> Promise.suppress
  +        |> Promise.map ignore
   
       let private moveCursorDownOneLine () =
  -        let args = createObj [ "to" ==> "down"; "by" ==> "line"; "value" ==> 1 ]
  -
  -        commands.executeCommand ("cursorMove", Some(box args)) |> ignore
  +        let args =
  +            {| ``to`` = "down"
  +               by = "line"
  +               value = 1 |}
  +
  +        commands.executeCommand ("cursorMove", Some(box args)) |> Promise.ofThenable
   
       let private sendLine () =
           let editor = window.activeTextEditor.Value
  -        let _ = editor.document.fileName
  -        let pos = editor.selection.start
  -        let line = editor.document.lineAt pos
  -        sendCd (Some editor)
  -
  -        send line.text
  -        |> Promise.onSuccess (fun _ -> moveCursorDownOneLine ())
  -        |> Promise.suppress // prevent unhandled promise exception
  -        |> ignore
  +
  +        promise {
  +            let! terminal = getTerminal ()
  +
  +            let pos = editor.selection.start
  +            let line = editor.document.lineAt pos
  +
  +            sendCd terminal (Some editor)
  +
  +            do! send terminal line.text
  +            do! moveCursorDownOneLine ()
  +        }
   
       let private sendSelection () =
           let editor = window.activeTextEditor.Value
  -        let _ = editor.document.fileName
  -
  -        sendCd (Some editor)
  -
  -        if editor.selection.isEmpty then
  -            sendLine ()
  -        else
  -            let range =
  -                vscode.Range.Create(
  -                    editor.selection.anchor.line,
  -                    editor.selection.anchor.character,
  -                    editor.selection.active.line,
  -                    editor.selection.active.character
  -                )
  -
  -            let text = editor.document.getText range
  -
  -            send text
  -            |> Promise.suppress // prevent unhandled promise exception
  -            |> ignore
  +
  +        promise {
  +            if editor.selection.isEmpty then
  +                do! sendLine ()
  +            else
  +                // Note: Handle terminal stuff only in this part of the if/else branch
  +                // because sendLine will already handle it for the other branch
  +
  +                let! terminal = getTerminal ()
  +
  +                sendCd terminal (Some editor)
  +
  +                let range =
  +                    vscode.Range.Create(
  +                        editor.selection.anchor.line,
  +                        editor.selection.anchor.character,
  +                        editor.selection.active.line,
  +                        editor.selection.active.character
  +                    )
  +
  +                let text = editor.document.getText range
  +
  +                do! send terminal text
  +        }
   
       let private sendLastSelection () =
  -        match lastSelectionSent with
  -        | Some x ->
  -            if "FSharp.saveOnSendLastSelection" |> Configuration.get false then
  -                window.activeTextEditor.Value.document.save () |> Promise.ofThenable
  -            else
  -                Promise.lift true
  -            |> Promise.bind (fun _ -> send x)
  -            |> Promise.suppress // prevent unhandled promise exception
  -            |> ignore
  -        | None -> ()
  +        promise {
  +            match lastSelectionSent with
  +            | Some lastSelectionText ->
  +                // If configuration is set to save before sending, save the file
  +                if "FSharp.saveOnSendLastSelection" |> Configuration.get false then
  +                    let! _ = window.activeTextEditor.Value.document.save () |> Promise.ofThenable
  +                    ()
  +
  +                let! terminal = getTerminal ()
  +
  +                do! send terminal lastSelectionText
  +            | None -> ()
  +        }
   
       let private sendFile () =
           let editor = window.activeTextEditor.Value
           let text = editor.document.getText ()
  -        sendCd (Some editor)
  -
  -        send text
  +
  +        promise {
  +            let! terminal = getTerminal ()
  +
  +            sendCd terminal (Some editor)
  +            do! send terminal text
  +        }
  +
  +    let private handleCloseTerminal (terminal: Terminal) =
  +        promise {
  +            match fsiTerminalPID with
  +            // There is an FSI terminal active, check if it's the one that was closed
  +            | Some currentTerminalPID ->
  +                let! closeTerminalPID = Promise.ofThenable terminal.processId
  +
  +                if Option.map int closeTerminalPID = Some currentTerminalPID then
  +                    fsiTerminal <- None
  +                    fsiTerminalPID <- None
  +                    lastCd <- None
  +                    lastCurrentFile <- None
  +
  +            // No existing terminal, ignore
  +            | None -> ()
  +        }
           |> Promise.suppress // prevent unhandled promise exception
  -        |> ignore
  -
  -    let private sendText (lines: string list) =
  -        send (String.concat ";;\n" lines)
  -        |> Promise.suppress // prevent unhandled promise exception
  -        |> ignore
  -
  -    let private referenceAssembly (path: ResolvedReferencePath) = path |> sprintf "#r @\"%s\"" |> send
  -    let private referenceAssemblies = Promise.executeForAll referenceAssembly
  -
  -    let private sendReferences () =
  -        window.activeTextEditor.Value.document.fileName
  -        |> Project.tryFindLoadedProjectByFile
  -        |> Option.iter (fun p ->
  -            sendCd window.activeTextEditor
  -
  -            p.References
  +        |> Promise.start // Start the promise without waiting for it to complete
  +
  +        None
  +
  +    let sendReferencesForProject project =
  +        let references =
  +            project.References
               |> Seq.filter (fun n -> n.EndsWith "FSharp.Core.dll" |> not && n.EndsWith "mscorlib.dll" |> not)
               |> Seq.toList
  -            |> referenceAssemblies
  -            |> Promise.suppress
  -            |> ignore)
  -
  -
  -    let private clearOldTerminalState () =
  -        fsiOutput |> Option.iter (fun t -> t.dispose ())
  -
  -    let private handleCloseTerminal (terminal: Terminal) =
  -        fsiOutputPID
  -        |> Option.iter (fun currentTerminalPID ->
  -            terminal.processId
  -            |> Promise.ofThenable
  -            |> Promise.onSuccess (fun closedTerminalPID ->
  -                if Option.map int closedTerminalPID = Some currentTerminalPID then
  -                    fsiOutput <- None
  -                    fsiOutputPID <- None
  -                    lastCd <- None
  -                    lastCurrentFile <- None)
  -            |> Promise.suppress // prevent unhandled promise exception
  -            |> ignore)
  +
  +        let sendReference terminal (path: ResolvedReferencePath) = send terminal $"#r @\"%s{path}\""
  +
  +        promise {
  +            let! terminal = getTerminal ()
  +
  +            do! Promise.executeForAll (sendReference terminal) references
  +        }
  +        |> Promise.suppress
           |> ignore
   
  -        None
  -
  -    // when a new terminal is created, if it's FSI and if we don't already have a terminal then setup the state for tracking FSI
  -    let private handleOpenTerminal (terminal: Terminal) =
  -        if terminal.name = fsiNetCoreName || terminal.name = fsiNetFrameworkName then
  -            clearOldTerminalState ()
  -            setupTerminalState terminal
  -            // initially have to set up the terminal to be in the correct start directory
  -            sendCd window.activeTextEditor
  -
  -        None
  -
  -
  -    let private generateProjectReferences () =
  -        let ctn =
  +    let private sendReferences () =
  +        let projectOpt =
               window.activeTextEditor.Value.document.fileName
               |> Project.tryFindLoadedProjectByFile
  -            |> Option.map (fun p ->
  -                [| yield!
  -                       p.References
  -                       |> Seq.filter (fun n -> n.EndsWith "FSharp.Core.dll" |> not && n.EndsWith "mscorlib.dll" |> not)
  -                       |> Seq.map (sprintf "#r @\"%s\"")
  -                   yield! p.Files |> Seq.map (sprintf "#load @\"%s\"") |])
  -
  -        promise {
  -            match ctn with
  -            | Some c ->
  -                let path = node.path.join (workspace.rootPath.Value, "references.fsx")
  -
  -                let! td = vscode.Uri.parse ("untitled:" + path) |> workspace.openTextDocument
  -
  -                let! te = window.showTextDocument (td, ViewColumn.Three)
  -
  -                let! _ =
  -                    te.edit (fun e ->
  -                        let p = vscode.Position.Create(0., 0.)
  -                        let ctn = c |> String.concat "\n"
  -                        e.insert (p, ctn))
  -
  -
  -                return ()
  -            | None -> return ()
  -        }
  -
  -    let sendReferencesForProject project =
  -        project.References
  -        |> Seq.filter (fun n -> n.EndsWith "FSharp.Core.dll" |> not && n.EndsWith "mscorlib.dll" |> not)
  -        |> Seq.toList
  -        |> referenceAssemblies
  -        |> Promise.suppress
  -        |> ignore
  +
  +        match projectOpt with
  +        | Some project -> sendReferencesForProject project
  +        | None -> window.showErrorMessage ("File not in a project") |> ignore
   
       let generateProjectReferencesForProject project =
           let ctn =
  
positive.code: 
          let setUseSdk () =
              Configuration.setGlobal useKey (Some(box true))
  
  
          let checkForPatternsAndPromptUser () =
              promise {
  
negative.code:     let isSdk () =
          Configuration.get false "FSharp.useSdkScripts"
  
      let private sendCd (terminal: Terminal) (textEditor: TextEditor option) =
          let file, dir =
              match textEditor with
              | Some textEditor ->
  