- Indent: Working
- Syntax: Modified from ionide-vim with some minor fixes
- Plugin: None (I recommend Neovim 0.8 with FsAutoComplete)
This plugin is currently focused on providing better indent support in F#. If you find any problems, raise an issue and we'll work out a solution together.
- vim-fsharp hasn't been updated for a few years and also contains old versions of FsAutoComplete which don't really work (at least for my setup)
- Language features can be provided by an LSP (e.g. Neovim 0.8's built-in LSP client or coc-fsharp)
- Enhancements to indent rules can provide a better experience
- Other plugins don't improve the basic syntax and indent behaviour and seem to have issues on Windows platforms
- A lightweight indenter written in pure Vimscript.
- Robust indentation support
- 2 line-breaks end function
- Reformatting support (providing above 2 blank lines rule is followed). For something full-featured, look at Fantomas also included in FsAutoComplete
- Automated tests - Rules can be added without breaking existing functionality
- Developed on Windows 10/11 and Ubuntu 20.04 with Neovim 0.8
- Tested in Vim and Neovim stable (Neovim nightly should okay too)
- Tested on Windows 10/11 and Ubuntu 20.04
Sometimes the indenter won't immediately indent something (e.g. record keys). Just keep typing and it should figure out what you want to do.
This plugin is tested with the following vim settings:
set shiftwidth=2
set backspace=2
set tabstop=2
set softtabstop=2
set expandtab
filetype plugin indent on
syntax enable
This plugin probably doesn't support deeply nested code. Then again, you probably shouldn't be writing deeply nested code. Still, if you think you have a valid case, raise an issue and I'll be happy to take a look.
Add to your plugin manager:
Plug 'PhilT/vim-fsharp'
Paq (Neovim Lua)
paq {'PhilT/vim-fsharp'}
If you use vim-polyglot be sure to
load vim-fsharp before it or let g:polyglot_disabled = ['fsharp']
before
loading plugins.
Neovim 0.8's LSP client with nvim-lspconfig provides out of the box support for many languages. I've just added support for F# using the awesome FsAutoComplete library.
The following code snippets were all typed without pressing the TAB key. (See test case here) This also serves as a bit of a style guide.
// ### Array and List
// The following applies to both arrays and lists.
let anArray = [|
item1
item2
|]
let returnsList =
[
item1
item2
]
// ### Classes
// Indents members, including default and override
type MyBase() =
member _.Func1 x =
x + 1
default _.Func2 y =
y + 2
type MyDerived() =
override _.Func1 x =
x + 10
// ### Conditional
let someFunc () =
if someCond then doThing
elif otherCond then doOther
else doDefaultThing
if someExpression then
doSomething
elif someOtherExpression then
doAnotherThing
else
doSomethingElse
// ### Exceptions
let handleExceptions func args =
try
func args
someOtherStuff
with
| MyException(str) -> printfn "MyError: %s" str
| MyTupleException(str, i) -> printfn "MyTupleError: %s, %d" str i
// ### Lamba (`fun`)
// Also supports auto-pairs
List.map (fun x ->
processMap
)
// ### Function (`let`)
let someFunc args =
doSomeStuff
doMoreStuff
singleLineBreaksStaysInLet
// Double line break resets to previous let indent
// Even when deeply nested
let anotherFunc =
doDifferentStuff
// ### Match
// Supports nested match expressions and dedenting when default case entered.
match action with
| compactCase1 -> result1
| compactCase2 -> result2
| multilineCase3 ->
result3
| multilineWithCondition4 ->
when condition ->
result4
| nestedMatch ->
match nested with
| nestedCase5 ->
result5
| _ -> nestedDefaultCase
| _ -> defaultCase
// ### Module
module Example
let func () =
doSomething
module ThisWillContainTheRestOfTheCode =
let func () =
doSomething
// ### Pipelining
let func () =
doSomething
|> andAnotherThing
|> andOneMoreThing
// Supports multiline pipeline expressions.
doSomething
|>
if condition then
doThis
else
doThat
// ### Type (Record, Discriminated Union)
type SomeRecord = {
Field1: int
Field2: string
}
let someFunc () =
{
Field1 = 1
Field2 = "something"
}
let someRecord = {
Field1 = 1
Field2 = "something"
}
{ someRecord with
Field1 = 2
}
let newRecord = {
someRecord with
Field1 = 3
}
- Optimise and cleanup code
- Check support for F# Interactive (.fsx/.fsi) files
- Ensure F# formatting conventions are followed as much as possible
- Add a test in
tests/
- Add the minimal code to get it working
- Refactor
- Repeat steps 1-3 as required
- Add to
tests/integration.vader
[optional] - Add to
tests/readme.vader
- Add to
README.md
- Add to
tests/reformat.vader
- For Neovim, run:
nvim -Nu tests/vimrc
- For Vim, run:
vim -Nu tests/vimrc
Install vader-vim with ./install-vader
(this will install into ./vader.vim/)
Run from either PowerShell or Bash.
Syntax: ./test [-v] [-l] [testname]
- Run all tests in Neovim -
./test
- Run a single test in Vim -
./test -v let
- Run a single test with logging -
./test -l let