Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,7 @@ fsacpath.txt
/out/

build/bin
build/obj
build/obj

# include vscode ui toolkit minified release file
!release/toolkit.min.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super weird - can you add not a reference to the toolkit and let webpack pull it in (I'm just skimming their getting started docs)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried following the getting started from the toolkit but their getting started assumes the directory where you launch your extension is the root of the project (hence why it had node_modules available), in our case the release directory is the root so we don't have access to node_modules, we'd likely need to do some webpack magic to pull this script at dev/build which was the part I couldn't figure out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. I'd also be ok longer term with removing the release split. It's just confusing IMO.

30 changes: 30 additions & 0 deletions release/toolkit.min.js

Large diffs are not rendered by default.

236 changes: 117 additions & 119 deletions src/Components/Fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -60,39 +60,28 @@ module Fsi =
()

module Watcher =
open Webviews
let mutable panel: WebviewPanel option = None

let setContent str =
panel
|> Option.iter (fun p ->
let str =
sprintf
"""
<html>
<head>
<meta>
<style>
table { border-collapse: collapse;}
th {
border-left: 1px solid var(--vscode-editor-foreground);
border-right: 1px solid var(--vscode-editor-foreground);
padding: 5px;
}
td {
border: 1px solid var(--vscode-editor-foreground);
min-width: 100px;
padding: 5px;
}
</style>
</head>
<body>
%s
</body>
</html>
"""
str

p.webview.html <- str)
let updateContent
(context: ExtensionContext)
(varsContent: (string * string) option)
(typesContent: (string * string) option)
(funcsContent: (string * string) option)
=
let (vars, varsScript) = defaultArg varsContent ("", "")
let (types, typesScript) = defaultArg typesContent ("", "")
let (funcs, funcsScript) = defaultArg funcsContent ("", "")

match panel with
| Some panel ->
FsWebview.render (
context,
panel,
$"{vars}{types}{funcs}",
scripts = [ varsScript; typesScript; funcsScript ]
)
| None -> ()

let openPanel () =
promise {
Expand All @@ -113,16 +102,21 @@ module Fsi =
match panel with
| Some p -> p.reveal (!! -2, true)
| None ->
let opts =
createObj [ "enableCommandUris" ==> true
"enableFindWidget" ==> true
"retainContextWhenHidden" ==> true ]

let viewOpts =
createObj [ "preserveFocus" ==> true
"viewColumn" ==> -2 ]

let p = window.createWebviewPanel ("fsiWatcher", "FSI Watcher", !!viewOpts, opts)
let p =
FsWebview.create (
"fsiWatcher",
"FSI Watcher",
!!viewOpts,
enableScripts = true,
enableFindWidget = true,
enableCommandUris = true,
retainContextWhenHidden = true
)

let onClose () = panel <- None

p.onDidDispose.Invoke(!!onClose) |> ignore
Expand All @@ -138,42 +132,44 @@ module Fsi =
path.join (VSCodeExtension.ionidePluginPath (), "watcher", "funcs.txt")


let handler () =
let mutable varsContent = ""
let mutable typesContent = ""
let mutable funcsContent = ""

let handler (context: ExtensionContext) =
let mutable varsContent = None
let mutable typesContent = None
let mutable funcsContent = None

node.fs.readFile (
varsUri,
(fun _ buf ->
if not (Utils.isUndefined buf) then
let cnt = buf.ToString()

varsContent <-
cnt
|> String.split [| '\n' |]
|> Seq.map (fun row ->
let x = row.Split([| "###IONIDESEP###" |], StringSplitOptions.None)

sprintf
"<tr><td>%s</td><td><code>%s</code></td><td><code>%s</code></td><td>%s</td></tr>"
x.[0]
x.[1]
x.[2]
x.[3])
|> String.concat "\n"
|> sprintf
"""</br><h3>Declared values</h3></br><table style="width:100%%"><tr><th style="width: 12%%">Name</th><th style="width: 65%%">Value</th><th style="width: 20%%">Type</th><th>Step</th></tr>%s</table>"""


setContent (
varsContent
+ "\n\n"
+ funcsContent
+ "\n\n"
+ typesContent
))
if String.IsNullOrWhiteSpace cnt then
varsContent <- None
else

let datagridContent =
cnt
|> String.split [| '\n' |]
|> Array.map (fun row ->
let x = row.Split([| "###IONIDESEP###" |], StringSplitOptions.None)

box
{| name = x[0]
value = x[1]
Type = x[2]
step = x[3] |})
// ensure column order
let headers =
[| "Name", "name"
"Value", "value"
"Type", "Type"
"Step", "step" |]

let grid, script = VsHtml.datagrid ("vars-content", datagridContent, headers)

varsContent <- Some(html $"<h3>Declared values</h3>{grid}", script)

updateContent context varsContent typesContent funcsContent)
)

node.fs.readFile (
Expand All @@ -182,30 +178,33 @@ module Fsi =
if not (Utils.isUndefined buf) then
let cnt = buf.ToString()

funcsContent <-
cnt
|> String.split [| '\n' |]
|> Seq.map (fun row ->
let x = row.Split([| "###IONIDESEP###" |], StringSplitOptions.None)

sprintf
"<tr><td>%s</td><td><code>%s</code></td><td><code>%s</code></td><td>%s</td></tr>"
x.[0]
x.[1]
x.[2]
x.[3])
|> String.concat "\n"
|> sprintf
"""</br><h3>Declared functions</h3></br><table style="width:100%%"><tr><th style="width: 12%%">Name</th><th style="width: 65%%">Parameters</th><th style="width: 20%%">Returned type</th><th>Step</th></tr>%s</table>"""


setContent (
varsContent
+ "\n\n"
+ funcsContent
+ "\n\n"
+ typesContent
))
if String.IsNullOrWhiteSpace cnt then
funcsContent <- None
else
let datagridContent =
cnt
|> String.split [| '\n' |]
|> Array.map (fun row ->
let x = row.Split([| "###IONIDESEP###" |], StringSplitOptions.None)

box
{| name = x[0]
parameters = x[1]
returnType = x[2]
step = x[3] |})

let grid, script =
VsHtml.datagrid (
"funcs-content",
datagridContent,
[| "Name", "name"
"Parameters", "parameters"
"Return Type", "returnType" |]
)

funcsContent <- Some(html $"<h3>Declared functions</h3>{grid}", script)

updateContent context varsContent typesContent funcsContent)
)

node.fs.readFile (
Expand All @@ -214,40 +213,39 @@ module Fsi =
if not (Utils.isUndefined buf) then
let cnt = buf.ToString()

typesContent <-
if String.IsNullOrWhiteSpace cnt then
""
else
if String.IsNullOrWhiteSpace cnt then
typesContent <- None
else
let extractSignature (str: string) =
if str.Contains "#|#" then
"| " + str.Replace("#|#", "</br>| ")
else
str

let datagridContent =
cnt
|> String.split [| '\n' |]
|> Seq.map (fun row ->
|> Array.map (fun row ->
let x = row.Split([| "###IONIDESEP###" |], StringSplitOptions.None)

let signature =
if x.[1].Contains "#|#" then
"| " + x.[1].Replace("#|#", "</br>| ")
else
x.[1]

sprintf "<tr><td>%s</td><td><code>%s</code></td><td>%s</td></tr>" x.[0] signature x.[2])
|> String.concat "\n"
|> sprintf
"""</br><h3>Declared types</h3></br><table style="width:100%%"><tr><th style="width: 12%%">Name</th><th style="width: 85%%">Signature</th><th>Step</th></tr>%s</table>"""


setContent (
varsContent
+ "\n\n"
+ funcsContent
+ "\n\n"
+ typesContent
))
let signature = extractSignature x[1]

box
{| Name = x[0]
Signature = signature
Step = x[2] |})

let grid, script = VsHtml.datagrid ("types-content", datagridContent)

typesContent <- Some(html $"<h3>Declared types</h3>{grid}", script)

updateContent context varsContent typesContent funcsContent)
)

let activate dispsables =
fs.watchFile (varsUri, (fun st st2 -> handler ()))
fs.watchFile (typesUri, (fun st st2 -> handler ()))
fs.watchFile (funcUri, (fun st st2 -> handler ()))
let activate context dispsables =
fs.watchFile (varsUri, (fun st st2 -> handler context))
fs.watchFile (typesUri, (fun st st2 -> handler context))
fs.watchFile (funcUri, (fun st st2 -> handler context))

let mutable fsiOutput: Terminal option = None
let mutable fsiOutputPID: int option = None
Expand Down Expand Up @@ -632,7 +630,7 @@ module Fsi =
}

let activate (context: ExtensionContext) =
Watcher.activate (!!context.subscriptions)
Watcher.activate context (!!context.subscriptions)
SdkScriptsNotify.activate context

window.registerTerminalProfileProvider ("ionide-fsharp.fsi", provider)
Expand Down
Loading