Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pretty print code blocks according to widget size #1897

Merged
merged 7 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions src/swarm-lang/Swarm/Language/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,25 @@ ppr = prettyPrec 0
docToText :: Doc a -> Text
docToText = RT.renderStrict . layoutPretty defaultLayoutOptions

-- | Render a pretty-printed document as @Text@.
-- This function consumes number of allowed characters in a
-- line before introducing a line break. In other words, it
-- expects the space of the layouter to be supplied.
docToTextWidth :: Doc a -> Int -> Text
docToTextWidth doc layoutWidth =
RT.renderStrict $ layoutPretty (LayoutOptions (AvailablePerLine layoutWidth 1.0)) doc

-- | Pretty-print something and render it as @Text@.
prettyText :: (PrettyPrec a) => a -> Text
prettyText = docToText . ppr

-- | Pretty-print something and render it as @Text@.
-- This is different than @prettyText@ in the sense that it also
-- consumes number of allowed characters in a line before introducing
-- a line break.
prettyTextWidth :: (PrettyPrec a) => a -> Int -> Text
prettyTextWidth = docToTextWidth . ppr

-- | Pretty-print something and render it as (preferably) one line @Text@.
prettyTextLine :: (PrettyPrec a) => a -> Text
prettyTextLine = RT.renderStrict . layoutPretty (LayoutOptions Unbounded) . group . ppr
Expand All @@ -77,6 +92,12 @@ pparens :: Bool -> Doc ann -> Doc ann
pparens True = group . encloseWithIndent 2 lparen rparen
pparens False = id

-- | Same as pparens but does not indent the lines. Only encloses
-- the document with parantheses.
pparens' :: Bool -> Doc ann -> Doc ann
pparens' True = group . enclose lparen rparen
pparens' False = id

encloseWithIndent :: Int -> Doc ann -> Doc ann -> Doc ann -> Doc ann
encloseWithIndent i l r = nest i . enclose (l <> line') (nest (-2) $ line' <> r)

Expand Down Expand Up @@ -171,8 +192,8 @@ instance (UnchainableFun t, PrettyPrec t, SubstRec t) => PrettyPrec (TypeF t) wh
let (iniF, lastF) = unsnocNE $ ty1 <| unchainFun ty2
funs = (prettyPrec 2 <$> iniF) <> [prettyPrec 1 lastF]
inLine l r = l <+> "->" <+> r
multiLine l r = l <+> "->" <> hardline <> r
in pparens (p > 1) . align $
multiLine l r = l <+> "->" <> softline <> r
in pparens' (p > 1) . align $
flatAlt (concatWith multiLine funs) (concatWith inLine funs)
TyRecF x ty ->
pparens (p > 0) $
Expand Down
36 changes: 26 additions & 10 deletions src/swarm-tui/Swarm/TUI/View.hs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ import Swarm.Game.Universe
import Swarm.Game.World.Coords
import Swarm.Game.World.Gen (Seed)
import Swarm.Language.Capability (Capability (..), constCaps)
import Swarm.Language.Pretty (prettyText, prettyTextLine)
import Swarm.Language.Pretty (prettyText, prettyTextLine, prettyTextWidth)
import Swarm.Language.Syntax
import Swarm.Language.Typecheck (inferConst)
import Swarm.Log
Expand Down Expand Up @@ -1276,15 +1276,31 @@ explainCapabilities gs e
]

renderCmdInfo c =
padTop (Pad 1) $
vBox
[ hBox
[ padRight (Pad 1) (txt . syntax $ constInfo c)
, padRight (Pad 1) (txt ":")
, withAttr magentaAttr . txt . prettyText $ inferConst c
]
, padTop (Pad 1) . padLeft (Pad 1) . txtWrap . briefDoc . constDoc $ constInfo c
]
Widget Fixed Fixed $ do
ctx <- getContext
let w = ctx ^. availWidthL
constType = inferConst c
info = constInfo c
requiredWidthForTypes = textWidth (syntax info <> " : " <> prettyTextLine constType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today I learned about textWidth! I didn't know about this before. There are probably some other places in the codebase where we ought to be using it instead of length! https://hackage.haskell.org/package/brick-2.3.1/docs/Brick-Widgets-Core.html#t:TextWidth , for anyone else reading this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@byorgey it will be more noticeable with Unicode and different terminals; see:
https://github.com/jtdaugherty/vty?tab=readme-ov-file#multi-column-character-support

render
. padTop (Pad 1)
$ vBox
[ hBox
[ padRight (Pad 1) (txt $ syntax info)
, padRight (Pad 1) (txt ":")
, if requiredWidthForTypes <= w
then withAttr magentaAttr . txt $ prettyTextLine constType
else emptyWidget
]
, hBox $
if requiredWidthForTypes > w
then
[ padRight (Pad 1) (txt " ")
, withAttr magentaAttr . txt $ prettyTextWidth constType (w - 2)
]
else [emptyWidget]
, padTop (Pad 1) . padLeft (Pad 1) . txtWrap . briefDoc $ constDoc info
]

costWidget cmdsAndCost =
if null ings
Expand Down