Merge branch 'main' into request-to-join-project

Antonio Scandurra created

Change summary

Cargo.lock                                    |   35 
assets/themes/cave-dark.json                  |   82 
assets/themes/cave-light.json                 |  150 
assets/themes/dark.json                       | 1710 ---------------------
assets/themes/light.json                      | 1710 ---------------------
assets/themes/solarized-dark.json             |   82 
assets/themes/solarized-light.json            |  150 
assets/themes/sulphurpool-dark.json           |   82 
assets/themes/sulphurpool-light.json          |  150 
crates/breadcrumbs/src/breadcrumbs.rs         |    6 
crates/collab/Cargo.toml                      |    8 
crates/collab/k8s/environments/production.sh  |    3 
crates/collab/k8s/environments/staging.sh     |    3 
crates/collab/k8s/manifest.template.yml       |    2 
crates/collab/src/auth.rs                     |    9 
crates/collab/src/main.rs                     |   72 
crates/collab/src/rpc.rs                      |   63 
crates/diagnostics/src/diagnostics.rs         |   19 
crates/diagnostics/src/items.rs               |    6 
crates/editor/src/editor.rs                   |  619 ++----
crates/editor/src/element.rs                  |    9 
crates/editor/src/items.rs                    |   22 
crates/editor/src/multi_buffer.rs             |   23 
crates/editor/src/selections_collection.rs    |  729 ++++++++
crates/editor/src/test.rs                     |    4 
crates/go_to_line/src/go_to_line.rs           |   10 
crates/gpui/src/app.rs                        |    7 
crates/gpui/src/presenter.rs                  |    6 
crates/journal/src/journal.rs                 |    6 
crates/outline/src/outline.rs                 |   12 
crates/project_symbols/src/project_symbols.rs |    8 
crates/rpc/Cargo.toml                         |    2 
crates/rpc/src/peer.rs                        |   90 
crates/search/src/buffer_search.rs            |   70 
crates/search/src/project_search.rs           |   32 
crates/theme/src/theme.rs                     |    2 
crates/vim/src/insert.rs                      |   10 
crates/vim/src/normal.rs                      |   44 
crates/vim/src/normal/change.rs               |   29 
crates/vim/src/normal/delete.rs               |   30 
crates/vim/src/vim_test_context.rs            |    9 
crates/vim/src/visual.rs                      |   78 
crates/zed/Cargo.toml                         |    2 
crates/zed/src/zed.rs                         |   42 
styles/dist/dark.json                         |  405 +---
styles/dist/light.json                        |  403 +---
styles/dist/solarized-dark.json               |   92 
styles/dist/solarized-light.json              |  104 
styles/dist/tokens.json                       |  824 ++-------
styles/src/buildThemes.ts                     |   11 
styles/src/buildTokens.ts                     |    4 
styles/src/themes/base16.ts                   |  214 +-
styles/src/themes/cave.ts                     |   40 
styles/src/themes/dark.ts                     |  240 --
styles/src/themes/gruvbox.ts                  |   30 
styles/src/themes/light.ts                    |  240 --
styles/src/themes/solarized.ts                |   40 
styles/src/themes/sulphurpool.ts              |   40 
styles/src/themes/theme.ts                    |    5 
59 files changed, 2,512 insertions(+), 6,417 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -876,6 +876,7 @@ dependencies = [
  "tonic",
  "tower",
  "tracing",
+ "tracing-log",
  "tracing-opentelemetry",
  "tracing-subscriber",
  "util",
@@ -2590,6 +2591,15 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
 
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata",
+]
+
 [[package]]
 name = "matches"
 version = "0.1.8"
@@ -3737,6 +3747,15 @@ dependencies = [
  "regex-syntax",
 ]
 
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax",
+]
+
 [[package]]
 name = "regex-syntax"
 version = "0.6.25"
@@ -3849,7 +3868,6 @@ dependencies = [
  "collections",
  "futures",
  "gpui",
- "log",
  "parking_lot",
  "prost 0.8.0",
  "prost-build 0.8.0",
@@ -3859,6 +3877,7 @@ dependencies = [
  "smol",
  "smol-timeout",
  "tempdir",
+ "tracing",
  "util",
  "zstd",
 ]
@@ -5247,9 +5266,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
 
 [[package]]
 name = "tracing"
-version = "0.1.26"
+version = "0.1.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
+checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
 dependencies = [
  "cfg-if 1.0.0",
  "log",
@@ -5260,9 +5279,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.15"
+version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
+checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5320,9 +5339,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
 dependencies = [
  "ansi_term 0.12.1",
+ "lazy_static",
+ "matchers",
+ "regex",
  "sharded-slab",
  "smallvec",
  "thread_local",
+ "tracing",
  "tracing-core",
  "tracing-log",
 ]
@@ -5987,7 +6010,7 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
 
 [[package]]
 name = "zed"
-version = "0.32.0"
+version = "0.33.0"
 dependencies = [
  "anyhow",
  "assets",

assets/themes/cave-dark.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#5852605c",
+        "background": "#3f3b45",
         "text": {
           "family": "Zed Sans",
           "color": "#e2dfe7",
@@ -31,7 +31,7 @@
         }
       },
       "hover": {
-        "background": "#5852603d"
+        "background": "#332f38"
       }
     },
     "border": {
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#e2dfe7",
-          "background": "#5852603d"
+          "background": "#332f38"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#5852603d"
+            "background": "#332f38"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#8b8792",
           "hover": {
             "icon_color": "#e2dfe7",
-            "background": "#5852603d"
+            "background": "#332f38"
           },
           "active": {
             "icon_color": "#efecf4",
-            "background": "#5852605c"
+            "background": "#3f3b45"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#26232a",
+      "background": "#332f38",
       "padding": {
         "left": 80,
         "right": 6
@@ -436,15 +436,15 @@
         },
         "color": "#8b8792",
         "hover": {
-          "background": "#5852603d",
+          "background": "#3f3b45",
           "color": "#8b8792"
         },
         "active": {
-          "background": "#5852605c",
+          "background": "#4c4653",
           "color": "#efecf4"
         },
         "active_hover": {
-          "background": "#5852603d",
+          "background": "#3f3b45",
           "color": "#efecf4"
         }
       },
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#efecf4",
     "background": "#19171c",
-    "active_line_background": "#efecf412",
+    "active_line_background": "#26232a",
     "code_actions_indicator": "#8b8792",
     "diff_background_deleted": "#be467826",
     "diff_background_inserted": "#2a929226",
-    "document_highlight_read_background": "#efecf41f",
-    "document_highlight_write_background": "#efecf43d",
+    "document_highlight_read_background": "#5852603d",
+    "document_highlight_write_background": "#5852607a",
     "error_color": "#be4678",
     "gutter_background": "#19171c",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#efecf41f",
+    "highlighted_line_background": "#332f38",
     "line_number": "#7e7887",
     "line_number_active": "#efecf4",
     "rename_fade": 0.6,
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#26232a3d"
+        "background": "#1c1a20"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#26232a5c"
+        "background": "#201d23"
       }
     },
     "diagnostic_header": {
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#efecf412",
+      "background": "#26232a",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#8b8792",
+        "color": "#e2dfe7",
         "weight": "normal"
       },
       "constant": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#5852603d",
+        "background": "#332f38",
         "text": {
           "family": "Zed Mono",
           "color": "#e2dfe7",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#5852605c",
+        "background": "#3f3b45",
         "text": {
           "family": "Zed Mono",
           "color": "#e2dfe7",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#5852603d",
+        "background": "#332f38",
         "text": {
           "family": "Zed Mono",
           "color": "#efecf4",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#26232a5c",
+      "background": "#201d23",
       "text": {
         "family": "Zed Mono",
         "color": "#e2dfe7",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#5852603d",
+        "background": "#332f38",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#5852603d",
+        "background": "#332f38",
         "corner_radius": 6
       },
       "menu": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#e2dfe7",
         "size": 14,
-        "background": "#5852605c"
+        "background": "#4c4653"
       }
     },
     "contact_row": {
@@ -1326,7 +1326,7 @@
         "right": 12
       },
       "active": {
-        "background": "#5852605c"
+        "background": "#4c4653"
       }
     },
     "tree_branch": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#26232a",
+      "background": "#332f38",
       "color": "#e2dfe7",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#5852603d"
+        "background": "#3f3b45"
       }
     },
     "disabled_contact_button": {
-      "background": "#26232a",
+      "background": "#332f38",
       "color": "#8b8792",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#26232a",
       "hover": {
-        "background": "#5852603d"
+        "background": "#332f38"
       },
       "active": {
-        "background": "#5852605c"
+        "background": "#3f3b45"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#5852605c",
+        "background": "#3f3b45",
         "text": {
           "family": "Zed Sans",
           "color": "#e2dfe7",
@@ -1436,7 +1436,7 @@
         }
       },
       "hover": {
-        "background": "#5852603d"
+        "background": "#332f38"
       }
     },
     "border": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#26232a",
+      "background": "#332f38",
       "color": "#e2dfe7",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#5852603d"
+        "background": "#3f3b45"
       }
     },
     "disabled_contact_button": {
-      "background": "#26232a",
+      "background": "#332f38",
       "color": "#8b8792",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,14 +1521,14 @@
     }
   },
   "search": {
-    "match_background": "#955ae77a",
+    "match_background": "#3d1576",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#8b8792",
       "size": 14,
-      "background": "#26232a",
+      "background": "#332f38",
       "corner_radius": 6,
       "border": {
         "color": "#26232a",
@@ -1547,7 +1547,7 @@
         "family": "Zed Mono",
         "color": "#efecf4",
         "size": 14,
-        "background": "#5852607a",
+        "background": "#4c4653",
         "border": {
           "color": "#655f6d",
           "width": 1
@@ -1557,7 +1557,7 @@
         "family": "Zed Mono",
         "color": "#efecf4",
         "size": 14,
-        "background": "#5852603d",
+        "background": "#3f3b45",
         "border": {
           "color": "#655f6d",
           "width": 1
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#26232a3d"
+        "background": "#1c1a20"
       }
     },
     "dismiss_button": {

assets/themes/cave-light.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#8b87922e",
+        "background": "#b7b3bd",
         "text": {
           "family": "Zed Sans",
           "color": "#26232a",
@@ -31,11 +31,11 @@
         }
       },
       "hover": {
-        "background": "#8b87921f"
+        "background": "#ccc9d2"
       }
     },
     "border": {
-      "color": "#efecf4",
+      "color": "#8b8792",
       "width": 1
     },
     "empty": {
@@ -69,7 +69,7 @@
         "size": 14
       },
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "padding": {
@@ -117,7 +117,7 @@
         "size": 14
       },
       "border": {
-        "color": "#efecf4",
+        "color": "#8b8792",
         "width": 1,
         "left": true,
         "bottom": true,
@@ -143,7 +143,7 @@
         "size": 14
       },
       "border": {
-        "color": "#efecf4",
+        "color": "#8b8792",
         "width": 1,
         "left": true,
         "bottom": false,
@@ -162,13 +162,13 @@
       "cursor": "Arrow"
     },
     "sidebar_resize_handle": {
-      "background": "#efecf4",
+      "background": "#8b8792",
       "padding": {
         "left": 1
       }
     },
     "pane_divider": {
-      "color": "#e2dfe7",
+      "color": "#8b8792",
       "width": 1
     },
     "status_bar": {
@@ -181,7 +181,7 @@
         "right": 6
       },
       "border": {
-        "color": "#efecf4",
+        "color": "#8b8792",
         "width": 1,
         "top": true,
         "overlay": true
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#26232a",
-          "background": "#8b87921f"
+          "background": "#ccc9d2"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#8b87921f"
+            "background": "#ccc9d2"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#585260",
           "hover": {
             "icon_color": "#26232a",
-            "background": "#8b87921f"
+            "background": "#ccc9d2"
           },
           "active": {
             "icon_color": "#19171c",
-            "background": "#8b87922e"
+            "background": "#b7b3bd"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "padding": {
         "left": 80,
         "right": 6
@@ -393,14 +393,14 @@
         "width": 12
       },
       "border": {
-        "color": "#efecf4",
+        "color": "#8b8792",
         "width": 1,
         "bottom": true,
         "overlay": true
       },
       "sign_in_prompt": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1
         },
         "corner_radius": 6,
@@ -436,15 +436,15 @@
         },
         "color": "#585260",
         "hover": {
-          "background": "#8b87921f",
+          "background": "#b7b3bd",
           "color": "#585260"
         },
         "active": {
-          "background": "#8b87922e",
+          "background": "#a19da7",
           "color": "#19171c"
         },
         "active_hover": {
-          "background": "#8b87921f",
+          "background": "#b7b3bd",
           "color": "#19171c"
         }
       },
@@ -468,7 +468,7 @@
       "height": 34,
       "background": "#efecf4",
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1,
         "bottom": true
       },
@@ -502,7 +502,7 @@
       "corner_radius": 6,
       "padding": 12,
       "border": {
-        "color": "#efecf4",
+        "color": "#8b8792",
         "width": 1
       },
       "shadow": {
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#19171c",
     "background": "#efecf4",
-    "active_line_background": "#19171c12",
+    "active_line_background": "#e2dfe7",
     "code_actions_indicator": "#585260",
     "diff_background_deleted": "#be467826",
     "diff_background_inserted": "#2a929226",
-    "document_highlight_read_background": "#19171c0f",
-    "document_highlight_write_background": "#19171c1f",
+    "document_highlight_read_background": "#8b87921f",
+    "document_highlight_write_background": "#8b87923d",
     "error_color": "#be4678",
     "gutter_background": "#efecf4",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#19171c1f",
+    "highlighted_line_background": "#ccc9d2",
     "line_number": "#655f6d",
     "line_number_active": "#19171c",
     "rename_fade": 0.6,
@@ -578,7 +578,7 @@
       "corner_radius": 8,
       "padding": 4,
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "item": {
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#e2dfe71f"
+        "background": "#ece9f1"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#e2dfe72e"
+        "background": "#e9e6ee"
       }
     },
     "diagnostic_header": {
@@ -624,7 +624,7 @@
       "icon_width_factor": 1.5,
       "text_scale_factor": 0.857,
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1,
         "bottom": true,
         "top": true
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#19171c12",
+      "background": "#e2dfe7",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -672,7 +672,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -695,7 +695,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -718,7 +718,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -741,7 +741,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -764,7 +764,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -787,7 +787,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -810,7 +810,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -833,7 +833,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1,
           "top": true
         }
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#585260",
+        "color": "#26232a",
         "weight": "normal"
       },
       "constant": {
@@ -959,7 +959,7 @@
       "corner_radius": 4,
       "background": "#efecf4",
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "padding": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#8b87921f",
+        "background": "#ccc9d2",
         "text": {
           "family": "Zed Mono",
           "color": "#26232a",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#8b87922e",
+        "background": "#b7b3bd",
         "text": {
           "family": "Zed Mono",
           "color": "#26232a",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#8b87921f",
+        "background": "#ccc9d2",
         "text": {
           "family": "Zed Mono",
           "color": "#19171c",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#e2dfe72e",
+      "background": "#e9e6ee",
       "text": {
         "family": "Zed Mono",
         "color": "#26232a",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#8b87921f",
+        "background": "#ccc9d2",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#8b87921f",
+        "background": "#ccc9d2",
         "corner_radius": 6
       },
       "menu": {
@@ -1151,7 +1151,7 @@
         "corner_radius": 6,
         "padding": 4,
         "border": {
-          "color": "#efecf4",
+          "color": "#8b8792",
           "width": 1
         },
         "shadow": {
@@ -1242,7 +1242,7 @@
         "selection": "#576ddb3d"
       },
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "padding": {
@@ -1276,7 +1276,7 @@
         "selection": "#576ddb3d"
       },
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "padding": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#26232a",
         "size": 14,
-        "background": "#8b87922e"
+        "background": "#a19da7"
       }
     },
     "contact_row": {
@@ -1326,17 +1326,17 @@
         "right": 12
       },
       "active": {
-        "background": "#8b87922e"
+        "background": "#a19da7"
       }
     },
     "tree_branch": {
-      "color": "#7e7887",
+      "color": "#655f6d",
       "width": 1,
       "hover": {
-        "color": "#7e7887"
+        "color": "#655f6d"
       },
       "active": {
-        "color": "#7e7887"
+        "color": "#655f6d"
       }
     },
     "contact_avatar": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "color": "#26232a",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#8b87921f"
+        "background": "#b7b3bd"
       }
     },
     "disabled_contact_button": {
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "color": "#585260",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#e2dfe7",
       "hover": {
-        "background": "#8b87921f"
+        "background": "#ccc9d2"
       },
       "active": {
-        "background": "#8b87922e"
+        "background": "#b7b3bd"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#8b87922e",
+        "background": "#b7b3bd",
         "text": {
           "family": "Zed Sans",
           "color": "#26232a",
@@ -1436,11 +1436,11 @@
         }
       },
       "hover": {
-        "background": "#8b87921f"
+        "background": "#ccc9d2"
       }
     },
     "border": {
-      "color": "#efecf4",
+      "color": "#8b8792",
       "width": 1
     },
     "empty": {
@@ -1474,7 +1474,7 @@
         "size": 14
       },
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "padding": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "color": "#26232a",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#8b87921f"
+        "background": "#b7b3bd"
       }
     },
     "disabled_contact_button": {
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "color": "#585260",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,17 +1521,17 @@
     }
   },
   "search": {
-    "match_background": "#955ae73d",
+    "match_background": "#d5bdfa",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#585260",
       "size": 14,
-      "background": "#e2dfe7",
+      "background": "#ccc9d2",
       "corner_radius": 6,
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "margin": {
@@ -1547,9 +1547,9 @@
         "family": "Zed Mono",
         "color": "#19171c",
         "size": 14,
-        "background": "#8b87923d",
+        "background": "#a19da7",
         "border": {
-          "color": "#7e7887",
+          "color": "#655f6d",
           "width": 1
         }
       },
@@ -1557,9 +1557,9 @@
         "family": "Zed Mono",
         "color": "#19171c",
         "size": 14,
-        "background": "#8b87921f",
+        "background": "#b7b3bd",
         "border": {
-          "color": "#7e7887",
+          "color": "#655f6d",
           "width": 1
         }
       }
@@ -1584,7 +1584,7 @@
         "size": 14
       },
       "border": {
-        "color": "#e2dfe7",
+        "color": "#8b8792",
         "width": 1
       },
       "margin": {
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#e2dfe71f"
+        "background": "#ece9f1"
       }
     },
     "dismiss_button": {

assets/themes/dark.json 🔗

@@ -1,1710 +0,0 @@
-{
-  "picker": {
-    "background": "#1c1c1c",
-    "corner_radius": 8,
-    "padding": 8,
-    "item": {
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 4
-      },
-      "corner_radius": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#9c9c9c",
-        "size": 14
-      },
-      "highlight_text": {
-        "family": "Zed Sans",
-        "color": "#4f8ff7",
-        "weight": "bold",
-        "size": 14
-      },
-      "active": {
-        "background": "#2b2b2b",
-        "text": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        }
-      },
-      "hover": {
-        "background": "#232323"
-      }
-    },
-    "border": {
-      "color": "#070707",
-      "width": 1
-    },
-    "empty": {
-      "text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 8
-      }
-    },
-    "input_editor": {
-      "background": "#000000",
-      "corner_radius": 8,
-      "placeholder_text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 16,
-        "right": 16,
-        "top": 7
-      }
-    },
-    "shadow": {
-      "blur": 16,
-      "color": "#00000052",
-      "offset": [
-        0,
-        2
-      ]
-    }
-  },
-  "workspace": {
-    "background": "#1c1c1c",
-    "joining_project_avatar": {
-      "corner_radius": 40,
-      "width": 80
-    },
-    "joining_project_message": {
-      "padding": 12,
-      "family": "Zed Sans",
-      "color": "#f1f1f1",
-      "size": 18
-    },
-    "leader_border_opacity": 0.7,
-    "leader_border_width": 2,
-    "tab": {
-      "height": 32,
-      "background": "#1c1c1c",
-      "icon_close": "#555555",
-      "icon_close_active": "#ffffff",
-      "icon_conflict": "#f6a724",
-      "icon_dirty": "#135acd",
-      "icon_width": 8,
-      "spacing": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#9c9c9c",
-        "size": 14
-      },
-      "border": {
-        "color": "#070707",
-        "width": 1,
-        "left": true,
-        "bottom": true,
-        "overlay": true
-      },
-      "padding": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "active_tab": {
-      "height": 32,
-      "background": "#000000",
-      "icon_close": "#555555",
-      "icon_close_active": "#ffffff",
-      "icon_conflict": "#f6a724",
-      "icon_dirty": "#135acd",
-      "icon_width": 8,
-      "spacing": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#ffffff",
-        "size": 14
-      },
-      "border": {
-        "color": "#070707",
-        "width": 1,
-        "left": true,
-        "bottom": false,
-        "overlay": true
-      },
-      "padding": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "modal": {
-      "margin": {
-        "bottom": 52,
-        "top": 52
-      },
-      "cursor": "Arrow"
-    },
-    "sidebar_resize_handle": {
-      "background": "#070707",
-      "padding": {
-        "left": 1
-      }
-    },
-    "pane_divider": {
-      "color": "#232323",
-      "width": 1
-    },
-    "status_bar": {
-      "height": 30,
-      "item_spacing": 8,
-      "padding": {
-        "top": 1,
-        "bottom": 1,
-        "left": 6,
-        "right": 6
-      },
-      "border": {
-        "color": "#070707",
-        "width": 1,
-        "top": true,
-        "overlay": true
-      },
-      "cursor_position": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "auto_update_progress_message": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "auto_update_done_message": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "lsp_status": {
-        "corner_radius": 6,
-        "padding": {
-          "top": 1,
-          "bottom": 1,
-          "left": 6,
-          "right": 6
-        },
-        "icon_spacing": 4,
-        "icon_width": 14,
-        "height": 18,
-        "message": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14
-        },
-        "icon_color": "#555555",
-        "hover": {
-          "message": {
-            "family": "Zed Sans",
-            "color": "#f1f1f1",
-            "size": 14
-          },
-          "icon_color": "#c6c6c6",
-          "background": "#232323"
-        }
-      },
-      "diagnostic_message": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14,
-        "hover": {
-          "family": "Zed Sans",
-          "color": "#9c9c9c",
-          "size": 14
-        }
-      },
-      "diagnostic_summary": {
-        "height": 16,
-        "icon_width": 14,
-        "icon_spacing": 2,
-        "summary_spacing": 6,
-        "text": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        },
-        "icon_color_ok": "#9c9c9c",
-        "icon_color_warning": "#f6a724",
-        "icon_color_error": "#eb2d2d",
-        "container_ok": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 3,
-            "bottom": 3,
-            "left": 7,
-            "right": 7
-          }
-        },
-        "container_warning": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 1,
-            "bottom": 1,
-            "left": 6,
-            "right": 6
-          },
-          "background": "#f6a72426",
-          "border": {
-            "color": "#f6a72426",
-            "width": 1
-          }
-        },
-        "container_error": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 1,
-            "bottom": 1,
-            "left": 6,
-            "right": 6
-          },
-          "background": "#c9181826",
-          "border": {
-            "color": "#eb2d2d26",
-            "width": 1
-          }
-        },
-        "hover": {
-          "icon_color_ok": "#c6c6c6",
-          "container_ok": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 3,
-              "bottom": 3,
-              "left": 7,
-              "right": 7
-            },
-            "background": "#232323"
-          },
-          "container_warning": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 1,
-              "bottom": 1,
-              "left": 6,
-              "right": 6
-            },
-            "background": "#f6a72433",
-            "border": {
-              "color": "#f6a72426",
-              "width": 1
-            }
-          },
-          "container_error": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 1,
-              "bottom": 1,
-              "left": 6,
-              "right": 6
-            },
-            "background": "#c9181833",
-            "border": {
-              "color": "#eb2d2d26",
-              "width": 1
-            }
-          }
-        }
-      },
-      "sidebar_buttons": {
-        "group_left": {},
-        "group_right": {},
-        "item": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 3,
-            "bottom": 3,
-            "left": 6,
-            "right": 6
-          },
-          "icon_size": 14,
-          "icon_color": "#9c9c9c",
-          "hover": {
-            "icon_color": "#c6c6c6",
-            "background": "#232323"
-          },
-          "active": {
-            "icon_color": "#ffffff",
-            "background": "#2b2b2b"
-          }
-        },
-        "badge": {
-          "corner_radius": 3,
-          "padding": 2,
-          "margin": {
-            "bottom": -1,
-            "right": -1
-          },
-          "border": {
-            "width": 1,
-            "color": "#1c1c1c"
-          },
-          "background": "#2472f2"
-        }
-      }
-    },
-    "titlebar": {
-      "avatar_width": 18,
-      "avatar_margin": 8,
-      "height": 33,
-      "background": "#2b2b2b",
-      "padding": {
-        "left": 80,
-        "right": 6
-      },
-      "title": {
-        "family": "Zed Sans",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "avatar": {
-        "corner_radius": 10,
-        "border": {
-          "color": "#00000088",
-          "width": 1
-        }
-      },
-      "avatar_ribbon": {
-        "height": 3,
-        "width": 12
-      },
-      "border": {
-        "color": "#070707",
-        "width": 1,
-        "bottom": true,
-        "overlay": true
-      },
-      "sign_in_prompt": {
-        "border": {
-          "color": "#070707",
-          "width": 1
-        },
-        "corner_radius": 6,
-        "margin": {
-          "top": 1
-        },
-        "padding": {
-          "left": 6,
-          "right": 6
-        },
-        "family": "Zed Sans",
-        "color": "#9c9c9c",
-        "size": 12,
-        "hover": {
-          "family": "Zed Sans",
-          "color": "#ffffff",
-          "size": 12
-        }
-      },
-      "offline_icon": {
-        "color": "#9c9c9c",
-        "width": 16,
-        "padding": {
-          "right": 4
-        }
-      },
-      "share_icon": {
-        "corner_radius": 6,
-        "margin": {
-          "top": 3,
-          "bottom": 2,
-          "left": 6
-        },
-        "color": "#9c9c9c",
-        "hover": {
-          "background": "#323232",
-          "color": "#9c9c9c"
-        },
-        "active": {
-          "background": "#1c1c1c",
-          "color": "#ffffff"
-        },
-        "active_hover": {
-          "background": "#323232",
-          "color": "#ffffff"
-        }
-      },
-      "outdated_warning": {
-        "family": "Zed Sans",
-        "color": "#f7bb57",
-        "size": 12,
-        "background": "#f6a72426",
-        "border": {
-          "color": "#f6a72426",
-          "width": 1
-        },
-        "padding": {
-          "left": 6,
-          "right": 6
-        },
-        "corner_radius": 6
-      }
-    },
-    "toolbar": {
-      "height": 34,
-      "background": "#000000",
-      "border": {
-        "color": "#232323",
-        "width": 1,
-        "bottom": true
-      },
-      "item_spacing": 8,
-      "padding": {
-        "left": 16,
-        "right": 8,
-        "top": 4,
-        "bottom": 4
-      }
-    },
-    "breadcrumbs": {
-      "family": "Zed Mono",
-      "color": "#9c9c9c",
-      "size": 14,
-      "padding": {
-        "left": 6
-      }
-    },
-    "disconnected_overlay": {
-      "family": "Zed Sans",
-      "color": "#ffffff",
-      "size": 14,
-      "background": "#000000aa"
-    },
-    "notification": {
-      "margin": {
-        "top": 10
-      },
-      "background": "#1c1c1c",
-      "corner_radius": 6,
-      "padding": 12,
-      "border": {
-        "color": "#070707",
-        "width": 1
-      },
-      "shadow": {
-        "blur": 16,
-        "color": "#00000052",
-        "offset": [
-          0,
-          2
-        ]
-      }
-    },
-    "notifications": {
-      "width": 380,
-      "margin": {
-        "right": 10,
-        "bottom": 10
-      }
-    }
-  },
-  "editor": {
-    "text_color": "#d5d5d5",
-    "background": "#000000",
-    "active_line_background": "#ffffff12",
-    "code_actions_indicator": "#555555",
-    "diff_background_deleted": "#c9181826",
-    "diff_background_inserted": "#1b944726",
-    "document_highlight_read_background": "#ffffff1f",
-    "document_highlight_write_background": "#ffffff29",
-    "error_color": "#f15656",
-    "gutter_background": "#000000",
-    "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#ffffff1f",
-    "line_number": "#474747",
-    "line_number_active": "#ffffff",
-    "rename_fade": 0.6,
-    "unnecessary_code_fade": 0.5,
-    "selection": {
-      "cursor": "#2472f2",
-      "selection": "#2472f23d"
-    },
-    "guest_selections": [
-      {
-        "cursor": "#79ba16",
-        "selection": "#79ba163d"
-      },
-      {
-        "cursor": "#d430e0",
-        "selection": "#d430e03d"
-      },
-      {
-        "cursor": "#ee670a",
-        "selection": "#ee670a3d"
-      },
-      {
-        "cursor": "#993bf3",
-        "selection": "#993bf33d"
-      },
-      {
-        "cursor": "#16d6c1",
-        "selection": "#16d6c13d"
-      },
-      {
-        "cursor": "#ef59a3",
-        "selection": "#ef59a33d"
-      },
-      {
-        "cursor": "#f7bf17",
-        "selection": "#f7bf173d"
-      }
-    ],
-    "autocomplete": {
-      "background": "#000000",
-      "corner_radius": 8,
-      "padding": 4,
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        }
-      },
-      "hovered_item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        },
-        "background": "#ffffff14"
-      },
-      "margin": {
-        "left": -14
-      },
-      "match_highlight": {
-        "family": "Zed Mono",
-        "color": "#4f8ff7",
-        "size": 14
-      },
-      "selected_item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        },
-        "background": "#ffffff1f"
-      }
-    },
-    "diagnostic_header": {
-      "background": "#1c1c1c",
-      "icon_width_factor": 1.5,
-      "text_scale_factor": 0.857,
-      "border": {
-        "color": "#232323",
-        "width": 1,
-        "bottom": true,
-        "top": true
-      },
-      "code": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14,
-        "margin": {
-          "left": 10
-        }
-      },
-      "message": {
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14,
-          "weight": "bold"
-        },
-        "text": {
-          "family": "Zed Sans",
-          "color": "#9c9c9c",
-          "size": 14
-        }
-      }
-    },
-    "diagnostic_path_header": {
-      "background": "#ffffff12",
-      "text_scale_factor": 0.857,
-      "filename": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "path": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14,
-        "margin": {
-          "left": 12
-        }
-      }
-    },
-    "error_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#f15656",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#f15656",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "warning_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#f7bb57",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#f7bb57",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "information_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "hint_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_error_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_hint_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_information_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_warning_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#070707",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "syntax": {
-      "primary": {
-        "color": "#d5d5d5",
-        "weight": "normal"
-      },
-      "comment": {
-        "color": "#aaaaaa",
-        "weight": "normal"
-      },
-      "punctuation": {
-        "color": "#c6c6c6",
-        "weight": "normal"
-      },
-      "constant": {
-        "color": "#d5d5d5",
-        "weight": "normal"
-      },
-      "keyword": {
-        "color": "#4f8ff7",
-        "weight": "normal"
-      },
-      "function": {
-        "color": "#f9da82",
-        "weight": "normal"
-      },
-      "type": {
-        "color": "#3eeeda",
-        "weight": "normal"
-      },
-      "variant": {
-        "color": "#53c1f5",
-        "weight": "normal"
-      },
-      "property": {
-        "color": "#4f8ff7",
-        "weight": "normal"
-      },
-      "enum": {
-        "color": "#ee670a",
-        "weight": "normal"
-      },
-      "operator": {
-        "color": "#ee670a",
-        "weight": "normal"
-      },
-      "string": {
-        "color": "#f99d5f",
-        "weight": "normal"
-      },
-      "number": {
-        "color": "#aeef4b",
-        "weight": "normal"
-      },
-      "boolean": {
-        "color": "#aeef4b",
-        "weight": "normal"
-      },
-      "predictive": {
-        "color": "#808080",
-        "weight": "normal"
-      },
-      "title": {
-        "color": "#de900c",
-        "weight": "bold"
-      },
-      "emphasis": {
-        "color": "#4f8ff7",
-        "weight": "normal"
-      },
-      "emphasis.strong": {
-        "color": "#4f8ff7",
-        "weight": "bold"
-      },
-      "link_uri": {
-        "color": "#79ba16",
-        "weight": "normal",
-        "underline": true
-      },
-      "link_text": {
-        "color": "#ee670a",
-        "weight": "normal",
-        "italic": true
-      }
-    }
-  },
-  "project_diagnostics": {
-    "background": "#000000",
-    "tab_icon_spacing": 4,
-    "tab_icon_width": 13,
-    "tab_summary_spacing": 10,
-    "empty_message": {
-      "family": "Zed Sans",
-      "color": "#9c9c9c",
-      "size": 16
-    }
-  },
-  "command_palette": {
-    "keystroke_spacing": 8,
-    "key": {
-      "text": {
-        "family": "Zed Mono",
-        "color": "#9c9c9c",
-        "size": 12
-      },
-      "corner_radius": 4,
-      "background": "#0e0e0e80",
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "padding": {
-        "top": 2,
-        "bottom": 2,
-        "left": 8,
-        "right": 8
-      },
-      "margin": {
-        "left": 2
-      },
-      "active": {
-        "text": {
-          "family": "Zed Mono",
-          "color": "#ffffff",
-          "size": 12
-        }
-      }
-    }
-  },
-  "project_panel": {
-    "padding": {
-      "left": 12,
-      "right": 12,
-      "top": 6,
-      "bottom": 6
-    },
-    "indent_width": 20,
-    "entry": {
-      "height": 24,
-      "icon_color": "#555555",
-      "icon_size": 8,
-      "icon_spacing": 8,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14
-      },
-      "hover": {
-        "background": "#232323",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#f1f1f1",
-          "size": 14
-        }
-      },
-      "active": {
-        "background": "#2b2b2b",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#f1f1f1",
-          "size": 14
-        }
-      },
-      "active_hover": {
-        "background": "#232323",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#ffffff",
-          "size": 14
-        }
-      }
-    },
-    "filename_editor": {
-      "background": "#ffffff1f",
-      "text": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      }
-    }
-  },
-  "chat_panel": {
-    "padding": {
-      "top": 12,
-      "bottom": 12
-    },
-    "channel_name": {
-      "family": "Zed Sans",
-      "color": "#f1f1f1",
-      "weight": "bold",
-      "size": 14
-    },
-    "channel_name_hash": {
-      "family": "Zed Sans",
-      "color": "#808080",
-      "size": 14,
-      "padding": {
-        "right": 8
-      }
-    },
-    "channel_select": {
-      "header": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        },
-        "padding": {
-          "bottom": 4,
-          "left": 0
-        },
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#9c9c9c",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "hovered_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#9c9c9c",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "background": "#232323",
-        "corner_radius": 6
-      },
-      "active_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "hovered_active_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#808080",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "background": "#232323",
-        "corner_radius": 6
-      },
-      "menu": {
-        "background": "#000000",
-        "corner_radius": 6,
-        "padding": 4,
-        "border": {
-          "color": "#070707",
-          "width": 1
-        },
-        "shadow": {
-          "blur": 16,
-          "color": "#00000052",
-          "offset": [
-            0,
-            2
-          ]
-        }
-      }
-    },
-    "sign_in_prompt": {
-      "family": "Zed Sans",
-      "color": "#9c9c9c",
-      "underline": true,
-      "size": 14
-    },
-    "hovered_sign_in_prompt": {
-      "family": "Zed Sans",
-      "color": "#f1f1f1",
-      "underline": true,
-      "size": 14
-    },
-    "message": {
-      "body": {
-        "family": "Zed Sans",
-        "color": "#9c9c9c",
-        "size": 14
-      },
-      "timestamp": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 6
-      },
-      "sender": {
-        "family": "Zed Sans",
-        "color": "#f1f1f1",
-        "weight": "bold",
-        "size": 14,
-        "margin": {
-          "right": 8
-        }
-      }
-    },
-    "pending_message": {
-      "body": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "timestamp": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 6
-      },
-      "sender": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "weight": "bold",
-        "size": 14,
-        "margin": {
-          "right": 8
-        }
-      }
-    },
-    "input_editor": {
-      "background": "#000000",
-      "corner_radius": 6,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 8,
-        "right": 8,
-        "top": 7
-      }
-    }
-  },
-  "contacts_panel": {
-    "padding": {
-      "top": 12,
-      "bottom": 12
-    },
-    "user_query_editor": {
-      "background": "#000000",
-      "corner_radius": 6,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 8,
-        "right": 8,
-        "top": 4
-      },
-      "margin": {
-        "left": 12,
-        "right": 12
-      }
-    },
-    "user_query_editor_height": 32,
-    "add_contact_button": {
-      "margin": {
-        "left": 6,
-        "right": 12
-      },
-      "color": "#c6c6c6",
-      "button_width": 8,
-      "icon_width": 8
-    },
-    "row_height": 28,
-    "section_icon_size": 8,
-    "header_row": {
-      "family": "Zed Mono",
-      "color": "#9c9c9c",
-      "size": 14,
-      "margin": {
-        "top": 14
-      },
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "active": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14,
-        "background": "#1c1c1c"
-      }
-    },
-    "contact_row": {
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "active": {
-        "background": "#1c1c1c"
-      }
-    },
-    "tree_branch": {
-      "color": "#000000",
-      "width": 1,
-      "hover": {
-        "color": "#000000"
-      },
-      "active": {
-        "color": "#000000"
-      }
-    },
-    "contact_avatar": {
-      "corner_radius": 10,
-      "width": 18
-    },
-    "contact_username": {
-      "family": "Zed Mono",
-      "color": "#f1f1f1",
-      "size": 14,
-      "margin": {
-        "left": 8
-      }
-    },
-    "contact_button_spacing": 8,
-    "contact_button": {
-      "background": "#2b2b2b",
-      "color": "#c6c6c6",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8,
-      "hover": {
-        "background": "#323232"
-      }
-    },
-    "disabled_contact_button": {
-      "background": "#2b2b2b",
-      "color": "#555555",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8
-    },
-    "project_row": {
-      "guest_avatar_spacing": 4,
-      "height": 24,
-      "guest_avatar": {
-        "corner_radius": 8,
-        "width": 14
-      },
-      "name": {
-        "family": "Zed Mono",
-        "color": "#9c9c9c",
-        "size": 14,
-        "margin": {
-          "left": 8,
-          "right": 6
-        }
-      },
-      "guests": {
-        "margin": {
-          "left": 8,
-          "right": 8
-        }
-      },
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "background": "#1c1c1c",
-      "hover": {
-        "background": "#232323"
-      },
-      "active": {
-        "background": "#2b2b2b"
-      }
-    }
-  },
-  "contact_finder": {
-    "background": "#1c1c1c",
-    "corner_radius": 8,
-    "padding": 8,
-    "item": {
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 4
-      },
-      "corner_radius": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#9c9c9c",
-        "size": 14
-      },
-      "highlight_text": {
-        "family": "Zed Sans",
-        "color": "#4f8ff7",
-        "weight": "bold",
-        "size": 14
-      },
-      "active": {
-        "background": "#2b2b2b",
-        "text": {
-          "family": "Zed Sans",
-          "color": "#f1f1f1",
-          "size": 14
-        }
-      },
-      "hover": {
-        "background": "#232323"
-      }
-    },
-    "border": {
-      "color": "#070707",
-      "width": 1
-    },
-    "empty": {
-      "text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 8
-      }
-    },
-    "input_editor": {
-      "background": "#000000",
-      "corner_radius": 8,
-      "placeholder_text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#f1f1f1",
-        "size": 14
-      },
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 16,
-        "right": 16,
-        "top": 7
-      }
-    },
-    "shadow": {
-      "blur": 16,
-      "color": "#00000052",
-      "offset": [
-        0,
-        2
-      ]
-    },
-    "row_height": 28,
-    "contact_avatar": {
-      "corner_radius": 10,
-      "width": 18
-    },
-    "contact_username": {
-      "padding": {
-        "left": 8
-      }
-    },
-    "contact_button": {
-      "background": "#2b2b2b",
-      "color": "#c6c6c6",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8,
-      "hover": {
-        "background": "#323232"
-      }
-    },
-    "disabled_contact_button": {
-      "background": "#2b2b2b",
-      "color": "#555555",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8
-    }
-  },
-  "search": {
-    "match_background": "#3f15a380",
-    "tab_icon_spacing": 8,
-    "tab_icon_width": 14,
-    "option_button": {
-      "family": "Zed Mono",
-      "color": "#9c9c9c",
-      "size": 14,
-      "background": "#0e0e0e",
-      "corner_radius": 6,
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "margin": {
-        "right": 4
-      },
-      "padding": {
-        "bottom": 2,
-        "left": 10,
-        "right": 10,
-        "top": 2
-      },
-      "active": {
-        "family": "Zed Mono",
-        "color": "#ffffff",
-        "size": 14,
-        "background": "#232323",
-        "border": {
-          "color": "#404040",
-          "width": 1
-        }
-      },
-      "hover": {
-        "family": "Zed Mono",
-        "color": "#ffffff",
-        "size": 14,
-        "background": "#1c1c1c",
-        "border": {
-          "color": "#404040",
-          "width": 1
-        }
-      }
-    },
-    "editor": {
-      "background": "#000000",
-      "corner_radius": 8,
-      "min_width": 200,
-      "max_width": 500,
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#ffffff",
-        "size": 14
-      },
-      "border": {
-        "color": "#232323",
-        "width": 1
-      },
-      "margin": {
-        "right": 12
-      },
-      "padding": {
-        "top": 3,
-        "bottom": 3,
-        "left": 12,
-        "right": 8
-      }
-    },
-    "invalid_editor": {
-      "background": "#000000",
-      "corner_radius": 8,
-      "min_width": 200,
-      "max_width": 500,
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#ffffff",
-        "size": 14
-      },
-      "border": {
-        "color": "#eb2d2d26",
-        "width": 1
-      },
-      "margin": {
-        "right": 12
-      },
-      "padding": {
-        "top": 3,
-        "bottom": 3,
-        "left": 12,
-        "right": 8
-      }
-    },
-    "match_index": {
-      "family": "Zed Mono",
-      "color": "#808080",
-      "size": 14,
-      "padding": 6
-    },
-    "option_button_group": {
-      "padding": {
-        "left": 12,
-        "right": 12
-      }
-    },
-    "results_status": {
-      "family": "Zed Mono",
-      "color": "#f1f1f1",
-      "size": 18
-    }
-  },
-  "breadcrumbs": {
-    "family": "Zed Sans",
-    "color": "#9c9c9c",
-    "size": 14,
-    "padding": {
-      "left": 6
-    }
-  },
-  "contact_notification": {
-    "header_avatar": {
-      "height": 12,
-      "width": 12,
-      "corner_radius": 6
-    },
-    "header_message": {
-      "family": "Zed Sans",
-      "color": "#f1f1f1",
-      "size": 12,
-      "margin": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "header_height": 18,
-    "body_message": {
-      "family": "Zed Sans",
-      "color": "#9c9c9c",
-      "size": 12,
-      "margin": {
-        "left": 20,
-        "top": 6,
-        "bottom": 6
-      }
-    },
-    "button": {
-      "family": "Zed Sans",
-      "color": "#f1f1f1",
-      "size": 12,
-      "background": "#0e0e0e80",
-      "padding": 4,
-      "corner_radius": 6,
-      "margin": {
-        "left": 6
-      },
-      "hover": {
-        "background": "#070707"
-      }
-    },
-    "dismiss_button": {
-      "color": "#9c9c9c",
-      "icon_width": 8,
-      "icon_height": 8,
-      "button_width": 8,
-      "button_height": 8,
-      "hover": {
-        "color": "#c6c6c6"
-      }
-    }
-  }
-}

assets/themes/light.json 🔗

@@ -1,1710 +0,0 @@
-{
-  "picker": {
-    "background": "#f8f8f8",
-    "corner_radius": 8,
-    "padding": 8,
-    "item": {
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 4
-      },
-      "corner_radius": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "highlight_text": {
-        "family": "Zed Sans",
-        "color": "#484bed",
-        "weight": "bold",
-        "size": 14
-      },
-      "active": {
-        "background": "#e3e3e3",
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        }
-      },
-      "hover": {
-        "background": "#eaeaea"
-      }
-    },
-    "border": {
-      "color": "#d5d5d5",
-      "width": 1
-    },
-    "empty": {
-      "text": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 8
-      }
-    },
-    "input_editor": {
-      "background": "#ffffff",
-      "corner_radius": 8,
-      "placeholder_text": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 16,
-        "right": 16,
-        "top": 7
-      }
-    },
-    "shadow": {
-      "blur": 16,
-      "color": "#0000001f",
-      "offset": [
-        0,
-        2
-      ]
-    }
-  },
-  "workspace": {
-    "background": "#f8f8f8",
-    "joining_project_avatar": {
-      "corner_radius": 40,
-      "width": 80
-    },
-    "joining_project_message": {
-      "padding": 12,
-      "family": "Zed Sans",
-      "color": "#2b2b2b",
-      "size": 18
-    },
-    "leader_border_opacity": 0.7,
-    "leader_border_width": 2,
-    "tab": {
-      "height": 32,
-      "background": "#f8f8f8",
-      "icon_close": "#9c9c9c",
-      "icon_close_active": "#000000",
-      "icon_conflict": "#f7bf17",
-      "icon_dirty": "#135acd",
-      "icon_width": 8,
-      "spacing": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "left": true,
-        "bottom": true,
-        "overlay": true
-      },
-      "padding": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "active_tab": {
-      "height": 32,
-      "background": "#ffffff",
-      "icon_close": "#9c9c9c",
-      "icon_close_active": "#000000",
-      "icon_conflict": "#f7bf17",
-      "icon_dirty": "#135acd",
-      "icon_width": 8,
-      "spacing": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#000000",
-        "size": 14
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "left": true,
-        "bottom": false,
-        "overlay": true
-      },
-      "padding": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "modal": {
-      "margin": {
-        "bottom": 52,
-        "top": 52
-      },
-      "cursor": "Arrow"
-    },
-    "sidebar_resize_handle": {
-      "background": "#d5d5d5",
-      "padding": {
-        "left": 1
-      }
-    },
-    "pane_divider": {
-      "color": "#d5d5d5",
-      "width": 1
-    },
-    "status_bar": {
-      "height": 30,
-      "item_spacing": 8,
-      "padding": {
-        "top": 1,
-        "bottom": 1,
-        "left": 6,
-        "right": 6
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "top": true,
-        "overlay": true
-      },
-      "cursor_position": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "auto_update_progress_message": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "auto_update_done_message": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "lsp_status": {
-        "corner_radius": 6,
-        "padding": {
-          "top": 1,
-          "bottom": 1,
-          "left": 6,
-          "right": 6
-        },
-        "icon_spacing": 4,
-        "icon_width": 14,
-        "height": 18,
-        "message": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14
-        },
-        "icon_color": "#9c9c9c",
-        "hover": {
-          "message": {
-            "family": "Zed Sans",
-            "color": "#2b2b2b",
-            "size": 14
-          },
-          "icon_color": "#393939",
-          "background": "#eaeaea"
-        }
-      },
-      "diagnostic_message": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14,
-        "hover": {
-          "family": "Zed Sans",
-          "color": "#474747",
-          "size": 14
-        }
-      },
-      "diagnostic_summary": {
-        "height": 16,
-        "icon_width": 14,
-        "icon_spacing": 2,
-        "summary_spacing": 6,
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        },
-        "icon_color_ok": "#717171",
-        "icon_color_warning": "#f7bf17",
-        "icon_color_error": "#c91818",
-        "container_ok": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 3,
-            "bottom": 3,
-            "left": 7,
-            "right": 7
-          }
-        },
-        "container_warning": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 1,
-            "bottom": 1,
-            "left": 6,
-            "right": 6
-          },
-          "background": "#f6a72426",
-          "border": {
-            "color": "#f6a72426",
-            "width": 1
-          }
-        },
-        "container_error": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 1,
-            "bottom": 1,
-            "left": 6,
-            "right": 6
-          },
-          "background": "#c9181826",
-          "border": {
-            "color": "#eb2d2d26",
-            "width": 1
-          }
-        },
-        "hover": {
-          "icon_color_ok": "#393939",
-          "container_ok": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 3,
-              "bottom": 3,
-              "left": 7,
-              "right": 7
-            },
-            "background": "#eaeaea"
-          },
-          "container_warning": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 1,
-              "bottom": 1,
-              "left": 6,
-              "right": 6
-            },
-            "background": "#f6a72433",
-            "border": {
-              "color": "#f6a72426",
-              "width": 1
-            }
-          },
-          "container_error": {
-            "corner_radius": 6,
-            "padding": {
-              "top": 1,
-              "bottom": 1,
-              "left": 6,
-              "right": 6
-            },
-            "background": "#c9181833",
-            "border": {
-              "color": "#eb2d2d26",
-              "width": 1
-            }
-          }
-        }
-      },
-      "sidebar_buttons": {
-        "group_left": {},
-        "group_right": {},
-        "item": {
-          "corner_radius": 6,
-          "padding": {
-            "top": 3,
-            "bottom": 3,
-            "left": 6,
-            "right": 6
-          },
-          "icon_size": 14,
-          "icon_color": "#717171",
-          "hover": {
-            "icon_color": "#393939",
-            "background": "#eaeaea"
-          },
-          "active": {
-            "icon_color": "#000000",
-            "background": "#e3e3e3"
-          }
-        },
-        "badge": {
-          "corner_radius": 3,
-          "padding": 2,
-          "margin": {
-            "bottom": -1,
-            "right": -1
-          },
-          "border": {
-            "width": 1,
-            "color": "#f8f8f8"
-          },
-          "background": "#484bed"
-        }
-      }
-    },
-    "titlebar": {
-      "avatar_width": 18,
-      "avatar_margin": 8,
-      "height": 33,
-      "background": "#eaeaea",
-      "padding": {
-        "left": 80,
-        "right": 6
-      },
-      "title": {
-        "family": "Zed Sans",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "avatar": {
-        "corner_radius": 10,
-        "border": {
-          "color": "#00000088",
-          "width": 1
-        }
-      },
-      "avatar_ribbon": {
-        "height": 3,
-        "width": 12
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "bottom": true,
-        "overlay": true
-      },
-      "sign_in_prompt": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1
-        },
-        "corner_radius": 6,
-        "margin": {
-          "top": 1
-        },
-        "padding": {
-          "left": 6,
-          "right": 6
-        },
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 12,
-        "hover": {
-          "family": "Zed Sans",
-          "color": "#000000",
-          "size": 12
-        }
-      },
-      "offline_icon": {
-        "color": "#717171",
-        "width": 16,
-        "padding": {
-          "right": 4
-        }
-      },
-      "share_icon": {
-        "corner_radius": 6,
-        "margin": {
-          "top": 3,
-          "bottom": 2,
-          "left": 6
-        },
-        "color": "#717171",
-        "hover": {
-          "background": "#e3e3e3",
-          "color": "#717171"
-        },
-        "active": {
-          "background": "#d5d5d5",
-          "color": "#000000"
-        },
-        "active_hover": {
-          "background": "#e3e3e3",
-          "color": "#000000"
-        }
-      },
-      "outdated_warning": {
-        "family": "Zed Sans",
-        "color": "#d3a20b",
-        "size": 12,
-        "background": "#f6a72426",
-        "border": {
-          "color": "#f6a72426",
-          "width": 1
-        },
-        "padding": {
-          "left": 6,
-          "right": 6
-        },
-        "corner_radius": 6
-      }
-    },
-    "toolbar": {
-      "height": 34,
-      "background": "#ffffff",
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "bottom": true
-      },
-      "item_spacing": 8,
-      "padding": {
-        "left": 16,
-        "right": 8,
-        "top": 4,
-        "bottom": 4
-      }
-    },
-    "breadcrumbs": {
-      "family": "Zed Mono",
-      "color": "#474747",
-      "size": 14,
-      "padding": {
-        "left": 6
-      }
-    },
-    "disconnected_overlay": {
-      "family": "Zed Sans",
-      "color": "#000000",
-      "size": 14,
-      "background": "#000000aa"
-    },
-    "notification": {
-      "margin": {
-        "top": 10
-      },
-      "background": "#f8f8f8",
-      "corner_radius": 6,
-      "padding": 12,
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "shadow": {
-        "blur": 16,
-        "color": "#0000001f",
-        "offset": [
-          0,
-          2
-        ]
-      }
-    },
-    "notifications": {
-      "width": 380,
-      "margin": {
-        "right": 10,
-        "bottom": 10
-      }
-    }
-  },
-  "editor": {
-    "text_color": "#1c1c1c",
-    "background": "#ffffff",
-    "active_line_background": "#0000000f",
-    "code_actions_indicator": "#9c9c9c",
-    "diff_background_deleted": "#c9181826",
-    "diff_background_inserted": "#1b944726",
-    "document_highlight_read_background": "#0000000f",
-    "document_highlight_write_background": "#00000029",
-    "error_color": "#eb2d2d",
-    "gutter_background": "#ffffff",
-    "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#0000001f",
-    "line_number": "#aaaaaa",
-    "line_number_active": "#000000",
-    "rename_fade": 0.6,
-    "unnecessary_code_fade": 0.5,
-    "selection": {
-      "cursor": "#2472f2",
-      "selection": "#2472f23d"
-    },
-    "guest_selections": [
-      {
-        "cursor": "#12d796",
-        "selection": "#12d7963d"
-      },
-      {
-        "cursor": "#de57e8",
-        "selection": "#de57e83d"
-      },
-      {
-        "cursor": "#f9812e",
-        "selection": "#f9812e3d"
-      },
-      {
-        "cursor": "#b066f8",
-        "selection": "#b066f83d"
-      },
-      {
-        "cursor": "#16d6c1",
-        "selection": "#16d6c13d"
-      },
-      {
-        "cursor": "#ef59a3",
-        "selection": "#ef59a33d"
-      },
-      {
-        "cursor": "#f7bf17",
-        "selection": "#f7bf173d"
-      }
-    ],
-    "autocomplete": {
-      "background": "#ffffff",
-      "corner_radius": 8,
-      "padding": 4,
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        }
-      },
-      "hovered_item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        },
-        "background": "#00000008"
-      },
-      "margin": {
-        "left": -14
-      },
-      "match_highlight": {
-        "family": "Zed Mono",
-        "color": "#484bed",
-        "size": 14
-      },
-      "selected_item": {
-        "corner_radius": 6,
-        "padding": {
-          "bottom": 2,
-          "left": 6,
-          "right": 6,
-          "top": 2
-        },
-        "background": "#0000000f"
-      }
-    },
-    "diagnostic_header": {
-      "background": "#f8f8f8",
-      "icon_width_factor": 1.5,
-      "text_scale_factor": 0.857,
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1,
-        "bottom": true,
-        "top": true
-      },
-      "code": {
-        "family": "Zed Mono",
-        "color": "#636363",
-        "size": 14,
-        "margin": {
-          "left": 10
-        }
-      },
-      "message": {
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14,
-          "weight": "bold"
-        },
-        "text": {
-          "family": "Zed Sans",
-          "color": "#474747",
-          "size": 14
-        }
-      }
-    },
-    "diagnostic_path_header": {
-      "background": "#0000000f",
-      "text_scale_factor": 0.857,
-      "filename": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "path": {
-        "family": "Zed Mono",
-        "color": "#636363",
-        "size": 14,
-        "margin": {
-          "left": 12
-        }
-      }
-    },
-    "error_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#eb2d2d",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#eb2d2d",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "warning_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#d3a20b",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#d3a20b",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "information_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "hint_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#2472f2",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_error_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_hint_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_information_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "invalid_warning_diagnostic": {
-      "text_scale_factor": 0.857,
-      "header": {
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1,
-          "top": true
-        }
-      },
-      "message": {
-        "text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14
-        },
-        "highlight_text": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "weight": "bold"
-        }
-      }
-    },
-    "syntax": {
-      "primary": {
-        "color": "#1c1c1c",
-        "weight": "normal"
-      },
-      "comment": {
-        "color": "#717171",
-        "weight": "normal"
-      },
-      "punctuation": {
-        "color": "#555555",
-        "weight": "normal"
-      },
-      "constant": {
-        "color": "#1c1c1c",
-        "weight": "normal"
-      },
-      "keyword": {
-        "color": "#1819a1",
-        "weight": "normal"
-      },
-      "function": {
-        "color": "#bb550e",
-        "weight": "normal"
-      },
-      "type": {
-        "color": "#a8820e",
-        "weight": "normal"
-      },
-      "variant": {
-        "color": "#97142a",
-        "weight": "normal"
-      },
-      "property": {
-        "color": "#106c4e",
-        "weight": "normal"
-      },
-      "enum": {
-        "color": "#eb2d2d",
-        "weight": "normal"
-      },
-      "operator": {
-        "color": "#eb2d2d",
-        "weight": "normal"
-      },
-      "string": {
-        "color": "#eb2d2d",
-        "weight": "normal"
-      },
-      "number": {
-        "color": "#484bed",
-        "weight": "normal"
-      },
-      "boolean": {
-        "color": "#eb2d2d",
-        "weight": "normal"
-      },
-      "predictive": {
-        "color": "#808080",
-        "weight": "normal"
-      },
-      "title": {
-        "color": "#1096d3",
-        "weight": "bold"
-      },
-      "emphasis": {
-        "color": "#484bed",
-        "weight": "normal"
-      },
-      "emphasis.strong": {
-        "color": "#484bed",
-        "weight": "bold"
-      },
-      "link_uri": {
-        "color": "#79ba16",
-        "weight": "normal",
-        "underline": true
-      },
-      "link_text": {
-        "color": "#eb2d2d",
-        "weight": "normal",
-        "italic": true
-      }
-    }
-  },
-  "project_diagnostics": {
-    "background": "#ffffff",
-    "tab_icon_spacing": 4,
-    "tab_icon_width": 13,
-    "tab_summary_spacing": 10,
-    "empty_message": {
-      "family": "Zed Sans",
-      "color": "#474747",
-      "size": 16
-    }
-  },
-  "command_palette": {
-    "keystroke_spacing": 8,
-    "key": {
-      "text": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 12
-      },
-      "corner_radius": 4,
-      "background": "#f1f1f1",
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "padding": {
-        "top": 2,
-        "bottom": 2,
-        "left": 8,
-        "right": 8
-      },
-      "margin": {
-        "left": 2
-      },
-      "active": {
-        "text": {
-          "family": "Zed Mono",
-          "color": "#000000",
-          "size": 12
-        }
-      }
-    }
-  },
-  "project_panel": {
-    "padding": {
-      "left": 12,
-      "right": 12,
-      "top": 6,
-      "bottom": 6
-    },
-    "indent_width": 20,
-    "entry": {
-      "height": 24,
-      "icon_color": "#9c9c9c",
-      "icon_size": 8,
-      "icon_spacing": 8,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#636363",
-        "size": 14
-      },
-      "hover": {
-        "background": "#eaeaea",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#2b2b2b",
-          "size": 14
-        }
-      },
-      "active": {
-        "background": "#e3e3e3",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#2b2b2b",
-          "size": 14
-        }
-      },
-      "active_hover": {
-        "background": "#eaeaea",
-        "text": {
-          "family": "Zed Mono",
-          "color": "#000000",
-          "size": 14
-        }
-      }
-    },
-    "filename_editor": {
-      "background": "#0000000f",
-      "text": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      }
-    }
-  },
-  "chat_panel": {
-    "padding": {
-      "top": 12,
-      "bottom": 12
-    },
-    "channel_name": {
-      "family": "Zed Sans",
-      "color": "#2b2b2b",
-      "weight": "bold",
-      "size": 14
-    },
-    "channel_name_hash": {
-      "family": "Zed Sans",
-      "color": "#636363",
-      "size": 14,
-      "padding": {
-        "right": 8
-      }
-    },
-    "channel_select": {
-      "header": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        },
-        "padding": {
-          "bottom": 4,
-          "left": 0
-        },
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#474747",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "hovered_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#474747",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "background": "#eaeaea",
-        "corner_radius": 6
-      },
-      "active_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "corner_radius": 0
-      },
-      "hovered_active_item": {
-        "name": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        },
-        "padding": 4,
-        "hash": {
-          "family": "Zed Sans",
-          "color": "#636363",
-          "size": 14,
-          "margin": {
-            "right": 8
-          }
-        },
-        "background": "#eaeaea",
-        "corner_radius": 6
-      },
-      "menu": {
-        "background": "#ffffff",
-        "corner_radius": 6,
-        "padding": 4,
-        "border": {
-          "color": "#d5d5d5",
-          "width": 1
-        },
-        "shadow": {
-          "blur": 16,
-          "color": "#0000001f",
-          "offset": [
-            0,
-            2
-          ]
-        }
-      }
-    },
-    "sign_in_prompt": {
-      "family": "Zed Sans",
-      "color": "#474747",
-      "underline": true,
-      "size": 14
-    },
-    "hovered_sign_in_prompt": {
-      "family": "Zed Sans",
-      "color": "#2b2b2b",
-      "underline": true,
-      "size": 14
-    },
-    "message": {
-      "body": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "timestamp": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 6
-      },
-      "sender": {
-        "family": "Zed Sans",
-        "color": "#2b2b2b",
-        "weight": "bold",
-        "size": 14,
-        "margin": {
-          "right": 8
-        }
-      }
-    },
-    "pending_message": {
-      "body": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "timestamp": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 6
-      },
-      "sender": {
-        "family": "Zed Sans",
-        "color": "#636363",
-        "weight": "bold",
-        "size": 14,
-        "margin": {
-          "right": 8
-        }
-      }
-    },
-    "input_editor": {
-      "background": "#ffffff",
-      "corner_radius": 6,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 8,
-        "right": 8,
-        "top": 7
-      }
-    }
-  },
-  "contacts_panel": {
-    "padding": {
-      "top": 12,
-      "bottom": 12
-    },
-    "user_query_editor": {
-      "background": "#ffffff",
-      "corner_radius": 6,
-      "text": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 8,
-        "right": 8,
-        "top": 4
-      },
-      "margin": {
-        "left": 12,
-        "right": 12
-      }
-    },
-    "user_query_editor_height": 32,
-    "add_contact_button": {
-      "margin": {
-        "left": 6,
-        "right": 12
-      },
-      "color": "#393939",
-      "button_width": 8,
-      "icon_width": 8
-    },
-    "row_height": 28,
-    "section_icon_size": 8,
-    "header_row": {
-      "family": "Zed Mono",
-      "color": "#474747",
-      "size": 14,
-      "margin": {
-        "top": 14
-      },
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "active": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14,
-        "background": "#d5d5d5"
-      }
-    },
-    "contact_row": {
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "active": {
-        "background": "#d5d5d5"
-      }
-    },
-    "tree_branch": {
-      "color": "#b8b8b8",
-      "width": 1,
-      "hover": {
-        "color": "#b8b8b8"
-      },
-      "active": {
-        "color": "#b8b8b8"
-      }
-    },
-    "contact_avatar": {
-      "corner_radius": 10,
-      "width": 18
-    },
-    "contact_username": {
-      "family": "Zed Mono",
-      "color": "#2b2b2b",
-      "size": 14,
-      "margin": {
-        "left": 8
-      }
-    },
-    "contact_button_spacing": 8,
-    "contact_button": {
-      "background": "#eaeaea",
-      "color": "#393939",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8,
-      "hover": {
-        "background": "#e3e3e3"
-      }
-    },
-    "disabled_contact_button": {
-      "background": "#eaeaea",
-      "color": "#9c9c9c",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8
-    },
-    "project_row": {
-      "guest_avatar_spacing": 4,
-      "height": 24,
-      "guest_avatar": {
-        "corner_radius": 8,
-        "width": 14
-      },
-      "name": {
-        "family": "Zed Mono",
-        "color": "#474747",
-        "size": 14,
-        "margin": {
-          "left": 8,
-          "right": 6
-        }
-      },
-      "guests": {
-        "margin": {
-          "left": 8,
-          "right": 8
-        }
-      },
-      "padding": {
-        "left": 12,
-        "right": 12
-      },
-      "background": "#f8f8f8",
-      "hover": {
-        "background": "#eaeaea"
-      },
-      "active": {
-        "background": "#e3e3e3"
-      }
-    }
-  },
-  "contact_finder": {
-    "background": "#f8f8f8",
-    "corner_radius": 8,
-    "padding": 8,
-    "item": {
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 4
-      },
-      "corner_radius": 8,
-      "text": {
-        "family": "Zed Sans",
-        "color": "#474747",
-        "size": 14
-      },
-      "highlight_text": {
-        "family": "Zed Sans",
-        "color": "#484bed",
-        "weight": "bold",
-        "size": 14
-      },
-      "active": {
-        "background": "#e3e3e3",
-        "text": {
-          "family": "Zed Sans",
-          "color": "#2b2b2b",
-          "size": 14
-        }
-      },
-      "hover": {
-        "background": "#eaeaea"
-      }
-    },
-    "border": {
-      "color": "#d5d5d5",
-      "width": 1
-    },
-    "empty": {
-      "text": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "padding": {
-        "bottom": 4,
-        "left": 12,
-        "right": 12,
-        "top": 8
-      }
-    },
-    "input_editor": {
-      "background": "#ffffff",
-      "corner_radius": 8,
-      "placeholder_text": {
-        "family": "Zed Sans",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#2b2b2b",
-        "size": 14
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "padding": {
-        "bottom": 7,
-        "left": 16,
-        "right": 16,
-        "top": 7
-      }
-    },
-    "shadow": {
-      "blur": 16,
-      "color": "#0000001f",
-      "offset": [
-        0,
-        2
-      ]
-    },
-    "row_height": 28,
-    "contact_avatar": {
-      "corner_radius": 10,
-      "width": 18
-    },
-    "contact_username": {
-      "padding": {
-        "left": 8
-      }
-    },
-    "contact_button": {
-      "background": "#eaeaea",
-      "color": "#393939",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8,
-      "hover": {
-        "background": "#e3e3e3"
-      }
-    },
-    "disabled_contact_button": {
-      "background": "#eaeaea",
-      "color": "#9c9c9c",
-      "icon_width": 8,
-      "button_width": 16,
-      "corner_radius": 8
-    }
-  },
-  "search": {
-    "match_background": "#fce9b7",
-    "tab_icon_spacing": 8,
-    "tab_icon_width": 14,
-    "option_button": {
-      "family": "Zed Mono",
-      "color": "#474747",
-      "size": 14,
-      "background": "#f1f1f1",
-      "corner_radius": 6,
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "margin": {
-        "right": 4
-      },
-      "padding": {
-        "bottom": 2,
-        "left": 10,
-        "right": 10,
-        "top": 2
-      },
-      "active": {
-        "family": "Zed Mono",
-        "color": "#000000",
-        "size": 14,
-        "background": "#ffffff",
-        "border": {
-          "color": "#e3e3e3",
-          "width": 1
-        }
-      },
-      "hover": {
-        "family": "Zed Mono",
-        "color": "#000000",
-        "size": 14,
-        "background": "#f8f8f8",
-        "border": {
-          "color": "#e3e3e3",
-          "width": 1
-        }
-      }
-    },
-    "editor": {
-      "background": "#ffffff",
-      "corner_radius": 8,
-      "min_width": 200,
-      "max_width": 500,
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#000000",
-        "size": 14
-      },
-      "border": {
-        "color": "#d5d5d5",
-        "width": 1
-      },
-      "margin": {
-        "right": 12
-      },
-      "padding": {
-        "top": 3,
-        "bottom": 3,
-        "left": 12,
-        "right": 8
-      }
-    },
-    "invalid_editor": {
-      "background": "#ffffff",
-      "corner_radius": 8,
-      "min_width": 200,
-      "max_width": 500,
-      "placeholder_text": {
-        "family": "Zed Mono",
-        "color": "#808080",
-        "size": 14
-      },
-      "selection": {
-        "cursor": "#2472f2",
-        "selection": "#2472f23d"
-      },
-      "text": {
-        "family": "Zed Mono",
-        "color": "#000000",
-        "size": 14
-      },
-      "border": {
-        "color": "#eb2d2d26",
-        "width": 1
-      },
-      "margin": {
-        "right": 12
-      },
-      "padding": {
-        "top": 3,
-        "bottom": 3,
-        "left": 12,
-        "right": 8
-      }
-    },
-    "match_index": {
-      "family": "Zed Mono",
-      "color": "#636363",
-      "size": 14,
-      "padding": 6
-    },
-    "option_button_group": {
-      "padding": {
-        "left": 12,
-        "right": 12
-      }
-    },
-    "results_status": {
-      "family": "Zed Mono",
-      "color": "#2b2b2b",
-      "size": 18
-    }
-  },
-  "breadcrumbs": {
-    "family": "Zed Sans",
-    "color": "#474747",
-    "size": 14,
-    "padding": {
-      "left": 6
-    }
-  },
-  "contact_notification": {
-    "header_avatar": {
-      "height": 12,
-      "width": 12,
-      "corner_radius": 6
-    },
-    "header_message": {
-      "family": "Zed Sans",
-      "color": "#2b2b2b",
-      "size": 12,
-      "margin": {
-        "left": 8,
-        "right": 8
-      }
-    },
-    "header_height": 18,
-    "body_message": {
-      "family": "Zed Sans",
-      "color": "#474747",
-      "size": 12,
-      "margin": {
-        "left": 20,
-        "top": 6,
-        "bottom": 6
-      }
-    },
-    "button": {
-      "family": "Zed Sans",
-      "color": "#2b2b2b",
-      "size": 12,
-      "background": "#f1f1f1",
-      "padding": 4,
-      "corner_radius": 6,
-      "margin": {
-        "left": 6
-      },
-      "hover": {
-        "background": "#e3e3e3"
-      }
-    },
-    "dismiss_button": {
-      "color": "#717171",
-      "icon_width": 8,
-      "icon_height": 8,
-      "button_width": 8,
-      "button_height": 8,
-      "hover": {
-        "color": "#393939"
-      }
-    }
-  }
-}

assets/themes/solarized-dark.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#586e755c",
+        "background": "#30525c",
         "text": {
           "family": "Zed Sans",
           "color": "#eee8d5",
@@ -31,7 +31,7 @@
         }
       },
       "hover": {
-        "background": "#586e753d"
+        "background": "#1b444f"
       }
     },
     "border": {
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#eee8d5",
-          "background": "#586e753d"
+          "background": "#1b444f"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#586e753d"
+            "background": "#1b444f"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#93a1a1",
           "hover": {
             "icon_color": "#eee8d5",
-            "background": "#586e753d"
+            "background": "#1b444f"
           },
           "active": {
             "icon_color": "#fdf6e3",
-            "background": "#586e755c"
+            "background": "#30525c"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#073642",
+      "background": "#1b444f",
       "padding": {
         "left": 80,
         "right": 6
@@ -436,15 +436,15 @@
         },
         "color": "#93a1a1",
         "hover": {
-          "background": "#586e753d",
+          "background": "#30525c",
           "color": "#93a1a1"
         },
         "active": {
-          "background": "#586e755c",
+          "background": "#446068",
           "color": "#fdf6e3"
         },
         "active_hover": {
-          "background": "#586e753d",
+          "background": "#30525c",
           "color": "#fdf6e3"
         }
       },
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#fdf6e3",
     "background": "#002b36",
-    "active_line_background": "#fdf6e312",
+    "active_line_background": "#073642",
     "code_actions_indicator": "#93a1a1",
     "diff_background_deleted": "#dc322f26",
     "diff_background_inserted": "#85990026",
-    "document_highlight_read_background": "#fdf6e31f",
-    "document_highlight_write_background": "#fdf6e33d",
+    "document_highlight_read_background": "#586e753d",
+    "document_highlight_write_background": "#586e757a",
     "error_color": "#dc322f",
     "gutter_background": "#002b36",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#fdf6e31f",
+    "highlighted_line_background": "#1b444f",
     "line_number": "#839496",
     "line_number_active": "#fdf6e3",
     "rename_fade": 0.6,
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#0736423d"
+        "background": "#022e39"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#0736425c"
+        "background": "#04313c"
       }
     },
     "diagnostic_header": {
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#fdf6e312",
+      "background": "#073642",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#93a1a1",
+        "color": "#eee8d5",
         "weight": "normal"
       },
       "constant": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#586e753d",
+        "background": "#1b444f",
         "text": {
           "family": "Zed Mono",
           "color": "#eee8d5",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#586e755c",
+        "background": "#30525c",
         "text": {
           "family": "Zed Mono",
           "color": "#eee8d5",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#586e753d",
+        "background": "#1b444f",
         "text": {
           "family": "Zed Mono",
           "color": "#fdf6e3",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#0736425c",
+      "background": "#04313c",
       "text": {
         "family": "Zed Mono",
         "color": "#eee8d5",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#586e753d",
+        "background": "#1b444f",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#586e753d",
+        "background": "#1b444f",
         "corner_radius": 6
       },
       "menu": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#eee8d5",
         "size": 14,
-        "background": "#586e755c"
+        "background": "#446068"
       }
     },
     "contact_row": {
@@ -1326,7 +1326,7 @@
         "right": 12
       },
       "active": {
-        "background": "#586e755c"
+        "background": "#446068"
       }
     },
     "tree_branch": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#073642",
+      "background": "#1b444f",
       "color": "#eee8d5",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#586e753d"
+        "background": "#30525c"
       }
     },
     "disabled_contact_button": {
-      "background": "#073642",
+      "background": "#1b444f",
       "color": "#93a1a1",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#073642",
       "hover": {
-        "background": "#586e753d"
+        "background": "#1b444f"
       },
       "active": {
-        "background": "#586e755c"
+        "background": "#30525c"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#586e755c",
+        "background": "#30525c",
         "text": {
           "family": "Zed Sans",
           "color": "#eee8d5",
@@ -1436,7 +1436,7 @@
         }
       },
       "hover": {
-        "background": "#586e753d"
+        "background": "#1b444f"
       }
     },
     "border": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#073642",
+      "background": "#1b444f",
       "color": "#eee8d5",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#586e753d"
+        "background": "#30525c"
       }
     },
     "disabled_contact_button": {
-      "background": "#073642",
+      "background": "#1b444f",
       "color": "#93a1a1",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,14 +1521,14 @@
     }
   },
   "search": {
-    "match_background": "#6c71c47a",
+    "match_background": "#1b1f6b",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#93a1a1",
       "size": 14,
-      "background": "#073642",
+      "background": "#1b444f",
       "corner_radius": 6,
       "border": {
         "color": "#073642",
@@ -1547,7 +1547,7 @@
         "family": "Zed Mono",
         "color": "#fdf6e3",
         "size": 14,
-        "background": "#586e757a",
+        "background": "#446068",
         "border": {
           "color": "#657b83",
           "width": 1
@@ -1557,7 +1557,7 @@
         "family": "Zed Mono",
         "color": "#fdf6e3",
         "size": 14,
-        "background": "#586e753d",
+        "background": "#30525c",
         "border": {
           "color": "#657b83",
           "width": 1
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#0736423d"
+        "background": "#022e39"
       }
     },
     "dismiss_button": {

assets/themes/solarized-light.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#93a1a12e",
+        "background": "#c1c5bb",
         "text": {
           "family": "Zed Sans",
           "color": "#073642",
@@ -31,11 +31,11 @@
         }
       },
       "hover": {
-        "background": "#93a1a11f"
+        "background": "#d7d6c8"
       }
     },
     "border": {
-      "color": "#fdf6e3",
+      "color": "#93a1a1",
       "width": 1
     },
     "empty": {
@@ -69,7 +69,7 @@
         "size": 14
       },
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "padding": {
@@ -117,7 +117,7 @@
         "size": 14
       },
       "border": {
-        "color": "#fdf6e3",
+        "color": "#93a1a1",
         "width": 1,
         "left": true,
         "bottom": true,
@@ -143,7 +143,7 @@
         "size": 14
       },
       "border": {
-        "color": "#fdf6e3",
+        "color": "#93a1a1",
         "width": 1,
         "left": true,
         "bottom": false,
@@ -162,13 +162,13 @@
       "cursor": "Arrow"
     },
     "sidebar_resize_handle": {
-      "background": "#fdf6e3",
+      "background": "#93a1a1",
       "padding": {
         "left": 1
       }
     },
     "pane_divider": {
-      "color": "#eee8d5",
+      "color": "#93a1a1",
       "width": 1
     },
     "status_bar": {
@@ -181,7 +181,7 @@
         "right": 6
       },
       "border": {
-        "color": "#fdf6e3",
+        "color": "#93a1a1",
         "width": 1,
         "top": true,
         "overlay": true
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#073642",
-          "background": "#93a1a11f"
+          "background": "#d7d6c8"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#93a1a11f"
+            "background": "#d7d6c8"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#586e75",
           "hover": {
             "icon_color": "#073642",
-            "background": "#93a1a11f"
+            "background": "#d7d6c8"
           },
           "active": {
             "icon_color": "#002b36",
-            "background": "#93a1a12e"
+            "background": "#c1c5bb"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "padding": {
         "left": 80,
         "right": 6
@@ -393,14 +393,14 @@
         "width": 12
       },
       "border": {
-        "color": "#fdf6e3",
+        "color": "#93a1a1",
         "width": 1,
         "bottom": true,
         "overlay": true
       },
       "sign_in_prompt": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1
         },
         "corner_radius": 6,
@@ -436,15 +436,15 @@
         },
         "color": "#586e75",
         "hover": {
-          "background": "#93a1a11f",
+          "background": "#c1c5bb",
           "color": "#586e75"
         },
         "active": {
-          "background": "#93a1a12e",
+          "background": "#aab3ae",
           "color": "#002b36"
         },
         "active_hover": {
-          "background": "#93a1a11f",
+          "background": "#c1c5bb",
           "color": "#002b36"
         }
       },
@@ -468,7 +468,7 @@
       "height": 34,
       "background": "#fdf6e3",
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1,
         "bottom": true
       },
@@ -502,7 +502,7 @@
       "corner_radius": 6,
       "padding": 12,
       "border": {
-        "color": "#fdf6e3",
+        "color": "#93a1a1",
         "width": 1
       },
       "shadow": {
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#002b36",
     "background": "#fdf6e3",
-    "active_line_background": "#002b3612",
+    "active_line_background": "#eee8d5",
     "code_actions_indicator": "#586e75",
     "diff_background_deleted": "#dc322f26",
     "diff_background_inserted": "#85990026",
-    "document_highlight_read_background": "#002b360f",
-    "document_highlight_write_background": "#002b361f",
+    "document_highlight_read_background": "#93a1a11f",
+    "document_highlight_write_background": "#93a1a13d",
     "error_color": "#dc322f",
     "gutter_background": "#fdf6e3",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#002b361f",
+    "highlighted_line_background": "#d7d6c8",
     "line_number": "#657b83",
     "line_number_active": "#002b36",
     "rename_fade": 0.6,
@@ -578,7 +578,7 @@
       "corner_radius": 8,
       "padding": 4,
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "item": {
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#eee8d51f"
+        "background": "#f9f3e0"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#eee8d52e"
+        "background": "#f6efdc"
       }
     },
     "diagnostic_header": {
@@ -624,7 +624,7 @@
       "icon_width_factor": 1.5,
       "text_scale_factor": 0.857,
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1,
         "bottom": true,
         "top": true
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#002b3612",
+      "background": "#eee8d5",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -672,7 +672,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -695,7 +695,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -718,7 +718,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -741,7 +741,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -764,7 +764,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -787,7 +787,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -810,7 +810,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -833,7 +833,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1,
           "top": true
         }
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#586e75",
+        "color": "#073642",
         "weight": "normal"
       },
       "constant": {
@@ -959,7 +959,7 @@
       "corner_radius": 4,
       "background": "#fdf6e3",
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "padding": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#93a1a11f",
+        "background": "#d7d6c8",
         "text": {
           "family": "Zed Mono",
           "color": "#073642",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#93a1a12e",
+        "background": "#c1c5bb",
         "text": {
           "family": "Zed Mono",
           "color": "#073642",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#93a1a11f",
+        "background": "#d7d6c8",
         "text": {
           "family": "Zed Mono",
           "color": "#002b36",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#eee8d52e",
+      "background": "#f6efdc",
       "text": {
         "family": "Zed Mono",
         "color": "#073642",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#93a1a11f",
+        "background": "#d7d6c8",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#93a1a11f",
+        "background": "#d7d6c8",
         "corner_radius": 6
       },
       "menu": {
@@ -1151,7 +1151,7 @@
         "corner_radius": 6,
         "padding": 4,
         "border": {
-          "color": "#fdf6e3",
+          "color": "#93a1a1",
           "width": 1
         },
         "shadow": {
@@ -1242,7 +1242,7 @@
         "selection": "#268bd23d"
       },
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "padding": {
@@ -1276,7 +1276,7 @@
         "selection": "#268bd23d"
       },
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "padding": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#073642",
         "size": 14,
-        "background": "#93a1a12e"
+        "background": "#aab3ae"
       }
     },
     "contact_row": {
@@ -1326,17 +1326,17 @@
         "right": 12
       },
       "active": {
-        "background": "#93a1a12e"
+        "background": "#aab3ae"
       }
     },
     "tree_branch": {
-      "color": "#839496",
+      "color": "#657b83",
       "width": 1,
       "hover": {
-        "color": "#839496"
+        "color": "#657b83"
       },
       "active": {
-        "color": "#839496"
+        "color": "#657b83"
       }
     },
     "contact_avatar": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "color": "#073642",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#93a1a11f"
+        "background": "#c1c5bb"
       }
     },
     "disabled_contact_button": {
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "color": "#586e75",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#eee8d5",
       "hover": {
-        "background": "#93a1a11f"
+        "background": "#d7d6c8"
       },
       "active": {
-        "background": "#93a1a12e"
+        "background": "#c1c5bb"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#93a1a12e",
+        "background": "#c1c5bb",
         "text": {
           "family": "Zed Sans",
           "color": "#073642",
@@ -1436,11 +1436,11 @@
         }
       },
       "hover": {
-        "background": "#93a1a11f"
+        "background": "#d7d6c8"
       }
     },
     "border": {
-      "color": "#fdf6e3",
+      "color": "#93a1a1",
       "width": 1
     },
     "empty": {
@@ -1474,7 +1474,7 @@
         "size": 14
       },
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "padding": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "color": "#073642",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#93a1a11f"
+        "background": "#c1c5bb"
       }
     },
     "disabled_contact_button": {
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "color": "#586e75",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,17 +1521,17 @@
     }
   },
   "search": {
-    "match_background": "#6c71c43d",
+    "match_background": "#bcc0f6",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#586e75",
       "size": 14,
-      "background": "#eee8d5",
+      "background": "#d7d6c8",
       "corner_radius": 6,
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "margin": {
@@ -1547,9 +1547,9 @@
         "family": "Zed Mono",
         "color": "#002b36",
         "size": 14,
-        "background": "#93a1a13d",
+        "background": "#aab3ae",
         "border": {
-          "color": "#839496",
+          "color": "#657b83",
           "width": 1
         }
       },
@@ -1557,9 +1557,9 @@
         "family": "Zed Mono",
         "color": "#002b36",
         "size": 14,
-        "background": "#93a1a11f",
+        "background": "#c1c5bb",
         "border": {
-          "color": "#839496",
+          "color": "#657b83",
           "width": 1
         }
       }
@@ -1584,7 +1584,7 @@
         "size": 14
       },
       "border": {
-        "color": "#eee8d5",
+        "color": "#93a1a1",
         "width": 1
       },
       "margin": {
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#eee8d51f"
+        "background": "#f9f3e0"
       }
     },
     "dismiss_button": {

assets/themes/sulphurpool-dark.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#5e66875c",
+        "background": "#444c6f",
         "text": {
           "family": "Zed Sans",
           "color": "#dfe2f1",
@@ -31,7 +31,7 @@
         }
       },
       "hover": {
-        "background": "#5e66873d"
+        "background": "#363f62"
       }
     },
     "border": {
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#dfe2f1",
-          "background": "#5e66873d"
+          "background": "#363f62"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#5e66873d"
+            "background": "#363f62"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#979db4",
           "hover": {
             "icon_color": "#dfe2f1",
-            "background": "#5e66873d"
+            "background": "#363f62"
           },
           "active": {
             "icon_color": "#f5f7ff",
-            "background": "#5e66875c"
+            "background": "#444c6f"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#293256",
+      "background": "#363f62",
       "padding": {
         "left": 80,
         "right": 6
@@ -436,15 +436,15 @@
         },
         "color": "#979db4",
         "hover": {
-          "background": "#5e66873d",
+          "background": "#444c6f",
           "color": "#979db4"
         },
         "active": {
-          "background": "#5e66875c",
+          "background": "#51597b",
           "color": "#f5f7ff"
         },
         "active_hover": {
-          "background": "#5e66873d",
+          "background": "#444c6f",
           "color": "#f5f7ff"
         }
       },
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#f5f7ff",
     "background": "#202746",
-    "active_line_background": "#f5f7ff12",
+    "active_line_background": "#293256",
     "code_actions_indicator": "#979db4",
     "diff_background_deleted": "#c9492226",
     "diff_background_inserted": "#ac973926",
-    "document_highlight_read_background": "#f5f7ff1f",
-    "document_highlight_write_background": "#f5f7ff3d",
+    "document_highlight_read_background": "#5e66873d",
+    "document_highlight_write_background": "#5e66877a",
     "error_color": "#c94922",
     "gutter_background": "#202746",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#f5f7ff1f",
+    "highlighted_line_background": "#363f62",
     "line_number": "#898ea4",
     "line_number_active": "#f5f7ff",
     "rename_fade": 0.6,
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#2932563d"
+        "background": "#222a4a"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#2932565c"
+        "background": "#252d4e"
       }
     },
     "diagnostic_header": {
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#f5f7ff12",
+      "background": "#293256",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#979db4",
+        "color": "#dfe2f1",
         "weight": "normal"
       },
       "constant": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#5e66873d",
+        "background": "#363f62",
         "text": {
           "family": "Zed Mono",
           "color": "#dfe2f1",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#5e66875c",
+        "background": "#444c6f",
         "text": {
           "family": "Zed Mono",
           "color": "#dfe2f1",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#5e66873d",
+        "background": "#363f62",
         "text": {
           "family": "Zed Mono",
           "color": "#f5f7ff",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#2932565c",
+      "background": "#252d4e",
       "text": {
         "family": "Zed Mono",
         "color": "#dfe2f1",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#5e66873d",
+        "background": "#363f62",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#5e66873d",
+        "background": "#363f62",
         "corner_radius": 6
       },
       "menu": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#dfe2f1",
         "size": 14,
-        "background": "#5e66875c"
+        "background": "#51597b"
       }
     },
     "contact_row": {
@@ -1326,7 +1326,7 @@
         "right": 12
       },
       "active": {
-        "background": "#5e66875c"
+        "background": "#51597b"
       }
     },
     "tree_branch": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#293256",
+      "background": "#363f62",
       "color": "#dfe2f1",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#5e66873d"
+        "background": "#444c6f"
       }
     },
     "disabled_contact_button": {
-      "background": "#293256",
+      "background": "#363f62",
       "color": "#979db4",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#293256",
       "hover": {
-        "background": "#5e66873d"
+        "background": "#363f62"
       },
       "active": {
-        "background": "#5e66875c"
+        "background": "#444c6f"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#5e66875c",
+        "background": "#444c6f",
         "text": {
           "family": "Zed Sans",
           "color": "#dfe2f1",
@@ -1436,7 +1436,7 @@
         }
       },
       "hover": {
-        "background": "#5e66873d"
+        "background": "#363f62"
       }
     },
     "border": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#293256",
+      "background": "#363f62",
       "color": "#dfe2f1",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#5e66873d"
+        "background": "#444c6f"
       }
     },
     "disabled_contact_button": {
-      "background": "#293256",
+      "background": "#363f62",
       "color": "#979db4",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,14 +1521,14 @@
     }
   },
   "search": {
-    "match_background": "#6679cc7a",
+    "match_background": "#1a2a6d",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#979db4",
       "size": 14,
-      "background": "#293256",
+      "background": "#363f62",
       "corner_radius": 6,
       "border": {
         "color": "#293256",
@@ -1547,7 +1547,7 @@
         "family": "Zed Mono",
         "color": "#f5f7ff",
         "size": 14,
-        "background": "#5e66877a",
+        "background": "#51597b",
         "border": {
           "color": "#6b7394",
           "width": 1
@@ -1557,7 +1557,7 @@
         "family": "Zed Mono",
         "color": "#f5f7ff",
         "size": 14,
-        "background": "#5e66873d",
+        "background": "#444c6f",
         "border": {
           "color": "#6b7394",
           "width": 1
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#2932563d"
+        "background": "#222a4a"
       }
     },
     "dismiss_button": {

assets/themes/sulphurpool-light.json 🔗

@@ -23,7 +23,7 @@
         "size": 14
       },
       "active": {
-        "background": "#979db42e",
+        "background": "#bbc0d3",
         "text": {
           "family": "Zed Sans",
           "color": "#293256",
@@ -31,11 +31,11 @@
         }
       },
       "hover": {
-        "background": "#979db41f"
+        "background": "#cdd1e2"
       }
     },
     "border": {
-      "color": "#f5f7ff",
+      "color": "#979db4",
       "width": 1
     },
     "empty": {
@@ -69,7 +69,7 @@
         "size": 14
       },
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "padding": {
@@ -117,7 +117,7 @@
         "size": 14
       },
       "border": {
-        "color": "#f5f7ff",
+        "color": "#979db4",
         "width": 1,
         "left": true,
         "bottom": true,
@@ -143,7 +143,7 @@
         "size": 14
       },
       "border": {
-        "color": "#f5f7ff",
+        "color": "#979db4",
         "width": 1,
         "left": true,
         "bottom": false,
@@ -162,13 +162,13 @@
       "cursor": "Arrow"
     },
     "sidebar_resize_handle": {
-      "background": "#f5f7ff",
+      "background": "#979db4",
       "padding": {
         "left": 1
       }
     },
     "pane_divider": {
-      "color": "#dfe2f1",
+      "color": "#979db4",
       "width": 1
     },
     "status_bar": {
@@ -181,7 +181,7 @@
         "right": 6
       },
       "border": {
-        "color": "#f5f7ff",
+        "color": "#979db4",
         "width": 1,
         "top": true,
         "overlay": true
@@ -225,7 +225,7 @@
             "size": 14
           },
           "icon_color": "#293256",
-          "background": "#979db41f"
+          "background": "#cdd1e2"
         }
       },
       "diagnostic_message": {
@@ -298,7 +298,7 @@
               "left": 7,
               "right": 7
             },
-            "background": "#979db41f"
+            "background": "#cdd1e2"
           },
           "container_warning": {
             "corner_radius": 6,
@@ -345,11 +345,11 @@
           "icon_color": "#5e6687",
           "hover": {
             "icon_color": "#293256",
-            "background": "#979db41f"
+            "background": "#cdd1e2"
           },
           "active": {
             "icon_color": "#202746",
-            "background": "#979db42e"
+            "background": "#bbc0d3"
           }
         },
         "badge": {
@@ -371,7 +371,7 @@
       "avatar_width": 18,
       "avatar_margin": 8,
       "height": 33,
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "padding": {
         "left": 80,
         "right": 6
@@ -393,14 +393,14 @@
         "width": 12
       },
       "border": {
-        "color": "#f5f7ff",
+        "color": "#979db4",
         "width": 1,
         "bottom": true,
         "overlay": true
       },
       "sign_in_prompt": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1
         },
         "corner_radius": 6,
@@ -436,15 +436,15 @@
         },
         "color": "#5e6687",
         "hover": {
-          "background": "#979db41f",
+          "background": "#bbc0d3",
           "color": "#5e6687"
         },
         "active": {
-          "background": "#979db42e",
+          "background": "#a9aec3",
           "color": "#202746"
         },
         "active_hover": {
-          "background": "#979db41f",
+          "background": "#bbc0d3",
           "color": "#202746"
         }
       },
@@ -468,7 +468,7 @@
       "height": 34,
       "background": "#f5f7ff",
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1,
         "bottom": true
       },
@@ -502,7 +502,7 @@
       "corner_radius": 6,
       "padding": 12,
       "border": {
-        "color": "#f5f7ff",
+        "color": "#979db4",
         "width": 1
       },
       "shadow": {
@@ -525,16 +525,16 @@
   "editor": {
     "text_color": "#202746",
     "background": "#f5f7ff",
-    "active_line_background": "#20274612",
+    "active_line_background": "#dfe2f1",
     "code_actions_indicator": "#5e6687",
     "diff_background_deleted": "#c9492226",
     "diff_background_inserted": "#ac973926",
-    "document_highlight_read_background": "#2027460f",
-    "document_highlight_write_background": "#2027461f",
+    "document_highlight_read_background": "#979db41f",
+    "document_highlight_write_background": "#979db43d",
     "error_color": "#c94922",
     "gutter_background": "#f5f7ff",
     "gutter_padding_factor": 3.5,
-    "highlighted_line_background": "#2027461f",
+    "highlighted_line_background": "#cdd1e2",
     "line_number": "#6b7394",
     "line_number_active": "#202746",
     "rename_fade": 0.6,
@@ -578,7 +578,7 @@
       "corner_radius": 8,
       "padding": 4,
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "item": {
@@ -598,7 +598,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#dfe2f11f"
+        "background": "#f0f2fc"
       },
       "margin": {
         "left": -14
@@ -616,7 +616,7 @@
           "right": 6,
           "top": 2
         },
-        "background": "#dfe2f12e"
+        "background": "#eaedf8"
       }
     },
     "diagnostic_header": {
@@ -624,7 +624,7 @@
       "icon_width_factor": 1.5,
       "text_scale_factor": 0.857,
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1,
         "bottom": true,
         "top": true
@@ -652,7 +652,7 @@
       }
     },
     "diagnostic_path_header": {
-      "background": "#20274612",
+      "background": "#dfe2f1",
       "text_scale_factor": 0.857,
       "filename": {
         "family": "Zed Mono",
@@ -672,7 +672,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -695,7 +695,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -718,7 +718,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -741,7 +741,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -764,7 +764,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -787,7 +787,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -810,7 +810,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -833,7 +833,7 @@
       "text_scale_factor": 0.857,
       "header": {
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1,
           "top": true
         }
@@ -862,7 +862,7 @@
         "weight": "normal"
       },
       "punctuation": {
-        "color": "#5e6687",
+        "color": "#293256",
         "weight": "normal"
       },
       "constant": {
@@ -959,7 +959,7 @@
       "corner_radius": 4,
       "background": "#f5f7ff",
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "padding": {
@@ -999,7 +999,7 @@
         "size": 14
       },
       "hover": {
-        "background": "#979db41f",
+        "background": "#cdd1e2",
         "text": {
           "family": "Zed Mono",
           "color": "#293256",
@@ -1007,7 +1007,7 @@
         }
       },
       "active": {
-        "background": "#979db42e",
+        "background": "#bbc0d3",
         "text": {
           "family": "Zed Mono",
           "color": "#293256",
@@ -1015,7 +1015,7 @@
         }
       },
       "active_hover": {
-        "background": "#979db41f",
+        "background": "#cdd1e2",
         "text": {
           "family": "Zed Mono",
           "color": "#202746",
@@ -1024,7 +1024,7 @@
       }
     },
     "filename_editor": {
-      "background": "#dfe2f12e",
+      "background": "#eaedf8",
       "text": {
         "family": "Zed Mono",
         "color": "#293256",
@@ -1108,7 +1108,7 @@
             "right": 8
           }
         },
-        "background": "#979db41f",
+        "background": "#cdd1e2",
         "corner_radius": 6
       },
       "active_item": {
@@ -1143,7 +1143,7 @@
             "right": 8
           }
         },
-        "background": "#979db41f",
+        "background": "#cdd1e2",
         "corner_radius": 6
       },
       "menu": {
@@ -1151,7 +1151,7 @@
         "corner_radius": 6,
         "padding": 4,
         "border": {
-          "color": "#f5f7ff",
+          "color": "#979db4",
           "width": 1
         },
         "shadow": {
@@ -1242,7 +1242,7 @@
         "selection": "#3d8fd13d"
       },
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "padding": {
@@ -1276,7 +1276,7 @@
         "selection": "#3d8fd13d"
       },
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "padding": {
@@ -1317,7 +1317,7 @@
         "family": "Zed Mono",
         "color": "#293256",
         "size": 14,
-        "background": "#979db42e"
+        "background": "#a9aec3"
       }
     },
     "contact_row": {
@@ -1326,17 +1326,17 @@
         "right": 12
       },
       "active": {
-        "background": "#979db42e"
+        "background": "#a9aec3"
       }
     },
     "tree_branch": {
-      "color": "#898ea4",
+      "color": "#6b7394",
       "width": 1,
       "hover": {
-        "color": "#898ea4"
+        "color": "#6b7394"
       },
       "active": {
-        "color": "#898ea4"
+        "color": "#6b7394"
       }
     },
     "contact_avatar": {
@@ -1353,17 +1353,17 @@
     },
     "contact_button_spacing": 8,
     "contact_button": {
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "color": "#293256",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#979db41f"
+        "background": "#bbc0d3"
       }
     },
     "disabled_contact_button": {
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "color": "#5e6687",
       "icon_width": 8,
       "button_width": 16,
@@ -1397,10 +1397,10 @@
       },
       "background": "#dfe2f1",
       "hover": {
-        "background": "#979db41f"
+        "background": "#cdd1e2"
       },
       "active": {
-        "background": "#979db42e"
+        "background": "#bbc0d3"
       }
     }
   },
@@ -1428,7 +1428,7 @@
         "size": 14
       },
       "active": {
-        "background": "#979db42e",
+        "background": "#bbc0d3",
         "text": {
           "family": "Zed Sans",
           "color": "#293256",
@@ -1436,11 +1436,11 @@
         }
       },
       "hover": {
-        "background": "#979db41f"
+        "background": "#cdd1e2"
       }
     },
     "border": {
-      "color": "#f5f7ff",
+      "color": "#979db4",
       "width": 1
     },
     "empty": {
@@ -1474,7 +1474,7 @@
         "size": 14
       },
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "padding": {
@@ -1503,17 +1503,17 @@
       }
     },
     "contact_button": {
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "color": "#293256",
       "icon_width": 8,
       "button_width": 16,
       "corner_radius": 8,
       "hover": {
-        "background": "#979db41f"
+        "background": "#bbc0d3"
       }
     },
     "disabled_contact_button": {
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "color": "#5e6687",
       "icon_width": 8,
       "button_width": 16,
@@ -1521,17 +1521,17 @@
     }
   },
   "search": {
-    "match_background": "#6679cc3d",
+    "match_background": "#bcc6f7",
     "tab_icon_spacing": 8,
     "tab_icon_width": 14,
     "option_button": {
       "family": "Zed Mono",
       "color": "#5e6687",
       "size": 14,
-      "background": "#dfe2f1",
+      "background": "#cdd1e2",
       "corner_radius": 6,
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "margin": {
@@ -1547,9 +1547,9 @@
         "family": "Zed Mono",
         "color": "#202746",
         "size": 14,
-        "background": "#979db43d",
+        "background": "#a9aec3",
         "border": {
-          "color": "#898ea4",
+          "color": "#6b7394",
           "width": 1
         }
       },
@@ -1557,9 +1557,9 @@
         "family": "Zed Mono",
         "color": "#202746",
         "size": 14,
-        "background": "#979db41f",
+        "background": "#bbc0d3",
         "border": {
-          "color": "#898ea4",
+          "color": "#6b7394",
           "width": 1
         }
       }
@@ -1584,7 +1584,7 @@
         "size": 14
       },
       "border": {
-        "color": "#dfe2f1",
+        "color": "#979db4",
         "width": 1
       },
       "margin": {
@@ -1693,7 +1693,7 @@
         "left": 6
       },
       "hover": {
-        "background": "#dfe2f11f"
+        "background": "#f0f2fc"
       }
     },
     "dismiss_button": {

crates/breadcrumbs/src/breadcrumbs.rs 🔗

@@ -37,11 +37,9 @@ impl Breadcrumbs {
         cx: &AppContext,
     ) -> Option<(ModelHandle<Buffer>, Vec<OutlineItem<Anchor>>)> {
         let editor = self.editor.as_ref()?.read(cx);
-        let cursor = editor.newest_anchor_selection().head();
+        let cursor = editor.selections.newest_anchor().head();
         let multibuffer = &editor.buffer().read(cx);
-        let (buffer_id, symbols) = multibuffer
-            .read(cx)
-            .symbols_containing(cursor, Some(theme))?;
+        let (buffer_id, symbols) = multibuffer.symbols_containing(cursor, Some(theme), cx)?;
         let buffer = multibuffer.buffer(buffer_id)?;
         Some((buffer, symbols))
     }

crates/collab/Cargo.toml 🔗

@@ -24,11 +24,9 @@ axum = { version = "0.5", features = ["json", "headers", "ws"] }
 base64 = "0.13"
 clap = { version = "3.1", features = ["derive"], optional = true }
 envy = "0.4.2"
-env_logger = "0.8"
 futures = "0.3"
 lazy_static = "1.4"
 lipsum = { version = "0.8", optional = true }
-log = { version = "0.4.16", features = ["kv_unstable_serde"] }
 opentelemetry = { version = "0.17", features = ["rt-tokio"] }
 opentelemetry-otlp = { version = "0.10", features = ["tls-roots"] }
 parking_lot = "0.11.1"
@@ -44,9 +42,10 @@ tokio-tungstenite = "0.17"
 tonic = "0.6"
 tower = "0.4"
 toml = "0.5.8"
-tracing = "0.1"
+tracing = "0.1.34"
+tracing-log = "0.1.3"
 tracing-opentelemetry = "0.17"
-tracing-subscriber = "0.3"
+tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
 
 [dependencies.sqlx]
 version = "0.5.2"
@@ -59,6 +58,7 @@ rpc = { path = "../rpc", features = ["test-support"] }
 client = { path = "../client", features = ["test-support"] }
 editor = { path = "../editor", features = ["test-support"] }
 language = { path = "../language", features = ["test-support"] }
+log = { version = "0.4.16", features = ["kv_unstable_serde"] }
 lsp = { path = "../lsp", features = ["test-support"] }
 project = { path = "../project", features = ["test-support"] }
 settings = { path = "../settings", features = ["test-support"] }

crates/collab/k8s/manifest.template.yml 🔗

@@ -83,8 +83,6 @@ spec:
                   key: token
             - name: RUST_LOG
               value: ${RUST_LOG}
-            - name: TRACE_LEVEL
-              value: ${TRACE_LEVEL}
             - name: HONEYCOMB_DATASET
               value: "collab"
             - name: HONEYCOMB_API_KEY

crates/collab/src/auth.rs 🔗

@@ -2,7 +2,7 @@ use std::sync::Arc;
 
 use super::db::{self, UserId};
 use crate::{AppState, Error};
-use anyhow::{Context, Result};
+use anyhow::{anyhow, Context, Result};
 use axum::{
     http::{self, Request, StatusCode},
     middleware::Next,
@@ -51,7 +51,12 @@ pub async fn validate_header<B>(mut req: Request<B>, next: Next<B>) -> impl Into
     }
 
     if credentials_valid {
-        req.extensions_mut().insert(user_id);
+        let user = state
+            .db
+            .get_user_by_id(user_id)
+            .await?
+            .ok_or_else(|| anyhow!("user {} not found", user_id))?;
+        req.extensions_mut().insert(user);
         Ok::<_, Error>(next.run(req).await)
     } else {
         Err(Error::Http(

crates/collab/src/main.rs 🔗

@@ -11,7 +11,9 @@ use std::{
     net::{SocketAddr, TcpListener},
     sync::Arc,
 };
-use tracing::metadata::LevelFilter;
+use tracing_log::LogTracer;
+use tracing_subscriber::filter::EnvFilter;
+use util::ResultExt;
 
 #[derive(Default, Deserialize)]
 pub struct Config {
@@ -20,7 +22,7 @@ pub struct Config {
     pub api_token: String,
     pub honeycomb_api_key: Option<String>,
     pub honeycomb_dataset: Option<String>,
-    pub trace_level: Option<String>,
+    pub rust_log: Option<String>,
 }
 
 pub struct AppState {
@@ -41,10 +43,8 @@ impl AppState {
 
 #[tokio::main]
 async fn main() -> Result<()> {
-    env_logger::init();
-
     if let Err(error) = env::load_dotenv() {
-        log::error!(
+        eprintln!(
             "error loading .env.toml (this is expected in production): {}",
             error
         );
@@ -119,42 +119,44 @@ pub fn init_tracing(config: &Config) -> Option<()> {
     use std::str::FromStr;
     use tracing_opentelemetry::OpenTelemetryLayer;
     use tracing_subscriber::layer::SubscriberExt;
+    let rust_log = config.rust_log.clone()?;
+
+    LogTracer::init().log_err()?;
 
-    let (honeycomb_api_key, honeycomb_dataset) = config
+    let open_telemetry_layer = config
         .honeycomb_api_key
         .clone()
-        .zip(config.honeycomb_dataset.clone())?;
-
-    let mut metadata = tonic::metadata::MetadataMap::new();
-    metadata.insert("x-honeycomb-team", honeycomb_api_key.parse().unwrap());
-    let tracer = opentelemetry_otlp::new_pipeline()
-        .tracing()
-        .with_exporter(
-            opentelemetry_otlp::new_exporter()
-                .tonic()
-                .with_endpoint("https://api.honeycomb.io")
-                .with_metadata(metadata),
-        )
-        .with_trace_config(opentelemetry::sdk::trace::config().with_resource(
-            opentelemetry::sdk::Resource::new(vec![KeyValue::new(
-                "service.name",
-                honeycomb_dataset,
-            )]),
-        ))
-        .install_batch(opentelemetry::runtime::Tokio)
-        .expect("failed to initialize tracing");
+        .zip(config.honeycomb_dataset.clone())
+        .map(|(honeycomb_api_key, honeycomb_dataset)| {
+            let mut metadata = tonic::metadata::MetadataMap::new();
+            metadata.insert("x-honeycomb-team", honeycomb_api_key.parse().unwrap());
+            let tracer = opentelemetry_otlp::new_pipeline()
+                .tracing()
+                .with_exporter(
+                    opentelemetry_otlp::new_exporter()
+                        .tonic()
+                        .with_endpoint("https://api.honeycomb.io")
+                        .with_metadata(metadata),
+                )
+                .with_trace_config(opentelemetry::sdk::trace::config().with_resource(
+                    opentelemetry::sdk::Resource::new(vec![KeyValue::new(
+                        "service.name",
+                        honeycomb_dataset,
+                    )]),
+                ))
+                .install_batch(opentelemetry::runtime::Tokio)
+                .expect("failed to initialize tracing");
+
+            OpenTelemetryLayer::new(tracer)
+        });
 
     let subscriber = tracing_subscriber::Registry::default()
-        .with(OpenTelemetryLayer::new(tracer))
-        .with(tracing_subscriber::fmt::layer())
+        .with(open_telemetry_layer)
         .with(
-            config
-                .trace_level
-                .as_ref()
-                .map_or(LevelFilter::INFO, |level| {
-                    LevelFilter::from_str(level).unwrap()
-                }),
-        );
+            tracing_subscriber::fmt::layer()
+                .event_format(tracing_subscriber::fmt::format().pretty()),
+        )
+        .with(EnvFilter::from_str(rust_log.as_str()).log_err()?);
 
     tracing::subscriber::set_global_default(subscriber).unwrap();
 

crates/collab/src/rpc.rs 🔗

@@ -2,7 +2,7 @@ mod store;
 
 use crate::{
     auth,
-    db::{self, ChannelId, MessageId, UserId},
+    db::{self, ChannelId, MessageId, User, UserId},
     AppState, Result,
 };
 use anyhow::anyhow;
@@ -49,7 +49,7 @@ use tokio::{
     time::Sleep,
 };
 use tower::ServiceBuilder;
-use tracing::{info_span, Instrument};
+use tracing::{info_span, instrument, Instrument};
 
 type MessageHandler =
     Box<dyn Send + Sync + Fn(Arc<Server>, Box<dyn AnyTypedEnvelope>) -> BoxFuture<'static, ()>>;
@@ -248,12 +248,14 @@ impl Server {
         self: &Arc<Self>,
         connection: Connection,
         address: String,
-        user_id: UserId,
+        user: User,
         mut send_connection_id: Option<mpsc::Sender<ConnectionId>>,
         executor: E,
     ) -> impl Future<Output = Result<()>> {
         let mut this = self.clone();
-        let span = info_span!("handle connection", %user_id, %address);
+        let user_id = user.id;
+        let login = user.github_login;
+        let span = info_span!("handle connection", %user_id, %login, %address);
         async move {
             let (connection_id, handle_io, mut incoming_rx) = this
                 .peer
@@ -268,7 +270,7 @@ impl Server {
                 })
                 .await;
 
-            tracing::info!(%user_id, %connection_id, %address, "connection opened");
+            tracing::info!(%user_id, %login, %connection_id, %address, "connection opened");
 
             if let Some(send_connection_id) = send_connection_id.as_mut() {
                 let _ = send_connection_id.send(connection_id).await;
@@ -291,14 +293,14 @@ impl Server {
                 futures::select_biased! {
                     result = handle_io => {
                         if let Err(error) = result {
-                            tracing::error!(%error, "error handling I/O");
+                            tracing::error!(?error, %user_id, %login, %connection_id, %address, "error handling I/O");
                         }
                         break;
                     }
                     message = next_message => {
                         if let Some(message) = message {
                             let type_name = message.payload_type_name();
-                            let span = tracing::info_span!("receive message", %user_id, %connection_id, %address, type_name);
+                            let span = tracing::info_span!("receive message", %user_id, %login, %connection_id, %address, type_name);
                             async {
                                 if let Some(handler) = this.handlers.get(&message.payload_type_id()) {
                                     let notifications = this.notifications.clone();
@@ -316,25 +318,27 @@ impl Server {
                                         handle_message.await;
                                     }
                                 } else {
-                                    tracing::error!("no message handler");
+                                    tracing::error!(%user_id, %login, %connection_id, %address, "no message handler");
                                 }
                             }.instrument(span).await;
                         } else {
-                            tracing::info!(%user_id, %connection_id, %address, "connection closed");
+                            tracing::info!(%user_id, %login, %connection_id, %address, "connection closed");
                             break;
                         }
                     }
                 }
             }
 
+            tracing::info!(%user_id, %login, %connection_id, %address, "signing out");
             if let Err(error) = this.sign_out(connection_id).await {
-                tracing::error!(%error, "error signing out");
+                tracing::error!(%user_id, %login, %connection_id, %address, ?error, "error signing out");
             }
 
             Ok(())
         }.instrument(span)
     }
 
+    #[instrument(skip(self), err)]
     async fn sign_out(self: &mut Arc<Self>, connection_id: ConnectionId) -> Result<()> {
         self.peer.disconnect(connection_id);
 
@@ -1528,7 +1532,7 @@ pub async fn handle_websocket_request(
     TypedHeader(ProtocolVersion(protocol_version)): TypedHeader<ProtocolVersion>,
     ConnectInfo(socket_address): ConnectInfo<SocketAddr>,
     Extension(server): Extension<Arc<Server>>,
-    Extension(user_id): Extension<UserId>,
+    Extension(user): Extension<User>,
     ws: WebSocketUpgrade,
 ) -> axum::response::Response {
     if protocol_version != rpc::PROTOCOL_VERSION {
@@ -1548,7 +1552,7 @@ pub async fn handle_websocket_request(
         let connection = Connection::new(Box::pin(socket));
         async move {
             server
-                .handle_connection(connection, socket_address, user_id, None, RealExecutor)
+                .handle_connection(connection, socket_address, user, None, RealExecutor)
                 .await
                 .log_err();
         }
@@ -3239,7 +3243,7 @@ mod tests {
 
         // Type a completion trigger character as the guest.
         editor_b.update(cx_b, |editor, cx| {
-            editor.select_ranges([13..13], None, cx);
+            editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
             editor.handle_input(&Input(".".into()), cx);
             cx.focus(&editor_b);
         });
@@ -4350,7 +4354,9 @@ mod tests {
 
         // Move cursor to a location that contains code actions.
         editor_b.update(cx_b, |editor, cx| {
-            editor.select_ranges([Point::new(1, 31)..Point::new(1, 31)], None, cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
+            });
             cx.focus(&editor_b);
         });
 
@@ -4576,7 +4582,7 @@ mod tests {
 
         // Move cursor to a location that can be renamed.
         let prepare_rename = editor_b.update(cx_b, |editor, cx| {
-            editor.select_ranges([7..7], None, cx);
+            editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
             editor.rename(&Rename, cx).unwrap()
         });
 
@@ -5564,8 +5570,12 @@ mod tests {
         });
 
         // When client B starts following client A, all visible view states are replicated to client B.
-        editor_a1.update(cx_a, |editor, cx| editor.select_ranges([0..1], None, cx));
-        editor_a2.update(cx_a, |editor, cx| editor.select_ranges([2..3], None, cx));
+        editor_a1.update(cx_a, |editor, cx| {
+            editor.change_selections(None, cx, |s| s.select_ranges([0..1]))
+        });
+        editor_a2.update(cx_a, |editor, cx| {
+            editor.change_selections(None, cx, |s| s.select_ranges([2..3]))
+        });
         workspace_b
             .update(cx_b, |workspace, cx| {
                 workspace
@@ -5588,11 +5598,11 @@ mod tests {
             Some((worktree_id, "2.txt").into())
         );
         assert_eq!(
-            editor_b2.read_with(cx_b, |editor, cx| editor.selected_ranges(cx)),
+            editor_b2.read_with(cx_b, |editor, cx| editor.selections.ranges(cx)),
             vec![2..3]
         );
         assert_eq!(
-            editor_b1.read_with(cx_b, |editor, cx| editor.selected_ranges(cx)),
+            editor_b1.read_with(cx_b, |editor, cx| editor.selections.ranges(cx)),
             vec![0..1]
         );
 
@@ -5631,11 +5641,11 @@ mod tests {
 
         // Changes to client A's editor are reflected on client B.
         editor_a1.update(cx_a, |editor, cx| {
-            editor.select_ranges([1..1, 2..2], None, cx);
+            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2]));
         });
         editor_b1
             .condition(cx_b, |editor, cx| {
-                editor.selected_ranges(cx) == vec![1..1, 2..2]
+                editor.selections.ranges(cx) == vec![1..1, 2..2]
             })
             .await;
 
@@ -5645,11 +5655,13 @@ mod tests {
             .await;
 
         editor_a1.update(cx_a, |editor, cx| {
-            editor.select_ranges([3..3], None, cx);
+            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
             editor.set_scroll_position(vec2f(0., 100.), cx);
         });
         editor_b1
-            .condition(cx_b, |editor, cx| editor.selected_ranges(cx) == vec![3..3])
+            .condition(cx_b, |editor, cx| {
+                editor.selections.ranges(cx) == vec![3..3]
+            })
             .await;
 
         // After unfollowing, client B stops receiving updates from client A.
@@ -6540,6 +6552,7 @@ mod tests {
             let client_name = name.to_string();
             let mut client = Client::new(http.clone());
             let server = self.server.clone();
+            let db = self.app_state.db.clone();
             let connection_killers = self.connection_killers.clone();
             let forbid_connections = self.forbid_connections.clone();
             let (connection_id_tx, mut connection_id_rx) = mpsc::channel(16);
@@ -6560,6 +6573,7 @@ mod tests {
                     assert_eq!(credentials.access_token, "the-token");
 
                     let server = server.clone();
+                    let db = db.clone();
                     let connection_killers = connection_killers.clone();
                     let forbid_connections = forbid_connections.clone();
                     let client_name = client_name.clone();
@@ -6573,11 +6587,12 @@ mod tests {
                             let (client_conn, server_conn, killed) =
                                 Connection::in_memory(cx.background());
                             connection_killers.lock().insert(user_id, killed);
+                            let user = db.get_user_by_id(user_id).await.unwrap().unwrap();
                             cx.background()
                                 .spawn(server.handle_connection(
                                     server_conn,
                                     client_name,
-                                    user_id,
+                                    user,
                                     Some(connection_id_tx),
                                     cx.background(),
                                 ))

crates/diagnostics/src/diagnostics.rs 🔗

@@ -5,7 +5,7 @@ use collections::{BTreeSet, HashSet};
 use editor::{
     diagnostic_block_renderer,
     display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock},
-    highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset,
+    highlight_diagnostic_message, Autoscroll, Editor, ExcerptId, MultiBuffer, ToOffset,
 };
 use gpui::{
     actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity,
@@ -417,8 +417,9 @@ impl ProjectDiagnosticsEditor {
                 }];
             } else {
                 groups = self.path_states.get(path_ix)?.diagnostic_groups.as_slice();
-                new_excerpt_ids_by_selection_id = editor.refresh_selections(cx);
-                selections = editor.local_selections::<usize>(cx);
+                new_excerpt_ids_by_selection_id =
+                    editor.change_selections(Some(Autoscroll::Fit), cx, |s| s.refresh());
+                selections = editor.selections.all::<usize>(cx);
             }
 
             // If any selection has lost its position, move it to start of the next primary diagnostic.
@@ -441,7 +442,9 @@ impl ProjectDiagnosticsEditor {
                     }
                 }
             }
-            editor.update_selections(selections, None, cx);
+            editor.change_selections(None, cx, |s| {
+                s.select(selections);
+            });
             Some(())
         });
 
@@ -486,11 +489,11 @@ impl workspace::Item for ProjectDiagnosticsEditor {
     }
 
     fn is_dirty(&self, cx: &AppContext) -> bool {
-        self.excerpts.read(cx).read(cx).is_dirty()
+        self.excerpts.read(cx).is_dirty(cx)
     }
 
     fn has_conflict(&self, cx: &AppContext) -> bool {
-        self.excerpts.read(cx).read(cx).has_conflict()
+        self.excerpts.read(cx).has_conflict(cx)
     }
 
     fn can_save(&self, _: &AppContext) -> bool {
@@ -894,7 +897,7 @@ mod tests {
             // Cursor is at the first diagnostic
             view.editor.update(cx, |editor, cx| {
                 assert_eq!(
-                    editor.selected_display_ranges(cx),
+                    editor.selections.display_ranges(cx),
                     [DisplayPoint::new(12, 6)..DisplayPoint::new(12, 6)]
                 );
             });
@@ -995,7 +998,7 @@ mod tests {
             // Cursor keeps its position.
             view.editor.update(cx, |editor, cx| {
                 assert_eq!(
-                    editor.selected_display_ranges(cx),
+                    editor.selections.display_ranges(cx),
                     [DisplayPoint::new(19, 6)..DisplayPoint::new(19, 6)]
                 );
             });

crates/diagnostics/src/items.rs 🔗

@@ -58,11 +58,9 @@ impl DiagnosticIndicator {
     fn update(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
         let editor = editor.read(cx);
         let buffer = editor.buffer().read(cx);
-        let cursor_position = editor
-            .newest_selection_with_snapshot::<usize>(&buffer.read(cx))
-            .head();
+        let cursor_position = editor.selections.newest::<usize>(cx).head();
         let new_diagnostic = buffer
-            .read(cx)
+            .snapshot(cx)
             .diagnostics_in_range::<_, usize>(cursor_position..cursor_position, false)
             .filter(|entry| !entry.range.is_empty())
             .min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))

crates/editor/src/editor.rs 🔗

@@ -3,6 +3,7 @@ mod element;
 pub mod items;
 pub mod movement;
 mod multi_buffer;
+mod selections_collection;
 
 #[cfg(test)]
 mod test;
@@ -28,7 +29,6 @@ use gpui::{
     ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
     WeakViewHandle,
 };
-use itertools::Itertools as _;
 pub use language::{char_kind, CharKind};
 use language::{
     BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticSeverity,
@@ -40,6 +40,7 @@ pub use multi_buffer::{
 };
 use ordered_float::OrderedFloat;
 use project::{Project, ProjectTransaction};
+use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
 use serde::{Deserialize, Serialize};
 use settings::Settings;
 use smallvec::SmallVec;
@@ -49,14 +50,12 @@ use std::{
     any::TypeId,
     borrow::Cow,
     cmp::{self, Ordering, Reverse},
-    iter::{self, FromIterator},
-    mem,
-    ops::{Deref, DerefMut, Range, RangeInclusive, Sub},
+    iter, mem,
+    ops::{Deref, DerefMut, Range, RangeInclusive},
     sync::Arc,
     time::{Duration, Instant},
 };
 pub use sum_tree::Bias;
-use text::rope::TextDimension;
 use theme::{DiagnosticStyle, Theme};
 use util::{post_inc, ResultExt, TryFutureExt};
 use workspace::{ItemNavHistory, Workspace};
@@ -377,9 +376,7 @@ pub struct Editor {
     handle: WeakViewHandle<Self>,
     buffer: ModelHandle<MultiBuffer>,
     display_map: ModelHandle<DisplayMap>,
-    next_selection_id: usize,
-    selections: Arc<[Selection<Anchor>]>,
-    pending_selection: Option<PendingSelection>,
+    pub selections: SelectionsCollection,
     columnar_selection_tail: Option<Anchor>,
     add_selections_state: Option<AddSelectionsState>,
     select_next_state: Option<SelectNextState>,
@@ -429,13 +426,7 @@ pub struct EditorSnapshot {
     scroll_top_anchor: Anchor,
 }
 
-#[derive(Clone)]
-pub struct PendingSelection {
-    selection: Selection<Anchor>,
-    mode: SelectMode,
-}
-
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct SelectionHistoryEntry {
     selections: Arc<[Selection<Anchor>]>,
     select_next_state: Option<SelectNextState>,
@@ -527,13 +518,13 @@ impl SelectionHistory {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct AddSelectionsState {
     above: bool,
     stack: Vec<usize>,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct SelectNextState {
     query: AhoCorasick,
     wordwise: bool,
@@ -545,6 +536,7 @@ struct BracketPairState {
     pair: BracketPair,
 }
 
+#[derive(Debug)]
 struct SnippetState {
     ranges: Vec<Vec<Range<Anchor>>>,
     active_index: usize,
@@ -945,23 +937,14 @@ impl Editor {
         cx.observe(&display_map, Self::on_display_map_changed)
             .detach();
 
+        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
+
         let mut this = Self {
             handle: cx.weak_handle(),
             buffer,
             display_map,
-            selections: Arc::from([]),
-            pending_selection: Some(PendingSelection {
-                selection: Selection {
-                    id: 0,
-                    start: Anchor::min(),
-                    end: Anchor::min(),
-                    reversed: false,
-                    goal: SelectionGoal::None,
-                },
-                mode: SelectMode::Character,
-            }),
+            selections,
             columnar_selection_tail: None,
-            next_selection_id: 1,
             add_selections_state: None,
             select_next_state: None,
             selection_history: Default::default(),
@@ -1204,12 +1187,11 @@ impl Editor {
             first_cursor_top = highlighted_rows.start as f32;
             last_cursor_bottom = first_cursor_top + 1.;
         } else if autoscroll == Autoscroll::Newest {
-            let newest_selection =
-                self.newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot);
+            let newest_selection = self.selections.newest::<Point>(cx);
             first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
             last_cursor_bottom = first_cursor_top + 1.;
         } else {
-            let selections = self.local_selections::<Point>(cx);
+            let selections = self.selections.all::<Point>(cx);
             first_cursor_top = selections
                 .first()
                 .unwrap()
@@ -1269,7 +1251,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) -> bool {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let selections = self.local_selections::<Point>(cx);
+        let selections = self.selections.all::<Point>(cx);
 
         let mut target_left;
         let mut target_right;
@@ -1318,83 +1300,96 @@ impl Editor {
         }
     }
 
-    pub fn replace_selections_with(
+    fn selections_did_change(
         &mut self,
+        local: bool,
+        old_cursor_position: &Anchor,
         cx: &mut ViewContext<Self>,
-        mut find_replacement: impl FnMut(&DisplaySnapshot) -> DisplayPoint,
     ) {
-        let display_map = self.snapshot(cx);
-        let cursor = find_replacement(&display_map);
-        let selection = Selection {
-            id: post_inc(&mut self.next_selection_id),
-            start: cursor,
-            end: cursor,
-            reversed: false,
-            goal: SelectionGoal::None,
+        if self.focused && self.leader_replica_id.is_none() {
+            self.buffer.update(cx, |buffer, cx| {
+                buffer.set_active_selections(&self.selections.disjoint_anchors(), cx)
+            });
         }
-        .map(|display_point| display_point.to_point(&display_map));
-        self.update_selections(vec![selection], None, cx);
-    }
 
-    pub fn display_selections(
-        &mut self,
-        cx: &mut ViewContext<Self>,
-    ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
-        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let selections = self
-            .local_selections::<Point>(cx)
-            .into_iter()
-            .map(|selection| selection.map(|point| point.to_display_point(&display_map)))
-            .collect();
-        (display_map, selections)
-    }
+        let display_map = self
+            .display_map
+            .update(cx, |display_map, cx| display_map.snapshot(cx));
+        let buffer = &display_map.buffer_snapshot;
+        self.add_selections_state = None;
+        self.select_next_state = None;
+        self.select_larger_syntax_node_stack.clear();
+        self.autoclose_stack
+            .invalidate(&self.selections.disjoint_anchors(), buffer);
+        self.snippet_stack
+            .invalidate(&self.selections.disjoint_anchors(), buffer);
+        self.take_rename(false, cx);
 
-    pub fn move_selections(
-        &mut self,
-        cx: &mut ViewContext<Self>,
-        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
-    ) {
-        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let selections = self
-            .local_selections::<Point>(cx)
-            .into_iter()
-            .map(|selection| {
-                let mut selection = selection.map(|point| point.to_display_point(&display_map));
-                move_selection(&display_map, &mut selection);
-                selection.map(|display_point| display_point.to_point(&display_map))
-            })
-            .collect();
-        self.update_selections(selections, Some(Autoscroll::Fit), cx);
-    }
+        let new_cursor_position = self.selections.newest_anchor().head();
 
-    pub fn move_selection_heads(
-        &mut self,
-        cx: &mut ViewContext<Self>,
-        mut update_head: impl FnMut(
-            &DisplaySnapshot,
-            DisplayPoint,
-            SelectionGoal,
-        ) -> (DisplayPoint, SelectionGoal),
-    ) {
-        self.move_selections(cx, |map, selection| {
-            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
-            selection.set_head(new_head, new_goal);
-        });
+        self.push_to_nav_history(
+            old_cursor_position.clone(),
+            Some(new_cursor_position.to_point(buffer)),
+            cx,
+        );
+
+        if local {
+            let new_cursor_position = self.selections.newest_anchor().head();
+            let completion_menu = match self.context_menu.as_mut() {
+                Some(ContextMenu::Completions(menu)) => Some(menu),
+                _ => {
+                    self.context_menu.take();
+                    None
+                }
+            };
+
+            if let Some(completion_menu) = completion_menu {
+                let cursor_position = new_cursor_position.to_offset(buffer);
+                let (word_range, kind) =
+                    buffer.surrounding_word(completion_menu.initial_position.clone());
+                if kind == Some(CharKind::Word)
+                    && word_range.to_inclusive().contains(&cursor_position)
+                {
+                    let query = Self::completion_query(buffer, cursor_position);
+                    cx.background()
+                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
+                    self.show_completions(&ShowCompletions, cx);
+                } else {
+                    self.hide_context_menu(cx);
+                }
+            }
+
+            if old_cursor_position.to_display_point(&display_map).row()
+                != new_cursor_position.to_display_point(&display_map).row()
+            {
+                self.available_code_actions.take();
+            }
+            self.refresh_code_actions(cx);
+            self.refresh_document_highlights(cx);
+        }
+
+        self.pause_cursor_blinking(cx);
+        cx.emit(Event::SelectionsChanged { local });
+        cx.notify();
     }
 
-    pub fn move_cursors(
+    pub fn change_selections<R>(
         &mut self,
+        autoscroll: Option<Autoscroll>,
         cx: &mut ViewContext<Self>,
-        mut update_cursor_position: impl FnMut(
-            &DisplaySnapshot,
-            DisplayPoint,
-            SelectionGoal,
-        ) -> (DisplayPoint, SelectionGoal),
-    ) {
-        self.move_selections(cx, |map, selection| {
-            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
-            selection.collapse_to(cursor, new_goal)
-        });
+        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
+    ) -> R {
+        let old_cursor_position = self.selections.newest_anchor().head();
+        self.push_to_selection_history();
+
+        let result = self.selections.change_with(cx, change);
+
+        if let Some(autoscroll) = autoscroll {
+            self.request_autoscroll(autoscroll, cx);
+        }
+        self.selections_did_change(true, &old_cursor_position, cx);
+
+        result
     }
 
     pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
@@ -1449,30 +1444,34 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let tail = self
-            .newest_selection_with_snapshot::<usize>(&display_map.buffer_snapshot)
-            .tail();
+        let tail = self.selections.newest::<usize>(cx).tail();
         self.begin_selection(position, false, click_count, cx);
 
         let position = position.to_offset(&display_map, Bias::Left);
         let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
-        let mut pending = self.pending_selection.clone().unwrap();
 
+        let mut pending_selection = self
+            .selections
+            .pending_anchor()
+            .expect("extend_selection not called with pending selection");
         if position >= tail {
-            pending.selection.start = tail_anchor.clone();
+            pending_selection.start = tail_anchor.clone();
         } else {
-            pending.selection.end = tail_anchor.clone();
-            pending.selection.reversed = true;
+            pending_selection.end = tail_anchor.clone();
+            pending_selection.reversed = true;
         }
 
-        match &mut pending.mode {
+        let mut pending_mode = self.selections.pending_mode().unwrap();
+        match &mut pending_mode {
             SelectMode::Word(range) | SelectMode::Line(range) => {
                 *range = tail_anchor.clone()..tail_anchor
             }
             _ => {}
         }
 
-        self.set_selections(self.selections.clone(), Some(pending), true, cx);
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.set_pending(pending_selection, pending_mode)
+        });
     }
 
     fn begin_selection(
@@ -1489,7 +1488,7 @@ impl Editor {
 
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = &display_map.buffer_snapshot;
-        let newest_selection = self.newest_anchor_selection().clone();
+        let newest_selection = self.selections.newest_anchor().clone();
         let position = display_map.clip_point(position, Bias::Left);
 
         let start;
@@ -1527,38 +1526,17 @@ impl Editor {
             }
         }
 
-        let selection = Selection {
-            id: post_inc(&mut self.next_selection_id),
-            start,
-            end,
-            reversed: false,
-            goal: SelectionGoal::None,
-        };
-
-        let mut selections;
-        if add {
-            selections = self.selections.clone();
-            // Remove the newest selection if it was added due to a previous mouse up
-            // within this multi-click.
-            if click_count > 1 {
-                selections = self
-                    .selections
-                    .iter()
-                    .filter(|selection| selection.id != newest_selection.id)
-                    .cloned()
-                    .collect();
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            if add {
+                if click_count > 1 {
+                    s.delete(newest_selection.id);
+                }
+            } else {
+                s.clear_disjoint();
             }
-        } else {
-            selections = Arc::from([]);
-        }
-        self.set_selections(
-            selections,
-            Some(PendingSelection { selection, mode }),
-            true,
-            cx,
-        );
 
-        cx.notify();
+            s.set_pending_range(start..end, mode);
+        });
     }
 
     fn begin_columnar_selection(
@@ -1573,9 +1551,7 @@ impl Editor {
         }
 
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let tail = self
-            .newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot)
-            .tail();
+        let tail = self.selections.newest::<Point>(cx).tail();
         self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 
         self.select_columns(
@@ -1599,14 +1575,15 @@ impl Editor {
         if let Some(tail) = self.columnar_selection_tail.as_ref() {
             let tail = tail.to_display_point(&display_map);
             self.select_columns(tail, position, overshoot, &display_map, cx);
-        } else if let Some(mut pending) = self.pending_selection.clone() {
+        } else if let Some(mut pending) = self.selections.pending_anchor().clone() {
             let buffer = self.buffer.read(cx).snapshot(cx);
             let head;
             let tail;
-            match &pending.mode {
+            let mode = self.selections.pending_mode().unwrap();
+            match &mode {
                 SelectMode::Character => {
                     head = position.to_point(&display_map);
-                    tail = pending.selection.tail().to_point(&buffer);
+                    tail = pending.tail().to_point(&buffer);
                 }
                 SelectMode::Word(original_range) => {
                     let original_display_range = original_range.start.to_display_point(&display_map)
@@ -1662,15 +1639,18 @@ impl Editor {
             };
 
             if head < tail {
-                pending.selection.start = buffer.anchor_before(head);
-                pending.selection.end = buffer.anchor_before(tail);
-                pending.selection.reversed = true;
+                pending.start = buffer.anchor_before(head);
+                pending.end = buffer.anchor_before(tail);
+                pending.reversed = true;
             } else {
-                pending.selection.start = buffer.anchor_before(tail);
-                pending.selection.end = buffer.anchor_before(head);
-                pending.selection.reversed = false;
+                pending.start = buffer.anchor_before(tail);
+                pending.end = buffer.anchor_before(head);
+                pending.reversed = false;
             }
-            self.set_selections(self.selections.clone(), Some(pending), true, cx);
+
+            self.change_selections(None, cx, |s| {
+                s.set_pending(pending, mode);
+            });
         } else {
             log::error!("update_selection dispatched with no pending selection");
             return;
@@ -1682,9 +1662,12 @@ impl Editor {
 
     fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
         self.columnar_selection_tail.take();
-        if self.pending_selection.is_some() {
-            let selections = self.local_selections::<usize>(cx);
-            self.update_selections(selections, None, cx);
+        if self.selections.pending_anchor().is_some() {
+            let selections = self.selections.all::<usize>(cx);
+            self.change_selections(None, cx, |s| {
+                s.select(selections);
+                s.clear_pending();
+            });
         }
     }
 
@@ -1702,7 +1685,7 @@ impl Editor {
         let end_column = cmp::max(tail.column(), head.column() + overshoot);
         let reversed = start_column < tail.column();
 
-        let selections = (start_row..=end_row)
+        let selection_ranges = (start_row..=end_row)
             .filter_map(|row| {
                 if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
                     let start = display_map
@@ -1711,25 +1694,25 @@ impl Editor {
                     let end = display_map
                         .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
                         .to_point(&display_map);
-                    Some(Selection {
-                        id: post_inc(&mut self.next_selection_id),
-                        start,
-                        end,
-                        reversed,
-                        goal: SelectionGoal::None,
-                    })
+                    if reversed {
+                        Some(end..start)
+                    } else {
+                        Some(start..end)
+                    }
                 } else {
                     None
                 }
             })
             .collect::<Vec<_>>();
 
-        self.update_selections(selections, None, cx);
+        self.change_selections(None, cx, |s| {
+            s.select_ranges(selection_ranges);
+        });
         cx.notify();
     }
 
     pub fn is_selecting(&self) -> bool {
-        self.pending_selection.is_some() || self.columnar_selection_tail.is_some()
+        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
     }
 
     pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
@@ -1751,26 +1734,7 @@ impl Editor {
                 return;
             }
 
-            if let Some(pending) = self.pending_selection.clone() {
-                let mut selections = self.selections.clone();
-                if selections.is_empty() {
-                    selections = Arc::from([pending.selection]);
-                }
-                self.set_selections(selections, None, true, cx);
-                self.request_autoscroll(Autoscroll::Fit, cx);
-                return;
-            }
-
-            let mut oldest_selection = self.oldest_selection::<usize>(&cx);
-            if self.selection_count() > 1 {
-                self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx);
-                return;
-            }
-
-            if !oldest_selection.is_empty() {
-                oldest_selection.start = oldest_selection.head().clone();
-                oldest_selection.end = oldest_selection.head().clone();
-                self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx);
+            if self.change_selections(Some(Autoscroll::Fit), cx, |s| s.try_cancel()) {
                 return;
             }
         }
@@ -1778,107 +1742,6 @@ impl Editor {
         cx.propagate_action();
     }
 
-    #[cfg(any(test, feature = "test-support"))]
-    pub fn selected_ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
-        &self,
-        cx: &AppContext,
-    ) -> Vec<Range<D>> {
-        self.local_selections::<D>(cx)
-            .iter()
-            .map(|s| {
-                if s.reversed {
-                    s.end.clone()..s.start.clone()
-                } else {
-                    s.start.clone()..s.end.clone()
-                }
-            })
-            .collect()
-    }
-
-    #[cfg(any(test, feature = "test-support"))]
-    pub fn selected_display_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
-        let display_map = self
-            .display_map
-            .update(cx, |display_map, cx| display_map.snapshot(cx));
-        self.selections
-            .iter()
-            .chain(
-                self.pending_selection
-                    .as_ref()
-                    .map(|pending| &pending.selection),
-            )
-            .map(|s| {
-                if s.reversed {
-                    s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
-                } else {
-                    s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
-                }
-            })
-            .collect()
-    }
-
-    pub fn select_ranges<I, T>(
-        &mut self,
-        ranges: I,
-        autoscroll: Option<Autoscroll>,
-        cx: &mut ViewContext<Self>,
-    ) where
-        I: IntoIterator<Item = Range<T>>,
-        T: ToOffset,
-    {
-        let buffer = self.buffer.read(cx).snapshot(cx);
-        let selections = ranges
-            .into_iter()
-            .map(|range| {
-                let mut start = range.start.to_offset(&buffer);
-                let mut end = range.end.to_offset(&buffer);
-                let reversed = if start > end {
-                    mem::swap(&mut start, &mut end);
-                    true
-                } else {
-                    false
-                };
-                Selection {
-                    id: post_inc(&mut self.next_selection_id),
-                    start,
-                    end,
-                    reversed,
-                    goal: SelectionGoal::None,
-                }
-            })
-            .collect::<Vec<_>>();
-        self.update_selections(selections, autoscroll, cx);
-    }
-
-    #[cfg(any(test, feature = "test-support"))]
-    pub fn select_display_ranges<'a, T>(&mut self, ranges: T, cx: &mut ViewContext<Self>)
-    where
-        T: IntoIterator<Item = &'a Range<DisplayPoint>>,
-    {
-        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let selections = ranges
-            .into_iter()
-            .map(|range| {
-                let mut start = range.start;
-                let mut end = range.end;
-                let reversed = if start > end {
-                    mem::swap(&mut start, &mut end);
-                    true
-                } else {
-                    false
-                };
-                Selection {
-                    id: post_inc(&mut self.next_selection_id),
-                    start: start.to_point(&display_map),
-                    end: end.to_point(&display_map),
-                    reversed,
-                    goal: SelectionGoal::None,
-                }
-            })
-            .collect();
-        self.update_selections(selections, None, cx);
-    }
-
     pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
         if !self.input_enabled {
             cx.propagate_action();
@@ -1900,7 +1763,8 @@ impl Editor {
     pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
         self.transact(cx, |this, cx| {
             let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
-                let selections = this.local_selections::<usize>(cx);
+                let selections = this.selections.all::<usize>(cx);
+
                 let buffer = this.buffer.read(cx).snapshot(cx);
                 selections
                     .iter()
@@ -1947,9 +1811,12 @@ impl Editor {
                         if insert_extra_newline {
                             new_text = new_text.repeat(2);
                         }
+
+                        let anchor = buffer.anchor_after(end);
+                        let new_selection = selection.map(|_| anchor.clone());
                         (
                             (start..end, new_text),
-                            (insert_extra_newline, buffer.anchor_after(end)),
+                            (insert_extra_newline, new_selection),
                         )
                     })
                     .unzip()
@@ -1957,35 +1824,28 @@ impl Editor {
 
             this.buffer.update(cx, |buffer, cx| {
                 buffer.edit_with_autoindent(edits, cx);
-
-                let buffer = buffer.read(cx);
-                this.selections = this
-                    .selections
-                    .iter()
-                    .cloned()
-                    .zip(selection_fixup_info)
-                    .map(|(mut new_selection, (extra_newline_inserted, end))| {
-                        let mut cursor = end.to_point(&buffer);
-                        if extra_newline_inserted {
-                            cursor.row -= 1;
-                            cursor.column = buffer.line_len(cursor.row);
-                        }
-                        let anchor = buffer.anchor_after(cursor);
-                        new_selection.start = anchor.clone();
-                        new_selection.end = anchor;
-                        new_selection
-                    })
-                    .collect();
             });
+            let buffer = this.buffer.read(cx).snapshot(cx);
+            let new_selections = selection_fixup_info
+                .into_iter()
+                .map(|(extra_newline_inserted, new_selection)| {
+                    let mut cursor = new_selection.end.to_point(&buffer);
+                    if extra_newline_inserted {
+                        cursor.row -= 1;
+                        cursor.column = buffer.line_len(cursor.row);
+                    }
+                    new_selection.map(|_| cursor.clone())
+                })
+                .collect();
 
-            this.request_autoscroll(Autoscroll::Fit, cx);
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
         });
     }
 
     pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
         let text: Arc<str> = text.into();
         self.transact(cx, |this, cx| {
-            let old_selections = this.local_selections::<usize>(cx);
+            let old_selections = this.selections.all::<usize>(cx);
             let selection_anchors = this.buffer.update(cx, |buffer, cx| {
                 let anchors = {
                     let snapshot = buffer.read(cx);
@@ -2019,12 +1879,15 @@ impl Editor {
                     })
                     .collect()
             };
-            this.update_selections(selections, Some(Autoscroll::Fit), cx);
+
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections);
+            })
         });
     }
 
     fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
-        let selection = self.newest_anchor_selection();
+        let selection = self.selections.newest_anchor();
         if self
             .buffer
             .read(cx)
@@ -2044,64 +1907,58 @@ impl Editor {
             .cloned()
         {
             if self
-                .local_selections::<usize>(cx)
+                .selections
+                .all::<usize>(cx)
                 .iter()
                 .any(|selection| selection.is_empty())
             {
-                false
-            } else {
-                let mut selections = self.selections.to_vec();
-                for selection in &mut selections {
-                    selection.end = selection.end.bias_left(&snapshot);
-                }
-                drop(snapshot);
+                return false;
+            }
 
-                self.buffer.update(cx, |buffer, cx| {
-                    let pair_start: Arc<str> = pair.start.clone().into();
-                    buffer.edit(
-                        selections
-                            .iter()
-                            .map(|s| (s.start.clone()..s.start.clone(), pair_start.clone())),
-                        cx,
-                    );
-                    let pair_end: Arc<str> = pair.end.clone().into();
-                    buffer.edit(
-                        selections
-                            .iter()
-                            .map(|s| (s.end.clone()..s.end.clone(), pair_end.clone())),
-                        cx,
-                    );
-                });
+            let mut selections = self.selections.disjoint_anchors().to_vec();
+            for selection in &mut selections {
+                selection.end = selection.end.bias_left(&snapshot);
+            }
+            drop(snapshot);
 
-                let snapshot = self.buffer.read(cx).read(cx);
-                for selection in &mut selections {
-                    selection.end = selection.end.bias_right(&snapshot);
-                }
-                drop(snapshot);
+            self.buffer.update(cx, |buffer, cx| {
+                let pair_start: Arc<str> = pair.start.clone().into();
+                let pair_end: Arc<str> = pair.end.clone().into();
+                buffer.edit(
+                    selections
+                        .iter()
+                        .map(|s| (s.start.clone()..s.start.clone(), pair_start.clone()))
+                        .chain(
+                            selections
+                                .iter()
+                                .map(|s| (s.end.clone()..s.end.clone(), pair_end.clone())),
+                        ),
+                    cx,
+                );
+            });
 
-                self.set_selections(selections.into(), None, true, cx);
-                true
+            let snapshot = self.buffer.read(cx).read(cx);
+            for selection in &mut selections {
+                selection.end = selection.end.bias_right(&snapshot);
             }
+            drop(snapshot);
+
+            self.change_selections(None, cx, |s| s.select_anchors(selections));
+            true
         } else {
             false
         }
     }
 
     fn autoclose_bracket_pairs(&mut self, cx: &mut ViewContext<Self>) {
-        let selections = self.local_selections::<usize>(cx);
+        let selections = self.selections.all::<usize>(cx);
         let mut bracket_pair_state = None;
         let mut new_selections = None;
         self.buffer.update(cx, |buffer, cx| {
             let mut snapshot = buffer.snapshot(cx);
             let left_biased_selections = selections
                 .iter()
-                .map(|selection| Selection {
-                    id: selection.id,
-                    start: snapshot.anchor_before(selection.start),
-                    end: snapshot.anchor_before(selection.end),
-                    reversed: selection.reversed,
-                    goal: selection.goal,
-                })
+                .map(|selection| selection.map(|p| snapshot.anchor_before(p)))
                 .collect::<Vec<_>>();
 
             let autoclose_pair = snapshot.language().and_then(|language| {
@@ -2155,7 +2012,7 @@ impl Editor {
                 snapshot = buffer.snapshot(cx);
 
                 new_selections = Some(
-                    self.resolve_selections::<usize, _>(left_biased_selections.iter(), &snapshot)
+                    resolve_multiple::<usize, _>(left_biased_selections.iter(), &snapshot)
                         .collect::<Vec<_>>(),
                 );
 
@@ -2177,7 +2034,9 @@ impl Editor {
         });
 
         if let Some(new_selections) = new_selections {
-            self.update_selections(new_selections, None, cx);
+            self.change_selections(None, cx, |s| {
+                s.select(new_selections);
+            });
         }
         if let Some(bracket_pair_state) = bracket_pair_state {
             self.autoclose_stack.push(bracket_pair_state);
@@ -2185,7 +2044,8 @@ impl Editor {
     }
 
     fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
-        let old_selections = self.local_selections::<usize>(cx);
+        let buffer = self.buffer.read(cx).snapshot(cx);
+        let old_selections = self.selections.all::<usize>(cx);
         let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() {
             autoclose_pair
         } else {
@@ -2197,7 +2057,6 @@ impl Editor {
 
         debug_assert_eq!(old_selections.len(), autoclose_pair.ranges.len());
 
-        let buffer = self.buffer.read(cx).snapshot(cx);
         if old_selections
             .iter()
             .zip(autoclose_pair.ranges.iter().map(|r| r.to_offset(&buffer)))
@@ -2220,7 +2079,9 @@ impl Editor {
                 })
                 .collect();
             self.autoclose_stack.pop();
-            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(new_selections);
+            });
             true
         } else {
             false
@@ -2252,7 +2113,7 @@ impl Editor {
             return;
         };
 
-        let position = self.newest_anchor_selection().head();
+        let position = self.selections.newest_anchor().head();
         let (buffer, buffer_position) = if let Some(output) = self
             .buffer
             .read(cx)
@@ -2353,12 +2214,12 @@ impl Editor {
             snippet = None;
             text = completion.new_text.clone();
         };
+        let selections = self.selections.all::<usize>(cx);
         let buffer = buffer_handle.read(cx);
         let old_range = completion.old_range.to_offset(&buffer);
         let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 
-        let selections = self.local_selections::<usize>(cx);
-        let newest_selection = self.newest_anchor_selection();
+        let newest_selection = self.selections.newest_anchor();
         if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
             return None;
         }
@@ -2524,7 +2385,7 @@ impl Editor {
                     editor
                         .buffer()
                         .read(cx)
-                        .excerpt_containing(editor.newest_anchor_selection().head(), cx)
+                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
                 });
                 if let Some((excerpted_buffer, excerpt_range)) = excerpt {
                     if excerpted_buffer == *buffer {
@@ -2585,7 +2446,7 @@ impl Editor {
     fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
         let project = self.project.as_ref()?;
         let buffer = self.buffer.read(cx);
-        let newest_selection = self.newest_anchor_selection().clone();
+        let newest_selection = self.selections.newest_anchor().clone();
         let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
         let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
         if start_buffer != end_buffer {
@@ -2620,7 +2481,7 @@ impl Editor {
 
         let project = self.project.as_ref()?;
         let buffer = self.buffer.read(cx);
-        let newest_selection = self.newest_anchor_selection().clone();
+        let newest_selection = self.selections.newest_anchor().clone();
         let cursor_position = newest_selection.head();
         let (cursor_buffer, cursor_buffer_position) =
             buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
@@ -2808,7 +2669,9 @@ impl Editor {
         });
 
         if let Some(tabstop) = tabstops.first() {
-            self.select_ranges(tabstop.iter().cloned(), Some(Autoscroll::Fit), cx);
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select_ranges(tabstop.iter().cloned());
+            });
             self.snippet_stack.push(SnippetState {
                 active_index: 0,
                 ranges: tabstops,
@@ -2827,14 +2690,13 @@ impl Editor {
     }
 
     pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
-        let buffer = self.buffer.read(cx).snapshot(cx);
-
-        if let Some(snippet) = self.snippet_stack.last_mut() {
+        if let Some(mut snippet) = self.snippet_stack.pop() {
             match bias {
                 Bias::Left => {
                     if snippet.active_index > 0 {
                         snippet.active_index -= 1;
                     } else {
+                        self.snippet_stack.push(snippet);
                         return false;
                     }
                 }
@@ -2842,34 +2704,21 @@ impl Editor {
                     if snippet.active_index + 1 < snippet.ranges.len() {
                         snippet.active_index += 1;
                     } else {
+                        self.snippet_stack.push(snippet);
                         return false;
                     }
                 }
             }
             if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
-                let new_selections = current_ranges
-                    .iter()
-                    .map(|new_range| {
-                        let new_range = new_range.to_offset(&buffer);
-                        Selection {
-                            id: post_inc(&mut self.next_selection_id),
-                            start: new_range.start,
-                            end: new_range.end,
-                            reversed: false,
-                            goal: SelectionGoal::None,
-                        }
-                    })
-                    .collect();
-
-                // Remove the snippet state when moving to the last tabstop.
-                if snippet.active_index + 1 == snippet.ranges.len() {
-                    self.snippet_stack.pop();
+                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_anchor_ranges(current_ranges.into_iter().cloned())
+                });
+                // If snippet state is not at the last tabstop, push it back on the stack
+                if snippet.active_index + 1 < snippet.ranges.len() {
+                    self.snippet_stack.push(snippet);
                 }
-
-                self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
                 return true;
             }
-            self.snippet_stack.pop();
         }
 
         false

crates/editor/src/element.rs 🔗

@@ -957,8 +957,10 @@ impl Element for EditorElement {
             selections.extend(remote_selections);
 
             if view.show_local_selections {
-                let local_selections =
-                    view.local_selections_in_range(start_anchor..end_anchor, &display_map);
+                let mut local_selections = view
+                    .selections
+                    .disjoint_in_range(start_anchor..end_anchor, cx);
+                local_selections.extend(view.selections.pending(cx));
                 for selection in &local_selections {
                     let is_empty = selection.start == selection.end;
                     let selection_start = snapshot.prev_line_boundary(selection.start).1;
@@ -1041,7 +1043,8 @@ impl Element for EditorElement {
             }
 
             let newest_selection_head = view
-                .newest_selection_with_snapshot::<usize>(&snapshot.buffer_snapshot)
+                .selections
+                .newest::<usize>(cx)
                 .head()
                 .to_display_point(&snapshot);
 

crates/editor/src/items.rs 🔗

@@ -102,7 +102,7 @@ impl FollowableItem for Editor {
         } else {
             self.buffer.update(cx, |buffer, cx| {
                 if self.focused {
-                    buffer.set_active_selections(&self.selections, cx);
+                    buffer.set_active_selections(&self.selections.disjoint_anchors(), cx);
                 }
             });
         }
@@ -118,7 +118,12 @@ impl FollowableItem for Editor {
             )),
             scroll_x: self.scroll_position.x(),
             scroll_y: self.scroll_position.y(),
-            selections: self.selections.iter().map(serialize_selection).collect(),
+            selections: self
+                .selections
+                .disjoint_anchors()
+                .iter()
+                .map(serialize_selection)
+                .collect(),
         }))
     }
 
@@ -144,8 +149,9 @@ impl FollowableItem for Editor {
                 Event::SelectionsChanged { .. } => {
                     update.selections = self
                         .selections
+                        .disjoint_anchors()
                         .iter()
-                        .chain(self.pending_selection.as_ref().map(|p| &p.selection))
+                        .chain(self.selections.pending_anchor().as_ref())
                         .map(serialize_selection)
                         .collect();
                     true
@@ -246,13 +252,13 @@ fn deserialize_selection(
 impl Item for Editor {
     fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
         if let Ok(data) = data.downcast::<NavigationData>() {
+            let newest_selection = self.selections.newest::<Point>(cx);
             let buffer = self.buffer.read(cx).read(cx);
             let offset = if buffer.can_resolve(&data.cursor_anchor) {
                 data.cursor_anchor.to_point(&buffer)
             } else {
                 buffer.clip_point(data.cursor_position, Bias::Left)
             };
-            let newest_selection = self.newest_selection_with_snapshot::<Point>(&buffer);
 
             let scroll_top_anchor = if buffer.can_resolve(&data.scroll_top_anchor) {
                 data.scroll_top_anchor
@@ -270,7 +276,9 @@ impl Item for Editor {
                 let nav_history = self.nav_history.take();
                 self.scroll_position = data.scroll_position;
                 self.scroll_top_anchor = scroll_top_anchor;
-                self.select_ranges([offset..offset], Some(Autoscroll::Fit), cx);
+                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_ranges([offset..offset])
+                });
                 self.nav_history = nav_history;
                 true
             }
@@ -307,7 +315,7 @@ impl Item for Editor {
     }
 
     fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
-        let selection = self.newest_anchor_selection();
+        let selection = self.selections.newest_anchor();
         self.push_to_nav_history(selection.head(), None, cx);
     }
 
@@ -457,7 +465,7 @@ impl CursorPosition {
 
         self.selected_count = 0;
         let mut last_selection: Option<Selection<usize>> = None;
-        for selection in editor.local_selections::<usize>(cx) {
+        for selection in editor.selections.all::<usize>(cx) {
             self.selected_count += selection.end - selection.start;
             if last_selection
                 .as_ref()

crates/editor/src/multi_buffer.rs 🔗

@@ -226,7 +226,7 @@ impl MultiBuffer {
         self.snapshot.borrow().clone()
     }
 
-    pub fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
+    pub(crate) fn read(&self, cx: &AppContext) -> Ref<MultiBufferSnapshot> {
         self.sync(cx);
         self.snapshot.borrow()
     }
@@ -255,6 +255,27 @@ impl MultiBuffer {
         self.subscriptions.subscribe()
     }
 
+    pub fn is_dirty(&self, cx: &AppContext) -> bool {
+        self.read(cx).is_dirty()
+    }
+
+    pub fn has_conflict(&self, cx: &AppContext) -> bool {
+        self.read(cx).has_conflict()
+    }
+
+    pub fn len(&self, cx: &AppContext) -> usize {
+        self.read(cx).len()
+    }
+
+    pub fn symbols_containing<T: ToOffset>(
+        &self,
+        offset: T,
+        theme: Option<&SyntaxTheme>,
+        cx: &AppContext,
+    ) -> Option<(usize, Vec<OutlineItem<Anchor>>)> {
+        self.read(cx).symbols_containing(offset, theme)
+    }
+
     pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
     where
         I: IntoIterator<Item = (Range<S>, T)>,

crates/editor/src/selections_collection.rs 🔗

@@ -0,0 +1,729 @@
+use std::{
+    cell::Ref,
+    cmp, iter, mem,
+    ops::{Deref, Range, Sub},
+    sync::Arc,
+};
+
+use collections::HashMap;
+use gpui::{AppContext, ModelHandle, MutableAppContext};
+use itertools::Itertools;
+use language::{rope::TextDimension, Bias, Point, Selection, SelectionGoal, ToPoint};
+use util::post_inc;
+
+use crate::{
+    display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
+    Anchor, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset,
+};
+
+#[derive(Clone)]
+pub struct PendingSelection {
+    pub selection: Selection<Anchor>,
+    pub mode: SelectMode,
+}
+
+pub struct SelectionsCollection {
+    display_map: ModelHandle<DisplayMap>,
+    buffer: ModelHandle<MultiBuffer>,
+    pub next_selection_id: usize,
+    disjoint: Arc<[Selection<Anchor>]>,
+    pending: Option<PendingSelection>,
+}
+
+impl SelectionsCollection {
+    pub fn new(display_map: ModelHandle<DisplayMap>, buffer: ModelHandle<MultiBuffer>) -> Self {
+        Self {
+            display_map,
+            buffer,
+            next_selection_id: 1,
+            disjoint: Arc::from([]),
+            pending: Some(PendingSelection {
+                selection: Selection {
+                    id: 0,
+                    start: Anchor::min(),
+                    end: Anchor::min(),
+                    reversed: false,
+                    goal: SelectionGoal::None,
+                },
+                mode: SelectMode::Character,
+            }),
+        }
+    }
+
+    fn display_map(&self, cx: &mut MutableAppContext) -> DisplaySnapshot {
+        self.display_map.update(cx, |map, cx| map.snapshot(cx))
+    }
+
+    fn buffer<'a>(&self, cx: &'a AppContext) -> Ref<'a, MultiBufferSnapshot> {
+        self.buffer.read(cx).read(cx)
+    }
+
+    pub fn count<'a>(&self) -> usize {
+        let mut count = self.disjoint.len();
+        if self.pending.is_some() {
+            count += 1;
+        }
+        count
+    }
+
+    pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> {
+        self.disjoint.clone()
+    }
+
+    pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
+        self.pending
+            .as_ref()
+            .map(|pending| pending.selection.clone())
+    }
+
+    pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
+        &self,
+        cx: &AppContext,
+    ) -> Option<Selection<D>> {
+        self.pending_anchor()
+            .as_ref()
+            .map(|pending| pending.map(|p| p.summary::<D>(&self.buffer(cx))))
+    }
+
+    pub fn pending_mode(&self) -> Option<SelectMode> {
+        self.pending.as_ref().map(|pending| pending.mode.clone())
+    }
+
+    pub fn all<'a, D>(&self, cx: &AppContext) -> Vec<Selection<D>>
+    where
+        D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
+    {
+        let disjoint_anchors = &self.disjoint;
+        let mut disjoint =
+            resolve_multiple::<D, _>(disjoint_anchors.iter(), &self.buffer(cx)).peekable();
+
+        let mut pending_opt = self.pending::<D>(cx);
+
+        iter::from_fn(move || {
+            if let Some(pending) = pending_opt.as_mut() {
+                while let Some(next_selection) = disjoint.peek() {
+                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
+                        let next_selection = disjoint.next().unwrap();
+                        if next_selection.start < pending.start {
+                            pending.start = next_selection.start;
+                        }
+                        if next_selection.end > pending.end {
+                            pending.end = next_selection.end;
+                        }
+                    } else if next_selection.end < pending.start {
+                        return disjoint.next();
+                    } else {
+                        break;
+                    }
+                }
+
+                pending_opt.take()
+            } else {
+                disjoint.next()
+            }
+        })
+        .collect()
+    }
+
+    pub fn disjoint_in_range<'a, D>(
+        &self,
+        range: Range<Anchor>,
+        cx: &AppContext,
+    ) -> Vec<Selection<D>>
+    where
+        D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
+    {
+        let buffer = self.buffer(cx);
+        let start_ix = match self
+            .disjoint
+            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
+        {
+            Ok(ix) | Err(ix) => ix,
+        };
+        let end_ix = match self
+            .disjoint
+            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
+        {
+            Ok(ix) => ix + 1,
+            Err(ix) => ix,
+        };
+        resolve_multiple(&self.disjoint[start_ix..end_ix], &buffer).collect()
+    }
+
+    pub fn all_display(
+        &mut self,
+        cx: &mut MutableAppContext,
+    ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
+        let display_map = self.display_map(cx);
+        let selections = self
+            .all::<Point>(cx)
+            .into_iter()
+            .map(|selection| selection.map(|point| point.to_display_point(&display_map)))
+            .collect();
+        (display_map, selections)
+    }
+
+    pub fn newest_anchor(&self) -> &Selection<Anchor> {
+        self.pending
+            .as_ref()
+            .map(|s| &s.selection)
+            .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
+            .unwrap()
+    }
+
+    pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
+        &self,
+        cx: &AppContext,
+    ) -> Selection<D> {
+        resolve(self.newest_anchor(), &self.buffer(cx))
+    }
+
+    pub fn oldest_anchor(&self) -> &Selection<Anchor> {
+        self.disjoint
+            .iter()
+            .min_by_key(|s| s.id)
+            .or_else(|| self.pending.as_ref().map(|p| &p.selection))
+            .unwrap()
+    }
+
+    pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
+        &self,
+        cx: &AppContext,
+    ) -> Selection<D> {
+        resolve(self.oldest_anchor(), &self.buffer(cx))
+    }
+
+    pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
+        &self,
+        cx: &AppContext,
+    ) -> Selection<D> {
+        self.all(cx).first().unwrap().clone()
+    }
+
+    pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
+        &self,
+        cx: &AppContext,
+    ) -> Selection<D> {
+        self.all(cx).last().unwrap().clone()
+    }
+
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
+        &self,
+        cx: &AppContext,
+    ) -> Vec<Range<D>> {
+        self.all::<D>(cx)
+            .iter()
+            .map(|s| {
+                if s.reversed {
+                    s.end.clone()..s.start.clone()
+                } else {
+                    s.start.clone()..s.end.clone()
+                }
+            })
+            .collect()
+    }
+
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn display_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
+        let display_map = self.display_map(cx);
+        self.disjoint_anchors()
+            .iter()
+            .chain(self.pending_anchor().as_ref())
+            .map(|s| {
+                if s.reversed {
+                    s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
+                } else {
+                    s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
+                }
+            })
+            .collect()
+    }
+
+    pub fn build_columnar_selection(
+        &mut self,
+        display_map: &DisplaySnapshot,
+        row: u32,
+        columns: &Range<u32>,
+        reversed: bool,
+    ) -> Option<Selection<Point>> {
+        let is_empty = columns.start == columns.end;
+        let line_len = display_map.line_len(row);
+        if columns.start < line_len || (is_empty && columns.start == line_len) {
+            let start = DisplayPoint::new(row, columns.start);
+            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
+
+            Some(Selection {
+                id: post_inc(&mut self.next_selection_id),
+                start: start.to_point(display_map),
+                end: end.to_point(display_map),
+                reversed,
+                goal: SelectionGoal::ColumnRange {
+                    start: columns.start,
+                    end: columns.end,
+                },
+            })
+        } else {
+            None
+        }
+    }
+
+    pub(crate) fn change_with<R>(
+        &mut self,
+        cx: &mut MutableAppContext,
+        change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
+    ) -> R {
+        let mut mutable_collection = MutableSelectionsCollection {
+            collection: self,
+            cx,
+        };
+
+        let result = change(&mut mutable_collection);
+        assert!(
+            !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
+            "There must be at least one selection"
+        );
+        result
+    }
+}
+
+pub struct MutableSelectionsCollection<'a> {
+    collection: &'a mut SelectionsCollection,
+    cx: &'a mut MutableAppContext,
+}
+
+impl<'a> MutableSelectionsCollection<'a> {
+    fn display_map(&mut self) -> DisplaySnapshot {
+        self.collection.display_map(self.cx)
+    }
+
+    fn buffer(&self) -> Ref<MultiBufferSnapshot> {
+        self.collection.buffer(self.cx)
+    }
+
+    pub fn clear_disjoint(&mut self) {
+        self.collection.disjoint = Arc::from([]);
+    }
+
+    pub fn delete(&mut self, selection_id: usize) {
+        self.collection.disjoint = self
+            .disjoint
+            .into_iter()
+            .filter(|selection| selection.id != selection_id)
+            .cloned()
+            .collect();
+    }
+
+    pub fn clear_pending(&mut self) {
+        self.collection.pending = None;
+    }
+
+    pub fn set_pending_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
+        self.collection.pending = Some(PendingSelection {
+            selection: Selection {
+                id: post_inc(&mut self.collection.next_selection_id),
+                start: range.start,
+                end: range.end,
+                reversed: false,
+                goal: SelectionGoal::None,
+            },
+            mode,
+        })
+    }
+
+    pub fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
+        self.collection.pending = Some(PendingSelection { selection, mode });
+    }
+
+    pub fn try_cancel(&mut self) -> bool {
+        if let Some(pending) = self.collection.pending.take() {
+            if self.disjoint.is_empty() {
+                self.collection.disjoint = Arc::from([pending.selection]);
+            }
+            return true;
+        }
+
+        let mut oldest = self.oldest_anchor().clone();
+        if self.count() > 1 {
+            self.collection.disjoint = Arc::from([oldest]);
+            return true;
+        }
+
+        if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
+            let head = oldest.head();
+            oldest.start = head.clone();
+            oldest.end = head;
+            self.collection.disjoint = Arc::from([oldest]);
+            return true;
+        }
+
+        return false;
+    }
+
+    pub fn reset_biases(&mut self) {
+        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        self.collection.disjoint = self
+            .collection
+            .disjoint
+            .into_iter()
+            .cloned()
+            .map(|selection| reset_biases(selection, &buffer))
+            .collect();
+
+        if let Some(pending) = self.collection.pending.as_mut() {
+            pending.selection = reset_biases(pending.selection.clone(), &buffer);
+        }
+    }
+
+    pub fn insert_range<T>(&mut self, range: Range<T>)
+    where
+        T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
+    {
+        let mut selections = self.all(self.cx);
+        let mut start = range.start.to_offset(&self.buffer());
+        let mut end = range.end.to_offset(&self.buffer());
+        let reversed = if start > end {
+            mem::swap(&mut start, &mut end);
+            true
+        } else {
+            false
+        };
+        selections.push(Selection {
+            id: post_inc(&mut self.collection.next_selection_id),
+            start,
+            end,
+            reversed,
+            goal: SelectionGoal::None,
+        });
+        self.select(selections);
+    }
+
+    pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
+    where
+        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
+    {
+        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        selections.sort_unstable_by_key(|s| s.start);
+        // Merge overlapping selections.
+        let mut i = 1;
+        while i < selections.len() {
+            if selections[i - 1].end >= selections[i].start {
+                let removed = selections.remove(i);
+                if removed.start < selections[i - 1].start {
+                    selections[i - 1].start = removed.start;
+                }
+                if removed.end > selections[i - 1].end {
+                    selections[i - 1].end = removed.end;
+                }
+            } else {
+                i += 1;
+            }
+        }
+
+        self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
+            let end_bias = if selection.end > selection.start {
+                Bias::Left
+            } else {
+                Bias::Right
+            };
+            Selection {
+                id: selection.id,
+                start: buffer.anchor_after(selection.start),
+                end: buffer.anchor_at(selection.end, end_bias),
+                reversed: selection.reversed,
+                goal: selection.goal,
+            }
+        }));
+
+        self.collection.pending = None;
+    }
+
+    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
+        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        let resolved_selections =
+            resolve_multiple::<usize, _>(&selections, &buffer).collect::<Vec<_>>();
+        self.select(resolved_selections);
+    }
+
+    pub fn select_ranges<I, T>(&mut self, ranges: I)
+    where
+        I: IntoIterator<Item = Range<T>>,
+        T: ToOffset,
+    {
+        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        let selections = ranges
+            .into_iter()
+            .map(|range| {
+                let mut start = range.start.to_offset(&buffer);
+                let mut end = range.end.to_offset(&buffer);
+                let reversed = if start > end {
+                    mem::swap(&mut start, &mut end);
+                    true
+                } else {
+                    false
+                };
+                Selection {
+                    id: post_inc(&mut self.collection.next_selection_id),
+                    start,
+                    end,
+                    reversed,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect::<Vec<_>>();
+
+        self.select(selections)
+    }
+
+    pub fn select_anchor_ranges<I: IntoIterator<Item = Range<Anchor>>>(&mut self, ranges: I) {
+        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        let selections = ranges
+            .into_iter()
+            .map(|range| {
+                let mut start = range.start;
+                let mut end = range.end;
+                let reversed = if start.cmp(&end, &buffer).is_gt() {
+                    mem::swap(&mut start, &mut end);
+                    true
+                } else {
+                    false
+                };
+                Selection {
+                    id: post_inc(&mut self.collection.next_selection_id),
+                    start,
+                    end,
+                    reversed,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect::<Vec<_>>();
+
+        self.select_anchors(selections)
+    }
+
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn select_display_ranges<T>(&mut self, ranges: T)
+    where
+        T: IntoIterator<Item = Range<DisplayPoint>>,
+    {
+        let display_map = self.display_map();
+        let selections = ranges
+            .into_iter()
+            .map(|range| {
+                let mut start = range.start;
+                let mut end = range.end;
+                let reversed = if start > end {
+                    mem::swap(&mut start, &mut end);
+                    true
+                } else {
+                    false
+                };
+                Selection {
+                    id: post_inc(&mut self.collection.next_selection_id),
+                    start: start.to_point(&display_map),
+                    end: end.to_point(&display_map),
+                    reversed,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect();
+        self.select(selections);
+    }
+
+    pub fn move_with(
+        &mut self,
+        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
+    ) {
+        let display_map = self.display_map();
+        let selections = self
+            .all::<Point>(self.cx)
+            .into_iter()
+            .map(|selection| {
+                let mut selection = selection.map(|point| point.to_display_point(&display_map));
+                move_selection(&display_map, &mut selection);
+                selection.map(|display_point| display_point.to_point(&display_map))
+            })
+            .collect();
+
+        self.select(selections)
+    }
+
+    pub fn move_heads_with(
+        &mut self,
+        mut update_head: impl FnMut(
+            &DisplaySnapshot,
+            DisplayPoint,
+            SelectionGoal,
+        ) -> (DisplayPoint, SelectionGoal),
+    ) {
+        self.move_with(|map, selection| {
+            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
+            selection.set_head(new_head, new_goal);
+        });
+    }
+
+    pub fn move_cursors_with(
+        &mut self,
+        mut update_cursor_position: impl FnMut(
+            &DisplaySnapshot,
+            DisplayPoint,
+            SelectionGoal,
+        ) -> (DisplayPoint, SelectionGoal),
+    ) {
+        self.move_with(|map, selection| {
+            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
+            selection.collapse_to(cursor, new_goal)
+        });
+    }
+
+    pub fn replace_cursors_with(
+        &mut self,
+        mut find_replacement_cursors: impl FnMut(&DisplaySnapshot) -> Vec<DisplayPoint>,
+    ) {
+        let display_map = self.display_map();
+        let new_selections = find_replacement_cursors(&display_map)
+            .into_iter()
+            .map(|cursor| {
+                let cursor_point = cursor.to_point(&display_map);
+                Selection {
+                    id: post_inc(&mut self.collection.next_selection_id),
+                    start: cursor_point,
+                    end: cursor_point,
+                    reversed: false,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect();
+        self.select(new_selections);
+    }
+
+    /// Compute new ranges for any selections that were located in excerpts that have
+    /// since been removed.
+    ///
+    /// Returns a `HashMap` indicating which selections whose former head position
+    /// was no longer present. The keys of the map are selection ids. The values are
+    /// the id of the new excerpt where the head of the selection has been moved.
+    pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
+        let mut pending = self.collection.pending.take();
+        let mut selections_with_lost_position = HashMap::default();
+
+        let anchors_with_status = {
+            let buffer = self.buffer();
+            let disjoint_anchors = self
+                .disjoint
+                .iter()
+                .flat_map(|selection| [&selection.start, &selection.end]);
+            buffer.refresh_anchors(disjoint_anchors)
+        };
+        let adjusted_disjoint: Vec<_> = anchors_with_status
+            .chunks(2)
+            .map(|selection_anchors| {
+                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
+                let (_, end, kept_end) = selection_anchors[1].clone();
+                let selection = &self.disjoint[anchor_ix / 2];
+                let kept_head = if selection.reversed {
+                    kept_start
+                } else {
+                    kept_end
+                };
+                if !kept_head {
+                    selections_with_lost_position
+                        .insert(selection.id, selection.head().excerpt_id.clone());
+                }
+
+                Selection {
+                    id: selection.id,
+                    start,
+                    end,
+                    reversed: selection.reversed,
+                    goal: selection.goal,
+                }
+            })
+            .collect();
+
+        if !adjusted_disjoint.is_empty() {
+            let resolved_selections =
+                resolve_multiple(adjusted_disjoint.iter(), &self.buffer()).collect();
+            self.select::<usize>(resolved_selections);
+        }
+
+        if let Some(pending) = pending.as_mut() {
+            let buffer = self.buffer();
+            let anchors =
+                buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
+            let (_, start, kept_start) = anchors[0].clone();
+            let (_, end, kept_end) = anchors[1].clone();
+            let kept_head = if pending.selection.reversed {
+                kept_start
+            } else {
+                kept_end
+            };
+            if !kept_head {
+                selections_with_lost_position.insert(
+                    pending.selection.id,
+                    pending.selection.head().excerpt_id.clone(),
+                );
+            }
+
+            pending.selection.start = start;
+            pending.selection.end = end;
+        }
+        self.collection.pending = pending;
+
+        selections_with_lost_position
+    }
+}
+
+impl<'a> Deref for MutableSelectionsCollection<'a> {
+    type Target = SelectionsCollection;
+    fn deref(&self) -> &Self::Target {
+        self.collection
+    }
+}
+
+// Panics if passed selections are not in order
+pub fn resolve_multiple<'a, D, I>(
+    selections: I,
+    snapshot: &MultiBufferSnapshot,
+) -> impl 'a + Iterator<Item = Selection<D>>
+where
+    D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
+    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
+{
+    let (to_summarize, selections) = selections.into_iter().tee();
+    let mut summaries = snapshot
+        .summaries_for_anchors::<D, _>(
+            to_summarize
+                .flat_map(|s| [&s.start, &s.end])
+                .collect::<Vec<_>>(),
+        )
+        .into_iter();
+    selections.map(move |s| Selection {
+        id: s.id,
+        start: summaries.next().unwrap(),
+        end: summaries.next().unwrap(),
+        reversed: s.reversed,
+        goal: s.goal,
+    })
+}
+
+fn resolve<D: TextDimension + Ord + Sub<D, Output = D>>(
+    selection: &Selection<Anchor>,
+    buffer: &MultiBufferSnapshot,
+) -> Selection<D> {
+    selection.map(|p| p.summary::<D>(&buffer))
+}
+
+fn reset_biases(
+    mut selection: Selection<Anchor>,
+    buffer: &MultiBufferSnapshot,
+) -> Selection<Anchor> {
+    let end_bias = if selection.end.to_offset(buffer) > selection.start.to_offset(buffer) {
+        Bias::Left
+    } else {
+        Bias::Right
+    };
+    selection.start = buffer.anchor_after(selection.start);
+    selection.end = buffer.anchor_at(selection.end, end_bias);
+    selection
+}

crates/editor/src/test.rs 🔗

@@ -43,7 +43,7 @@ pub fn marked_display_snapshot(
 pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
     let (umarked_text, text_ranges) = marked_text_ranges(marked_text);
     assert_eq!(editor.text(cx), umarked_text);
-    editor.select_ranges(text_ranges, None, cx);
+    editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
 }
 
 pub fn assert_text_with_selections(
@@ -54,5 +54,5 @@ pub fn assert_text_with_selections(
     let (unmarked_text, text_ranges) = marked_text_ranges(marked_text);
 
     assert_eq!(editor.text(cx), unmarked_text);
-    assert_eq!(editor.selected_ranges(cx), text_ranges);
+    assert_eq!(editor.selections.ranges(cx), text_ranges);
 }

crates/go_to_line/src/go_to_line.rs 🔗

@@ -40,10 +40,10 @@ impl GoToLine {
 
         let (scroll_position, cursor_point, max_point) = active_editor.update(cx, |editor, cx| {
             let scroll_position = editor.scroll_position(cx);
-            let buffer = editor.buffer().read(cx).read(cx);
+            let buffer = editor.buffer().read(cx).snapshot(cx);
             (
                 Some(scroll_position),
-                editor.newest_selection_with_snapshot(&buffer).head(),
+                editor.selections.newest(cx).head(),
                 buffer.max_point(),
             )
         });
@@ -80,7 +80,9 @@ impl GoToLine {
             if let Some(rows) = active_editor.highlighted_rows() {
                 let snapshot = active_editor.snapshot(cx).display_snapshot;
                 let position = DisplayPoint::new(rows.start, 0).to_point(&snapshot);
-                active_editor.select_ranges([position..position], Some(Autoscroll::Center), cx);
+                active_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                    s.select_ranges([position..position])
+                });
             }
         });
         cx.emit(Event::Dismissed);
@@ -106,7 +108,7 @@ impl GoToLine {
         match event {
             editor::Event::Blurred => cx.emit(Event::Dismissed),
             editor::Event::BufferEdited { .. } => {
-                let line_editor = self.line_editor.read(cx).buffer().read(cx).read(cx).text();
+                let line_editor = self.line_editor.read(cx).text(cx);
                 let mut components = line_editor.trim().split(&[',', ':'][..]);
                 let row = components.next().and_then(|row| row.parse::<u32>().ok());
                 let column = components.next().and_then(|row| row.parse::<u32>().ok());

crates/gpui/src/app.rs 🔗

@@ -1005,6 +1005,13 @@ impl MutableAppContext {
             .and_then(|window| window.root_view.clone().downcast::<T>())
     }
 
+    pub fn window_is_active(&self, window_id: usize) -> bool {
+        self.cx
+            .windows
+            .get(&window_id)
+            .map_or(false, |window| window.is_active)
+    }
+
     pub fn render_view(
         &mut self,
         window_id: usize,

crates/gpui/src/presenter.rs 🔗

@@ -122,8 +122,10 @@ impl Presenter {
             self.text_layout_cache.finish_frame();
             self.cursor_styles = scene.cursor_styles();
 
-            if let Some(event) = self.last_mouse_moved_event.clone() {
-                self.dispatch_event(event, cx)
+            if cx.window_is_active(self.window_id) {
+                if let Some(event) = self.last_mouse_moved_event.clone() {
+                    self.dispatch_event(event, cx)
+                }
             }
         } else {
             log::error!("could not find root_view_id for window {}", self.window_id);

crates/journal/src/journal.rs 🔗

@@ -56,8 +56,10 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
             if let Some(Some(Ok(item))) = opened.first() {
                 if let Some(editor) = item.downcast::<Editor>() {
                     editor.update(&mut cx, |editor, cx| {
-                        let len = editor.buffer().read(cx).read(cx).len();
-                        editor.select_ranges([len..len], Some(Autoscroll::Center), cx);
+                        let len = editor.buffer().read(cx).len(cx);
+                        editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                            s.select_ranges([len..len])
+                        });
                         if len > 0 {
                             editor.insert("\n\n", cx);
                         }

crates/outline/src/outline.rs 🔗

@@ -84,7 +84,7 @@ impl OutlineView {
                 .read(cx)
                 .buffer()
                 .read(cx)
-                .read(cx)
+                .snapshot(cx)
                 .outline(Some(cx.global::<Settings>().theme.editor.syntax.as_ref()));
             if let Some(outline) = buffer {
                 workspace.toggle_modal(cx, |_, cx| {
@@ -171,10 +171,8 @@ impl PickerDelegate for OutlineView {
                 .collect();
 
             let editor = self.active_editor.read(cx);
-            let buffer = editor.buffer().read(cx).read(cx);
-            let cursor_offset = editor
-                .newest_selection_with_snapshot::<usize>(&buffer)
-                .head();
+            let cursor_offset = editor.selections.newest::<usize>(cx).head();
+            let buffer = editor.buffer().read(cx).snapshot(cx);
             selected_index = self
                 .outline
                 .items
@@ -217,7 +215,9 @@ impl PickerDelegate for OutlineView {
             if let Some(rows) = active_editor.highlighted_rows() {
                 let snapshot = active_editor.snapshot(cx).display_snapshot;
                 let position = DisplayPoint::new(rows.start, 0).to_point(&snapshot);
-                active_editor.select_ranges([position..position], Some(Autoscroll::Center), cx);
+                active_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                    s.select_ranges([position..position])
+                });
             }
         });
         cx.emit(Event::Dismissed);

crates/project_symbols/src/project_symbols.rs 🔗

@@ -145,11 +145,9 @@ impl ProjectSymbolsView {
 
                         let editor = workspace.open_project_item::<Editor>(buffer, cx);
                         editor.update(cx, |editor, cx| {
-                            editor.select_ranges(
-                                [position..position],
-                                Some(Autoscroll::Center),
-                                cx,
-                            );
+                            editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                                s.select_ranges([position..position])
+                            });
                         });
                     });
                     Ok::<_, anyhow::Error>(())

crates/rpc/Cargo.toml 🔗

@@ -21,13 +21,13 @@ async-lock = "2.4"
 async-tungstenite = "0.16"
 base64 = "0.13"
 futures = "0.3"
-log = { version = "0.4.16", features = ["kv_unstable_serde"] }
 parking_lot = "0.11.1"
 prost = "0.8"
 rand = "0.8"
 rsa = "0.4"
 serde = { version = "1", features = ["derive"] }
 smol-timeout = "0.6"
+tracing = { version = "0.1.34", features = ["log"] }
 zstd = "0.9"
 
 [build-dependencies]

crates/rpc/src/peer.rs 🔗

@@ -22,6 +22,7 @@ use std::{
     },
     time::Duration,
 };
+use tracing::instrument;
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct ConnectionId(pub u32);
@@ -108,6 +109,7 @@ impl Peer {
         })
     }
 
+    #[instrument(skip_all)]
     pub async fn add_connection<F, Fut, Out>(
         self: &Arc<Self>,
         connection: Connection,
@@ -145,9 +147,12 @@ impl Peer {
         let this = self.clone();
         let response_channels = connection_state.response_channels.clone();
         let handle_io = async move {
+            tracing::debug!(%connection_id, "handle io future: start");
+
             let _end_connection = util::defer(|| {
                 response_channels.lock().take();
                 this.connections.write().remove(&connection_id);
+                tracing::debug!(%connection_id, "handle io future: end");
             });
 
             // Send messages on this frequency so the connection isn't closed.
@@ -159,49 +164,68 @@ impl Peer {
             futures::pin_mut!(receive_timeout);
 
             loop {
+                tracing::debug!(%connection_id, "outer loop iteration start");
                 let read_message = reader.read().fuse();
                 futures::pin_mut!(read_message);
 
                 loop {
+                    tracing::debug!(%connection_id, "inner loop iteration start");
                     futures::select_biased! {
                         outgoing = outgoing_rx.next().fuse() => match outgoing {
                             Some(outgoing) => {
+                                tracing::debug!(%connection_id, "outgoing rpc message: writing");
                                 if let Some(result) = writer.write(outgoing).timeout(WRITE_TIMEOUT).await {
+                                    tracing::debug!(%connection_id, "outgoing rpc message: done writing");
                                     result.context("failed to write RPC message")?;
+                                    tracing::debug!(%connection_id, "keepalive interval: resetting after sending message");
                                     keepalive_timer.set(create_timer(KEEPALIVE_INTERVAL).fuse());
                                 } else {
+                                    tracing::debug!(%connection_id, "outgoing rpc message: writing timed out");
                                     Err(anyhow!("timed out writing message"))?;
                                 }
                             }
                             None => {
-                                log::info!("outgoing channel closed");
+                                tracing::debug!(%connection_id, "outgoing rpc message: channel closed");
                                 return Ok(())
                             },
                         },
                         incoming = read_message => {
-                            let incoming = incoming.context("received invalid RPC message")?;
+                            let incoming = incoming.context("error reading rpc message from socket")?;
+                            tracing::debug!(%connection_id, "incoming rpc message: received");
+                            tracing::debug!(%connection_id, "receive timeout: resetting");
                             receive_timeout.set(create_timer(RECEIVE_TIMEOUT).fuse());
                             if let proto::Message::Envelope(incoming) = incoming {
+                                tracing::debug!(%connection_id, "incoming rpc message: processing");
                                 match incoming_tx.send(incoming).timeout(RECEIVE_TIMEOUT).await {
-                                    Some(Ok(_)) => {},
+                                    Some(Ok(_)) => {
+                                        tracing::debug!(%connection_id, "incoming rpc message: processed");
+                                    },
                                     Some(Err(_)) => {
-                                        log::info!("incoming channel closed");
+                                        tracing::debug!(%connection_id, "incoming rpc message: channel closed");
                                         return Ok(())
                                     },
-                                    None => Err(anyhow!("timed out processing incoming message"))?,
+                                    None => {
+                                        tracing::debug!(%connection_id, "incoming rpc message: processing timed out");
+                                        Err(anyhow!("timed out processing incoming message"))?
+                                    },
                                 }
                             }
                             break;
                         },
                         _ = keepalive_timer => {
+                            tracing::debug!(%connection_id, "keepalive interval: pinging");
                             if let Some(result) = writer.write(proto::Message::Ping).timeout(WRITE_TIMEOUT).await {
+                                tracing::debug!(%connection_id, "keepalive interval: done pinging");
                                 result.context("failed to send keepalive")?;
+                                tracing::debug!(%connection_id, "keepalive interval: resetting after pinging");
                                 keepalive_timer.set(create_timer(KEEPALIVE_INTERVAL).fuse());
                             } else {
+                                tracing::debug!(%connection_id, "keepalive interval: pinging timed out");
                                 Err(anyhow!("timed out sending keepalive"))?;
                             }
                         }
                         _ = receive_timeout => {
+                            tracing::debug!(%connection_id, "receive timeout: delay between messages too long");
                             Err(anyhow!("delay between messages too long"))?
                         }
                     }
@@ -217,25 +241,71 @@ impl Peer {
         let incoming_rx = incoming_rx.filter_map(move |incoming| {
             let response_channels = response_channels.clone();
             async move {
+                let message_id = incoming.id;
+                tracing::debug!(?incoming, "incoming message future: start");
+                let _end = util::defer(move || {
+                    tracing::debug!(
+                        %connection_id,
+                        message_id,
+                        "incoming message future: end"
+                    );
+                });
+
                 if let Some(responding_to) = incoming.responding_to {
+                    tracing::debug!(
+                        %connection_id,
+                        message_id,
+                        responding_to,
+                        "incoming response: received"
+                    );
                     let channel = response_channels.lock().as_mut()?.remove(&responding_to);
                     if let Some(tx) = channel {
                         let requester_resumed = oneshot::channel();
                         if let Err(error) = tx.send((incoming, requester_resumed.0)) {
-                            log::debug!(
-                                "received RPC but request future was dropped {:?}",
-                                error.0
+                            tracing::debug!(
+                                %connection_id,
+                                message_id,
+                                responding_to = responding_to,
+                                ?error,
+                                "incoming response: request future dropped",
                             );
                         }
+
+                        tracing::debug!(
+                            %connection_id,
+                            message_id,
+                            responding_to,
+                            "incoming response: waiting to resume requester"
+                        );
                         let _ = requester_resumed.1.await;
+                        tracing::debug!(
+                            %connection_id,
+                            message_id,
+                            responding_to,
+                            "incoming response: requester resumed"
+                        );
                     } else {
-                        log::warn!("received RPC response to unknown request {}", responding_to);
+                        tracing::warn!(
+                            %connection_id,
+                            message_id,
+                            responding_to,
+                            "incoming response: unknown request"
+                        );
                     }
 
                     None
                 } else {
+                    tracing::debug!(
+                        %connection_id,
+                        message_id,
+                        "incoming message: received"
+                    );
                     proto::build_typed_envelope(connection_id, incoming).or_else(|| {
-                        log::error!("unable to construct a typed envelope");
+                        tracing::error!(
+                            %connection_id,
+                            message_id,
+                            "unable to construct a typed envelope"
+                        );
                         None
                     })
                 }

crates/search/src/buffer_search.rs 🔗

@@ -225,9 +225,7 @@ impl BufferSearchBar {
         let display_map = editor
             .update(cx, |editor, cx| editor.snapshot(cx))
             .display_snapshot;
-        let selection = editor
-            .read(cx)
-            .newest_selection_with_snapshot::<usize>(&display_map.buffer_snapshot);
+        let selection = editor.read(cx).selections.newest::<usize>(cx);
 
         let mut text: String;
         if selection.start == selection.end {
@@ -267,7 +265,7 @@ impl BufferSearchBar {
     fn set_query(&mut self, query: &str, cx: &mut ViewContext<Self>) {
         self.query_editor.update(cx, |query_editor, cx| {
             query_editor.buffer().update(cx, |query_buffer, cx| {
-                let len = query_buffer.read(cx).len();
+                let len = query_buffer.len(cx);
                 query_buffer.edit([(0..len, query)], cx);
             });
         });
@@ -387,14 +385,16 @@ impl BufferSearchBar {
                     if let Some(ranges) = self.editors_with_matches.get(&cx.weak_handle()) {
                         let new_index = match_index_for_direction(
                             ranges,
-                            &editor.newest_anchor_selection().head(),
+                            &editor.selections.newest_anchor().head(),
                             index,
                             direction,
-                            &editor.buffer().read(cx).read(cx),
+                            &editor.buffer().read(cx).snapshot(cx),
                         );
                         let range_to_select = ranges[new_index].clone();
                         editor.unfold_ranges([range_to_select.clone()], false, cx);
-                        editor.select_ranges([range_to_select], Some(Autoscroll::Fit), cx);
+                        editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                            s.select_ranges([range_to_select])
+                        });
                     }
                 });
             }
@@ -535,10 +535,10 @@ impl BufferSearchBar {
                                 editor.update(cx, |editor, cx| {
                                     if select_closest_match {
                                         if let Some(match_ix) = this.active_match_index {
-                                            editor.select_ranges(
-                                                [ranges[match_ix].clone()],
+                                            editor.change_selections(
                                                 Some(Autoscroll::Fit),
                                                 cx,
+                                                |s| s.select_ranges([ranges[match_ix].clone()]),
                                             );
                                         }
                                     }
@@ -564,8 +564,8 @@ impl BufferSearchBar {
             let editor = editor.read(cx);
             active_match_index(
                 &ranges,
-                &editor.newest_anchor_selection().head(),
-                &editor.buffer().read(cx).read(cx),
+                &editor.selections.newest_anchor().head(),
+                &editor.buffer().read(cx).snapshot(cx),
             )
         });
         if new_index != self.active_match_index {
@@ -721,13 +721,15 @@ mod tests {
         });
 
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(0));
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
             );
         });
@@ -738,7 +740,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
             );
         });
@@ -749,7 +751,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
             );
         });
@@ -760,7 +762,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
             );
         });
@@ -771,7 +773,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
             );
         });
@@ -782,7 +784,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
             );
         });
@@ -793,7 +795,7 @@ mod tests {
         search_bar.update(cx, |search_bar, cx| {
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
             );
         });
@@ -804,13 +806,15 @@ mod tests {
         // Park the cursor in between matches and ensure that going to the previous match selects
         // the closest match to the left.
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(1));
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
             );
         });
@@ -821,13 +825,15 @@ mod tests {
         // Park the cursor in between matches and ensure that going to the next match selects the
         // closest match to the right.
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(1));
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)]
             );
         });
@@ -838,13 +844,15 @@ mod tests {
         // Park the cursor after the last match and ensure that going to the previous match selects
         // the last match.
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(2));
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
             );
         });
@@ -855,13 +863,15 @@ mod tests {
         // Park the cursor after the last match and ensure that going to the next match selects the
         // first match.
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(2));
             search_bar.select_next_match(&SelectNextMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)]
             );
         });
@@ -872,13 +882,15 @@ mod tests {
         // Park the cursor before the first match and ensure that going to the previous match
         // selects the last match.
         editor.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
+            });
         });
         search_bar.update(cx, |search_bar, cx| {
             assert_eq!(search_bar.active_match_index, Some(0));
             search_bar.select_prev_match(&SelectPrevMatch, cx);
             assert_eq!(
-                editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)]
             );
         });

crates/search/src/project_search.rs 🔗

@@ -454,15 +454,17 @@ impl ProjectSearchView {
             let results_editor = self.results_editor.read(cx);
             let new_index = match_index_for_direction(
                 &model.match_ranges,
-                &results_editor.newest_anchor_selection().head(),
+                &results_editor.selections.newest_anchor().head(),
                 index,
                 direction,
-                &results_editor.buffer().read(cx).read(cx),
+                &results_editor.buffer().read(cx).snapshot(cx),
             );
             let range_to_select = model.match_ranges[new_index].clone();
             self.results_editor.update(cx, |editor, cx| {
                 editor.unfold_ranges([range_to_select.clone()], false, cx);
-                editor.select_ranges([range_to_select], Some(Autoscroll::Fit), cx);
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_ranges([range_to_select])
+                });
             });
         }
     }
@@ -476,8 +478,8 @@ impl ProjectSearchView {
 
     fn focus_results_editor(&self, cx: &mut ViewContext<Self>) {
         self.query_editor.update(cx, |query_editor, cx| {
-            let cursor = query_editor.newest_anchor_selection().head();
-            query_editor.select_ranges([cursor.clone()..cursor], None, cx);
+            let cursor = query_editor.selections.newest_anchor().head();
+            query_editor.change_selections(None, cx, |s| s.select_ranges([cursor.clone()..cursor]));
         });
         cx.focus(&self.results_editor);
     }
@@ -489,7 +491,9 @@ impl ProjectSearchView {
         } else {
             self.results_editor.update(cx, |editor, cx| {
                 if reset_selections {
-                    editor.select_ranges(match_ranges.first().cloned(), Some(Autoscroll::Fit), cx);
+                    editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                        s.select_ranges(match_ranges.first().cloned())
+                    });
                 }
                 editor.highlight_background::<Self>(
                     match_ranges,
@@ -510,8 +514,8 @@ impl ProjectSearchView {
         let results_editor = self.results_editor.read(cx);
         let new_index = active_match_index(
             &self.model.read(cx).match_ranges,
-            &results_editor.newest_anchor_selection().head(),
-            &results_editor.buffer().read(cx).read(cx),
+            &results_editor.selections.newest_anchor().head(),
+            &results_editor.buffer().read(cx).snapshot(cx),
         );
         if self.active_match_index != new_index {
             self.active_match_index = new_index;
@@ -887,7 +891,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(2, 32)..DisplayPoint::new(2, 35)]
             );
 
@@ -899,7 +903,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(2, 37)..DisplayPoint::new(2, 40)]
             );
             search_view.select_match(Direction::Next, cx);
@@ -910,7 +914,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(5, 6)..DisplayPoint::new(5, 9)]
             );
             search_view.select_match(Direction::Next, cx);
@@ -921,7 +925,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(2, 32)..DisplayPoint::new(2, 35)]
             );
             search_view.select_match(Direction::Prev, cx);
@@ -932,7 +936,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(5, 6)..DisplayPoint::new(5, 9)]
             );
             search_view.select_match(Direction::Prev, cx);
@@ -943,7 +947,7 @@ mod tests {
             assert_eq!(
                 search_view
                     .results_editor
-                    .update(cx, |editor, cx| editor.selected_display_ranges(cx)),
+                    .update(cx, |editor, cx| editor.selections.display_ranges(cx)),
                 [DisplayPoint::new(2, 37)..DisplayPoint::new(2, 40)]
             );
         });

crates/theme/src/theme.rs 🔗

@@ -12,7 +12,7 @@ use std::{collections::HashMap, sync::Arc};
 
 pub use theme_registry::*;
 
-pub const DEFAULT_THEME_NAME: &'static str = "dark";
+pub const DEFAULT_THEME_NAME: &'static str = "cave-dark";
 
 #[derive(Deserialize, Default)]
 pub struct Theme {

crates/vim/src/insert.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{state::Mode, Vim};
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::{actions, MutableAppContext, ViewContext};
 use language::SelectionGoal;
 use workspace::Workspace;
@@ -13,9 +13,11 @@ pub fn init(cx: &mut MutableAppContext) {
 fn normal_before(_: &mut Workspace, _: &NormalBefore, cx: &mut ViewContext<Workspace>) {
     Vim::update(cx, |state, cx| {
         state.update_active_editor(cx, |editor, cx| {
-            editor.move_cursors(cx, |map, mut cursor, _| {
-                *cursor.column_mut() = cursor.column().saturating_sub(1);
-                (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_cursors_with(|map, mut cursor, _| {
+                    *cursor.column_mut() = cursor.column().saturating_sub(1);
+                    (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
+                });
             });
         });
         state.switch_mode(Mode::Normal, cx);

crates/vim/src/normal.rs 🔗

@@ -8,7 +8,7 @@ use crate::{
 };
 use change::init as change_init;
 use collections::HashSet;
-use editor::{Bias, DisplayPoint};
+use editor::{Autoscroll, Bias, DisplayPoint};
 use gpui::{actions, MutableAppContext, ViewContext};
 use language::SelectionGoal;
 use workspace::Workspace;
@@ -76,7 +76,9 @@ pub fn normal_motion(motion: Motion, cx: &mut MutableAppContext) {
 
 fn move_cursor(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
     vim.update_active_editor(cx, |editor, cx| {
-        editor.move_cursors(cx, |map, cursor, goal| motion.move_point(map, cursor, goal))
+        editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.move_cursors_with(|map, cursor, goal| motion.move_point(map, cursor, goal))
+        })
     });
 }
 
@@ -84,8 +86,10 @@ fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext<Workspa
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.move_cursors(cx, |map, cursor, goal| {
-                Motion::Right.move_point(map, cursor, goal)
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_cursors_with(|map, cursor, goal| {
+                    Motion::Right.move_point(map, cursor, goal)
+                });
             });
         });
     });
@@ -99,8 +103,10 @@ fn insert_first_non_whitespace(
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.move_cursors(cx, |map, cursor, goal| {
-                Motion::FirstNonWhitespace.move_point(map, cursor, goal)
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_cursors_with(|map, cursor, goal| {
+                    Motion::FirstNonWhitespace.move_point(map, cursor, goal)
+                });
             });
         });
     });
@@ -110,8 +116,10 @@ fn insert_end_of_line(_: &mut Workspace, _: &InsertEndOfLine, cx: &mut ViewConte
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.move_cursors(cx, |map, cursor, goal| {
-                Motion::EndOfLine.move_point(map, cursor, goal)
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_cursors_with(|map, cursor, goal| {
+                    Motion::EndOfLine.move_point(map, cursor, goal)
+                });
             });
         });
     });
@@ -122,7 +130,7 @@ fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContex
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
             editor.transact(cx, |editor, cx| {
-                let (map, old_selections) = editor.display_selections(cx);
+                let (map, old_selections) = editor.selections.all_display(cx);
                 let selection_start_rows: HashSet<u32> = old_selections
                     .into_iter()
                     .map(|selection| selection.start.row())
@@ -137,10 +145,12 @@ fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContex
                     (start_of_line..start_of_line, new_text)
                 });
                 editor.edit_with_autoindent(edits, cx);
-                editor.move_cursors(cx, |map, mut cursor, _| {
-                    *cursor.row_mut() -= 1;
-                    *cursor.column_mut() = map.line_len(cursor.row());
-                    (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.move_cursors_with(|map, mut cursor, _| {
+                        *cursor.row_mut() -= 1;
+                        *cursor.column_mut() = map.line_len(cursor.row());
+                        (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
+                    });
                 });
             });
         });
@@ -152,7 +162,7 @@ fn insert_line_below(_: &mut Workspace, _: &InsertLineBelow, cx: &mut ViewContex
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
             editor.transact(cx, |editor, cx| {
-                let (map, old_selections) = editor.display_selections(cx);
+                let (map, old_selections) = editor.selections.all_display(cx);
                 let selection_end_rows: HashSet<u32> = old_selections
                     .into_iter()
                     .map(|selection| selection.end.row())
@@ -166,8 +176,10 @@ fn insert_line_below(_: &mut Workspace, _: &InsertLineBelow, cx: &mut ViewContex
                     new_text.push_str(&" ".repeat(indent as usize));
                     (end_of_line..end_of_line, new_text)
                 });
-                editor.move_cursors(cx, |map, cursor, goal| {
-                    Motion::EndOfLine.move_point(map, cursor, goal)
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.move_cursors_with(|map, cursor, goal| {
+                        Motion::EndOfLine.move_point(map, cursor, goal)
+                    });
                 });
                 editor.edit_with_autoindent(edits, cx);
             });

crates/vim/src/normal/change.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{motion::Motion, state::Mode, Vim};
-use editor::{char_kind, movement};
+use editor::{char_kind, movement, Autoscroll};
 use gpui::{impl_actions, MutableAppContext, ViewContext};
 use serde::Deserialize;
 use workspace::Workspace;
@@ -22,8 +22,10 @@ pub fn change_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
         editor.transact(cx, |editor, cx| {
             // We are swapping to insert mode anyway. Just set the line end clipping behavior now
             editor.set_clip_at_line_ends(false, cx);
-            editor.move_selections(cx, |map, selection| {
-                motion.expand_selection(map, selection, false);
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    motion.expand_selection(map, selection, false);
+                });
             });
             editor.insert(&"", cx);
         });
@@ -46,16 +48,21 @@ fn change_word(
             editor.transact(cx, |editor, cx| {
                 // We are swapping to insert mode anyway. Just set the line end clipping behavior now
                 editor.set_clip_at_line_ends(false, cx);
-                editor.move_selections(cx, |map, selection| {
-                    if selection.end.column() == map.line_len(selection.end.row()) {
-                        return;
-                    }
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.move_with(|map, selection| {
+                        if selection.end.column() == map.line_len(selection.end.row()) {
+                            return;
+                        }
 
-                    selection.end = movement::find_boundary(map, selection.end, |left, right| {
-                        let left_kind = char_kind(left).coerce_punctuation(ignore_punctuation);
-                        let right_kind = char_kind(right).coerce_punctuation(ignore_punctuation);
+                        selection.end =
+                            movement::find_boundary(map, selection.end, |left, right| {
+                                let left_kind =
+                                    char_kind(left).coerce_punctuation(ignore_punctuation);
+                                let right_kind =
+                                    char_kind(right).coerce_punctuation(ignore_punctuation);
 
-                        left_kind != right_kind || left == '\n' || right == '\n'
+                                left_kind != right_kind || left == '\n' || right == '\n'
+                            });
                     });
                 });
                 editor.insert(&"", cx);

crates/vim/src/normal/delete.rs 🔗

@@ -1,6 +1,6 @@
 use crate::{motion::Motion, Vim};
 use collections::HashMap;
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::MutableAppContext;
 
 pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
@@ -8,24 +8,28 @@ pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
         editor.transact(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
             let mut original_columns: HashMap<_, _> = Default::default();
-            editor.move_selections(cx, |map, selection| {
-                let original_head = selection.head();
-                motion.expand_selection(map, selection, true);
-                original_columns.insert(selection.id, original_head.column());
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    let original_head = selection.head();
+                    motion.expand_selection(map, selection, true);
+                    original_columns.insert(selection.id, original_head.column());
+                });
             });
             editor.insert(&"", cx);
 
             // Fixup cursor position after the deletion
             editor.set_clip_at_line_ends(true, cx);
-            editor.move_selections(cx, |map, selection| {
-                let mut cursor = selection.head();
-                if motion.linewise() {
-                    if let Some(column) = original_columns.get(&selection.id) {
-                        *cursor.column_mut() = *column
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    let mut cursor = selection.head();
+                    if motion.linewise() {
+                        if let Some(column) = original_columns.get(&selection.id) {
+                            *cursor.column_mut() = *column
+                        }
                     }
-                }
-                cursor = map.clip_point(cursor, Bias::Left);
-                selection.collapse_to(cursor, selection.goal)
+                    cursor = map.clip_point(cursor, Bias::Left);
+                    selection.collapse_to(cursor, selection.goal)
+                });
             });
         });
     });

crates/vim/src/vim_test_context.rs 🔗

@@ -3,7 +3,7 @@ use std::ops::{Deref, Range};
 use collections::BTreeMap;
 use itertools::{Either, Itertools};
 
-use editor::display_map::ToDisplayPoint;
+use editor::{display_map::ToDisplayPoint, Autoscroll};
 use gpui::{json::json, keymap::Keystroke, ViewHandle};
 use indoc::indoc;
 use language::Selection;
@@ -128,7 +128,9 @@ impl<'a> VimTestContext<'a> {
             let (unmarked_text, markers) = marked_text(&text);
             editor.set_text(unmarked_text, cx);
             let cursor_offset = markers[0];
-            editor.replace_selections_with(cx, |map| cursor_offset.to_display_point(map));
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.replace_cursors_with(|map| vec![cursor_offset.to_display_point(map)])
+            });
         })
     }
 
@@ -197,7 +199,8 @@ impl<'a> VimTestContext<'a> {
         let (empty_selections, reverse_selections, forward_selections) =
             self.editor.read_with(self.cx, |editor, cx| {
                 let (empty_selections, non_empty_selections): (Vec<_>, Vec<_>) = editor
-                    .local_selections::<usize>(cx)
+                    .selections
+                    .all::<usize>(cx)
                     .into_iter()
                     .partition_map(|selection| {
                         if selection.is_empty() {

crates/vim/src/visual.rs 🔗

@@ -1,4 +1,4 @@
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::{actions, MutableAppContext, ViewContext};
 use workspace::Workspace;
 
@@ -14,23 +14,25 @@ pub fn init(cx: &mut MutableAppContext) {
 pub fn visual_motion(motion: Motion, cx: &mut MutableAppContext) {
     Vim::update(cx, |vim, cx| {
         vim.update_active_editor(cx, |editor, cx| {
-            editor.move_selections(cx, |map, selection| {
-                let (new_head, goal) = motion.move_point(map, selection.head(), selection.goal);
-                let new_head = map.clip_at_line_end(new_head);
-                let was_reversed = selection.reversed;
-                selection.set_head(new_head, goal);
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    let (new_head, goal) = motion.move_point(map, selection.head(), selection.goal);
+                    let new_head = map.clip_at_line_end(new_head);
+                    let was_reversed = selection.reversed;
+                    selection.set_head(new_head, goal);
 
-                if was_reversed && !selection.reversed {
-                    // Head was at the start of the selection, and now is at the end. We need to move the start
-                    // back by one if possible in order to compensate for this change.
-                    *selection.start.column_mut() = selection.start.column().saturating_sub(1);
-                    selection.start = map.clip_point(selection.start, Bias::Left);
-                } else if !was_reversed && selection.reversed {
-                    // Head was at the end of the selection, and now is at the start. We need to move the end
-                    // forward by one if possible in order to compensate for this change.
-                    *selection.end.column_mut() = selection.end.column() + 1;
-                    selection.end = map.clip_point(selection.end, Bias::Left);
-                }
+                    if was_reversed && !selection.reversed {
+                        // Head was at the start of the selection, and now is at the end. We need to move the start
+                        // back by one if possible in order to compensate for this change.
+                        *selection.start.column_mut() = selection.start.column().saturating_sub(1);
+                        selection.start = map.clip_point(selection.start, Bias::Left);
+                    } else if !was_reversed && selection.reversed {
+                        // Head was at the end of the selection, and now is at the start. We need to move the end
+                        // forward by one if possible in order to compensate for this change.
+                        *selection.end.column_mut() = selection.end.column() + 1;
+                        selection.end = map.clip_point(selection.end, Bias::Left);
+                    }
+                });
             });
         });
     });
@@ -40,13 +42,15 @@ pub fn change(_: &mut Workspace, _: &VisualChange, cx: &mut ViewContext<Workspac
     Vim::update(cx, |vim, cx| {
         vim.update_active_editor(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
-            editor.move_selections(cx, |map, selection| {
-                if !selection.reversed {
-                    // Head was at the end of the selection, and now is at the start. We need to move the end
-                    // forward by one if possible in order to compensate for this change.
-                    *selection.end.column_mut() = selection.end.column() + 1;
-                    selection.end = map.clip_point(selection.end, Bias::Left);
-                }
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    if !selection.reversed {
+                        // Head was at the end of the selection, and now is at the start. We need to move the end
+                        // forward by one if possible in order to compensate for this change.
+                        *selection.end.column_mut() = selection.end.column() + 1;
+                        selection.end = map.clip_point(selection.end, Bias::Left);
+                    }
+                });
             });
             editor.insert("", cx);
         });
@@ -59,22 +63,26 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspac
         vim.switch_mode(Mode::Normal, cx);
         vim.update_active_editor(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
-            editor.move_selections(cx, |map, selection| {
-                if !selection.reversed {
-                    // Head was at the end of the selection, and now is at the start. We need to move the end
-                    // forward by one if possible in order to compensate for this change.
-                    *selection.end.column_mut() = selection.end.column() + 1;
-                    selection.end = map.clip_point(selection.end, Bias::Left);
-                }
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    if !selection.reversed {
+                        // Head was at the end of the selection, and now is at the start. We need to move the end
+                        // forward by one if possible in order to compensate for this change.
+                        *selection.end.column_mut() = selection.end.column() + 1;
+                        selection.end = map.clip_point(selection.end, Bias::Left);
+                    }
+                });
             });
             editor.insert("", cx);
 
             // Fixup cursor position after the deletion
             editor.set_clip_at_line_ends(true, cx);
-            editor.move_selections(cx, |map, selection| {
-                let mut cursor = selection.head();
-                cursor = map.clip_point(cursor, Bias::Left);
-                selection.collapse_to(cursor, selection.goal)
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.move_with(|map, selection| {
+                    let mut cursor = selection.head();
+                    cursor = map.clip_point(cursor, Bias::Left);
+                    selection.collapse_to(cursor, selection.goal)
+                });
             });
         });
     });

crates/zed/Cargo.toml 🔗

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
 description = "The fast, collaborative code editor."
 edition = "2021"
 name = "zed"
-version = "0.32.0"
+version = "0.33.0"
 
 [lib]
 name = "zed"

crates/zed/src/zed.rs 🔗

@@ -311,7 +311,7 @@ fn open_config_file(
 mod tests {
     use super::*;
     use assets::Assets;
-    use editor::{DisplayPoint, Editor};
+    use editor::{Autoscroll, DisplayPoint, Editor};
     use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle};
     use project::{Fs, ProjectPath};
     use serde_json::json;
@@ -964,7 +964,9 @@ mod tests {
             .downcast::<Editor>()
             .unwrap();
         editor1.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(10, 0)..DisplayPoint::new(10, 0)], cx);
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(10, 0)..DisplayPoint::new(10, 0)])
+            });
         });
         let editor2 = workspace
             .update(cx, |w, cx| w.open_path(file2.clone(), true, cx))
@@ -981,10 +983,9 @@ mod tests {
 
         editor3
             .update(cx, |editor, cx| {
-                editor.select_display_ranges(
-                    &[DisplayPoint::new(12, 0)..DisplayPoint::new(12, 0)],
-                    cx,
-                );
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_display_ranges([DisplayPoint::new(12, 0)..DisplayPoint::new(12, 0)])
+                });
                 editor.newline(&Default::default(), cx);
                 editor.newline(&Default::default(), cx);
                 editor.move_down(&Default::default(), cx);
@@ -1125,34 +1126,37 @@ mod tests {
         // Modify file to collapse multiple nav history entries into the same location.
         // Ensure we don't visit the same location twice when navigating.
         editor1.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)], cx)
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)])
+            })
         });
 
         for _ in 0..5 {
             editor1.update(cx, |editor, cx| {
-                editor
-                    .select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
+                editor.change_selections(None, cx, |s| {
+                    s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
+                });
             });
             editor1.update(cx, |editor, cx| {
-                editor.select_display_ranges(
-                    &[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 0)],
-                    cx,
-                )
+                editor.change_selections(None, cx, |s| {
+                    s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 0)])
+                })
             });
         }
 
         editor1.update(cx, |editor, cx| {
             editor.transact(cx, |editor, cx| {
-                editor.select_display_ranges(
-                    &[DisplayPoint::new(2, 0)..DisplayPoint::new(14, 0)],
-                    cx,
-                );
+                editor.change_selections(None, cx, |s| {
+                    s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(14, 0)])
+                });
                 editor.insert("", cx);
             })
         });
 
         editor1.update(cx, |editor, cx| {
-            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx)
+            editor.change_selections(None, cx, |s| {
+                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
+            })
         });
         workspace
             .update(cx, |w, cx| Pane::go_back(w, None, cx))
@@ -1178,7 +1182,7 @@ mod tests {
                 let editor = item.downcast::<Editor>().unwrap();
                 let (selections, scroll_position) = editor.update(cx, |editor, cx| {
                     (
-                        editor.selected_display_ranges(cx),
+                        editor.selections.display_ranges(cx),
                         editor.scroll_position(cx),
                     )
                 });

styles/dist/dark.json 🔗

@@ -1,698 +1,531 @@
 {
   "meta": {
-    "themeName": "dark"
+    "themeName": "cave-dark"
   },
   "text": {
     "primary": {
-      "value": "#f1f1f1",
-      "description": "Step: 50",
+      "value": "#e2dfe7",
       "type": "color"
     },
     "secondary": {
-      "value": "#9c9c9c",
-      "description": "Step: 350",
+      "value": "#8b8792",
       "type": "color"
     },
     "muted": {
-      "value": "#808080",
-      "description": "Step: 450",
+      "value": "#8b8792",
       "type": "color"
     },
     "placeholder": {
-      "value": "#474747",
-      "description": "Step: 650",
+      "value": "#7e7887",
       "type": "color"
     },
     "active": {
-      "value": "#ffffff",
-      "description": "Step: 0",
+      "value": "#efecf4",
       "type": "color"
     },
     "feature": {
-      "value": "#4f8ff7",
-      "description": "Step: 400",
+      "value": "#576ddb",
       "type": "color"
     },
     "ok": {
-      "value": "#1b9447",
-      "description": "Step: 600",
+      "value": "#2a9292",
       "type": "color"
     },
     "error": {
-      "value": "#f15656",
-      "description": "Step: 400",
+      "value": "#be4678",
       "type": "color"
     },
     "warning": {
-      "value": "#f7bb57",
-      "description": "Step: 300",
+      "value": "#a06e3b",
       "type": "color"
     },
     "info": {
-      "value": "#2472f2",
-      "description": "Step: 500",
+      "value": "#576ddb",
       "type": "color"
     }
   },
   "icon": {
     "primary": {
-      "value": "#c6c6c6",
-      "description": "Step: 200",
+      "value": "#e2dfe7",
       "type": "color"
     },
     "secondary": {
-      "value": "#9c9c9c",
-      "description": "Step: 350",
+      "value": "#8b8792",
       "type": "color"
     },
     "muted": {
-      "value": "#555555",
-      "description": "Step: 600",
+      "value": "#8b8792",
       "type": "color"
     },
     "placeholder": {
-      "value": "#393939",
-      "description": "Step: 700",
+      "value": "#7e7887",
       "type": "color"
     },
     "active": {
-      "value": "#ffffff",
-      "description": "Step: 0",
+      "value": "#efecf4",
       "type": "color"
     },
     "feature": {
-      "value": "#2472f2",
-      "description": "Step: 500",
+      "value": "#576ddb",
       "type": "color"
     },
     "ok": {
-      "value": "#1b9447",
-      "description": "Step: 600",
+      "value": "#2a9292",
       "type": "color"
     },
     "error": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#be4678",
       "type": "color"
     },
     "warning": {
-      "value": "#f6a724",
-      "description": "Step: 400",
+      "value": "#a06e3b",
       "type": "color"
     },
     "info": {
-      "value": "#135acd",
-      "description": "Step: 600",
+      "value": "#576ddb",
       "type": "color"
     }
   },
   "background": {
     "100": {
       "base": {
-        "value": "#2b2b2b",
-        "description": "Step: 750",
+        "value": "#26232a",
         "type": "color"
       },
       "hovered": {
-        "value": "#323232",
-        "description": "Step: 725",
+        "value": "#5852603d",
         "type": "color"
       },
       "active": {
-        "value": "#1c1c1c",
-        "description": "Step: 800",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#404040",
-        "description": "Step: 675",
+        "value": "#5852605c",
         "type": "color"
       }
     },
     "300": {
       "base": {
-        "value": "#1c1c1c",
-        "description": "Step: 800",
+        "value": "#26232a",
         "type": "color"
       },
       "hovered": {
-        "value": "#232323",
-        "description": "Step: 775",
+        "value": "#5852603d",
         "type": "color"
       },
       "active": {
-        "value": "#2b2b2b",
-        "description": "Step: 750",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#232323",
-        "description": "Step: 775",
+        "value": "#5852605c",
         "type": "color"
       }
     },
     "500": {
       "base": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#19171c",
         "type": "color"
       },
       "hovered": {
-        "value": "#ffffff14",
-        "description": "Step: 0",
+        "value": "#26232a3d",
         "type": "color"
       },
       "active": {
-        "value": "#ffffff1f",
-        "description": "Step: 0",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#151515",
-        "description": "Step: 825",
+        "value": "#26232a5c",
         "type": "color"
       }
     },
     "on300": {
       "base": {
-        "value": "#0e0e0e80",
-        "description": "Step: 850",
+        "value": "#19171c",
         "type": "color"
       },
       "hovered": {
-        "value": "#070707",
-        "description": "Step: 875",
+        "value": "#26232a3d",
         "type": "color"
       },
       "active": {
-        "value": "#000000",
-        "description": "Step: 900",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#070707",
-        "description": "Step: 875",
+        "value": "#26232a7a",
         "type": "color"
       }
     },
     "on500": {
       "base": {
-        "value": "#0e0e0e",
-        "description": "Step: 850",
+        "value": "#26232a",
         "type": "color"
       },
       "hovered": {
-        "value": "#1c1c1c",
-        "description": "Step: 800",
+        "value": "#5852603d",
         "type": "color"
       },
       "active": {
-        "value": "#232323",
-        "description": "Step: 775",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#1c1c1c",
-        "description": "Step: 800",
+        "value": "#5852607a",
         "type": "color"
       }
     },
     "ok": {
       "base": {
-        "value": "#1b944726",
-        "description": "Step: 600",
+        "value": "#2a929226",
         "type": "color"
       },
       "hovered": {
-        "value": "#1b944733",
-        "description": "Step: 600",
+        "value": "#2a929233",
         "type": "color"
       },
       "active": {
-        "value": "#1b944740",
-        "description": "Step: 600",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#1b944733",
-        "description": "Step: 600",
+        "value": "#2a929240",
         "type": "color"
       }
     },
     "error": {
       "base": {
-        "value": "#c9181826",
-        "description": "Step: 600",
+        "value": "#be467826",
         "type": "color"
       },
       "hovered": {
-        "value": "#c9181833",
-        "description": "Step: 600",
+        "value": "#be467833",
         "type": "color"
       },
       "active": {
-        "value": "#c9181840",
-        "description": "Step: 600",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#c9181833",
-        "description": "Step: 600",
+        "value": "#be467840",
         "type": "color"
       }
     },
     "warning": {
       "base": {
-        "value": "#f6a72426",
-        "description": "Step: 400",
+        "value": "#a06e3b26",
         "type": "color"
       },
       "hovered": {
-        "value": "#f6a72433",
-        "description": "Step: 400",
+        "value": "#a06e3b33",
         "type": "color"
       },
       "active": {
-        "value": "#f6a72440",
-        "description": "Step: 400",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#f6a72433",
-        "description": "Step: 400",
+        "value": "#a06e3b40",
         "type": "color"
       }
     },
     "info": {
       "base": {
-        "value": "#2472f226",
-        "description": "Step: 500",
+        "value": "#576ddb26",
         "type": "color"
       },
       "hovered": {
-        "value": "#2472f233",
-        "description": "Step: 500",
+        "value": "#576ddb33",
         "type": "color"
       },
       "active": {
-        "value": "#2472f240",
-        "description": "Step: 500",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#2472f233",
-        "description": "Step: 500",
+        "value": "#576ddb40",
         "type": "color"
       }
     }
   },
   "border": {
     "primary": {
-      "value": "#070707",
-      "description": "Step: 875",
+      "value": "#19171c",
       "type": "color"
     },
     "secondary": {
-      "value": "#232323",
-      "description": "Step: 775",
+      "value": "#26232a",
       "type": "color"
     },
     "muted": {
-      "value": "#404040",
-      "description": "Step: 675",
-      "type": "color"
-    },
-    "focused": {
-      "value": "#484bed",
-      "description": "Step: 500",
+      "value": "#655f6d",
       "type": "color"
     },
     "active": {
-      "value": "#000000",
-      "description": "Step: 900",
+      "value": "#655f6d",
       "type": "color"
     },
     "onMedia": {
-      "value": "#0707071a",
-      "description": "Step: 875",
+      "value": "#19171c1a",
       "type": "color"
     },
     "ok": {
-      "value": "#1b944726",
-      "description": "Step: 600",
+      "value": "#2a929226",
       "type": "color"
     },
     "error": {
-      "value": "#eb2d2d26",
-      "description": "Step: 500",
+      "value": "#be467826",
       "type": "color"
     },
     "warning": {
-      "value": "#f6a72426",
-      "description": "Step: 400",
+      "value": "#a06e3b26",
       "type": "color"
     },
     "info": {
-      "value": "#2472f226",
-      "description": "Step: 500",
+      "value": "#576ddb26",
       "type": "color"
     }
   },
   "editor": {
     "background": {
-      "value": "#000000",
-      "description": "Step: 900",
+      "value": "#19171c",
       "type": "color"
     },
     "indent_guide": {
-      "value": "#404040",
-      "description": "Step: 675",
+      "value": "#655f6d",
       "type": "color"
     },
     "indent_guide_active": {
-      "value": "#232323",
-      "description": "Step: 775",
+      "value": "#26232a",
       "type": "color"
     },
     "line": {
       "active": {
-        "value": "#ffffff12",
-        "description": "Step: 0",
+        "value": "#efecf412",
         "type": "color"
       },
       "highlighted": {
-        "value": "#ffffff1f",
-        "description": "Step: 0",
+        "value": "#efecf41f",
         "type": "color"
       },
       "inserted": {
-        "value": "#1b944740",
-        "description": "Step: 600",
+        "value": "#2a929240",
         "type": "color"
       },
       "deleted": {
-        "value": "#c9181840",
-        "description": "Step: 600",
+        "value": "#be467840",
         "type": "color"
       },
       "modified": {
-        "value": "#2472f240",
-        "description": "Step: 500",
+        "value": "#576ddb40",
         "type": "color"
       }
     },
     "highlight": {
       "selection": {
-        "value": "#2472f23d",
-        "description": "Step: 500",
+        "value": "#576ddb3d",
         "type": "color"
       },
       "occurrence": {
-        "value": "#ffffff1f",
-        "description": "Step: 0",
+        "value": "#efecf41f",
         "type": "color"
       },
       "activeOccurrence": {
-        "value": "#ffffff29",
-        "description": "Step: 0",
+        "value": "#efecf43d",
         "type": "color"
       },
       "matchingBracket": {
-        "value": "#ffffff1f",
-        "description": "Step: 0",
+        "value": "#26232a5c",
         "type": "color"
       },
       "match": {
-        "value": "#3f15a380",
-        "description": "Step: 700",
+        "value": "#955ae77a",
         "type": "color"
       },
       "activeMatch": {
-        "value": "#5316e0b3",
-        "description": "Step: 600",
+        "value": "#955ae7b8",
         "type": "color"
       },
       "related": {
-        "value": "#151515",
-        "description": "Step: 825",
+        "value": "#26232a3d",
         "type": "color"
       }
     },
     "gutter": {
       "primary": {
-        "value": "#474747",
-        "description": "Step: 650",
+        "value": "#7e7887",
         "type": "color"
       },
       "active": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#efecf4",
         "type": "color"
       }
     }
   },
   "syntax": {
     "primary": {
-      "value": "#d5d5d5",
-      "description": "Step: 150",
+      "value": "#efecf4",
       "type": "color"
     },
     "comment": {
-      "value": "#aaaaaa",
-      "description": "Step: 300",
+      "value": "#8b8792",
       "type": "color"
     },
     "keyword": {
-      "value": "#4f8ff7",
-      "description": "Step: 400",
+      "value": "#576ddb",
       "type": "color"
     },
     "function": {
-      "value": "#f9da82",
-      "description": "Step: 200",
+      "value": "#a06e3b",
       "type": "color"
     },
     "type": {
-      "value": "#3eeeda",
-      "description": "Step: 300",
+      "value": "#398bc6",
       "type": "color"
     },
     "variant": {
-      "value": "#53c1f5",
-      "description": "Step: 300",
+      "value": "#576ddb",
       "type": "color"
     },
     "property": {
-      "value": "#4f8ff7",
-      "description": "Step: 400",
+      "value": "#576ddb",
       "type": "color"
     },
     "enum": {
-      "value": "#ee670a",
-      "description": "Step: 500",
+      "value": "#aa573c",
       "type": "color"
     },
     "operator": {
-      "value": "#ee670a",
-      "description": "Step: 500",
+      "value": "#aa573c",
       "type": "color"
     },
     "string": {
-      "value": "#f99d5f",
-      "description": "Step: 300",
+      "value": "#aa573c",
       "type": "color"
     },
     "number": {
-      "value": "#aeef4b",
-      "description": "Step: 300",
+      "value": "#2a9292",
       "type": "color"
     },
     "boolean": {
-      "value": "#aeef4b",
-      "description": "Step: 300",
+      "value": "#2a9292",
       "type": "color"
     }
   },
   "player": {
     "1": {
       "baseColor": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#2472f23d",
-        "description": "Step: 500",
+        "value": "#576ddb3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#2472f2cc",
-        "description": "Step: 500",
+        "value": "#576ddbcc",
         "type": "color"
       }
     },
     "2": {
       "baseColor": {
-        "value": "#79ba16",
-        "description": "Step: 500",
+        "value": "#2a9292",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#79ba16",
-        "description": "Step: 500",
+        "value": "#2a9292",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#79ba163d",
-        "description": "Step: 500",
+        "value": "#2a92923d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#79ba16cc",
-        "description": "Step: 500",
+        "value": "#2a9292cc",
         "type": "color"
       }
     },
     "3": {
       "baseColor": {
-        "value": "#d430e0",
-        "description": "Step: 500",
+        "value": "#bf40bf",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#d430e0",
-        "description": "Step: 500",
+        "value": "#bf40bf",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#d430e03d",
-        "description": "Step: 500",
+        "value": "#bf40bf3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#d430e0cc",
-        "description": "Step: 500",
+        "value": "#bf40bfcc",
         "type": "color"
       }
     },
     "4": {
       "baseColor": {
-        "value": "#ee670a",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#ee670a",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#ee670a3d",
-        "description": "Step: 500",
+        "value": "#aa573c3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#ee670acc",
-        "description": "Step: 500",
+        "value": "#aa573ccc",
         "type": "color"
       }
     },
     "5": {
       "baseColor": {
-        "value": "#993bf3",
-        "description": "Step: 500",
+        "value": "#955ae7",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#993bf3",
-        "description": "Step: 500",
+        "value": "#955ae7",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#993bf33d",
-        "description": "Step: 500",
+        "value": "#955ae73d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#993bf3cc",
-        "description": "Step: 500",
+        "value": "#955ae7cc",
         "type": "color"
       }
     },
     "6": {
       "baseColor": {
-        "value": "#16d6c1",
-        "description": "Step: 400",
+        "value": "#398bc6",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#16d6c1",
-        "description": "Step: 400",
+        "value": "#398bc6",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#16d6c13d",
-        "description": "Step: 400",
+        "value": "#398bc63d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#16d6c1cc",
-        "description": "Step: 400",
+        "value": "#398bc6cc",
         "type": "color"
       }
     },
     "7": {
       "baseColor": {
-        "value": "#ef59a3",
-        "description": "Step: 400",
+        "value": "#be4678",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#ef59a3",
-        "description": "Step: 400",
+        "value": "#be4678",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#ef59a33d",
-        "description": "Step: 400",
+        "value": "#be46783d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#ef59a3cc",
-        "description": "Step: 400",
+        "value": "#be4678cc",
         "type": "color"
       }
     },
     "8": {
       "baseColor": {
-        "value": "#f7bf17",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#f7bf17",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#f7bf173d",
-        "description": "Step: 400",
+        "value": "#a06e3b3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#f7bf17cc",
-        "description": "Step: 400",
+        "value": "#a06e3bcc",
         "type": "color"
       }
     }
   },
   "shadowAlpha": {
-    "value": 0.32,
+    "value": 0.24,
     "type": "number"
   }
 }

styles/dist/light.json 🔗

@@ -1,692 +1,525 @@
 {
   "meta": {
-    "themeName": "light"
+    "themeName": "cave-light"
   },
   "text": {
     "primary": {
-      "value": "#2b2b2b",
-      "description": "Step: 750",
+      "value": "#26232a",
       "type": "color"
     },
     "secondary": {
-      "value": "#474747",
-      "description": "Step: 650",
+      "value": "#585260",
       "type": "color"
     },
     "muted": {
-      "value": "#636363",
-      "description": "Step: 550",
+      "value": "#585260",
       "type": "color"
     },
     "placeholder": {
-      "value": "#808080",
-      "description": "Step: 450",
+      "value": "#655f6d",
       "type": "color"
     },
     "active": {
-      "value": "#000000",
-      "description": "Step: 900",
+      "value": "#19171c",
       "type": "color"
     },
     "feature": {
-      "value": "#484bed",
-      "description": "Step: 500",
+      "value": "#576ddb",
       "type": "color"
     },
     "ok": {
-      "value": "#20b456",
-      "description": "Step: 500",
+      "value": "#2a9292",
       "type": "color"
     },
     "error": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#be4678",
       "type": "color"
     },
     "warning": {
-      "value": "#d3a20b",
-      "description": "Step: 500",
+      "value": "#a06e3b",
       "type": "color"
     },
     "info": {
-      "value": "#2472f2",
-      "description": "Step: 500",
+      "value": "#576ddb",
       "type": "color"
     }
   },
   "icon": {
     "primary": {
-      "value": "#393939",
-      "description": "Step: 700",
+      "value": "#26232a",
       "type": "color"
     },
     "secondary": {
-      "value": "#717171",
-      "description": "Step: 500",
+      "value": "#585260",
       "type": "color"
     },
     "muted": {
-      "value": "#9c9c9c",
-      "description": "Step: 350",
+      "value": "#585260",
       "type": "color"
     },
     "placeholder": {
-      "value": "#aaaaaa",
-      "description": "Step: 300",
+      "value": "#655f6d",
       "type": "color"
     },
     "active": {
-      "value": "#000000",
-      "description": "Step: 900",
+      "value": "#19171c",
       "type": "color"
     },
     "feature": {
-      "value": "#484bed",
-      "description": "Step: 500",
+      "value": "#576ddb",
       "type": "color"
     },
     "ok": {
-      "value": "#1b9447",
-      "description": "Step: 600",
+      "value": "#2a9292",
       "type": "color"
     },
     "error": {
-      "value": "#c91818",
-      "description": "Step: 600",
+      "value": "#be4678",
       "type": "color"
     },
     "warning": {
-      "value": "#f7bf17",
-      "description": "Step: 400",
+      "value": "#a06e3b",
       "type": "color"
     },
     "info": {
-      "value": "#135acd",
-      "description": "Step: 600",
+      "value": "#576ddb",
       "type": "color"
     }
   },
   "background": {
     "100": {
       "base": {
-        "value": "#eaeaea",
-        "description": "Step: 75",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "hovered": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
+        "value": "#8b87921f",
         "type": "color"
       },
       "active": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
+        "value": "#8b87922e",
         "type": "color"
       }
     },
     "300": {
       "base": {
-        "value": "#f8f8f8",
-        "description": "Step: 25",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "hovered": {
-        "value": "#eaeaea",
-        "description": "Step: 75",
+        "value": "#8b87921f",
         "type": "color"
       },
       "active": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#eaeaea",
-        "description": "Step: 75",
+        "value": "#8b87922e",
         "type": "color"
       }
     },
     "500": {
       "base": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#efecf4",
         "type": "color"
       },
       "hovered": {
-        "value": "#00000008",
-        "description": "Step: 900",
+        "value": "#e2dfe71f",
         "type": "color"
       },
       "active": {
-        "value": "#0000000f",
-        "description": "Step: 900",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#f1f1f1",
-        "description": "Step: 50",
+        "value": "#e2dfe72e",
         "type": "color"
       }
     },
     "on300": {
       "base": {
-        "value": "#f1f1f1",
-        "description": "Step: 50",
+        "value": "#efecf4",
         "type": "color"
       },
       "hovered": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
+        "value": "#e2dfe71f",
         "type": "color"
       },
       "active": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
+        "value": "#e2dfe73d",
         "type": "color"
       }
     },
     "on500": {
       "base": {
-        "value": "#f1f1f1",
-        "description": "Step: 50",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "hovered": {
-        "value": "#f8f8f8",
-        "description": "Step: 25",
+        "value": "#8b87921f",
         "type": "color"
       },
       "active": {
-        "value": "#ffffff",
-        "description": "Step: 0",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#f8f8f8",
-        "description": "Step: 25",
+        "value": "#8b87923d",
         "type": "color"
       }
     },
     "ok": {
       "base": {
-        "value": "#1b944726",
-        "description": "Step: 600",
+        "value": "#2a929226",
         "type": "color"
       },
       "hovered": {
-        "value": "#1b944733",
-        "description": "Step: 600",
+        "value": "#2a929233",
         "type": "color"
       },
       "active": {
-        "value": "#1b944740",
-        "description": "Step: 600",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#1b944733",
-        "description": "Step: 600",
+        "value": "#2a929240",
         "type": "color"
       }
     },
     "error": {
       "base": {
-        "value": "#c9181826",
-        "description": "Step: 600",
+        "value": "#be467826",
         "type": "color"
       },
       "hovered": {
-        "value": "#c9181833",
-        "description": "Step: 600",
+        "value": "#be467833",
         "type": "color"
       },
       "active": {
-        "value": "#c9181840",
-        "description": "Step: 600",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#c9181833",
-        "description": "Step: 600",
+        "value": "#be467840",
         "type": "color"
       }
     },
     "warning": {
       "base": {
-        "value": "#f6a72426",
-        "description": "Step: 400",
+        "value": "#a06e3b26",
         "type": "color"
       },
       "hovered": {
-        "value": "#f6a72433",
-        "description": "Step: 400",
+        "value": "#a06e3b33",
         "type": "color"
       },
       "active": {
-        "value": "#f6a72440",
-        "description": "Step: 400",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#f6a72433",
-        "description": "Step: 400",
+        "value": "#a06e3b40",
         "type": "color"
       }
     },
     "info": {
       "base": {
-        "value": "#2472f226",
-        "description": "Step: 500",
+        "value": "#576ddb26",
         "type": "color"
       },
       "hovered": {
-        "value": "#2472f233",
-        "description": "Step: 500",
+        "value": "#576ddb33",
         "type": "color"
       },
       "active": {
-        "value": "#2472f240",
-        "description": "Step: 500",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#2472f233",
-        "description": "Step: 500",
+        "value": "#576ddb40",
         "type": "color"
       }
     }
   },
   "border": {
     "primary": {
-      "value": "#d5d5d5",
-      "description": "Step: 150",
+      "value": "#efecf4",
       "type": "color"
     },
     "secondary": {
-      "value": "#d5d5d5",
-      "description": "Step: 150",
+      "value": "#e2dfe7",
       "type": "color"
     },
     "muted": {
-      "value": "#e3e3e3",
-      "description": "Step: 100",
-      "type": "color"
-    },
-    "focused": {
-      "value": "#484bed",
-      "description": "Step: 500",
+      "value": "#7e7887",
       "type": "color"
     },
     "active": {
-      "value": "#b8b8b8",
-      "description": "Step: 250",
+      "value": "#7e7887",
       "type": "color"
     },
     "onMedia": {
-      "value": "#b8b8b84d",
-      "description": "Step: 250",
+      "value": "#efecf41a",
       "type": "color"
     },
     "ok": {
-      "value": "#1b944726",
-      "description": "Step: 600",
+      "value": "#2a929226",
       "type": "color"
     },
     "error": {
-      "value": "#eb2d2d26",
-      "description": "Step: 500",
+      "value": "#be467826",
       "type": "color"
     },
     "warning": {
-      "value": "#f6a72426",
-      "description": "Step: 400",
+      "value": "#a06e3b26",
       "type": "color"
     },
     "info": {
-      "value": "#2472f226",
-      "description": "Step: 500",
+      "value": "#576ddb26",
       "type": "color"
     }
   },
   "editor": {
     "background": {
-      "value": "#ffffff",
-      "description": "Step: 0",
+      "value": "#efecf4",
       "type": "color"
     },
     "indent_guide": {
-      "value": "#e3e3e3",
-      "description": "Step: 100",
+      "value": "#7e7887",
       "type": "color"
     },
     "indent_guide_active": {
-      "value": "#d5d5d5",
-      "description": "Step: 150",
+      "value": "#e2dfe7",
       "type": "color"
     },
     "line": {
       "active": {
-        "value": "#0000000f",
-        "description": "Step: 900",
+        "value": "#19171c12",
         "type": "color"
       },
       "highlighted": {
-        "value": "#0000001f",
-        "description": "Step: 900",
+        "value": "#19171c1f",
         "type": "color"
       },
       "inserted": {
-        "value": "#1b944740",
-        "description": "Step: 600",
+        "value": "#2a929240",
         "type": "color"
       },
       "deleted": {
-        "value": "#c9181840",
-        "description": "Step: 600",
+        "value": "#be467840",
         "type": "color"
       },
       "modified": {
-        "value": "#2472f240",
-        "description": "Step: 500",
+        "value": "#576ddb40",
         "type": "color"
       }
     },
     "highlight": {
       "selection": {
-        "value": "#2472f23d",
-        "description": "Step: 500",
+        "value": "#576ddb3d",
         "type": "color"
       },
       "occurrence": {
-        "value": "#0000000f",
-        "description": "Step: 900",
+        "value": "#19171c0f",
         "type": "color"
       },
       "activeOccurrence": {
-        "value": "#00000029",
-        "description": "Step: 900",
+        "value": "#19171c1f",
         "type": "color"
       },
       "matchingBracket": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#e2dfe72e",
         "type": "color"
       },
       "match": {
-        "value": "#fce9b7",
-        "description": "Step: 100",
+        "value": "#955ae73d",
         "type": "color"
       },
       "activeMatch": {
-        "value": "#f9da82",
-        "description": "Step: 200",
+        "value": "#955ae75c",
         "type": "color"
       },
       "related": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#e2dfe71f",
         "type": "color"
       }
     },
     "gutter": {
       "primary": {
-        "value": "#aaaaaa",
-        "description": "Step: 300",
+        "value": "#655f6d",
         "type": "color"
       },
       "active": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#19171c",
         "type": "color"
       }
     }
   },
   "syntax": {
     "primary": {
-      "value": "#1c1c1c",
-      "description": "Step: 800",
+      "value": "#19171c",
       "type": "color"
     },
     "comment": {
-      "value": "#717171",
-      "description": "Step: 500",
+      "value": "#585260",
       "type": "color"
     },
     "keyword": {
-      "value": "#1819a1",
-      "description": "Step: 700",
+      "value": "#576ddb",
       "type": "color"
     },
     "function": {
-      "value": "#bb550e",
-      "description": "Step: 600",
+      "value": "#a06e3b",
       "type": "color"
     },
     "type": {
-      "value": "#a8820e",
-      "description": "Step: 600",
+      "value": "#398bc6",
       "type": "color"
     },
     "variant": {
-      "value": "#97142a",
-      "description": "Step: 700",
+      "value": "#576ddb",
       "type": "color"
     },
     "property": {
-      "value": "#106c4e",
-      "description": "Step: 700",
+      "value": "#576ddb",
       "type": "color"
     },
     "enum": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#aa573c",
       "type": "color"
     },
     "operator": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#aa573c",
       "type": "color"
     },
     "string": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#aa573c",
       "type": "color"
     },
     "number": {
-      "value": "#484bed",
-      "description": "Step: 500",
+      "value": "#2a9292",
       "type": "color"
     },
     "boolean": {
-      "value": "#eb2d2d",
-      "description": "Step: 500",
+      "value": "#2a9292",
       "type": "color"
     }
   },
   "player": {
     "1": {
       "baseColor": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#2472f23d",
-        "description": "Step: 500",
+        "value": "#576ddb3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#2472f2cc",
-        "description": "Step: 500",
+        "value": "#576ddbcc",
         "type": "color"
       }
     },
     "2": {
       "baseColor": {
-        "value": "#12d796",
-        "description": "Step: 400",
+        "value": "#2a9292",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#12d796",
-        "description": "Step: 400",
+        "value": "#2a9292",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#12d7963d",
-        "description": "Step: 400",
+        "value": "#2a92923d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#12d796cc",
-        "description": "Step: 400",
+        "value": "#2a9292cc",
         "type": "color"
       }
     },
     "3": {
       "baseColor": {
-        "value": "#de57e8",
-        "description": "Step: 400",
+        "value": "#bf40bf",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#de57e8",
-        "description": "Step: 400",
+        "value": "#bf40bf",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#de57e83d",
-        "description": "Step: 400",
+        "value": "#bf40bf3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#de57e8cc",
-        "description": "Step: 400",
+        "value": "#bf40bfcc",
         "type": "color"
       }
     },
     "4": {
       "baseColor": {
-        "value": "#f9812e",
-        "description": "Step: 400",
+        "value": "#aa573c",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#f9812e",
-        "description": "Step: 400",
+        "value": "#aa573c",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#f9812e3d",
-        "description": "Step: 400",
+        "value": "#aa573c3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#f9812ecc",
-        "description": "Step: 400",
+        "value": "#aa573ccc",
         "type": "color"
       }
     },
     "5": {
       "baseColor": {
-        "value": "#b066f8",
-        "description": "Step: 400",
+        "value": "#955ae7",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#b066f8",
-        "description": "Step: 400",
+        "value": "#955ae7",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#b066f83d",
-        "description": "Step: 400",
+        "value": "#955ae73d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#b066f8cc",
-        "description": "Step: 400",
+        "value": "#955ae7cc",
         "type": "color"
       }
     },
     "6": {
       "baseColor": {
-        "value": "#16d6c1",
-        "description": "Step: 400",
+        "value": "#398bc6",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#16d6c1",
-        "description": "Step: 400",
+        "value": "#398bc6",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#16d6c13d",
-        "description": "Step: 400",
+        "value": "#398bc63d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#16d6c1cc",
-        "description": "Step: 400",
+        "value": "#398bc6cc",
         "type": "color"
       }
     },
     "7": {
       "baseColor": {
-        "value": "#ef59a3",
-        "description": "Step: 400",
+        "value": "#be4678",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#ef59a3",
-        "description": "Step: 400",
+        "value": "#be4678",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#ef59a33d",
-        "description": "Step: 400",
+        "value": "#be46783d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#ef59a3cc",
-        "description": "Step: 400",
+        "value": "#be4678cc",
         "type": "color"
       }
     },
     "8": {
       "baseColor": {
-        "value": "#f7bf17",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "cursorColor": {
-        "value": "#f7bf17",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "selectionColor": {
-        "value": "#f7bf173d",
-        "description": "Step: 400",
+        "value": "#a06e3b3d",
         "type": "color"
       },
       "borderColor": {
-        "value": "#f7bf17cc",
-        "description": "Step: 400",
+        "value": "#a06e3bcc",
         "type": "color"
       }
     }

styles/dist/solarized-dark.json 🔗

@@ -89,19 +89,15 @@
   "background": {
     "100": {
       "base": {
-        "value": "#073642",
+        "value": "#1b444f",
         "type": "color"
       },
       "hovered": {
-        "value": "#586e753d",
+        "value": "#30525c",
         "type": "color"
       },
       "active": {
-        "value": "#586e755c",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#586e753d",
+        "value": "#446068",
         "type": "color"
       }
     },
@@ -111,15 +107,11 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#586e753d",
+        "value": "#1b444f",
         "type": "color"
       },
       "active": {
-        "value": "#586e755c",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#586e753d",
+        "value": "#30525c",
         "type": "color"
       }
     },
@@ -129,15 +121,11 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#0736423d",
+        "value": "#022e39",
         "type": "color"
       },
       "active": {
-        "value": "#0736425c",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#0736423d",
+        "value": "#04313c",
         "type": "color"
       }
     },
@@ -147,33 +135,25 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#0736423d",
+        "value": "#022e39",
         "type": "color"
       },
       "active": {
-        "value": "#0736427a",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#0736423d",
+        "value": "#04313c",
         "type": "color"
       }
     },
     "on500": {
       "base": {
-        "value": "#073642",
+        "value": "#1b444f",
         "type": "color"
       },
       "hovered": {
-        "value": "#586e753d",
+        "value": "#30525c",
         "type": "color"
       },
       "active": {
-        "value": "#586e757a",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#586e753d",
+        "value": "#446068",
         "type": "color"
       }
     },
@@ -189,10 +169,6 @@
       "active": {
         "value": "#85990040",
         "type": "color"
-      },
-      "focused": {
-        "value": "#85990033",
-        "type": "color"
       }
     },
     "error": {
@@ -207,10 +183,6 @@
       "active": {
         "value": "#dc322f40",
         "type": "color"
-      },
-      "focused": {
-        "value": "#dc322f33",
-        "type": "color"
       }
     },
     "warning": {
@@ -225,10 +197,6 @@
       "active": {
         "value": "#b5890040",
         "type": "color"
-      },
-      "focused": {
-        "value": "#b5890033",
-        "type": "color"
       }
     },
     "info": {
@@ -243,10 +211,6 @@
       "active": {
         "value": "#268bd240",
         "type": "color"
-      },
-      "focused": {
-        "value": "#268bd233",
-        "type": "color"
       }
     }
   },
@@ -263,10 +227,6 @@
       "value": "#657b83",
       "type": "color"
     },
-    "focused": {
-      "value": "#657b83",
-      "type": "color"
-    },
     "active": {
       "value": "#657b83",
       "type": "color"
@@ -307,23 +267,11 @@
     },
     "line": {
       "active": {
-        "value": "#fdf6e312",
+        "value": "#073642",
         "type": "color"
       },
       "highlighted": {
-        "value": "#fdf6e31f",
-        "type": "color"
-      },
-      "inserted": {
-        "value": "#85990040",
-        "type": "color"
-      },
-      "deleted": {
-        "value": "#dc322f40",
-        "type": "color"
-      },
-      "modified": {
-        "value": "#268bd240",
+        "value": "#1b444f",
         "type": "color"
       }
     },
@@ -333,27 +281,27 @@
         "type": "color"
       },
       "occurrence": {
-        "value": "#fdf6e31f",
+        "value": "#586e753d",
         "type": "color"
       },
       "activeOccurrence": {
-        "value": "#fdf6e33d",
+        "value": "#586e757a",
         "type": "color"
       },
       "matchingBracket": {
-        "value": "#0736425c",
+        "value": "#04313c",
         "type": "color"
       },
       "match": {
-        "value": "#6c71c47a",
+        "value": "#1b1f6b",
         "type": "color"
       },
       "activeMatch": {
-        "value": "#6c71c4b8",
+        "value": "#434abc7a",
         "type": "color"
       },
       "related": {
-        "value": "#0736423d",
+        "value": "#022e39",
         "type": "color"
       }
     },

styles/dist/solarized-light.json 🔗

@@ -89,19 +89,15 @@
   "background": {
     "100": {
       "base": {
-        "value": "#eee8d5",
+        "value": "#d7d6c8",
         "type": "color"
       },
       "hovered": {
-        "value": "#93a1a11f",
+        "value": "#c1c5bb",
         "type": "color"
       },
       "active": {
-        "value": "#93a1a12e",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#93a1a11f",
+        "value": "#aab3ae",
         "type": "color"
       }
     },
@@ -111,15 +107,11 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#93a1a11f",
+        "value": "#d7d6c8",
         "type": "color"
       },
       "active": {
-        "value": "#93a1a12e",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#93a1a11f",
+        "value": "#c1c5bb",
         "type": "color"
       }
     },
@@ -129,15 +121,11 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#eee8d51f",
+        "value": "#f9f3e0",
         "type": "color"
       },
       "active": {
-        "value": "#eee8d52e",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#eee8d51f",
+        "value": "#f6efdc",
         "type": "color"
       }
     },
@@ -147,33 +135,25 @@
         "type": "color"
       },
       "hovered": {
-        "value": "#eee8d51f",
+        "value": "#f9f3e0",
         "type": "color"
       },
       "active": {
-        "value": "#eee8d53d",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#eee8d51f",
+        "value": "#f6efdc",
         "type": "color"
       }
     },
     "on500": {
       "base": {
-        "value": "#eee8d5",
+        "value": "#d7d6c8",
         "type": "color"
       },
       "hovered": {
-        "value": "#93a1a11f",
+        "value": "#c1c5bb",
         "type": "color"
       },
       "active": {
-        "value": "#93a1a13d",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#93a1a11f",
+        "value": "#aab3ae",
         "type": "color"
       }
     },
@@ -189,10 +169,6 @@
       "active": {
         "value": "#85990040",
         "type": "color"
-      },
-      "focused": {
-        "value": "#85990033",
-        "type": "color"
       }
     },
     "error": {
@@ -207,10 +183,6 @@
       "active": {
         "value": "#dc322f40",
         "type": "color"
-      },
-      "focused": {
-        "value": "#dc322f33",
-        "type": "color"
       }
     },
     "warning": {
@@ -225,10 +197,6 @@
       "active": {
         "value": "#b5890040",
         "type": "color"
-      },
-      "focused": {
-        "value": "#b5890033",
-        "type": "color"
       }
     },
     "info": {
@@ -243,32 +211,24 @@
       "active": {
         "value": "#268bd240",
         "type": "color"
-      },
-      "focused": {
-        "value": "#268bd233",
-        "type": "color"
       }
     }
   },
   "border": {
     "primary": {
-      "value": "#fdf6e3",
+      "value": "#93a1a1",
       "type": "color"
     },
     "secondary": {
-      "value": "#eee8d5",
+      "value": "#93a1a1",
       "type": "color"
     },
     "muted": {
-      "value": "#839496",
-      "type": "color"
-    },
-    "focused": {
-      "value": "#839496",
+      "value": "#657b83",
       "type": "color"
     },
     "active": {
-      "value": "#839496",
+      "value": "#657b83",
       "type": "color"
     },
     "onMedia": {
@@ -298,32 +258,20 @@
       "type": "color"
     },
     "indent_guide": {
-      "value": "#839496",
+      "value": "#657b83",
       "type": "color"
     },
     "indent_guide_active": {
-      "value": "#eee8d5",
+      "value": "#93a1a1",
       "type": "color"
     },
     "line": {
       "active": {
-        "value": "#002b3612",
+        "value": "#eee8d5",
         "type": "color"
       },
       "highlighted": {
-        "value": "#002b361f",
-        "type": "color"
-      },
-      "inserted": {
-        "value": "#85990040",
-        "type": "color"
-      },
-      "deleted": {
-        "value": "#dc322f40",
-        "type": "color"
-      },
-      "modified": {
-        "value": "#268bd240",
+        "value": "#d7d6c8",
         "type": "color"
       }
     },
@@ -333,27 +281,27 @@
         "type": "color"
       },
       "occurrence": {
-        "value": "#002b360f",
+        "value": "#93a1a11f",
         "type": "color"
       },
       "activeOccurrence": {
-        "value": "#002b361f",
+        "value": "#93a1a13d",
         "type": "color"
       },
       "matchingBracket": {
-        "value": "#eee8d52e",
+        "value": "#f6efdc",
         "type": "color"
       },
       "match": {
-        "value": "#6c71c43d",
+        "value": "#bcc0f6",
         "type": "color"
       },
       "activeMatch": {
-        "value": "#6c71c45c",
+        "value": "#7f84d73d",
         "type": "color"
       },
       "related": {
-        "value": "#eee8d51f",
+        "value": "#f9f3e0",
         "type": "color"
       }
     },

styles/dist/tokens.json 🔗

@@ -1180,1393 +1180,1035 @@
       }
     }
   },
-  "dark": {
+  "cave-dark": {
     "meta": {
-      "themeName": "dark"
+      "themeName": "cave-dark"
     },
     "text": {
       "primary": {
-        "value": "#f1f1f1",
-        "description": "Step: 50",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "secondary": {
-        "value": "#9c9c9c",
-        "description": "Step: 350",
+        "value": "#8b8792",
         "type": "color"
       },
       "muted": {
-        "value": "#808080",
-        "description": "Step: 450",
+        "value": "#8b8792",
         "type": "color"
       },
       "placeholder": {
-        "value": "#474747",
-        "description": "Step: 650",
+        "value": "#7e7887",
         "type": "color"
       },
       "active": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#efecf4",
         "type": "color"
       },
       "feature": {
-        "value": "#4f8ff7",
-        "description": "Step: 400",
+        "value": "#576ddb",
         "type": "color"
       },
       "ok": {
-        "value": "#1b9447",
-        "description": "Step: 600",
+        "value": "#2a9292",
         "type": "color"
       },
       "error": {
-        "value": "#f15656",
-        "description": "Step: 400",
+        "value": "#be4678",
         "type": "color"
       },
       "warning": {
-        "value": "#f7bb57",
-        "description": "Step: 300",
+        "value": "#a06e3b",
         "type": "color"
       },
       "info": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       }
     },
     "icon": {
       "primary": {
-        "value": "#c6c6c6",
-        "description": "Step: 200",
+        "value": "#e2dfe7",
         "type": "color"
       },
       "secondary": {
-        "value": "#9c9c9c",
-        "description": "Step: 350",
+        "value": "#8b8792",
         "type": "color"
       },
       "muted": {
-        "value": "#555555",
-        "description": "Step: 600",
+        "value": "#8b8792",
         "type": "color"
       },
       "placeholder": {
-        "value": "#393939",
-        "description": "Step: 700",
+        "value": "#7e7887",
         "type": "color"
       },
       "active": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#efecf4",
         "type": "color"
       },
       "feature": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "ok": {
-        "value": "#1b9447",
-        "description": "Step: 600",
+        "value": "#2a9292",
         "type": "color"
       },
       "error": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#be4678",
         "type": "color"
       },
       "warning": {
-        "value": "#f6a724",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "info": {
-        "value": "#135acd",
-        "description": "Step: 600",
+        "value": "#576ddb",
         "type": "color"
       }
     },
     "background": {
       "100": {
         "base": {
-          "value": "#2b2b2b",
-          "description": "Step: 750",
+          "value": "#332f38",
           "type": "color"
         },
         "hovered": {
-          "value": "#323232",
-          "description": "Step: 725",
+          "value": "#3f3b45",
           "type": "color"
         },
         "active": {
-          "value": "#1c1c1c",
-          "description": "Step: 800",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#404040",
-          "description": "Step: 675",
+          "value": "#4c4653",
           "type": "color"
         }
       },
       "300": {
         "base": {
-          "value": "#1c1c1c",
-          "description": "Step: 800",
+          "value": "#26232a",
           "type": "color"
         },
         "hovered": {
-          "value": "#232323",
-          "description": "Step: 775",
+          "value": "#332f38",
           "type": "color"
         },
         "active": {
-          "value": "#2b2b2b",
-          "description": "Step: 750",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#232323",
-          "description": "Step: 775",
+          "value": "#3f3b45",
           "type": "color"
         }
       },
       "500": {
         "base": {
-          "value": "#000000",
-          "description": "Step: 900",
+          "value": "#19171c",
           "type": "color"
         },
         "hovered": {
-          "value": "#ffffff14",
-          "description": "Step: 0",
+          "value": "#1c1a20",
           "type": "color"
         },
         "active": {
-          "value": "#ffffff1f",
-          "description": "Step: 0",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#151515",
-          "description": "Step: 825",
+          "value": "#201d23",
           "type": "color"
         }
       },
       "on300": {
         "base": {
-          "value": "#0e0e0e80",
-          "description": "Step: 850",
+          "value": "#19171c",
           "type": "color"
         },
         "hovered": {
-          "value": "#070707",
-          "description": "Step: 875",
+          "value": "#1c1a20",
           "type": "color"
         },
         "active": {
-          "value": "#000000",
-          "description": "Step: 900",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#070707",
-          "description": "Step: 875",
+          "value": "#201d23",
           "type": "color"
         }
       },
       "on500": {
         "base": {
-          "value": "#0e0e0e",
-          "description": "Step: 850",
+          "value": "#332f38",
           "type": "color"
         },
         "hovered": {
-          "value": "#1c1c1c",
-          "description": "Step: 800",
+          "value": "#3f3b45",
           "type": "color"
         },
         "active": {
-          "value": "#232323",
-          "description": "Step: 775",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#1c1c1c",
-          "description": "Step: 800",
+          "value": "#4c4653",
           "type": "color"
         }
       },
       "ok": {
         "base": {
-          "value": "#1b944726",
-          "description": "Step: 600",
+          "value": "#2a929226",
           "type": "color"
         },
         "hovered": {
-          "value": "#1b944733",
-          "description": "Step: 600",
+          "value": "#2a929233",
           "type": "color"
         },
         "active": {
-          "value": "#1b944740",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#1b944733",
-          "description": "Step: 600",
+          "value": "#2a929240",
           "type": "color"
         }
       },
       "error": {
         "base": {
-          "value": "#c9181826",
-          "description": "Step: 600",
+          "value": "#be467826",
           "type": "color"
         },
         "hovered": {
-          "value": "#c9181833",
-          "description": "Step: 600",
+          "value": "#be467833",
           "type": "color"
         },
         "active": {
-          "value": "#c9181840",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#c9181833",
-          "description": "Step: 600",
+          "value": "#be467840",
           "type": "color"
         }
       },
       "warning": {
         "base": {
-          "value": "#f6a72426",
-          "description": "Step: 400",
+          "value": "#a06e3b26",
           "type": "color"
         },
         "hovered": {
-          "value": "#f6a72433",
-          "description": "Step: 400",
+          "value": "#a06e3b33",
           "type": "color"
         },
         "active": {
-          "value": "#f6a72440",
-          "description": "Step: 400",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#f6a72433",
-          "description": "Step: 400",
+          "value": "#a06e3b40",
           "type": "color"
         }
       },
       "info": {
         "base": {
-          "value": "#2472f226",
-          "description": "Step: 500",
+          "value": "#576ddb26",
           "type": "color"
         },
         "hovered": {
-          "value": "#2472f233",
-          "description": "Step: 500",
+          "value": "#576ddb33",
           "type": "color"
         },
         "active": {
-          "value": "#2472f240",
-          "description": "Step: 500",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#2472f233",
-          "description": "Step: 500",
+          "value": "#576ddb40",
           "type": "color"
         }
       }
     },
     "border": {
       "primary": {
-        "value": "#070707",
-        "description": "Step: 875",
+        "value": "#19171c",
         "type": "color"
       },
       "secondary": {
-        "value": "#232323",
-        "description": "Step: 775",
+        "value": "#26232a",
         "type": "color"
       },
       "muted": {
-        "value": "#404040",
-        "description": "Step: 675",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#484bed",
-        "description": "Step: 500",
+        "value": "#655f6d",
         "type": "color"
       },
       "active": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#655f6d",
         "type": "color"
       },
       "onMedia": {
-        "value": "#0707071a",
-        "description": "Step: 875",
+        "value": "#19171c1a",
         "type": "color"
       },
       "ok": {
-        "value": "#1b944726",
-        "description": "Step: 600",
+        "value": "#2a929226",
         "type": "color"
       },
       "error": {
-        "value": "#eb2d2d26",
-        "description": "Step: 500",
+        "value": "#be467826",
         "type": "color"
       },
       "warning": {
-        "value": "#f6a72426",
-        "description": "Step: 400",
+        "value": "#a06e3b26",
         "type": "color"
       },
       "info": {
-        "value": "#2472f226",
-        "description": "Step: 500",
+        "value": "#576ddb26",
         "type": "color"
       }
     },
     "editor": {
       "background": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#19171c",
         "type": "color"
       },
       "indent_guide": {
-        "value": "#404040",
-        "description": "Step: 675",
+        "value": "#655f6d",
         "type": "color"
       },
       "indent_guide_active": {
-        "value": "#232323",
-        "description": "Step: 775",
+        "value": "#26232a",
         "type": "color"
       },
       "line": {
         "active": {
-          "value": "#ffffff12",
-          "description": "Step: 0",
+          "value": "#26232a",
           "type": "color"
         },
         "highlighted": {
-          "value": "#ffffff1f",
-          "description": "Step: 0",
-          "type": "color"
-        },
-        "inserted": {
-          "value": "#1b944740",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "deleted": {
-          "value": "#c9181840",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "modified": {
-          "value": "#2472f240",
-          "description": "Step: 500",
+          "value": "#332f38",
           "type": "color"
         }
       },
       "highlight": {
         "selection": {
-          "value": "#2472f23d",
-          "description": "Step: 500",
+          "value": "#576ddb3d",
           "type": "color"
         },
         "occurrence": {
-          "value": "#ffffff1f",
-          "description": "Step: 0",
+          "value": "#5852603d",
           "type": "color"
         },
         "activeOccurrence": {
-          "value": "#ffffff29",
-          "description": "Step: 0",
+          "value": "#5852607a",
           "type": "color"
         },
         "matchingBracket": {
-          "value": "#ffffff1f",
-          "description": "Step: 0",
+          "value": "#201d23",
           "type": "color"
         },
         "match": {
-          "value": "#3f15a380",
-          "description": "Step: 700",
+          "value": "#3d1576",
           "type": "color"
         },
         "activeMatch": {
-          "value": "#5316e0b3",
-          "description": "Step: 600",
+          "value": "#782edf7a",
           "type": "color"
         },
         "related": {
-          "value": "#151515",
-          "description": "Step: 825",
+          "value": "#1c1a20",
           "type": "color"
         }
       },
       "gutter": {
         "primary": {
-          "value": "#474747",
-          "description": "Step: 650",
+          "value": "#7e7887",
           "type": "color"
         },
         "active": {
-          "value": "#ffffff",
-          "description": "Step: 0",
+          "value": "#efecf4",
           "type": "color"
         }
       }
     },
     "syntax": {
       "primary": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
+        "value": "#efecf4",
         "type": "color"
       },
       "comment": {
-        "value": "#aaaaaa",
-        "description": "Step: 300",
+        "value": "#8b8792",
         "type": "color"
       },
       "keyword": {
-        "value": "#4f8ff7",
-        "description": "Step: 400",
+        "value": "#576ddb",
         "type": "color"
       },
       "function": {
-        "value": "#f9da82",
-        "description": "Step: 200",
+        "value": "#a06e3b",
         "type": "color"
       },
       "type": {
-        "value": "#3eeeda",
-        "description": "Step: 300",
+        "value": "#398bc6",
         "type": "color"
       },
       "variant": {
-        "value": "#53c1f5",
-        "description": "Step: 300",
+        "value": "#576ddb",
         "type": "color"
       },
       "property": {
-        "value": "#4f8ff7",
-        "description": "Step: 400",
+        "value": "#576ddb",
         "type": "color"
       },
       "enum": {
-        "value": "#ee670a",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "operator": {
-        "value": "#ee670a",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "string": {
-        "value": "#f99d5f",
-        "description": "Step: 300",
+        "value": "#aa573c",
         "type": "color"
       },
       "number": {
-        "value": "#aeef4b",
-        "description": "Step: 300",
+        "value": "#2a9292",
         "type": "color"
       },
       "boolean": {
-        "value": "#aeef4b",
-        "description": "Step: 300",
+        "value": "#2a9292",
         "type": "color"
       }
     },
     "player": {
       "1": {
         "baseColor": {
-          "value": "#2472f2",
-          "description": "Step: 500",
+          "value": "#576ddb",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#2472f2",
-          "description": "Step: 500",
+          "value": "#576ddb",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#2472f23d",
-          "description": "Step: 500",
+          "value": "#576ddb3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#2472f2cc",
-          "description": "Step: 500",
+          "value": "#576ddbcc",
           "type": "color"
         }
       },
       "2": {
         "baseColor": {
-          "value": "#79ba16",
-          "description": "Step: 500",
+          "value": "#2a9292",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#79ba16",
-          "description": "Step: 500",
+          "value": "#2a9292",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#79ba163d",
-          "description": "Step: 500",
+          "value": "#2a92923d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#79ba16cc",
-          "description": "Step: 500",
+          "value": "#2a9292cc",
           "type": "color"
         }
       },
       "3": {
         "baseColor": {
-          "value": "#d430e0",
-          "description": "Step: 500",
+          "value": "#bf40bf",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#d430e0",
-          "description": "Step: 500",
+          "value": "#bf40bf",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#d430e03d",
-          "description": "Step: 500",
+          "value": "#bf40bf3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#d430e0cc",
-          "description": "Step: 500",
+          "value": "#bf40bfcc",
           "type": "color"
         }
       },
       "4": {
         "baseColor": {
-          "value": "#ee670a",
-          "description": "Step: 500",
+          "value": "#aa573c",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#ee670a",
-          "description": "Step: 500",
+          "value": "#aa573c",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#ee670a3d",
-          "description": "Step: 500",
+          "value": "#aa573c3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#ee670acc",
-          "description": "Step: 500",
+          "value": "#aa573ccc",
           "type": "color"
         }
       },
       "5": {
         "baseColor": {
-          "value": "#993bf3",
-          "description": "Step: 500",
+          "value": "#955ae7",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#993bf3",
-          "description": "Step: 500",
+          "value": "#955ae7",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#993bf33d",
-          "description": "Step: 500",
+          "value": "#955ae73d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#993bf3cc",
-          "description": "Step: 500",
+          "value": "#955ae7cc",
           "type": "color"
         }
       },
       "6": {
         "baseColor": {
-          "value": "#16d6c1",
-          "description": "Step: 400",
+          "value": "#398bc6",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#16d6c1",
-          "description": "Step: 400",
+          "value": "#398bc6",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#16d6c13d",
-          "description": "Step: 400",
+          "value": "#398bc63d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#16d6c1cc",
-          "description": "Step: 400",
+          "value": "#398bc6cc",
           "type": "color"
         }
       },
       "7": {
         "baseColor": {
-          "value": "#ef59a3",
-          "description": "Step: 400",
+          "value": "#be4678",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#ef59a3",
-          "description": "Step: 400",
+          "value": "#be4678",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#ef59a33d",
-          "description": "Step: 400",
+          "value": "#be46783d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#ef59a3cc",
-          "description": "Step: 400",
+          "value": "#be4678cc",
           "type": "color"
         }
       },
       "8": {
         "baseColor": {
-          "value": "#f7bf17",
-          "description": "Step: 400",
+          "value": "#a06e3b",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#f7bf17",
-          "description": "Step: 400",
+          "value": "#a06e3b",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#f7bf173d",
-          "description": "Step: 400",
+          "value": "#a06e3b3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#f7bf17cc",
-          "description": "Step: 400",
+          "value": "#a06e3bcc",
           "type": "color"
         }
       }
     },
     "shadowAlpha": {
-      "value": 0.32,
+      "value": 0.24,
       "type": "number"
     }
   },
-  "light": {
+  "cave-light": {
     "meta": {
-      "themeName": "light"
+      "themeName": "cave-light"
     },
     "text": {
       "primary": {
-        "value": "#2b2b2b",
-        "description": "Step: 750",
+        "value": "#26232a",
         "type": "color"
       },
       "secondary": {
-        "value": "#474747",
-        "description": "Step: 650",
+        "value": "#585260",
         "type": "color"
       },
       "muted": {
-        "value": "#636363",
-        "description": "Step: 550",
+        "value": "#585260",
         "type": "color"
       },
       "placeholder": {
-        "value": "#808080",
-        "description": "Step: 450",
+        "value": "#655f6d",
         "type": "color"
       },
       "active": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#19171c",
         "type": "color"
       },
       "feature": {
-        "value": "#484bed",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "ok": {
-        "value": "#20b456",
-        "description": "Step: 500",
+        "value": "#2a9292",
         "type": "color"
       },
       "error": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#be4678",
         "type": "color"
       },
       "warning": {
-        "value": "#d3a20b",
-        "description": "Step: 500",
+        "value": "#a06e3b",
         "type": "color"
       },
       "info": {
-        "value": "#2472f2",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       }
     },
     "icon": {
       "primary": {
-        "value": "#393939",
-        "description": "Step: 700",
+        "value": "#26232a",
         "type": "color"
       },
       "secondary": {
-        "value": "#717171",
-        "description": "Step: 500",
+        "value": "#585260",
         "type": "color"
       },
       "muted": {
-        "value": "#9c9c9c",
-        "description": "Step: 350",
+        "value": "#585260",
         "type": "color"
       },
       "placeholder": {
-        "value": "#aaaaaa",
-        "description": "Step: 300",
+        "value": "#655f6d",
         "type": "color"
       },
       "active": {
-        "value": "#000000",
-        "description": "Step: 900",
+        "value": "#19171c",
         "type": "color"
       },
       "feature": {
-        "value": "#484bed",
-        "description": "Step: 500",
+        "value": "#576ddb",
         "type": "color"
       },
       "ok": {
-        "value": "#1b9447",
-        "description": "Step: 600",
+        "value": "#2a9292",
         "type": "color"
       },
       "error": {
-        "value": "#c91818",
-        "description": "Step: 600",
+        "value": "#be4678",
         "type": "color"
       },
       "warning": {
-        "value": "#f7bf17",
-        "description": "Step: 400",
+        "value": "#a06e3b",
         "type": "color"
       },
       "info": {
-        "value": "#135acd",
-        "description": "Step: 600",
+        "value": "#576ddb",
         "type": "color"
       }
     },
     "background": {
       "100": {
         "base": {
-          "value": "#eaeaea",
-          "description": "Step: 75",
+          "value": "#ccc9d2",
           "type": "color"
         },
         "hovered": {
-          "value": "#e3e3e3",
-          "description": "Step: 100",
+          "value": "#b7b3bd",
           "type": "color"
         },
         "active": {
-          "value": "#d5d5d5",
-          "description": "Step: 150",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#e3e3e3",
-          "description": "Step: 100",
+          "value": "#a19da7",
           "type": "color"
         }
       },
       "300": {
         "base": {
-          "value": "#f8f8f8",
-          "description": "Step: 25",
+          "value": "#e2dfe7",
           "type": "color"
         },
         "hovered": {
-          "value": "#eaeaea",
-          "description": "Step: 75",
+          "value": "#ccc9d2",
           "type": "color"
         },
         "active": {
-          "value": "#e3e3e3",
-          "description": "Step: 100",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#eaeaea",
-          "description": "Step: 75",
+          "value": "#b7b3bd",
           "type": "color"
         }
       },
       "500": {
         "base": {
-          "value": "#ffffff",
-          "description": "Step: 0",
+          "value": "#efecf4",
           "type": "color"
         },
         "hovered": {
-          "value": "#00000008",
-          "description": "Step: 900",
+          "value": "#ece9f1",
           "type": "color"
         },
         "active": {
-          "value": "#0000000f",
-          "description": "Step: 900",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#f1f1f1",
-          "description": "Step: 50",
+          "value": "#e9e6ee",
           "type": "color"
         }
       },
       "on300": {
         "base": {
-          "value": "#f1f1f1",
-          "description": "Step: 50",
+          "value": "#efecf4",
           "type": "color"
         },
         "hovered": {
-          "value": "#e3e3e3",
-          "description": "Step: 100",
+          "value": "#ece9f1",
           "type": "color"
         },
         "active": {
-          "value": "#d5d5d5",
-          "description": "Step: 150",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#e3e3e3",
-          "description": "Step: 100",
+          "value": "#e9e6ee",
           "type": "color"
         }
       },
       "on500": {
         "base": {
-          "value": "#f1f1f1",
-          "description": "Step: 50",
+          "value": "#ccc9d2",
           "type": "color"
         },
         "hovered": {
-          "value": "#f8f8f8",
-          "description": "Step: 25",
+          "value": "#b7b3bd",
           "type": "color"
         },
         "active": {
-          "value": "#ffffff",
-          "description": "Step: 0",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#f8f8f8",
-          "description": "Step: 25",
+          "value": "#a19da7",
           "type": "color"
         }
       },
       "ok": {
         "base": {
-          "value": "#1b944726",
-          "description": "Step: 600",
+          "value": "#2a929226",
           "type": "color"
         },
         "hovered": {
-          "value": "#1b944733",
-          "description": "Step: 600",
+          "value": "#2a929233",
           "type": "color"
         },
         "active": {
-          "value": "#1b944740",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#1b944733",
-          "description": "Step: 600",
+          "value": "#2a929240",
           "type": "color"
         }
       },
       "error": {
         "base": {
-          "value": "#c9181826",
-          "description": "Step: 600",
+          "value": "#be467826",
           "type": "color"
         },
         "hovered": {
-          "value": "#c9181833",
-          "description": "Step: 600",
+          "value": "#be467833",
           "type": "color"
         },
         "active": {
-          "value": "#c9181840",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#c9181833",
-          "description": "Step: 600",
+          "value": "#be467840",
           "type": "color"
         }
       },
       "warning": {
         "base": {
-          "value": "#f6a72426",
-          "description": "Step: 400",
+          "value": "#a06e3b26",
           "type": "color"
         },
         "hovered": {
-          "value": "#f6a72433",
-          "description": "Step: 400",
+          "value": "#a06e3b33",
           "type": "color"
         },
         "active": {
-          "value": "#f6a72440",
-          "description": "Step: 400",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#f6a72433",
-          "description": "Step: 400",
+          "value": "#a06e3b40",
           "type": "color"
         }
       },
       "info": {
         "base": {
-          "value": "#2472f226",
-          "description": "Step: 500",
+          "value": "#576ddb26",
           "type": "color"
         },
         "hovered": {
-          "value": "#2472f233",
-          "description": "Step: 500",
+          "value": "#576ddb33",
           "type": "color"
         },
         "active": {
-          "value": "#2472f240",
-          "description": "Step: 500",
-          "type": "color"
-        },
-        "focused": {
-          "value": "#2472f233",
-          "description": "Step: 500",
+          "value": "#576ddb40",
           "type": "color"
         }
       }
     },
     "border": {
       "primary": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
+        "value": "#8b8792",
         "type": "color"
       },
       "secondary": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
+        "value": "#8b8792",
         "type": "color"
       },
       "muted": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
-        "type": "color"
-      },
-      "focused": {
-        "value": "#484bed",
-        "description": "Step: 500",
+        "value": "#655f6d",
         "type": "color"
       },
       "active": {
-        "value": "#b8b8b8",
-        "description": "Step: 250",
+        "value": "#655f6d",
         "type": "color"
       },
       "onMedia": {
-        "value": "#b8b8b84d",
-        "description": "Step: 250",
+        "value": "#efecf41a",
         "type": "color"
       },
       "ok": {
-        "value": "#1b944726",
-        "description": "Step: 600",
+        "value": "#2a929226",
         "type": "color"
       },
       "error": {
-        "value": "#eb2d2d26",
-        "description": "Step: 500",
+        "value": "#be467826",
         "type": "color"
       },
       "warning": {
-        "value": "#f6a72426",
-        "description": "Step: 400",
+        "value": "#a06e3b26",
         "type": "color"
       },
       "info": {
-        "value": "#2472f226",
-        "description": "Step: 500",
+        "value": "#576ddb26",
         "type": "color"
       }
     },
     "editor": {
       "background": {
-        "value": "#ffffff",
-        "description": "Step: 0",
+        "value": "#efecf4",
         "type": "color"
       },
       "indent_guide": {
-        "value": "#e3e3e3",
-        "description": "Step: 100",
+        "value": "#655f6d",
         "type": "color"
       },
       "indent_guide_active": {
-        "value": "#d5d5d5",
-        "description": "Step: 150",
+        "value": "#8b8792",
         "type": "color"
       },
       "line": {
         "active": {
-          "value": "#0000000f",
-          "description": "Step: 900",
+          "value": "#e2dfe7",
           "type": "color"
         },
         "highlighted": {
-          "value": "#0000001f",
-          "description": "Step: 900",
-          "type": "color"
-        },
-        "inserted": {
-          "value": "#1b944740",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "deleted": {
-          "value": "#c9181840",
-          "description": "Step: 600",
-          "type": "color"
-        },
-        "modified": {
-          "value": "#2472f240",
-          "description": "Step: 500",
+          "value": "#ccc9d2",
           "type": "color"
         }
       },
       "highlight": {
         "selection": {
-          "value": "#2472f23d",
-          "description": "Step: 500",
+          "value": "#576ddb3d",
           "type": "color"
         },
         "occurrence": {
-          "value": "#0000000f",
-          "description": "Step: 900",
+          "value": "#8b87921f",
           "type": "color"
         },
         "activeOccurrence": {
-          "value": "#00000029",
-          "description": "Step: 900",
+          "value": "#8b87923d",
           "type": "color"
         },
         "matchingBracket": {
-          "value": "#ffffff",
-          "description": "Step: 0",
+          "value": "#e9e6ee",
           "type": "color"
         },
         "match": {
-          "value": "#fce9b7",
-          "description": "Step: 100",
+          "value": "#d5bdfa",
           "type": "color"
         },
         "activeMatch": {
-          "value": "#f9da82",
-          "description": "Step: 200",
+          "value": "#a775ee3d",
           "type": "color"
         },
         "related": {
-          "value": "#ffffff",
-          "description": "Step: 0",
+          "value": "#ece9f1",
           "type": "color"
         }
       },
       "gutter": {
         "primary": {
-          "value": "#aaaaaa",
-          "description": "Step: 300",
+          "value": "#655f6d",
           "type": "color"
         },
         "active": {
-          "value": "#000000",
-          "description": "Step: 900",
+          "value": "#19171c",
           "type": "color"
         }
       }
     },
     "syntax": {
       "primary": {
-        "value": "#1c1c1c",
-        "description": "Step: 800",
+        "value": "#19171c",
         "type": "color"
       },
       "comment": {
-        "value": "#717171",
-        "description": "Step: 500",
+        "value": "#585260",
         "type": "color"
       },
       "keyword": {
-        "value": "#1819a1",
-        "description": "Step: 700",
+        "value": "#576ddb",
         "type": "color"
       },
       "function": {
-        "value": "#bb550e",
-        "description": "Step: 600",
+        "value": "#a06e3b",
         "type": "color"
       },
       "type": {
-        "value": "#a8820e",
-        "description": "Step: 600",
+        "value": "#398bc6",
         "type": "color"
       },
       "variant": {
-        "value": "#97142a",
-        "description": "Step: 700",
+        "value": "#576ddb",
         "type": "color"
       },
       "property": {
-        "value": "#106c4e",
-        "description": "Step: 700",
+        "value": "#576ddb",
         "type": "color"
       },
       "enum": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "operator": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "string": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#aa573c",
         "type": "color"
       },
       "number": {
-        "value": "#484bed",
-        "description": "Step: 500",
+        "value": "#2a9292",
         "type": "color"
       },
       "boolean": {
-        "value": "#eb2d2d",
-        "description": "Step: 500",
+        "value": "#2a9292",
         "type": "color"
       }
     },
     "player": {
       "1": {
         "baseColor": {
-          "value": "#2472f2",
-          "description": "Step: 500",
+          "value": "#576ddb",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#2472f2",
-          "description": "Step: 500",
+          "value": "#576ddb",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#2472f23d",
-          "description": "Step: 500",
+          "value": "#576ddb3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#2472f2cc",
-          "description": "Step: 500",
+          "value": "#576ddbcc",
           "type": "color"
         }
       },
       "2": {
         "baseColor": {
-          "value": "#12d796",
-          "description": "Step: 400",
+          "value": "#2a9292",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#12d796",
-          "description": "Step: 400",
+          "value": "#2a9292",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#12d7963d",
-          "description": "Step: 400",
+          "value": "#2a92923d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#12d796cc",
-          "description": "Step: 400",
+          "value": "#2a9292cc",
           "type": "color"
         }
       },
       "3": {
         "baseColor": {
-          "value": "#de57e8",
-          "description": "Step: 400",
+          "value": "#bf40bf",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#de57e8",
-          "description": "Step: 400",
+          "value": "#bf40bf",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#de57e83d",
-          "description": "Step: 400",
+          "value": "#bf40bf3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#de57e8cc",
-          "description": "Step: 400",
+          "value": "#bf40bfcc",
           "type": "color"
         }
       },
       "4": {
         "baseColor": {
-          "value": "#f9812e",
-          "description": "Step: 400",
+          "value": "#aa573c",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#f9812e",
-          "description": "Step: 400",
+          "value": "#aa573c",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#f9812e3d",
-          "description": "Step: 400",
+          "value": "#aa573c3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#f9812ecc",
-          "description": "Step: 400",
+          "value": "#aa573ccc",
           "type": "color"
         }
       },
       "5": {
         "baseColor": {
-          "value": "#b066f8",
-          "description": "Step: 400",
+          "value": "#955ae7",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#b066f8",
-          "description": "Step: 400",
+          "value": "#955ae7",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#b066f83d",
-          "description": "Step: 400",
+          "value": "#955ae73d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#b066f8cc",
-          "description": "Step: 400",
+          "value": "#955ae7cc",
           "type": "color"
         }
       },
       "6": {
         "baseColor": {
-          "value": "#16d6c1",
-          "description": "Step: 400",
+          "value": "#398bc6",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#16d6c1",
-          "description": "Step: 400",
+          "value": "#398bc6",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#16d6c13d",
-          "description": "Step: 400",
+          "value": "#398bc63d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#16d6c1cc",
-          "description": "Step: 400",
+          "value": "#398bc6cc",
           "type": "color"
         }
       },
       "7": {
         "baseColor": {
-          "value": "#ef59a3",
-          "description": "Step: 400",
+          "value": "#be4678",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#ef59a3",
-          "description": "Step: 400",
+          "value": "#be4678",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#ef59a33d",
-          "description": "Step: 400",
+          "value": "#be46783d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#ef59a3cc",
-          "description": "Step: 400",
+          "value": "#be4678cc",
           "type": "color"
         }
       },
       "8": {
         "baseColor": {
-          "value": "#f7bf17",
-          "description": "Step: 400",
+          "value": "#a06e3b",
           "type": "color"
         },
         "cursorColor": {
-          "value": "#f7bf17",
-          "description": "Step: 400",
+          "value": "#a06e3b",
           "type": "color"
         },
         "selectionColor": {
-          "value": "#f7bf173d",
-          "description": "Step: 400",
+          "value": "#a06e3b3d",
           "type": "color"
         },
         "borderColor": {
-          "value": "#f7bf17cc",
-          "description": "Step: 400",
+          "value": "#a06e3bcc",
           "type": "color"
         }
       }

styles/src/buildThemes.ts 🔗

@@ -2,19 +2,24 @@ import * as fs from "fs";
 import * as path from "path";
 import app from "./styleTree/app";
 import { dark as caveDark, light as caveLight } from "./themes/cave";
-import dark from "./themes/dark";
-import light from "./themes/light";
 import { dark as solarizedDark, light as solarizedLight } from "./themes/solarized";
 import { dark as sulphurpoolDark, light as sulphurpoolLight } from "./themes/sulphurpool";
 import snakeCase from "./utils/snakeCase";
 
 const themes = [
-  dark, light,
   caveDark, caveLight,
   solarizedDark, solarizedLight,
   sulphurpoolDark, sulphurpoolLight
 ];
 
+const themeDirectory = `${__dirname}/../../assets/themes/`;
+
+// Clear existing themes
+for (const file of fs.readdirSync(themeDirectory)) {
+  fs.unlinkSync(path.join(themeDirectory, file));
+}
+
+// Write new themes to theme directory
 for (let theme of themes) {
   let styleTree = snakeCase(app(theme));
   let styleTreeJSON = JSON.stringify(styleTree, null, 2);

styles/src/buildTokens.ts 🔗

@@ -1,8 +1,8 @@
 import * as fs from "fs";
 import * as path from "path";
-import dark from "./themes/dark";
-import light from "./themes/light";
 import { light as solarizedLight, dark as solarizedDark } from "./themes/solarized";
+// Use cave as "light" and "dark" themes
+import { light, dark } from "./themes/cave";
 import Theme from "./themes/theme";
 import { colors, fontFamilies, fontSizes, fontWeights, sizes } from "./tokens";
 

styles/src/themes/base16.ts 🔗

@@ -1,116 +1,123 @@
-import { ColorToken, fontWeights, NumberToken } from "../tokens";
+import chroma from "chroma-js";
+import { Scale, Color } from "chroma-js";
+import { color, ColorToken, fontWeights, NumberToken } from "../tokens";
 import { withOpacity } from "../utils/color";
 import Theme, { buildPlayer, Syntax } from "./theme";
 
-export interface Accents {
-  "red": ColorToken,
-  "orange": ColorToken,
-  "yellow": ColorToken,
-  "green": ColorToken,
-  "cyan": ColorToken,
-  "blue": ColorToken,
-  "violet": ColorToken,
-  "magenta": ColorToken,
+export function colorRamp(color: Color): Scale {
+  let hue = color.hsl()[0];
+  let endColor = chroma.hsl(hue, 0.88, 0.96);
+  let startColor = chroma.hsl(hue, 0.68, 0.12);
+  return chroma
+    .scale([startColor, color, endColor])
+    .mode("hsl");
 }
 
-export function createTheme(name: string, isLight: boolean, neutral: ColorToken[], accent: Accents): Theme {
+// Neutral. 8 stops from 0 to 1.
+
+export function createTheme(name: string, isLight: boolean, ramps: { [rampName: string]: Scale }, blend?: number): Theme {
   if (isLight) {
-    neutral = [...neutral].reverse();
+    for (var rampName in ramps) {
+      ramps[rampName] = ramps[rampName].domain([1, 0]);
+    }
+    ramps.neutral = ramps.neutral.domain([7, 0]);
+  } else {
+    ramps.neutral = ramps.neutral.domain([0, 7]);
+  }
+
+  if (blend === undefined) {
+    blend = isLight ? 0.12 : 0.24;
+  }
+
+  function rampColor(ramp: Scale, index: number): ColorToken {
+    return color(ramp(index).hex());
   }
-  let blend = isLight ? 0.12 : 0.24;
 
   const backgroundColor = {
+    // Title bar
     100: {
-      base: neutral[1],
-      hovered: withOpacity(neutral[2], blend),
-      active: withOpacity(neutral[2], blend * 1.5),
-      focused: withOpacity(neutral[2], blend),
+      base: rampColor(ramps.neutral, 1.25),
+      hovered: rampColor(ramps.neutral, 1.5),
+      active: rampColor(ramps.neutral, 1.75),
     },
+    // Midground (panels, etc)
     300: {
-      base: neutral[1],
-      hovered: withOpacity(neutral[2], blend),
-      active: withOpacity(neutral[2], blend * 1.5),
-      focused: withOpacity(neutral[2], blend),
+      base: rampColor(ramps.neutral, 1),
+      hovered: rampColor(ramps.neutral, 1.25),
+      active: rampColor(ramps.neutral, 1.5),
     },
+    // Editor
     500: {
-      base: neutral[0],
-      hovered: withOpacity(neutral[1], blend),
-      active: withOpacity(neutral[1], blend * 1.5),
-      focused: withOpacity(neutral[1], blend),
+      base: rampColor(ramps.neutral, 0),
+      hovered: rampColor(ramps.neutral, 0.25),
+      active: rampColor(ramps.neutral, 0.5),
     },
     on300: {
-      base: neutral[0],
-      hovered: withOpacity(neutral[1], blend),
-      active: withOpacity(neutral[1], blend * 2),
-      focused: withOpacity(neutral[1], blend),
+      base: rampColor(ramps.neutral, 0),
+      hovered: rampColor(ramps.neutral, 0.25),
+      active: rampColor(ramps.neutral, 0.5),
     },
     on500: {
-      base: neutral[1],
-      hovered: withOpacity(neutral[2], blend),
-      active: withOpacity(neutral[2], blend * 2),
-      focused: withOpacity(neutral[2], blend),
+      base: rampColor(ramps.neutral, 1.25),
+      hovered: rampColor(ramps.neutral, 1.5),
+      active: rampColor(ramps.neutral, 1.75),
     },
     ok: {
-      base: withOpacity(accent.green, 0.15),
-      hovered: withOpacity(accent.green, 0.20),
-      active: withOpacity(accent.green, 0.25),
-      focused: withOpacity(accent.green, 0.20),
+      base: withOpacity(rampColor(ramps.green, 0.5), 0.15),
+      hovered: withOpacity(rampColor(ramps.green, 0.5), 0.20),
+      active: withOpacity(rampColor(ramps.green, 0.5), 0.25),
     },
     error: {
-      base: withOpacity(accent.red, 0.15),
-      hovered: withOpacity(accent.red, 0.20),
-      active: withOpacity(accent.red, 0.25),
-      focused: withOpacity(accent.red, 0.20),
+      base: withOpacity(rampColor(ramps.red, 0.5), 0.15),
+      hovered: withOpacity(rampColor(ramps.red, 0.5), 0.20),
+      active: withOpacity(rampColor(ramps.red, 0.5), 0.25),
     },
     warning: {
-      base: withOpacity(accent.yellow, 0.15),
-      hovered: withOpacity(accent.yellow, 0.20),
-      active: withOpacity(accent.yellow, 0.25),
-      focused: withOpacity(accent.yellow, 0.20),
+      base: withOpacity(rampColor(ramps.yellow, 0.5), 0.15),
+      hovered: withOpacity(rampColor(ramps.yellow, 0.5), 0.20),
+      active: withOpacity(rampColor(ramps.yellow, 0.5), 0.25),
     },
     info: {
-      base: withOpacity(accent.blue, 0.15),
-      hovered: withOpacity(accent.blue, 0.20),
-      active: withOpacity(accent.blue, 0.25),
-      focused: withOpacity(accent.blue, 0.20),
+      base: withOpacity(rampColor(ramps.blue, 0.5), 0.15),
+      hovered: withOpacity(rampColor(ramps.blue, 0.5), 0.20),
+      active: withOpacity(rampColor(ramps.blue, 0.5), 0.25),
     },
   };
 
   const borderColor = {
-    primary: neutral[0],
-    secondary: neutral[1],
-    muted: neutral[3],
-    focused: neutral[3],
-    active: neutral[3],
-    onMedia: withOpacity(neutral[0], 0.1),
-    ok: withOpacity(accent.green, 0.15),
-    error: withOpacity(accent.red, 0.15),
-    warning: withOpacity(accent.yellow, 0.15),
-    info: withOpacity(accent.blue, 0.15),
+    primary: rampColor(ramps.neutral, isLight ? 2 : 0),
+    secondary: rampColor(ramps.neutral, isLight ? 2 : 1),
+    muted: rampColor(ramps.neutral, isLight ? 4 : 3),
+    active: rampColor(ramps.neutral, isLight ? 4 : 3),
+    onMedia: withOpacity(rampColor(ramps.neutral, 0), 0.1),
+    ok: withOpacity(rampColor(ramps.green, 0.5), 0.15),
+    error: withOpacity(rampColor(ramps.red, 0.5), 0.15),
+    warning: withOpacity(rampColor(ramps.yellow, 0.5), 0.15),
+    info: withOpacity(rampColor(ramps.blue, 0.5), 0.15),
   };
 
   const textColor = {
-    primary: neutral[6],
-    secondary: neutral[5],
-    muted: neutral[5],
-    placeholder: neutral[4],
-    active: neutral[7],
-    feature: accent.blue,
-    ok: accent.green,
-    error: accent.red,
-    warning: accent.yellow,
-    info: accent.blue,
+    primary: rampColor(ramps.neutral, 6),
+    secondary: rampColor(ramps.neutral, 5),
+    muted: rampColor(ramps.neutral, 5),
+    placeholder: rampColor(ramps.neutral, 4),
+    active: rampColor(ramps.neutral, 7),
+    feature: rampColor(ramps.blue, 0.5),
+    ok: rampColor(ramps.green, 0.5),
+    error: rampColor(ramps.red, 0.5),
+    warning: rampColor(ramps.yellow, 0.5),
+    info: rampColor(ramps.blue, 0.5),
   };
 
   const player = {
-    1: buildPlayer(accent.blue),
-    2: buildPlayer(accent.green),
-    3: buildPlayer(accent.magenta),
-    4: buildPlayer(accent.orange),
-    5: buildPlayer(accent.violet),
-    6: buildPlayer(accent.cyan),
-    7: buildPlayer(accent.red),
-    8: buildPlayer(accent.yellow),
+    1: buildPlayer(rampColor(ramps.blue, 0.5)),
+    2: buildPlayer(rampColor(ramps.green, 0.5)),
+    3: buildPlayer(rampColor(ramps.magenta, 0.5)),
+    4: buildPlayer(rampColor(ramps.orange, 0.5)),
+    5: buildPlayer(rampColor(ramps.violet, 0.5)),
+    6: buildPlayer(rampColor(ramps.cyan, 0.5)),
+    7: buildPlayer(rampColor(ramps.red, 0.5)),
+    8: buildPlayer(rampColor(ramps.yellow, 0.5)),
   };
 
   const editor = {
@@ -118,20 +125,17 @@ export function createTheme(name: string, isLight: boolean, neutral: ColorToken[
     indent_guide: borderColor.muted,
     indent_guide_active: borderColor.secondary,
     line: {
-      active: withOpacity(neutral[7], 0.07),
-      highlighted: withOpacity(neutral[7], 0.12),
-      inserted: backgroundColor.ok.active,
-      deleted: backgroundColor.error.active,
-      modified: backgroundColor.info.active,
+      active: rampColor(ramps.neutral, 1),
+      highlighted: rampColor(ramps.neutral, 1.25), // TODO: Where is this used?
     },
     highlight: {
       selection: player[1].selectionColor,
-      occurrence: withOpacity(neutral[7], blend / 2),
-      activeOccurrence: withOpacity(neutral[7], blend),
-      matchingBracket: backgroundColor[500].active,
-      match: withOpacity(accent.violet, blend * 2),
-      activeMatch: withOpacity(accent.violet, blend * 3),
-      related: backgroundColor[500].focused,
+      occurrence: withOpacity(rampColor(ramps.neutral, 2), blend),
+      activeOccurrence: withOpacity(rampColor(ramps.neutral, 2), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
+      matchingBracket: backgroundColor[500].active, // TODO: Not hooked up
+      match: rampColor(ramps.violet, 0.15),
+      activeMatch: withOpacity(rampColor(ramps.violet, 0.4), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
+      related: backgroundColor[500].hovered,
     },
     gutter: {
       primary: textColor.placeholder,
@@ -141,59 +145,59 @@ export function createTheme(name: string, isLight: boolean, neutral: ColorToken[
 
   const syntax: Syntax = {
     primary: {
-      color: neutral[7],
+      color: rampColor(ramps.neutral, 7),
       weight: fontWeights.normal,
     },
     comment: {
-      color: neutral[5],
+      color: rampColor(ramps.neutral, 5),
       weight: fontWeights.normal,
     },
     punctuation: {
-      color: neutral[5],
+      color: rampColor(ramps.neutral, 6),
       weight: fontWeights.normal,
     },
     constant: {
-      color: neutral[4],
+      color: rampColor(ramps.neutral, 4),
       weight: fontWeights.normal,
     },
     keyword: {
-      color: accent.blue,
+      color: rampColor(ramps.blue, 0.5),
       weight: fontWeights.normal,
     },
     function: {
-      color: accent.yellow,
+      color: rampColor(ramps.yellow, 0.5),
       weight: fontWeights.normal,
     },
     type: {
-      color: accent.cyan,
+      color: rampColor(ramps.cyan, 0.5),
       weight: fontWeights.normal,
     },
     variant: {
-      color: accent.blue,
+      color: rampColor(ramps.blue, 0.5),
       weight: fontWeights.normal,
     },
     property: {
-      color: accent.blue,
+      color: rampColor(ramps.blue, 0.5),
       weight: fontWeights.normal,
     },
     enum: {
-      color: accent.orange,
+      color: rampColor(ramps.orange, 0.5),
       weight: fontWeights.normal,
     },
     operator: {
-      color: accent.orange,
+      color: rampColor(ramps.orange, 0.5),
       weight: fontWeights.normal,
     },
     string: {
-      color: accent.orange,
+      color: rampColor(ramps.orange, 0.5),
       weight: fontWeights.normal,
     },
     number: {
-      color: accent.green,
+      color: rampColor(ramps.green, 0.5),
       weight: fontWeights.normal,
     },
     boolean: {
-      color: accent.green,
+      color: rampColor(ramps.green, 0.5),
       weight: fontWeights.normal,
     },
     predictive: {
@@ -201,7 +205,7 @@ export function createTheme(name: string, isLight: boolean, neutral: ColorToken[
       weight: fontWeights.normal,
     },
     title: {
-      color: accent.yellow,
+      color: rampColor(ramps.yellow, 0.5),
       weight: fontWeights.bold,
     },
     emphasis: {
@@ -213,12 +217,12 @@ export function createTheme(name: string, isLight: boolean, neutral: ColorToken[
       weight: fontWeights.bold,
     },
     linkUri: {
-      color: accent.green,
+      color: rampColor(ramps.green, 0.5),
       weight: fontWeights.normal,
       underline: true,
     },
     linkText: {
-      color: accent.orange,
+      color: rampColor(ramps.orange, 0.5),
       weight: fontWeights.normal,
       italic: true,
     },

styles/src/themes/cave.ts 🔗

@@ -1,29 +1,19 @@
-import { createTheme } from "./base16";
-import { color } from "../tokens";
+import chroma from "chroma-js";
+import { colorRamp, createTheme } from "./base16";
 
 const name = "cave";
 
-const neutrals = [
-  color("#19171c"),
-  color("#26232a"),
-  color("#585260"),
-  color("#655f6d"),
-  color("#7e7887"),
-  color("#8b8792"),
-  color("#e2dfe7"),
-  color("#efecf4"),
-];
+const ramps = {
+  neutral: chroma.scale(["#19171c", "#26232a", "#585260", "#655f6d", "#7e7887", "#8b8792", "#e2dfe7", "#efecf4"]),
+  red: colorRamp(chroma("#be4678")),
+  orange: colorRamp(chroma("#aa573c")),
+  yellow: colorRamp(chroma("#a06e3b")),
+  green: colorRamp(chroma("#2a9292")),
+  cyan: colorRamp(chroma("#398bc6")),
+  blue: colorRamp(chroma("#576ddb")),
+  violet: colorRamp(chroma("#955ae7")),
+  magenta: colorRamp(chroma("#bf40bf")),
+}
 
-const colors = {
-  "red": color("#be4678"),
-  "orange": color("#aa573c"),
-  "yellow": color("#a06e3b"),
-  "green": color("#2a9292"),
-  "cyan": color("#398bc6"),
-  "blue": color("#576ddb"),
-  "violet": color("#955ae7"),
-  "magenta": color("#bf40bf"),
-};
-
-export const dark = createTheme(`${name}-dark`, false, neutrals, colors);
-export const light = createTheme(`${name}-light`, true, neutrals, colors);
+export const dark = createTheme(`${name}-dark`, false, ramps);
+export const light = createTheme(`${name}-light`, true, ramps);

styles/src/themes/dark.ts 🔗

@@ -1,240 +0,0 @@
-import { colors, fontWeights, NumberToken } from "../tokens";
-import { withOpacity } from "../utils/color";
-import Theme, { buildPlayer, Syntax } from "./theme";
-
-const backgroundColor = {
-  100: {
-    base: colors.neutral[750],
-    hovered: colors.neutral[725],
-    active: colors.neutral[800],
-    focused: colors.neutral[675],
-  },
-  300: {
-    base: colors.neutral[800],
-    hovered: colors.neutral[775],
-    active: colors.neutral[750],
-    focused: colors.neutral[775],
-  },
-  500: {
-    base: colors.neutral[900],
-    hovered: withOpacity(colors.neutral[0], 0.08),
-    active: withOpacity(colors.neutral[0], 0.12),
-    focused: colors.neutral[825],
-  },
-  on300: {
-    base: withOpacity(colors.neutral[850], 0.5),
-    hovered: colors.neutral[875],
-    active: colors.neutral[900],
-    focused: colors.neutral[875],
-  },
-  on500: {
-    base: colors.neutral[850],
-    hovered: colors.neutral[800],
-    active: colors.neutral[775],
-    focused: colors.neutral[800],
-  },
-  ok: {
-    base: withOpacity(colors.green[600], 0.15),
-    hovered: withOpacity(colors.green[600], 0.20),
-    active: withOpacity(colors.green[600], 0.25),
-    focused: withOpacity(colors.green[600], 0.20),
-  },
-  error: {
-    base: withOpacity(colors.red[600], 0.15),
-    hovered: withOpacity(colors.red[600], 0.20),
-    active: withOpacity(colors.red[600], 0.25),
-    focused: withOpacity(colors.red[600], 0.20),
-  },
-  warning: {
-    base: withOpacity(colors.amber[400], 0.15),
-    hovered: withOpacity(colors.amber[400], 0.20),
-    active: withOpacity(colors.amber[400], 0.25),
-    focused: withOpacity(colors.amber[400], 0.20),
-  },
-  info: {
-    base: withOpacity(colors.blue[500], 0.15),
-    hovered: withOpacity(colors.blue[500], 0.20),
-    active: withOpacity(colors.blue[500], 0.25),
-    focused: withOpacity(colors.blue[500], 0.20),
-  },
-};
-
-const borderColor = {
-  primary: colors.neutral[875],
-  secondary: colors.neutral[775],
-  muted: colors.neutral[675],
-  focused: colors.indigo[500],
-  active: colors.neutral[900],
-  onMedia: withOpacity(colors.neutral[875], 0.1),
-  ok: withOpacity(colors.green[600], 0.15),
-  error: withOpacity(colors.red[500], 0.15),
-  warning: withOpacity(colors.amber[400], 0.15),
-  info: withOpacity(colors.blue[500], 0.15),
-};
-
-const textColor = {
-  primary: colors.neutral[50],
-  secondary: colors.neutral[350],
-  muted: colors.neutral[450],
-  placeholder: colors.neutral[650],
-  active: colors.neutral[0],
-  feature: colors.blue[400],
-  ok: colors.green[600],
-  error: colors.red[400],
-  warning: colors.amber[300],
-  info: colors.blue[500],
-};
-
-const iconColor = {
-  primary: colors.neutral[200],
-  secondary: colors.neutral[350],
-  muted: colors.neutral[600],
-  placeholder: colors.neutral[700],
-  active: colors.neutral[0],
-  feature: colors.blue[500],
-  ok: colors.green[600],
-  error: colors.red[500],
-  warning: colors.amber[400],
-  info: colors.blue[600],
-};
-
-const player = {
-  1: buildPlayer(colors.blue[500]),
-  2: buildPlayer(colors.lime[500]),
-  3: buildPlayer(colors.fuschia[500]),
-  4: buildPlayer(colors.orange[500]),
-  5: buildPlayer(colors.purple[500]),
-  6: buildPlayer(colors.teal[400]),
-  7: buildPlayer(colors.pink[400]),
-  8: buildPlayer(colors.yellow[400]),
-};
-
-const editor = {
-  background: backgroundColor[500].base,
-  indent_guide: borderColor.muted,
-  indent_guide_active: borderColor.secondary,
-  line: {
-    active: withOpacity(colors.neutral[0], 0.07),
-    highlighted: withOpacity(colors.neutral[0], 0.12),
-    inserted: backgroundColor.ok.active,
-    deleted: backgroundColor.error.active,
-    modified: backgroundColor.info.active,
-  },
-  highlight: {
-    selection: player[1].selectionColor,
-    occurrence: withOpacity(colors.neutral[0], 0.12),
-    activeOccurrence: withOpacity(colors.neutral[0], 0.16),
-    matchingBracket: backgroundColor[500].active,
-    match: withOpacity(colors.violet[700], 0.5),
-    activeMatch: withOpacity(colors.violet[600], 0.7),
-    related: backgroundColor[500].focused,
-  },
-  gutter: {
-    primary: textColor.placeholder,
-    active: textColor.active,
-  },
-};
-
-const syntax: Syntax = {
-  primary: {
-    color: colors.neutral[150],
-    weight: fontWeights.normal,
-  },
-  comment: {
-    color: colors.neutral[300],
-    weight: fontWeights.normal,
-  },
-  punctuation: {
-    color: colors.neutral[200],
-    weight: fontWeights.normal,
-  },
-  constant: {
-    color: colors.neutral[150],
-    weight: fontWeights.normal,
-  },
-  keyword: {
-    color: colors.blue[400],
-    weight: fontWeights.normal,
-  },
-  function: {
-    color: colors.yellow[200],
-    weight: fontWeights.normal,
-  },
-  type: {
-    color: colors.teal[300],
-    weight: fontWeights.normal,
-  },
-  variant: {
-    color: colors.sky[300],
-    weight: fontWeights.normal,
-  },
-  property: {
-    color: colors.blue[400],
-    weight: fontWeights.normal,
-  },
-  enum: {
-    color: colors.orange[500],
-    weight: fontWeights.normal,
-  },
-  operator: {
-    color: colors.orange[500],
-    weight: fontWeights.normal,
-  },
-  string: {
-    color: colors.orange[300],
-    weight: fontWeights.normal,
-  },
-  number: {
-    color: colors.lime[300],
-    weight: fontWeights.normal,
-  },
-  boolean: {
-    color: colors.lime[300],
-    weight: fontWeights.normal,
-  },
-  predictive: {
-    color: textColor.muted,
-    weight: fontWeights.normal,
-  },
-  title: {
-    color: colors.amber[500],
-    weight: fontWeights.bold,
-  },
-  emphasis: {
-    color: textColor.feature,
-    weight: fontWeights.normal,
-  },
-  "emphasis.strong": {
-    color: textColor.feature,
-    weight: fontWeights.bold,
-  },
-  linkUri: {
-    color: colors.lime[500],
-    weight: fontWeights.normal,
-    underline: true,
-  },
-  linkText: {
-    color: colors.orange[500],
-    weight: fontWeights.normal,
-    italic: true,
-  },
-};
-
-const shadowAlpha: NumberToken = {
-  value: 0.32,
-  type: "number",
-};
-
-const theme: Theme = {
-  name: "dark",
-  backgroundColor,
-  borderColor,
-  textColor,
-  iconColor,
-  editor,
-  syntax,
-  player,
-  shadowAlpha,
-};
-
-export default theme;

styles/src/themes/gruvbox.ts 🔗

@@ -0,0 +1,30 @@
+import chroma from "chroma-js";
+import { createTheme } from "./base16";
+
+const name = "cave";
+
+const colors = {
+  "red": chroma("#be4678"),
+  "orange": chroma("#aa573c"),
+  "yellow": chroma("#a06e3b"),
+  "green": chroma("#2a9292"),
+  "cyan": chroma("#398bc6"),
+  "blue": chroma("#576ddb"),
+  "violet": chroma("#955ae7"),
+  "magenta": chroma("#bf40bf"),
+};
+
+const ramps = {
+  neutral: chroma.scale(["#19171c", "#26232a", "#585260", "#655f6d", "#7e7887", "#8b8792", "#e2dfe7", "#efecf4"]),
+  red: chroma.scale([colors.red.darken(3), colors.red, colors.red.brighten(3)]),
+  orange: chroma.scale([colors.orange.darken(3), colors.orange, colors.orange.brighten(3)]),
+  yellow: chroma.scale([colors.yellow.darken(3), colors.yellow, colors.yellow.brighten(3)]),
+  green: chroma.scale([colors.green.darken(3), colors.green, colors.green.brighten(3)]),
+  cyan: chroma.scale([colors.cyan.darken(3), colors.cyan, colors.cyan.brighten(3)]),
+  blue: chroma.scale([colors.blue.darken(3), colors.blue, colors.blue.brighten(3)]),
+  violet: chroma.scale([colors.violet.darken(3), colors.violet, colors.violet.brighten(3)]),
+  magenta: chroma.scale([colors.magenta.darken(3), colors.magenta, colors.magenta.brighten(3)]),
+}
+
+export const dark = createTheme(`${name}-dark`, false, ramps);
+export const light = createTheme(`${name}-light`, true, ramps);

styles/src/themes/light.ts 🔗

@@ -1,240 +0,0 @@
-import { colors, fontWeights, NumberToken } from "../tokens";
-import { withOpacity } from "../utils/color";
-import Theme, { buildPlayer, Syntax } from "./theme";
-
-const backgroundColor = {
-  100: {
-    base: colors.neutral[75],
-    hovered: colors.neutral[100],
-    active: colors.neutral[150],
-    focused: colors.neutral[100],
-  },
-  300: {
-    base: colors.neutral[25],
-    hovered: colors.neutral[75],
-    active: colors.neutral[100],
-    focused: colors.neutral[75],
-  },
-  500: {
-    base: colors.neutral[0],
-    hovered: withOpacity(colors.neutral[900], 0.03),
-    active: withOpacity(colors.neutral[900], 0.06),
-    focused: colors.neutral[50],
-  },
-  on300: {
-    base: colors.neutral[50],
-    hovered: colors.neutral[100],
-    active: colors.neutral[150],
-    focused: colors.neutral[100],
-  },
-  on500: {
-    base: colors.neutral[50],
-    hovered: colors.neutral[25],
-    active: colors.neutral[0],
-    focused: colors.neutral[25],
-  },
-  ok: {
-    base: withOpacity(colors.green[600], 0.15),
-    hovered: withOpacity(colors.green[600], 0.20),
-    active: withOpacity(colors.green[600], 0.25),
-    focused: withOpacity(colors.green[600], 0.20),
-  },
-  error: {
-    base: withOpacity(colors.red[600], 0.15),
-    hovered: withOpacity(colors.red[600], 0.20),
-    active: withOpacity(colors.red[600], 0.25),
-    focused: withOpacity(colors.red[600], 0.20),
-  },
-  warning: {
-    base: withOpacity(colors.amber[400], 0.15),
-    hovered: withOpacity(colors.amber[400], 0.20),
-    active: withOpacity(colors.amber[400], 0.25),
-    focused: withOpacity(colors.amber[400], 0.20),
-  },
-  info: {
-    base: withOpacity(colors.blue[500], 0.15),
-    hovered: withOpacity(colors.blue[500], 0.20),
-    active: withOpacity(colors.blue[500], 0.25),
-    focused: withOpacity(colors.blue[500], 0.20),
-  },
-};
-
-const borderColor = {
-  primary: colors.neutral[150],
-  secondary: colors.neutral[150],
-  muted: colors.neutral[100],
-  focused: colors.indigo[500],
-  active: colors.neutral[250],
-  onMedia: withOpacity(colors.neutral[250], 0.3),
-  ok: withOpacity(colors.green[600], 0.15),
-  error: withOpacity(colors.red[500], 0.15),
-  warning: withOpacity(colors.amber[400], 0.15),
-  info: withOpacity(colors.blue[500], 0.15),
-};
-
-const textColor = {
-  primary: colors.neutral[750],
-  secondary: colors.neutral[650],
-  muted: colors.neutral[550],
-  placeholder: colors.neutral[450],
-  active: colors.neutral[900],
-  feature: colors.indigo[500],
-  ok: colors.green[500],
-  error: colors.red[500],
-  warning: colors.yellow[500],
-  info: colors.blue[500],
-};
-
-const iconColor = {
-  primary: colors.neutral[700],
-  secondary: colors.neutral[500],
-  muted: colors.neutral[350],
-  placeholder: colors.neutral[300],
-  active: colors.neutral[900],
-  feature: colors.indigo[500],
-  ok: colors.green[600],
-  error: colors.red[600],
-  warning: colors.yellow[400],
-  info: colors.blue[600],
-};
-
-const player = {
-  1: buildPlayer(colors.blue[500]),
-  2: buildPlayer(colors.emerald[400]),
-  3: buildPlayer(colors.fuschia[400]),
-  4: buildPlayer(colors.orange[400]),
-  5: buildPlayer(colors.purple[400]),
-  6: buildPlayer(colors.teal[400]),
-  7: buildPlayer(colors.pink[400]),
-  8: buildPlayer(colors.yellow[400]),
-};
-
-const editor = {
-  background: backgroundColor[500].base,
-  indent_guide: borderColor.muted,
-  indent_guide_active: borderColor.secondary,
-  line: {
-    active: withOpacity(colors.neutral[900], 0.06),
-    highlighted: withOpacity(colors.neutral[900], 0.12),
-    inserted: backgroundColor.ok.active,
-    deleted: backgroundColor.error.active,
-    modified: backgroundColor.info.active,
-  },
-  highlight: {
-    selection: player[1].selectionColor,
-    occurrence: withOpacity(colors.neutral[900], 0.06),
-    activeOccurrence: withOpacity(colors.neutral[900], 0.16),
-    matchingBracket: colors.neutral[0],
-    match: colors.yellow[100],
-    activeMatch: colors.yellow[200],
-    related: colors.neutral[0],
-  },
-  gutter: {
-    primary: colors.neutral[300],
-    active: textColor.active,
-  },
-};
-
-const syntax: Syntax = {
-  primary: {
-    color: colors.neutral[800],
-    weight: fontWeights.normal,
-  },
-  comment: {
-    color: colors.neutral[500],
-    weight: fontWeights.normal,
-  },
-  punctuation: {
-    color: colors.neutral[600],
-    weight: fontWeights.normal,
-  },
-  constant: {
-    color: colors.neutral[800],
-    weight: fontWeights.normal,
-  },
-  keyword: {
-    color: colors.indigo[700],
-    weight: fontWeights.normal,
-  },
-  function: {
-    color: colors.orange[600],
-    weight: fontWeights.normal,
-  },
-  type: {
-    color: colors.yellow[600],
-    weight: fontWeights.normal,
-  },
-  variant: {
-    color: colors.rose[700],
-    weight: fontWeights.normal,
-  },
-  property: {
-    color: colors.emerald[700],
-    weight: fontWeights.normal,
-  },
-  enum: {
-    color: colors.red[500],
-    weight: fontWeights.normal,
-  },
-  operator: {
-    color: colors.red[500],
-    weight: fontWeights.normal,
-  },
-  string: {
-    color: colors.red[500],
-    weight: fontWeights.normal,
-  },
-  number: {
-    color: colors.indigo[500],
-    weight: fontWeights.normal,
-  },
-  boolean: {
-    color: colors.red[500],
-    weight: fontWeights.normal,
-  },
-  predictive: {
-    color: textColor.placeholder,
-    weight: fontWeights.normal,
-  },
-  title: {
-    color: colors.sky[500],
-    weight: fontWeights.bold,
-  },
-  emphasis: {
-    color: textColor.feature,
-    weight: fontWeights.normal,
-  },
-  "emphasis.strong": {
-    color: textColor.feature,
-    weight: fontWeights.bold,
-  },
-  linkUri: {
-    color: colors.lime[500],
-    weight: fontWeights.normal,
-    underline: true
-  },
-  linkText: {
-    color: colors.red[500],
-    weight: fontWeights.normal,
-    italic: true
-  },
-};
-
-const shadowAlpha: NumberToken = {
-  value: 0.12,
-  type: "number",
-};
-
-const theme: Theme = {
-  name: "light",
-  backgroundColor,
-  borderColor,
-  textColor,
-  iconColor,
-  editor,
-  syntax,
-  player,
-  shadowAlpha,
-};
-
-export default theme;

styles/src/themes/solarized.ts 🔗

@@ -1,29 +1,19 @@
-import { createTheme } from "./base16";
-import { color } from "../tokens";
+import chroma from "chroma-js";
+import { colorRamp, createTheme } from "./base16";
 
 const name = "solarized";
 
-const neutrals = [
-  color("#002b36"),
-  color("#073642"),
-  color("#586e75"),
-  color("#657b83"),
-  color("#839496"),
-  color("#93a1a1"),
-  color("#eee8d5"),
-  color("#fdf6e3"),
-];
+const ramps = {
+  neutral: chroma.scale(["#002b36", "#073642", "#586e75", "#657b83", "#839496", "#93a1a1", "#eee8d5", "#fdf6e3"]),
+  red: colorRamp(chroma("#dc322f")),
+  orange: colorRamp(chroma("#cb4b16")),
+  yellow: colorRamp(chroma("#b58900")),
+  green: colorRamp(chroma("#859900")),
+  cyan: colorRamp(chroma("#2aa198")),
+  blue: colorRamp(chroma("#268bd2")),
+  violet: colorRamp(chroma("#6c71c4")),
+  magenta: colorRamp(chroma("#d33682")),
+}
 
-const colors = {
-  "red": color("#dc322f"),
-  "orange": color("#cb4b16"),
-  "yellow": color("#b58900"),
-  "green": color("#859900"),
-  "cyan": color("#2aa198"),
-  "blue": color("#268bd2"),
-  "violet": color("#6c71c4"),
-  "magenta": color("#d33682"),
-};
-
-export const dark = createTheme(`${name}-dark`, false, neutrals, colors);
-export const light = createTheme(`${name}-light`, true, neutrals, colors);
+export const dark = createTheme(`${name}-dark`, false, ramps);
+export const light = createTheme(`${name}-light`, true, ramps);

styles/src/themes/sulphurpool.ts 🔗

@@ -1,29 +1,19 @@
-import { createTheme } from "./base16";
-import { color } from "../tokens";
+import chroma from "chroma-js";
+import { colorRamp, createTheme } from "./base16";
 
 const name = "sulphurpool";
 
-const neutrals = [
-  color("#202746"),
-  color("#293256"),
-  color("#5e6687"),
-  color("#6b7394"),
-  color("#898ea4"),
-  color("#979db4"),
-  color("#dfe2f1"),
-  color("#f5f7ff"),
-]
+const ramps = {
+  neutral: chroma.scale(["#202746", "#293256", "#5e6687", "#6b7394", "#898ea4", "#979db4", "#dfe2f1", "#f5f7ff"]),
+  red: colorRamp(chroma("#c94922")),
+  orange: colorRamp(chroma("#c76b29")),
+  yellow: colorRamp(chroma("#c08b30")),
+  green: colorRamp(chroma("#ac9739")),
+  cyan: colorRamp(chroma("#22a2c9")),
+  blue: colorRamp(chroma("#3d8fd1")),
+  violet: colorRamp(chroma("#6679cc")),
+  magenta: colorRamp(chroma("#9c637a")),
+}
 
-const colors = {
-  "red": color("#c94922"),
-  "orange": color("#c76b29"),
-  "yellow": color("#c08b30"),
-  "green": color("#ac9739"),
-  "cyan": color("#22a2c9"),
-  "blue": color("#3d8fd1"),
-  "violet": color("#6679cc"),
-  "magenta": color("#9c637a"),
-};
-
-export const dark = createTheme(`${name}-dark`, false, neutrals, colors);
-export const light = createTheme(`${name}-light`, true, neutrals, colors);
+export const dark = createTheme(`${name}-dark`, false, ramps);
+export const light = createTheme(`${name}-light`, true, ramps);

styles/src/themes/theme.ts 🔗

@@ -32,7 +32,6 @@ export interface BackgroundColorSet {
   base: ColorToken;
   hovered: ColorToken;
   active: ColorToken;
-  focused: ColorToken;
 }
 
 export interface Syntax {
@@ -85,7 +84,6 @@ export default interface Theme {
     primary: ColorToken;
     secondary: ColorToken;
     muted: ColorToken;
-    focused: ColorToken;
     active: ColorToken;
     /**
     * Used for rendering borders on top of media like avatars, images, video, etc.
@@ -127,9 +125,6 @@ export default interface Theme {
     line: {
       active: ColorToken;
       highlighted: ColorToken;
-      inserted: ColorToken;
-      deleted: ColorToken;
-      modified: ColorToken;
     };
     highlight: {
       selection: ColorToken;