From 4a5041e3cc5775c1f876a4c09f04e319c99004ea Mon Sep 17 00:00:00 2001 From: Huw Campbell Date: Fri, 26 May 2023 11:39:33 +1000 Subject: [PATCH 1/4] Use layoutPretty instead of layoutSmart when rendering help texts. The latter can occasionally result in a hang given complex inputs. --- CHANGELOG.md | 11 +++++++++++ src/Options/Applicative/Help/Pretty.hs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04131555..5ef13ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## Version 0.18.1.0 (26 May 2023) + +- Change layout algorithm used to a simpler, faster one. + + The layoutSmart algorithm appears to be extremely slow with some command line + sets, to the point where the program appears to hang. + + Fixes issues: + * \# 476 - Stack executable 'hangs' with 0.17.1 and 0.18.0. + + ## Version 0.18.0.0 (22 May 2023) - Move to 'prettyprinter` library for pretty printing. diff --git a/src/Options/Applicative/Help/Pretty.hs b/src/Options/Applicative/Help/Pretty.hs index c5ab867a..997ffd58 100644 --- a/src/Options/Applicative/Help/Pretty.hs +++ b/src/Options/Applicative/Help/Pretty.hs @@ -106,7 +106,7 @@ hangAtIfOver i j d = renderPretty :: Double -> Int -> Doc -> SimpleDocStream AnsiStyle renderPretty ribbonFraction lineWidth - = layoutSmart LayoutOptions + = layoutPretty LayoutOptions { layoutPageWidth = AvailablePerLine lineWidth ribbonFraction } prettyString :: Double -> Int -> Doc -> String From 66284950a600a1053978bf0b554eccf9ac53a044 Mon Sep 17 00:00:00 2001 From: Huw Campbell Date: Fri, 26 May 2023 15:28:01 +1000 Subject: [PATCH 2/4] Use Ansi aware rendering functions for printing to the terminal. This unfortunately brings in a direct `text` dependency, which will make supporting text free use cases a bit harder. --- CHANGELOG.md | 1 + optparse-applicative.cabal | 1 + src/Options/Applicative/Help/Pretty.hs | 12 ++++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef13ec8..e84e46a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Fixes issues: * \# 476 - Stack executable 'hangs' with 0.17.1 and 0.18.0. +- Render help text with `AnsiStyle` aware rendering functions. ## Version 0.18.0.0 (22 May 2023) diff --git a/optparse-applicative.cabal b/optparse-applicative.cabal index be172b16..59f64351 100644 --- a/optparse-applicative.cabal +++ b/optparse-applicative.cabal @@ -101,6 +101,7 @@ library , Options.Applicative.Internal build-depends: base >= 4.5 && < 5 + , text >= 1.2 , transformers >= 0.2 && < 0.7 , transformers-compat >= 0.3 && < 0.8 , prettyprinter >= 1.7 && < 1.8 diff --git a/src/Options/Applicative/Help/Pretty.hs b/src/Options/Applicative/Help/Pretty.hs index 997ffd58..43d111a8 100644 --- a/src/Options/Applicative/Help/Pretty.hs +++ b/src/Options/Applicative/Help/Pretty.hs @@ -18,15 +18,15 @@ module Options.Applicative.Help.Pretty #if !MIN_VERSION_base(4,11,0) import Data.Semigroup ((<>), mempty) #endif +import qualified Data.Text.Lazy as Lazy import Prettyprinter hiding (Doc) import qualified Prettyprinter as PP -import qualified Prettyprinter.Render.String as PP import Prettyprinter.Render.Terminal import Prelude -type Doc = PP.Doc Prettyprinter.Render.Terminal.AnsiStyle +type Doc = PP.Doc AnsiStyle type SimpleDoc = SimpleDocStream AnsiStyle linebreak :: Doc @@ -115,5 +115,9 @@ prettyString ribbonFraction lineWidth . renderPretty ribbonFraction lineWidth streamToString :: SimpleDocStream AnsiStyle -> String -streamToString stream = - PP.renderShowS stream "" +streamToString sdoc = + let + rendered = + Prettyprinter.Render.Terminal.renderLazy sdoc + in + Lazy.unpack rendered From d4f5d0d58b077a1643a5c8af18ed8c3bf8e3de34 Mon Sep 17 00:00:00 2001 From: Huw Campbell Date: Fri, 26 May 2023 15:48:25 +1000 Subject: [PATCH 3/4] Rework documentation for latest version --- src/Options/Applicative/Builder.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Options/Applicative/Builder.hs b/src/Options/Applicative/Builder.hs index ec7809c0..bc12b5f2 100644 --- a/src/Options/Applicative/Builder.hs +++ b/src/Options/Applicative/Builder.hs @@ -189,7 +189,7 @@ showDefault = showDefaultWith show help :: String -> Mod f a help s = optionMod $ \p -> p { propHelp = paragraph s } --- | Specify the help text for an option as a 'Text.PrettyPrint.ANSI.Leijen.Doc' +-- | Specify the help text for an option as a 'Prettyprinter.Doc AnsiStyle' -- value. helpDoc :: Maybe Doc -> Mod f a helpDoc doc = optionMod $ \p -> p { propHelp = Chunk doc } @@ -215,7 +215,7 @@ hidden = optionMod $ \p -> -- | Apply a function to the option description in the usage text. -- -- > import Options.Applicative.Help --- > flag' () (short 't' <> style bold) +-- > flag' () (short 't' <> style (annotate bold)) -- -- /NOTE/: This builder is more flexible than its name and example -- allude. One of the motivating examples for its addition was to @@ -402,7 +402,7 @@ briefDesc = InfoMod $ \i -> i { infoFullDesc = False } header :: String -> InfoMod a header s = InfoMod $ \i -> i { infoHeader = paragraph s } --- | Specify a header for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc' +-- | Specify a header for this parser as a 'Prettyprinter.Doc AnsiStyle' -- value. headerDoc :: Maybe Doc -> InfoMod a headerDoc doc = InfoMod $ \i -> i { infoHeader = Chunk doc } @@ -411,7 +411,7 @@ headerDoc doc = InfoMod $ \i -> i { infoHeader = Chunk doc } footer :: String -> InfoMod a footer s = InfoMod $ \i -> i { infoFooter = paragraph s } --- | Specify a footer for this parser as a 'Text.PrettyPrint.ANSI.Leijen.Doc' +-- | Specify a footer for this parser as a 'Prettyprinter.Doc AnsiStyle' -- value. footerDoc :: Maybe Doc -> InfoMod a footerDoc doc = InfoMod $ \i -> i { infoFooter = Chunk doc } @@ -420,7 +420,7 @@ footerDoc doc = InfoMod $ \i -> i { infoFooter = Chunk doc } progDesc :: String -> InfoMod a progDesc s = InfoMod $ \i -> i { infoProgDesc = paragraph s } --- | Specify a short program description as a 'Text.PrettyPrint.ANSI.Leijen.Doc' +-- | Specify a short program description as a 'Prettyprinter.Doc AnsiStyle' -- value. progDescDoc :: Maybe Doc -> InfoMod a progDescDoc doc = InfoMod $ \i -> i { infoProgDesc = Chunk doc } From 0713e59ed028afc3345115a2f438aa14404bae41 Mon Sep 17 00:00:00 2001 From: Huw Campbell Date: Mon, 29 May 2023 09:15:44 +1000 Subject: [PATCH 4/4] Bump version in cabal file --- CHANGELOG.md | 4 ++-- optparse-applicative.cabal | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e84e46a6..d397e8c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ -## Version 0.18.1.0 (26 May 2023) +## Version 0.18.1.0 (29 May 2023) -- Change layout algorithm used to a simpler, faster one. +- Change pretty printer layout algorithm used. The layoutSmart algorithm appears to be extremely slow with some command line sets, to the point where the program appears to hang. diff --git a/optparse-applicative.cabal b/optparse-applicative.cabal index 59f64351..d9a20768 100644 --- a/optparse-applicative.cabal +++ b/optparse-applicative.cabal @@ -1,5 +1,5 @@ name: optparse-applicative -version: 0.18.0.0 +version: 0.18.1.0 synopsis: Utilities and combinators for parsing command line options description: optparse-applicative is a haskell library for parsing options