diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## [0.0.0.4] - 2026-02-25
+
+### Changed
+
+* `pureGoldenNixOptions` now prepends a generated file comment pointing to the test that generated each file
+
 ## [0.0.0.3] - 2025-11-20
 
 ### Added
diff --git a/opt-env-conf-test.cabal b/opt-env-conf-test.cabal
--- a/opt-env-conf-test.cabal
+++ b/opt-env-conf-test.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.36.1.
+-- This file has been generated from package.yaml by hpack version 0.38.3.
 --
 -- see: https://github.com/sol/hpack
 
 name:           opt-env-conf-test
-version:        0.0.0.3
+version:        0.0.0.4
 synopsis:       A testing companion package for opt-env-conf
 homepage:       https://github.com/NorfairKing/opt-env-conf#readme
 bug-reports:    https://github.com/NorfairKing/opt-env-conf/issues
diff --git a/src/OptEnvConf/Test.hs b/src/OptEnvConf/Test.hs
--- a/src/OptEnvConf/Test.hs
+++ b/src/OptEnvConf/Test.hs
@@ -38,10 +38,12 @@
 where
 
 import Data.Aeson as JSON
+import Data.Char (isDigit)
 import Data.Maybe
 import Data.Text (Text)
 import qualified Data.Text as T
-import GHC.Stack (HasCallStack, withFrozenCallStack)
+import GHC.Stack (CallStack, HasCallStack, getCallStack, withFrozenCallStack)
+import qualified GHC.Stack as Stack
 import OptEnvConf
 import OptEnvConf.Args
 import OptEnvConf.Completion
@@ -106,7 +108,8 @@
   let arg = fromMaybe "" $ listToMaybe $ drop ix ws
   let completions = pureCompletionQuery p ix ws
   evaluatedCompletions <- evalCompletions arg completions
-  evaluatedCompletions `shouldBe` expected
+  let toStringCompletion c = c {completionSuggestion = completionResultValue (completionSuggestion c)}
+  map toStringCompletion evaluatedCompletions `shouldBe` expected
 
 parserCompletionDescriptionTest :: Parser a -> Int -> [String] -> [String] -> IO ()
 parserCompletionDescriptionTest p ix ws descriptions = do
@@ -136,7 +139,42 @@
   specify "produces the nix options as before" $
     pureGoldenNixOptions path parser
 
-pureGoldenNixOptions :: FilePath -> Parser a -> GoldenTest Text
+pureGoldenNixOptions :: (HasCallStack) => FilePath -> Parser a -> GoldenTest Text
 pureGoldenNixOptions path parser =
   pureGoldenTextFile path $
-    renderParserNixOptions parser
+    generatedFileComment Stack.callStack <> renderParserNixOptions parser
+
+generatedFileComment :: CallStack -> T.Text
+generatedFileComment cs =
+  let loc = case getCallStack cs of
+        (_, srcLoc) : _ ->
+          packageName (Stack.srcLocPackage srcLoc)
+            <> ":"
+            <> Stack.srcLocFile srcLoc
+            <> ":"
+            <> show (Stack.srcLocStartLine srcLoc)
+        [] -> "unknown"
+   in T.pack $
+        unlines $
+          map
+            ("# " <>)
+            [ "DO NOT EDIT THIS FILE DIRECTLY",
+              "This file was generated by",
+              loc,
+              "To update this it, run the test with --golden-reset"
+            ]
+
+-- | Extract just the package name from a GHC package identifier.
+--
+-- GHC package identifiers look like: @name-version-hash-unitid@
+-- This function returns just @name@.
+packageName :: String -> String
+packageName = go
+  where
+    go [] = []
+    go ('-' : rest)
+      | isVersion version = []
+      where
+        version = takeWhile (\c -> isDigit c || c == '.') rest
+    go (c : rest) = c : go rest
+    isVersion v = not (null v) && elem '.' v && all (\c -> isDigit c || c == '.') v
diff --git a/test/OptEnvConf/APISpec.hs b/test/OptEnvConf/APISpec.hs
--- a/test/OptEnvConf/APISpec.hs
+++ b/test/OptEnvConf/APISpec.hs
@@ -112,8 +112,7 @@
         parserDocs p
 
   it "renders the Nix options the same way" $
-    pureGoldenTextFile ("test_resources/docs/" <> dir <> "/nix-options.nix") $
-      renderParserNixOptions p
+    pureGoldenNixOptions ("test_resources/docs/" <> dir <> "/nix-options.nix") p
 
 sameHelpParser :: Parser (Either Int String, Bool)
 sameHelpParser =
diff --git a/test/OptEnvConf/CompleterSpec.hs b/test/OptEnvConf/CompleterSpec.hs
--- a/test/OptEnvConf/CompleterSpec.hs
+++ b/test/OptEnvConf/CompleterSpec.hs
@@ -27,6 +27,9 @@
         -- File in dir in dir
         exampleFile3 <- resolveFile deeperDir "gold.txt"
         writeFile (fromAbsFile exampleFile3) ""
+        -- YAML file
+        yamlFile <- resolveFile tdir "config.yaml"
+        writeFile (fromAbsFile yamlFile) ""
         -- Hidden file
         hiddenFile <- resolveFile tdir ".hidden.txt"
         writeFile (fromAbsFile hiddenFile) ""
@@ -43,37 +46,192 @@
       )
     $ do
       describe "filePath" $ do
-        let c :: (HasCallStack) => String -> [String] -> TestDef '[Path Abs Dir] ()
+        let c :: (HasCallStack) => String -> [CompletionResult] -> TestDef '[Path Abs Dir] ()
             c s l =
               withFrozenCallStack $
-                itWithOuter (unwords ["can complete", show s, "to", show l]) $ \tdir ->
+                itWithOuter (unwords ["can complete", show s, "to", show (map completionResultValue l)]) $ \tdir ->
                   withCurrentDir tdir $
                     unCompleter filePath s `shouldReturn` l
 
-        c "" ["foo.txt", "bar/"]
-        c "f" ["foo.txt"]
-        c "b" ["bar/"]
-        c "bar" ["bar/quux.txt", "bar/", "bar/deep/"]
+        c "" [fileR "foo.txt", fileR "config.yaml", dirR "bar/"]
+        c "f" [fileR "foo.txt"]
+        c "b" [dirR "bar/"]
+        c "bar" [fileR "bar/quux.txt", dirR "bar/", dirR "bar/deep/"]
+        c "c" [fileR "config.yaml"]
         c "q" []
-        c "." [".hidden.txt", ".hidden/"]
-        c "./" ["./foo.txt", "./bar/"]
-        c "././" ["././foo.txt", "././bar/"]
-        c "./." ["./.hidden.txt", "./.hidden/"]
-        c "./bar" ["./bar/quux.txt", "./bar/", "./bar/deep/"]
+        c "." [fileR ".hidden.txt", dirR ".hidden/"]
+        c "./" [fileR "./foo.txt", fileR "./config.yaml", dirR "./bar/"]
+        c "././" [fileR "././foo.txt", fileR "././config.yaml", dirR "././bar/"]
+        c "./." [fileR "./.hidden.txt", dirR "./.hidden/"]
+        c "./bar" [fileR "./bar/quux.txt", dirR "./bar/", dirR "./bar/deep/"]
 
+        -- Deeper nesting.
+        -- Directories end in /, files do not.  This convention is how
+        -- shells decide whether to append a trailing space after a
+        -- completion.
+        c "bar/" [fileR "bar/quux.txt", dirR "bar/deep/"]
+        c "bar/d" [dirR "bar/deep/"]
+        c "bar/deep" [fileR "bar/deep/gold.txt", dirR "bar/deep/"]
+        c "bar/deep/" [fileR "bar/deep/gold.txt"]
+        c "bar/q" [fileR "bar/quux.txt"]
+
+        -- Parent directory paths (..)
+        -- These tests run from inside bar/ so that .. refers to the
+        -- test root directory.
+        itWithOuter "can complete \"..\" to parent directory contents" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter filePath ".."
+            results
+              `shouldBe` [ fileR "../foo.txt",
+                           fileR "../config.yaml",
+                           dirR "../bar/"
+                         ]
+        itWithOuter "can complete \"../\" to parent directory contents" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter filePath "../"
+            results
+              `shouldBe` [ fileR "../foo.txt",
+                           fileR "../config.yaml",
+                           dirR "../bar/"
+                         ]
+        itWithOuter "can complete \"../f\" to matching parent files" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter filePath "../f"
+            results
+              `shouldBe` [fileR "../foo.txt"]
+        itWithOuter "can complete \"../bar/\" to sibling dir contents" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter filePath "../bar/"
+            results
+              `shouldBe` [ fileR "../bar/quux.txt",
+                           dirR "../bar/deep/"
+                         ]
+
+        -- Parent directory in the middle of a path
+        itWithOuter "can complete \"bar/../\" to current dir contents" $ \tdir ->
+          withCurrentDir tdir $ do
+            results <- unCompleter filePath "bar/../"
+            results
+              `shouldBe` [ fileR "bar/../foo.txt",
+                           fileR "bar/../config.yaml",
+                           dirR "bar/../bar/"
+                         ]
+        itWithOuter "can complete \"bar/../f\" to matching files" $ \tdir ->
+          withCurrentDir tdir $ do
+            results <- unCompleter filePath "bar/../f"
+            results
+              `shouldBe` [fileR "bar/../foo.txt"]
+        itWithOuter "can complete \"../bar/deep/../\" to bar/ contents" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter filePath "../bar/deep/../"
+            results
+              `shouldBe` [ fileR "../bar/deep/../quux.txt",
+                           dirR "../bar/deep/../deep/"
+                         ]
+
+        -- Absolute paths
+        itWithOuter "can complete absolute paths" $ \tdir ->
+          withCurrentDir tdir $ do
+            let absPrefix = fromAbsDir tdir
+            results <- unCompleter filePath absPrefix
+            results
+              `shouldBe` [ fileR (absPrefix <> "foo.txt"),
+                           fileR (absPrefix <> "config.yaml"),
+                           dirR (absPrefix <> "bar/")
+                         ]
+
       describe "directoryPath" $ do
-        let c :: (HasCallStack) => String -> [String] -> TestDef '[Path Abs Dir] ()
+        let c :: (HasCallStack) => String -> [CompletionResult] -> TestDef '[Path Abs Dir] ()
             c s l = withFrozenCallStack $
-              itWithOuter (unwords ["can complete", show s, "to", show l]) $ \tdir ->
+              itWithOuter (unwords ["can complete", show s, "to", show (map completionResultValue l)]) $ \tdir ->
                 withCurrentDir tdir $
                   unCompleter directoryPath s `shouldReturn` l
 
-        c "" ["bar/"]
-        c "b" ["bar/"]
+        c "" [dirR "bar/"]
+        c "b" [dirR "bar/"]
         c "f" []
-        c "." [".hidden/"]
-        c "./" ["./bar/"]
-        c "./." ["./.hidden/"]
-        c "././" ["././bar/"]
-        c "./." ["./.hidden/"]
-        c "./bar" ["./bar/", "./bar/deep/"]
+        c "." [dirR ".hidden/"]
+        c "./" [dirR "./bar/"]
+        c "./." [dirR "./.hidden/"]
+        c "././" [dirR "././bar/"]
+        c "./." [dirR "./.hidden/"]
+        c "./bar" [dirR "./bar/", dirR "./bar/deep/"]
+
+        -- Deeper nesting.
+        -- Only directories are returned, never files.
+        c "bar/" [dirR "bar/", dirR "bar/deep/"]
+        c "bar/d" [dirR "bar/deep/"]
+        c "bar/deep" [dirR "bar/deep/"]
+
+        -- Parent directory paths (..)
+        itWithOuter "can complete \"..\" to parent directories" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter directoryPath ".."
+            results
+              `shouldBe` [dirR "../bar/"]
+        itWithOuter "can complete \"../\" to parent directories" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter directoryPath "../"
+            results
+              `shouldBe` [dirR "../bar/"]
+        itWithOuter "can complete \"../b\" to matching parent directories" $ \tdir -> do
+          subdir <- resolveDir tdir "bar"
+          withCurrentDir subdir $ do
+            results <- unCompleter directoryPath "../b"
+            results
+              `shouldBe` [dirR "../bar/"]
+
+        -- Parent directory in the middle of a path
+        itWithOuter "can complete \"bar/../\" to current dir directories" $ \tdir ->
+          withCurrentDir tdir $ do
+            results <- unCompleter directoryPath "bar/../"
+            results
+              `shouldBe` [dirR "bar/../bar/"]
+        itWithOuter "can complete \"bar/../b\" to matching directories" $ \tdir ->
+          withCurrentDir tdir $ do
+            results <- unCompleter directoryPath "bar/../b"
+            results
+              `shouldBe` [dirR "bar/../bar/"]
+
+      describe "filePathWithExtension" $ do
+        let c :: (HasCallStack) => String -> [CompletionResult] -> TestDef '[Path Abs Dir] ()
+            c s l = withFrozenCallStack $
+              itWithOuter (unwords ["can complete", show s, "to", show (map completionResultValue l)]) $ \tdir ->
+                withCurrentDir tdir $
+                  unCompleter (filePathWithExtension ".yaml") s `shouldReturn` l
+
+        c "" [fileR "config.yaml", dirR "bar/"]
+        c "c" [fileR "config.yaml"]
+        c "b" [dirR "bar/"]
+        c "bar" [dirR "bar/", dirR "bar/deep/"]
+
+      describe "filePathWithExtensions" $ do
+        let c :: (HasCallStack) => String -> [CompletionResult] -> TestDef '[Path Abs Dir] ()
+            c s l = withFrozenCallStack $
+              itWithOuter (unwords ["can complete", show s, "to", show (map completionResultValue l)]) $ \tdir ->
+                withCurrentDir tdir $
+                  unCompleter (filePathWithExtensions [".txt", ".yaml"]) s `shouldReturn` l
+
+        c "" [fileR "foo.txt", fileR "config.yaml", dirR "bar/"]
+        c "bar/" [fileR "bar/quux.txt", dirR "bar/deep/"]
+
+fileR :: String -> CompletionResult
+fileR s =
+  CompletionResult
+    { completionResultValue = s,
+      completionResultFinality = CompletionFinal
+    }
+
+dirR :: String -> CompletionResult
+dirR s =
+  CompletionResult
+    { completionResultValue = s,
+      completionResultFinality = CompletionNotFinal
+    }
diff --git a/test/OptEnvConf/CompletionSpec.hs b/test/OptEnvConf/CompletionSpec.hs
--- a/test/OptEnvConf/CompletionSpec.hs
+++ b/test/OptEnvConf/CompletionSpec.hs
@@ -4,236 +4,1543 @@
 module OptEnvConf.CompletionSpec (spec) where
 
 import Control.Applicative
-import OptEnvConf.Completer
-import OptEnvConf.Completion
-import OptEnvConf.Parser
-import OptEnvConf.Setting
-import OptEnvConf.Test
-import Path
-import Test.Syd
-
-spec :: Spec
-spec = do
-  describe "bash" $ do
-    it "produces the same bash completion script" $
-      pureGoldenStringFile "test_resources/completion/bash-completion-script.bash" $
-        bashCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
-  describe "zsh" $ do
-    it "produces the same zsh completion script" $
-      pureGoldenStringFile "test_resources/completion/zsh-completion-script.zsh" $
-        zshCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
-  describe "fish" $ do
-    it "produces the same fish completion script" $
-      pureGoldenStringFile "test_resources/completion/fish-completion-script.fish" $
-        fishCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
-
-  describe "pureCompletionQuery" $ do
-    it "can complete a switch from nothing" $
-      parserCompletionTest
-        (setting [switch (), short 'e', long "example"])
-        0
-        []
-        ["--example"] -- Only the long version
-    it "can complete a short switch from a single dash" $
-      parserCompletionTest
-        (setting [switch (), short 'e'])
-        0
-        ["-"]
-        ["-e"]
-
-    it "can complete a long switch from a single dash" $
-      parserCompletionTest
-        (setting [switch (), long "example"])
-        0
-        ["-"]
-        ["--example"]
-
-    it "can complete a long switch from a double dash" $
-      parserCompletionTest
-        (setting [switch (), long "example"])
-        0
-        ["--"]
-        ["--example"]
-
-    it "can complete a short option's dashed" $
-      parserCompletionTest
-        (setting [option, short 'e', completer $ listCompleter ["hi"]])
-        0
-        []
-        ["-e"]
-
-    it "can complete a long option's dashed" $
-      parserCompletionTest
-        (setting [option, long "example", completer $ listCompleter ["hi"]])
-        0
-        []
-        ["--example"]
-
-    it "can complete a short option with a separate arg" $
-      parserCompletionTest
-        (setting [option, short 'e', completer $ listCompleter ["hi"]])
-        1
-        ["-e"]
-        ["hi"]
-
-    -- Don't think we want to support this.
-    -- pending "can complete a short option in short-hand mode.
-
-    it "can complete a long option" $
-      parserCompletionTest
-        (setting [option, long "example", completer $ listCompleter ["hi"]])
-        1
-        ["--example"]
-        ["hi"]
-
-    -- Don't think we want to support this
-    -- pending "can complete a long option with equals sign"
-
-    it "can complete both switches of a tuple" $
-      parserCompletionTest
-        ((,) <$> setting [switch (), long "foo"] <*> setting [switch (), long "bar"])
-        0
-        []
-        ["--foo", "--bar"]
-
-    it "can complete both switches of a tuple, with a prefix" $
-      parserCompletionTest
-        ((,) <$> setting [switch (), long "bar"] <*> setting [switch (), long "baz"])
-        0
-        ["--b"]
-        ["--bar", "--baz"]
-
-    it "can complete both switches of an either" $
-      parserCompletionTest
-        (setting [switch (), long "foo"] <|> setting [switch (), long "bar"])
-        0
-        []
-        ["--foo", "--bar"]
-
-    it "can complete both switches of an either wrapped in optionals" $
-      parserCompletionTest
-        (optional (setting [switch (), long "foo"]) <|> optional (setting [switch (), long "bar"]))
-        0
-        []
-        ["--foo", "--bar"]
-
-    describe "commands" $ do
-      let p =
-            commands
-              [ command "foo" "1" $ pure (),
-                command "bar" "2" $ pure (),
-                command "baz" "3" $ pure ()
-              ]
-
-      it "can complete a command argument" $
-        parserCompletionTest
-          p
-          0
-          []
-          [Completion "foo" (Just "1"), Completion "bar" (Just "2"), Completion "baz" (Just "3")]
-
-      it "can complete a command argument when it's been partially provided" $
-        parserCompletionTest
-          p
-          0
-          ["b"]
-          [Completion "bar" (Just "2"), Completion "baz" (Just "3")]
-
-    describe "completion after a command" $ do
-      it "can complete a command with a switch" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [help "ex", switch (), short 'e', long "example"]])
-          1
-          ["foo"]
-          [Completion "--example" (Just "ex")] -- Only the long version
-      it "can complete a command's short switch" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [switch (), short 'e']])
-          1
-          ["foo", "-"]
-          ["-e"]
-
-      it "can complete a command's long switch from a single dash" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [switch (), long "example"]])
-          1
-          ["foo", "-"]
-          ["--example"]
-
-      it "can complete a command's long switch from a double dash" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [switch (), long "example"]])
-          1
-          ["foo", "--"]
-          ["--example"]
-
-      it "can complete a command's short option" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [option, short 'e', completer $ listCompleter ["hi"]]])
-          2
-          ["foo", "-e"]
-          ["hi"]
-
-      it "can complete a command's long option" $
-        parserCompletionTest
-          (commands [command "foo" "1" $ setting [option, long "example", completer $ listCompleter ["hi"]]])
-          2
-          ["foo", "--example"]
-          ["hi"]
-
-    it "can complete a file argument" $
-      parserCompletionDescriptionTest
-        (filePathSetting [help "file arg", argument])
-        0
-        []
-        ["file arg"]
-
-    it "can complete a file option" $
-      parserCompletionDescriptionTest
-        (filePathSetting [help "file arg", option, long "file"])
-        1
-        ["--file"]
-        ["file arg"]
-
-    it "can complete a directory argument" $
-      parserCompletionDescriptionTest
-        (directoryPathSetting [help "dir arg", argument])
-        0
-        []
-        ["dir arg"]
-
-    it "can complete a directory option" $
-      parserCompletionDescriptionTest
-        (directoryPathSetting [help "dir arg", option, long "file"])
-        1
-        ["--file"]
-        ["dir arg"]
-
-    it "no longer suggests a switch that has already been parsed" $
-      parserCompletionTest
-        ((,) <$> setting [switch (), long "foo"] <*> setting [switch (), long "bar"])
-        1
-        ["--foo"]
-        ["--bar"]
-
-    it "no longer suggests an option that has already been parsed" $
-      parserCompletionTest
-        ( (,,)
-            <$> setting [option, reader (str :: Reader String), long "foo"]
-            <*> setting [option, reader (str :: Reader String), long "bar"]
-            <*> setting [switch (), long "quux"]
-        )
-        2
-        ["--foo", "foo"]
-        ["--bar", "--quux"]
-
-    it "no longer suggests an argument that has already been parsed" $
-      parserCompletionDescriptionTest
-        ( (,,)
-            <$> setting [argument, reader (str :: Reader String), help "hi", completer $ listCompleter ["hi"]]
-            <*> setting [argument, reader (str :: Reader String), help "ho", completer $ listCompleter ["ho"]]
-            <*> setting [switch (), long "bar", help "hu"]
-        )
-        1
-        ["foo"]
-        ["ho", "hu"]
+import qualified Data.List.NonEmpty as NE
+import Data.Maybe
+import OptEnvConf.Completer
+import OptEnvConf.Completion
+import OptEnvConf.Parser
+import OptEnvConf.Setting
+import OptEnvConf.Test
+import Path
+import Path.IO
+import Test.Syd
+
+spec :: Spec
+spec = do
+  describe "bash" $ do
+    it "produces the same bash completion script" $
+      pureGoldenStringFile "test_resources/completion/bash-completion-script.bash" $
+        bashCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
+  describe "zsh" $ do
+    it "produces the same zsh completion script" $
+      pureGoldenStringFile "test_resources/completion/zsh-completion-script.zsh" $
+        zshCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
+  describe "fish" $ do
+    it "produces the same fish completion script" $
+      pureGoldenStringFile "test_resources/completion/fish-completion-script.fish" $
+        fishCompletionScript [absfile|/usr/bin/example-executable|] "example-executable"
+
+  describe "pureCompletionQuery" $ do
+    it "can complete a switch from nothing" $
+      parserCompletionTest
+        (setting [switch (), short 'e', long "example"])
+        0
+        []
+        ["--example"] -- Only the long version
+    it "can complete a short switch from a single dash" $
+      parserCompletionTest
+        (setting [switch (), short 'e'])
+        0
+        ["-"]
+        ["-e"]
+
+    it "can complete a long switch from a single dash" $
+      parserCompletionTest
+        (setting [switch (), long "example"])
+        0
+        ["-"]
+        ["--example"]
+
+    it "can complete a long switch from a double dash" $
+      parserCompletionTest
+        (setting [switch (), long "example"])
+        0
+        ["--"]
+        ["--example"]
+
+    it "can complete a short option's dashed" $
+      parserCompletionTest
+        (setting [option, short 'e', completer $ listCompleter ["hi"]])
+        0
+        []
+        ["-e"]
+
+    it "can complete a long option's dashed" $
+      parserCompletionTest
+        (setting [option, long "example", completer $ listCompleter ["hi"]])
+        0
+        []
+        ["--example"]
+
+    it "can complete a short option with a separate arg" $
+      parserCompletionTest
+        (setting [option, short 'e', completer $ listCompleter ["hi"]])
+        1
+        ["-e"]
+        ["hi"]
+
+    -- Don't think we want to support this.
+    -- pending "can complete a short option in short-hand mode.
+
+    it "can complete a long option" $
+      parserCompletionTest
+        (setting [option, long "example", completer $ listCompleter ["hi"]])
+        1
+        ["--example"]
+        ["hi"]
+
+    -- Don't think we want to support this
+    -- pending "can complete a long option with equals sign"
+
+    it "can complete both switches of a tuple" $
+      parserCompletionTest
+        ((,) <$> setting [switch (), long "foo"] <*> setting [switch (), long "bar"])
+        0
+        []
+        [ "--foo",
+          "--bar"
+        ]
+
+    it "can complete both switches of a tuple, with a prefix" $
+      parserCompletionTest
+        ((,) <$> setting [switch (), long "bar"] <*> setting [switch (), long "baz"])
+        0
+        ["--b"]
+        [ "--bar",
+          "--baz"
+        ]
+
+    it "can complete both switches of an either" $
+      parserCompletionTest
+        (setting [switch (), long "foo"] <|> setting [switch (), long "bar"])
+        0
+        []
+        [ "--foo",
+          "--bar"
+        ]
+
+    it "can complete both switches of an either wrapped in optionals" $
+      parserCompletionTest
+        (optional (setting [switch (), long "foo"]) <|> optional (setting [switch (), long "bar"]))
+        0
+        []
+        [ "--foo",
+          "--bar"
+        ]
+
+    describe "commands" $ do
+      let p =
+            commands
+              [ command "foo" "1" $ pure (),
+                command "bar" "2" $ pure (),
+                command "baz" "3" $ pure ()
+              ]
+
+      it "can complete a command argument" $
+        parserCompletionTest
+          p
+          0
+          []
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2"),
+            Completion "baz" (Just "3")
+          ]
+
+      it "can complete a command argument when it's been partially provided" $
+        parserCompletionTest
+          p
+          0
+          ["b"]
+          [ Completion "bar" (Just "2"),
+            Completion "baz" (Just "3")
+          ]
+
+    describe "completion after a command" $ do
+      it "can complete a command with a switch" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [help "ex", switch (), short 'e', long "example"]])
+          1
+          ["foo"]
+          [Completion "--example" (Just "ex")] -- Only the long version
+      it "can complete a command's short switch" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [switch (), short 'e']])
+          1
+          ["foo", "-"]
+          ["-e"]
+
+      it "can complete a command's long switch from a single dash" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [switch (), long "example"]])
+          1
+          ["foo", "-"]
+          ["--example"]
+
+      it "can complete a command's long switch from a double dash" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [switch (), long "example"]])
+          1
+          ["foo", "--"]
+          ["--example"]
+
+      it "can complete a command's short option" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [option, short 'e', completer $ listCompleter ["hi"]]])
+          2
+          ["foo", "-e"]
+          ["hi"]
+
+      it "can complete a command's long option" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ setting [option, long "example", completer $ listCompleter ["hi"]]])
+          2
+          ["foo", "--example"]
+          ["hi"]
+
+    it "can complete a file argument" $
+      parserCompletionDescriptionTest
+        (filePathSetting [help "file arg", argument])
+        0
+        []
+        ["file arg"]
+
+    it "can complete a file option" $
+      parserCompletionDescriptionTest
+        (filePathSetting [help "file arg", option, long "file"])
+        1
+        ["--file"]
+        ["file arg"]
+
+    it "can complete a directory argument" $
+      parserCompletionDescriptionTest
+        (directoryPathSetting [help "dir arg", argument])
+        0
+        []
+        ["dir arg"]
+
+    it "can complete a directory option" $
+      parserCompletionDescriptionTest
+        (directoryPathSetting [help "dir arg", option, long "file"])
+        1
+        ["--file"]
+        ["dir arg"]
+
+    it "no longer suggests a switch that has already been parsed" $
+      parserCompletionTest
+        ((,) <$> setting [switch (), long "foo"] <*> setting [switch (), long "bar"])
+        1
+        ["--foo"]
+        ["--bar"]
+
+    it "no longer suggests an option that has already been parsed" $
+      parserCompletionTest
+        ( (,,)
+            <$> setting [option, reader (str :: Reader String), long "foo"]
+            <*> setting [option, reader (str :: Reader String), long "bar"]
+            <*> setting [switch (), long "quux"]
+        )
+        2
+        ["--foo", "foo"]
+        [ "--bar",
+          "--quux"
+        ]
+
+    it "no longer suggests an argument that has already been parsed" $
+      parserCompletionDescriptionTest
+        ( (,,)
+            <$> setting [argument, reader (str :: Reader String), help "hi", completer $ listCompleter ["hi"]]
+            <*> setting [argument, reader (str :: Reader String), help "ho", completer $ listCompleter ["ho"]]
+            <*> setting [switch (), long "bar", help "hu"]
+        )
+        1
+        ["foo"]
+        [ "ho",
+          "hu"
+        ]
+
+    describe "commands with a default command" $ do
+      let p =
+            commands
+              [ command "foo" "1" $ pure (),
+                command "bar" "2" $ pure (),
+                command "baz" "3" $ pure (),
+                defaultCommand "bar"
+              ]
+
+      it "still lists all commands when there is a default" $
+        parserCompletionTest
+          p
+          0
+          []
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2"),
+            Completion "baz" (Just "3")
+          ]
+
+      it "still filters commands by prefix when there is a default" $
+        parserCompletionTest
+          p
+          0
+          ["b"]
+          [ Completion "bar" (Just "2"),
+            Completion "baz" (Just "3")
+          ]
+
+      it "completes the default command's switch when no command is given" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [switch (), long "example"],
+                command "bar" "2" $ pure (),
+                defaultCommand "foo"
+              ]
+          )
+          0
+          ["--"]
+          ["--example"]
+
+      it "completes both commands and the default command's switch" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [switch (), long "example"],
+                command "bar" "2" $ pure (),
+                defaultCommand "foo"
+              ]
+          )
+          0
+          []
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2"),
+            "--example"
+          ]
+
+      it "completes the default command's option when no command is given" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [option, long "example", completer $ listCompleter ["hi"]],
+                command "bar" "2" $ pure (),
+                defaultCommand "foo"
+              ]
+          )
+          0
+          ["--"]
+          ["--example"]
+
+      it "completes the default command's option value when no command is given" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [option, long "example", reader (str :: Reader String), completer $ listCompleter ["hi"]],
+                command "bar" "2" $ pure "bar",
+                defaultCommand "foo"
+              ]
+          )
+          1
+          ["--example"]
+          ["hi"]
+
+      it "completes the default command's argument when no command is given" $
+        parserCompletionDescriptionTest
+          ( commands
+              [ command "foo" "1" $ setting [argument, reader (str :: Reader String), help "arg help", completer $ listCompleter ["val"]],
+                command "bar" "2" $ pure "bar",
+                defaultCommand "foo"
+              ]
+          )
+          0
+          []
+          -- Should include the default command's argument completer along with command names
+          [ "1",
+            "2",
+            "arg help"
+          ]
+
+      it "completes inside the default command after consuming its switch" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $
+                  (,)
+                    <$> setting [switch (), long "first"]
+                    <*> setting [switch (), long "second"],
+                command "bar" "2" $ pure ((), ()),
+                defaultCommand "foo"
+              ]
+          )
+          1
+          ["--first"]
+          ["--second"]
+
+      it "completes inside the default command after consuming its option" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $
+                  (,)
+                    <$> setting [option, reader (str :: Reader String), long "name"]
+                    <*> setting [switch (), long "verbose"],
+                command "bar" "2" $ pure ("bar", ()),
+                defaultCommand "foo"
+              ]
+          )
+          2
+          ["--name", "hello"]
+          ["--verbose"]
+
+    describe "global options with commands and a default" $ do
+      it "completes global options and commands together" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> commands
+                [ command "foo" "1" $ pure (),
+                  command "bar" "2" $ pure (),
+                  defaultCommand "foo"
+                ]
+          )
+          0
+          []
+          [ "--verbose",
+            Completion "foo" (Just "1"),
+            Completion "bar" (Just "2")
+          ]
+
+      it "completes commands after a global option" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> commands
+                [ command "foo" "1" $ pure (),
+                  command "bar" "2" $ pure (),
+                  defaultCommand "foo"
+                ]
+          )
+          1
+          ["--verbose"]
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2")
+          ]
+
+      it "completes the default command's options after a global option" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> commands
+                [ command "foo" "1" $ setting [switch (), long "example"],
+                  command "bar" "2" $ pure (),
+                  defaultCommand "foo"
+                ]
+          )
+          1
+          ["--verbose"]
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2"),
+            "--example"
+          ]
+
+    describe "many" $ do
+      it "can complete repeated switches" $
+        parserCompletionTest
+          (length <$> many (setting [switch (), long "verbose", short 'v']))
+          0
+          []
+          ["--verbose"]
+
+      it "can still complete after consuming one" $
+        parserCompletionTest
+          (length <$> many (setting [switch (), long "verbose", short 'v']))
+          1
+          ["--verbose"]
+          ["--verbose"]
+
+      it "can still complete after consuming two" $
+        parserCompletionTest
+          (length <$> many (setting [switch (), long "verbose", short 'v']))
+          2
+          ["-v", "-v"]
+          ["--verbose"]
+
+      it "can complete repeated options" $
+        parserCompletionTest
+          ( many
+              ( setting
+                  [ option,
+                    reader (str :: Reader String),
+                    long "include",
+                    completer $ listCompleter ["foo", "bar"]
+                  ]
+              )
+          )
+          1
+          ["--include"]
+          [ "foo",
+            "bar"
+          ]
+
+      it "can complete repeated options after one has already been parsed" $
+        parserCompletionTest
+          ( many
+              ( setting
+                  [ option,
+                    reader (str :: Reader String),
+                    long "include",
+                    completer $ listCompleter ["foo", "bar"]
+                  ]
+              )
+          )
+          3
+          [ "--include",
+            "foo",
+            "--include"
+          ]
+          [ "foo",
+            "bar"
+          ]
+
+    describe "some" $ do
+      it "can complete at least one switch" $
+        parserCompletionTest
+          (NE.length <$> someNonEmpty (setting [switch (), long "verbose", short 'v']))
+          0
+          []
+          ["--verbose"]
+
+      it "can still complete after consuming one" $
+        parserCompletionTest
+          (NE.length <$> someNonEmpty (setting [switch (), long "verbose", short 'v']))
+          1
+          ["--verbose"]
+          ["--verbose"]
+
+    describe "allOrNothing" $ do
+      it "completes normally inside allOrNothing" $
+        parserCompletionTest
+          ( allOrNothing $
+              (,)
+                <$> setting [option, reader (str :: Reader String), long "host"]
+                <*> setting [option, reader (str :: Reader String), long "port"]
+          )
+          0
+          []
+          [ "--host",
+            "--port"
+          ]
+
+      it "still suggests the remaining option after one is consumed" $
+        parserCompletionTest
+          ( allOrNothing $
+              (,)
+                <$> setting [option, reader (str :: Reader String), long "host"]
+                <*> setting [option, reader (str :: Reader String), long "port"]
+          )
+          2
+          ["--host", "localhost"]
+          ["--port"]
+
+    describe "check" $ do
+      it "completes through a checkMapEither" $
+        parserCompletionTest
+          ( checkMapEither
+              (\s -> if null s then Left "empty" else Right s)
+              (setting [argument, reader (str :: Reader String), completer $ listCompleter ["hello"]])
+          )
+          0
+          []
+          ["hello"]
+
+      it "completes through a mapIO" $
+        parserCompletionTest
+          ( mapIO pure $
+              setting [switch (), long "example"]
+          )
+          0
+          []
+          ["--example"]
+
+    describe "hidden settings" $ do
+      it "does not suggest hidden switches" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "visible"]
+              <*> setting [switch (), long "secret", hidden]
+          )
+          0
+          []
+          ["--visible"]
+
+      it "does not suggest hidden options" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [option, reader (str :: Reader String), long "visible"]
+              <*> setting [option, reader (str :: Reader String), long "secret", hidden]
+          )
+          0
+          []
+          ["--visible"]
+
+    describe "settings with only env or conf" $ do
+      it "does not error on env-only settings combined with arg settings" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [reader (str :: Reader String), env "MY_VAR"]
+          )
+          0
+          []
+          ["--verbose"]
+
+    describe "enableDisableSwitch" $ do
+      -- enableDisableSwitch uses a visible "dummy" with the
+      -- (enable|disable)- prefix for documentation, while the actual
+      -- --enable-feature and --disable-feature switches are hidden.
+      it "completes the documented dummy flag" $
+        parserCompletionTest
+          ( enableDisableSwitch
+              [ help "enable feature",
+                name "feature",
+                value False
+              ]
+          )
+          0
+          []
+          [Completion "--(enable|disable)-feature" (Just "enable feature")]
+
+      it "filters the documented flag by prefix" $
+        parserCompletionTest
+          ( enableDisableSwitch
+              [ help "enable feature",
+                name "feature",
+                value False
+              ]
+          )
+          0
+          ["--(e"]
+          [Completion "--(enable|disable)-feature" (Just "enable feature")]
+
+    describe "choice" $ do
+      it "completes across all choices" $
+        parserCompletionTest
+          ( choice
+              [ setting [switch (), long "alpha"],
+                setting [switch (), long "beta"],
+                setting [switch (), long "gamma"]
+              ]
+          )
+          0
+          []
+          [ "--alpha",
+            "--beta",
+            "--gamma"
+          ]
+
+    describe "withDefault" $ do
+      it "completes the underlying parser" $
+        parserCompletionTest
+          (withDefault "default" $ setting [option, reader (str :: Reader String), long "name", completer $ listCompleter ["alice", "bob"]])
+          1
+          ["--name"]
+          [ "alice",
+            "bob"
+          ]
+
+      it "still suggests the option when it has a default" $
+        parserCompletionTest
+          (withDefault "default" $ setting [option, reader (str :: Reader String), long "name"])
+          0
+          []
+          ["--name"]
+
+    describe "nested commands" $ do
+      let p =
+            commands
+              [ command "top" "top-level" $
+                  commands
+                    [ command "sub-a" "sub a" $ pure (),
+                      command "sub-b" "sub b" $ pure ()
+                    ],
+                command "other" "other" $ pure ()
+              ]
+
+      it "completes top-level commands" $
+        parserCompletionTest
+          p
+          0
+          []
+          [ Completion "top" (Just "top-level"),
+            Completion "other" (Just "other")
+          ]
+
+      it "completes sub-commands after selecting a top-level command" $
+        parserCompletionTest
+          p
+          1
+          ["top"]
+          [ Completion "sub-a" (Just "sub a"),
+            Completion "sub-b" (Just "sub b")
+          ]
+
+      it "filters sub-commands by prefix" $
+        parserCompletionTest
+          p
+          1
+          ["top", "sub-a"]
+          [Completion "sub-a" (Just "sub a")]
+
+      it "completes nested default commands" $
+        parserCompletionTest
+          ( commands
+              [ command "top" "top-level" $
+                  commands
+                    [ command "sub-a" "sub a" $ setting [switch (), long "flag"],
+                      command "sub-b" "sub b" $ pure (),
+                      defaultCommand "sub-a"
+                    ],
+                command "other" "other" $ pure ()
+              ]
+          )
+          1
+          ["top"]
+          [ Completion "sub-a" (Just "sub a"),
+            Completion "sub-b" (Just "sub b"),
+            "--flag"
+          ]
+
+    describe "commands merged via alternative" $ do
+      it "completes commands from both sides of an alternative" $
+        parserCompletionTest
+          ( commands [command "foo" "1" $ pure ()]
+              <|> commands [command "bar" "2" $ pure ()]
+          )
+          0
+          []
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2")
+          ]
+
+    describe "arguments after double dash" $ do
+      -- A bare -- is consumed as the argument value "--" when it's
+      -- the only argument remaining, so completion sees nothing left.
+      it "consumes -- as the argument value" $
+        parserCompletionTest
+          (setting [argument, reader (str :: Reader String), completer $ listCompleter ["file1", "file2"]])
+          1
+          ["--"]
+          []
+
+      -- After --, the completion should suggest positional arguments
+      -- rather than switches. Currently it does not: the switch is
+      -- still suggested because the completion engine does not
+      -- account for -- separating options from arguments.
+      it "suggests the switch even after -- (known bug)" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["file1", "file2"]]
+          )
+          2
+          ["--", "fi"]
+          ["--verbose"]
+
+    describe "mixed arguments and options" $ do
+      it "can complete an option after a positional argument" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["input"]]
+              <*> setting [switch (), long "verbose"]
+          )
+          1
+          ["input"]
+          ["--verbose"]
+
+      it "can complete a positional after an option" $
+        parserCompletionDescriptionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [argument, reader (str :: Reader String), help "file", completer $ listCompleter ["output"]]
+          )
+          1
+          ["--verbose"]
+          ["file"]
+
+    describe "multiple arguments" $ do
+      -- When no args have been typed, both argument completers fire
+      -- because the completion engine doesn't know which one will be
+      -- consumed first. This is the documented TODO in Completion.hs.
+      it "completes both arguments when none have been typed" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["src"]]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["dst"]]
+          )
+          0
+          []
+          [ "src",
+            "dst"
+          ]
+
+      it "completes the second argument after the first" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["src"]]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["dst"]]
+          )
+          1
+          ["something"]
+          ["dst"]
+
+    describe "empty parser" $ do
+      it "produces no completions for empty" $
+        parserCompletionTest
+          (empty :: Parser ())
+          0
+          []
+          []
+
+    describe "pure parser" $ do
+      it "produces no completions for pure" $
+        parserCompletionTest
+          (pure () :: Parser ())
+          0
+          []
+          []
+
+    describe "select" $ do
+      -- Select uses andCompletions: both branches contribute because
+      -- the completion engine cannot know at completion time whether
+      -- the first parser will return Left or Right.
+      it "completes through a select" $
+        parserCompletionTest
+          ( select
+              (Left <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["hello"]])
+              (const <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["world"]])
+          )
+          0
+          []
+          [ "hello",
+            "world"
+          ]
+
+    describe "withConfig" $ do
+      it "completes the main parser through withConfig" $
+        parserCompletionTest
+          ( withConfig (pure Nothing) $
+              setting [switch (), long "example"]
+          )
+          0
+          []
+          ["--example"]
+
+      it "completes the config file option together with the main parser" $
+        parserCompletionTest
+          ( withConfig
+              (Nothing <$ setting [option, reader (str :: Reader String), long "config-file", completer $ listCompleter ["config.yaml"]])
+              (setting [switch (), long "verbose"])
+          )
+          0
+          []
+          -- Main parser completions come first (p2), then config parser completions (p1)
+          [ "--verbose",
+            "--config-file"
+          ]
+
+      it "completes the config file value along with main parser suggestions" $
+        parserCompletionTest
+          ( withConfig
+              (Nothing <$ setting [option, reader (str :: Reader String), long "config-file", completer $ listCompleter ["config.yaml"]])
+              (setting [switch (), long "verbose"])
+          )
+          1
+          ["--config-file"]
+          -- The main parser (p2) still suggests --verbose since it hasn't
+          -- consumed anything, and the config parser (p1) offers the completer.
+          [ "--verbose",
+            "config.yaml"
+          ]
+
+      it "completes the main parser after the config option is consumed" $
+        parserCompletionTest
+          ( withConfig
+              (Nothing <$ setting [option, reader (str :: Reader String), long "config-file", completer $ listCompleter ["config.yaml"]])
+              (setting [switch (), long "verbose"])
+          )
+          2
+          ["--config-file", "config.yaml"]
+          ["--verbose"]
+
+    describe "optional" $ do
+      it "completes through an optional parser" $
+        parserCompletionTest
+          (optional $ setting [switch (), long "verbose"])
+          0
+          []
+          ["--verbose"]
+
+      it "completes an optional with an applicative" $
+        parserCompletionTest
+          ( (,)
+              <$> optional (setting [option, reader (str :: Reader String), long "name", completer $ listCompleter ["alice"]])
+              <*> setting [switch (), long "verbose"]
+          )
+          0
+          []
+          [ "--name",
+            "--verbose"
+          ]
+
+      it "completes the second part when the optional is skipped" $
+        parserCompletionTest
+          ( (,)
+              <$> optional (setting [option, reader (str :: Reader String), long "name"])
+              <*> setting [switch (), long "verbose"]
+          )
+          0
+          []
+          [ "--name",
+            "--verbose"
+          ]
+
+    describe "many with other parsers" $ do
+      it "completes both many and a following switch" $
+        parserCompletionTest
+          ( (,)
+              <$> many (setting [option, reader (str :: Reader String), long "include", completer $ listCompleter ["foo"]])
+              <*> setting [switch (), long "verbose"]
+          )
+          0
+          []
+          [ "--include",
+            "--verbose"
+          ]
+
+      it "completes both after consuming one many-option" $
+        parserCompletionTest
+          ( (,)
+              <$> many (setting [option, reader (str :: Reader String), long "include", completer $ listCompleter ["foo"]])
+              <*> setting [switch (), long "verbose"]
+          )
+          2
+          ["--include", "foo"]
+          [ "--include",
+            "--verbose"
+          ]
+
+      it "completes many switches combined with a command" $
+        parserCompletionTest
+          ( (,)
+              <$> many (setting [switch (), long "verbose", short 'v'])
+              <*> commands
+                [ command "run" "run it" $ pure (),
+                  command "build" "build it" $ pure ()
+                ]
+          )
+          0
+          []
+          [ "--verbose",
+            Completion "run" (Just "run it"),
+            Completion "build" (Just "build it")
+          ]
+
+      it "completes commands after consuming many switches" $
+        parserCompletionTest
+          ( (,)
+              <$> many (setting [switch (), long "verbose", short 'v'])
+              <*> commands
+                [ command "run" "run it" $ pure (),
+                  command "build" "build it" $ pure ()
+                ]
+          )
+          2
+          ["-v", "-v"]
+          [ "--verbose",
+            Completion "run" (Just "run it"),
+            Completion "build" (Just "build it")
+          ]
+
+    describe "folded short switches" $ do
+      it "can complete after a folded short switch is consumed" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), short 'v']
+              <*> setting [switch (), short 'n']
+          )
+          1
+          ["-v"]
+          ["-n"]
+
+      it "no longer suggests a switch consumed via folding" $
+        parserCompletionTest
+          ( (,,)
+              <$> setting [switch (), short 'v']
+              <*> setting [switch (), short 'n']
+              <*> setting [switch (), short 'x']
+          )
+          1
+          ["-vn"]
+          ["-x"]
+
+    describe "short option shorthand" $ do
+      it "completes after a short option consumed in shorthand" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [option, reader (str :: Reader String), short 'f']
+              <*> setting [switch (), long "verbose"]
+          )
+          1
+          ["-ffoo.txt"]
+          ["--verbose"]
+
+    describe "deeply nested parsers" $ do
+      it "completes through optional + many + applicative" $
+        parserCompletionTest
+          ( (,,)
+              <$> optional (setting [option, reader (str :: Reader String), long "config"])
+              <*> many (setting [switch (), long "verbose", short 'v'])
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["file.txt"]]
+          )
+          0
+          []
+          [ "--config",
+            "--verbose",
+            "file.txt"
+          ]
+
+      it "completes correctly after all optional+many consumed" $
+        parserCompletionTest
+          ( (,,)
+              <$> optional (setting [option, reader (str :: Reader String), long "config"])
+              <*> many (setting [switch (), long "verbose", short 'v'])
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["file.txt"]]
+          )
+          3
+          [ "--config",
+            "foo",
+            "--verbose"
+          ]
+          [ "--verbose",
+            "file.txt"
+          ]
+
+    describe "commands with options inside" $ do
+      it "completes a command's many options" $
+        parserCompletionTest
+          ( commands
+              [ command "run" "run it" $
+                  many (setting [option, reader (str :: Reader String), long "arg", completer $ listCompleter ["val"]])
+              ]
+          )
+          2
+          ["run", "--arg"]
+          ["val"]
+
+      it "completes a command's many options after one is consumed" $
+        parserCompletionTest
+          ( commands
+              [ command "run" "run it" $
+                  many (setting [option, reader (str :: Reader String), long "arg", completer $ listCompleter ["val"]])
+              ]
+          )
+          3
+          [ "run",
+            "--arg",
+            "val"
+          ]
+          ["--arg"]
+
+    describe "multiple commands with shared options" $ do
+      it "completes options in the selected command only" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [switch (), long "alpha"],
+                command "bar" "2" $ setting [switch (), long "beta"]
+              ]
+          )
+          1
+          ["foo"]
+          ["--alpha"]
+
+      it "does not leak options from other commands" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ setting [switch (), long "alpha"],
+                command "bar" "2" $ setting [switch (), long "beta"]
+              ]
+          )
+          1
+          ["bar"]
+          ["--beta"]
+
+    describe "alternative branch failures" $ do
+      -- A parser that is not detected as isEmpty but still fails during
+      -- completion (andCompletions fails because the inner empty fails).
+      -- This avoids the (<|>) optimization that removes empty alternatives.
+      let failingP = (empty :: Parser ()) *> pure ()
+      it "restores state when first branch fails in an alternative" $
+        parserCompletionTest
+          (failingP <|> setting [switch (), long "foo"])
+          0
+          []
+          ["--foo"]
+
+      it "returns first branch completions when second branch fails" $
+        parserCompletionTest
+          (setting [switch (), long "foo"] <|> failingP)
+          0
+          []
+          ["--foo"]
+
+      it "returns no completions when both alternatives fail" $
+        parserCompletionTest
+          (failingP <|> failingP)
+          0
+          []
+          []
+
+    describe "applicative branch failures" $ do
+      it "returns nothing when first applicative branch fails" $
+        parserCompletionTest
+          ((,) <$> ((empty :: Parser ()) *> pure ()) <*> setting [switch (), long "foo"])
+          0
+          []
+          []
+
+      it "returns nothing when second applicative branch fails" $
+        parserCompletionTest
+          ((,) <$> setting [switch (), long "foo"] <*> ((empty :: Parser String) *> pure ("" :: String)))
+          0
+          []
+          []
+
+    describe "many edge cases" $ do
+      it "handles many where the inner parser fails" $
+        parserCompletionTest
+          (many ((empty :: Parser ()) *> pure ()))
+          0
+          []
+          []
+
+      it "returns first iteration completions when recursive call fails" $
+        parserCompletionTest
+          (many (commands [command "foo" "1" $ pure ()]))
+          1
+          ["foo"]
+          [Completion "foo" (Just "1")]
+
+    describe "command not found" $ do
+      it "returns no completions for an unknown command" $
+        parserCompletionTest
+          (commands [command "foo" "1" $ pure (), command "bar" "2" $ pure ()])
+          1
+          ["unknown"]
+          []
+
+    describe "argument completer at end" $ do
+      it "offers the argument completer at the end after a switch is consumed" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["file"]]
+          )
+          1
+          ["--verbose"]
+          ["file"]
+
+      it "does not offer option completer when not at end of args" $
+        parserCompletionTest
+          ( (,,)
+              <$> setting [switch (), long "other"]
+              <*> setting [option, reader (str :: Reader String), long "name", completer $ listCompleter ["val"]]
+              <*> setting [switch (), long "extra"]
+          )
+          3
+          [ "--name",
+            "--other",
+            "--extra"
+          ]
+          []
+
+    describe "option with different dashed in args" $ do
+      it "does not suggest an option when a different dashed is in the args" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [option, reader (str :: Reader String), long "output", completer $ listCompleter ["file.txt"]]
+              <*> setting [option, reader (str :: Reader String), long "input", completer $ listCompleter ["data.csv"]]
+          )
+          1
+          ["--input"]
+          ["data.csv"]
+
+    describe "default command parser failure" $ do
+      let emptyS = empty :: Parser String
+      it "falls back to explicit commands when default command parser fails" $
+        parserCompletionTest
+          ( commands
+              [ command "foo" "1" $ (,) <$> setting [argument, reader (str :: Reader String)] <*> emptyS,
+                command "bar" "2" $ pure ("", ""),
+                defaultCommand "foo"
+              ]
+          )
+          0
+          []
+          [ Completion "foo" (Just "1"),
+            Completion "bar" (Just "2")
+          ]
+
+    describe "prefix filtering" $ do
+      it "filters switches by typed prefix" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [switch (), long "version"]
+          )
+          0
+          ["--verb"]
+          ["--verbose"]
+
+      it "returns nothing when prefix matches nothing" $
+        parserCompletionTest
+          (setting [switch (), long "verbose"])
+          0
+          ["--xyz"]
+          []
+
+      it "filters commands by typed prefix" $
+        parserCompletionDescriptionTest
+          ( commands
+              [ command "generate" "gen" $ pure (),
+                command "get" "getter" $ pure (),
+                command "build" "builder" $ pure ()
+              ]
+          )
+          0
+          ["ge"]
+          [ "gen",
+            "getter"
+          ]
+
+    describe "argument completion with dashed values" $ do
+      -- When a dashed-looking value is provided as a positional argument,
+      -- the completion engine treats it as a potential switch (first
+      -- consumeArgument possibility) instead of consuming it.  This
+      -- causes the argument's completer to fire even though a value was
+      -- already provided.
+      it "should not offer the argument completer after a dashed value is consumed" $
+        parserCompletionTest
+          (setting [argument, reader (str :: Reader String), completer $ listCompleter ["file"]])
+          1
+          ["--foo"]
+          []
+
+      -- Same issue in a tuple: the first argument's completer fires
+      -- alongside the second's, even though the first argument already
+      -- has a value.
+      it "should only complete the second argument after a dashed first argument" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["file"]]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["dest"]]
+          )
+          1
+          ["--foo"]
+          ["dest"]
+
+    describe "partial option value completion" $ do
+      it "filters option values by typed prefix" $
+        parserCompletionTest
+          ( setting
+              [ option,
+                reader (str :: Reader String),
+                long "name",
+                completer $ listCompleter ["alice", "bob"]
+              ]
+          )
+          1
+          ["--name", "al"]
+          ["alice"]
+
+      it "returns all option values when prefix is empty" $
+        parserCompletionTest
+          ( setting
+              [ option,
+                reader (str :: Reader String),
+                long "name",
+                completer $ listCompleter ["alice", "bob"]
+              ]
+          )
+          1
+          ["--name", ""]
+          [ "alice",
+            "bob"
+          ]
+
+    describe "partial argument completion" $ do
+      it "filters argument values by typed prefix" $
+        parserCompletionTest
+          ( setting
+              [ argument,
+                reader (str :: Reader String),
+                completer $ listCompleter ["file1", "file2", "data"]
+              ]
+          )
+          0
+          ["fi"]
+          [ "file1",
+            "file2"
+          ]
+
+      it "filters argument values by a different prefix" $
+        parserCompletionTest
+          ( setting
+              [ argument,
+                reader (str :: Reader String),
+                completer $ listCompleter ["file1", "file2", "data"]
+              ]
+          )
+          0
+          ["da"]
+          ["data"]
+
+    describe "partial command name with inner option completion" $ do
+      it "completes a command's options after selecting by prefix" $
+        parserCompletionTest
+          ( commands
+              [ command "deploy" "deploy it" $ setting [switch (), long "force"],
+                command "debug" "debug it" $ pure ()
+              ]
+          )
+          1
+          ["deploy"]
+          ["--force"]
+
+    describe "completion at a middle index" $ do
+      it "completes the value of an option at its value position with a matching prefix" $
+        parserCompletionTest
+          ( (,)
+              <$> setting
+                [ option,
+                  reader (str :: Reader String),
+                  long "foo",
+                  completer $ listCompleter ["val1", "val2"]
+                ]
+              <*> setting [switch (), long "bar"]
+          )
+          1
+          ["--foo", "v", "--bar"]
+          [ "val1",
+            "val2"
+          ]
+
+      it "filters completions when cursor word narrows the match" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "alpha"]
+              <*> setting [switch (), long "beta"]
+          )
+          0
+          ["--alpha", "--beta"]
+          ["--alpha"]
+
+    describe "partial long option prefix with multiple matches" $ do
+      it "filters options by a short prefix matching multiple" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [switch (), long "version"]
+          )
+          0
+          ["--ver"]
+          [ "--verbose",
+            "--version"
+          ]
+
+      it "filters options by a longer prefix matching one" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [switch (), long "verbose"]
+              <*> setting [switch (), long "version"]
+          )
+          0
+          ["--verb"]
+          ["--verbose"]
+
+    describe "partial argument completion after consuming earlier args" $ do
+      it "filters the second argument's completer by prefix after the first is consumed" $
+        parserCompletionTest
+          ( (,)
+              <$> setting [argument, reader (str :: Reader String), completer $ listCompleter ["src"]]
+              <*> setting [argument, reader (str :: Reader String), completer $ listCompleter ["dst", "data"]]
+          )
+          1
+          ["src", "ds"]
+          ["dst"]
+
+    describe "commands with partial option value inside" $ do
+      it "filters a command's option values by prefix" $
+        parserCompletionTest
+          ( commands
+              [ command "run" "run it" $
+                  setting
+                    [ option,
+                      reader (str :: Reader String),
+                      long "output",
+                      completer $ listCompleter ["file.txt", "final.out", "data.csv"]
+                    ]
+              ]
+          )
+          2
+          ["run", "--output", "fi"]
+          [ "file.txt",
+            "final.out"
+          ]
+
+    describe "many with partial values" $ do
+      it "filters many option values by prefix" $
+        parserCompletionTest
+          ( many
+              ( setting
+                  [ option,
+                    reader (str :: Reader String),
+                    long "include",
+                    completer $ listCompleter ["foo", "bar"]
+                  ]
+              )
+          )
+          1
+          ["--include", "fo"]
+          ["foo"]
+
+      it "filters many option values by prefix after one is consumed" $
+        parserCompletionTest
+          ( many
+              ( setting
+                  [ option,
+                    reader (str :: Reader String),
+                    long "include",
+                    completer $ listCompleter ["foo", "bar"]
+                  ]
+              )
+          )
+          3
+          ["--include", "foo", "--include", "ba"]
+          ["bar"]
+
+  sequential . doNotRandomiseExecutionOrder
+    $ aroundAll
+      ( \func -> withSystemTempDir "completion-spec" $ \tdir -> do
+          exampleFile <- resolveFile tdir "example.txt"
+          writeFile (fromAbsFile exampleFile) ""
+          exampleDir <- resolveDir tdir "exampledir"
+          createDir exampleDir
+          nested <- resolveFile exampleDir "nested.txt"
+          writeFile (fromAbsFile nested) ""
+          func tdir
+      )
+    $ do
+      let evalQuery p ix ws tdir = withCurrentDir tdir $ do
+            let arg = fromMaybe "" $ listToMaybe $ drop ix ws
+            let completions = pureCompletionQuery p ix ws
+            evalCompletions arg completions
+          suggestionValues = map (completionResultValue . completionSuggestion)
+
+      describe "file and directory completion" $ do
+        describe "filePathSetting" $ do
+          itWithOuter "completes files and directories for a file argument" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "f", argument]) 0 [] tdir
+            suggestionValues results `shouldBe` ["example.txt", "exampledir/"]
+
+          itWithOuter "completes files and directories after a file option's dashed" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "f", option, long "file"]) 1 ["--file"] tdir
+            suggestionValues results `shouldBe` ["example.txt", "exampledir/"]
+
+          itWithOuter "filters by prefix" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "f", argument]) 0 ["exampledi"] tdir
+            suggestionValues results `shouldBe` ["exampledir/"]
+
+          -- Directories end in /, files do not.  This convention is how
+          -- shells decide whether to append a trailing space after a
+          -- completion.  The exact values are checked by
+          -- "completes files and directories for a file argument" above;
+          -- this test re-states the invariant explicitly.
+          itWithOuter "directories end in / and files do not" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "f", argument]) 0 [] tdir
+            suggestionValues results `shouldBe` ["example.txt", "exampledir/"]
+
+          itWithOuter "files are final and directories are not final" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "f", argument]) 0 [] tdir
+            map (completionResultFinality . completionSuggestion) results
+              `shouldBe` [CompletionFinal, CompletionNotFinal]
+
+          itWithOuter "carries the description through to file completions" $ \tdir -> do
+            results <- evalQuery (filePathSetting [help "my file", argument]) 0 [] tdir
+            map completionDescription results `shouldBe` [Just "my file", Just "my file"]
+
+        describe "directoryPathSetting" $ do
+          itWithOuter "completes only directories for a directory argument" $ \tdir -> do
+            results <- evalQuery (directoryPathSetting [help "d", argument]) 0 [] tdir
+            suggestionValues results `shouldBe` ["exampledir/"]
+
+          itWithOuter "completes only directories after a directory option's dashed" $ \tdir -> do
+            results <- evalQuery (directoryPathSetting [help "d", option, long "dir"]) 1 ["--dir"] tdir
+            suggestionValues results `shouldBe` ["exampledir/"]
+
+          itWithOuter "never includes files" $ \tdir -> do
+            results <- evalQuery (directoryPathSetting [help "d", argument]) 0 [] tdir
+            suggestionValues results `shouldBe` ["exampledir/"]
+
+          itWithOuter "directories are not final" $ \tdir -> do
+            results <- evalQuery (directoryPathSetting [help "d", argument]) 0 [] tdir
+            map (completionResultFinality . completionSuggestion) results
+              `shouldBe` [CompletionNotFinal]
+
+          itWithOuter "carries the description through to directory completions" $ \tdir -> do
+            results <- evalQuery (directoryPathSetting [help "my dir", argument]) 0 [] tdir
+            map completionDescription results `shouldBe` [Just "my dir"]
+
+        describe "combined with other settings" $ do
+          itWithOuter "includes file completions alongside other options" $ \tdir -> do
+            let parser =
+                  (,)
+                    <$> filePathSetting [help "f", option, long "file"]
+                    <*> setting [switch (), long "verbose"]
+            results <- evalQuery parser 1 ["--file"] tdir
+            suggestionValues results `shouldBe` ["example.txt", "exampledir/", "--verbose"]
+
+          itWithOuter "includes directory completions alongside other options" $ \tdir -> do
+            let parser =
+                  (,)
+                    <$> directoryPathSetting [help "d", option, long "dir"]
+                    <*> setting [switch (), long "verbose"]
+            results <- evalQuery parser 1 ["--dir"] tdir
+            suggestionValues results `shouldBe` ["exampledir/", "--verbose"]
+
+          -- After typing the dashed of an option that takes a value, the
+          -- cursor is in the value position.  The option's completer
+          -- should fire first, then other options should follow.
+          --
+          -- Shell sends index pointing at the empty cursor word:
+          --   exe --dir <tab> -> index=1, words=["--dir", ""]
+          itWithOuter "completes directory option value first, then other options" $ \tdir -> do
+            let parser =
+                  (,)
+                    <$> directoryPathSetting [help "d", option, long "dir"]
+                    <*> setting [switch (), long "verbose"]
+            results <- evalQuery parser 1 ["--dir", ""] tdir
+            suggestionValues results `shouldBe` ["exampledir/", "--verbose"]
+
+          itWithOuter "completes file option value first, then other options" $ \tdir -> do
+            let parser =
+                  (,)
+                    <$> filePathSetting [help "f", option, long "file"]
+                    <*> setting [switch (), long "verbose"]
+            results <- evalQuery parser 1 ["--file", ""] tdir
+            suggestionValues results `shouldBe` ["example.txt", "exampledir/", "--verbose"]
+
+          -- A default command with an argument combined with a
+          -- directory option causes the directory completer not to fire
+          -- when completing the option's value.
+          itWithOuter "completes directory option value alongside default command with argument" $ \tdir -> do
+            let parser =
+                  (,)
+                    <$> commands
+                      [ command "file" "f" $
+                          setting [help "f", argument, reader (str :: Reader String)],
+                        defaultCommand "file"
+                      ]
+                    <*> directoryPathSetting [help "a", option, long "archive-dir"]
+            results <- evalQuery parser 1 ["--archive-dir", ""] tdir
+            suggestionValues results `shouldSatisfy` elem "exampledir/"
diff --git a/test/OptEnvConf/RunSpec.hs b/test/OptEnvConf/RunSpec.hs
--- a/test/OptEnvConf/RunSpec.hs
+++ b/test/OptEnvConf/RunSpec.hs
@@ -8,6 +8,7 @@
 import Autodocodec
 import Control.Applicative
 import Control.Concurrent
+import Control.Monad (void)
 import Data.Aeson as JSON (Object, Value (Null), toJSON)
 import qualified Data.Aeson.Key as Key
 import qualified Data.Aeson.KeyMap as KeyMap
@@ -25,6 +26,7 @@
 import qualified OptEnvConf.EnvMap as EnvMap
 import OptEnvConf.EnvMap.Gen ()
 import OptEnvConf.Error
+import qualified System.Timeout as Timeout
 import Test.Syd
 import Test.Syd.Validity
 import Text.Colour
@@ -129,6 +131,45 @@
               let expected = NE.toList ls
               shouldParse p args e mConf expected
 
+      -- Regression test for an exponential-time bug.
+      --
+      -- A parser shaped like
+      --
+      --     choice [some argument, many --filter] <*> many --opt1 <*> many --opt2 <*> ...
+      --
+      -- combined with input that has both several @--opt1 VAL@ pairs and at
+      -- least one @--opt2 VAL@ pair scaled super-linearly: in the broken
+      -- version, every added @--opt2@ multiplied total parse time by ~3x.
+      --
+      -- The original report came from a sydtest mutation suite invocation
+      -- with 6 @--mutation@ + 6 @--mutation-suite-exe@ flags taking
+      -- > 30 seconds of CPU just to parse settings. With the parser shape
+      -- below and 6 @--opt1@ + 6 @--opt2@ pairs the broken version takes
+      -- many minutes; the fixed version completes in milliseconds.
+      it "parses many-many input in bounded time (regression: no exponential blowup)" $ do
+        let parser :: Parser ()
+            parser =
+              void $
+                (,,)
+                  <$> choice
+                    [ some (setting [reader str, argument, help "F", metavar "F"] :: Parser String),
+                      many (setting [reader str, option, long "filter", help "F", metavar "F"])
+                    ]
+                  <*> many (setting [reader str, option, long "opt1", help "x", metavar "X"] :: Parser String)
+                  <*> many (setting [reader str, option, long "opt2", help "x", metavar "X"] :: Parser String)
+        let args =
+              parseArgs $
+                concat (replicate 6 ["--opt1", "/v"])
+                  ++ concat (replicate 6 ["--opt2", "/v"])
+        mResult <-
+          Timeout.timeout
+            (500 * 1000)
+            (runParserOn allCapabilities Nothing parser args EnvMap.empty Nothing)
+        case mResult of
+          Nothing -> expectationFailure "parser took longer than 0.5 seconds; likely exponential blowup"
+          Just (Left errs) -> expectationFailure $ T.unpack $ renderChunksText With24BitColours $ renderErrors errs
+          Just (Right ()) -> pure ()
+
     describe "MapIO" $ do
       it "can run an IO action on the result of a parser" $
         forAllValid $ \e ->
@@ -526,16 +567,15 @@
 
       -- Unfolding short options as well
       argParseSpecs
-        ( (,)
-            <$> ( length
-                    <$> many
-                      ( setting
-                          [ help "verbosity",
-                            switch (),
-                            short 'v'
-                          ]
-                      )
+        ( ( (,) . length
+              <$> many
+                ( setting
+                    [ help "verbosity",
+                      switch (),
+                      short 'v'
+                    ]
                 )
+          )
             <*> setting
               [ reader str,
                 option,
@@ -650,8 +690,9 @@
         verbosityArgsExamples
       argParseSpecs
         ( swap
-            <$> ( (,)
-                    <$> (length <$> many (setting [switch (), short 'v', long "verbose"]))
+            <$> ( ( (,) . length
+                      <$> many (setting [switch (), short 'v', long "verbose"])
+                  )
                     <*> many (setting [reader str, argument])
                 ) ::
             Parser ([String], Int)
diff --git a/test_resources/completion/fish-completion-script.fish b/test_resources/completion/fish-completion-script.fish
--- a/test_resources/completion/fish-completion-script.fish
+++ b/test_resources/completion/fish-completion-script.fish
@@ -8,10 +8,11 @@
       set tmpline $tmpline --completion-word $arg
     end
     for opt in (/usr/bin/example-executable $tmpline)
-      if test -d $opt
-        echo -E "$opt/"
+      set -l val (string split \t -- $opt)[1]
+      if test -d $val
+        echo -E "$val/"
       else
-        echo -E "$opt"
+        echo -E "$val"
       end
     end
 end
diff --git a/test_resources/completion/zsh-completion-script.zsh b/test_resources/completion/zsh-completion-script.zsh
--- a/test_resources/completion/zsh-completion-script.zsh
+++ b/test_resources/completion/zsh-completion-script.zsh
@@ -22,11 +22,18 @@
      if [[ $word[1] == "-" ]]; then
        local desc=("$parts[1] ($parts[2])")
        compadd -d desc -- $parts[1]
+     elif [[ $parts[3] == 'N' ]]; then
+       local desc=($(print -f  "%-019s -- %s" $parts[1] $parts[2]))
+       compadd -f -l -S '' -d desc -- $parts[1]
      else
        local desc=($(print -f  "%-019s -- %s" $parts[1] $parts[2]))
-       compadd -l -d desc -- $parts[1]
+       compadd -f -l -d desc -- $parts[1]
      fi
   else
-    compadd -f -- $word
+    if [[ $parts[3] == 'N' ]]; then
+      compadd -f -S '' -- $parts[1]
+    else
+      compadd -f -- $parts[1]
+    fi
   fi
 done
diff --git a/test_resources/docs/big-config/nix-options.nix b/test_resources/docs/big-config/nix-options.nix
--- a/test_resources/docs/big-config/nix-options.nix
+++ b/test_resources/docs/big-config/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:25
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   big = lib.mkOption {
diff --git a/test_resources/docs/empty/nix-options.nix b/test_resources/docs/empty/nix-options.nix
--- a/test_resources/docs/empty/nix-options.nix
+++ b/test_resources/docs/empty/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:21
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/enable-disable-optional/nix-options.nix b/test_resources/docs/enable-disable-optional/nix-options.nix
--- a/test_resources/docs/enable-disable-optional/nix-options.nix
+++ b/test_resources/docs/enable-disable-optional/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:30
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   example = lib.mkOption {
diff --git a/test_resources/docs/enable-disable/nix-options.nix b/test_resources/docs/enable-disable/nix-options.nix
--- a/test_resources/docs/enable-disable/nix-options.nix
+++ b/test_resources/docs/enable-disable/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:28
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   example = lib.mkOption {
diff --git a/test_resources/docs/greet/nix-options.nix b/test_resources/docs/greet/nix-options.nix
--- a/test_resources/docs/greet/nix-options.nix
+++ b/test_resources/docs/greet/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:37
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   greeting = lib.mkOption {
diff --git a/test_resources/docs/hidden/nix-options.nix b/test_resources/docs/hidden/nix-options.nix
--- a/test_resources/docs/hidden/nix-options.nix
+++ b/test_resources/docs/hidden/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:27
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/many-args/nix-options.nix b/test_resources/docs/many-args/nix-options.nix
--- a/test_resources/docs/many-args/nix-options.nix
+++ b/test_resources/docs/many-args/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:22
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/optional/nix-options.nix b/test_resources/docs/optional/nix-options.nix
--- a/test_resources/docs/optional/nix-options.nix
+++ b/test_resources/docs/optional/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:24
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/same-help/nix-options.nix b/test_resources/docs/same-help/nix-options.nix
--- a/test_resources/docs/same-help/nix-options.nix
+++ b/test_resources/docs/same-help/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:33
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   int = lib.mkOption {
diff --git a/test_resources/docs/secret/nix-options.nix b/test_resources/docs/secret/nix-options.nix
--- a/test_resources/docs/secret/nix-options.nix
+++ b/test_resources/docs/secret/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:35
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   first-secret-file = lib.mkOption {
diff --git a/test_resources/docs/some-args/nix-options.nix b/test_resources/docs/some-args/nix-options.nix
--- a/test_resources/docs/some-args/nix-options.nix
+++ b/test_resources/docs/some-args/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:23
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/sub-commands/nix-options.nix b/test_resources/docs/sub-commands/nix-options.nix
--- a/test_resources/docs/sub-commands/nix-options.nix
+++ b/test_resources/docs/sub-commands/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:39
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   name = lib.mkOption {
diff --git a/test_resources/docs/sub-settings/nix-options.nix b/test_resources/docs/sub-settings/nix-options.nix
--- a/test_resources/docs/sub-settings/nix-options.nix
+++ b/test_resources/docs/sub-settings/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:26
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   foo = lib.mkOption {
diff --git a/test_resources/docs/sum-type/nix-options.nix b/test_resources/docs/sum-type/nix-options.nix
--- a/test_resources/docs/sum-type/nix-options.nix
+++ b/test_resources/docs/sum-type/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:34
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   sum-type = lib.mkOption {
diff --git a/test_resources/docs/three-commands/nix-options.nix b/test_resources/docs/three-commands/nix-options.nix
--- a/test_resources/docs/three-commands/nix-options.nix
+++ b/test_resources/docs/three-commands/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:38
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   enable = lib.mkOption {
diff --git a/test_resources/docs/verbose/nix-options.nix b/test_resources/docs/verbose/nix-options.nix
--- a/test_resources/docs/verbose/nix-options.nix
+++ b/test_resources/docs/verbose/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:32
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/with-default/nix-options.nix b/test_resources/docs/with-default/nix-options.nix
--- a/test_resources/docs/with-default/nix-options.nix
+++ b/test_resources/docs/with-default/nix-options.nix
@@ -1,2 +1,6 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:36
+# To update this it, run the test with --golden-reset
 { lib }:
 { }
diff --git a/test_resources/docs/yes-no-optional/nix-options.nix b/test_resources/docs/yes-no-optional/nix-options.nix
--- a/test_resources/docs/yes-no-optional/nix-options.nix
+++ b/test_resources/docs/yes-no-optional/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:31
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   example = lib.mkOption {
diff --git a/test_resources/docs/yes-no/nix-options.nix b/test_resources/docs/yes-no/nix-options.nix
--- a/test_resources/docs/yes-no/nix-options.nix
+++ b/test_resources/docs/yes-no/nix-options.nix
@@ -1,3 +1,7 @@
+# DO NOT EDIT THIS FILE DIRECTLY
+# This file was generated by
+# opt-env-conf-test:test/OptEnvConf/APISpec.hs:29
+# To update this it, run the test with --golden-reset
 { lib }:
 {
   example = lib.mkOption {
diff --git a/test_resources/error/all-or-nothing-relevant.txt b/test_resources/error/all-or-nothing-relevant.txt
--- a/test_resources/error/all-or-nothing-relevant.txt
+++ b/test_resources/error/all-or-nothing-relevant.txt
@@ -1,5 +1,5 @@
 Missing option: [37m--bar[m [34mThis one will not exist[m
 You are seeing this error because at least one, but not all, of the settings in an allOrNothing (or subSettings) parser have been defined.
 The following settings have been parsed:
-[36mtest/OptEnvConf/ErrorSpec.hs:153:21 in main:OptEnvConf.ErrorSpec[m
+[36mtest/OptEnvConf/ErrorSpec.hs:153:21 in opt-env-conf-test:OptEnvConf.ErrorSpec[m
 Hit the 'empty' case of the Parser type, this should not happen.
diff --git a/test_resources/error/all-or-nothing.txt b/test_resources/error/all-or-nothing.txt
--- a/test_resources/error/all-or-nothing.txt
+++ b/test_resources/error/all-or-nothing.txt
@@ -1,4 +1,4 @@
 Missing option: [37m--bar[m [34mThis one will not exist[m
 You are seeing this error because at least one, but not all, of the settings in an allOrNothing (or subSettings) parser have been defined.
 The following settings have been parsed:
-[36mtest/OptEnvConf/ErrorSpec.hs:141:19 in main:OptEnvConf.ErrorSpec[m
+[36mtest/OptEnvConf/ErrorSpec.hs:141:19 in opt-env-conf-test:OptEnvConf.ErrorSpec[m
diff --git a/test_resources/help/toplevel-pure-with-invalid-port.txt b/test_resources/help/toplevel-pure-with-invalid-port.txt
--- a/test_resources/help/toplevel-pure-with-invalid-port.txt
+++ b/test_resources/help/toplevel-pure-with-invalid-port.txt
@@ -1,4 +1,4 @@
-[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mFILE_PATH[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
+[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
 
 example program description
 
@@ -37,8 +37,8 @@
       [33m<string>[m
 
   [34mSecret key[m
-  option: [37m--payment-secret-key[m [33mFILE_PATH[m
-  env: [37mPAYMENT_SECRET_KEY[m [33mFILE_PATH[m
+  option: [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m
+  env: [37mPAYMENT_SECRET_KEY[m [33mSECRET_KEY_FILE[m
   config:
     [37mpayment.secret-key[m: # [32mor null[m
       [33m<string>[m
diff --git a/test_resources/help/toplevel-pure.txt b/test_resources/help/toplevel-pure.txt
--- a/test_resources/help/toplevel-pure.txt
+++ b/test_resources/help/toplevel-pure.txt
@@ -1,4 +1,4 @@
-[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mFILE_PATH[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
+[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
 
 example program description
 
@@ -37,8 +37,8 @@
       [33m<string>[m
 
   [34mSecret key[m
-  option: [37m--payment-secret-key[m [33mFILE_PATH[m
-  env: [37mPAYMENT_SECRET_KEY[m [33mFILE_PATH[m
+  option: [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m
+  env: [37mPAYMENT_SECRET_KEY[m [33mSECRET_KEY_FILE[m
   config:
     [37mpayment.secret-key[m: # [32mor null[m
       [33m<string>[m
diff --git a/test_resources/help/wrong-command.txt b/test_resources/help/wrong-command.txt
--- a/test_resources/help/wrong-command.txt
+++ b/test_resources/help/wrong-command.txt
@@ -1,4 +1,4 @@
-[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mFILE_PATH[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
+[36mUsage: [m[33mexample[m [36m[[m[37m--config-file[m [33mFILE_PATH[m[36m][m [36m[[m[37m--port[m [33mPORT[m[36m][m [36m[[m[37m--log-level[m [33mLOG_LEVEL[m[36m][m [36m[[m[37m--payment-public-key[m [33mPUBLIC_KEY[m [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m [36m[[m[37m--payment-currency[m [33mCURRENCY[m[36m][m[36m][m COMMAND
 
 example program description
 
@@ -37,8 +37,8 @@
       [33m<string>[m
 
   [34mSecret key[m
-  option: [37m--payment-secret-key[m [33mFILE_PATH[m
-  env: [37mPAYMENT_SECRET_KEY[m [33mFILE_PATH[m
+  option: [37m--payment-secret-key[m [33mSECRET_KEY_FILE[m
+  env: [37mPAYMENT_SECRET_KEY[m [33mSECRET_KEY_FILE[m
   config:
     [37mpayment.secret-key[m: # [32mor null[m
       [33m<string>[m
diff --git a/test_resources/lint/config-without-load.txt b/test_resources/lint/config-without-load.txt
--- a/test_resources/lint/config-without-load.txt
+++ b/test_resources/lint/config-without-load.txt
@@ -3,4 +3,4 @@
   [31mInvalid Setting:[m
   [33mconf[m or [33mname[m was called with no way to load configuration.
   You can load configuration with [33mwithConfig[m, or explicitly not load any configuration with [33mwithoutConfig[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:124:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:124:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/dash-in-long.txt b/test_resources/lint/dash-in-long.txt
--- a/test_resources/lint/dash-in-long.txt
+++ b/test_resources/lint/dash-in-long.txt
@@ -4,4 +4,4 @@
   [33mlong[m may not start with a '-'.
   Found [33mlong[m "--switch".
   Try [33mlong[m "switch" instead.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:33:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:33:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/dash-in-short.txt b/test_resources/lint/dash-in-short.txt
--- a/test_resources/lint/dash-in-short.txt
+++ b/test_resources/lint/dash-in-short.txt
@@ -3,4 +3,4 @@
   [31mInvalid Setting:[m
   [33mshort[m may not contain a '-'.
   Found [33mshort[m '-'.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:25:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:25:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/empty-setting.txt b/test_resources/lint/empty-setting.txt
--- a/test_resources/lint/empty-setting.txt
+++ b/test_resources/lint/empty-setting.txt
@@ -3,4 +3,4 @@
   [31mInvalid Setting:[m
   This [33msetting[m parses nothing.
   Add an [33margument[m, [33mswitch[m, [33moption[m, [33menv[m, [33mconf[m, or [33mvalue[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:19:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:19:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-commands.txt b/test_resources/lint/no-commands.txt
--- a/test_resources/lint/no-commands.txt
+++ b/test_resources/lint/no-commands.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33mcommands[m was called with an empty list.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:121:6 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:121:6 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-dashed-for-option.txt b/test_resources/lint/no-dashed-for-option.txt
--- a/test_resources/lint/no-dashed-for-option.txt
+++ b/test_resources/lint/no-dashed-for-option.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33moption[m has no [33mlong[m or [33mshort[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:67:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:67:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-dashed-for-switch.txt b/test_resources/lint/no-dashed-for-switch.txt
--- a/test_resources/lint/no-dashed-for-switch.txt
+++ b/test_resources/lint/no-dashed-for-switch.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33mswitch[m has no [33mlong[m or [33mshort[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:98:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:98:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-metavar-for-argument.txt b/test_resources/lint/no-metavar-for-argument.txt
--- a/test_resources/lint/no-metavar-for-argument.txt
+++ b/test_resources/lint/no-metavar-for-argument.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33margument[m has no [33mmetavar[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:49:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:49:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-metavar-for-env.txt b/test_resources/lint/no-metavar-for-env.txt
--- a/test_resources/lint/no-metavar-for-env.txt
+++ b/test_resources/lint/no-metavar-for-env.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33menv[m or [33mname[m has no [33mmetavar[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:112:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:112:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-metavar-for-option.txt b/test_resources/lint/no-metavar-for-option.txt
--- a/test_resources/lint/no-metavar-for-option.txt
+++ b/test_resources/lint/no-metavar-for-option.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33moption[m or [33mname[m has no [33mmetavar[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:88:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:88:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-option-or-switch-for-dashed.txt b/test_resources/lint/no-option-or-switch-for-dashed.txt
--- a/test_resources/lint/no-option-or-switch-for-dashed.txt
+++ b/test_resources/lint/no-option-or-switch-for-dashed.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33mlong[m or [33mshort[m has no [33moption[m or [33mswitch[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:77:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:77:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-reader-for-argument.txt b/test_resources/lint/no-reader-for-argument.txt
--- a/test_resources/lint/no-reader-for-argument.txt
+++ b/test_resources/lint/no-reader-for-argument.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33margument[m has no [33mreader[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:41:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:41:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-reader-for-env.txt b/test_resources/lint/no-reader-for-env.txt
--- a/test_resources/lint/no-reader-for-env.txt
+++ b/test_resources/lint/no-reader-for-env.txt
@@ -2,8 +2,8 @@
   
   [31mInvalid Setting:[m
   [33menv[m or [33mname[m has no [33mreader[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:105:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:105:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
   
   [31mInvalid Setting:[m
   [33menv[m or [33mname[m has no [33mmetavar[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:105:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:105:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/no-reader-for-option.txt b/test_resources/lint/no-reader-for-option.txt
--- a/test_resources/lint/no-reader-for-option.txt
+++ b/test_resources/lint/no-reader-for-option.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33moption[m or [33mname[m has no [33mreader[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:58:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:58:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/null-setting.txt b/test_resources/lint/null-setting.txt
--- a/test_resources/lint/null-setting.txt
+++ b/test_resources/lint/null-setting.txt
@@ -2,9 +2,9 @@
   
   [31mInvalid Setting:[m
   missing [33mhelp[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:16:6 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:16:6 in opt-env-conf-test:OptEnvConf.LintSpec[m
   
   [31mInvalid Setting:[m
   This [33msetting[m parses nothing.
   Add an [33margument[m, [33mswitch[m, [33moption[m, [33menv[m, [33mconf[m, or [33mvalue[m.
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:16:6 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:16:6 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/unknown-default-command.txt b/test_resources/lint/unknown-default-command.txt
--- a/test_resources/lint/unknown-default-command.txt
+++ b/test_resources/lint/unknown-default-command.txt
@@ -2,4 +2,4 @@
   
   [31mInvalid Setting:[m
   [33mdefaultCommand[m was called with an unknown command: [35mb[m
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:185:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:185:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
diff --git a/test_resources/lint/unreadable-example.txt b/test_resources/lint/unreadable-example.txt
--- a/test_resources/lint/unreadable-example.txt
+++ b/test_resources/lint/unreadable-example.txt
@@ -3,4 +3,4 @@
   [31mInvalid Setting:[m
   [33mexample[m was called with an example that none of the [33mreader[ms succeed in reading.
   Example: NaN
-  Defined at: [36mtest/OptEnvConf/LintSpec.hs:132:7 in main:OptEnvConf.LintSpec[m
+  Defined at: [36mtest/OptEnvConf/LintSpec.hs:132:7 in opt-env-conf-test:OptEnvConf.LintSpec[m
