Skip to content

Commit 60bce89

Browse files
Merge pull request #34 from ionide/fsformatting
Add F# Formatting and WebPreview
2 parents 802fbe8 + 828aa32 commit 60bce89

File tree

12 files changed

+239
-9
lines changed

12 files changed

+239
-9
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
release/bin
2+
release/bin_ff
23

34
# Logs
45
logs
@@ -63,3 +64,4 @@ temp
6364
.orig
6465
release.cmd
6566
paket-files
67+
issueList.md

build.fsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ open Fake.ReleaseNotesHelper
1414
open Fake.ZipHelper
1515

1616
#load "src/vscode-bindings.fsx"
17+
#load "src/Core/Bindings.fs"
1718
#load "src/Core/DTO.fs"
1819
#load "src/Core/LanguageService.fs"
1920
#load "src/Components/Linter.fs"
@@ -25,6 +26,8 @@ open Fake.ZipHelper
2526
#load "src/Components/Outline.fs"
2627
#load "src/Components/Fsi.fs"
2728
#load "src/Components/QuickInfo.fs"
29+
#load "src/Components/FSharpFormatting.fs"
30+
#load "src/Components/Webpreview.fs"
2831
#load "src/fsharp.fs"
2932
#load "src/main.fs"
3033

@@ -92,14 +95,25 @@ Target "RunScript" (fun () ->
9295
let releaseBin = "release/bin"
9396
let fsacBin = "paket-files/github.com/ionide/FsAutoComplete/bin/release"
9497

98+
9599
Target "CopyFSAC" (fun _ ->
96100
ensureDirectory releaseBin
97101
CleanDir releaseBin
98102

99103
!! (fsacBin + "/*")
100-
|> CopyFiles releaseBin
104+
|> CopyFiles releaseBin
101105
)
102106

107+
let releaseBinFF = "release/bin_ff"
108+
let ffbin = "paket-files/github.com/ionide/FSharpFormatting.CLI/build"
109+
110+
Target "CopyFSharpFormatting" (fun _ ->
111+
ensureDirectory releaseBinFF
112+
CleanDir releaseBinFF
113+
114+
!! (ffbin + "/*")
115+
|> CopyFiles releaseBinFF
116+
)
103117

104118
Target "InstallVSCE" ( fun _ ->
105119
killProcess "npm"
@@ -125,7 +139,7 @@ Target "BuildPackage" ( fun _ ->
125139
|> Seq.iter(MoveFile "./temp/")
126140
)
127141

128-
Target "PublishToGallery" ( fun _ ->
142+
Target "PublishToGallery" ( fun _ ->
129143
let token =
130144
match getBuildParam "vsce-token" with
131145
| s when not (String.IsNullOrWhiteSpace s) -> s
@@ -179,7 +193,8 @@ Target "Release" DoNothing
179193

180194
"Clean"
181195
==> "RunScript"
182-
==> "CopyFSAC"
196+
//==> "CopyFSAC"
197+
==> "CopyFSharpFormatting"
183198
==> "Default"
184199

185200
"Default"

paket.dependencies

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
source https://nuget.org/api/v2
22

33
git [email protected]:ionide/ionide-vscode-helpers.git master build:"build.cmd"
4+
git [email protected]:ionide/FSharpFormatting.CLI.git master build:"build.cmd"
45
git [email protected]:ionide/FsAutoComplete.git master build:"build.cmd LocalRelease"
56

67

paket.lock

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ GIT
1919
specs:
2020
(b81a80ede2179222a5639cf866423d9bc6c2f0b4)
2121
build: build.cmd
22-
remote: [email protected]:ionide/ionide-fsgrammar.git
22+
remote: [email protected]:ionide/FSharpFormatting.CLI.git
2323
specs:
24-
(7672ca5d35651c899fa9c095db5e94d45cb9f0ba)
24+
(dda1756ab2a9af5cacb084da29a81f772277174c)
25+
build: build.cmd
2526
remote: [email protected]:ionide/FsAutoComplete.git
2627
specs:
27-
(43364293eb5da2eb8599aa2d70324324b3b1adbb)
28+
(e8fdda0e620b58d687f1d758ecec9c3683379735)
2829
build: build.cmd LocalRelease
2930
GITHUB
3031
remote: fsharp/FAKE

release/package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
},{
4343
"command": "fsi.SendFile",
4444
"title": "FSI: Send File"
45+
},{
46+
"command": "ff.Show",
47+
"title": "F# Formatting: Show"
48+
},{
49+
"command": "webpreview.Show",
50+
"title": "Ionide: Show Web View"
51+
}
52+
,{
53+
"command": "webpreview.Refresh",
54+
"title": "Ionide: Refresh Web View"
4555
}],
4656
"outputChannels": [
4757
"F# Interactive"
@@ -67,7 +77,8 @@
6777
"vscode.fsharp"
6878
],
6979
"dependencies": {
70-
"xhr2": "*"
80+
"xhr2": "*",
81+
"toml": "*"
7182
},
7283
"devDependencies": {
7384
"vscode": "*"

src/Components/FSharpFormatting.fs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
namespace Ionide.VSCode.FSharp
2+
3+
open System
4+
open FunScript
5+
open FunScript.TypeScript
6+
open FunScript.TypeScript.vscode
7+
open FunScript.TypeScript.vscode.languages
8+
open FunScript.TypeScript.child_process
9+
open FunScript.TypeScript.fs
10+
11+
open DTO
12+
open Ionide.VSCode.Helpers
13+
14+
[<ReflectedDefinition>]
15+
module FSharpFormatting =
16+
17+
[<FunScript.JSEmitInline "(vscode.workspace.registerTextDocumentContentProvider({0}, {1}))">]
18+
let registerTextDocumentContentProvider(scheme : string, provider : TextDocumentContentProvider) : Disposable = failwith "JS"
19+
20+
let private path = (VSCode.getPluginPath "Ionide.Ionide-fsharp") + "/bin_ff/FSharpFormattingCLI.exe"
21+
let private output = (VSCode.getPluginPath "Ionide.Ionide-fsharp") + "/temp/temp.html"
22+
let private eventEmitter = EventEmitter.Create ()
23+
let private previewUri = Uri.parse "fsharpformatting://preview"
24+
25+
26+
let private update = eventEmitter.fire
27+
28+
let private createProvider () =
29+
let provider = createEmpty<TextDocumentContentProvider> ()
30+
31+
let generate () =
32+
let editor = vscode.window.Globals.activeTextEditor
33+
let file = editor.document.fileName
34+
35+
Process.exec path "mono" (sprintf "%s %s" file output)
36+
|> Promise.success (fun (e,i,o) ->
37+
38+
let style = "height: 100%; width: 100%; background-color: white;"
39+
sprintf "<iframe style='%s' src='file:///%s' />" style output
40+
41+
// fs.Globals.readFileSync output |> fun b ->b.ToString()
42+
)
43+
|> Promise.toThenable
44+
45+
provider.``provideTextDocumentContent <-``((fun _ -> generate ()) |> unbox<_>)
46+
provider.onDidChange <- eventEmitter.event
47+
provider
48+
49+
let show () =
50+
vscode.commands.Globals.executeCommandOverload2("vscode.previewHtml", previewUri, 2)
51+
52+
let activate (disposables: Disposable[]) =
53+
let prov = createProvider ()
54+
registerTextDocumentContentProvider("fsharpformatting", prov) |> ignore
55+
56+
workspace.Globals.onDidSaveTextDocument
57+
|> EventHandler.add (fun _ -> eventEmitter.fire previewUri) () disposables
58+
59+
commands.Globals.registerCommand("ff.Show", show |> unbox) |> ignore
60+
61+
()

src/Components/Outline.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ module Outline =
2525
| "F" -> 7
2626
| "T" -> 4
2727
| _ -> 0
28-
29-
28+
29+
3030
provider.``provideDocumentSymbols <-`` (fun doc _ ->
3131
LanguageService.declarations doc.fileName
3232
|> Promise.success (fun (o : DeclarationResult) ->

src/Components/WebPreview.fs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
namespace Ionide.VSCode.FSharp
2+
3+
open System
4+
open FunScript
5+
open FunScript.TypeScript
6+
open FunScript.TypeScript.vscode
7+
open FunScript.TypeScript.vscode.languages
8+
open FunScript.TypeScript.child_process
9+
open FunScript.TypeScript.fs
10+
11+
open DTO
12+
open Ionide.VSCode
13+
open Ionide.VSCode.Helpers
14+
15+
16+
[<ReflectedDefinition>]
17+
module WebPreview =
18+
[<FunScript.JSEmitInline "(vscode.workspace.registerTextDocumentContentProvider({0}, {1}))">]
19+
let registerTextDocumentContentProvider(scheme : string, provider : TextDocumentContentProvider) : Disposable = failwith "JS"
20+
21+
let private previewUri = Uri.parse "webpreview://preview"
22+
let private eventEmitter = EventEmitter.Create ()
23+
let private update = eventEmitter.fire
24+
25+
26+
let mutable linuxPrefix = ""
27+
let mutable command = "packages/FAKE/tools/FAKE.exe"
28+
let mutable host = ""
29+
let mutable port = 8083
30+
let mutable script = ""
31+
let mutable build = ""
32+
let mutable startString = ""
33+
let mutable parameters = [||]
34+
let mutable startingPage = ""
35+
let mutable fakeProcess : ChildProcess Option = None
36+
37+
38+
39+
40+
let loadSettings () =
41+
linuxPrefix <- Settings.loadOrDefault (fun s -> s.WebPreview.linuxPrefix) "mono"
42+
command <- Settings.loadOrDefault (fun s -> s.WebPreview.command) "packages/FAKE/tools/FAKE.exe"
43+
host <- Settings.loadOrDefault (fun s -> s.WebPreview.host) "localhost"
44+
port <- Settings.loadOrDefault (fun s -> s.WebPreview.port) 8888
45+
script <- Settings.loadOrDefault (fun s -> s.WebPreview.script) "build.fsx"
46+
build <- Settings.loadOrDefault (fun s -> s.WebPreview.build) "Serve"
47+
startString <- Settings.loadOrDefault (fun s -> s.WebPreview.startString) "listener started"
48+
parameters <- Settings.loadOrDefault (fun s -> s.WebPreview.parameters) [||]
49+
startingPage <- Settings.loadOrDefault (fun s -> s.WebPreview.startingPage) ""
50+
()
51+
52+
let private createProvider () =
53+
let provider = createEmpty<TextDocumentContentProvider> ()
54+
55+
let generate () =
56+
let src = sprintf "http://%s:%d/%s" host port startingPage
57+
let style = "height: 100%; width: 100%; background-color: white;"
58+
sprintf "<iframe style='%s' src='%s' />" style src
59+
60+
provider.``provideTextDocumentContent <-``((fun _ -> generate ()) |> unbox<_>)
61+
provider.onDidChange <- eventEmitter.event
62+
provider
63+
64+
let parseResponse o =
65+
if JS.isDefined o && o <> null then
66+
let str = o.ToString ()
67+
if str.Contains startString then
68+
vscode.commands.Globals.executeCommandOverload2("vscode.previewHtml", previewUri, 2)
69+
|> ignore
70+
Globals.console.log <| o.ToString ()
71+
()
72+
73+
let close () =
74+
try
75+
fakeProcess |> Option.iter (fun p ->
76+
p.kill ()
77+
fakeProcess <- None)
78+
with
79+
| _ -> ()
80+
81+
let show () =
82+
loadSettings ()
83+
if fakeProcess.IsSome then close ()
84+
let cp =
85+
let args = sprintf "%s %s port=%d" script build port
86+
let args' = parameters |> Array.fold (fun acc e -> acc + " " + e) args
87+
Process.spawn command linuxPrefix args'
88+
89+
cp.stdout.on ("readable", unbox<Function> (cp.stdout.read >> parseResponse )) |> ignore
90+
cp.stderr.on ("readable", unbox<Function> (cp.stdout.read >> (fun o -> if JS.isDefined o && o <> null then Globals.console.error <| o.ToString ()) )) |> ignore
91+
fakeProcess <- Some cp
92+
93+
94+
95+
let activate (disposables : Disposable[]) =
96+
let prov = createProvider ()
97+
registerTextDocumentContentProvider("webpreview", prov) |> ignore
98+
99+
commands.Globals.registerCommand("webpreview.Show", show |> unbox) |> ignore
100+
commands.Globals.registerCommand("webpreview.Refresh", (fun _ -> eventEmitter.fire previewUri) |> unbox) |> ignore
101+
()

src/Core/Bindings.fs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace FunScript.TypeScript.vscode
2+
3+
open System
4+
open FunScript
5+
open FunScript.TypeScript
6+
open FunScript.TypeScript.vscode
7+
8+
type TextDocumentContentProvider = interface end
9+
type EventEmitter<'T> = interface end
10+
11+
[<AutoOpen>]
12+
module Bindings =
13+
14+
type TextDocumentContentProvider with
15+
[<FunScript.JSEmitInline "({0}.provideTextDocumentContent({1}, {2}))">]
16+
member __.provideTextDocumentContent(uri : Uri, token : CancellationToken) : Thenable<string> = failwith "JS"
17+
[<FunScript.JSEmitInline "({0}.provideTextDocumentContent = {1})">]
18+
member __.``provideTextDocumentContent <-``(func : System.Func<Uri* CancellationToken , Thenable<string>>) : unit = failwith "JS"
19+
20+
[<FunScript.JSEmitInline "({0}.onDidChange)">]
21+
member __.onDidChange with get() : vscode.Event<Uri> = failwith "JS" and set (v : vscode.Event<Uri>) : unit = failwith "JS"
22+
23+
type EventEmitter<'T> with
24+
[<FunScript.JSEmitInline "({0}.event)">]
25+
member __.event : vscode.Event<'T> = failwith "JS"
26+
27+
[<FunScript.JSEmitInline "({0}.fire({1}))">]
28+
member __.fire(a : 'T) : unit = failwith "JS"
29+
30+
[<FunScript.JSEmitInline "(new vscode.EventEmitter())">]
31+
static member Create() : EventEmitter<'T> = failwith "JS"
32+

src/Ionide.FSharp.fsproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets" />
3535
<ItemGroup>
3636
<None Include="paket.references" />
37+
<Compile Include="Core\Bindings.fs" />
3738
<Compile Include="Core\DTO.fs" />
3839
<Compile Include="Core\LanguageService.fs" />
3940
<Compile Include="Components\Linter.fs" />
@@ -45,6 +46,8 @@
4546
<Compile Include="Components\Outline.fs" />
4647
<Compile Include="Components\Fsi.fs" />
4748
<Compile Include="Components\QuickInfo.fs" />
49+
<Compile Include="Components\FSharpFormatting.fs" />
50+
<Compile Include="Components\WebPreview.fs" />
4851
<Compile Include="fsharp.fs" />
4952
<Compile Include="main.fs" />
5053
<None Include="vscode-bindings.fsx" />

0 commit comments

Comments
 (0)