WTF — Wayland Tiling, F# Home Releases GitHub

Editing your WTF config with autocomplete

Your window manager is configured in F# — ~/.config/wtf/config.fsx is a real program the WM compiles at launch (the xMonad idea). WTF ships a config Type Provider that makes that file strongly-typed and machine-aware: in an editor with the F# language server you get autocomplete and typo-checking driven by your machine.

A typo like SetLayout "tll", or a rule for an app you don't have installed, becomes a compile error — a red squiggle in the editor, and a config-load error in the WM (which then falls back to the built-in default so the WM still starts). This is the same FSharp.Compiler.Service that the WM uses to load the config, so what the editor flags is exactly what the WM would reject.

TL;DR

wtf-edit            # ensures the F# LSP is installed, fixes the #r paths, opens $EDITOR
wtf-edit --setup    # just verify the LSP + print per-editor setup snippets

wtf-edit (installed to /usr/local/bin by scripts/install.sh):

  1. ensures fsautocomplete (the standard F# language server) is installed, running dotnet tool install -g fsautocomplete if it is missing;
  2. makes sure config.fsx exists and its two #r lines point at the real on-disk WTF.Core.dll + WTF.TypeProviders.dll (so the LSP can resolve them);
  3. opens it in $VISUAL / $EDITOR.

How it works (honest framing)

The two #r lines are guarded by #if !WTF_RUNTIME. When the WM loads the file it defines WTF_RUNTIME and injects its own references, so the dev/installed paths in the file are only used by the editor and by dotnet fsi.

Per-editor setup

You only need fsautocomplete on your PATH (a dotnet tool install -g fsautocomplete puts it in ~/.dotnet/tools). Then point your editor's F# LSP at it.

VSCode (Ionide)

Install the Ionide-fsharp extension — it bundles/uses fsautocomplete. Open the config folder:

code ~/.config/wtf

Open config.fsx; IntelliSense for a bare script comes from the file's #r lines (kept correct by wtf-edit).

Neovim (nvim-lspconfig)

require('lspconfig').fsautocomplete.setup {
  -- the LSP binary installed by `dotnet tool install -g fsautocomplete`
  cmd = { 'fsautocomplete', '--adaptive-lsp-server-enabled' },
  filetypes = { 'fsharp' },
  root_dir = require('lspconfig.util').root_pattern('.config/wtf', '*.fsx'),
}

Make sure *.fsx is detected as fsharp (nvim does this by default).

Emacs (eglot or lsp-mode)

With eglot:

(require 'fsharp-mode)
(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               '(fsharp-mode . ("fsautocomplete"))))
(add-hook 'fsharp-mode-hook #'eglot-ensure)

lsp-mode + lsp-fsharp works too and uses fsautocomplete out of the box.

Helix (languages.toml)

[language-server.fsautocomplete]
command = "fsautocomplete"

[[language]]
name = "fsharp"
language-servers = ["fsautocomplete"]

Troubleshooting

Found a problem on this page? Edit it on GitHub — the site rebuilds from docs/ automatically.