榆树:如何在浏览器中打印模型?

时间:2016-11-09 23:43:03

标签: elm

这个问题有点傻,但我没有找到直接的解决方案。

假设我有一个类似于此的模型: - 至少这个大。

initModel =
{ selectedCategory = "Vacantion"
, context = "root/Work"
, abstractSyntaxTree =
    [ { categoryName = "Work"
      , categoryContent =
            []
      }
    , { categoryName = "Vacation"
      , categoryContent =
            [ { folderName = "Hawaii"
              , folderContent =
                    FolderContent
                        ( [ { folderName = "Booking"
                            , folderContent = FolderContent ( [], [] )
                            }
                          ]
                        , [ "flightTicket.jpg" ]
                        )
              }
            ]
      }
    ]
}

问题: 如何在浏览器中显示它以使其看起来不错? - 没什么特别的 - 只是为了看看发生了什么就像一个快速的调试器......

到目前为止我尝试过的事情:

view = 
    div [] 
        [ pre [style [("width", "300") ] ] [ text (toString model)]
        ]

在较小的模型上运行得很好,但在这种情况下, 我得到这个长单行 - 格式化json结构: enter image description here

我认为这就是问题:我在谷歌浏览器中安装的美化扩展程序并不知道如何处理其中不包含\n的字符串。为了检查这一点,我手动添加了\n - 该字符串在第二行被拆分,正如预期的那样。

输出表单text (toSting model) - 它是中没有\n的字符串 - 所以这就是显示所有内容的原因浏览器中的单行 - 无论宽度限制为300 px。

通过自己添加\n来分割字符串 - 除了我不知道添加\n的确切位置之外。要使其动态化,这需要模型的完整标记解析器。一种了解表达式开始位置的方法,下一个匹配括号的位置等等。我不足以构建这个解析器。我觉得我过于复杂化了这些东西。必须是一个更好的解决方案..

你们是怎么做到的?

3 个答案:

答案 0 :(得分:8)

Elm不允许您枚举记录中的项目。对于类型安全毫无疑问。所以没有"清洁"很好地显示记录的方法。

更新:以下解决方案将不再适用于Elm 0.19。

它依赖于(已弃用的)函数toString,它将任何类型转换为字符串。 自从Elm 0.17(当我做到这一点)以来,Elm已经在0.18中发布了一个很棒的调试器,它已经具有在单独的窗口中跟踪模型和消息的功能。

对于调试,您可以使用toString做一些诡计,以便更整洁地打印它。 以下是示例代码,您可以将其复制/粘贴到elm-lang.org/try

只需将任何记录传递给viewModel函数,它就会在浏览器中显示。 它非常粗糙,可能不是很大的记录,但它会完成这项工作..

import Html exposing (Html, text, div, p, pre)
import Html.Attributes exposing (style)
import String

quote = "\""
indentChars = "[{("
outdentChars = "}])"
newLineChars = ","
uniqueHead = "##FORMAT##"
incr = 20


model = 
  { name = "Abe"
  , age = 49
  , someTuple = (18,49)
  , relatives = [ "Claire", "Bill" ]
  , comments = "any special characters like []{}, will not be parsed"
  , cars = [ { brand = "BMW", model = "535i" } ]
  }

viewModel : a -> Html msg
viewModel model =
  let
    lines =
      model
      |> toString
      |> formatString False 0 
      |> String.split uniqueHead
  in
    pre [] <| List.map viewLine lines

viewLine : String -> Html msg
viewLine lineStr =
  let
    (indent, lineTxt) = splitLine lineStr
  in
    p [ style 
        [ ("paddingLeft", px (indent))
        , ("marginTop", "0px")
        , ("marginBottom", "0px")
        ] 
      ]
      [ text lineTxt ]


px : Int -> String
px int =
  toString int
  ++ "px"

formatString : Bool -> Int -> String -> String
formatString isInQuotes indent str =
  case String.left 1 str of
    "" -> ""

    firstChar -> 
      if isInQuotes then
        if firstChar == quote then
          firstChar 
          ++ formatString (not isInQuotes) indent (String.dropLeft 1 str)
        else
          firstChar 
          ++ formatString isInQuotes indent (String.dropLeft 1 str)
      else
        if String.contains firstChar newLineChars then
          uniqueHead ++ pad indent ++ firstChar
          ++ formatString isInQuotes indent (String.dropLeft 1 str)
        else if String.contains firstChar indentChars then
          uniqueHead ++ pad (indent + incr) ++ firstChar
          ++ formatString isInQuotes (indent + incr) (String.dropLeft 1 str)
        else if String.contains firstChar outdentChars then
          firstChar ++ uniqueHead ++ pad (indent - incr)
          ++ formatString isInQuotes (indent - incr) (String.dropLeft 1 str)
        else if firstChar == quote then
          firstChar 
          ++ formatString (not isInQuotes) indent (String.dropLeft 1 str)
        else
          firstChar 
          ++ formatString isInQuotes indent (String.dropLeft 1 str)

pad : Int -> String
pad indent =
  String.padLeft 5 '0' <| toString indent

splitLine : String -> (Int, String)
splitLine line =
  let
    indent = 
      String.left 5 line
      |> String.toInt
      |> Result.withDefault 0
    newLine =
      String.dropLeft 5 line
  in
    (indent, newLine)

main =
  viewModel model

答案 1 :(得分:2)

现在我们有一个nice package代表0.19。

elm install ThinkAlexandria/elm-pretty-print-json

并运行

json = """{"name": "Arnold", "age": 70, "isStrong": true,"knownWeakness": null,"nicknames": ["Terminator", "The Governator"],"extra": {"foo": "bar","zap": {"cat": 1,"dog": 2},"transport": [[ "ford", "chevy" ],[ "TGV", "bullet train", "steam" ]]}}"""

{-| Formating configuration.
`indent` is the number of spaces in an indent.
`columns` is the desired column width of the formatted string. The formatter
will try to fit it as best as possible to the column width, but can still
exceed this limit. The maximum column width of the formatted string is
unbounded.
-}
config = {indent = 4, columns = 80}

-- run prettifier
Result.withDefault "" (Json.Print.prettyString config json)

-- result
{-
{
    "extra": {
        "transport": [
            [
                "ford",
                "chevy"
            ],
            [
                "TGV",
                "bullet train",
                "steam"
            ]
        ],
        "zap": {
            "dog": 2,
            "cat": 1
        },
        "foo": "bar"
    },
    "nicknames": [
        "Terminator",
        "The Governator"
    ],
    "knownWeakness": null,
    "isStrong": true,
    "age": 70,
    "name": "Arnold"
}
-}

答案 2 :(得分:0)

我在闲暇时发现了这个:elm-debug-transformer

how to pretty print elm model or elm types in the browser

不要依赖我的要求,因为例如,我将需要使其也可以与node.js一起使用,但目前看来仍然是不错的解决方案。