| -- Copyright 2020 The Fuchsia Authors. All rights reserved. |
| -- Use of this source code is governed by a BSD-style license that can be |
| -- found in the LICENSE file. |
| |
| |
| module Settings exposing |
| ( Model |
| , Msg |
| , Scheme |
| , decode |
| , decodeScheme |
| , defaultScheme |
| , encode |
| , init |
| , initCmd |
| , themeClass |
| , update |
| , view |
| ) |
| |
| {-| This module defines a settings form. |
| -} |
| |
| import Dict exposing (Dict) |
| import Form exposing (Form) |
| import Html exposing (Html) |
| import Json.Decode as Decode |
| import Json.Encode as Encode |
| import Ports |
| import Set exposing (Set) |
| |
| |
| |
| ------------- MODEL ------------------------------------------------------------ |
| |
| |
| type alias Model = |
| { form : Form.Model |
| , preferredScheme : Scheme |
| } |
| |
| |
| type Scheme |
| = Light |
| | Dark |
| |
| |
| init : Scheme -> Model |
| init preferredScheme = |
| { form = |
| Form.empty |
| |> Form.insertStringValue "theme" (defaultTheme preferredScheme) |
| , preferredScheme = preferredScheme |
| } |
| |
| |
| initCmd : Model -> Cmd msg |
| initCmd model = |
| applySettings model |
| |
| |
| defaultScheme : Scheme |
| defaultScheme = |
| Light |
| |
| |
| defaultTheme : Scheme -> String |
| defaultTheme scheme = |
| case scheme of |
| Light -> |
| "textmate" |
| |
| Dark -> |
| "tomorrow_night" |
| |
| |
| getTheme : Model -> String |
| getTheme model = |
| Form.getStringValue form "theme" model.form |
| |
| |
| getScheme : String -> Scheme |
| getScheme theme = |
| if Set.member theme lightThemes then |
| Light |
| |
| else |
| Dark |
| |
| |
| themeClass : Model -> String |
| themeClass model = |
| case Dict.get (getTheme model) themeClassSuffixes of |
| Just class -> |
| "ace-" ++ class |
| |
| Nothing -> |
| "" |
| |
| |
| form : Form |
| form = |
| Form.define |
| [ Form.groupedSelect "theme" "Theme" themes "textmate" |
| , Form.select "keyboardHandler" "Keybindings" keybindings "ace" |
| , Form.number "refreshDelay" "Refresh delay (ms)" 500 (\n -> n > 0) |
| , Form.number "fontSize" "Font size" 14 (\n -> n > 0) |
| , Form.checkbox "wrap" "Wrap lines" False |
| , Form.checkbox "indentedSoftWrap" "Indent wrapped lines" False |
| , Form.number "tabSize" "Tab width" 4 (\n -> n > 0) |
| , Form.checkbox "useSoftTabs" "Soft tabs" True |
| , Form.checkbox "atomicSoftTabs" "Atomic soft tabs" True |
| , Form.checkbox "showGutter" "Show gutter" True |
| , Form.checkbox "showLineNumbers" "Line numbers" True |
| , Form.checkbox "relativeLineNumbers" "Relative line numbers" False |
| , Form.checkbox "highlightActiveLine" "Highlight active line" True |
| , Form.checkbox "scrollPastEnd" "Scroll past end" False |
| , Form.select "foldStyle" "Fold markers" foldStyles "markbegin" |
| , Form.checkbox "displayIndentGuides" "Show indent guides" True |
| , Form.checkbox "showInvisibles" "Show invisibles" False |
| , Form.checkbox "showPrintMargin" "Show margin" False |
| , Form.number "printMarginColumn" "Margin column" 80 (\n -> n >= 0) |
| ] |
| |
| |
| themes : List ( String, List ( Form.Identifier, String ) ) |
| themes = |
| [ ( "Light" |
| , [ ( "chrome", "Chrome" ) |
| , ( "clouds", "Clouds" ) |
| , ( "crimson_editor", "Crimson Editor" ) |
| , ( "dawn", "Dawn" ) |
| , ( "dreamweaver", "Dreamweaver" ) |
| , ( "eclipse", "Eclipse" ) |
| , ( "github", "GitHub" ) |
| , ( "iplastic", "iPlastic" ) |
| , ( "katzenmilch", "KatzenMilch" ) |
| , ( "kuroir", "Kuroir" ) |
| , ( "solarized_light", "Solarized Light" ) |
| , ( "sqlserver", "SQL Server" ) |
| , ( "textmate", "TextMate" ) |
| , ( "tomorrow", "Tomorrow" ) |
| , ( "xcode", "Xcode" ) |
| ] |
| ) |
| , ( "Dark" |
| , [ ( "ambiance", "Ambiance" ) |
| , ( "chaos", "Chaos" ) |
| , ( "clouds_midnight", "Clouds Midnight" ) |
| , ( "cobalt", "Cobalt" ) |
| , ( "dracula", "Dracula" ) |
| , ( "gob", "Gob" ) |
| , ( "gruvbox", "Gruvbox" ) |
| , ( "idle_fingers", "idleFingers" ) |
| , ( "kr_theme", "krTheme" ) |
| , ( "merbivore", "Merbivore" ) |
| , ( "merbivore_soft", "Merbivore Soft" ) |
| , ( "mono_industrial", "Mono Industrial" ) |
| , ( "monokai", "Monokai" ) |
| , ( "pastel_on_dark", "Pastel on Dark" ) |
| , ( "solarized_dark", "Solarized Dark" ) |
| , ( "terminal", "Terminal" ) |
| , ( "tomorrow_night", "Tomorrow Night" ) |
| , ( "tomorrow_night_blue", "Tomorrow Night Blue" ) |
| , ( "tomorrow_night_bright", "Tomorrow Night Bright" ) |
| , ( "tomorrow_night_eighties", "Tomorrow Night 80s" ) |
| , ( "twilight", "Twilight" ) |
| , ( "vibrant_ink", "Vibrant Ink" ) |
| ] |
| ) |
| ] |
| |
| |
| lightThemes : Set Form.Identifier |
| lightThemes = |
| Set.fromList |
| [ "chrome" |
| , "clouds" |
| , "crimson_editor" |
| , "dawn" |
| , "dreamweaver" |
| , "eclipse" |
| , "github" |
| , "iplastic" |
| , "katzenmilch" |
| , "kuroir" |
| , "solarized_light" |
| , "sqlserver" |
| , "textmate" |
| , "tomorrow" |
| , "xcode" |
| ] |
| |
| |
| themeClassSuffixes : Dict Form.Identifier String |
| themeClassSuffixes = |
| Dict.fromList |
| [ ( "ambiance", "ambiance" ) |
| , ( "chaos", "chaos" ) |
| , ( "chrome", "chrome" ) |
| , ( "clouds", "clouds" ) |
| , ( "clouds_midnight", "clouds-midnight" ) |
| , ( "cobalt", "cobalt" ) |
| , ( "crimson_editor", "crimson-editor" ) |
| , ( "dawn", "dawn" ) |
| , ( "dracula", "dracula" ) |
| , ( "dreamweaver", "dreamweaver" ) |
| , ( "eclipse", "eclipse" ) |
| , ( "github", "github" ) |
| , ( "gob", "gob" ) |
| , ( "gruvbox", "gruvbox" ) |
| , ( "idle_fingers", "idle-fingers" ) |
| , ( "iplastic", "iplastic" ) |
| , ( "katzenmilch", "katzenmilch" ) |
| , ( "kr_theme", "kr-theme" ) |
| , ( "kuroir", "kuroir" ) |
| , ( "merbivore", "merbivore" ) |
| , ( "merbivore_soft", "merbivore-soft" ) |
| , ( "mono_industrial", "mono-industrial" ) |
| , ( "monokai", "monokai" ) |
| , ( "pastel_on_dark", "pastel-on-dark" ) |
| , ( "solarized_dark", "solarized-dark" ) |
| , ( "solarized_light", "solarized-light" ) |
| , ( "sqlserver", "sqlserver" ) |
| , ( "terminal", "terminal-theme" ) |
| , ( "textmate", "tm" ) |
| , ( "tomorrow", "tomorrow" ) |
| , ( "tomorrow_night", "tomorrow-night" ) |
| , ( "tomorrow_night_blue", "tomorrow-night-blue" ) |
| , ( "tomorrow_night_bright", "tomorrow-night-bright" ) |
| , ( "tomorrow_night_eighties", "tomorrow-night-eighties" ) |
| , ( "twilight", "twilight" ) |
| , ( "vibrant_ink", "vibrant-ink" ) |
| , ( "xcode", "xcode" ) |
| ] |
| |
| |
| keybindings : List ( Form.Identifier, String ) |
| keybindings = |
| [ ( "ace", "Ace" ) |
| , ( "emacs", "Emacs" ) |
| , ( "sublime", "Sublime Text" ) |
| , ( "vim", "Vim" ) |
| , ( "vscode", "VS Code" ) |
| ] |
| |
| |
| foldStyles : List ( Form.Identifier, String ) |
| foldStyles = |
| [ ( "manual", "Off" ) |
| , ( "markbegin", "Begin" ) |
| , ( "markbeginend", "Begin and end" ) |
| ] |
| |
| |
| |
| ------------- UPDATE ----------------------------------------------------------- |
| |
| |
| type Msg |
| = FormMsg Form.Msg |
| | ResetForm |
| | ClearDataAndReload |
| |
| |
| update : Msg -> Model -> ( Model, Cmd msg ) |
| update msg model = |
| case msg of |
| FormMsg formMsg -> |
| let |
| newModel = |
| { model | form = Form.update formMsg model.form } |
| in |
| ( newModel |
| , applySettings newModel |
| ) |
| |
| ResetForm -> |
| let |
| newModel = |
| init model.preferredScheme |
| in |
| ( newModel |
| , applySettings newModel |
| ) |
| |
| ClearDataAndReload -> |
| ( model, Ports.clearDataAndReload ) |
| |
| |
| applySettings : Model -> Cmd msg |
| applySettings model = |
| let |
| scheme = |
| getScheme (getTheme model) |
| |
| augmentedModel = |
| Form.insertStringValue "scheme" |
| (schemeToString scheme) |
| model.form |
| in |
| Ports.applySettings (Form.encodeEffective form augmentedModel) |
| |
| |
| |
| ------------- VIEW ------------------------------------------------------------- |
| |
| |
| view : (Msg -> msg) -> Model -> Html msg |
| view toMsg model = |
| Form.view form (buttons toMsg) (toMsg << FormMsg) model.form |
| |
| |
| buttons : (Msg -> msg) -> List (Form.Button msg) |
| buttons toMsg = |
| [ ( "Use defaults", toMsg ResetForm ) |
| |
| -- Labelling it "Reset" instead of "Clear" because, while it does clear the |
| -- local storage items, they will immediately get set again to their default |
| -- values when the page reloads. |
| , ( "Reset all data", toMsg ClearDataAndReload ) |
| ] |
| |
| |
| |
| ------------- ENCODE / DECODE -------------------------------------------------- |
| |
| |
| encode : Model -> Encode.Value |
| encode model = |
| Form.encode model.form |
| |
| |
| decode : Decode.Decoder Model |
| decode = |
| Decode.map2 Model |
| Form.decode |
| (Decode.succeed defaultScheme) |
| |
| |
| schemeToString : Scheme -> String |
| schemeToString scheme = |
| case scheme of |
| Light -> |
| "light" |
| |
| Dark -> |
| "dark" |
| |
| |
| decodeScheme : Decode.Decoder Scheme |
| decodeScheme = |
| Decode.string |
| |> Decode.andThen |
| (\string -> |
| case schemeFromString string of |
| Just scheme -> |
| Decode.succeed scheme |
| |
| _ -> |
| Decode.fail ("Invalid scheme: " ++ string) |
| ) |
| |
| |
| schemeFromString : String -> Maybe Scheme |
| schemeFromString string = |
| case string of |
| "light" -> |
| Just Light |
| |
| "dark" -> |
| Just Dark |
| |
| _ -> |
| Nothing |