bashCompletionQuery :: ParserInfo a -> ParserPrefs -> [String] -> Int -> String -> IO [String]
bashCompletionQuery pinfo pprefs ws i _ = case runCompletion compl pprefs of
  Just (Left (SomeParser p)) -> list_options p
  Just (Right c)             -> run_completer c
  _                          -> return []
  where
    list_options =
        fmap concat
      . sequence
      . mapParser (const opt_completions)

    opt_completions opt = case optMain opt of
      OptReader ns _ _ -> return $ show_names ns
      FlagReader ns _  -> return $ show_names ns
      ArgReader rdr    -> run_completer (crCompleter rdr)
      CmdReader ns _   -> return $ filter_names ns

    show_name :: OptName -> String
    show_name (OptShort c) = '-':[c]
    show_name (OptLong name) = "--" ++ name

    show_names :: [OptName] -> [String]
    show_names = filter_names . map show_name

    filter_names :: [String] -> [String]
    filter_names = filter is_completion

    run_completer :: Completer -> IO [String]
    run_completer c = runCompleter c (fromMaybe "" (listToMaybe ws''))

    (ws', ws'') = splitAt i ws

    is_completion :: String -> Bool
    is_completion =
      case ws'' of
        w:_ -> isPrefixOf w
        _ -> const True

    compl = runParserInfo pinfo (drop 1 ws')
bashCompletionQuery :: ParserInfo a -> ParserPrefs -> [String] -> Int -> String -> IO [String]
bashCompletionQuery pinfo pprefs ws i _ = case runCompletion compl pprefs of
  Just (Left (SomeParser p)) -> list_options p
  Just (Right c)             -> run_completer c
  _                          -> return []
  where
    list_options =
        fmap concat
      . sequence
      . mapParser (const opt_completions)

    opt_completions opt = case optMain opt of
      OptReader ns _ _ -> return $ show_names ns
      FlagReader ns _  -> return $ show_names ns
      ArgReader rdr    -> run_completer (crCompleter rdr)
      CmdReader ns _   -> return $ filter_names ns

    show_name :: OptName -> String
    show_name (OptShort c) = '-':[c]
    show_name (OptLong name) = "--" ++ name

    show_names :: [OptName] -> [String]
    show_names = filter_names . map show_name

    filter_names :: [String] -> [String]
    filter_names = filter is_completion

    run_completer :: Completer -> IO [String]
    run_completer c = runCompleter c (fromMaybe "" (listToMaybe ws''))

    (ws', ws'') = splitAt i ws

    is_completion :: String -> Bool
    is_completion =
      case ws'' of
        w:_ -> isPrefixOf w
        _ -> const True

    compl = runParserInfo pinfo (drop 1 ws')
bashCompletionQuery pinfo pprefs ws i _ = case runCompletion compl pprefs of
  Just (Left (SomeParser p)) -> list_options p
  Just (Right c)             -> run_completer c
  _                          -> return []
  where
    list_options =
        fmap concat
      . sequence
      . mapParser (const opt_completions)

    opt_completions opt = case optMain opt of
      OptReader ns _ _ -> return $ show_names ns
      FlagReader ns _  -> return $ show_names ns
      ArgReader rdr    -> run_completer (crCompleter rdr)
      CmdReader ns _   -> return $ filter_names ns

    show_name :: OptName -> String
    show_name (OptShort c) = '-':[c]
    show_name (OptLong name) = "--" ++ name

    show_names :: [OptName] -> [String]
    show_names = filter_names . map show_name

    filter_names :: [String] -> [String]
    filter_names = filter is_completion

    run_completer :: Completer -> IO [String]
    run_completer c = runCompleter c (fromMaybe "" (listToMaybe ws''))

    (ws', ws'') = splitAt i ws

    is_completion :: String -> Bool
    is_completion =
      case ws'' of
        w:_ -> isPrefixOf w
        _ -> const True

    compl = runParserInfo pinfo (drop 1 ws')