@@ -12,6 +12,15 @@ let g:loaded_autoload_fsharp = 1
12
12
let s: cpo_save = &cpo
13
13
set cpo &vim
14
14
15
+
16
+ " basic setups
17
+
18
+ let s: script_root_dir = expand (' <sfile>:p:h' ) . " /../"
19
+
20
+ if has (' nvim-0.5' )
21
+ lua ionide = require (" ionide" )
22
+ endif
23
+
15
24
function ! s: prompt (msg)
16
25
let height = &cmdheight
17
26
if height < 2
@@ -21,6 +30,9 @@ function! s:prompt(msg)
21
30
let &cmdheight = height
22
31
endfunction
23
32
33
+
34
+ " FSAC payload interfaces
35
+
24
36
function ! s: PlainNotification (content)
25
37
return { ' Content' : a: content }
26
38
endfunction
@@ -80,8 +92,24 @@ function! s:FsdnRequest(query)
80
92
return { ' Query' : a: query }
81
93
endfunction
82
94
95
+
96
+ " LSP functions
97
+
83
98
function ! s: call (method, params, cont)
84
- call LanguageClient#Call (a: method , a: params , a: cont )
99
+ if g: fsharp #backend == ' languageclient-neovim'
100
+ call LanguageClient#Call (a: method , a: params , a: cont )
101
+ elseif g: fsharp #backend == ' nvim'
102
+ let key = fsharp#register_callback (a: cont )
103
+ call luaeval (' ionide.call(_A[1], _A[2], _A[3])' , [a: method , a: params , key ])
104
+ endif
105
+ endfunction
106
+
107
+ function ! s: notify (method, params)
108
+ if g: fsharp #backend == ' languageclient-neovim'
109
+ call LanguageClient#Notify (a: method , a: params )
110
+ elseif g: fsharp #backend == ' nvim'
111
+ call luaeval (' ionide.notify(_A[1], _A[2])' , [a: method , a: params ])
112
+ endif
85
113
endfunction
86
114
87
115
function ! s: signature (filePath, line , character , cont)
@@ -121,6 +149,9 @@ function! s:documentationSymbol(xmlSig, assembly, cont)
121
149
return s: call (' fsharp/documentationSymbol' , s: DocumentationForSymbolRequest (a: xmlSig , a: assembly ), a: cont )
122
150
endfunction
123
151
152
+
153
+ " FSAC configuration
154
+
124
155
" FSharpConfigDto from https://github.com/fsharp/FsAutoComplete/blob/master/src/FsAutoComplete/LspHelpers.fs
125
156
"
126
157
" * The following options seems not working with workspace/didChangeConfiguration
@@ -160,7 +191,7 @@ let s:config_keys_camel =
160
191
\ ]
161
192
let s: config_keys = []
162
193
163
- function ! fsharp# toSnakeCase (str)
194
+ function ! s: toSnakeCase (str)
164
195
let sn = substitute (a: str , ' \(\<\u\l\+\|\l\+\)\(\u\)' , ' \l\1_\l\2' , ' g' )
165
196
if sn == a: str | return tolower (a: str ) | endif
166
197
return sn
@@ -170,7 +201,7 @@ function! s:buildConfigKeys()
170
201
if len (s: config_keys ) == 0
171
202
for key_camel in s: config_keys_camel
172
203
let key = {}
173
- let key .snake = fsharp# toSnakeCase (key_camel.key )
204
+ let key .snake = s: toSnakeCase (key_camel.key )
174
205
let key .camel = key_camel.key
175
206
if has_key (key_camel, ' default' )
176
207
let key .default = key_camel.default
@@ -180,7 +211,7 @@ function! s:buildConfigKeys()
180
211
endif
181
212
endfunction
182
213
183
- function ! g: fsharp#getServerConfig ()
214
+ function ! fsharp#getServerConfig ()
184
215
let fsharp = {}
185
216
call s: buildConfigKeys ()
186
217
for key in s: config_keys
@@ -196,12 +227,76 @@ function! g:fsharp#getServerConfig()
196
227
return fsharp
197
228
endfunction
198
229
199
- function ! g: fsharp#updateServerConfig ()
230
+ function ! fsharp#updateServerConfig ()
200
231
let fsharp = fsharp#getServerConfig ()
201
232
let settings = {' settings' : {' FSharp' : fsharp}}
202
- call LanguageClient#Notify (' workspace/didChangeConfiguration' , settings)
233
+ call s: notify (' workspace/didChangeConfiguration' , settings)
234
+ endfunction
235
+
236
+
237
+ " handlers for notifications
238
+
239
+ let s: handlers = {
240
+ \ ' fsharp/notifyWorkspace' : ' fsharp#handle_notifyWorkspace' ,
241
+ \ }
242
+
243
+ function ! s: registerAutocmds ()
244
+ if g: fsharp #backend == ' nvim' && g: fsharp #lsp_codelens
245
+ augroup FSharp_AutoRefreshCodeLens
246
+ autocmd !
247
+ autocmd CursorHold ,InsertLeave <buffer> lua vim .lsp .codelens.refresh ()
248
+ augroup END
249
+ endif
250
+ if g: fsharp #backend != ' disable'
251
+ augroup FSharp_OnCursorMove
252
+ autocmd !
253
+ autocmd CursorMoved *.fs,*.fsi,*.fsx call fsharp#OnCursorMove ()
254
+ augroup END
255
+ endif
256
+ endfunction
257
+
258
+ function ! fsharp#initialize ()
259
+ echom ' [FSAC] Initialized'
260
+ if g: fsharp #backend == ' languageclient-neovim'
261
+ call LanguageClient_registerHandlers (s: handlers )
262
+ endif
263
+ call fsharp#updateServerConfig ()
264
+ call s: registerAutocmds ()
265
+ endfunction
266
+
267
+
268
+ " nvim-lsp specific functions
269
+
270
+ " handlers are picked up by ionide.setup()
271
+ function ! fsharp#get_handlers ()
272
+ return s: handlers
203
273
endfunction
204
274
275
+ let s: callbacks = {}
276
+
277
+ function ! fsharp#register_callback (fn)
278
+ if g: fsharp #backend != ' nvim'
279
+ return -1
280
+ endif
281
+ let rnd = reltimestr (reltime ())
282
+ let s: callbacks [rnd] = a: fn
283
+ return rnd
284
+ endfunction
285
+
286
+ function ! fsharp#resolve_callback (key , arg)
287
+ if g: fsharp #backend != ' nvim'
288
+ return
289
+ endif
290
+ if has_key (s: callbacks , a: key )
291
+ let Callback = s: callbacks [a: key ]
292
+ call Callback (a: arg )
293
+ call remove (s: callbacks , a: key )
294
+ endif
295
+ endfunction
296
+
297
+
298
+ " .NET/F# specific operations
299
+
205
300
function ! s: findWorkspace (dir , cont)
206
301
let s: cont_findWorkspace = a: cont
207
302
function ! s: callback_findWorkspace (result)
@@ -237,13 +332,20 @@ endfunction
237
332
238
333
let s: workspace = []
239
334
335
+ function ! fsharp#handle_notifyWorkspace (payload) abort
336
+ let content = json_decode (a: payload .content)
337
+ if content.Kind == ' projectLoading'
338
+ echom " [FSAC] Loading" content.Data.Project
339
+ let s: workspace = uniq (sort (add (s: workspace , content.Data.Project)))
340
+ elseif content.Kind == ' workspaceLoad' && content.Data.Status == ' finished'
341
+ echom printf (" [FSAC] Workspace loaded (%d project(s))" , len (s: workspace ))
342
+ call fsharp#updateServerConfig ()
343
+ endif
344
+ endfunction
345
+
346
+
240
347
function ! s: load (arg)
241
- let s: loading_workspace = a: arg
242
- function ! s: callback_load (_)
243
- echo " [FSAC] Workspace loaded: " . join (s: loading_workspace , ' , ' )
244
- let s: workspace = s: workspace + s: loading_workspace
245
- endfunction
246
- call s: workspaceLoad (a: arg , function (" s:callback_load" ))
348
+ call s: workspaceLoad (a: arg , v: null )
247
349
endfunction
248
350
249
351
function ! fsharp#loadProject (... )
@@ -254,23 +356,15 @@ function! fsharp#loadProject(...)
254
356
call s: load (prjs)
255
357
endfunction
256
358
257
- function ! fsharp#loadWorkspaceAuto ()
258
- if &ft == ' fsharp'
259
- call fsharp#updateServerConfig ()
260
- if g: fsharp #automatic_workspace_init
261
- echom " [FSAC] Loading workspace..."
262
- let bufferDirectory = fnamemodify (resolve (expand (' %:p' )), ' :h' )
263
- call s: findWorkspace (bufferDirectory, function (" s:load" ))
264
- endif
265
- endif
359
+ function ! fsharp#showLoadedProjects ()
360
+ for proj in s: workspace
361
+ echo " -" proj
362
+ endfor
266
363
endfunction
267
364
268
365
function ! fsharp#reloadProjects ()
269
366
if len (s: workspace ) > 0
270
- function ! s: callback_reloadProjects (_)
271
- call s: prompt (" [FSAC] Workspace reloaded." )
272
- endfunction
273
- call s: workspaceLoad (s: workspace , function (" s:callback_reloadProjects" ))
367
+ call s: workspaceLoad (s: workspace , v: null )
274
368
else
275
369
echom " [FSAC] Workspace is empty"
276
370
endif
@@ -288,7 +382,7 @@ function! fsharp#showSignature()
288
382
if exists (' result.result.content' )
289
383
let content = json_decode (result.result.content)
290
384
if exists (' content.Data' )
291
- echom substitute (content.Data, ' \n\+$' , ' ' , ' g' )
385
+ echo substitute (content.Data, ' \n\+$' , ' ' , ' g' )
292
386
endif
293
387
endif
294
388
endfunction
@@ -306,26 +400,30 @@ function! fsharp#showF1Help()
306
400
echo result
307
401
endfunction
308
402
403
+ function ! s: hover ()
404
+ if g: fsharp #backend == ' languageclient-neovim'
405
+ call LanguageClient#textDocument_hover ()
406
+ elseif g: fsharp #backend == ' nvim'
407
+ lua vim .lsp .buf .hover ()
408
+ endif
409
+ endfunction
410
+
309
411
function ! fsharp#showTooltip ()
310
412
function ! s: callback_showTooltip (result)
311
413
let result = a: result
312
414
if exists (' result.result.content' )
313
415
let content = json_decode (result.result.content)
314
416
if exists (' content.Data' )
315
- call LanguageClient#textDocument_hover ()
417
+ call s: hover ()
316
418
endif
317
419
endif
318
420
endfunction
319
421
" show hover only if signature exists for the current position
320
422
call s: signature (expand (' %:p' ), line (' .' ) - 1 , col (' .' ) - 1 , function (" s:callback_showTooltip" ))
321
423
endfunction
322
424
323
- let s: script_root_dir = expand (' <sfile>:p:h' ) . " /../"
324
- let s: fsac = fnamemodify (s: script_root_dir . " fsac/fsautocomplete.dll" , " :p" )
325
- let g: fsharp #languageserver_command =
326
- \ [' dotnet' , s: fsac ,
327
- \ ' --background-service-enabled'
328
- \ ]
425
+
426
+ " FSAC update utils
329
427
330
428
function ! s: update_win ()
331
429
echom " [FSAC] Downloading FSAC. This may take a while..."
@@ -357,6 +455,9 @@ function! fsharp#updateFSAC(...)
357
455
endif
358
456
endfunction
359
457
458
+
459
+ " FSI integration
460
+
360
461
let s: fsi_buffer = -1
361
462
let s: fsi_job = -1
362
463
let s: fsi_width = 0
@@ -385,7 +486,6 @@ endfunction
385
486
function ! fsharp#openFsi (returnFocus)
386
487
if bufwinid (s: fsi_buffer ) <= 0
387
488
let fsi_command = s: get_fsi_command ()
388
- " Neovim
389
489
if exists (' *termopen' ) || exists (' *term_start' )
390
490
let current_win = win_getid ()
391
491
execute g: fsharp #fsi_window_command
@@ -429,7 +529,7 @@ function! fsharp#openFsi(returnFocus)
429
529
if a: returnFocus | call s: win_gotoid_safe (current_win) | endif
430
530
return s: fsi_buffer
431
531
else
432
- echom " [FSAC] Your Vim does not support terminal" .
532
+ echom " [FSAC] Your (neo)vim does not support terminal" .
433
533
return 0
434
534
endif
435
535
endif
@@ -517,6 +617,7 @@ function! fsharp#sendAllToFsi()
517
617
return fsharp#sendFsi (text)
518
618
endfunction
519
619
620
+
520
621
let &cpo = s: cpo_save
521
622
unlet s: cpo_save
522
623
0 commit comments