Skip to content

Commit 540dba0

Browse files
committed
Add experimental support for local print option overrides
1 parent 81264c9 commit 540dba0

File tree

8 files changed

+114
-18
lines changed

8 files changed

+114
-18
lines changed

packages.dhall

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
let upstream =
2-
https://github.com/purescript/package-sets/releases/download/psc-0.14.0-20210324/packages.dhall sha256:b4564d575da6aed1c042ca7936da97c8b7a29473b63f4515f09bb95fae8dddab
2+
https://github.com/purescript/package-sets/releases/download/psc-0.14.3-20210811/packages.dhall sha256:a2de7ef2f2e753733eddfa90573a82da0c7c61d46fa87d015b7f15ef8a6e97d5
33

44
let overrides = {=}
55

spago.dhall

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,30 @@ You can edit this file as you like.
66
, dependencies =
77
[ "aff"
88
, "ansi"
9+
, "arrays"
910
, "avar"
1011
, "console"
12+
, "control"
1113
, "effect"
14+
, "either"
15+
, "exceptions"
1216
, "foldable-traversable"
17+
, "integers"
1318
, "lists"
1419
, "maybe"
1520
, "minibench"
21+
, "node-buffer"
1622
, "node-child-process"
1723
, "node-fs-aff"
24+
, "node-path"
1825
, "node-process"
26+
, "node-streams"
27+
, "parallel"
28+
, "posix-types"
29+
, "prelude"
1930
, "psci-support"
2031
, "strings"
32+
, "tuples"
2133
]
2234
, packages = ./packages.dhall
2335
, sources = [ "src/**/*.purs", "test/**/*.purs" ]

src/Dodo.purs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module Dodo
2828
, encloseWithSeparator
2929
, foldWithSeparator
3030
, foldWith
31+
, locally
3132
, print
3233
, Printer(..)
3334
, plainText
@@ -48,7 +49,7 @@ import Data.String as String
4849
import Data.String.Regex as Regex
4950
import Data.String.Regex.Flags (global)
5051
import Data.String.Regex.Unsafe (unsafeRegex)
51-
import Dodo.Internal (Doc(..), Position, bothNotEmpty, isEmpty, notEmpty)
52+
import Dodo.Internal (Doc(..), Position, LocalOptions, bothNotEmpty, isEmpty, notEmpty)
5253
import Dodo.Internal (Doc, Position, bothNotEmpty, isEmpty, notEmpty) as Exports
5354
import Dodo.Internal.Buffer (Buffer)
5455
import Dodo.Internal.Buffer as Buffer
@@ -193,6 +194,11 @@ foldWithSeparator separator = foldWith (\a b -> a <> (separator <> b))
193194
foldWith :: forall f a. Foldable f => (Doc a -> Doc a -> Doc a) -> f (Doc a) -> Doc a
194195
foldWith f = foldr (bothNotEmpty f) mempty
195196

197+
-- | *EXPERIMENTAL:* modifies printing state and options locally for a document.
198+
-- | This may change or be removed at any time.
199+
locally :: forall a. (LocalOptions -> LocalOptions) -> Doc a -> Doc a
200+
locally = Local
201+
196202
-- | Custom printers can be used to render richer documents than just plain
197203
-- | text.
198204
-- | * `emptyBuffer` - The initial buffer.
@@ -255,6 +261,7 @@ data DocCmd a
255261
| Dedent String Int
256262
| LeaveAnnotation a (List a)
257263
| LeaveFlexGroup (Doc a) (Doc a)
264+
| LeaveLocal LocalOptions
258265

259266
data FlexGroupStatus b a
260267
= NoFlexGroup
@@ -267,6 +274,7 @@ type FlexGroupState b a =
267274
, annotations :: List a
268275
, indentSpaces :: String
269276
, stack :: List (DocCmd a)
277+
, options :: PrintOptions
270278
}
271279

272280
type DocState b a =
@@ -275,15 +283,39 @@ type DocState b a =
275283
, annotations :: List a
276284
, indentSpaces :: String
277285
, flexGroup :: FlexGroupStatus b a
286+
, options :: PrintOptions
278287
}
279288

280289
resetState :: forall a b. FlexGroupState b a -> DocState b a
281-
resetState { position, buffer, annotations, indentSpaces } =
282-
{ position, buffer, annotations, indentSpaces, flexGroup: NoFlexGroup }
290+
resetState { position, buffer, annotations, indentSpaces, options } =
291+
{ position, buffer, annotations, indentSpaces, flexGroup: NoFlexGroup, options }
283292

284293
storeState :: forall a b. List (DocCmd a) -> DocState b a -> FlexGroupState b a
285-
storeState stack { position, buffer, annotations, indentSpaces } =
286-
{ position, buffer, annotations, indentSpaces, stack }
294+
storeState stack { position, buffer, annotations, indentSpaces, options } =
295+
{ position, buffer, annotations, indentSpaces, stack, options }
296+
297+
storeOptions :: forall a b. Int -> LocalOptions -> DocState b a -> DocState b a
298+
storeOptions prevIndent localOptions state = do
299+
let
300+
newOptions =
301+
{ indentUnit: localOptions.indentUnit
302+
, indentWidth: localOptions.indentWidth
303+
, pageWidth: localOptions.pageWidth
304+
, ribbonRatio: localOptions.ribbonRatio
305+
}
306+
state
307+
{ indentSpaces = localOptions.indentSpaces
308+
, options = newOptions
309+
, position
310+
{ pageWidth = newOptions.pageWidth
311+
, ribbonWidth = calcRibbonWidth newOptions prevIndent
312+
, nextIndent = localOptions.indent
313+
}
314+
}
315+
316+
calcRibbonWidth :: PrintOptions -> Int -> Int
317+
calcRibbonWidth { pageWidth, ribbonRatio } n =
318+
max 0 $ Int.ceil $ mul ribbonRatio $ Int.toNumber $ pageWidth - n
287319

288320
-- | Prints a documents given a printer and print options.
289321
-- |
@@ -297,11 +329,8 @@ storeState stack { position, buffer, annotations, indentSpaces } =
297329
print :: forall b a r. Printer b a r -> PrintOptions -> Doc a -> r
298330
print (Printer printer) opts = flip go initState <<< pure <<< Doc
299331
where
300-
ribbonRatio :: Number
301-
ribbonRatio = max 0.0 (min 1.0 opts.ribbonRatio)
302-
303-
calcRibbonWidth :: Int -> Int
304-
calcRibbonWidth = max 0 <<< Int.ceil <<< mul ribbonRatio <<< Int.toNumber <<< (opts.pageWidth - _)
332+
initOptions :: PrintOptions
333+
initOptions = opts { ribbonRatio = max 0.0 (min 1.0 opts.ribbonRatio) }
305334

306335
initState :: DocState b a
307336
initState =
@@ -310,13 +339,14 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
310339
, column: 0
311340
, indent: 0
312341
, nextIndent: 0
313-
, pageWidth: opts.pageWidth
314-
, ribbonWidth: calcRibbonWidth 0
342+
, pageWidth: initOptions.pageWidth
343+
, ribbonWidth: calcRibbonWidth initOptions 0
315344
}
316345
, buffer: Buffer.new printer.emptyBuffer
317346
, annotations: List.Nil
318347
, indentSpaces: ""
319348
, flexGroup: NoFlexGroup
349+
, options: initOptions
320350
}
321351

322352
go :: List (DocCmd a) -> DocState b a -> r
@@ -356,7 +386,7 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
356386
{ line = state.position.line + 1
357387
, column = 0
358388
, indent = state.position.nextIndent
359-
, ribbonWidth = calcRibbonWidth state.position.nextIndent
389+
, ribbonWidth = calcRibbonWidth state.options state.position.nextIndent
360390
}
361391
, buffer = Buffer.modify printer.writeBreak state.buffer
362392
, flexGroup = NoFlexGroup
@@ -367,7 +397,7 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
367397
{ position
368398
{ indent = state.position.nextIndent + opts.indentWidth
369399
, nextIndent = state.position.nextIndent + opts.indentWidth
370-
, ribbonWidth = calcRibbonWidth (state.position.nextIndent + opts.indentWidth)
400+
, ribbonWidth = calcRibbonWidth state.options (state.position.nextIndent + opts.indentWidth)
371401
}
372402
, indentSpaces = state.indentSpaces <> opts.indentUnit
373403
}
@@ -382,7 +412,7 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
382412
{ position
383413
{ indent = state.position.nextIndent + width
384414
, nextIndent = state.position.nextIndent + width
385-
, ribbonWidth = calcRibbonWidth (state.position.nextIndent + width)
415+
, ribbonWidth = calcRibbonWidth state.options (state.position.nextIndent + width)
386416
}
387417
, indentSpaces = state.indentSpaces <> power " " width
388418
}
@@ -423,6 +453,18 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
423453
{ annotations = ann : state.annotations
424454
, buffer = Buffer.modify (printer.enterAnnotation ann state.annotations) state.buffer
425455
}
456+
Local k doc1 -> do
457+
let
458+
prevOptions =
459+
{ indent: state.position.indent
460+
, indentSpaces: state.indentSpaces
461+
, indentUnit: state.options.indentUnit
462+
, indentWidth: state.options.indentWidth
463+
, pageWidth: state.options.pageWidth
464+
, ribbonRatio: state.options.ribbonRatio
465+
}
466+
localOptions = k prevOptions
467+
go (Doc doc1 : LeaveLocal prevOptions: stk) $ storeOptions state.position.indent localOptions state
426468
Empty ->
427469
go stk state
428470
LeaveFlexGroup doc1 doc2 -> case state.flexGroup of
@@ -445,3 +487,5 @@ print (Printer printer) opts = flip go initState <<< pure <<< Doc
445487
{ annotations = anns
446488
, buffer = Buffer.modify (printer.leaveAnnotation ann anns) state.buffer
447489
}
490+
LeaveLocal prevOptions ->
491+
go stk $ storeOptions state.position.indent prevOptions state

src/Dodo/Ansi.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ ansiGraphics = Printer
118118
}
119119

120120
leaveAnnotation :: Ansi.GraphicsParam -> List Ansi.GraphicsParam -> AnsiBuffer -> AnsiBuffer
121-
leaveAnnotation a as (AnsiBuffer buffer) = do
121+
leaveAnnotation _ as (AnsiBuffer buffer) = do
122122
let current = getCurrentGraphics as
123123
AnsiBuffer buffer
124124
{ pending = Just $ fromMaybe (pure Ansi.Reset) $ getPendingGraphics current

src/Dodo/Internal.purs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,20 @@ data Doc a
2323
| FlexSelect (Doc a) (Doc a) (Doc a)
2424
| FlexAlt (Doc a) (Doc a)
2525
| WithPosition (Position -> Doc a)
26+
| Local (LocalOptions -> LocalOptions) (Doc a)
2627
| Text Int String
2728
| Break
2829
| Empty
2930

31+
type LocalOptions =
32+
{ indent :: Int
33+
, indentSpaces :: String
34+
, indentUnit :: String
35+
, indentWidth :: Int
36+
, pageWidth :: Int
37+
, ribbonRatio :: Number
38+
}
39+
3040
derive instance functorDoc :: Functor Doc
3141

3242
instance semigroupDoc :: Semigroup (Doc a) where

test/Snapshot.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ snapshotMainOutput directory accept mbPattern = do
8484
writeFile outputFile =<< liftEffect (Buffer.fromString output UTF8)
8585
savedOutput <- try $ readFile outputFile
8686
case savedOutput of
87-
Left err -> do
87+
Left _ -> do
8888
acceptOutput
8989
pure { name, output, result: Saved }
9090
Right buffer -> do

test/snapshots/DodoLocally.output

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
hello
2+
indented
3+
undented
4+
undented indent
5+
indented again

test/snapshots/DodoLocally.purs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module DodoLocally where
2+
3+
import Prelude
4+
5+
import Dodo (Doc, fourSpaces, indent, lines, locally, plainText, print, text)
6+
import Effect (Effect)
7+
import Effect.Class.Console as Console
8+
9+
test1 :: forall a. Doc a
10+
test1 = lines
11+
[ text "hello"
12+
, indent $ lines
13+
[ text "indented"
14+
, locally (_ { indent = 2, indentSpaces = " " }) do
15+
lines
16+
[ text "undented"
17+
, indent $ text "undented indent"
18+
]
19+
, text "indented again"
20+
]
21+
]
22+
23+
main :: Effect Unit
24+
main = do
25+
Console.log $ print plainText fourSpaces test1

0 commit comments

Comments
 (0)