Allow overriding background selection color

The Ace editor uses the same color for regular selections and search
highlights, which is fairly low contrast in all themes. This CL adds an
input to the settings form to override that color.

Fixed: 112017
Change-Id: I1bea0beae7e7ab7f94f5db49463f79061bff1169
Reviewed-on: https://fuchsia-review.googlesource.com/c/fidlbolt/+/740607
Reviewed-by: Mukesh Agrawal <quiche@google.com>
diff --git a/frontend/src/elm/Settings.elm b/frontend/src/elm/Settings.elm
index 3cf9c55..5aa75ea 100644
--- a/frontend/src/elm/Settings.elm
+++ b/frontend/src/elm/Settings.elm
@@ -27,6 +27,7 @@
 import Json.Decode as Decode
 import Json.Encode as Encode
 import Ports
+import Regex
 import Set exposing (Set)
 
 
@@ -120,6 +121,17 @@
         , Form.checkbox "showInvisibles" "Show invisibles" False
         , Form.checkbox "showPrintMargin" "Show margin" False
         , Form.number "printMarginColumn" "Margin column" 80 Form.nonnegative
+        , Form.text "selectionBackground"
+            "Selection background"
+            ""
+            { validate =
+                Regex.contains
+                    (Maybe.withDefault Regex.never <|
+                        Regex.fromString "^$|^#(|[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
+                    )
+            , placeholder = Just "#ff0"
+            , invalidMessage = "Invalid color. Try a CSS hex color like \"#ff0\" or \"#d7f05d\"."
+            }
         ]
 
 
@@ -291,13 +303,12 @@
 applySettings : Model -> Cmd msg
 applySettings model =
     let
-        scheme =
-            getScheme (getTheme model)
-
         augmentedModel =
-            Form.insertStringValue "scheme"
-                (schemeToString scheme)
-                model.form
+            model.form
+                |> Form.insertStringValue "scheme"
+                    (schemeToString (getScheme (getTheme model)))
+                |> Form.insertStringValue "themeClass"
+                    (themeClass model)
     in
     Ports.applySettings (Form.encodeEffective form augmentedModel)
 
diff --git a/frontend/src/index.html b/frontend/src/index.html
index 99b107f..51856e1 100644
--- a/frontend/src/index.html
+++ b/frontend/src/index.html
@@ -3,6 +3,7 @@
   <head>
     <meta charset="utf-8">
     <title>fidlbolt</title>
+    <style id="ExtraStyle"></style>
   </head>
   <body>
     <div id="Loader" class="loader" hidden>
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index cf9dd6e..18dc96b 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -74,6 +74,12 @@
         } else {
           classes.remove('dark');
         }
+        const extraStyle = document.getElementById('ExtraStyle');
+        extraStyle!.innerHTML = `
+          .${payload.themeClass} .ace_marker-layer .ace_selection {
+            background: ${payload.selectionBackground};
+          }
+        `;
         break;
       }
       case 'setMainTabEnabled': {
diff --git a/frontend/src/style.css b/frontend/src/style.css
index a4e34f7..a072f15 100644
--- a/frontend/src/style.css
+++ b/frontend/src/style.css
@@ -326,6 +326,16 @@
   font-size: 14px;
 }
 
+.modal-box .form-text {
+  width: 60px;
+}
+
+.modal-box .form-invalid-message {
+  display: block;
+  margin: 8px 0 0;
+  max-width: 200px;
+}
+
 .form-number--invalid, .form-text--invalid {
   color: #f33;
 }