Pretty.hs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. {-# LANGUAGE RecordWildCards #-}
  2. {-# LANGUAGE OverloadedStrings #-}
  3. module Data.SCargot.Pretty where
  4. -- | A 'LayoutOptions' value describes how to pretty-print a 'SExpr'.
  5. -- It describes how to print atoms, what horizontal space to fit
  6. -- it into, and other related options.
  7. --
  8. -- The 'swingIndent' value might require a big of explanation: in
  9. -- pretty-printing s-expressions, you have the option of whether
  10. -- to 'swing' expressions which get pushed to subsequent lines
  11. -- to the left, or to align them along the right. e.g. the
  12. -- s-expression @(foo a b)@ could use a non-swing indent as
  13. --
  14. -- > (foo arg-one
  15. -- > arg-two)
  16. --
  17. -- or a swing indent as
  18. --
  19. -- > (foo arg-one
  20. -- > arg-two)
  21. --
  22. -- often, in formatting Lisp code, control structures will
  23. -- swing subsequent expressions, as in
  24. --
  25. -- > (define (factorial n)
  26. -- > (if (= n 0)
  27. -- > 1
  28. -- > (* n (fact (- n 1)))))
  29. --
  30. -- but most functions will _not_ swing:
  31. --
  32. -- > (call-my-func arg-number-one
  33. -- > arg-number-two
  34. -- > arg-number-three)
  35. --
  36. -- The 'swingIndent' field lets you choose whether or not to
  37. -- swing subsequent s-expressions based on the atom in the car
  38. -- position of a list. You can default to always swinging subsequent
  39. -- expressions with @const True@ and never with @const False@, or
  40. -- choose based on some more advanced criteria. _If_ a swing happens,
  41. -- subsequent lines are indented based on the 'indentAmount' variable;
  42. -- otherwise, subsequent lines are indented based on the size of the
  43. -- @car@ of the list.
  44. data LayoutOptions a = LayoutOptions
  45. { atomPrinter :: a -> Text -- ^ How to serialize a given atom to 'Text'.
  46. , swingIndent :: a -> Bool -- ^ Whether or not to swing
  47. , indentAmount :: Int -- ^ How much to indent after a swing
  48. , maxWidth :: Maybe Int -- ^ The maximum width (if any)
  49. }
  50. flatPrint :: (a -> Text) -> LayoutOptions a
  51. flatPrint printer = LayoutOptions
  52. { atomPrinter = printer
  53. , swingIndent = const True
  54. , indentAmount = 2
  55. , maxWidth = Nothing
  56. }
  57. basicPrint :: (a -> Text) -> LayoutOptions a
  58. basicPrint printer = LayoutOptions
  59. { atomPrinter = printer
  60. , swingIndent = const True
  61. , indentAmount = 2
  62. , maxWidth = Just 80
  63. }
  64. prettyPrintSExpr :: LayoutOptions a -> SExpr a -> Text
  65. prettyPrintSExpr LayoutOptions { .. } = go 0
  66. where go _ SNil = "()"
  67. go _ _ = undefined