diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,7 +1,33 @@
 * Hackage: <http://hackage.haskell.org/package/crackNum>
 * GitHub:  <http://github.com/LeventErkok/crackNum/>
 
-* Latest Hackage released version: 3.24, 2026-08-17
+* Latest Hackage released version: 3.26, 2026-08-19
+
+### Version 3.26, 2026-08-19
+
+  * New flag `--list-formats`, which prints the floating-point formats `-f` accepts,
+    one name per line. It is meant for editor integrations, which would otherwise have
+    to hardcode the list and let it go stale; the VIM plugin now asks rather than
+    guesses, and picks up any format added later for free.
+
+  * `--help` now also lists the supported floating-point formats. Both it and the
+    `-f` error message are generated from a single table, so they cannot disagree.
+
+  * Fix the VIM integration, which had been broken since version 3.0. The plugin
+    offered `i`, `w`, and `f` as the choices at its precision prompt, and passed
+    whichever you picked through as-is, so `:CrackNum` ran `crackNum i 0b0110`:
+    no leading dash, and no bit-width. Every invocation was rejected, and the
+    quickfix window filled up with crackNum's usage text instead of an answer.
+    The completion list now offers real flags (`-i8`, `-fhp`, ...), and anything
+    else crackNum accepts, such as `-f3+4` or `-l4 -fhp`, can be typed in directly.
+
+  * The VIM plugin also set `grepformat` to `VIM %m`, matching a `--vim` output
+    mode that was removed in 3.0. Nothing matched that format, so even a correct
+    invocation produced an empty quickfix window. Take crackNum's output as-is now.
+
+  * The VIM plugin now finds the bit-pattern under the cursor itself, instead of
+    relying on `<cword>`. Verilog notation stops at the quote (`64'hdeadbeef` came
+    out as just `64`), and the value is quoted before it reaches the shell.
 
 ### Version 3.25, 2026-08-18
 
diff --git a/GUI/tclGUI/README.md b/GUI/tclGUI/README.md
deleted file mode 100644
--- a/GUI/tclGUI/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# CrackNum Tcl/Tk GUI
-
-A cross-platform GUI for [crackNum](https://github.com/LeventErkok/crackNum), written in Tcl/Tk.
-Works on Linux and macOS anywhere `wish` (Tk 8.6+) is available.
-
-## Requirements
-
-- `crackNum` on your PATH
-- `z3` on your PATH
-- `wish` (Tk 8.6+)
-
-On NixOS / Nix:
-
-```bash
-nix profile install nixpkgs#tk
-```
-
-On Debian/Ubuntu:
-
-```bash
-sudo apt install tk
-```
-
-On RHEL/Fedora/Rocky:
-
-```bash
-sudo dnf install tk
-```
-
-## Installation
-
-Nothing to do: this script is a cabal data-file, so `cabal install crackNum`
-puts it on disk next to the binary, and `crackNum --gui` finds it there.
-
-If you do not have it — say you only have the binary, or you moved it — get the
-sources with either of:
-
-```bash
-cabal get crackNum
-git clone http://github.com/LeventErkok/crackNum.git
-```
-
-### Running a different copy
-
-`crackNum` looks for the script in three places, first match wins:
-
-| Order | Location                             | Use it for                        |
-|-------|--------------------------------------|-----------------------------------|
-| 1     | `$CRACKNUM_TCL`                      | pointing at an explicit file      |
-| 2     | `crackNum.tcl` on your PATH          | shadowing with a checkout         |
-| 3     | the copy installed with the package  | the normal case; nothing to set   |
-
-So to test a modified script:
-
-```bash
-export CRACKNUM_TCL=/path/to/crackNum/GUI/tclGUI/crackNum.tcl
-```
-
-or put its directory on your PATH (the script must be executable for this route):
-
-```bash
-export PATH=/path/to/crackNum/GUI/tclGUI:$PATH
-```
-
-When working inside a checkout, `cabal run crackNum -- --gui` also works: cabal
-sets `crackNum_datadir` so the in-tree copy is used.
-
-## Usage
-
-Launch via the `crackNum` binary:
-
-```bash
-crackNum --gui
-crackNum --gui -fsp 2.5
-crackNum --gui -w32 0xDEADBEEF
-```
-
-Or directly with `wish`:
-
-```bash
-wish crackNum.tcl
-wish crackNum.tcl -fsp 2.5
-```
-
-## Keyboard shortcuts
-
-| Key      | Action          |
-|----------|-----------------|
-| Ctrl+W   | Close window    |
-| Ctrl+Q   | Quit            |
-| Return   | Crack the value |
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -23,20 +23,24 @@
 
 ### Supported formats
 
-| Flag        | Format                              | Exponent | Significand (incl. implicit bit) |
-|-------------|-------------------------------------|---------:|---------------------------------:|
-| `-fhp`      | Half precision (IEEE-754 binary16)  |        5 |                               11 |
-| `-fbp`      | Brain float (bfloat16)              |        8 |                                8 |
-| `-ftf32`    | TensorFloat-32                      |        8 |                               11 |
-| `-fsp`      | Single precision (binary32)         |        8 |                               24 |
-| `-fdp`      | Double precision (binary64)         |       11 |                               53 |
-| `-fqp`      | Quad precision (binary128)          |       15 |                              113 |
-| `-fe5m2`    | FP8, IEEE-754 style                 |        5 |                                3 |
-| `-fe4m3`    | FP8, alternate (no infinities)      |        4 |                                4 |
-| `-ffp4`     | FP4 (E2M1)                          |        2 |                                2 |
-| `-ffp4e0m3` | FP4 (E0M3), sign-magnitude          |        0 |                                3 |
-| `-fa+b`     | Arbitrary IEEE-754 float            |        a |                                b |
+```
+Flag        Format                               Exponent   Significand
+-----------------------------------------------------------------------
+-fhp        Half precision (IEEE-754 binary16)          5            11
+-fbp        Brain float (bfloat16)                      8             8
+-ftf32      TensorFloat-32                              8            11
+-fsp        Single precision (binary32)                 8            24
+-fdp        Double precision (binary64)                11            53
+-fqp        Quad precision (binary128)                 15           113
+-fe5m2      FP8, IEEE-754 style                         5             3
+-fe4m3      FP8, alternate (no infinities)              4             4
+-ffp4       FP4 (E2M1)                                  2             2
+-ffp4e0m3   FP4 (E0M3), sign-magnitude                  0             3
+-fa+b       Arbitrary IEEE-754 float                    a             b
+```
 
+Significand sizes include the implicit bit.
+
 FP4 (E0M3) is the odd one out: with no exponent bits at all it is really a 4-bit
 sign-magnitude *integer*, holding a sign and a 3-bit magnitude. It covers -7 to 7,
 with both a positive and a negative zero, and has neither NaN nor Inf.
@@ -348,47 +352,63 @@
 ### Usage info
 ```
 Usage: crackNum value OR binary/hex-pattern
-  -i N                 Signed   integer of N-bits
-  -w N                 Unsigned integer of N-bits
-  -f fp                Floating point format fp
-  -r rm                Rounding mode to use. If not given, Nearest-ties-to-Even.
-  -l lanes             Number of lanes to decode
-  -h, -?    --help     print help, with examples
-  -v        --version  print version info
-  -d        --debug    debug mode, developers only
-            --gui      launch the graphical interface
+  -i N                      Signed   integer of N-bits
+  -w N                      Unsigned integer of N-bits
+  -f fp                     Floating point format fp
+  -r rm                     Rounding mode to use. If not given, Nearest-ties-to-Even.
+  -l lanes                  Number of lanes to decode
+  -h, -?    --help          print help, with examples
+  -v        --version       print version info
+  -d        --debug         debug mode, developers only
+            --gui           launch the graphical interface
+            --list-formats  list the formats supported by -f, one per line
 
+Supported floating-point formats (for use with -f):
+
+       hp: Half float             ( 5 +  11)
+       bp: Brain float            ( 8 +   8)
+     tf32: TensorFloat-32         ( 8 +  11)
+       sp: Single precision       ( 8 +  24)
+       dp: Double precision       (11 +  53)
+       qp: Quad   precision       (15 + 113)
+      a+b: Arbitrary IEEE-754     ( a +   b)
+     e5m2: FP8 format (IEEE-754)  ( 5 +   3)
+     e4m3: FP8 format (Alternate) ( 4 +   4)
+      fp4: FP4 format (E2M1)      ( 2 +   2)
+  fp4e0m3: FP4 format (E0M3)      ( 0 +   3)
+
 Examples:
  Encoding:
-   crackNum -i4       -- -2                    -- encode as 4-bit signed integer
-   crackNum -w4       2                        -- encode as 4-bit unsigned integer
-   crackNum -f3+4     2.5                      -- encode as float with 3 bits exponent, 4 bits significand
-   crackNum -f3+4     2.5 -rRTZ                -- encode as above, but use RTZ rounding mode.
-   crackNum -fbp      2.5                      -- encode as a brain-precision float
-   crackNum -ftf32    2.5                      -- encode as a TensorFloat-32 float
-   crackNum -fdp      2.5                      -- encode as a double-precision float
-   crackNum -fqp      2.5                      -- encode as a quad-precision float
-   crackNum -fe4m3    2.5                      -- encode as an E4M3 FP8 float
-   crackNum -fe5m2    2.5                      -- encode as an E5M2 FP8 float
-   crackNum -ffp4     2.5                      -- encode as an FP4 (E2M1) float
-   crackNum -ffp4e0m3 3.5                      -- encode as an FP4 (E0M3) sign-magnitude integer
-   crackNum -fsp      0x3.2p5                  -- encode as single-precision from hex-float
+   crackNum -i4       -- -2                   -- encode as 4-bit signed integer
+   crackNum -w4       2                       -- encode as 4-bit unsigned integer
+   crackNum -f3+4     2.5                     -- encode as float with 3 bits exponent, 4 bits significand
+   crackNum -f3+4     2.5 -rRTZ               -- encode as above, but use RTZ rounding mode.
+   crackNum -fbp      2.5                     -- encode as a brain-precision float
+   crackNum -ftf32    2.5                     -- encode as a TensorFloat-32 float
+   crackNum -fdp      2.5                     -- encode as a double-precision float
+   crackNum -fqp      2.5                     -- encode as a quad-precision float
+   crackNum -fe4m3    2.5                     -- encode as an E4M3 FP8 float
+   crackNum -fe5m2    2.5                     -- encode as an E5M2 FP8 float
+   crackNum -ffp4     2.5                     -- encode as an FP4 (E2M1) float
+   crackNum -ffp4e0m3 3.5                     -- encode as an FP4 (E0M3) sign-magnitude integer
+   crackNum -fsp      0x3.2p5                 -- encode as single-precision from hex-float
 
  Decoding:
-   crackNum -i4       0b0110                   -- decode as 4-bit signed integer, from binary
-   crackNum -w4       0xE                      -- decode as 4-bit unsigned integer, from hex
-   crackNum -f3+4     0b0111001                -- decode as float with 3 bits exponent, 4 bits significand
-   crackNum -fbp      0x000F                   -- decode as a brain-precision float
-   crackNum -ftf32    19\'h0000F               -- decode as a TensorFloat-32 float
-   crackNum -fdp      0x8000000000000000       -- decode as a double-precision float
-   crackNum -fhp      0x8000                   -- decode as a half-precision float
-   crackNum -ffp4     0b0111                   -- decode as an FP4 (E2M1) float
-   crackNum -ffp4e0m3 0b1101                   -- decode as an FP4 (E0M3) sign-magnitude integer
-   crackNum -l4 -fhp  64\'hbdffaaffdc71fc60    -- decode as half-precision float over 4 lanes using verilog notation
+   crackNum -i4       0b0110                  -- decode as 4-bit signed integer, from binary
+   crackNum -w4       0xE                     -- decode as 4-bit unsigned integer, from hex
+   crackNum -f3+4     0b0111001               -- decode as float with 3 bits exponent, 4 bits significand
+   crackNum -fbp      0x000F                  -- decode as a brain-precision float
+   crackNum -ftf32    19\'h0000F              -- decode as a TensorFloat-32 float
+   crackNum -fdp      0x8000000000000000      -- decode as a double-precision float
+   crackNum -fhp      0x8000                  -- decode as a half-precision float
+   crackNum -ffp4     0b0111                  -- decode as an FP4 (E2M1) float
+   crackNum -ffp4e0m3 0b1101                  -- decode as an FP4 (E0M3) sign-magnitude integer
+   crackNum -l4 -fhp  64\'hbdffaaffdc71fc60   -- decode as half-precision float over 4 lanes using verilog notation
 
  GUI:
-   crackNum --gui                     -- launch the graphical interface
-   crackNum --gui 0xdeadbeef          -- launch the GUI, pre-filled with the given value
+   crackNum --gui                             -- launch the graphical interface
+   crackNum --gui      0xdeadbeef             -- launch the GUI, pre-filled with the given value
+   crackNum --gui -fsp 0xdeadbeef             -- launch the GUI, using the given format
 
  Notes:
    - For encoding:
diff --git a/crackNum.cabal b/crackNum.cabal
--- a/crackNum.cabal
+++ b/crackNum.cabal
@@ -1,6 +1,6 @@
 Cabal-version      : 2.2
 Name               : crackNum
-Version            : 3.25
+Version            : 3.26
 Synopsis           : Crack various integer and floating-point data formats
 Description        : Crack IEEE-754 and other float formats and arbitrary sized words and integers, showing the layout.
                      .
@@ -13,7 +13,8 @@
 Copyright          : Levent Erkok
 Category           : Tools
 Build-type         : Simple
-Extra-Source-Files : README.md, COPYRIGHT, CHANGES.md, GUI/tclGUI/README.md
+Extra-Source-Files : README.md, COPYRIGHT, crackNum.vim
+Extra-Doc-Files    : CHANGES.md
 
 -- The Tcl/Tk GUI is a data-file (not merely an extra-source-file) so that it is
 -- actually installed alongside the binary, and can be found at run time via
diff --git a/crackNum.vim b/crackNum.vim
new file mode 100644
--- /dev/null
+++ b/crackNum.vim
@@ -0,0 +1,158 @@
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+" VI interface to crackNum
+"
+" Copyright   :  (c) Levent Erkok
+" License     :  BSD3
+" Maintainer  :  erkokl@gmail.com
+"
+" INSTALLATION: Put this file in a convenient location (typically your .vim directory),
+" and put "so crackNum.vim" in your .vimrc file. (With the appropriate path.)
+"
+" Once you restart vim, locate your cursor over a stream of binary/hex digits, and
+" enter the command :CrackNum to see further options.
+"
+" Arguments are passed to crackNum verbatim, so anything the executable accepts works:
+"
+"     :CrackNum -i4              " decode as a 4-bit signed integer
+"     :CrackNum -fhp             " decode as a half-precision float
+"     :CrackNum -f3+4            " decode as a float with 3 exponent, 4 significand bits
+"     :CrackNum -l4 -fhp         " decode 4 lanes of half-precision floats
+"
+" Use TAB to complete the common formats. With no arguments, :CrackNum prompts for them.
+" The formats offered come from "crackNum --list-formats", so they track the executable.
+"
+" Set g:crackNumProgram to run a crackNum that is not on your PATH, and
+" g:crackNumPrecisions to replace the completion list outright.
+"
+" See https://github.com/LeventErkok/CrackNum for details.
+
+" Which executable to run; override if crackNum is not on your PATH.
+if !exists("g:crackNumProgram")
+    let g:crackNumProgram = "crackNum"
+endif
+
+" Integer widths and lane counts offered by TAB completion. These are only the common
+" cases: crackNum takes any -iN/-wN/-lN, and any such argument can be typed in directly.
+let s:crackNumIntFlags  = ["-i8", "-i16", "-i32", "-i64", "-w8", "-w16", "-w32", "-w64"]
+let s:crackNumLaneFlags = ["-l2", "-l4", "-l8"]
+
+" Used only when crackNum is too old to know --list-formats, or is not on the PATH.
+" Anything crackNum has learned since is picked up from the executable, not from here.
+let s:crackNumFallbackFormats = [ "hp", "bp", "tf32", "sp", "dp", "qp"
+                              \ , "e5m2", "e4m3", "fp4", "fp4e0m3"
+                              \ ]
+
+" The formats the executable reports, as -f flags. Asking it keeps this list from
+" drifting out of date as crackNum grows new formats. Cached per executable, since
+" completion is on a keystroke path and this shells out.
+let s:crackNumFormatCache = {}
+function! s:CrackNumFormats()
+    if has_key(s:crackNumFormatCache, g:crackNumProgram)
+        return s:crackNumFormatCache[g:crackNumProgram]
+    endif
+    let l:names = []
+    " 2>&1 so that an older crackNum, which errors out here, cannot scribble on the screen.
+    let l:out = systemlist(shellescape(g:crackNumProgram) . " --list-formats 2>&1")
+    if v:shell_error == 0
+        let l:names = filter(l:out, 'v:val =~# "^[a-z0-9]\\+$"')
+    endif
+    if empty(l:names)
+        let l:names = s:crackNumFallbackFormats
+    endif
+    let s:crackNumFormatCache[g:crackNumProgram] = map(copy(l:names), '"-f" . v:val')
+    return s:crackNumFormatCache[g:crackNumProgram]
+endfunction
+
+" What TAB offers. Set g:crackNumPrecisions yourself to override the whole list.
+function! s:CrackNumChoices()
+    if exists("g:crackNumPrecisions")
+        return g:crackNumPrecisions
+    endif
+    return s:crackNumIntFlags + s:CrackNumFormats() + s:crackNumLaneFlags
+endfunction
+
+function! CrackNumComplete(A, L, P)
+    let l:all = s:CrackNumChoices()
+    if empty(a:A)
+        return l:all
+    endif
+    " Plain prefix match: the arguments contain '-' and '+', so avoid regex matching.
+    let l:out = filter(copy(l:all), 'stridx(v:val, a:A) == 0')
+    if empty(l:out)
+        return l:all
+    endif
+    return l:out
+endfunction
+
+" Patterns crackNum accepts as input, most specific first. Note that <cword> is not
+" good enough on its own: it stops at the quote in verilog notation (64'hdeadbeef),
+" and <cWORD> is too greedy, picking up trailing punctuation such as "0x8000;".
+let s:crackNumPatterns = [ "\\d\\+'[bBoOdDhH][0-9a-fA-F_]\\+"
+                       \ , "0[xX][0-9a-fA-F_]\\+"
+                       \ , "0[bB][01_]\\+"
+                       \ ]
+
+" The bit-pattern under the cursor, falling back on <cword> if nothing matches.
+function! s:CrackNumWord()
+    let l:line = getline('.')
+    let l:idx  = col('.') - 1
+    for l:pat in s:crackNumPatterns
+        let l:from = 0
+        while 1
+            let l:m = matchstrpos(l:line, l:pat, l:from)
+            if l:m[1] < 0
+                break
+            endif
+            if l:idx >= l:m[1] && l:idx < l:m[2]
+                return l:m[0]
+            endif
+            let l:from = l:m[2]
+        endwhile
+    endfor
+    return expand("<cword>")
+endfunction
+
+function! CrackNum(...)
+    redraw
+    let l:curWord = s:CrackNumWord()
+    if empty(l:curWord)
+        echoerr "Place the cursor on a bin/hex number to crack!"
+        return
+    endif
+    if empty(a:000)
+        echo "Cracking \"" . l:curWord . "\".. Use TAB to see the formats supported."
+        call inputsave()
+        let l:args = [input("Format> ", "", "customlist,CrackNumComplete")]
+        call inputrestore()
+        redraw
+        if empty(join(l:args, ''))
+            echoerr "No format given; use e.g. -i4, -w8, or -fhp."
+            return
+        endif
+    else
+        echo "Cracking \""  . l:curWord . "\".."
+        let l:args = copy(a:000)
+    endif
+
+    " Quote the value: verilog notation (64'hdeadbeef) is not shell-safe as-is.
+    let l:grepargs = join(l:args + [shellescape(l:curWord)], ' ')
+    let l:grepprg_bak=&grepprg
+    let l:grepformat_bak=&grepformat
+    try
+        let &grepprg=g:crackNumProgram
+        " crackNum reports plain text, not file:line diagnostics, so take each line as is.
+        let &grepformat="%m"
+        silent execute "grep" . " " . l:grepargs
+    finally
+        let &grepprg=l:grepprg_bak
+        let &grepformat=l:grepformat_bak
+    endtry
+
+    call setqflist([], 'a', {'title': g:crackNumProgram . ' ' . l:grepargs})
+
+    botright copen
+
+    redraw!
+endfunction
+command! -nargs=* -complete=customlist,CrackNumComplete CrackNum call CrackNum(<f-args>)
+" end crackNum interface
diff --git a/src/CrackNum/Main.hs b/src/CrackNum/Main.hs
--- a/src/CrackNum/Main.hs
+++ b/src/CrackNum/Main.hs
@@ -124,6 +124,7 @@
           | Version            -- ^ Version
           | Debug              -- ^ Run in debug mode. Debugging only.
           | GUI                -- ^ Launch the graphical interface
+          | Formats            -- ^ List the floating-point formats we support
           | Help               -- ^ Show help
           deriving (Show, Eq)
 
@@ -161,6 +162,37 @@
 #define FP_MAX_SB 1073741822
 #endif
 
+-- | The floating-point formats we support, in the order we present them: the name to
+-- pass to -f, what it is, and its (exponent + significand) sizes. The arbitrary format
+-- stands in for any a+b pair rather than naming a format of its own, which is what the
+-- final field records: only the named ones can be listed as choices.
+fpFormats :: [(String, String, String, Bool)]
+fpFormats = [ ("hp",      "Half float",             "( 5 +  11)", True )
+            , ("bp",      "Brain float",            "( 8 +   8)", True )
+            , ("tf32",    "TensorFloat-32",         "( 8 +  11)", True )
+            , ("sp",      "Single precision",       "( 8 +  24)", True )
+            , ("dp",      "Double precision",       "(11 +  53)", True )
+            , ("qp",      "Quad   precision",       "(15 + 113)", True )
+            , ("a+b",     "Arbitrary IEEE-754",     "( a +   b)", False)
+            , ("e5m2",    "FP8 format (IEEE-754)",  "( 5 +   3)", True )
+            , ("e4m3",    "FP8 format (Alternate)", "( 4 +   4)", True )
+            , ("fp4",     "FP4 format (E2M1)",      "( 2 +   2)", True )
+            , ("fp4e0m3", "FP4 format (E0M3)",      "( 0 +   3)", True )
+            ]
+
+-- | The formats that can actually be named, i.e., everything but the arbitrary a+b
+-- placeholder. This is what --list-formats prints, one per line.
+fpFormatNames :: [String]
+fpFormatNames = [n | (n, _, _, True) <- fpFormats]
+
+-- | Floating-point formats we support, as a table for use in help/error messages.
+fpFormatsHelp :: [String]
+fpFormatsHelp = [rjust n ++ ": " ++ ljust d ++ " " ++ sz | (n, d, sz, _) <- fpFormats]
+  where nw      = maximum [length n | (n, _, _, _) <- fpFormats]
+        dw      = maximum [length d | (_, d, _, _) <- fpFormats]
+        rjust x = replicate (nw - length x) ' ' ++ x
+        ljust x = x ++ replicate (dw - length x) ' '
+
 -- | Given a float flag value, turn it into a flag
 getFP :: String -> Flag
 getFP "hp"      = Floating $ FP 5 11
@@ -178,23 +210,14 @@
                                         (sp@(_:_), "") -> mkEBSB (read eb) (read sp)
                                         _              -> bad
                   _                 -> bad
-                where bad = BadFlag [ "Option " ++ show "-f" ++ " requires one of:"
-                                    , ""
-                                    , "     hp: Half float             ( 5 +  11)"
-                                    , "     bp: Brain float            ( 8 +   8)"
-                                    , "   tf32: TensorFloat-32         ( 8 +  11)"
-                                    , "     sp: Single precision       ( 8 +  24)"
-                                    , "     dp: Double precision       (11 +  53)"
-                                    , "     qp: Quad   precision       (15 + 113)"
-                                    , "    a+b: Arbitrary IEEE-754     ( a +   b)"
-                                    , "   e5m2: FP8 format (IEEE-754)  ( 5 +   3)"
-                                    , "   e4m3: FP8 format (Alternate) ( 4 +   4)"
-                                    , "    fp4: FP4 format (E2M1)      ( 2 +   2)"
-                                    , "fp4e0m3: FP4 format (E0M3)      ( 0 +   3)"
-                                    , ""
-                                    , "In the arbitrary format, the first number is the number of bits in the exponent"
-                                    , "and the second number is the number of bits in the significand, including the implicit bit."
-                                    ]
+                where bad = BadFlag $ [ "Option " ++ show "-f" ++ " requires one of:"
+                                      , ""
+                                      ]
+                                   ++ fpFormatsHelp
+                                   ++ [ ""
+                                      , "In the arbitrary format, the first number is the number of bits in the exponent"
+                                      , "and the second number is the number of bits in the significand, including the implicit bit."
+                                      ]
                       mkEBSB :: Int -> Int -> Flag
                       mkEBSB eb sb
                        |    eb >= FP_MIN_EB && eb <= FP_MAX_EB
@@ -227,15 +250,16 @@
 -- | Options we accept
 pgmOptions :: [OptDescr Flag]
 pgmOptions = [
-      Option "i"  []          (ReqArg (getSize "-i" Signed)   "N" )    "Signed   integer of N-bits"
-    , Option "w"  []          (ReqArg (getSize "-w" Unsigned) "N" )    "Unsigned integer of N-bits"
-    , Option "f"  []          (ReqArg getFP                   "fp")    "Floating point format fp"
-    , Option "r"  []          (ReqArg (getRM . map toLower)   "rm")    "Rounding mode to use. If not given, Nearest-ties-to-Even."
-    , Option "l"  []          (ReqArg (getSize "-l" Lanes)    "lanes") "Number of lanes to decode"
-    , Option "h?" ["help"]    (NoArg Help)                             "print help, with examples"
-    , Option "v"  ["version"] (NoArg Version)                          "print version info"
-    , Option "d"  ["debug"]   (NoArg Debug)                            "debug mode, developers only"
-    , Option ""   ["gui"]     (NoArg GUI)                              "launch the graphical interface"
+      Option "i"  []               (ReqArg (getSize "-i" Signed)   "N" )    "Signed   integer of N-bits"
+    , Option "w"  []               (ReqArg (getSize "-w" Unsigned) "N" )    "Unsigned integer of N-bits"
+    , Option "f"  []               (ReqArg getFP                   "fp")    "Floating point format fp"
+    , Option "r"  []               (ReqArg (getRM . map toLower)   "rm")    "Rounding mode to use. If not given, Nearest-ties-to-Even."
+    , Option "l"  []               (ReqArg (getSize "-l" Lanes)    "lanes") "Number of lanes to decode"
+    , Option "h?" ["help"]         (NoArg Help)                             "print help, with examples"
+    , Option "v"  ["version"]      (NoArg Version)                          "print version info"
+    , Option "d"  ["debug"]        (NoArg Debug)                            "debug mode, developers only"
+    , Option ""   ["gui"]          (NoArg GUI)                              "launch the graphical interface"
+    , Option ""   ["list-formats"] (NoArg Formats)                          "list the formats supported by -f, one per line"
     ]
 
 -- | Help info
@@ -244,56 +268,62 @@
 
 -- | Print usage info and examples.
 usage :: String -> IO ()
-usage pn = putStr $ unlines [ helpStr pn
-                            , "Examples:"
-                            , " Encoding:"
-                            , "   " ++ pn ++ " -i4    -- -2                    -- encode as 4-bit signed integer"
-                            , "   " ++ pn ++ " -w4    2                        -- encode as 4-bit unsigned integer"
-                            , "   " ++ pn ++ " -f3+4  2.5                      -- encode as float with 3 bits exponent, 4 bits significand"
-                            , "   " ++ pn ++ " -f3+4  2.5 -rRTZ                -- encode as above, but use RTZ rounding mode."
-                            , "   " ++ pn ++ " -fbp   2.5                      -- encode as a brain-precision float"
-                            , "   " ++ pn ++ " -ftf32 2.5                      -- encode as a TensorFloat-32 float"
-                            , "   " ++ pn ++ " -fdp   2.5                      -- encode as a double-precision float"
-                            , "   " ++ pn ++ " -fqp   2.5                      -- encode as a quad-precision float"
-                            , "   " ++ pn ++ " -fe4m3 2.5                      -- encode as an E4M3 FP8 float"
-                            , "   " ++ pn ++ " -fe5m2 2.5                      -- encode as an E5M2 FP8 float"
-                            , "   " ++ pn ++ " -ffp4  2.5                      -- encode as an FP4 (E2M1) float"
-                            , "   " ++ pn ++ " -ffp4e0m3 3.5                   -- encode as an FP4 (E0M3) sign-magnitude integer"
-                            , "   " ++ pn ++ " -fsp   0x3.2p5                  -- encode as single-precision from hex-float"
-                            , ""
-                            , " Decoding:"
-                            , "   " ++ pn ++ " -i4      0b0110                -- decode as 4-bit signed integer, from binary"
-                            , "   " ++ pn ++ " -w4      0xE                   -- decode as 4-bit unsigned integer, from hex"
-                            , "   " ++ pn ++ " -f3+4    0b0111001             -- decode as float with 3 bits exponent, 4 bits significand"
-                            , "   " ++ pn ++ " -fbp     0x000F                -- decode as a brain-precision float"
-                            , "   " ++ pn ++ " -ftf32   19\\'h0000F            -- decode as a TensorFloat-32 float"
-                            , "   " ++ pn ++ " -fdp     0x8000000000000000    -- decode as a double-precision float"
-                            , "   " ++ pn ++ " -fhp     0x8000                -- decode as a half-precision float"
-                            , "   " ++ pn ++ " -ffp4    0b0111                -- decode as an FP4 (E2M1) float"
-                            , "   " ++ pn ++ " -ffp4e0m3 0b1101               -- decode as an FP4 (E0M3) sign-magnitude integer"
-                            , "   " ++ pn ++ " -l4 -fhp 64\\'hbdffaaffdc71fc60 -- decode as half-precision float over 4 lanes using verilog notation"
-                            , ""
-                            , " GUI:"
-                            , "   " ++ pn ++ " --gui                     -- launch the graphical interface"
-                            , "   " ++ pn ++ " --gui 0xdeadbeef          -- launch the GUI, pre-filled with the given value"
-                            , ""
-                            , " Notes:"
-                            , "   - For encoding:"
-                            , "       - Use -- to separate your argument if it's a negative number."
-                            , "       - For floats: You can pass in NaN, Inf, -0, -Inf etc as the argument"
-                            , "                     along with a decimal (2.3, -4.1e5) or hexadecimal float (0x2.4p3)"
-                            , "       - FP4 (E2M1) has neither NaN nor Inf, so those inputs are rejected. Finite"
-                            , "         values outside its range of [-6, 6] saturate to the nearest end-point."
-                            , "       - FP4 (E0M3) is a sign-magnitude integer: a sign bit and a 3-bit magnitude,"
-                            , "         covering -7 to 7, with both a positive and a negative zero. It has no NaN"
-                            , "         and no Inf either, and values outside [-7, 7] saturate to the end-point."
-                            , "   - For decoding:"
-                            , "       - Use hexadecimal (0x) binary (0b), or N'h (verilog) notation as input."
-                            , "         Input must have one of these prefixes."
-                            , "       - You can use _,- or space as a digit to improve readability for the pattern to be decoded"
-                            , "       - With -lN parameter, you can decode multiple lanes of data."
-                            , "       - If you use verilog input format, then we will infer the number of lanes unless you provide it."
-                            ]
+usage pn = putStr $ unlines $ [ helpStr pn
+                              , "Supported floating-point formats (for use with -f):"
+                              , ""
+                              ]
+                           ++ map ("  " ++) fpFormatsHelp
+                           ++ [ ""
+                              , "Examples:"
+                              , " Encoding:"
+                              , "   " ++ pn ++ " -i4       -- -2                   -- encode as 4-bit signed integer"
+                              , "   " ++ pn ++ " -w4       2                       -- encode as 4-bit unsigned integer"
+                              , "   " ++ pn ++ " -f3+4     2.5                     -- encode as float with 3 bits exponent, 4 bits significand"
+                              , "   " ++ pn ++ " -f3+4     2.5 -rRTZ               -- encode as above, but use RTZ rounding mode."
+                              , "   " ++ pn ++ " -fbp      2.5                     -- encode as a brain-precision float"
+                              , "   " ++ pn ++ " -ftf32    2.5                     -- encode as a TensorFloat-32 float"
+                              , "   " ++ pn ++ " -fdp      2.5                     -- encode as a double-precision float"
+                              , "   " ++ pn ++ " -fqp      2.5                     -- encode as a quad-precision float"
+                              , "   " ++ pn ++ " -fe4m3    2.5                     -- encode as an E4M3 FP8 float"
+                              , "   " ++ pn ++ " -fe5m2    2.5                     -- encode as an E5M2 FP8 float"
+                              , "   " ++ pn ++ " -ffp4     2.5                     -- encode as an FP4 (E2M1) float"
+                              , "   " ++ pn ++ " -ffp4e0m3 3.5                     -- encode as an FP4 (E0M3) sign-magnitude integer"
+                              , "   " ++ pn ++ " -fsp      0x3.2p5                 -- encode as single-precision from hex-float"
+                              , ""
+                              , " Decoding:"
+                              , "   " ++ pn ++ " -i4       0b0110                  -- decode as 4-bit signed integer, from binary"
+                              , "   " ++ pn ++ " -w4       0xE                     -- decode as 4-bit unsigned integer, from hex"
+                              , "   " ++ pn ++ " -f3+4     0b0111001               -- decode as float with 3 bits exponent, 4 bits significand"
+                              , "   " ++ pn ++ " -fbp      0x000F                  -- decode as a brain-precision float"
+                              , "   " ++ pn ++ " -ftf32    19\\'h0000F              -- decode as a TensorFloat-32 float"
+                              , "   " ++ pn ++ " -fdp      0x8000000000000000      -- decode as a double-precision float"
+                              , "   " ++ pn ++ " -fhp      0x8000                  -- decode as a half-precision float"
+                              , "   " ++ pn ++ " -ffp4     0b0111                  -- decode as an FP4 (E2M1) float"
+                              , "   " ++ pn ++ " -ffp4e0m3 0b1101                  -- decode as an FP4 (E0M3) sign-magnitude integer"
+                              , "   " ++ pn ++ " -l4 -fhp  64\\'hbdffaaffdc71fc60   -- decode as half-precision float over 4 lanes using verilog notation"
+                              , ""
+                              , " GUI:"
+                              , "   " ++ pn ++ " --gui                             -- launch the graphical interface"
+                              , "   " ++ pn ++ " --gui      0xdeadbeef             -- launch the GUI, pre-filled with the given value"
+                              , "   " ++ pn ++ " --gui -fsp 0xdeadbeef             -- launch the GUI, using the given format"
+                              , ""
+                              , " Notes:"
+                              , "   - For encoding:"
+                              , "       - Use -- to separate your argument if it's a negative number."
+                              , "       - For floats: You can pass in NaN, Inf, -0, -Inf etc as the argument"
+                              , "                     along with a decimal (2.3, -4.1e5) or hexadecimal float (0x2.4p3)"
+                              , "       - FP4 (E2M1) has neither NaN nor Inf, so those inputs are rejected. Finite"
+                              , "         values outside its range of [-6, 6] saturate to the nearest end-point."
+                              , "       - FP4 (E0M3) is a sign-magnitude integer: a sign bit and a 3-bit magnitude,"
+                              , "         covering -7 to 7, with both a positive and a negative zero. It has no NaN"
+                              , "         and no Inf either, and values outside [-7, 7] saturate to the end-point."
+                              , "   - For decoding:"
+                              , "       - Use hexadecimal (0x) binary (0b), or N'h (verilog) notation as input."
+                              , "         Input must have one of these prefixes."
+                              , "       - You can use _,- or space as a digit to improve readability for the pattern to be decoded"
+                              , "       - With -lN parameter, you can decode multiple lanes of data."
+                              , "       - If you use verilog input format, then we will infer the number of lanes unless you provide it."
+                              ]
 
 -- | Terminate early
 die :: [String] -> IO a
@@ -409,6 +439,9 @@
                   (_,  _,  errs@(_:_)) -> die $ errs ++ lines (helpStr pn)
                   (os, rs, [])
                     | Version `elem` os -> putStrLn $ pn ++ " v" ++ showVersion version ++ ", " ++ copyRight
+                    -- NB. Machine readable, one name per line: this is what the editor
+                    -- integrations use so they need not hardcode the list of formats.
+                    | Formats `elem` os -> mapM_ putStrLn fpFormatNames
                     | Help    `elem` os -> usage pn
                     -- NB. Check for bad flags before launching: otherwise a typo like
                     -- "-ft32" would silently bring the GUI up with nothing selected.
