pcapriotti / optparse-applicative

Applicative option parser
BSD 3-Clause "New" or "Revised" License
910 stars 116 forks source link

Make shell completion script text functions public #472

Closed ghost closed 1 year ago

ghost commented 1 year ago

Hi! Sometimes we don't want to use the flag (for example, --fish-completion-script) to invoke the completion script text generation and instead prefer to use custom command (such as calling generate:completion:zsh for convenience) to invoke it. However, I can't find a way to get the completion script text itself from optparse-applicative.

This PR should expose all current shell's completion script to the public API.

HuwCampbell commented 1 year ago

I'm happy with exporting these scripts.

Don't worry about renaming the functions for the scripts, just change the return to unlines in each script and adjust the signature. They can be exported with the old name but just returning strings.

The helper shellScripStringHelper calls lines on a string which has just had unlines applied to it, the result of which gets passed to unlines again! That's a bit nuts.

You can instead just add a function in bashCompletionParser to do the right thing where each of the scripts is invoked (I also renamed failure).

bashCompletionParser :: ParserInfo a -> ParserPrefs -> Parser CompletionResult
bashCompletionParser pinfo pprefs = complParser
  where
    returnCompletions opts =
      CompletionResult $
        \progn -> unlines <$> opts progn

    scriptRequest =
      CompletionResult . fmap pure

    complParser = asum
      [ returnCompletions <$>
        (  bashCompletionQuery pinfo pprefs
        -- To get rich completions, one just needs the first
        -- command. To customise the lengths, use either of
        -- the `desc-length` options.
        -- zsh commands can go on a single line, so they might
        -- want to be longer.
        <$> ( flag' Enriched (long "bash-completion-enriched" `mappend` internal)
                <*> option auto (long "bash-completion-option-desc-length" `mappend` internal `mappend` value 40)
                <*> option auto (long "bash-completion-command-desc-length" `mappend` internal `mappend` value 40)
          <|> pure Standard
          )
        <*> (many . strOption) (long "bash-completion-word"
                                  `mappend` internal)
        <*> option auto (long "bash-completion-index" `mappend` internal) )

      , scriptRequest . bashCompletionScript <$>
            strOption (long "bash-completion-script" `mappend` internal)
      , scriptRequest . fishCompletionScript <$>
            strOption (long "fish-completion-script" `mappend` internal)
      , scriptRequest . zshCompletionScript <$>
            strOption (long "zsh-completion-script" `mappend` internal)
      ]
ghost commented 1 year ago

You're correct! It was totally my mistake. I've should paid attention more.

Thank you for the tips and the fix! I've incorporated the suggestions.

HuwCampbell commented 1 year ago

Ta. Can you squash down to one commit and I'll merge.

HuwCampbell commented 1 year ago

Ta