2016-11-09 2 views
4

Этот вопрос выглядит глупым, но я не нашел прямого решения.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)] 
     ] 

Прекрасно работает на небольших моделях, но на этом я получаю эта длинная -Single линия - отформатированный JSON, как структура: enter image description here

Я думаю, что это проблема: предварительно Расширение ttify i, установленное в Google Chrome, не знает, как бороться со строками, которые не содержат \n. Чтобы проверить это, я вручную добавил \n - и эта строка была разделена на вторую строку, как и ожидалось.

Выходная форма text (toSting model) - это строка, которая не имеет в нем нет \n - так , поэтому все отображается на одной строке в браузере - независимо от лимита 300 рх по ширине.

Разделение строки - путем добавления \n самостоятельно - работает, кроме как я не знаю, где именно добавить \n. Чтобы сделать его динамичным, для этого требуется полноразмерный синтаксический анализатор для модели. Способ узнать, где начинается выражение, где следующая совпадающая скобка ... и т. Д. Я недостаточно хорош, чтобы построить этот синтаксический анализатор. Я чувствую, что я слишком усложняю этот материал. Должно быть лучшим решением.

Как вы это делаете?

ответ

7

Elm не позволяет перечислить элементы в записи. Для безопасности типа, без сомнения. Таким образом, нет «чистого» способа сделать запись хорошо.

Для отладки вы можете сделать некоторые обманки с помощью 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 
+0

спасибо, человек! Вау! Из этого вы можете сделать пакет :). В слабине никто не знал, как это сделать, и я предполагаю, что другие могли бы также выиграть. У меня еще вопрос: что именно означает yo: '' Elm не позволяет вам перечислить элементы в записи . "? У вас не может быть что-то вроде Object.keys из javascript? – AIon

+0

Рад помочь :) Я не очень хорошо разбираюсь в создании пакетов, но буду изучать его. – wintvelt

+1

Что касается вашего вопроса: ваша интуиция верна. У Elm нет 'Object.keys'.Я предполагаю, что это связано с безопасностью типа: каждый элемент объекта может быть любого типа, и Elm должен знать, какой тип вы используете. Что-то вроде JavaScript 'myObject [someString]' динамических типов, это нарушит эту гарантию. Если каждый элемент имеет тот же тип, вы также можете использовать 'Dict'. – wintvelt

Смежные вопросы