From cf75b090d3f0ff633977df7af5426eb1c66549af Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Mon, 29 May 2023 15:45:13 +0200 Subject: [PATCH 01/53] feat: organize themes by folders with LICENSE --- styles/src/themes/andromeda/LICENSE | 21 +++++++++++++++++++ .../src/themes/{ => andromeda}/andromeda.ts | 4 ++-- .../{ => atelier-cave}/atelier-cave-dark.ts | 6 +++--- .../{ => atelier-cave}/atelier-cave-light.ts | 6 +++--- .../{ => atelier-dune}/atelier-dune-dark.ts | 6 +++--- .../{ => atelier-dune}/atelier-dune-light.ts | 6 +++--- .../atelier-estuary-dark.ts | 6 +++--- .../atelier-estuary-light.ts | 6 +++--- .../atelier-forest-dark.ts | 6 +++--- .../atelier-forest-light.ts | 6 +++--- .../{ => atelier-heath}/atelier-heath-dark.ts | 6 +++--- .../atelier-heath-light.ts | 6 +++--- .../atelier-lakeside-dark.ts | 6 +++--- .../atelier-lakeside-light.ts | 6 +++--- .../atelier-plateau-dark.ts | 6 +++--- .../atelier-plateau-light.ts | 6 +++--- .../atelier-savanna-dark.ts | 6 +++--- .../atelier-savanna-light.ts | 6 +++--- .../atelier-seaside-dark.ts | 6 +++--- .../atelier-seaside-light.ts | 6 +++--- .../atelier-sulphurpool-dark.ts | 6 +++--- .../atelier-sulphurpool-light.ts | 6 +++--- styles/src/themes/{ => ayu}/ayu-dark.ts | 4 ++-- styles/src/themes/{ => ayu}/ayu-light.ts | 4 ++-- styles/src/themes/{ => ayu}/ayu-mirage.ts | 4 ++-- styles/src/themes/gruvbox/LICENSE | 21 +++++++++++++++++++ .../themes/{ => gruvbox}/gruvbox-common.ts | 4 ++-- .../themes/{ => gruvbox}/gruvbox-dark-hard.ts | 0 .../themes/{ => gruvbox}/gruvbox-dark-soft.ts | 0 .../src/themes/{ => gruvbox}/gruvbox-dark.ts | 0 .../{ => gruvbox}/gruvbox-light-hard.ts | 0 .../{ => gruvbox}/gruvbox-light-soft.ts | 0 .../src/themes/{ => gruvbox}/gruvbox-light.ts | 0 styles/src/themes/one/LICENSE | 21 +++++++++++++++++++ styles/src/themes/{ => one}/one-dark.ts | 6 +++--- styles/src/themes/{ => one}/one-light.ts | 6 +++--- styles/src/themes/rose-pine/LICENSE | 21 +++++++++++++++++++ .../themes/{ => rose-pine}/rose-pine-dawn.ts | 4 ++-- .../themes/{ => rose-pine}/rose-pine-moon.ts | 4 ++-- .../src/themes/{ => rose-pine}/rose-pine.ts | 4 ++-- styles/src/themes/sandcastle/LICENSE | 21 +++++++++++++++++++ .../src/themes/{ => sandcastle}/sandcastle.ts | 4 ++-- styles/src/themes/solarized/LICENSE | 21 +++++++++++++++++++ .../src/themes/{ => solarized}/solarized.ts | 4 ++-- styles/src/themes/summercamp/LICENSE | 21 +++++++++++++++++++ .../src/themes/{ => summercamp}/summercamp.ts | 4 ++-- 46 files changed, 235 insertions(+), 88 deletions(-) create mode 100644 styles/src/themes/andromeda/LICENSE rename styles/src/themes/{ => andromeda}/andromeda.ts (91%) rename styles/src/themes/{ => atelier-cave}/atelier-cave-dark.ts (89%) rename styles/src/themes/{ => atelier-cave}/atelier-cave-light.ts (90%) rename styles/src/themes/{ => atelier-dune}/atelier-dune-dark.ts (89%) rename styles/src/themes/{ => atelier-dune}/atelier-dune-light.ts (90%) rename styles/src/themes/{ => atelier-estuary}/atelier-estuary-dark.ts (89%) rename styles/src/themes/{ => atelier-estuary}/atelier-estuary-light.ts (90%) rename styles/src/themes/{ => atelier-forest}/atelier-forest-dark.ts (89%) rename styles/src/themes/{ => atelier-forest}/atelier-forest-light.ts (90%) rename styles/src/themes/{ => atelier-heath}/atelier-heath-dark.ts (89%) rename styles/src/themes/{ => atelier-heath}/atelier-heath-light.ts (90%) rename styles/src/themes/{ => atelier-lakeside}/atelier-lakeside-dark.ts (90%) rename styles/src/themes/{ => atelier-lakeside}/atelier-lakeside-light.ts (90%) rename styles/src/themes/{ => atelier-plateau}/atelier-plateau-dark.ts (89%) rename styles/src/themes/{ => atelier-plateau}/atelier-plateau-light.ts (90%) rename styles/src/themes/{ => atelier-savanna}/atelier-savanna-dark.ts (89%) rename styles/src/themes/{ => atelier-savanna}/atelier-savanna-light.ts (90%) rename styles/src/themes/{ => atelier-seaside}/atelier-seaside-dark.ts (89%) rename styles/src/themes/{ => atelier-seaside}/atelier-seaside-light.ts (90%) rename styles/src/themes/{ => atelier-sulphurpool}/atelier-sulphurpool-dark.ts (90%) rename styles/src/themes/{ => atelier-sulphurpool}/atelier-sulphurpool-light.ts (90%) rename styles/src/themes/{ => ayu}/ayu-dark.ts (66%) rename styles/src/themes/{ => ayu}/ayu-light.ts (66%) rename styles/src/themes/{ => ayu}/ayu-mirage.ts (66%) create mode 100644 styles/src/themes/gruvbox/LICENSE rename styles/src/themes/{ => gruvbox}/gruvbox-common.ts (98%) rename styles/src/themes/{ => gruvbox}/gruvbox-dark-hard.ts (100%) rename styles/src/themes/{ => gruvbox}/gruvbox-dark-soft.ts (100%) rename styles/src/themes/{ => gruvbox}/gruvbox-dark.ts (100%) rename styles/src/themes/{ => gruvbox}/gruvbox-light-hard.ts (100%) rename styles/src/themes/{ => gruvbox}/gruvbox-light-soft.ts (100%) rename styles/src/themes/{ => gruvbox}/gruvbox-light.ts (100%) create mode 100644 styles/src/themes/one/LICENSE rename styles/src/themes/{ => one}/one-dark.ts (93%) rename styles/src/themes/{ => one}/one-light.ts (93%) create mode 100644 styles/src/themes/rose-pine/LICENSE rename styles/src/themes/{ => rose-pine}/rose-pine-dawn.ts (91%) rename styles/src/themes/{ => rose-pine}/rose-pine-moon.ts (91%) rename styles/src/themes/{ => rose-pine}/rose-pine.ts (91%) create mode 100644 styles/src/themes/sandcastle/LICENSE rename styles/src/themes/{ => sandcastle}/sandcastle.ts (91%) create mode 100644 styles/src/themes/solarized/LICENSE rename styles/src/themes/{ => solarized}/solarized.ts (91%) create mode 100644 styles/src/themes/summercamp/LICENSE rename styles/src/themes/{ => summercamp}/summercamp.ts (91%) diff --git a/styles/src/themes/andromeda/LICENSE b/styles/src/themes/andromeda/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..bdd549491fac6822878157337aa5dc4d09ef53f2 --- /dev/null +++ b/styles/src/themes/andromeda/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/andromeda.ts b/styles/src/themes/andromeda/andromeda.ts similarity index 91% rename from styles/src/themes/andromeda.ts rename to styles/src/themes/andromeda/andromeda.ts index 7eba7b1481aeba8b1429b323bb51c0f78c0a6069..adfea37d0694dc47350d96178478ef0b370117f3 100644 --- a/styles/src/themes/andromeda.ts +++ b/styles/src/themes/andromeda/andromeda.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Andromeda" diff --git a/styles/src/themes/atelier-cave-dark.ts b/styles/src/themes/atelier-cave/atelier-cave-dark.ts similarity index 89% rename from styles/src/themes/atelier-cave-dark.ts rename to styles/src/themes/atelier-cave/atelier-cave-dark.ts index a56e22cd92373997cc40d19eddf5b05e9cad5a02..a61db0e590eeea584b89481b5682cd37bb3ab2af 100644 --- a/styles/src/themes/atelier-cave-dark.ts +++ b/styles/src/themes/atelier-cave/atelier-cave-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-cave-light.ts b/styles/src/themes/atelier-cave/atelier-cave-light.ts similarity index 90% rename from styles/src/themes/atelier-cave-light.ts rename to styles/src/themes/atelier-cave/atelier-cave-light.ts index 3b180752cf97ea1bcc515c904deb20eafc03aea6..739fe1320b6cf49e81cdde5eb84113ea67e4eb3c 100644 --- a/styles/src/themes/atelier-cave-light.ts +++ b/styles/src/themes/atelier-cave/atelier-cave-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-dune-dark.ts b/styles/src/themes/atelier-dune/atelier-dune-dark.ts similarity index 89% rename from styles/src/themes/atelier-dune-dark.ts rename to styles/src/themes/atelier-dune/atelier-dune-dark.ts index 0ab402a99d4adf8f1e0ed41979d5cc9973696404..7a3c3fbd07dac797d97eb05c7c74e10f95f954ca 100644 --- a/styles/src/themes/atelier-dune-dark.ts +++ b/styles/src/themes/atelier-dune/atelier-dune-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-dune-light.ts b/styles/src/themes/atelier-dune/atelier-dune-light.ts similarity index 90% rename from styles/src/themes/atelier-dune-light.ts rename to styles/src/themes/atelier-dune/atelier-dune-light.ts index e6a09985d5e09f8612d0a41f7b3a898991b9b720..3ee60164b689f41db333f31b80f01dcbfc2a7de9 100644 --- a/styles/src/themes/atelier-dune-light.ts +++ b/styles/src/themes/atelier-dune/atelier-dune-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-estuary-dark.ts b/styles/src/themes/atelier-estuary/atelier-estuary-dark.ts similarity index 89% rename from styles/src/themes/atelier-estuary-dark.ts rename to styles/src/themes/atelier-estuary/atelier-estuary-dark.ts index c4ec50c1e00ed7731d069ed3f559204b9030b10c..5ec6df8d359ff6cf6c169d03d4cf4b252795f4bd 100644 --- a/styles/src/themes/atelier-estuary-dark.ts +++ b/styles/src/themes/atelier-estuary/atelier-estuary-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-estuary-light.ts b/styles/src/themes/atelier-estuary/atelier-estuary-light.ts similarity index 90% rename from styles/src/themes/atelier-estuary-light.ts rename to styles/src/themes/atelier-estuary/atelier-estuary-light.ts index 6fce0e44833d2d0bf8657a3465bcfb601b262644..bc583d41ac7cd7345c2b1d0b3ca11a6258658391 100644 --- a/styles/src/themes/atelier-estuary-light.ts +++ b/styles/src/themes/atelier-estuary/atelier-estuary-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-forest-dark.ts b/styles/src/themes/atelier-forest/atelier-forest-dark.ts similarity index 89% rename from styles/src/themes/atelier-forest-dark.ts rename to styles/src/themes/atelier-forest/atelier-forest-dark.ts index 7c47c55a830ed780f662d83d9f768d26207dc31e..72f958efdfad406d7a1e1504f735e6684851ef9c 100644 --- a/styles/src/themes/atelier-forest-dark.ts +++ b/styles/src/themes/atelier-forest/atelier-forest-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-forest-light.ts b/styles/src/themes/atelier-forest/atelier-forest-light.ts similarity index 90% rename from styles/src/themes/atelier-forest-light.ts rename to styles/src/themes/atelier-forest/atelier-forest-light.ts index 8ce06164769a7a8dfa15fc74a77b6aa0f3c9e3af..463350f822a2f8941b31a5e2e7bad93d0d8668f1 100644 --- a/styles/src/themes/atelier-forest-light.ts +++ b/styles/src/themes/atelier-forest/atelier-forest-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-heath-dark.ts b/styles/src/themes/atelier-heath/atelier-heath-dark.ts similarity index 89% rename from styles/src/themes/atelier-heath-dark.ts rename to styles/src/themes/atelier-heath/atelier-heath-dark.ts index 87458ab8f5ab68a30e602de9b62edbe1e4cf5c18..010169b0225b759ee4b10fbc6037d12f13eebd4e 100644 --- a/styles/src/themes/atelier-heath-dark.ts +++ b/styles/src/themes/atelier-heath/atelier-heath-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-heath-light.ts b/styles/src/themes/atelier-heath/atelier-heath-light.ts similarity index 90% rename from styles/src/themes/atelier-heath-light.ts rename to styles/src/themes/atelier-heath/atelier-heath-light.ts index 3db34370418f1cd27e305a3175e045e591e36ae9..09d39b6d6662b8f3018ea418c9278a15bc86d9c7 100644 --- a/styles/src/themes/atelier-heath-light.ts +++ b/styles/src/themes/atelier-heath/atelier-heath-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-lakeside-dark.ts b/styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts similarity index 90% rename from styles/src/themes/atelier-lakeside-dark.ts rename to styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts index a8297ef9fd307243f1c9c84f3caa1e627120a19e..59728f30f327a20fab35210d3400ed62176de870 100644 --- a/styles/src/themes/atelier-lakeside-dark.ts +++ b/styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-lakeside-light.ts b/styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts similarity index 90% rename from styles/src/themes/atelier-lakeside-light.ts rename to styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts index 408fabcaf36a50df5229ea0034d12c67bd3b3562..d26c4fe67945454b7bbd43b27f409fea9dc171bd 100644 --- a/styles/src/themes/atelier-lakeside-light.ts +++ b/styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-plateau-dark.ts b/styles/src/themes/atelier-plateau/atelier-plateau-dark.ts similarity index 89% rename from styles/src/themes/atelier-plateau-dark.ts rename to styles/src/themes/atelier-plateau/atelier-plateau-dark.ts index 731cb824e44eba0590c5f1dc4804121aa7f97cd9..8299116c0efbd484279cb01dd1f946e9923af3ba 100644 --- a/styles/src/themes/atelier-plateau-dark.ts +++ b/styles/src/themes/atelier-plateau/atelier-plateau-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-plateau-light.ts b/styles/src/themes/atelier-plateau/atelier-plateau-light.ts similarity index 90% rename from styles/src/themes/atelier-plateau-light.ts rename to styles/src/themes/atelier-plateau/atelier-plateau-light.ts index 96f295a69518b1216482776e44d5b36912f526da..7fcc4220accaca761cec203e9856102781a14b7d 100644 --- a/styles/src/themes/atelier-plateau-light.ts +++ b/styles/src/themes/atelier-plateau/atelier-plateau-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-savanna-dark.ts b/styles/src/themes/atelier-savanna/atelier-savanna-dark.ts similarity index 89% rename from styles/src/themes/atelier-savanna-dark.ts rename to styles/src/themes/atelier-savanna/atelier-savanna-dark.ts index dfcb4f27cbedd41608b941da97172d083e7a8e76..5b6f034563433379d30f27d4b5043b35d3402ee1 100644 --- a/styles/src/themes/atelier-savanna-dark.ts +++ b/styles/src/themes/atelier-savanna/atelier-savanna-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-savanna-light.ts b/styles/src/themes/atelier-savanna/atelier-savanna-light.ts similarity index 90% rename from styles/src/themes/atelier-savanna-light.ts rename to styles/src/themes/atelier-savanna/atelier-savanna-light.ts index 4bc1389fc9cf3cb3b4870a58665a510a65d4c9e2..498959487696546e2d5c540a44019fbb5262e6ac 100644 --- a/styles/src/themes/atelier-savanna-light.ts +++ b/styles/src/themes/atelier-savanna/atelier-savanna-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-seaside-dark.ts b/styles/src/themes/atelier-seaside/atelier-seaside-dark.ts similarity index 89% rename from styles/src/themes/atelier-seaside-dark.ts rename to styles/src/themes/atelier-seaside/atelier-seaside-dark.ts index 1326a277861e417711c3ea30d39230b227c9ac51..00631eff51f8e3431a8ae5c872a0428efe659dca 100644 --- a/styles/src/themes/atelier-seaside-dark.ts +++ b/styles/src/themes/atelier-seaside/atelier-seaside-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-seaside-light.ts b/styles/src/themes/atelier-seaside/atelier-seaside-light.ts similarity index 90% rename from styles/src/themes/atelier-seaside-light.ts rename to styles/src/themes/atelier-seaside/atelier-seaside-light.ts index 6f6823718aed9ba4e3d7325b9968b11ba5472b40..af6af2f02737968d5161118bb2442c6426cc6a1d 100644 --- a/styles/src/themes/atelier-seaside-light.ts +++ b/styles/src/themes/atelier-seaside/atelier-seaside-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-sulphurpool-dark.ts b/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts similarity index 90% rename from styles/src/themes/atelier-sulphurpool-dark.ts rename to styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts index dcfc0d932a67d7081f5bcdb195f6fc57cfc2d79f..140d02c2e6bc49a69e4dda59c4142dbcc6f714af 100644 --- a/styles/src/themes/atelier-sulphurpool-dark.ts +++ b/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-sulphurpool-light.ts b/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts similarity index 90% rename from styles/src/themes/atelier-sulphurpool-light.ts rename to styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts index b2b5f7c328ba86be296be0fb938bf850571dbef9..b6dba4c384cde17bafe88ce27cbf5a802b8ee020 100644 --- a/styles/src/themes/atelier-sulphurpool-light.ts +++ b/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "./common/atelier-common" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" +import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" const variant: Variant = { meta: { diff --git a/styles/src/themes/ayu-dark.ts b/styles/src/themes/ayu/ayu-dark.ts similarity index 66% rename from styles/src/themes/ayu-dark.ts rename to styles/src/themes/ayu/ayu-dark.ts index c7e86994feec6a78879b383e5bf71941084c0b9e..eb837231fe1b0d3818768ce0b149a512d6ea3f7d 100644 --- a/styles/src/themes/ayu-dark.ts +++ b/styles/src/themes/ayu/ayu-dark.ts @@ -1,5 +1,5 @@ -import { createColorScheme } from "./common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "./common/ayu-common" +import { createColorScheme } from "../common/ramps" +import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/ayu-light.ts b/styles/src/themes/ayu/ayu-light.ts similarity index 66% rename from styles/src/themes/ayu-light.ts rename to styles/src/themes/ayu/ayu-light.ts index 9acabf6a3957a20aca2e3fa0181cf675840ddae4..9c29449db5bd323e21aa9004a1b2ac2731c0a617 100644 --- a/styles/src/themes/ayu-light.ts +++ b/styles/src/themes/ayu/ayu-light.ts @@ -1,5 +1,5 @@ -import { createColorScheme } from "./common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "./common/ayu-common" +import { createColorScheme } from "../common/ramps" +import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/ayu-mirage.ts b/styles/src/themes/ayu/ayu-mirage.ts similarity index 66% rename from styles/src/themes/ayu-mirage.ts rename to styles/src/themes/ayu/ayu-mirage.ts index 2a01512673b73d104ead5fc20edf353b813c16bb..52bf5493922102fffd9cd8cc0eef24ba9bb2b720 100644 --- a/styles/src/themes/ayu-mirage.ts +++ b/styles/src/themes/ayu/ayu-mirage.ts @@ -1,5 +1,5 @@ -import { createColorScheme } from "./common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "./common/ayu-common" +import { createColorScheme } from "../common/ramps" +import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/gruvbox/LICENSE b/styles/src/themes/gruvbox/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2a9230614399a48916e74cfb74bd4625686c7bcb --- /dev/null +++ b/styles/src/themes/gruvbox/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/gruvbox-common.ts b/styles/src/themes/gruvbox/gruvbox-common.ts similarity index 98% rename from styles/src/themes/gruvbox-common.ts rename to styles/src/themes/gruvbox/gruvbox-common.ts index c42362c11c007e5371ad7134c7300667fe04304e..5958fe62aceeeba3c7c6b5191a8046eeecee5e93 100644 --- a/styles/src/themes/gruvbox-common.ts +++ b/styles/src/themes/gruvbox/gruvbox-common.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta, ThemeSyntax } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta, ThemeSyntax } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Gruvbox" diff --git a/styles/src/themes/gruvbox-dark-hard.ts b/styles/src/themes/gruvbox/gruvbox-dark-hard.ts similarity index 100% rename from styles/src/themes/gruvbox-dark-hard.ts rename to styles/src/themes/gruvbox/gruvbox-dark-hard.ts diff --git a/styles/src/themes/gruvbox-dark-soft.ts b/styles/src/themes/gruvbox/gruvbox-dark-soft.ts similarity index 100% rename from styles/src/themes/gruvbox-dark-soft.ts rename to styles/src/themes/gruvbox/gruvbox-dark-soft.ts diff --git a/styles/src/themes/gruvbox-dark.ts b/styles/src/themes/gruvbox/gruvbox-dark.ts similarity index 100% rename from styles/src/themes/gruvbox-dark.ts rename to styles/src/themes/gruvbox/gruvbox-dark.ts diff --git a/styles/src/themes/gruvbox-light-hard.ts b/styles/src/themes/gruvbox/gruvbox-light-hard.ts similarity index 100% rename from styles/src/themes/gruvbox-light-hard.ts rename to styles/src/themes/gruvbox/gruvbox-light-hard.ts diff --git a/styles/src/themes/gruvbox-light-soft.ts b/styles/src/themes/gruvbox/gruvbox-light-soft.ts similarity index 100% rename from styles/src/themes/gruvbox-light-soft.ts rename to styles/src/themes/gruvbox/gruvbox-light-soft.ts diff --git a/styles/src/themes/gruvbox-light.ts b/styles/src/themes/gruvbox/gruvbox-light.ts similarity index 100% rename from styles/src/themes/gruvbox-light.ts rename to styles/src/themes/gruvbox/gruvbox-light.ts diff --git a/styles/src/themes/one/LICENSE b/styles/src/themes/one/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..dc07dc10ad0de56ebe0bfad8d65e82f0f5d627ef --- /dev/null +++ b/styles/src/themes/one/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/one-dark.ts b/styles/src/themes/one/one-dark.ts similarity index 93% rename from styles/src/themes/one-dark.ts rename to styles/src/themes/one/one-dark.ts index 85417a0e68651341edded4689425b15a0d8f29b1..71062940a5cb8f4d9fc345b3abdcb3ab0d4d2ea6 100644 --- a/styles/src/themes/one-dark.ts +++ b/styles/src/themes/one/one-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { fontWeights } from "../common" -import { Meta, ThemeSyntax } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { fontWeights } from "../../common" +import { Meta, ThemeSyntax } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "One Dark" diff --git a/styles/src/themes/one-light.ts b/styles/src/themes/one/one-light.ts similarity index 93% rename from styles/src/themes/one-light.ts rename to styles/src/themes/one/one-light.ts index 7bf21aee17d4871681b33174e3b20bea06ced9fe..8ae42e8b1d161f291bc76dd462aae5e79b18e109 100644 --- a/styles/src/themes/one-light.ts +++ b/styles/src/themes/one/one-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" -import { fontWeights } from "../common" -import { Meta, ThemeSyntax } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { fontWeights } from "../../common" +import { Meta, ThemeSyntax } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "One Light" diff --git a/styles/src/themes/rose-pine/LICENSE b/styles/src/themes/rose-pine/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..dfd60136f95374fbe3e112a6051a4854b61ac4ec --- /dev/null +++ b/styles/src/themes/rose-pine/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 Emilia Dunfelt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/rose-pine-dawn.ts b/styles/src/themes/rose-pine/rose-pine-dawn.ts similarity index 91% rename from styles/src/themes/rose-pine-dawn.ts rename to styles/src/themes/rose-pine/rose-pine-dawn.ts index 427b05f72b8e5672897b7457738d4c43e2c6f603..48da855304781e58584368dfdf9f8ea088c25823 100644 --- a/styles/src/themes/rose-pine-dawn.ts +++ b/styles/src/themes/rose-pine/rose-pine-dawn.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Rosé Pine Dawn" diff --git a/styles/src/themes/rose-pine-moon.ts b/styles/src/themes/rose-pine/rose-pine-moon.ts similarity index 91% rename from styles/src/themes/rose-pine-moon.ts rename to styles/src/themes/rose-pine/rose-pine-moon.ts index be2f5a8dafd366803f13737c75bdb48d7e101aa9..2e13ca4b707d77747f58afbf28229bf9d381c2a9 100644 --- a/styles/src/themes/rose-pine-moon.ts +++ b/styles/src/themes/rose-pine/rose-pine-moon.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Rosé Pine Moon" diff --git a/styles/src/themes/rose-pine.ts b/styles/src/themes/rose-pine/rose-pine.ts similarity index 91% rename from styles/src/themes/rose-pine.ts rename to styles/src/themes/rose-pine/rose-pine.ts index 944550f1250ad01146f8622a8199cf027f4658ab..33d7d533e6508fd4217dc02f3b864f3fbb5c05fe 100644 --- a/styles/src/themes/rose-pine.ts +++ b/styles/src/themes/rose-pine/rose-pine.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Rosé Pine" diff --git a/styles/src/themes/sandcastle/LICENSE b/styles/src/themes/sandcastle/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..c66a06c51b46671cfe20194ac8ff545683c7a7e3 --- /dev/null +++ b/styles/src/themes/sandcastle/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 George Essig + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/sandcastle.ts b/styles/src/themes/sandcastle/sandcastle.ts similarity index 91% rename from styles/src/themes/sandcastle.ts rename to styles/src/themes/sandcastle/sandcastle.ts index 483f01b27a1850463348e0a9c575086a014d5f1b..0b265212562745717efef8871f23e69066673b59 100644 --- a/styles/src/themes/sandcastle.ts +++ b/styles/src/themes/sandcastle/sandcastle.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Sandcastle" diff --git a/styles/src/themes/solarized/LICENSE b/styles/src/themes/solarized/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..221eee6f152873e2e6c52ca4a89ac1d65118843b --- /dev/null +++ b/styles/src/themes/solarized/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011 Ethan Schoonover + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/solarized.ts b/styles/src/themes/solarized/solarized.ts similarity index 91% rename from styles/src/themes/solarized.ts rename to styles/src/themes/solarized/solarized.ts index 1210c4380608e812d39dec0f36d6ec69dab37e9b..13e3e34460bee124b1220f23556b6fd885a5d310 100644 --- a/styles/src/themes/solarized.ts +++ b/styles/src/themes/solarized/solarized.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta as Metadata } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta as Metadata } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Solarized" diff --git a/styles/src/themes/summercamp/LICENSE b/styles/src/themes/summercamp/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..d7525414ad01c246c21e908666064d6db4233901 --- /dev/null +++ b/styles/src/themes/summercamp/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Zoe FiriH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/summercamp.ts b/styles/src/themes/summercamp/summercamp.ts similarity index 91% rename from styles/src/themes/summercamp.ts rename to styles/src/themes/summercamp/summercamp.ts index 7df125e86606d299e52ffb07140f156744e086ce..41e101af0208f676261dec19cf0a55d714bf0ce0 100644 --- a/styles/src/themes/summercamp.ts +++ b/styles/src/themes/summercamp/summercamp.ts @@ -1,6 +1,6 @@ import chroma from "chroma-js" -import { Meta } from "./common/colorScheme" -import { colorRamp, createColorScheme } from "./common/ramps" +import { Meta } from "../common/colorScheme" +import { colorRamp, createColorScheme } from "../common/ramps" const name = "Summercamp" From 89446c7fd41f3733b657e4f0a57438d323770331 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 29 May 2023 13:48:27 -0700 Subject: [PATCH 02/53] Start work on respecting project-specific settings --- crates/copilot/src/copilot.rs | 5 + crates/copilot_button/src/copilot_button.rs | 2 +- crates/editor/src/display_map.rs | 2 +- crates/editor/src/items.rs | 4 + crates/editor/src/multi_buffer.rs | 20 ++- crates/language/src/buffer.rs | 17 ++- crates/language/src/language_settings.rs | 13 +- crates/project/src/lsp_command.rs | 3 +- crates/project/src/project.rs | 130 +++++++++++++++----- crates/project/src/project_tests.rs | 56 +++++++++ crates/project/src/worktree.rs | 45 +++++-- crates/settings/src/settings_file.rs | 13 +- crates/settings/src/settings_store.rs | 91 +++++++++----- crates/terminal_view/src/terminal_view.rs | 5 +- crates/util/src/paths.rs | 1 + crates/zed/src/languages/yaml.rs | 2 +- 16 files changed, 326 insertions(+), 83 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index de9104a6848d504eb78d28ab45da896d771dca29..88b0aebd17127765535db8bf8966dd630e95b851 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -787,6 +787,7 @@ impl Copilot { let position = position.to_point_utf16(buffer); let settings = language_settings( buffer.language_at(position).map(|l| l.name()).as_deref(), + buffer.file().map(|f| f.as_ref()), cx, ); let tab_size = settings.tab_size; @@ -1175,6 +1176,10 @@ mod tests { fn to_proto(&self) -> rpc::proto::File { unimplemented!() } + + fn worktree_id(&self) -> usize { + 0 + } } impl language::LocalFile for File { diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 17d27ca41f66caf08117518d29b7f6f627febe4c..686b3d2dfb3dc222433166f3aeed20f5d869be33 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -198,7 +198,7 @@ impl CopilotButton { if let Some(language) = self.language.clone() { let fs = fs.clone(); let language_enabled = - language_settings::language_settings(Some(language.as_ref()), cx) + language_settings::language_settings(Some(language.as_ref()), None, cx) .show_copilot_suggestions; menu_options.push(ContextMenuItem::handler( format!( diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 366e47ddc640fa6c9ee205debdc7b837b205ebe8..f8d6f0bc406a497f13e36f320ed461aff1ddec60 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -277,7 +277,7 @@ impl DisplayMap { .as_singleton() .and_then(|buffer| buffer.read(cx).language()) .map(|language| language.name()); - language_settings(language_name.as_deref(), cx).tab_size + language_settings(language_name.as_deref(), None, cx).tab_size } #[cfg(test)] diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 40e7c89cb298e34510002550349f7faff6f0fa19..8da746075e25f7130b739b82d40e33ceb2ef8130 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1231,6 +1231,10 @@ mod tests { unimplemented!() } + fn worktree_id(&self) -> usize { + 0 + } + fn is_deleted(&self) -> bool { unimplemented!() } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 4650dff38f58088eab5fc1638080680dc86dd84e..597feb832b07c80ed33bdf578377c720c16a393e 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1377,8 +1377,14 @@ impl MultiBuffer { point: T, cx: &'a AppContext, ) -> &'a LanguageSettings { - let language = self.language_at(point, cx); - language_settings(language.map(|l| l.name()).as_deref(), cx) + let mut language = None; + let mut file = None; + if let Some((buffer, offset)) = self.point_to_buffer_offset(point, cx) { + let buffer = buffer.read(cx); + language = buffer.language_at(offset).map(|l| l.name()); + file = buffer.file().map(|f| f.as_ref()); + } + language_settings(language.as_deref(), file, cx) } pub fn for_each_buffer(&self, mut f: impl FnMut(&ModelHandle)) { @@ -2785,9 +2791,13 @@ impl MultiBufferSnapshot { point: T, cx: &'a AppContext, ) -> &'a LanguageSettings { - self.point_to_buffer_offset(point) - .map(|(buffer, offset)| buffer.settings_at(offset, cx)) - .unwrap_or_else(|| language_settings(None, cx)) + let mut language = None; + let mut file = None; + if let Some((buffer, offset)) = self.point_to_buffer_offset(point) { + language = buffer.language_at(offset).map(|l| l.name()); + file = buffer.file().map(|f| f.as_ref()); + } + language_settings(language.as_deref(), file, cx) } pub fn language_scope_at<'a, T: ToOffset>(&'a self, point: T) -> Option { diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 93b50cf597cfd3e0ed18ac8e317fa5847740f1b1..ddec085e2a622ca84190c5acec9c891512a80b2f 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -216,6 +216,11 @@ pub trait File: Send + Sync { /// of its worktree, then this method will return the name of the worktree itself. fn file_name<'a>(&'a self, cx: &'a AppContext) -> &'a OsStr; + /// Returns the id of the worktree to which this file belongs. + /// + /// This is needed for looking up project-specific settings. + fn worktree_id(&self) -> usize; + fn is_deleted(&self) -> bool; fn as_any(&self) -> &dyn Any; @@ -1803,7 +1808,11 @@ impl BufferSnapshot { pub fn language_indent_size_at(&self, position: T, cx: &AppContext) -> IndentSize { let language_name = self.language_at(position).map(|language| language.name()); - let settings = language_settings(language_name.as_deref(), cx); + let settings = language_settings( + language_name.as_deref(), + self.file().map(|f| f.as_ref()), + cx, + ); if settings.hard_tabs { IndentSize::tab() } else { @@ -2128,7 +2137,11 @@ impl BufferSnapshot { cx: &'a AppContext, ) -> &'a LanguageSettings { let language = self.language_at(position); - language_settings(language.map(|l| l.name()).as_deref(), cx) + language_settings( + language.map(|l| l.name()).as_deref(), + self.file.as_ref().map(AsRef::as_ref), + cx, + ) } pub fn language_scope_at(&self, position: D) -> Option { diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index c98297c03648f7db9c307a592b4f7bf2dcfe279d..70aaca03c408ab0a9995fee88f54144f4ab997d9 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -1,3 +1,4 @@ +use crate::File; use anyhow::Result; use collections::HashMap; use globset::GlobMatcher; @@ -13,8 +14,16 @@ pub fn init(cx: &mut AppContext) { settings::register::(cx); } -pub fn language_settings<'a>(language: Option<&str>, cx: &'a AppContext) -> &'a LanguageSettings { - settings::get::(cx).language(language) +pub fn language_settings<'a>( + language: Option<&str>, + file: Option<&dyn File>, + cx: &'a AppContext, +) -> &'a LanguageSettings { + settings::get_local::( + file.map(|f| (f.worktree_id(), f.path().as_ref())), + cx, + ) + .language(language) } pub fn all_language_settings<'a>(cx: &'a AppContext) -> &'a AllLanguageSettings { diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 5ee64438963977fb6f265ed4d5fe32444bd96b3f..0a8b5f8a2e52f6a33e14bd5bc4a01ebe3dba7601 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1717,7 +1717,8 @@ impl LspCommand for OnTypeFormatting { let tab_size = buffer.read_with(&cx, |buffer, cx| { let language_name = buffer.language().map(|language| language.name()); - language_settings(language_name.as_deref(), cx).tab_size + let file = buffer.file().map(|f| f.as_ref()); + language_settings(language_name.as_deref(), file, cx).tab_size }); Ok(Self { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 92210a75a8ea2067aafe3e36d68449c3af2e5142..c76587ff56328fabdab93abf77965e547f11979b 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -71,7 +71,10 @@ use std::{ time::{Duration, Instant, SystemTime}, }; use terminals::Terminals; -use util::{debug_panic, defer, merge_json_value_into, post_inc, ResultExt, TryFutureExt as _}; +use util::{ + debug_panic, defer, merge_json_value_into, paths::LOCAL_SETTINGS_RELATIVE_PATH, post_inc, + ResultExt, TryFutureExt as _, +}; pub use fs::*; pub use worktree::*; @@ -697,12 +700,7 @@ impl Project { .language(Some(&language.name())) .enable_language_server { - let worktree = file.worktree.read(cx); - language_servers_to_start.push(( - worktree.id(), - worktree.as_local().unwrap().abs_path().clone(), - language.clone(), - )); + language_servers_to_start.push((file.worktree.clone(), language.clone())); } } } @@ -732,8 +730,9 @@ impl Project { } // Start all the newly-enabled language servers. - for (worktree_id, worktree_path, language) in language_servers_to_start { - self.start_language_servers(worktree_id, worktree_path, language, cx); + for (worktree, language) in language_servers_to_start { + let worktree_path = worktree.read(cx).abs_path(); + self.start_language_servers(&worktree, worktree_path, language, cx); } if !self.copilot_enabled && Copilot::global(cx).is_some() { @@ -2320,25 +2319,34 @@ impl Project { }); if let Some(file) = File::from_dyn(buffer.read(cx).file()) { - if let Some(worktree) = file.worktree.read(cx).as_local() { - let worktree_id = worktree.id(); - let worktree_abs_path = worktree.abs_path().clone(); - self.start_language_servers(worktree_id, worktree_abs_path, new_language, cx); + let worktree = file.worktree.clone(); + if let Some(tree) = worktree.read(cx).as_local() { + self.start_language_servers(&worktree, tree.abs_path().clone(), new_language, cx); } } } fn start_language_servers( &mut self, - worktree_id: WorktreeId, + worktree: &ModelHandle, worktree_path: Arc, language: Arc, cx: &mut ModelContext, ) { - if !language_settings(Some(&language.name()), cx).enable_language_server { + if !language_settings( + Some(&language.name()), + worktree + .update(cx, |tree, cx| tree.root_file(cx)) + .as_ref() + .map(|f| f as _), + cx, + ) + .enable_language_server + { return; } + let worktree_id = worktree.read(cx).id(); for adapter in language.lsp_adapters() { let key = (worktree_id, adapter.name.clone()); if self.language_server_ids.contains_key(&key) { @@ -2747,23 +2755,22 @@ impl Project { buffers: impl IntoIterator>, cx: &mut ModelContext, ) -> Option<()> { - let language_server_lookup_info: HashSet<(WorktreeId, Arc, Arc)> = buffers + let language_server_lookup_info: HashSet<(ModelHandle, Arc)> = buffers .into_iter() .filter_map(|buffer| { let buffer = buffer.read(cx); let file = File::from_dyn(buffer.file())?; - let worktree = file.worktree.read(cx).as_local()?; let full_path = file.full_path(cx); let language = self .languages .language_for_file(&full_path, Some(buffer.as_rope())) .now_or_never()? .ok()?; - Some((worktree.id(), worktree.abs_path().clone(), language)) + Some((file.worktree.clone(), language)) }) .collect(); - for (worktree_id, worktree_abs_path, language) in language_server_lookup_info { - self.restart_language_servers(worktree_id, worktree_abs_path, language, cx); + for (worktree, language) in language_server_lookup_info { + self.restart_language_servers(worktree, language, cx); } None @@ -2772,11 +2779,13 @@ impl Project { // TODO This will break in the case where the adapter's root paths and worktrees are not equal fn restart_language_servers( &mut self, - worktree_id: WorktreeId, - fallback_path: Arc, + worktree: ModelHandle, language: Arc, cx: &mut ModelContext, ) { + let worktree_id = worktree.read(cx).id(); + let fallback_path = worktree.read(cx).abs_path(); + let mut stops = Vec::new(); for adapter in language.lsp_adapters() { stops.push(self.stop_language_server(worktree_id, adapter.name.clone(), cx)); @@ -2806,7 +2815,7 @@ impl Project { .map(|path_buf| Arc::from(path_buf.as_path())) .unwrap_or(fallback_path); - this.start_language_servers(worktree_id, root_path, language.clone(), cx); + this.start_language_servers(&worktree, root_path, language.clone(), cx); // Lookup new server ids and set them for each of the orphaned worktrees for adapter in language.lsp_adapters() { @@ -3430,7 +3439,12 @@ impl Project { for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers { let settings = buffer.read_with(&cx, |buffer, cx| { let language_name = buffer.language().map(|language| language.name()); - language_settings(language_name.as_deref(), cx).clone() + language_settings( + language_name.as_deref(), + buffer.file().map(|f| f.as_ref()), + cx, + ) + .clone() }); let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save; @@ -4439,11 +4453,15 @@ impl Project { push_to_history: bool, cx: &mut ModelContext, ) -> Task>> { - let tab_size = buffer.read_with(cx, |buffer, cx| { - let language_name = buffer.language().map(|language| language.name()); - language_settings(language_name.as_deref(), cx).tab_size + let (position, tab_size) = buffer.read_with(cx, |buffer, cx| { + let position = position.to_point_utf16(buffer); + let language_name = buffer.language_at(position).map(|l| l.name()); + let file = buffer.file().map(|f| f.as_ref()); + ( + position, + language_settings(language_name.as_deref(), file, cx).tab_size, + ) }); - let position = position.to_point_utf16(buffer.read(cx)); self.request_lsp( buffer.clone(), OnTypeFormatting { @@ -4849,6 +4867,7 @@ impl Project { worktree::Event::UpdatedEntries(changes) => { this.update_local_worktree_buffers(&worktree, changes, cx); this.update_local_worktree_language_servers(&worktree, changes, cx); + this.update_local_worktree_settings(&worktree, changes, cx); } worktree::Event::UpdatedGitRepositories(updated_repos) => { this.update_local_worktree_buffers_git_repos(worktree, updated_repos, cx) @@ -5155,6 +5174,61 @@ impl Project { .detach(); } + pub fn update_local_worktree_settings( + &mut self, + worktree: &ModelHandle, + changes: &UpdatedEntriesSet, + cx: &mut ModelContext, + ) { + let worktree_id = worktree.id(); + let worktree = worktree.read(cx).as_local().unwrap(); + + let mut settings_contents = Vec::new(); + for (path, _, change) in changes.iter() { + if path.ends_with(&*LOCAL_SETTINGS_RELATIVE_PATH) { + let settings_dir = Arc::from( + path.ancestors() + .nth(LOCAL_SETTINGS_RELATIVE_PATH.components().count()) + .unwrap(), + ); + let fs = self.fs.clone(); + let removed = *change == PathChange::Removed; + let abs_path = worktree.absolutize(path); + settings_contents.push(async move { + anyhow::Ok(( + settings_dir, + (!removed).then_some(fs.load(&abs_path).await?), + )) + }); + } + } + + if settings_contents.is_empty() { + return; + } + + cx.spawn_weak(move |_, mut cx| async move { + let settings_contents = futures::future::join_all(settings_contents).await; + cx.update(|cx| { + cx.update_global::(|store, cx| { + for entry in settings_contents { + if let Some((directory, file_content)) = entry.log_err() { + store + .set_local_settings( + worktree_id, + directory, + file_content.as_ref().map(String::as_str), + cx, + ) + .log_err(); + } + } + }); + }); + }) + .detach(); + } + pub fn set_active_path(&mut self, entry: Option, cx: &mut ModelContext) { let new_active_entry = entry.and_then(|project_path| { let worktree = self.worktree_for_id(project_path.worktree_id, cx)?; diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 34b63fd5bd9fcaff67f9736ac79f6302045fd8f0..577b22d7309e3afeba8ae1f5a5ccb376c5aeeffb 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -63,6 +63,62 @@ async fn test_symlinks(cx: &mut gpui::TestAppContext) { }); } +#[gpui::test] +async fn test_managing_project_specific_settings( + deterministic: Arc, + cx: &mut gpui::TestAppContext, +) { + init_test(cx); + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/the-root", + json!({ + ".zed": { + "settings.json": r#"{ "tab_size": 8 }"# + }, + "a": { + "a.rs": "fn a() {\n A\n}" + }, + "b": { + ".zed": { + "settings.json": r#"{ "tab_size": 2 }"# + }, + "b.rs": "fn b() {\n B\n}" + } + }), + ) + .await; + + let project = Project::test(fs.clone(), ["/the-root".as_ref()], cx).await; + let worktree = project.read_with(cx, |project, cx| project.worktrees(cx).next().unwrap()); + + deterministic.run_until_parked(); + cx.read(|cx| { + let tree = worktree.read(cx); + + let settings_a = language_settings( + None, + Some(&File::for_entry( + tree.entry_for_path("a/a.rs").unwrap().clone(), + worktree.clone(), + )), + cx, + ); + let settings_b = language_settings( + None, + Some(&File::for_entry( + tree.entry_for_path("b/b.rs").unwrap().clone(), + worktree.clone(), + )), + cx, + ); + + assert_eq!(settings_a.tab_size.get(), 8); + assert_eq!(settings_b.tab_size.get(), 2); + }); +} + #[gpui::test] async fn test_managing_language_servers( deterministic: Arc, diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index dc3c172775721c5142aedab6fc4f0f5d66a1c913..7432eb8d40b5ce7da02b3fb06c007aaa74de1730 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -677,6 +677,18 @@ impl Worktree { Worktree::Remote(worktree) => worktree.abs_path.clone(), } } + + pub fn root_file(&self, cx: &mut ModelContext) -> Option { + let entry = self.entry_for_path("")?; + Some(File { + worktree: cx.handle(), + path: entry.path.clone(), + mtime: entry.mtime, + entry_id: entry.id, + is_local: self.is_local(), + is_deleted: false, + }) + } } impl LocalWorktree { @@ -684,14 +696,6 @@ impl LocalWorktree { path.starts_with(&self.abs_path) } - fn absolutize(&self, path: &Path) -> PathBuf { - if path.file_name().is_some() { - self.abs_path.join(path) - } else { - self.abs_path.to_path_buf() - } - } - pub(crate) fn load_buffer( &mut self, id: u64, @@ -1544,6 +1548,14 @@ impl Snapshot { &self.abs_path } + pub fn absolutize(&self, path: &Path) -> PathBuf { + if path.file_name().is_some() { + self.abs_path.join(path) + } else { + self.abs_path.to_path_buf() + } + } + pub fn contains_entry(&self, entry_id: ProjectEntryId) -> bool { self.entries_by_id.get(&entry_id, &()).is_some() } @@ -2383,6 +2395,10 @@ impl language::File for File { .unwrap_or_else(|| OsStr::new(&self.worktree.read(cx).root_name)) } + fn worktree_id(&self) -> usize { + self.worktree.id() + } + fn is_deleted(&self) -> bool { self.is_deleted } @@ -2447,6 +2463,17 @@ impl language::LocalFile for File { } impl File { + pub fn for_entry(entry: Entry, worktree: ModelHandle) -> Self { + Self { + worktree, + path: entry.path.clone(), + mtime: entry.mtime, + entry_id: entry.id, + is_local: true, + is_deleted: false, + } + } + pub fn from_proto( proto: rpc::proto::File, worktree: ModelHandle, @@ -2507,7 +2534,7 @@ pub enum EntryKind { File(CharBag), } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum PathChange { /// A filesystem entry was was created. Added, diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index cca2909da22dba93842304b87c600e2b05a99ae4..4c98dca51a4e661126843b28615e1cdb8a53accc 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -4,7 +4,14 @@ use assets::Assets; use fs::Fs; use futures::{channel::mpsc, StreamExt}; use gpui::{executor::Background, AppContext, AssetSource}; -use std::{borrow::Cow, io::ErrorKind, path::PathBuf, str, sync::Arc, time::Duration}; +use std::{ + borrow::Cow, + io::ErrorKind, + path::{Path, PathBuf}, + str, + sync::Arc, + time::Duration, +}; use util::{paths, ResultExt}; pub fn register(cx: &mut AppContext) { @@ -17,6 +24,10 @@ pub fn get<'a, T: Setting>(cx: &'a AppContext) -> &'a T { cx.global::().get(None) } +pub fn get_local<'a, T: Setting>(location: Option<(usize, &Path)>, cx: &'a AppContext) -> &'a T { + cx.global::().get(location) +} + pub fn default_settings() -> Cow<'static, str> { match Assets.load(DEFAULT_SETTINGS_ASSET_PATH).unwrap() { Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 71b3cc635f4e03465d94cb498567c21bd36bd76a..2560d0b752da72881b8ba373772159e07541c74b 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -89,14 +89,14 @@ pub struct SettingsStore { setting_values: HashMap>, default_deserialized_settings: Option, user_deserialized_settings: Option, - local_deserialized_settings: BTreeMap, serde_json::Value>, + local_deserialized_settings: BTreeMap<(usize, Arc), serde_json::Value>, tab_size_callback: Option<(TypeId, Box Option>)>, } #[derive(Debug)] struct SettingValue { global_value: Option, - local_values: Vec<(Arc, T)>, + local_values: Vec<(usize, Arc, T)>, } trait AnySettingValue { @@ -109,9 +109,9 @@ trait AnySettingValue { custom: &[DeserializedSetting], cx: &AppContext, ) -> Result>; - fn value_for_path(&self, path: Option<&Path>) -> &dyn Any; + fn value_for_path(&self, path: Option<(usize, &Path)>) -> &dyn Any; fn set_global_value(&mut self, value: Box); - fn set_local_value(&mut self, path: Arc, value: Box); + fn set_local_value(&mut self, root_id: usize, path: Arc, value: Box); fn json_schema( &self, generator: &mut SchemaGenerator, @@ -165,7 +165,7 @@ impl SettingsStore { /// /// Panics if the given setting type has not been registered, or if there is no /// value for this setting. - pub fn get(&self, path: Option<&Path>) -> &T { + pub fn get(&self, path: Option<(usize, &Path)>) -> &T { self.setting_values .get(&TypeId::of::()) .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::())) @@ -343,17 +343,19 @@ impl SettingsStore { /// Add or remove a set of local settings via a JSON string. pub fn set_local_settings( &mut self, + root_id: usize, path: Arc, settings_content: Option<&str>, cx: &AppContext, ) -> Result<()> { if let Some(content) = settings_content { self.local_deserialized_settings - .insert(path.clone(), parse_json_with_comments(content)?); + .insert((root_id, path.clone()), parse_json_with_comments(content)?); } else { - self.local_deserialized_settings.remove(&path); + self.local_deserialized_settings + .remove(&(root_id, path.clone())); } - self.recompute_values(Some(&path), cx)?; + self.recompute_values(Some((root_id, &path)), cx)?; Ok(()) } @@ -436,12 +438,12 @@ impl SettingsStore { fn recompute_values( &mut self, - changed_local_path: Option<&Path>, + changed_local_path: Option<(usize, &Path)>, cx: &AppContext, ) -> Result<()> { // Reload the global and local values for every setting. let mut user_settings_stack = Vec::::new(); - let mut paths_stack = Vec::>::new(); + let mut paths_stack = Vec::>::new(); for setting_value in self.setting_values.values_mut() { if let Some(default_settings) = &self.default_deserialized_settings { let default_settings = setting_value.deserialize_setting(default_settings)?; @@ -469,11 +471,11 @@ impl SettingsStore { } // Reload the local values for the setting. - for (path, local_settings) in &self.local_deserialized_settings { + for ((root_id, path), local_settings) in &self.local_deserialized_settings { // Build a stack of all of the local values for that setting. - while let Some(prev_path) = paths_stack.last() { - if let Some(prev_path) = prev_path { - if !path.starts_with(prev_path) { + while let Some(prev_entry) = paths_stack.last() { + if let Some((prev_root_id, prev_path)) = prev_entry { + if root_id != prev_root_id || !path.starts_with(prev_path) { paths_stack.pop(); user_settings_stack.pop(); continue; @@ -485,14 +487,17 @@ impl SettingsStore { if let Some(local_settings) = setting_value.deserialize_setting(&local_settings).log_err() { - paths_stack.push(Some(path.as_ref())); + paths_stack.push(Some((*root_id, path.as_ref()))); user_settings_stack.push(local_settings); // If a local settings file changed, then avoid recomputing local // settings for any path outside of that directory. - if changed_local_path.map_or(false, |changed_local_path| { - !path.starts_with(changed_local_path) - }) { + if changed_local_path.map_or( + false, + |(changed_root_id, changed_local_path)| { + *root_id != changed_root_id || !path.starts_with(changed_local_path) + }, + ) { continue; } @@ -500,7 +505,7 @@ impl SettingsStore { .load_setting(&default_settings, &user_settings_stack, cx) .log_err() { - setting_value.set_local_value(path.clone(), value); + setting_value.set_local_value(*root_id, path.clone(), value); } } } @@ -510,6 +515,24 @@ impl SettingsStore { } } +impl Debug for SettingsStore { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SettingsStore") + .field( + "types", + &self + .setting_values + .values() + .map(|value| value.setting_type_name()) + .collect::>(), + ) + .field("default_settings", &self.default_deserialized_settings) + .field("user_settings", &self.user_deserialized_settings) + .field("local_settings", &self.local_deserialized_settings) + .finish_non_exhaustive() + } +} + impl AnySettingValue for SettingValue { fn key(&self) -> Option<&'static str> { T::KEY @@ -546,10 +569,10 @@ impl AnySettingValue for SettingValue { Ok(DeserializedSetting(Box::new(value))) } - fn value_for_path(&self, path: Option<&Path>) -> &dyn Any { - if let Some(path) = path { - for (settings_path, value) in self.local_values.iter().rev() { - if path.starts_with(&settings_path) { + fn value_for_path(&self, path: Option<(usize, &Path)>) -> &dyn Any { + if let Some((root_id, path)) = path { + for (settings_root_id, settings_path, value) in self.local_values.iter().rev() { + if root_id == *settings_root_id && path.starts_with(&settings_path) { return value; } } @@ -563,11 +586,14 @@ impl AnySettingValue for SettingValue { self.global_value = Some(*value.downcast().unwrap()); } - fn set_local_value(&mut self, path: Arc, value: Box) { + fn set_local_value(&mut self, root_id: usize, path: Arc, value: Box) { let value = *value.downcast().unwrap(); - match self.local_values.binary_search_by_key(&&path, |e| &e.0) { - Ok(ix) => self.local_values[ix].1 = value, - Err(ix) => self.local_values.insert(ix, (path, value)), + match self + .local_values + .binary_search_by_key(&(root_id, &path), |e| (e.0, &e.1)) + { + Ok(ix) => self.local_values[ix].2 = value, + Err(ix) => self.local_values.insert(ix, (root_id, path, value)), } } @@ -884,6 +910,7 @@ mod tests { store .set_local_settings( + 1, Path::new("/root1").into(), Some(r#"{ "user": { "staff": true } }"#), cx, @@ -891,6 +918,7 @@ mod tests { .unwrap(); store .set_local_settings( + 1, Path::new("/root1/subdir").into(), Some(r#"{ "user": { "name": "Jane Doe" } }"#), cx, @@ -899,6 +927,7 @@ mod tests { store .set_local_settings( + 1, Path::new("/root2").into(), Some(r#"{ "user": { "age": 42 }, "key2": "b" }"#), cx, @@ -906,7 +935,7 @@ mod tests { .unwrap(); assert_eq!( - store.get::(Some(Path::new("/root1/something"))), + store.get::(Some((1, Path::new("/root1/something")))), &UserSettings { name: "John Doe".to_string(), age: 31, @@ -914,7 +943,7 @@ mod tests { } ); assert_eq!( - store.get::(Some(Path::new("/root1/subdir/something"))), + store.get::(Some((1, Path::new("/root1/subdir/something")))), &UserSettings { name: "Jane Doe".to_string(), age: 31, @@ -922,7 +951,7 @@ mod tests { } ); assert_eq!( - store.get::(Some(Path::new("/root2/something"))), + store.get::(Some((1, Path::new("/root2/something")))), &UserSettings { name: "John Doe".to_string(), age: 42, @@ -930,7 +959,7 @@ mod tests { } ); assert_eq!( - store.get::(Some(Path::new("/root2/something"))), + store.get::(Some((1, Path::new("/root2/something")))), &MultiKeySettings { key1: "a".to_string(), key2: "b".to_string(), diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 767e3bf4dbb3847064c7a32d217596840457c080..2842dfa8a4f2592830ce3d092e2bfec4ebd2e35c 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -905,7 +905,10 @@ mod tests { cx: &mut TestAppContext, ) -> (ModelHandle, ViewHandle) { let params = cx.update(AppState::test); - cx.update(|cx| theme::init((), cx)); + cx.update(|cx| { + theme::init((), cx); + language::init(cx); + }); let project = Project::test(params.fs.clone(), [], cx).await; let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); diff --git a/crates/util/src/paths.rs b/crates/util/src/paths.rs index f998fc319fcb7bcdfc6be70c66b482ec247a93b0..e3397a1557cfeed520e4c56fa38c40e4539d71a9 100644 --- a/crates/util/src/paths.rs +++ b/crates/util/src/paths.rs @@ -15,6 +15,7 @@ lazy_static::lazy_static! { pub static ref LAST_USERNAME: PathBuf = CONFIG_DIR.join("last-username.txt"); pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log"); pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old"); + pub static ref LOCAL_SETTINGS_RELATIVE_PATH: &'static Path = Path::new(".zed/settings.json"); } pub mod legacy { diff --git a/crates/zed/src/languages/yaml.rs b/crates/zed/src/languages/yaml.rs index bd5f2b4c021e7d8239d76ea29d8ef88ddcf8015b..d66602ee04cb58da09d8b037020cb1fb483937fa 100644 --- a/crates/zed/src/languages/yaml.rs +++ b/crates/zed/src/languages/yaml.rs @@ -107,7 +107,7 @@ impl LspAdapter for YamlLspAdapter { "keyOrdering": false }, "[yaml]": { - "editor.tabSize": language_settings(Some("YAML"), cx).tab_size, + "editor.tabSize": language_settings(Some("YAML"), None, cx).tab_size, } })) .boxed(), From ed0fa2404c3cc53fb4e59a21692fcc18bfe1f4b4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 29 May 2023 14:31:54 -0700 Subject: [PATCH 03/53] Use settings JSON schema when editing local settings files --- crates/zed/src/languages/json.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index 406d54cc03907e94d2b76c4e87e97941458ac694..3947c62a6d96d11ba37444b34930f75bb8fbaec1 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -135,7 +135,10 @@ impl LspAdapter for JsonLspAdapter { }, "schemas": [ { - "fileMatch": [schema_file_match(&paths::SETTINGS)], + "fileMatch": [ + schema_file_match(&paths::SETTINGS), + &*paths::LOCAL_SETTINGS_RELATIVE_PATH, + ], "schema": settings_schema, }, { From 2269c19169741fc9a86e9cf9cbec50b4132e7782 Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 14:06:19 +0200 Subject: [PATCH 04/53] chore: add LICENSE files --- styles/src/themes/atelier-cave/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-dune/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-estuary/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-forest/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-heath/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-lakeside/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-plateau/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-savanna/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-seaside/LICENSE | 21 +++++++++++++++++++ styles/src/themes/atelier-sulphurpool/LICENSE | 21 +++++++++++++++++++ styles/src/themes/ayu/LICENSE | 21 +++++++++++++++++++ 11 files changed, 231 insertions(+) create mode 100644 styles/src/themes/atelier-cave/LICENSE create mode 100644 styles/src/themes/atelier-dune/LICENSE create mode 100644 styles/src/themes/atelier-estuary/LICENSE create mode 100644 styles/src/themes/atelier-forest/LICENSE create mode 100644 styles/src/themes/atelier-heath/LICENSE create mode 100644 styles/src/themes/atelier-lakeside/LICENSE create mode 100644 styles/src/themes/atelier-plateau/LICENSE create mode 100644 styles/src/themes/atelier-savanna/LICENSE create mode 100644 styles/src/themes/atelier-seaside/LICENSE create mode 100644 styles/src/themes/atelier-sulphurpool/LICENSE create mode 100644 styles/src/themes/ayu/LICENSE diff --git a/styles/src/themes/atelier-cave/LICENSE b/styles/src/themes/atelier-cave/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-cave/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-dune/LICENSE b/styles/src/themes/atelier-dune/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-dune/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-estuary/LICENSE b/styles/src/themes/atelier-estuary/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-estuary/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-forest/LICENSE b/styles/src/themes/atelier-forest/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-forest/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-heath/LICENSE b/styles/src/themes/atelier-heath/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-heath/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-lakeside/LICENSE b/styles/src/themes/atelier-lakeside/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-lakeside/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-plateau/LICENSE b/styles/src/themes/atelier-plateau/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-plateau/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-savanna/LICENSE b/styles/src/themes/atelier-savanna/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-savanna/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-seaside/LICENSE b/styles/src/themes/atelier-seaside/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-seaside/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-sulphurpool/LICENSE b/styles/src/themes/atelier-sulphurpool/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9f92967a0436d7118c20cf29bfb8844dba2699b1 --- /dev/null +++ b/styles/src/themes/atelier-sulphurpool/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/ayu/LICENSE b/styles/src/themes/ayu/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..6b83ef0582f26b04f37f8b78ef5a3121b3f3a326 --- /dev/null +++ b/styles/src/themes/ayu/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Ike Ku + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 0d62e76cd629d721997d0798ca50832dd28a9073 Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 15:52:32 +0200 Subject: [PATCH 05/53] refactor: colorSchemes --- styles/src/buildThemes.ts | 2 +- styles/src/colorSchemes.ts | 76 +++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/styles/src/buildThemes.ts b/styles/src/buildThemes.ts index 2a63a407cc4f83dba146991a5edf3757abdfab65..43537655733b10fc2dbaefebf208722acfa2effb 100644 --- a/styles/src/buildThemes.ts +++ b/styles/src/buildThemes.ts @@ -1,7 +1,7 @@ import * as fs from "fs" import { tmpdir } from "os" import * as path from "path" -import colorSchemes, { staffColorSchemes } from "./colorSchemes" +import { colorSchemes, staffColorSchemes } from "./colorSchemes" import app from "./styleTree/app" import { ColorScheme } from "./themes/common/colorScheme" import snakeCase from "./utils/snakeCase" diff --git a/styles/src/colorSchemes.ts b/styles/src/colorSchemes.ts index 4d2d7f6e0253c6b6dd8d6d579000f3d9cb53ad5f..e8d06870440e0d2fe1f1cb528ff04ed5e79b1f5f 100644 --- a/styles/src/colorSchemes.ts +++ b/styles/src/colorSchemes.ts @@ -2,53 +2,63 @@ import fs from "fs" import path from "path" import { ColorScheme, Meta } from "./themes/common/colorScheme" -const colorSchemes: ColorScheme[] = [] -export default colorSchemes +const THEMES_DIRECTORY = path.resolve(`${__dirname}/themes`) +const STAFF_DIRECTORY = path.resolve(`${__dirname}/themes/staff`) +const IGNORE_ITEMS = ["staff", "common", "template.ts"] +const ACCEPT_EXTENSION = ".ts" -const schemeMeta: Meta[] = [] -export { schemeMeta } +function getAllTsFiles(directoryPath: string) { + const files = fs.readdirSync(directoryPath) + const fileList: string[] = [] -const staffColorSchemes: ColorScheme[] = [] -export { staffColorSchemes } + for (const file of files) { + if (!IGNORE_ITEMS.includes(file)) { + const filePath = path.join(directoryPath, file) -const experimentalColorSchemes: ColorScheme[] = [] -export { experimentalColorSchemes } - -const themes_directory = path.resolve(`${__dirname}/themes`) - -function for_all_color_schemes_in( - themesPath: string, - callback: (module: any, path: string) => void -) { - for (const fileName of fs.readdirSync(themesPath)) { - if (fileName == "template.ts") continue - const filePath = path.join(themesPath, fileName) - - if (fs.statSync(filePath).isFile()) { - const colorScheme = require(filePath) - callback(colorScheme, path.basename(filePath)) + if (fs.statSync(filePath).isDirectory()) { + fileList.push(...getAllTsFiles(filePath)) + } else if (path.extname(file) === ACCEPT_EXTENSION) { + fileList.push(filePath) + } } } + + return fileList +} + +function getAllColorSchemes(directoryPath: string) { + const files = getAllTsFiles(directoryPath) + return files.map((filePath) => ({ + colorScheme: require(filePath), + filePath: path.basename(filePath), + })) } -function fillColorSchemes(themesPath: string, colorSchemes: ColorScheme[]) { - for_all_color_schemes_in(themesPath, (colorScheme, _path) => { +function getColorSchemes(directoryPath: string) { + const colorSchemes: ColorScheme[] = [] + + for (const { colorScheme } of getAllColorSchemes(directoryPath)) { if (colorScheme.dark) colorSchemes.push(colorScheme.dark) - if (colorScheme.light) colorSchemes.push(colorScheme.light) - }) + else if (colorScheme.light) colorSchemes.push(colorScheme.light) + } + + return colorSchemes } -fillColorSchemes(themes_directory, colorSchemes) -fillColorSchemes(path.resolve(`${themes_directory}/staff`), staffColorSchemes) +function getMeta(directoryPath: string) { + const meta: Meta[] = [] -function fillMeta(themesPath: string, meta: Meta[]) { - for_all_color_schemes_in(themesPath, (colorScheme, path) => { + for (const { colorScheme, filePath } of getAllColorSchemes(directoryPath)) { if (colorScheme.meta) { meta.push(colorScheme.meta) } else { - throw Error(`Public theme ${path} must have a meta field`) + throw Error(`Public theme ${filePath} must have a meta field`) } - }) + } + + return meta } -fillMeta(themes_directory, schemeMeta) +export const colorSchemes = getColorSchemes(THEMES_DIRECTORY) +export const staffColorSchemes = getColorSchemes(STAFF_DIRECTORY) +export const schemeMeta = getMeta(THEMES_DIRECTORY) From ac63043c273f724777a1ba9254ee6d8e6a882977 Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 16:52:28 +0200 Subject: [PATCH 06/53] chore: move similar themes to one folder --- styles/src/themes/atelier-dune/LICENSE | 21 ------------------- styles/src/themes/atelier-estuary/LICENSE | 21 ------------------- styles/src/themes/atelier-forest/LICENSE | 21 ------------------- styles/src/themes/atelier-heath/LICENSE | 21 ------------------- styles/src/themes/atelier-lakeside/LICENSE | 21 ------------------- styles/src/themes/atelier-plateau/LICENSE | 21 ------------------- styles/src/themes/atelier-savanna/LICENSE | 21 ------------------- styles/src/themes/atelier-seaside/LICENSE | 21 ------------------- styles/src/themes/atelier-sulphurpool/LICENSE | 21 ------------------- .../themes/{atelier-cave => atelier}/LICENSE | 0 .../atelier-cave-dark.ts | 2 +- .../atelier-cave-light.ts | 2 +- .../atelier-dune-dark.ts | 2 +- .../atelier-dune-light.ts | 2 +- .../atelier-estuary-dark.ts | 2 +- .../atelier-estuary-light.ts | 2 +- .../atelier-forest-dark.ts | 2 +- .../atelier-forest-light.ts | 2 +- .../atelier-heath-dark.ts | 2 +- .../atelier-heath-light.ts | 2 +- .../atelier-lakeside-dark.ts | 2 +- .../atelier-lakeside-light.ts | 2 +- .../atelier-plateau-dark.ts | 2 +- .../atelier-plateau-light.ts | 2 +- .../atelier-savanna-dark.ts | 2 +- .../atelier-savanna-light.ts | 2 +- .../atelier-seaside-dark.ts | 2 +- .../atelier-seaside-light.ts | 2 +- .../atelier-sulphurpool-dark.ts | 2 +- .../atelier-sulphurpool-light.ts | 2 +- 30 files changed, 20 insertions(+), 209 deletions(-) delete mode 100644 styles/src/themes/atelier-dune/LICENSE delete mode 100644 styles/src/themes/atelier-estuary/LICENSE delete mode 100644 styles/src/themes/atelier-forest/LICENSE delete mode 100644 styles/src/themes/atelier-heath/LICENSE delete mode 100644 styles/src/themes/atelier-lakeside/LICENSE delete mode 100644 styles/src/themes/atelier-plateau/LICENSE delete mode 100644 styles/src/themes/atelier-savanna/LICENSE delete mode 100644 styles/src/themes/atelier-seaside/LICENSE delete mode 100644 styles/src/themes/atelier-sulphurpool/LICENSE rename styles/src/themes/{atelier-cave => atelier}/LICENSE (100%) rename styles/src/themes/{atelier-cave => atelier}/atelier-cave-dark.ts (95%) rename styles/src/themes/{atelier-cave => atelier}/atelier-cave-light.ts (95%) rename styles/src/themes/{atelier-dune => atelier}/atelier-dune-dark.ts (95%) rename styles/src/themes/{atelier-dune => atelier}/atelier-dune-light.ts (95%) rename styles/src/themes/{atelier-estuary => atelier}/atelier-estuary-dark.ts (95%) rename styles/src/themes/{atelier-estuary => atelier}/atelier-estuary-light.ts (95%) rename styles/src/themes/{atelier-forest => atelier}/atelier-forest-dark.ts (95%) rename styles/src/themes/{atelier-forest => atelier}/atelier-forest-light.ts (95%) rename styles/src/themes/{atelier-heath => atelier}/atelier-heath-dark.ts (95%) rename styles/src/themes/{atelier-heath => atelier}/atelier-heath-light.ts (95%) rename styles/src/themes/{atelier-lakeside => atelier}/atelier-lakeside-dark.ts (95%) rename styles/src/themes/{atelier-lakeside => atelier}/atelier-lakeside-light.ts (95%) rename styles/src/themes/{atelier-plateau => atelier}/atelier-plateau-dark.ts (95%) rename styles/src/themes/{atelier-plateau => atelier}/atelier-plateau-light.ts (95%) rename styles/src/themes/{atelier-savanna => atelier}/atelier-savanna-dark.ts (95%) rename styles/src/themes/{atelier-savanna => atelier}/atelier-savanna-light.ts (95%) rename styles/src/themes/{atelier-seaside => atelier}/atelier-seaside-dark.ts (95%) rename styles/src/themes/{atelier-seaside => atelier}/atelier-seaside-light.ts (95%) rename styles/src/themes/{atelier-sulphurpool => atelier}/atelier-sulphurpool-dark.ts (95%) rename styles/src/themes/{atelier-sulphurpool => atelier}/atelier-sulphurpool-light.ts (95%) diff --git a/styles/src/themes/atelier-dune/LICENSE b/styles/src/themes/atelier-dune/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-dune/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-estuary/LICENSE b/styles/src/themes/atelier-estuary/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-estuary/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-forest/LICENSE b/styles/src/themes/atelier-forest/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-forest/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-heath/LICENSE b/styles/src/themes/atelier-heath/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-heath/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-lakeside/LICENSE b/styles/src/themes/atelier-lakeside/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-lakeside/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-plateau/LICENSE b/styles/src/themes/atelier-plateau/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-plateau/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-savanna/LICENSE b/styles/src/themes/atelier-savanna/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-savanna/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-seaside/LICENSE b/styles/src/themes/atelier-seaside/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-seaside/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-sulphurpool/LICENSE b/styles/src/themes/atelier-sulphurpool/LICENSE deleted file mode 100644 index 9f92967a0436d7118c20cf29bfb8844dba2699b1..0000000000000000000000000000000000000000 --- a/styles/src/themes/atelier-sulphurpool/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/styles/src/themes/atelier-cave/LICENSE b/styles/src/themes/atelier/LICENSE similarity index 100% rename from styles/src/themes/atelier-cave/LICENSE rename to styles/src/themes/atelier/LICENSE diff --git a/styles/src/themes/atelier-cave/atelier-cave-dark.ts b/styles/src/themes/atelier/atelier-cave-dark.ts similarity index 95% rename from styles/src/themes/atelier-cave/atelier-cave-dark.ts rename to styles/src/themes/atelier/atelier-cave-dark.ts index a61db0e590eeea584b89481b5682cd37bb3ab2af..41ee6a745c9c9165c0e5610fb30c92bbbedce3a6 100644 --- a/styles/src/themes/atelier-cave/atelier-cave-dark.ts +++ b/styles/src/themes/atelier/atelier-cave-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-cave/atelier-cave-light.ts b/styles/src/themes/atelier/atelier-cave-light.ts similarity index 95% rename from styles/src/themes/atelier-cave/atelier-cave-light.ts rename to styles/src/themes/atelier/atelier-cave-light.ts index 739fe1320b6cf49e81cdde5eb84113ea67e4eb3c..9e0473bbfa0b63838329e21eaae11ba63abc2c53 100644 --- a/styles/src/themes/atelier-cave/atelier-cave-light.ts +++ b/styles/src/themes/atelier/atelier-cave-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-dune/atelier-dune-dark.ts b/styles/src/themes/atelier/atelier-dune-dark.ts similarity index 95% rename from styles/src/themes/atelier-dune/atelier-dune-dark.ts rename to styles/src/themes/atelier/atelier-dune-dark.ts index 7a3c3fbd07dac797d97eb05c7c74e10f95f954ca..c21ee61a6030c03ced3adb3ae399edb1c4ac999f 100644 --- a/styles/src/themes/atelier-dune/atelier-dune-dark.ts +++ b/styles/src/themes/atelier/atelier-dune-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-dune/atelier-dune-light.ts b/styles/src/themes/atelier/atelier-dune-light.ts similarity index 95% rename from styles/src/themes/atelier-dune/atelier-dune-light.ts rename to styles/src/themes/atelier/atelier-dune-light.ts index 3ee60164b689f41db333f31b80f01dcbfc2a7de9..956ae72c60f6da957abffb3c7234cea5441d50a3 100644 --- a/styles/src/themes/atelier-dune/atelier-dune-light.ts +++ b/styles/src/themes/atelier/atelier-dune-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-estuary/atelier-estuary-dark.ts b/styles/src/themes/atelier/atelier-estuary-dark.ts similarity index 95% rename from styles/src/themes/atelier-estuary/atelier-estuary-dark.ts rename to styles/src/themes/atelier/atelier-estuary-dark.ts index 5ec6df8d359ff6cf6c169d03d4cf4b252795f4bd..b9f1880d682fa8b9a9b23015beba5ffb355564b5 100644 --- a/styles/src/themes/atelier-estuary/atelier-estuary-dark.ts +++ b/styles/src/themes/atelier/atelier-estuary-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-estuary/atelier-estuary-light.ts b/styles/src/themes/atelier/atelier-estuary-light.ts similarity index 95% rename from styles/src/themes/atelier-estuary/atelier-estuary-light.ts rename to styles/src/themes/atelier/atelier-estuary-light.ts index bc583d41ac7cd7345c2b1d0b3ca11a6258658391..a9eeb612edb4a45fcf0d51bcf92f95c1122697dd 100644 --- a/styles/src/themes/atelier-estuary/atelier-estuary-light.ts +++ b/styles/src/themes/atelier/atelier-estuary-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-forest/atelier-forest-dark.ts b/styles/src/themes/atelier/atelier-forest-dark.ts similarity index 95% rename from styles/src/themes/atelier-forest/atelier-forest-dark.ts rename to styles/src/themes/atelier/atelier-forest-dark.ts index 72f958efdfad406d7a1e1504f735e6684851ef9c..352f1ea43efe7760e6752e7d5a313ad8a5ff3dd9 100644 --- a/styles/src/themes/atelier-forest/atelier-forest-dark.ts +++ b/styles/src/themes/atelier/atelier-forest-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-forest/atelier-forest-light.ts b/styles/src/themes/atelier/atelier-forest-light.ts similarity index 95% rename from styles/src/themes/atelier-forest/atelier-forest-light.ts rename to styles/src/themes/atelier/atelier-forest-light.ts index 463350f822a2f8941b31a5e2e7bad93d0d8668f1..1378c9b061490b0606e5e6b5297d81878cf5986e 100644 --- a/styles/src/themes/atelier-forest/atelier-forest-light.ts +++ b/styles/src/themes/atelier/atelier-forest-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-heath/atelier-heath-dark.ts b/styles/src/themes/atelier/atelier-heath-dark.ts similarity index 95% rename from styles/src/themes/atelier-heath/atelier-heath-dark.ts rename to styles/src/themes/atelier/atelier-heath-dark.ts index 010169b0225b759ee4b10fbc6037d12f13eebd4e..4c3519442271f6a0e5967dc2c4e5a276834ffa0d 100644 --- a/styles/src/themes/atelier-heath/atelier-heath-dark.ts +++ b/styles/src/themes/atelier/atelier-heath-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-heath/atelier-heath-light.ts b/styles/src/themes/atelier/atelier-heath-light.ts similarity index 95% rename from styles/src/themes/atelier-heath/atelier-heath-light.ts rename to styles/src/themes/atelier/atelier-heath-light.ts index 09d39b6d6662b8f3018ea418c9278a15bc86d9c7..51b9ef93988f2e4f0eb3527a6e2a4003a1a13647 100644 --- a/styles/src/themes/atelier-heath/atelier-heath-light.ts +++ b/styles/src/themes/atelier/atelier-heath-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts b/styles/src/themes/atelier/atelier-lakeside-dark.ts similarity index 95% rename from styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts rename to styles/src/themes/atelier/atelier-lakeside-dark.ts index 59728f30f327a20fab35210d3400ed62176de870..ece9179860ec0bd45db4849a179ce0ff7b7a77a8 100644 --- a/styles/src/themes/atelier-lakeside/atelier-lakeside-dark.ts +++ b/styles/src/themes/atelier/atelier-lakeside-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts b/styles/src/themes/atelier/atelier-lakeside-light.ts similarity index 95% rename from styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts rename to styles/src/themes/atelier/atelier-lakeside-light.ts index d26c4fe67945454b7bbd43b27f409fea9dc171bd..fd265d10c8acde6e989e5ac5e961aa706e0fc207 100644 --- a/styles/src/themes/atelier-lakeside/atelier-lakeside-light.ts +++ b/styles/src/themes/atelier/atelier-lakeside-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-plateau/atelier-plateau-dark.ts b/styles/src/themes/atelier/atelier-plateau-dark.ts similarity index 95% rename from styles/src/themes/atelier-plateau/atelier-plateau-dark.ts rename to styles/src/themes/atelier/atelier-plateau-dark.ts index 8299116c0efbd484279cb01dd1f946e9923af3ba..ef64782bda4109269beb52b9f8c9aa65486cb4f7 100644 --- a/styles/src/themes/atelier-plateau/atelier-plateau-dark.ts +++ b/styles/src/themes/atelier/atelier-plateau-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-plateau/atelier-plateau-light.ts b/styles/src/themes/atelier/atelier-plateau-light.ts similarity index 95% rename from styles/src/themes/atelier-plateau/atelier-plateau-light.ts rename to styles/src/themes/atelier/atelier-plateau-light.ts index 7fcc4220accaca761cec203e9856102781a14b7d..9fe51f5b7914d283bfcc4e2651bab2f987ede16a 100644 --- a/styles/src/themes/atelier-plateau/atelier-plateau-light.ts +++ b/styles/src/themes/atelier/atelier-plateau-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-savanna/atelier-savanna-dark.ts b/styles/src/themes/atelier/atelier-savanna-dark.ts similarity index 95% rename from styles/src/themes/atelier-savanna/atelier-savanna-dark.ts rename to styles/src/themes/atelier/atelier-savanna-dark.ts index 5b6f034563433379d30f27d4b5043b35d3402ee1..36de9b817f52bc490723a8ecc5d91f271dcb6f27 100644 --- a/styles/src/themes/atelier-savanna/atelier-savanna-dark.ts +++ b/styles/src/themes/atelier/atelier-savanna-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-savanna/atelier-savanna-light.ts b/styles/src/themes/atelier/atelier-savanna-light.ts similarity index 95% rename from styles/src/themes/atelier-savanna/atelier-savanna-light.ts rename to styles/src/themes/atelier/atelier-savanna-light.ts index 498959487696546e2d5c540a44019fbb5262e6ac..d5d9cb369d8da7b5a141b251b4af1d5ef8c9b978 100644 --- a/styles/src/themes/atelier-savanna/atelier-savanna-light.ts +++ b/styles/src/themes/atelier/atelier-savanna-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-seaside/atelier-seaside-dark.ts b/styles/src/themes/atelier/atelier-seaside-dark.ts similarity index 95% rename from styles/src/themes/atelier-seaside/atelier-seaside-dark.ts rename to styles/src/themes/atelier/atelier-seaside-dark.ts index 00631eff51f8e3431a8ae5c872a0428efe659dca..f7c49ad71eb1e885e92491f960560b5c7b72d24b 100644 --- a/styles/src/themes/atelier-seaside/atelier-seaside-dark.ts +++ b/styles/src/themes/atelier/atelier-seaside-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-seaside/atelier-seaside-light.ts b/styles/src/themes/atelier/atelier-seaside-light.ts similarity index 95% rename from styles/src/themes/atelier-seaside/atelier-seaside-light.ts rename to styles/src/themes/atelier/atelier-seaside-light.ts index af6af2f02737968d5161118bb2442c6426cc6a1d..1cf64614464a5d8b3e23576b1bc110d4c21ebff6 100644 --- a/styles/src/themes/atelier-seaside/atelier-seaside-light.ts +++ b/styles/src/themes/atelier/atelier-seaside-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts b/styles/src/themes/atelier/atelier-sulphurpool-dark.ts similarity index 95% rename from styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts rename to styles/src/themes/atelier/atelier-sulphurpool-dark.ts index 140d02c2e6bc49a69e4dda59c4142dbcc6f714af..b4a4e2a651981487b1e51c275d31d0c7ff70b029 100644 --- a/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-dark.ts +++ b/styles/src/themes/atelier/atelier-sulphurpool-dark.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { diff --git a/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts b/styles/src/themes/atelier/atelier-sulphurpool-light.ts similarity index 95% rename from styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts rename to styles/src/themes/atelier/atelier-sulphurpool-light.ts index b6dba4c384cde17bafe88ce27cbf5a802b8ee020..046adbdf4315a4d305d96b79046631513a133a91 100644 --- a/styles/src/themes/atelier-sulphurpool/atelier-sulphurpool-light.ts +++ b/styles/src/themes/atelier/atelier-sulphurpool-light.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js" import { Meta } from "../common/colorScheme" import { colorRamp, createColorScheme } from "../common/ramps" -import { metaCommon, name, buildSyntax, Variant } from "../common/atelier-common" +import { metaCommon, name, buildSyntax, Variant } from "./common" const variant: Variant = { meta: { From 05d1dd6b11386002680d8d0df67e975c56517ce2 Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 16:53:12 +0200 Subject: [PATCH 07/53] refactor: move common to theme folder --- styles/src/colorSchemes.ts | 2 +- .../themes/{common/atelier-common.ts => atelier/common.ts} | 2 +- styles/src/themes/ayu/ayu-dark.ts | 2 +- styles/src/themes/ayu/ayu-light.ts | 2 +- styles/src/themes/ayu/ayu-mirage.ts | 2 +- styles/src/themes/{common/ayu-common.ts => ayu/common.ts} | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) rename styles/src/themes/{common/atelier-common.ts => atelier/common.ts} (96%) rename styles/src/themes/{common/ayu-common.ts => ayu/common.ts} (95%) diff --git a/styles/src/colorSchemes.ts b/styles/src/colorSchemes.ts index e8d06870440e0d2fe1f1cb528ff04ed5e79b1f5f..07eb26a591d6014ff6f73dcce73fe2ac86515e11 100644 --- a/styles/src/colorSchemes.ts +++ b/styles/src/colorSchemes.ts @@ -4,7 +4,7 @@ import { ColorScheme, Meta } from "./themes/common/colorScheme" const THEMES_DIRECTORY = path.resolve(`${__dirname}/themes`) const STAFF_DIRECTORY = path.resolve(`${__dirname}/themes/staff`) -const IGNORE_ITEMS = ["staff", "common", "template.ts"] +const IGNORE_ITEMS = ["staff", "common", "common.ts"] const ACCEPT_EXTENSION = ".ts" function getAllTsFiles(directoryPath: string) { diff --git a/styles/src/themes/common/atelier-common.ts b/styles/src/themes/atelier/common.ts similarity index 96% rename from styles/src/themes/common/atelier-common.ts rename to styles/src/themes/atelier/common.ts index 08a915d01948f300441d0904cbff2fd406e3dcba..7fb07f7a6e98beb2b9d7c53ee60f03bedcdcdc12 100644 --- a/styles/src/themes/common/atelier-common.ts +++ b/styles/src/themes/atelier/common.ts @@ -1,4 +1,4 @@ -import { License, Meta, ThemeSyntax } from "./colorScheme" +import { License, Meta, ThemeSyntax } from "../common/colorScheme" export interface Variant { meta: Meta diff --git a/styles/src/themes/ayu/ayu-dark.ts b/styles/src/themes/ayu/ayu-dark.ts index eb837231fe1b0d3818768ce0b149a512d6ea3f7d..1dc663f161b6baa862fb42cb07fc9ddbb9c5c3e0 100644 --- a/styles/src/themes/ayu/ayu-dark.ts +++ b/styles/src/themes/ayu/ayu-dark.ts @@ -1,5 +1,5 @@ import { createColorScheme } from "../common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" +import { ayu, meta as themeMeta, buildTheme } from "./common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/ayu/ayu-light.ts b/styles/src/themes/ayu/ayu-light.ts index 9c29449db5bd323e21aa9004a1b2ac2731c0a617..25435219447e1d7e4dd1125c59cb04cb420315eb 100644 --- a/styles/src/themes/ayu/ayu-light.ts +++ b/styles/src/themes/ayu/ayu-light.ts @@ -1,5 +1,5 @@ import { createColorScheme } from "../common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" +import { ayu, meta as themeMeta, buildTheme } from "./common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/ayu/ayu-mirage.ts b/styles/src/themes/ayu/ayu-mirage.ts index 52bf5493922102fffd9cd8cc0eef24ba9bb2b720..2ada3678ee47a95112bcff76150b8b2f54273f40 100644 --- a/styles/src/themes/ayu/ayu-mirage.ts +++ b/styles/src/themes/ayu/ayu-mirage.ts @@ -1,5 +1,5 @@ import { createColorScheme } from "../common/ramps" -import { ayu, meta as themeMeta, buildTheme } from "../common/ayu-common" +import { ayu, meta as themeMeta, buildTheme } from "./common" export const meta = { ...themeMeta, diff --git a/styles/src/themes/common/ayu-common.ts b/styles/src/themes/ayu/common.ts similarity index 95% rename from styles/src/themes/common/ayu-common.ts rename to styles/src/themes/ayu/common.ts index f08817ef492e7c56fac0e593ffd0d74d1e4d735b..2d3687801f82300cc95af15941ec1ce72ea5e3ad 100644 --- a/styles/src/themes/common/ayu-common.ts +++ b/styles/src/themes/ayu/common.ts @@ -1,8 +1,8 @@ import { dark, light, mirage } from "ayu" -import { ThemeSyntax } from "./syntax" +import { ThemeSyntax } from "../common/syntax" import chroma from "chroma-js" -import { colorRamp } from "./ramps" -import { Meta } from "./colorScheme" +import { colorRamp } from "../common/ramps" +import { Meta } from "../common/colorScheme" export const ayu = { dark, From 14efc18ecac7a601ad8481cde656a5dc6123ef2b Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 18:11:54 +0200 Subject: [PATCH 08/53] refactor: add license file and check it exists --- styles/src/colorSchemes.ts | 33 ++++++++++++++++++------- styles/src/themes/common/colorScheme.ts | 5 ++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/styles/src/colorSchemes.ts b/styles/src/colorSchemes.ts index 07eb26a591d6014ff6f73dcce73fe2ac86515e11..74f1a2a03c4e44e43640534755d804e8163413d3 100644 --- a/styles/src/colorSchemes.ts +++ b/styles/src/colorSchemes.ts @@ -1,11 +1,12 @@ import fs from "fs" import path from "path" -import { ColorScheme, Meta } from "./themes/common/colorScheme" +import { ColorScheme, MetaAndLicense } from "./themes/common/colorScheme" const THEMES_DIRECTORY = path.resolve(`${__dirname}/themes`) const STAFF_DIRECTORY = path.resolve(`${__dirname}/themes/staff`) const IGNORE_ITEMS = ["staff", "common", "common.ts"] const ACCEPT_EXTENSION = ".ts" +const LICENSE_FILE_NAME = "LICENSE" function getAllTsFiles(directoryPath: string) { const files = fs.readdirSync(directoryPath) @@ -30,7 +31,9 @@ function getAllColorSchemes(directoryPath: string) { const files = getAllTsFiles(directoryPath) return files.map((filePath) => ({ colorScheme: require(filePath), - filePath: path.basename(filePath), + filePath, + fileName: path.basename(filePath), + licenseFile: `${path.dirname(filePath)}/${LICENSE_FILE_NAME}`, })) } @@ -45,15 +48,27 @@ function getColorSchemes(directoryPath: string) { return colorSchemes } -function getMeta(directoryPath: string) { - const meta: Meta[] = [] +function getMetaAndLicense(directoryPath: string) { + const meta: MetaAndLicense[] = [] - for (const { colorScheme, filePath } of getAllColorSchemes(directoryPath)) { - if (colorScheme.meta) { - meta.push(colorScheme.meta) - } else { + for (const { colorScheme, filePath, licenseFile } of getAllColorSchemes( + directoryPath + )) { + const licenseExists = fs.existsSync(licenseFile) + if (!licenseExists) { + throw Error( + `Public theme should have a LICENSE file ${licenseFile}` + ) + } + + if (!colorScheme.meta) { throw Error(`Public theme ${filePath} must have a meta field`) } + + meta.push({ + meta: colorScheme.meta, + licenseFile, + }) } return meta @@ -61,4 +76,4 @@ function getMeta(directoryPath: string) { export const colorSchemes = getColorSchemes(THEMES_DIRECTORY) export const staffColorSchemes = getColorSchemes(STAFF_DIRECTORY) -export const schemeMeta = getMeta(THEMES_DIRECTORY) +export const schemeMeta = getMetaAndLicense(THEMES_DIRECTORY) diff --git a/styles/src/themes/common/colorScheme.ts b/styles/src/themes/common/colorScheme.ts index 3b5b8f69329651f20a0ad5aef834eb9435e8b5d1..657250f5f298ad79ee7ea9e248be51d20f24553e 100644 --- a/styles/src/themes/common/colorScheme.ts +++ b/styles/src/themes/common/colorScheme.ts @@ -19,6 +19,11 @@ export interface ColorScheme { syntax?: Partial } +export interface MetaAndLicense { + meta: Meta + licenseFile: string +} + export interface Meta { name: string author: string From 4568f80f2e7cbc7e822762bcf7d54e782998d02f Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 18:12:31 +0200 Subject: [PATCH 09/53] feat: read from LICENSE file --- styles/src/buildLicenses.ts | 78 ++++++++++--------------------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/styles/src/buildLicenses.ts b/styles/src/buildLicenses.ts index 3367e50ff027601db2b68ead242dc3a266b21e1e..9a053e9c0c9ca7732a71b149a884df4a11b9391c 100644 --- a/styles/src/buildLicenses.ts +++ b/styles/src/buildLicenses.ts @@ -1,11 +1,9 @@ import * as fs from "fs" import toml from "toml" import { schemeMeta } from "./colorSchemes" -import { Meta, Verification } from "./themes/common/colorScheme" -import https from "https" -import crypto from "crypto" +import { MetaAndLicense } from "./themes/common/colorScheme" -const accepted_licenses_file = `${__dirname}/../../script/licenses/zed-licenses.toml` +const ACCEPTED_LICENSES_FILE = `${__dirname}/../../script/licenses/zed-licenses.toml` // Use the cargo-about configuration file as the source of truth for supported licenses. function parseAcceptedToml(file: string): string[] { @@ -20,8 +18,11 @@ function parseAcceptedToml(file: string): string[] { return obj.accepted } -function checkLicenses(schemeMeta: Meta[], licenses: string[]) { - for (let meta of schemeMeta) { +function checkLicenses( + schemeMetaWithLicense: MetaAndLicense[], + licenses: string[] +) { + for (const { meta } of schemeMetaWithLicense) { // FIXME: Add support for conjuctions and conditions if (licenses.indexOf(meta.license.SPDX) < 0) { throw Error( @@ -31,62 +32,23 @@ function checkLicenses(schemeMeta: Meta[], licenses: string[]) { } } -function getLicenseText( - schemeMeta: Meta[], - callback: (meta: Meta, license_text: string) => void -) { - for (let meta of schemeMeta) { - if (typeof meta.license.license_text == "string") { - callback(meta, meta.license.license_text) - } else { - let license_text_obj: Verification = meta.license.license_text - // The following copied from the example code on nodejs.org: - // https://nodejs.org/api/http.html#httpgetoptions-callback - https - .get(license_text_obj.https_url, (res) => { - const { statusCode } = res - - if (statusCode < 200 || statusCode >= 300) { - throw new Error( - `Failed to fetch license for: ${meta.name}, Status Code: ${statusCode}` - ) - } - - res.setEncoding("utf8") - let rawData = "" - res.on("data", (chunk) => { - rawData += chunk - }) - res.on("end", () => { - const hash = crypto - .createHash("sha256") - .update(rawData) - .digest("hex") - if (license_text_obj.license_checksum == hash) { - callback(meta, rawData) - } else { - throw Error( - `Checksum for ${meta.name} did not match file downloaded from ${license_text_obj.https_url}` - ) - } - }) - }) - .on("error", (e) => { - throw e - }) - } +function generateLicenseFile(schemeMetaWithLicense: MetaAndLicense[]) { + for (const { meta, licenseFile } of schemeMetaWithLicense) { + const licenseText = fs.readFileSync(licenseFile).toString() + writeLicense(meta.name, meta.url, licenseText) } } -function writeLicense(schemeMeta: Meta, text: String) { +function writeLicense( + themeName: string, + themeUrl: string, + licenseText: String +) { process.stdout.write( - `## [${schemeMeta.name}](${schemeMeta.url})\n\n${text}\n********************************************************************************\n\n` + `## [${themeName}](${themeUrl})\n\n${licenseText}\n********************************************************************************\n\n` ) } -const accepted_licenses = parseAcceptedToml(accepted_licenses_file) -checkLicenses(schemeMeta, accepted_licenses) - -getLicenseText(schemeMeta, (meta, text) => { - writeLicense(meta, text) -}) +const acceptedLicenses = parseAcceptedToml(ACCEPTED_LICENSES_FILE) +checkLicenses(schemeMeta, acceptedLicenses) +generateLicenseFile(schemeMeta) From 51c7078f47827e3701c275e501bc2a040799d32b Mon Sep 17 00:00:00 2001 From: Sergey Onufrienko Date: Tue, 30 May 2023 18:16:50 +0200 Subject: [PATCH 10/53] chore: remove license_text --- styles/src/themes/andromeda/andromeda.ts | 6 ------ styles/src/themes/atelier/common.ts | 5 ----- styles/src/themes/ayu/common.ts | 6 ------ styles/src/themes/common/colorScheme.ts | 7 ------- styles/src/themes/gruvbox/gruvbox-common.ts | 2 -- styles/src/themes/one/one-dark.ts | 6 ------ styles/src/themes/one/one-light.ts | 6 ------ styles/src/themes/rose-pine/rose-pine-dawn.ts | 6 ------ styles/src/themes/rose-pine/rose-pine-moon.ts | 6 ------ styles/src/themes/rose-pine/rose-pine.ts | 6 ------ styles/src/themes/sandcastle/sandcastle.ts | 6 ------ styles/src/themes/solarized/solarized.ts | 6 ------ styles/src/themes/summercamp/summercamp.ts | 6 ------ 13 files changed, 74 deletions(-) diff --git a/styles/src/themes/andromeda/andromeda.ts b/styles/src/themes/andromeda/andromeda.ts index adfea37d0694dc47350d96178478ef0b370117f3..d7f7f53b90705bbee2431100797631d33bfbb041 100644 --- a/styles/src/themes/andromeda/andromeda.ts +++ b/styles/src/themes/andromeda/andromeda.ts @@ -34,12 +34,6 @@ export const meta: Meta = { author: "EliverLara", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/EliverLara/Andromeda/master/LICENSE.md", - license_checksum: - "2f7886f1a05cefc2c26f5e49de1a39fa4466413c1ccb06fc80960e73f5ed4b89", - }, }, url: "https://github.com/EliverLara/Andromeda", } diff --git a/styles/src/themes/atelier/common.ts b/styles/src/themes/atelier/common.ts index 7fb07f7a6e98beb2b9d7c53ee60f03bedcdcdc12..746834c88b0103daa7be8c73e75b96dd298e1c6a 100644 --- a/styles/src/themes/atelier/common.ts +++ b/styles/src/themes/atelier/common.ts @@ -29,11 +29,6 @@ export const metaCommon: { author: "Bram de Haan (http://atelierbramdehaan.nl)", license: { SPDX: "MIT", - license_text: { - https_url: "https://atelierbram.mit-license.org/license.txt", - license_checksum: - "f95ce526ef4e7eecf7a832bba0e3451cc1000f9ce63eb01ed6f64f8109f5d0a5", - }, }, } diff --git a/styles/src/themes/ayu/common.ts b/styles/src/themes/ayu/common.ts index 2d3687801f82300cc95af15941ec1ce72ea5e3ad..e586e2d22d7c8a2fdf237ed0f19d56e4eb3bc249 100644 --- a/styles/src/themes/ayu/common.ts +++ b/styles/src/themes/ayu/common.ts @@ -79,12 +79,6 @@ export const meta: Meta = { author: "dempfi", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/dempfi/ayu/master/LICENSE", - license_checksum: - "e0af0e0d1754c18ca075649d42f5c6d9a60f8bdc03c20dfd97105f2253a94173", - }, }, url: "https://github.com/dempfi/ayu", } diff --git a/styles/src/themes/common/colorScheme.ts b/styles/src/themes/common/colorScheme.ts index 657250f5f298ad79ee7ea9e248be51d20f24553e..5cf125ae8f723fd2130eacda5d00be3ad604bf6e 100644 --- a/styles/src/themes/common/colorScheme.ts +++ b/styles/src/themes/common/colorScheme.ts @@ -33,13 +33,6 @@ export interface Meta { export interface License { SPDX: SPDXExpression - /// A url where we can download the license's text - license_text: Verification | string -} - -export interface Verification { - https_url: string - license_checksum: string } // License name -> License text diff --git a/styles/src/themes/gruvbox/gruvbox-common.ts b/styles/src/themes/gruvbox/gruvbox-common.ts index 5958fe62aceeeba3c7c6b5191a8046eeecee5e93..b113ce68c6f94450671247c066402ed6102095cb 100644 --- a/styles/src/themes/gruvbox/gruvbox-common.ts +++ b/styles/src/themes/gruvbox/gruvbox-common.ts @@ -248,8 +248,6 @@ export const meta: Meta = { name, license: { SPDX: "MIT", // "MIT/X11" - license_text: - "Copyright \n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/ or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", }, author: "morhetz ", url: "https://github.com/morhetz/gruvbox", diff --git a/styles/src/themes/one/one-dark.ts b/styles/src/themes/one/one-dark.ts index 71062940a5cb8f4d9fc345b3abdcb3ab0d4d2ea6..1a88ddf7dce22e39e6712136b619e0ff2aefeccd 100644 --- a/styles/src/themes/one/one-dark.ts +++ b/styles/src/themes/one/one-dark.ts @@ -74,12 +74,6 @@ export const meta: Meta = { author: "simurai", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/atom/atom/master/packages/one-light-ui/LICENSE.md", - license_checksum: - "d5af8fc171f6f600c0ab4e7597dca398dda80dbe6821ce01cef78e859e7a00f8", - }, }, url: "https://github.com/atom/atom/tree/master/packages/one-dark-ui", } diff --git a/styles/src/themes/one/one-light.ts b/styles/src/themes/one/one-light.ts index 8ae42e8b1d161f291bc76dd462aae5e79b18e109..231ee3abb3d19cbc6f4bd9a0d4d150a578542db8 100644 --- a/styles/src/themes/one/one-light.ts +++ b/styles/src/themes/one/one-light.ts @@ -73,12 +73,6 @@ export const meta: Meta = { author: "simurai", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/atom/atom/master/packages/one-light-ui/LICENSE.md", - license_checksum: - "d5af8fc171f6f600c0ab4e7597dca398dda80dbe6821ce01cef78e859e7a00f8", - }, }, url: "https://github.com/atom/atom/tree/master/packages/one-light-ui", } diff --git a/styles/src/themes/rose-pine/rose-pine-dawn.ts b/styles/src/themes/rose-pine/rose-pine-dawn.ts index 48da855304781e58584368dfdf9f8ea088c25823..cf953872e1a4f7a15e1e0bd3f49356ca86a5e11b 100644 --- a/styles/src/themes/rose-pine/rose-pine-dawn.ts +++ b/styles/src/themes/rose-pine/rose-pine-dawn.ts @@ -34,12 +34,6 @@ export const meta: Meta = { author: "edunfelt", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/edunfelt/base16-rose-pine-scheme/main/LICENSE", - license_checksum: - "6ca1b9da8c78c8441c5aa43d024a4e4a7bf59d1ecca1480196e94fda0f91ee4a", - }, }, url: "https://github.com/edunfelt/base16-rose-pine-scheme", } diff --git a/styles/src/themes/rose-pine/rose-pine-moon.ts b/styles/src/themes/rose-pine/rose-pine-moon.ts index 2e13ca4b707d77747f58afbf28229bf9d381c2a9..85ac5fd73ef73bc8e36f228a50c4ab1cc3749169 100644 --- a/styles/src/themes/rose-pine/rose-pine-moon.ts +++ b/styles/src/themes/rose-pine/rose-pine-moon.ts @@ -34,12 +34,6 @@ export const meta: Meta = { author: "edunfelt", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/edunfelt/base16-rose-pine-scheme/main/LICENSE", - license_checksum: - "6ca1b9da8c78c8441c5aa43d024a4e4a7bf59d1ecca1480196e94fda0f91ee4a", - }, }, url: "https://github.com/edunfelt/base16-rose-pine-scheme", } diff --git a/styles/src/themes/rose-pine/rose-pine.ts b/styles/src/themes/rose-pine/rose-pine.ts index 33d7d533e6508fd4217dc02f3b864f3fbb5c05fe..fe2817be1363076b6e171adf1fbd0469d1f85cdb 100644 --- a/styles/src/themes/rose-pine/rose-pine.ts +++ b/styles/src/themes/rose-pine/rose-pine.ts @@ -32,12 +32,6 @@ export const meta: Meta = { author: "edunfelt", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/edunfelt/base16-rose-pine-scheme/main/LICENSE", - license_checksum: - "6ca1b9da8c78c8441c5aa43d024a4e4a7bf59d1ecca1480196e94fda0f91ee4a", - }, }, url: "https://github.com/edunfelt/base16-rose-pine-scheme", } diff --git a/styles/src/themes/sandcastle/sandcastle.ts b/styles/src/themes/sandcastle/sandcastle.ts index 0b265212562745717efef8871f23e69066673b59..2544b6399a66168446f96b3d71654cad48d9fcdc 100644 --- a/styles/src/themes/sandcastle/sandcastle.ts +++ b/styles/src/themes/sandcastle/sandcastle.ts @@ -32,12 +32,6 @@ export const meta: Meta = { author: "gessig", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/gessig/base16-sandcastle-scheme/master/LICENSE", - license_checksum: - "8399d44b4d935b60be9fee0a76d7cc9a817b4f3f11574c9d6d1e8fd57e72ffdc", - }, }, url: "https://github.com/gessig/base16-sandcastle-scheme", } diff --git a/styles/src/themes/solarized/solarized.ts b/styles/src/themes/solarized/solarized.ts index 13e3e34460bee124b1220f23556b6fd885a5d310..6c826fbee75c7a18633a782bad1e0106c9cf81d7 100644 --- a/styles/src/themes/solarized/solarized.ts +++ b/styles/src/themes/solarized/solarized.ts @@ -35,12 +35,6 @@ export const meta: Metadata = { author: "Ethan Schoonover", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/altercation/solarized/master/LICENSE", - license_checksum: - "494aefdabf86acce06bd63001ad8aedad4ee38da23509d3f917d95aa3368b9a6", - }, }, url: "https://github.com/altercation/solarized", } diff --git a/styles/src/themes/summercamp/summercamp.ts b/styles/src/themes/summercamp/summercamp.ts index 41e101af0208f676261dec19cf0a55d714bf0ce0..94c0072e4fddd5eda97851c4b0d8cc2908700303 100644 --- a/styles/src/themes/summercamp/summercamp.ts +++ b/styles/src/themes/summercamp/summercamp.ts @@ -34,11 +34,5 @@ export const meta: Meta = { url: "https://github.com/zoefiri/base16-sc", license: { SPDX: "MIT", - license_text: { - https_url: - "https://raw.githubusercontent.com/zoefiri/base16-sc/master/LICENSE", - license_checksum: - "fadcc834b7eaf2943800956600e8aeea4b495ecf6490f4c4b6c91556a90accaf", - }, }, } From 31516b7863b04d336253b62c08135b59dfb0056d Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 30 May 2023 14:46:27 -0400 Subject: [PATCH 11/53] `TextStyle::default()` ask system for known existing font family Rather than assuming a specific family exists, try a set of specific names and if they fail, just grab any old font that the system reports as existing Co-Authored-By: Nathan Sobo --- crates/gpui/src/font_cache.rs | 52 +++++++++++++++++++++------ crates/gpui/src/fonts.rs | 11 +++--- crates/gpui/src/platform.rs | 1 + crates/gpui/src/platform/mac/fonts.rs | 8 +++++ 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/crates/gpui/src/font_cache.rs b/crates/gpui/src/font_cache.rs index 4388ad4bcbd2bea66149c05258bfe39d5682af03..57dad48e341005ff267dabe2af41951b1d41d657 100644 --- a/crates/gpui/src/font_cache.rs +++ b/crates/gpui/src/font_cache.rs @@ -25,8 +25,9 @@ struct Family { pub struct FontCache(RwLock); pub struct FontCacheState { - fonts: Arc, + font_system: Arc, families: Vec, + default_family: Option, font_selections: HashMap>, metrics: HashMap, wrapper_pool: HashMap<(FontId, OrderedFloat), Vec>, @@ -42,8 +43,9 @@ unsafe impl Send for FontCache {} impl FontCache { pub fn new(fonts: Arc) -> Self { Self(RwLock::new(FontCacheState { - fonts, + font_system: fonts, families: Default::default(), + default_family: None, font_selections: Default::default(), metrics: Default::default(), wrapper_pool: Default::default(), @@ -73,14 +75,14 @@ impl FontCache { let mut state = RwLockUpgradableReadGuard::upgrade(state); - if let Ok(font_ids) = state.fonts.load_family(name, features) { + if let Ok(font_ids) = state.font_system.load_family(name, features) { if font_ids.is_empty() { continue; } let family_id = FamilyId(state.families.len()); for font_id in &font_ids { - if state.fonts.glyph_for_char(*font_id, 'm').is_none() { + if state.font_system.glyph_for_char(*font_id, 'm').is_none() { return Err(anyhow!("font must contain a glyph for the 'm' character")); } } @@ -99,6 +101,31 @@ impl FontCache { )) } + /// Returns an arbitrary font family that is available on the system. + pub fn known_existing_family(&self) -> FamilyId { + if let Some(family_id) = self.0.read().default_family { + return family_id; + } + + let default_family = self + .load_family( + &["Courier", "Helvetica", "Arial", "Verdana"], + &Default::default(), + ) + .unwrap_or_else(|_| { + let all_family_names = self.0.read().font_system.all_families(); + let all_family_names: Vec<_> = all_family_names + .iter() + .map(|string| string.as_str()) + .collect(); + self.load_family(&all_family_names, &Default::default()) + .expect("could not load any default font family") + }); + + self.0.write().default_family = Some(default_family); + default_family + } + pub fn default_font(&self, family_id: FamilyId) -> FontId { self.select_font(family_id, &Properties::default()).unwrap() } @@ -115,7 +142,7 @@ impl FontCache { let mut inner = RwLockUpgradableReadGuard::upgrade(inner); let family = &inner.families[family_id.0]; let font_id = inner - .fonts + .font_system .select_font(&family.font_ids, properties) .unwrap_or(family.font_ids[0]); @@ -137,7 +164,7 @@ impl FontCache { if let Some(metrics) = state.metrics.get(&font_id) { f(metrics) } else { - let metrics = state.fonts.font_metrics(font_id); + let metrics = state.font_system.font_metrics(font_id); let metric = f(&metrics); let mut state = RwLockUpgradableReadGuard::upgrade(state); state.metrics.insert(font_id, metrics); @@ -157,8 +184,11 @@ impl FontCache { let bounds; { let state = self.0.read(); - glyph_id = state.fonts.glyph_for_char(font_id, 'm').unwrap(); - bounds = state.fonts.typographic_bounds(font_id, glyph_id).unwrap(); + glyph_id = state.font_system.glyph_for_char(font_id, 'm').unwrap(); + bounds = state + .font_system + .typographic_bounds(font_id, glyph_id) + .unwrap(); } bounds.width() * self.em_scale(font_id, font_size) } @@ -168,8 +198,8 @@ impl FontCache { let advance; { let state = self.0.read(); - glyph_id = state.fonts.glyph_for_char(font_id, 'm').unwrap(); - advance = state.fonts.advance(font_id, glyph_id).unwrap(); + glyph_id = state.font_system.glyph_for_char(font_id, 'm').unwrap(); + advance = state.font_system.advance(font_id, glyph_id).unwrap(); } advance.x() * self.em_scale(font_id, font_size) } @@ -214,7 +244,7 @@ impl FontCache { .or_default(); let wrapper = wrappers .pop() - .unwrap_or_else(|| LineWrapper::new(font_id, font_size, state.fonts.clone())); + .unwrap_or_else(|| LineWrapper::new(font_id, font_size, state.font_system.clone())); LineWrapperHandle { wrapper: Some(wrapper), font_cache: self.clone(), diff --git a/crates/gpui/src/fonts.rs b/crates/gpui/src/fonts.rs index e0f037acb8fe1ec5b954b049930fbaac0e69313f..5e77593d05298b232f83b0f53d0c947e79501b67 100644 --- a/crates/gpui/src/fonts.rs +++ b/crates/gpui/src/fonts.rs @@ -295,13 +295,14 @@ impl Default for TextStyle { .as_ref() .expect("TextStyle::default can only be called within a call to with_font_cache"); - let font_family_name = Arc::from("Courier"); - let font_family_id = font_cache - .load_family(&[&font_family_name], &Default::default()) - .unwrap(); + let font_family_id = font_cache.known_existing_family(); let font_id = font_cache .select_font(font_family_id, &Default::default()) - .unwrap(); + .expect("did not have any font in system-provided family"); + let font_family_name = font_cache + .family_name(font_family_id) + .expect("we loaded this family from the font cache, so this should work"); + Self { color: Default::default(), font_family_name, diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 9b4fd7ca510a49a12b439da29a6df8002f9dada0..7fc02b054808786d412b45d532d72156c1ffefa5 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -343,6 +343,7 @@ pub enum RasterizationOptions { pub trait FontSystem: Send + Sync { fn add_fonts(&self, fonts: &[Arc>]) -> anyhow::Result<()>; + fn all_families(&self) -> Vec; fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result>; fn select_font( &self, diff --git a/crates/gpui/src/platform/mac/fonts.rs b/crates/gpui/src/platform/mac/fonts.rs index 96916698fcd126653ac9f9cd9748212f7ef41203..0414cb8a6ce051419fa94e1bddda7a1c23d6cc17 100644 --- a/crates/gpui/src/platform/mac/fonts.rs +++ b/crates/gpui/src/platform/mac/fonts.rs @@ -66,6 +66,14 @@ impl platform::FontSystem for FontSystem { self.0.write().add_fonts(fonts) } + fn all_families(&self) -> Vec { + self.0 + .read() + .system_source + .all_families() + .expect("core text should never return an error") + } + fn load_family(&self, name: &str, features: &Features) -> anyhow::Result> { self.0.write().load_family(name, features) } From 84f98f13c47933eb584ebbfcd66dbb16d11aaf63 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 11:52:14 -0700 Subject: [PATCH 12/53] Seperate open and zoom bits conceptually for new panels co-authored-by: max --- crates/workspace/src/dock.rs | 22 +++-- crates/workspace/src/workspace.rs | 140 +++++++++++++++++++++++++----- 2 files changed, 131 insertions(+), 31 deletions(-) diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 73d4f79399bd73bd52c9b0ecce04076e76b0407e..fbfcbad817e27d3c43fef36e571b80d9f7d6b4e4 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -180,7 +180,7 @@ impl Dock { } pub fn has_focus(&self, cx: &WindowContext) -> bool { - self.active_panel() + self.visible_panel() .map_or(false, |panel| panel.has_focus(cx)) } @@ -259,7 +259,7 @@ impl Dock { cx.focus(&panel); } } else if T::should_close_on_event(event) - && this.active_panel().map_or(false, |p| p.id() == panel.id()) + && this.visible_panel().map_or(false, |p| p.id() == panel.id()) { this.set_open(false, cx); } @@ -315,12 +315,16 @@ impl Dock { } } - pub fn active_panel(&self) -> Option<&Rc> { - let entry = self.active_entry()?; + pub fn visible_panel(&self) -> Option<&Rc> { + let entry = self.visible_entry()?; Some(&entry.panel) } - fn active_entry(&self) -> Option<&PanelEntry> { + pub fn active_panel(&self) -> Option<&Rc> { + Some(&self.panel_entries.get(self.active_panel_index)?.panel) + } + + fn visible_entry(&self) -> Option<&PanelEntry> { if self.is_open { self.panel_entries.get(self.active_panel_index) } else { @@ -329,7 +333,7 @@ impl Dock { } pub fn zoomed_panel(&self, cx: &WindowContext) -> Option> { - let entry = self.active_entry()?; + let entry = self.visible_entry()?; if entry.panel.is_zoomed(cx) { Some(entry.panel.clone()) } else { @@ -362,7 +366,7 @@ impl Dock { } pub fn render_placeholder(&self, cx: &WindowContext) -> AnyElement { - if let Some(active_entry) = self.active_entry() { + if let Some(active_entry) = self.visible_entry() { Empty::new() .into_any() .contained() @@ -399,7 +403,7 @@ impl View for Dock { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - if let Some(active_entry) = self.active_entry() { + if let Some(active_entry) = self.visible_entry() { let style = self.style(cx); ChildView::new(active_entry.panel.as_any(), cx) .contained() @@ -417,7 +421,7 @@ impl View for Dock { fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { if cx.is_self_focused() { - if let Some(active_entry) = self.active_entry() { + if let Some(active_entry) = self.visible_entry() { cx.focus(active_entry.panel.as_any()); } else { cx.focus_parent(); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8afad46ea108c0ab5ef1e6eac4ccf19e1f4661f1..6309b1d01f5965453afe06c8b45633f836e1ece9 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -901,7 +901,7 @@ impl Workspace { was_visible = dock.is_open() && dock - .active_panel() + .visible_panel() .map_or(false, |active_panel| active_panel.id() == panel.id()); dock.remove_panel(&panel, cx); }); @@ -1636,7 +1636,7 @@ impl Workspace { } else { dock.set_open(true, cx); dock.activate_panel(panel_index, cx); - dock.active_panel().cloned() + dock.visible_panel().cloned() } }); @@ -1658,17 +1658,27 @@ impl Workspace { pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { - let active_item = dock.update(cx, |dock, cx| { - dock.set_open(true, cx); + let focus_center = dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); - dock.active_panel().cloned() - }); - if let Some(active_item) = active_item { - if active_item.has_focus(cx) { - cx.focus_self(); + + if let Some(panel) = dock.active_panel().cloned() { + if panel.has_focus(cx) { + if panel.is_zoomed(cx) { + dock.set_open(false, cx); + } + true + } else { + dock.set_open(true, cx); + cx.focus(panel.as_any()); + false + } } else { - cx.focus(active_item.as_any()); + false } + }); + + if focus_center { + cx.focus_self(); } self.serialize_workspace(cx); @@ -2835,7 +2845,7 @@ impl Workspace { fn build_serialized_docks(this: &Workspace, cx: &AppContext) -> DockStructure { let left_dock = this.left_dock.read(cx); let left_visible = left_dock.is_open(); - let left_active_panel = left_dock.active_panel().and_then(|panel| { + let left_active_panel = left_dock.visible_panel().and_then(|panel| { Some( cx.view_ui_name(panel.as_any().window_id(), panel.id())? .to_string(), @@ -2844,7 +2854,7 @@ impl Workspace { let right_dock = this.right_dock.read(cx); let right_visible = right_dock.is_open(); - let right_active_panel = right_dock.active_panel().and_then(|panel| { + let right_active_panel = right_dock.visible_panel().and_then(|panel| { Some( cx.view_ui_name(panel.as_any().window_id(), panel.id())? .to_string(), @@ -2853,7 +2863,7 @@ impl Workspace { let bottom_dock = this.bottom_dock.read(cx); let bottom_visible = bottom_dock.is_open(); - let bottom_active_panel = bottom_dock.active_panel().and_then(|panel| { + let bottom_active_panel = bottom_dock.visible_panel().and_then(|panel| { Some( cx.view_ui_name(panel.as_any().window_id(), panel.id())? .to_string(), @@ -3035,7 +3045,7 @@ impl Workspace { DockPosition::Right => &self.right_dock, DockPosition::Bottom => &self.bottom_dock, }; - let active_panel = dock.read(cx).active_panel()?; + let active_panel = dock.read(cx).visible_panel()?; let element = if Some(active_panel.id()) == self.zoomed.as_ref().map(|zoomed| zoomed.id()) { dock.read(cx).render_placeholder(cx) } else { @@ -4171,6 +4181,82 @@ mod tests { }); } + #[gpui::test] + async fn test_toggle_panel_focus(cx: &mut gpui::TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.background()); + + let project = Project::test(fs, [], cx).await; + let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx)); + + let panel = workspace.update(cx, |workspace, cx| { + let panel = cx.add_view(|_| TestPanel::new(DockPosition::Right)); + workspace.add_panel(panel.clone(), cx); + + workspace + .right_dock() + .update(cx, |right_dock, cx| right_dock.set_open(true, cx)); + + panel + }); + + // Transfer focus from center to panel + workspace.update(cx, |workspace, cx| { + workspace.toggle_panel_focus::(cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(!panel.is_zoomed(cx)); + assert!(panel.has_focus(cx)); + }); + + // Transfer focus from panel to center + workspace.update(cx, |workspace, cx| { + workspace.toggle_panel_focus::(cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(!panel.is_zoomed(cx)); + assert!(!panel.has_focus(cx)); + }); + + // Focus and zoom panel + panel.update(cx, |panel, cx| { + cx.focus_self(); + panel.set_zoomed(true, cx) + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(panel.is_zoomed(cx)); + assert!(panel.has_focus(cx)); + }); + + // Transfer focus to the center closes the dock + workspace.update(cx, |workspace, cx| { + workspace.toggle_panel_focus::(cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(!workspace.right_dock().read(cx).is_open()); + assert!(panel.is_zoomed(cx)); + assert!(!panel.has_focus(cx)); + }); + + // Transfering focus back to the panel keeps it zoomed + workspace.update(cx, |workspace, cx| { + workspace.toggle_panel_focus::(cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(panel.is_zoomed(cx)); + assert!(panel.has_focus(cx)); + }); + } + #[gpui::test] async fn test_panels(cx: &mut gpui::TestAppContext) { init_test(cx); @@ -4194,7 +4280,7 @@ mod tests { let left_dock = workspace.left_dock(); assert_eq!( - left_dock.read(cx).active_panel().unwrap().id(), + left_dock.read(cx).visible_panel().unwrap().id(), panel_1.id() ); assert_eq!( @@ -4204,7 +4290,12 @@ mod tests { left_dock.update(cx, |left_dock, cx| left_dock.resize_active_panel(1337., cx)); assert_eq!( - workspace.right_dock().read(cx).active_panel().unwrap().id(), + workspace + .right_dock() + .read(cx) + .visible_panel() + .unwrap() + .id(), panel_2.id() ); @@ -4220,10 +4311,10 @@ mod tests { // Since panel_1 was visible on the left, it should now be visible now that it's been moved to the right. // Since it was the only panel on the left, the left dock should now be closed. assert!(!workspace.left_dock().read(cx).is_open()); - assert!(workspace.left_dock().read(cx).active_panel().is_none()); + assert!(workspace.left_dock().read(cx).visible_panel().is_none()); let right_dock = workspace.right_dock(); assert_eq!( - right_dock.read(cx).active_panel().unwrap().id(), + right_dock.read(cx).visible_panel().unwrap().id(), panel_1.id() ); assert_eq!(right_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); @@ -4238,7 +4329,12 @@ mod tests { // And the right dock is unaffected in it's displaying of panel_1 assert!(workspace.right_dock().read(cx).is_open()); assert_eq!( - workspace.right_dock().read(cx).active_panel().unwrap().id(), + workspace + .right_dock() + .read(cx) + .visible_panel() + .unwrap() + .id(), panel_1.id() ); }); @@ -4253,7 +4349,7 @@ mod tests { let left_dock = workspace.left_dock(); assert!(left_dock.read(cx).is_open()); assert_eq!( - left_dock.read(cx).active_panel().unwrap().id(), + left_dock.read(cx).visible_panel().unwrap().id(), panel_1.id() ); assert_eq!(left_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); @@ -4287,7 +4383,7 @@ mod tests { let left_dock = workspace.left_dock(); assert!(left_dock.read(cx).is_open()); assert_eq!( - left_dock.read(cx).active_panel().unwrap().id(), + left_dock.read(cx).visible_panel().unwrap().id(), panel_1.id() ); assert!(panel_1.is_focused(cx)); @@ -4301,7 +4397,7 @@ mod tests { let left_dock = workspace.left_dock(); assert!(left_dock.read(cx).is_open()); assert_eq!( - left_dock.read(cx).active_panel().unwrap().id(), + left_dock.read(cx).visible_panel().unwrap().id(), panel_1.id() ); }); From 1a23fe91b47e78705afe26cf0e47826dc6ffec6f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 12:00:15 -0700 Subject: [PATCH 13/53] WIP: Remove focus side effects from toggle dock commands co-authored-by: max --- assets/keymaps/default.json | 27 ++-------------- crates/welcome/src/welcome.rs | 2 +- crates/workspace/src/workspace.rs | 51 ++++++------------------------- crates/zed/src/menus.rs | 6 ++-- crates/zed/src/zed.rs | 2 +- 5 files changed, 18 insertions(+), 70 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 35182dfaa66763cb2ec885ba762b0d9f9fd41b31..7e1a8429bfd695a75b423b5e2a175d474ad3d49b 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -373,30 +373,9 @@ "workspace::ActivatePane", 8 ], - "cmd-b": [ - "workspace::ToggleLeftDock", - { "focus": true } - ], - "cmd-shift-b": [ - "workspace::ToggleLeftDock", - { "focus": false } - ], - "cmd-r": [ - "workspace::ToggleRightDock", - { "focus": true } - ], - "cmd-shift-r": [ - "workspace::ToggleRightDock", - { "focus": false } - ], - "cmd-j": [ - "workspace::ToggleBottomDock", - { "focus": true } - ], - "cmd-shift-j": [ - "workspace::ToggleBottomDock", - { "focus": false } - ], + "cmd-b": "workspace::ToggleLeftDock", + "cmd-r": "workspace::ToggleRightDock", + "cmd-j": "workspace::ToggleBottomDock", "cmd-shift-f": "workspace::NewSearch", "cmd-k cmd-t": "theme_selector::Toggle", "cmd-k cmd-s": "zed::OpenKeymap", diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index cef6f53a6ecf50b376b93b460fbba82c96eb51de..b7460c4c461f6a707bf77ee193145770418eeb50 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -32,7 +32,7 @@ pub fn init(cx: &mut AppContext) { pub fn show_welcome_experience(app_state: &Arc, cx: &mut AppContext) { open_new(&app_state, cx, |workspace, cx| { - workspace.toggle_dock(DockPosition::Left, false, cx); + workspace.toggle_dock(DockPosition::Left, cx); let welcome_page = cx.add_view(|cx| WelcomePage::new(workspace, cx)); workspace.add_item_to_center(Box::new(welcome_page.clone()), cx); cx.focus(&welcome_page); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 6309b1d01f5965453afe06c8b45633f836e1ece9..1a14f39fb9d598bd176e16dae19d87e793354829 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -103,24 +103,6 @@ pub trait Modal: View { #[derive(Clone, PartialEq)] pub struct RemoveWorktreeFromProject(pub WorktreeId); -#[derive(Copy, Clone, Default, Deserialize, PartialEq)] -pub struct ToggleLeftDock { - #[serde(default = "default_true")] - pub focus: bool, -} - -#[derive(Copy, Clone, Default, Deserialize, PartialEq)] -pub struct ToggleBottomDock { - #[serde(default = "default_true")] - pub focus: bool, -} - -#[derive(Copy, Clone, Default, Deserialize, PartialEq)] -pub struct ToggleRightDock { - #[serde(default = "default_true")] - pub focus: bool, -} - actions!( workspace, [ @@ -143,16 +125,14 @@ actions!( Restart, Welcome, ToggleZoom, + ToggleLeftDock, + ToggleRightDock, + ToggleBottomDock, ] ); actions!(zed, [OpenSettings]); -impl_actions!( - workspace, - [ToggleLeftDock, ToggleBottomDock, ToggleRightDock] -); - #[derive(Clone, PartialEq)] pub struct OpenPaths { pub paths: Vec, @@ -268,14 +248,14 @@ pub fn init(app_state: Arc, cx: &mut AppContext) { cx.add_action(|workspace: &mut Workspace, _: &ActivateNextPane, cx| { workspace.activate_next_pane(cx) }); - cx.add_action(|workspace: &mut Workspace, action: &ToggleLeftDock, cx| { - workspace.toggle_dock(DockPosition::Left, action.focus, cx); + cx.add_action(|workspace: &mut Workspace, _: &ToggleLeftDock, cx| { + workspace.toggle_dock(DockPosition::Left, cx); }); - cx.add_action(|workspace: &mut Workspace, action: &ToggleRightDock, cx| { - workspace.toggle_dock(DockPosition::Right, action.focus, cx); + cx.add_action(|workspace: &mut Workspace, _: &ToggleRightDock, cx| { + workspace.toggle_dock(DockPosition::Right, cx); }); - cx.add_action(|workspace: &mut Workspace, action: &ToggleBottomDock, cx| { - workspace.toggle_dock(DockPosition::Bottom, action.focus, cx); + cx.add_action(|workspace: &mut Workspace, _: &ToggleBottomDock, cx| { + workspace.toggle_dock(DockPosition::Bottom, cx); }); cx.add_action(Workspace::activate_pane_at_index); cx.add_action(|workspace: &mut Workspace, _: &ReopenClosedItem, cx| { @@ -1596,7 +1576,6 @@ impl Workspace { pub fn toggle_dock( &mut self, dock_side: DockPosition, - focus: bool, cx: &mut ViewContext, ) { let dock = match dock_side { @@ -1608,12 +1587,6 @@ impl Workspace { let open = !dock.is_open(); dock.set_open(open, cx); }); - - if dock.read(cx).is_open() && focus { - cx.focus(dock); - } else { - cx.focus_self(); - } cx.notify(); self.serialize_workspace(cx); } @@ -3599,10 +3572,6 @@ fn parse_pixel_position_env_var(value: &str) -> Option { Some(vec2f(width as f32, height as f32)) } -fn default_true() -> bool { - true -} - #[cfg(test)] mod tests { use super::*; @@ -4187,7 +4156,7 @@ mod tests { let fs = FakeFs::new(cx.background()); let project = Project::test(fs, [], cx).await; - let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx)); + let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx)); let panel = workspace.update(cx, |workspace, cx| { let panel = cx.add_view(|_| TestPanel::new(DockPosition::Right)); diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index adc1f81589fbe7cf4e062a225fb1ac439cd60966..ecfd567e78d8e739b19484e80ee9d2749cb9eb98 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -91,15 +91,15 @@ pub fn menus() -> Vec> { MenuItem::separator(), MenuItem::action( "Toggle Left Dock", - workspace::ToggleLeftDock { focus: false }, + workspace::ToggleLeftDock, ), MenuItem::action( "Toggle Right Dock", - workspace::ToggleRightDock { focus: false }, + workspace::ToggleRightDock, ), MenuItem::action( "Toggle Bottom Dock", - workspace::ToggleBottomDock { focus: false }, + workspace::ToggleBottomDock, ), MenuItem::submenu(Menu { name: "Editor Layout", diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index c22967686ac2f76e523db16182320ac59290100d..6dbddae2ada970ee754c20c2aa735c3f46c86d91 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -354,7 +354,7 @@ pub fn initialize_workspace( .map_or(false, |entry| entry.is_dir()) }) { - workspace.toggle_dock(project_panel_position, false, cx); + workspace.toggle_dock(project_panel_position, cx); } workspace.add_panel(terminal_panel, cx) From 501f9ab2c6dca2bc90c1466a3f95d10c86d13fb4 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Tue, 30 May 2023 15:06:35 -0400 Subject: [PATCH 14/53] Scrape email from feedback editor --- Cargo.lock | 1 + crates/feedback/Cargo.toml | 1 + crates/feedback/src/feedback_editor.rs | 12 ++++++++++++ crates/feedback/src/feedback_info_text.rs | 4 ++-- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3537056373c320c8998a0fe283801767f0bcbdbc..3751b34d3156da64fc0efea74e707fc9222bb324 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2236,6 +2236,7 @@ dependencies = [ "log", "postage", "project", + "regex", "search", "serde", "serde_derive", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index cd35afbda8ce36e7890f09fd6c02dceeeda51b4b..07b6ad790c8dcd553b8edb193f7d37179e212634 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -16,6 +16,7 @@ editor = { path = "../editor" } language = { path = "../language" } gpui = { path = "../gpui" } project = { path = "../project" } +regex.workspace = true search = { path = "../search" } settings = { path = "../settings" } theme = { path = "../theme" } diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index d5d20b069ac108c70208b0230fe53b394143ffb2..5a4f912e3a063068adba31d787a21d1df42368b2 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -14,6 +14,7 @@ use isahc::Request; use language::Buffer; use postage::prelude::Stream; use project::Project; +use regex::Regex; use serde::Serialize; use smallvec::SmallVec; use std::{ @@ -46,6 +47,7 @@ pub fn init(cx: &mut AppContext) { #[derive(Serialize)] struct FeedbackRequestBody<'a> { feedback_text: &'a str, + email: Option, metrics_id: Option>, installation_id: Option>, system_specs: SystemSpecs, @@ -157,8 +159,18 @@ impl FeedbackEditor { let is_staff = telemetry.is_staff(); let http_client = zed_client.http_client(); + let re = Regex::new(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b").unwrap(); + + let emails: Vec<&str> = re + .captures_iter(feedback_text) + .map(|capture| capture.get(0).unwrap().as_str()) + .collect(); + + let email = emails.first().map(|e| e.to_string()); + let request = FeedbackRequestBody { feedback_text: &feedback_text, + email, metrics_id, installation_id, system_specs, diff --git a/crates/feedback/src/feedback_info_text.rs b/crates/feedback/src/feedback_info_text.rs index 5852cd9a6184449b08eb7844bf7ac6d11b3ca6ee..6c55b7a7139076b4b34410e063628d71f38765b2 100644 --- a/crates/feedback/src/feedback_info_text.rs +++ b/crates/feedback/src/feedback_info_text.rs @@ -34,7 +34,7 @@ impl View for FeedbackInfoText { Flex::row() .with_child( Text::new( - "We read whatever you submit here. For issues and discussions, visit the ", + "Share your feedback. Include your email for replies. For issues and discussions, visit the ", theme.feedback.info_text_default.text.clone(), ) .with_soft_wrap(false) @@ -60,7 +60,7 @@ impl View for FeedbackInfoText { }), ) .with_child( - Text::new(" on GitHub.", theme.feedback.info_text_default.text.clone()) + Text::new(".", theme.feedback.info_text_default.text.clone()) .with_soft_wrap(false) .aligned(), ) From efcf78cbe9512f04444e5546544952af93f21c7a Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Tue, 30 May 2023 15:15:20 -0400 Subject: [PATCH 15/53] Update pull_request_template.md --- .github/pull_request_template.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 67a7ed31c9b5a4cfbf3ab6881c627b1a9db126c5..2cd2050013f7639ff3d3a4ea10379584f0e5f387 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,12 +2,11 @@ Release Notes: -Use `N/A` in this section if this item should be skipped in the release notes. +- N/A -Add release note lines here: +or -* (Added|Fixed|Improved) ... ([#](https://github.com/zed-industries/community/issues/)). -* ... +- (Added|Fixed|Improved) ... ([#](https://github.com/zed-industries/community/issues/)). If the release notes are only intended for a specific release channel only, add `(-only)` to the end of the release note line. These will be removed by the person making the release. From 9c9af5ed94291ad1e019c671552abdc6b2c193fb Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 12:32:00 -0700 Subject: [PATCH 16/53] Remove focus side effects from toggle dock commands co-authored-by: max --- crates/workspace/src/dock.rs | 7 +-- crates/workspace/src/workspace.rs | 77 +++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index fbfcbad817e27d3c43fef36e571b80d9f7d6b4e4..13bebc567345c770d2aca353b9f59d0426bdc1e8 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -201,7 +201,7 @@ impl Dock { self.active_panel_index } - pub fn set_open(&mut self, open: bool, cx: &mut ViewContext) { + pub(crate) fn set_open(&mut self, open: bool, cx: &mut ViewContext) { if open != self.is_open { self.is_open = open; if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { @@ -212,11 +212,6 @@ impl Dock { } } - pub fn toggle_open(&mut self, cx: &mut ViewContext) { - self.set_open(!self.is_open, cx); - cx.notify(); - } - pub fn set_panel_zoomed( &mut self, panel: &AnyViewHandle, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1a14f39fb9d598bd176e16dae19d87e793354829..657285388aff3ec583522b332432d88e38140efb 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1583,10 +1583,27 @@ impl Workspace { DockPosition::Bottom => &self.bottom_dock, DockPosition::Right => &self.right_dock, }; - dock.update(cx, |dock, cx| { - let open = !dock.is_open(); - dock.set_open(open, cx); + let focus_center = dock.update(cx, |dock, cx| { + let was_open = dock.is_open(); + dock.set_open(!was_open, cx); + + if let Some(active_panel) = dock.active_panel() { + if was_open { + if active_panel.has_focus(cx) { + return true; + } + } else if active_panel.is_zoomed(cx) { + cx.focus(active_panel.as_any()); + } + } + + false }); + + if focus_center { + cx.focus_self(); + } + cx.notify(); self.serialize_workspace(cx); } @@ -1639,15 +1656,13 @@ impl Workspace { if panel.is_zoomed(cx) { dock.set_open(false, cx); } - true + return true } else { dock.set_open(true, cx); cx.focus(panel.as_any()); - false } - } else { - false } + false }); if focus_center { @@ -4151,7 +4166,7 @@ mod tests { } #[gpui::test] - async fn test_toggle_panel_focus(cx: &mut gpui::TestAppContext) { + async fn test_toggle_docks_and_panels(cx: &mut gpui::TestAppContext) { init_test(cx); let fs = FakeFs::new(cx.background()); @@ -4191,6 +4206,28 @@ mod tests { assert!(!panel.has_focus(cx)); }); + // Close the dock + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(!workspace.right_dock().read(cx).is_open()); + assert!(!panel.is_zoomed(cx)); + assert!(!panel.has_focus(cx)); + }); + + // Open the dock + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx); + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(!panel.is_zoomed(cx)); + assert!(!panel.has_focus(cx)); + }); + // Focus and zoom panel panel.update(cx, |panel, cx| { cx.focus_self(); @@ -4224,6 +4261,30 @@ mod tests { assert!(panel.is_zoomed(cx)); assert!(panel.has_focus(cx)); }); + + // Close the dock while it is zoomed + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx) + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(!workspace.right_dock().read(cx).is_open()); + assert!(panel.is_zoomed(cx)); + assert!(workspace.zoomed.is_none()); + assert!(!panel.has_focus(cx)); + }); + + // Opening the dock, when it's zoomed, retains focus + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx) + }); + + workspace.read_with(cx, |workspace, cx| { + assert!(workspace.right_dock().read(cx).is_open()); + assert!(panel.is_zoomed(cx)); + assert!(workspace.zoomed.is_some()); + assert!(panel.has_focus(cx)); + }); } #[gpui::test] From 506580438803a2ef050c40351a0841596f6b4952 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 14:55:49 -0700 Subject: [PATCH 17/53] WIP: iron out bugs in interaction between toggle and toggle focus key bindings co-authored-by: max --- crates/workspace/src/workspace.rs | 143 +++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 21 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 657285388aff3ec583522b332432d88e38140efb..53240a9a73dde7ecd080f9e77bd33102413d17cb 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -478,6 +478,7 @@ pub struct Workspace { remote_entity_subscription: Option, modal: Option, zoomed: Option, + zoomed_position: Option, center: PaneGroup, left_dock: ViewHandle, bottom_dock: ViewHandle, @@ -683,6 +684,7 @@ impl Workspace { weak_self: weak_handle.clone(), modal: None, zoomed: None, + zoomed_position: None, center: PaneGroup::new(center_pane.clone()), panes: vec![center_pane.clone()], panes_by_item: Default::default(), @@ -885,6 +887,11 @@ impl Workspace { .map_or(false, |active_panel| active_panel.id() == panel.id()); dock.remove_panel(&panel, cx); }); + + if panel.is_zoomed(cx) { + this.zoomed_position = Some(new_position); + } + dock = match panel.read(cx).position(cx) { DockPosition::Left => &this.left_dock, DockPosition::Bottom => &this.bottom_dock, @@ -903,14 +910,17 @@ impl Workspace { dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx)); if panel.has_focus(cx) { this.zoomed = Some(panel.downgrade().into_any()); + this.zoomed_position = Some(panel.read(cx).position(cx)); } } else if T::should_zoom_out_on_event(event) { this.zoom_out(cx); } else if T::is_focus_event(event) { if panel.is_zoomed(cx) { this.zoomed = Some(panel.downgrade().into_any()); + this.zoomed_position = Some(panel.read(cx).position(cx)); } else { this.zoomed = None; + this.zoomed_position = None; } cx.notify(); } @@ -1573,33 +1583,36 @@ impl Workspace { } } - pub fn toggle_dock( - &mut self, - dock_side: DockPosition, - cx: &mut ViewContext, - ) { + pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext) { let dock = match dock_side { DockPosition::Left => &self.left_dock, DockPosition::Bottom => &self.bottom_dock, DockPosition::Right => &self.right_dock, }; - let focus_center = dock.update(cx, |dock, cx| { - let was_open = dock.is_open(); - dock.set_open(!was_open, cx); + let mut focus_center = false; + let mut zoom_out = false; + dock.update(cx, |dock, cx| { + let other_is_zoomed = self.zoomed.is_some() && self.zoomed_position != Some(dock_side); + let was_visible = dock.is_open() && !other_is_zoomed; + dock.set_open(!was_visible, cx); if let Some(active_panel) = dock.active_panel() { - if was_open { + if was_visible { if active_panel.has_focus(cx) { - return true; + focus_center = true; + } + } else { + if active_panel.is_zoomed(cx) { + cx.focus(active_panel.as_any()); } - } else if active_panel.is_zoomed(cx) { - cx.focus(active_panel.as_any()); + zoom_out = true; } } - - false }); + if zoom_out { + self.zoom_out_everything_except(dock_side, cx); + } if focus_center { cx.focus_self(); } @@ -1646,9 +1659,24 @@ impl Workspace { } pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { - for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { + for (dock, position) in [ + self.left_dock.clone(), + self.bottom_dock.clone(), + self.right_dock.clone(), + ] + .into_iter() + .zip( + [ + DockPosition::Left, + DockPosition::Bottom, + DockPosition::Right, + ] + .into_iter(), + ) { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { - let focus_center = dock.update(cx, |dock, cx| { + let mut focus_center = false; + let mut zoom_out = false; + dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); if let Some(panel) = dock.active_panel().cloned() { @@ -1656,15 +1684,18 @@ impl Workspace { if panel.is_zoomed(cx) { dock.set_open(false, cx); } - return true + focus_center = true; } else { dock.set_open(true, cx); cx.focus(panel.as_any()); + zoom_out = true; } } - false }); + if zoom_out { + self.zoom_out_everything_except(position, cx); + } if focus_center { cx.focus_self(); } @@ -1685,6 +1716,36 @@ impl Workspace { self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); self.zoomed = None; + self.zoomed_position = None; + + cx.notify(); + } + + fn zoom_out_everything_except( + &mut self, + except_position: DockPosition, + cx: &mut ViewContext, + ) { + for pane in &self.panes { + pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + } + + if except_position != DockPosition::Left { + self.left_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if except_position != DockPosition::Bottom { + self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if except_position != DockPosition::Right { + self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if self.zoomed_position != Some(except_position) { + self.zoomed = None; + self.zoomed_position = None; + } cx.notify(); } @@ -1901,6 +1962,7 @@ impl Workspace { } else { self.zoomed = None; } + self.zoomed_position = None; self.update_followers( proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView { @@ -1960,6 +2022,7 @@ impl Workspace { pane.update(cx, |pane, cx| pane.set_zoomed(true, cx)); if pane.read(cx).has_focus() { self.zoomed = Some(pane.downgrade().into_any()); + self.zoomed_position = None; } cx.notify(); } @@ -3234,13 +3297,38 @@ impl View for Workspace { .with_children(self.zoomed.as_ref().and_then(|zoomed| { enum ZoomBackground {} let zoomed = zoomed.upgrade(cx)?; + + let mut background_style = + theme.workspace.zoomed_background; + match self.zoomed_position { + Some(DockPosition::Left) => { + background_style.padding.left = 0.; + background_style.padding.top = 0.; + background_style.padding.bottom = 0.; + background_style.padding.right *= 1.; + } + Some(DockPosition::Right) => { + background_style.padding.right = 0.; + background_style.padding.top = 0.; + background_style.padding.bottom = 0.; + background_style.padding.left *= 1.; + } + Some(DockPosition::Bottom) => { + background_style.padding.left = 0.; + background_style.padding.right = 0.; + background_style.padding.bottom = 0.; + background_style.padding.top *= 1.; + } + None => {} + } + Some( ChildView::new(&zoomed, cx) .contained() .with_style(theme.workspace.zoomed_foreground) .aligned() .contained() - .with_style(theme.workspace.zoomed_background) + .with_style(background_style) .mouse::(0) .capture_all() .on_down( @@ -4436,6 +4524,14 @@ mod tests { panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn)); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Left)); + }); + + // Move panel to another dock while it is zoomed + panel_1.update(cx, |panel, cx| panel.set_position(DockPosition::Right, cx)); + workspace.read_with(cx, |workspace, _| { + assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // If focus is transferred to another view that's not a panel or another pane, we still show @@ -4444,12 +4540,14 @@ mod tests { focus_receiver.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // If focus is transferred elsewhere in the workspace, the panel is no longer zoomed. workspace.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // If focus is transferred again to another view that's not a panel or a pane, we won't @@ -4457,18 +4555,21 @@ mod tests { focus_receiver.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // When focus is transferred back to the panel, it is zoomed again. panel_1.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // Emitting a ZoomOut event unzooms the panel. panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut)); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // Emit closed event on panel 1, which is active @@ -4476,8 +4577,8 @@ mod tests { // Now the left dock is closed, because panel_1 was the active panel workspace.read_with(cx, |workspace, cx| { - let left_dock = workspace.left_dock(); - assert!(!left_dock.read(cx).is_open()); + let right_dock = workspace.right_dock(); + assert!(!right_dock.read(cx).is_open()); }); } From 5e4a9abd0907eff8412c8a65df0d6f89bd16eb59 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 15:17:42 -0700 Subject: [PATCH 18/53] Fix bug in panel button dispatch --- crates/workspace/src/dock.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 13bebc567345c770d2aca353b9f59d0426bdc1e8..2f198f62f4714b2948e2c5c89aaf6e4120446371 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -503,13 +503,21 @@ impl View for PanelButtons { }) .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, { + let tooltip_action = + tooltip_action.as_ref().map(|action| action.boxed_clone()); move |_, this, cx| { - if let Some(workspace) = this.workspace.upgrade(cx) { - cx.window_context().defer(move |cx| { - workspace.update(cx, |workspace, cx| { - workspace.toggle_panel(dock_position, panel_ix, cx) - }); - }); + if let Some(tooltip_action) = &tooltip_action { + let window_id = cx.window_id(); + let view_id = this.workspace.id(); + let tooltip_action = tooltip_action.boxed_clone(); + cx.spawn(|_, mut cx| async move { + cx.dispatch_action( + window_id, + view_id, + &*tooltip_action, + ) + .ok(); + }).detach(); } } }) From e80ab5f096bae73e6522d120370089d8cb0104be Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 15:40:30 -0700 Subject: [PATCH 19/53] Fix focus bug with new docks co-authored-by: max --- crates/workspace/src/pane.rs | 15 ++++----------- crates/workspace/src/workspace.rs | 6 +----- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 2919bb7cd447d1fe50e2afe972c31217d23e9e00..e722b3be6ac81bc7c8b6deb0bc5187bd3fdd1f61 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -306,15 +306,6 @@ impl Pane { &self.workspace } - pub fn is_active(&self) -> bool { - self.is_active - } - - pub fn set_active(&mut self, is_active: bool, cx: &mut ViewContext) { - self.is_active = is_active; - cx.notify(); - } - pub fn has_focus(&self) -> bool { self.has_focus } @@ -1129,7 +1120,7 @@ impl Pane { None }; - let pane_active = self.is_active; + let pane_active = self.has_focus; enum Tabs {} let mut row = Flex::row().scrollable::(1, autoscroll, cx); @@ -1508,7 +1499,7 @@ impl View for Pane { let mut tab_row = Flex::row() .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs")); - if self.is_active { + if self.has_focus { let render_tab_bar_buttons = self.render_tab_bar_buttons.clone(); tab_row.add_child( (render_tab_bar_buttons)(self, cx) @@ -1599,6 +1590,7 @@ impl View for Pane { if !self.has_focus { self.has_focus = true; cx.emit(Event::Focus); + cx.notify(); } self.toolbar.update(cx, |toolbar, cx| { @@ -1633,6 +1625,7 @@ impl View for Pane { self.toolbar.update(cx, |toolbar, cx| { toolbar.pane_focus_update(false, cx); }); + cx.notify(); } fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 53240a9a73dde7ecd080f9e77bd33102413d17cb..e51a0bf812caf337f0bda102da135629e7d93797 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1945,11 +1945,7 @@ impl Workspace { fn handle_pane_focused(&mut self, pane: ViewHandle, cx: &mut ViewContext) { if self.active_pane != pane { - self.active_pane - .update(cx, |pane, cx| pane.set_active(false, cx)); self.active_pane = pane.clone(); - self.active_pane - .update(cx, |pane, cx| pane.set_active(true, cx)); self.status_bar.update(cx, |status_bar, cx| { status_bar.set_active_pane(&self.active_pane, cx); }); @@ -2868,7 +2864,7 @@ impl Workspace { }) }) .collect::>(), - pane.is_active(), + pane.has_focus(), ) }; From 9c707eff27c61136ff995d1462d3cbdadca9822b Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 16:10:07 -0700 Subject: [PATCH 20/53] Rework new terminal actions --- crates/terminal_view/src/terminal_panel.rs | 19 +++++-- crates/terminal_view/src/terminal_view.rs | 8 +-- crates/workspace/src/pane.rs | 6 +- crates/workspace/src/workspace.rs | 64 +++++++--------------- 4 files changed, 41 insertions(+), 56 deletions(-) diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index d34a261bfecf32bcdedbaaffa8dfa49e4dd0d003..c2f7eb36e4f6fd725a6f67572a1e1ba10acbdb1f 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -22,7 +22,7 @@ const TERMINAL_PANEL_KEY: &'static str = "TerminalPanel"; actions!(terminal_panel, [ToggleFocus]); pub fn init(cx: &mut AppContext) { - cx.add_action(TerminalPanel::add_terminal); + cx.add_action(TerminalPanel::new_terminal); } pub enum Event { @@ -80,7 +80,7 @@ impl TerminalPanel { cx.window_context().defer(move |cx| { if let Some(this) = this.upgrade(cx) { this.update(cx, |this, cx| { - this.add_terminal(&Default::default(), cx); + this.add_terminal(cx); }); } }) @@ -220,7 +220,18 @@ impl TerminalPanel { } } - fn add_terminal(&mut self, _: &workspace::NewTerminal, cx: &mut ViewContext) { + + fn new_terminal(workspace: &mut Workspace, _: &workspace::NewTerminal, cx: &mut ViewContext) { + let Some(this) = workspace.focus_panel::(cx) else { + return; + }; + + this.update(cx, |this, cx| { + this.add_terminal(cx) + }) + } + + fn add_terminal(&mut self, cx: &mut ViewContext) { let workspace = self.workspace.clone(); cx.spawn(|this, mut cx| async move { let pane = this.read_with(&cx, |this, _| this.pane.clone())?; @@ -363,7 +374,7 @@ impl Panel for TerminalPanel { fn set_active(&mut self, active: bool, cx: &mut ViewContext) { if active && self.pane.read(cx).items_len() == 0 { - self.add_terminal(&Default::default(), cx) + self.add_terminal(cx) } } diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 767e3bf4dbb3847064c7a32d217596840457c080..633b83afb8bbb0cc7019e02ad089856939585732 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -38,7 +38,7 @@ use workspace::{ notifications::NotifyResultExt, pane, register_deserializable_item, searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle}, - Pane, ToolbarItemLocation, Workspace, WorkspaceId, + Pane, ToolbarItemLocation, Workspace, WorkspaceId, NewCenterTerminal, }; pub use terminal::TerminalSettings; @@ -66,10 +66,10 @@ pub fn init(cx: &mut AppContext) { terminal_panel::init(cx); terminal::init(cx); - cx.add_action(TerminalView::deploy); - register_deserializable_item::(cx); + cx.add_action(TerminalView::deploy); + //Useful terminal views cx.add_action(TerminalView::send_text); cx.add_action(TerminalView::send_keystroke); @@ -101,7 +101,7 @@ impl TerminalView { ///Create a new Terminal in the current working directory or the user's home directory pub fn deploy( workspace: &mut Workspace, - _: &workspace::NewTerminal, + _: &NewCenterTerminal, cx: &mut ViewContext, ) { let strategy = settings::get::(cx); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index e722b3be6ac81bc7c8b6deb0bc5187bd3fdd1f61..23d3d6f37813135af8bc4975650ae47f348f9b3a 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -3,7 +3,7 @@ mod dragged_item_receiver; use super::{ItemHandle, SplitDirection}; use crate::{ item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewFile, NewSearch, NewTerminal, - ToggleZoom, Workspace, WorkspaceSettings, + ToggleZoom, Workspace, WorkspaceSettings, NewCenterTerminal, }; use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; @@ -131,7 +131,6 @@ pub enum Event { pub struct Pane { items: Vec>, activation_history: Vec, - is_active: bool, zoomed: bool, active_item_index: usize, last_focused_view_by_item: HashMap, @@ -238,7 +237,6 @@ impl Pane { Self { items: Vec::new(), activation_history: Vec::new(), - is_active: true, zoomed: false, active_item_index: 0, last_focused_view_by_item: Default::default(), @@ -996,7 +994,7 @@ impl Pane { AnchorCorner::TopRight, vec![ ContextMenuItem::action("New File", NewFile), - ContextMenuItem::action("New Terminal", NewTerminal), + ContextMenuItem::action("New Terminal", NewCenterTerminal), ContextMenuItem::action("New Search", NewSearch), ], cx, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e51a0bf812caf337f0bda102da135629e7d93797..9285e911ef15001964b87796230ee500748cd7f5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -55,7 +55,7 @@ use std::{ path::{Path, PathBuf}, str, sync::{atomic::AtomicUsize, Arc}, - time::Duration, + time::Duration, rc::Rc, }; use crate::{ @@ -119,6 +119,7 @@ actions!( ActivateNextPane, FollowNextCollaborator, NewTerminal, + NewCenterTerminal, ToggleTerminalFocus, NewSearch, Feedback, @@ -1621,44 +1622,15 @@ impl Workspace { self.serialize_workspace(cx); } - pub fn toggle_panel( - &mut self, - position: DockPosition, - panel_index: usize, - cx: &mut ViewContext, - ) { - let dock = match position { - DockPosition::Left => &mut self.left_dock, - DockPosition::Bottom => &mut self.bottom_dock, - DockPosition::Right => &mut self.right_dock, - }; - let active_item = dock.update(cx, move |dock, cx| { - if dock.is_open() && dock.active_panel_index() == panel_index { - dock.set_open(false, cx); - None - } else { - dock.set_open(true, cx); - dock.activate_panel(panel_index, cx); - dock.visible_panel().cloned() - } - }); - - if let Some(active_item) = active_item { - if active_item.has_focus(cx) { - cx.focus_self(); - } else { - cx.focus(active_item.as_any()); - } - } else { - cx.focus_self(); - } - - self.serialize_workspace(cx); - - cx.notify(); + pub fn focus_panel(&mut self, cx: &mut ViewContext) -> Option> { + self.show_or_hide_panel::(cx, |_, _| true)?.as_any().clone().downcast() } pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { + self.show_or_hide_panel::(cx, |panel, cx| !panel.has_focus(cx)); + } + + fn show_or_hide_panel(&mut self, cx: &mut ViewContext, show: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool) -> Option> { for (dock, position) in [ self.left_dock.clone(), self.bottom_dock.clone(), @@ -1676,21 +1648,24 @@ impl Workspace { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { let mut focus_center = false; let mut zoom_out = false; - dock.update(cx, |dock, cx| { + let panel = dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); - if let Some(panel) = dock.active_panel().cloned() { - if panel.has_focus(cx) { + let panel = dock.active_panel().cloned(); + if let Some(panel) = panel.as_ref() { + let should_show = show(&**panel, cx); + if should_show { + dock.set_open(true, cx); + cx.focus(panel.as_any()); + zoom_out = true; + } else { if panel.is_zoomed(cx) { dock.set_open(false, cx); } focus_center = true; - } else { - dock.set_open(true, cx); - cx.focus(panel.as_any()); - zoom_out = true; } } + panel }); if zoom_out { @@ -1702,9 +1677,10 @@ impl Workspace { self.serialize_workspace(cx); cx.notify(); - break; + return panel; } } + None } fn zoom_out(&mut self, cx: &mut ViewContext) { From 685e8d70072f7f3cfb0dd8beb7bf513c6aa205e7 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 16:23:16 -0700 Subject: [PATCH 21/53] Seperate pane and panel styling co-authored-by: max --- crates/theme/src/theme.rs | 3 ++- crates/workspace/src/pane.rs | 2 +- crates/workspace/src/workspace.rs | 39 +++++++++++++++++-------------- styles/src/styleTree/workspace.ts | 10 +++++--- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index b1c9e9c215324bbd6dcdf363d2aeb272ec86f057..21c01150a852b7251ac6968641ad915d4124d399 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -89,7 +89,8 @@ pub struct Workspace { pub breadcrumbs: Interactive, pub disconnected_overlay: ContainedText, pub modal: ContainerStyle, - pub zoomed_foreground: ContainerStyle, + pub zoomed_panel_foreground: ContainerStyle, + pub zoomed_pane_foreground: ContainerStyle, pub zoomed_background: ContainerStyle, pub notification: ContainerStyle, pub notifications: Notifications, diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 23d3d6f37813135af8bc4975650ae47f348f9b3a..8dca08ec810585a95e01febec77d67e8e598854c 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -2,7 +2,7 @@ mod dragged_item_receiver; use super::{ItemHandle, SplitDirection}; use crate::{ - item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewFile, NewSearch, NewTerminal, + item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewFile, NewSearch, ToggleZoom, Workspace, WorkspaceSettings, NewCenterTerminal, }; use anyhow::Result; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 9285e911ef15001964b87796230ee500748cd7f5..0aefe455ac919ae1d42bc02af493b12395b0590a 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3270,37 +3270,42 @@ impl View for Workspace { enum ZoomBackground {} let zoomed = zoomed.upgrade(cx)?; - let mut background_style = - theme.workspace.zoomed_background; + let mut foreground_style; match self.zoomed_position { Some(DockPosition::Left) => { - background_style.padding.left = 0.; - background_style.padding.top = 0.; - background_style.padding.bottom = 0.; - background_style.padding.right *= 1.; + foreground_style = + theme.workspace.zoomed_panel_foreground; + foreground_style.margin.left = 0.; + foreground_style.margin.top = 0.; + foreground_style.margin.bottom = 0.; } Some(DockPosition::Right) => { - background_style.padding.right = 0.; - background_style.padding.top = 0.; - background_style.padding.bottom = 0.; - background_style.padding.left *= 1.; + foreground_style = + theme.workspace.zoomed_panel_foreground; + foreground_style.margin.right = 0.; + foreground_style.margin.top = 0.; + foreground_style.margin.bottom = 0.; } Some(DockPosition::Bottom) => { - background_style.padding.left = 0.; - background_style.padding.right = 0.; - background_style.padding.bottom = 0.; - background_style.padding.top *= 1.; + foreground_style = + theme.workspace.zoomed_panel_foreground; + foreground_style.margin.left = 0.; + foreground_style.margin.right = 0.; + foreground_style.margin.bottom = 0.; + } + None => { + foreground_style = + theme.workspace.zoomed_pane_foreground; } - None => {} } Some( ChildView::new(&zoomed, cx) .contained() - .with_style(theme.workspace.zoomed_foreground) + .with_style(foreground_style) .aligned() .contained() - .with_style(background_style) + .with_style(theme.workspace.zoomed_background) .mouse::(0) .capture_all() .on_down( diff --git a/styles/src/styleTree/workspace.ts b/styles/src/styleTree/workspace.ts index 737d225784aeabe86edbdcf9a044748855ffc01f..cf5234aa004eb29022a967f6bbdfcd135b0e5dbf 100644 --- a/styles/src/styleTree/workspace.ts +++ b/styles/src/styleTree/workspace.ts @@ -119,14 +119,18 @@ export default function workspace(colorScheme: ColorScheme) { cursor: "Arrow", }, zoomedBackground: { - padding: 10, cursor: "Arrow", - background: withOpacity(background(colorScheme.lowest), 0.5) + background: withOpacity(background(colorScheme.lowest), 0.85) }, - zoomedForeground: { + zoomedPaneForeground: { + margin: 10, shadow: colorScheme.modalShadow, border: border(colorScheme.highest, { overlay: true }), }, + zoomedPanelForeground: { + margin: 18, + border: border(colorScheme.highest, { overlay: true }), + }, dock: { left: { border: border(layer, { right: true }), From 0122cd61c555154c61f9f94c0c23f671c322bdf5 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 16:33:42 -0700 Subject: [PATCH 22/53] fmt --- crates/terminal_view/src/terminal_panel.rs | 11 ++++++----- crates/terminal_view/src/terminal_view.rs | 2 +- crates/workspace/src/dock.rs | 3 ++- crates/workspace/src/pane.rs | 4 ++-- crates/workspace/src/workspace.rs | 14 +++++++++++--- crates/zed/src/menus.rs | 15 +++------------ 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index c2f7eb36e4f6fd725a6f67572a1e1ba10acbdb1f..e45459e68363169b1bd0b3f2cc8b44621e078271 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -220,15 +220,16 @@ impl TerminalPanel { } } - - fn new_terminal(workspace: &mut Workspace, _: &workspace::NewTerminal, cx: &mut ViewContext) { + fn new_terminal( + workspace: &mut Workspace, + _: &workspace::NewTerminal, + cx: &mut ViewContext, + ) { let Some(this) = workspace.focus_panel::(cx) else { return; }; - this.update(cx, |this, cx| { - this.add_terminal(cx) - }) + this.update(cx, |this, cx| this.add_terminal(cx)) } fn add_terminal(&mut self, cx: &mut ViewContext) { diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 633b83afb8bbb0cc7019e02ad089856939585732..7f43f99ebd43727ea3284e179c70da49accfbff1 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -38,7 +38,7 @@ use workspace::{ notifications::NotifyResultExt, pane, register_deserializable_item, searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle}, - Pane, ToolbarItemLocation, Workspace, WorkspaceId, NewCenterTerminal, + NewCenterTerminal, Pane, ToolbarItemLocation, Workspace, WorkspaceId, }; pub use terminal::TerminalSettings; diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 2f198f62f4714b2948e2c5c89aaf6e4120446371..886afe943d0c6ff57c8c2f9fb5c385b8c09f7451 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -517,7 +517,8 @@ impl View for PanelButtons { &*tooltip_action, ) .ok(); - }).detach(); + }) + .detach(); } } }) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 8dca08ec810585a95e01febec77d67e8e598854c..921ae5e0100d45ced85f1664dfe9a1acf534892a 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -2,8 +2,8 @@ mod dragged_item_receiver; use super::{ItemHandle, SplitDirection}; use crate::{ - item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewFile, NewSearch, - ToggleZoom, Workspace, WorkspaceSettings, NewCenterTerminal, + item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewCenterTerminal, NewFile, + NewSearch, ToggleZoom, Workspace, WorkspaceSettings, }; use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 0aefe455ac919ae1d42bc02af493b12395b0590a..d051f6d80a9f6a2ee8974797333ac3ae0d6ddfe8 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -53,9 +53,10 @@ use std::{ cmp, env, future::Future, path::{Path, PathBuf}, + rc::Rc, str, sync::{atomic::AtomicUsize, Arc}, - time::Duration, rc::Rc, + time::Duration, }; use crate::{ @@ -1623,14 +1624,21 @@ impl Workspace { } pub fn focus_panel(&mut self, cx: &mut ViewContext) -> Option> { - self.show_or_hide_panel::(cx, |_, _| true)?.as_any().clone().downcast() + self.show_or_hide_panel::(cx, |_, _| true)? + .as_any() + .clone() + .downcast() } pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { self.show_or_hide_panel::(cx, |panel, cx| !panel.has_focus(cx)); } - fn show_or_hide_panel(&mut self, cx: &mut ViewContext, show: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool) -> Option> { + fn show_or_hide_panel( + &mut self, + cx: &mut ViewContext, + show: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, + ) -> Option> { for (dock, position) in [ self.left_dock.clone(), self.bottom_dock.clone(), diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index ecfd567e78d8e739b19484e80ee9d2749cb9eb98..76e88325f5cc858091cd3fcc367340337d554a9c 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -89,18 +89,9 @@ pub fn menus() -> Vec> { MenuItem::action("Zoom Out", super::DecreaseBufferFontSize), MenuItem::action("Reset Zoom", super::ResetBufferFontSize), MenuItem::separator(), - MenuItem::action( - "Toggle Left Dock", - workspace::ToggleLeftDock, - ), - MenuItem::action( - "Toggle Right Dock", - workspace::ToggleRightDock, - ), - MenuItem::action( - "Toggle Bottom Dock", - workspace::ToggleBottomDock, - ), + MenuItem::action("Toggle Left Dock", workspace::ToggleLeftDock), + MenuItem::action("Toggle Right Dock", workspace::ToggleRightDock), + MenuItem::action("Toggle Bottom Dock", workspace::ToggleBottomDock), MenuItem::submenu(Menu { name: "Editor Layout", items: vec![ From c9820fde61acd5673dda49c3e4144b8e6bfd1b3b Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 17:48:41 -0700 Subject: [PATCH 23/53] WIP: Add toast when users attempt to use shift-escape for the first time --- crates/util/src/channel.rs | 2 + crates/workspace/src/notifications.rs | 166 ++++++++++++++------------ crates/workspace/src/pane.rs | 10 +- crates/workspace/src/workspace.rs | 60 +++++++++- crates/zed/src/main.rs | 1 + 5 files changed, 157 insertions(+), 82 deletions(-) diff --git a/crates/util/src/channel.rs b/crates/util/src/channel.rs index 274fd576a050076511c8c1253b7187fbd437e8c3..2b45cb6b6611cb6a036f1cf61768fcd2f5dac184 100644 --- a/crates/util/src/channel.rs +++ b/crates/util/src/channel.rs @@ -2,6 +2,8 @@ use std::env; use lazy_static::lazy_static; +pub struct ZedVersion(pub &'static str); + lazy_static! { pub static ref RELEASE_CHANNEL_NAME: String = if cfg!(debug_assertions) { env::var("ZED_RELEASE_CHANNEL") diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 21b3be09d06ea6781e70dd12fa91a1c2ace2e152..4437a960ef250e1a025c3fb1255826823cd42fda 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -1,5 +1,5 @@ use crate::{Toast, Workspace}; -use collections::HashSet; +use collections::HashMap; use gpui::{AnyViewHandle, AppContext, Entity, View, ViewContext, ViewHandle}; use std::{any::TypeId, ops::DerefMut}; @@ -34,11 +34,11 @@ impl From<&dyn NotificationHandle> for AnyViewHandle { } struct NotificationTracker { - notifications_sent: HashSet, + notifications_sent: HashMap>, } impl std::ops::Deref for NotificationTracker { - type Target = HashSet; + type Target = HashMap>; fn deref(&self) -> &Self::Target { &self.notifications_sent @@ -54,24 +54,35 @@ impl DerefMut for NotificationTracker { impl NotificationTracker { fn new() -> Self { Self { - notifications_sent: HashSet::default(), + notifications_sent: Default::default(), } } } impl Workspace { + pub fn has_shown_notification_once( + &self, + id: usize, + cx: &ViewContext, + ) -> bool { + cx + .global::() + .get(&TypeId::of::()) + .map(|ids| ids.contains(&id)) + .unwrap_or(false) + } + pub fn show_notification_once( &mut self, id: usize, cx: &mut ViewContext, build_notification: impl FnOnce(&mut ViewContext) -> ViewHandle, ) { - if !cx - .global::() - .contains(&TypeId::of::()) + if !self.has_shown_notification_once::(id, cx) { cx.update_global::(|tracker, _| { - tracker.insert(TypeId::of::()) + let entry = tracker.entry(TypeId::of::()).or_default(); + entry.push(id); }); self.show_notification::(id, cx, build_notification) @@ -247,80 +258,81 @@ pub mod simple_message_notification { let on_click = self.on_click.clone(); let has_click_action = on_click.is_some(); - MouseEventHandler::::new(0, cx, |state, cx| { - Flex::column() - .with_child( - Flex::row() - .with_child( - Text::new(message, theme.message.text.clone()) - .contained() - .with_style(theme.message.container) - .aligned() - .top() - .left() - .flex(1., true), - ) - .with_child( - MouseEventHandler::::new(0, cx, |state, _| { - let style = theme.dismiss_button.style_for(state, false); - Svg::new("icons/x_mark_8.svg") - .with_color(style.color) - .constrained() - .with_width(style.icon_width) - .aligned() - .contained() - .with_style(style.container) - .constrained() - .with_width(style.button_width) - .with_height(style.button_width) - }) - .with_padding(Padding::uniform(5.)) - .on_click(MouseButton::Left, move |_, this, cx| { - this.dismiss(&Default::default(), cx); - }) - .with_cursor_style(CursorStyle::PointingHand) - .aligned() - .constrained() - .with_height( - cx.font_cache().line_height(theme.message.text.font_size), - ) + Flex::column() + .with_child( + Flex::row() + .with_child( + Text::new(message, theme.message.text.clone()) + .contained() + .with_style(theme.message.container) .aligned() .top() - .flex_float(), - ), - ) - .with_children({ - let style = theme.action_message.style_for(state, false); - if let Some(click_message) = click_message { - Some( - Flex::row().with_child( - Text::new(click_message, style.text.clone()) + .left() + .flex(1., true), + ) + .with_child( + MouseEventHandler::::new(0, cx, |state, _| { + let style = theme.dismiss_button.style_for(state, false); + Svg::new("icons/x_mark_8.svg") + .with_color(style.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .contained() + .with_style(style.container) + .constrained() + .with_width(style.button_width) + .with_height(style.button_width) + }) + .with_padding(Padding::uniform(5.)) + .on_click(MouseButton::Left, move |_, this, cx| { + this.dismiss(&Default::default(), cx); + }) + .with_cursor_style(CursorStyle::PointingHand) + .aligned() + .constrained() + .with_height(cx.font_cache().line_height(theme.message.text.font_size)) + .aligned() + .top() + .flex_float(), + ), + ) + .with_children({ + click_message + .map(|click_message| { + MouseEventHandler::::new( + 0, + cx, + |state, _| { + let style = theme.action_message.style_for(state, false); + + Flex::row() + .with_child( + Text::new(click_message, style.text.clone()) + .contained() + .with_style(style.container), + ) .contained() - .with_style(style.container), - ), + }, ) - } else { - None - } + .on_click(MouseButton::Left, move |_, this, cx| { + if let Some(on_click) = on_click.as_ref() { + on_click(cx); + this.dismiss(&Default::default(), cx); + } + }) + // Since we're not using a proper overlay, we have to capture these extra events + .on_down(MouseButton::Left, |_, _, _| {}) + .on_up(MouseButton::Left, |_, _, _| {}) + .with_cursor_style(if has_click_action { + CursorStyle::PointingHand + } else { + CursorStyle::Arrow + }) + }) .into_iter() - }) - .contained() - }) - // Since we're not using a proper overlay, we have to capture these extra events - .on_down(MouseButton::Left, |_, _, _| {}) - .on_up(MouseButton::Left, |_, _, _| {}) - .on_click(MouseButton::Left, move |_, this, cx| { - if let Some(on_click) = on_click.as_ref() { - on_click(cx); - this.dismiss(&Default::default(), cx); - } - }) - .with_cursor_style(if has_click_action { - CursorStyle::PointingHand - } else { - CursorStyle::Arrow - }) - .into_any() + }) + .into_any() } } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 921ae5e0100d45ced85f1664dfe9a1acf534892a..fad8cd8864e1a55cec7d214201abb35eb60f9404 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -2,8 +2,8 @@ mod dragged_item_receiver; use super::{ItemHandle, SplitDirection}; use crate::{ - item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewCenterTerminal, NewFile, - NewSearch, ToggleZoom, Workspace, WorkspaceSettings, + item::WeakItemHandle, notify_of_new_dock, toolbar::Toolbar, AutosaveSetting, Item, + NewCenterTerminal, NewFile, NewSearch, ToggleZoom, Workspace, WorkspaceSettings, }; use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; @@ -536,6 +536,12 @@ impl Pane { } pub fn toggle_zoom(&mut self, _: &ToggleZoom, cx: &mut ViewContext) { + // Potentially warn the user of the new keybinding + let workspace_handle = self.workspace().clone(); + cx.spawn(|_, mut cx| async move { notify_of_new_dock(&workspace_handle, &mut cx) }) + .detach(); + + if self.zoomed { cx.emit(Event::ZoomOut); } else if !self.items.is_empty() { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d051f6d80a9f6a2ee8974797333ac3ae0d6ddfe8..292ec28abc664335caa97d0402d62e3fbc6e5215 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,7 @@ use assets::Assets; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, TypedEnvelope, UserStore, + Client, TypedEnvelope, UserStore, ZED_APP_VERSION, }; use collections::{hash_map, HashMap, HashSet}; use drag_and_drop::DragAndDrop; @@ -83,7 +83,7 @@ use status_bar::StatusBar; pub use status_bar::StatusItemView; use theme::Theme; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; -use util::{async_iife, paths, ResultExt}; +use util::{async_iife, channel::ZedVersion, paths, ResultExt}; pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; lazy_static! { @@ -3190,6 +3190,60 @@ async fn open_items( opened_items } +fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppContext) { + const NEW_PANEL_BLOG_POST: &str = "https://zed.dev/blog/new-panel-system"; + const NEW_DOCK_HINT_KEY: &str = "show_new_dock_key"; + + if workspace + .read_with(cx, |workspace, cx| { + let version = cx.global::().0; + if !version.contains("0.88") + && !version.contains("0.89") + && !version.contains("0.90") + && !version.contains("0.91") + && !version.contains("0.92") + { + return true; + } + workspace.has_shown_notification_once::(2, cx) + }) + .unwrap_or(false) + { + return; + } + + if db::kvp::KEY_VALUE_STORE + .read_kvp(NEW_DOCK_HINT_KEY) + .ok() + .flatten() + .is_some() + { + return; + } + + cx.spawn(|_| async move { + db::kvp::KEY_VALUE_STORE + .write_kvp(NEW_DOCK_HINT_KEY.to_string(), "seen".to_string()) + .await + .ok(); + }) + .detach(); + + workspace + .update(cx, |workspace, cx| { + workspace.show_notification_once(2, cx, |cx| { + cx.add_view(|_| { + MessageNotification::new( + "Looking for the dock? Try 'ctrl-`'!\n'shift-escape' now zooms your pane", + ) + .with_click_message("Click to read more about the new panel system") + .on_click(|cx| cx.platform().open_url(NEW_PANEL_BLOG_POST)) + }) + }) + }) + .ok(); +} + fn notify_if_database_failed(workspace: &WeakViewHandle, cx: &mut AsyncAppContext) { const REPORT_ISSUE_URL: &str ="https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml"; @@ -3206,7 +3260,7 @@ fn notify_if_database_failed(workspace: &WeakViewHandle, cx: &mut Asy } else { let backup_path = (*db::BACKUP_DB_PATH).read(); if let Some(backup_path) = backup_path.clone() { - workspace.show_notification_once(0, cx, move |cx| { + workspace.show_notification_once(1, cx, move |cx| { cx.add_view(move |_| { MessageNotification::new(format!( "Database file was corrupted. Old database backed up to {}", diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 31f331ef93ef17eecb4870f3ed23c9f963a5b3aa..558796807bedc4f8151faaa8cf0c6544ac5f5423 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -119,6 +119,7 @@ fn main() { app.run(move |cx| { cx.set_global(*RELEASE_CHANNEL); + cx.set_global(util::channel::ZedVersion(env!("CARGO_PKG_VERSION"))); #[cfg(debug_assertions)] cx.set_global(StaffMode(true)); From 8f95435548ee3ef34085992588e4f4107bf1b346 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 30 May 2023 11:05:08 -0700 Subject: [PATCH 24/53] Replicate project-specific settings when collaborating --- .../20221109000000_test_schema.sql | 10 ++ ...0529164700_add_worktree_settings_files.sql | 10 ++ crates/collab/src/db.rs | 101 ++++++++++++++ .../collab/src/db/worktree_settings_file.rs | 19 +++ crates/collab/src/rpc.rs | 50 +++++++ crates/collab/src/tests/integration_tests.rs | 129 ++++++++++++++++++ crates/project/src/project.rs | 105 +++++++++++--- crates/rpc/proto/zed.proto | 9 ++ crates/rpc/src/proto.rs | 2 + crates/settings/src/settings_store.rs | 15 ++ 10 files changed, 432 insertions(+), 18 deletions(-) create mode 100644 crates/collab/migrations/20230529164700_add_worktree_settings_files.sql create mode 100644 crates/collab/src/db/worktree_settings_file.rs diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index 7c6a49f179c2258cc2f18a834e8d63c9c70a6df8..b0b2a684d9501bf135f4280022437ef1c39f1230 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -112,6 +112,16 @@ CREATE INDEX "index_worktree_repository_statuses_on_project_id" ON "worktree_rep CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id" ON "worktree_repository_statuses" ("project_id", "worktree_id"); CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id_and_work_directory_id" ON "worktree_repository_statuses" ("project_id", "worktree_id", "work_directory_id"); +CREATE TABLE "worktree_settings_files" ( + "project_id" INTEGER NOT NULL, + "worktree_id" INTEGER NOT NULL, + "path" VARCHAR NOT NULL, + "content" TEXT, + PRIMARY KEY(project_id, worktree_id, path), + FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE +); +CREATE INDEX "index_worktree_settings_files_on_project_id" ON "worktree_settings_files" ("project_id"); +CREATE INDEX "index_worktree_settings_files_on_project_id_and_worktree_id" ON "worktree_settings_files" ("project_id", "worktree_id"); CREATE TABLE "worktree_diagnostic_summaries" ( "project_id" INTEGER NOT NULL, diff --git a/crates/collab/migrations/20230529164700_add_worktree_settings_files.sql b/crates/collab/migrations/20230529164700_add_worktree_settings_files.sql new file mode 100644 index 0000000000000000000000000000000000000000..973a40af0f21908e5dbe0d5a30373629f24b7f1e --- /dev/null +++ b/crates/collab/migrations/20230529164700_add_worktree_settings_files.sql @@ -0,0 +1,10 @@ +CREATE TABLE "worktree_settings_files" ( + "project_id" INTEGER NOT NULL, + "worktree_id" INT8 NOT NULL, + "path" VARCHAR NOT NULL, + "content" TEXT NOT NULL, + PRIMARY KEY(project_id, worktree_id, path), + FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE +); +CREATE INDEX "index_settings_files_on_project_id" ON "worktree_settings_files" ("project_id"); +CREATE INDEX "index_settings_files_on_project_id_and_wt_id" ON "worktree_settings_files" ("project_id", "worktree_id"); diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index fd28fb910177099d0cf7d639cfd802aa4f3dab25..1deca1baa8036113c4ad2c4f0535a18085cb5db1 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -16,6 +16,7 @@ mod worktree_diagnostic_summary; mod worktree_entry; mod worktree_repository; mod worktree_repository_statuses; +mod worktree_settings_file; use crate::executor::Executor; use crate::{Error, Result}; @@ -1494,6 +1495,7 @@ impl Database { updated_repositories: Default::default(), removed_repositories: Default::default(), diagnostic_summaries: Default::default(), + settings_files: Default::default(), scan_id: db_worktree.scan_id as u64, completed_scan_id: db_worktree.completed_scan_id as u64, }; @@ -1638,6 +1640,25 @@ impl Database { }) .collect::>(); + { + let mut db_settings_files = worktree_settings_file::Entity::find() + .filter(worktree_settings_file::Column::ProjectId.eq(project_id)) + .stream(&*tx) + .await?; + while let Some(db_settings_file) = db_settings_files.next().await { + let db_settings_file = db_settings_file?; + if let Some(worktree) = worktrees + .iter_mut() + .find(|w| w.id == db_settings_file.worktree_id as u64) + { + worktree.settings_files.push(WorktreeSettingsFile { + path: db_settings_file.path, + content: db_settings_file.content, + }); + } + } + } + let mut collaborators = project .find_related(project_collaborator::Entity) .all(&*tx) @@ -2637,6 +2658,58 @@ impl Database { .await } + pub async fn update_worktree_settings( + &self, + update: &proto::UpdateWorktreeSettings, + connection: ConnectionId, + ) -> Result>> { + let project_id = ProjectId::from_proto(update.project_id); + let room_id = self.room_id_for_project(project_id).await?; + self.room_transaction(room_id, |tx| async move { + // Ensure the update comes from the host. + let project = project::Entity::find_by_id(project_id) + .one(&*tx) + .await? + .ok_or_else(|| anyhow!("no such project"))?; + if project.host_connection()? != connection { + return Err(anyhow!("can't update a project hosted by someone else"))?; + } + + if let Some(content) = &update.content { + worktree_settings_file::Entity::insert(worktree_settings_file::ActiveModel { + project_id: ActiveValue::Set(project_id), + worktree_id: ActiveValue::Set(update.worktree_id as i64), + path: ActiveValue::Set(update.path.clone()), + content: ActiveValue::Set(content.clone()), + }) + .on_conflict( + OnConflict::columns([ + worktree_settings_file::Column::ProjectId, + worktree_settings_file::Column::WorktreeId, + worktree_settings_file::Column::Path, + ]) + .update_column(worktree_settings_file::Column::Content) + .to_owned(), + ) + .exec(&*tx) + .await?; + } else { + worktree_settings_file::Entity::delete(worktree_settings_file::ActiveModel { + project_id: ActiveValue::Set(project_id), + worktree_id: ActiveValue::Set(update.worktree_id as i64), + path: ActiveValue::Set(update.path.clone()), + ..Default::default() + }) + .exec(&*tx) + .await?; + } + + let connection_ids = self.project_guest_connection_ids(project_id, &tx).await?; + Ok(connection_ids) + }) + .await + } + pub async fn join_project( &self, project_id: ProjectId, @@ -2707,6 +2780,7 @@ impl Database { entries: Default::default(), repository_entries: Default::default(), diagnostic_summaries: Default::default(), + settings_files: Default::default(), scan_id: db_worktree.scan_id as u64, completed_scan_id: db_worktree.completed_scan_id as u64, }, @@ -2819,6 +2893,25 @@ impl Database { } } + // Populate worktree settings files + { + let mut db_settings_files = worktree_settings_file::Entity::find() + .filter(worktree_settings_file::Column::ProjectId.eq(project_id)) + .stream(&*tx) + .await?; + while let Some(db_settings_file) = db_settings_files.next().await { + let db_settings_file = db_settings_file?; + if let Some(worktree) = + worktrees.get_mut(&(db_settings_file.worktree_id as u64)) + { + worktree.settings_files.push(WorktreeSettingsFile { + path: db_settings_file.path, + content: db_settings_file.content, + }); + } + } + } + // Populate language servers. let language_servers = project .find_related(language_server::Entity) @@ -3482,6 +3575,7 @@ pub struct RejoinedWorktree { pub updated_repositories: Vec, pub removed_repositories: Vec, pub diagnostic_summaries: Vec, + pub settings_files: Vec, pub scan_id: u64, pub completed_scan_id: u64, } @@ -3537,10 +3631,17 @@ pub struct Worktree { pub entries: Vec, pub repository_entries: BTreeMap, pub diagnostic_summaries: Vec, + pub settings_files: Vec, pub scan_id: u64, pub completed_scan_id: u64, } +#[derive(Debug)] +pub struct WorktreeSettingsFile { + pub path: String, + pub content: String, +} + #[cfg(test)] pub use test::*; diff --git a/crates/collab/src/db/worktree_settings_file.rs b/crates/collab/src/db/worktree_settings_file.rs new file mode 100644 index 0000000000000000000000000000000000000000..f8e87f6e599cbaaeb698bdb28cb1316c7097dc77 --- /dev/null +++ b/crates/collab/src/db/worktree_settings_file.rs @@ -0,0 +1,19 @@ +use super::ProjectId; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "worktree_settings_files")] +pub struct Model { + #[sea_orm(primary_key)] + pub project_id: ProjectId, + #[sea_orm(primary_key)] + pub worktree_id: i64, + #[sea_orm(primary_key)] + pub path: String, + pub content: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 4c117b613da90ce6ac54c792833aa94364715758..61c6123a827e897d9bf8c5db15e9e79fdbd4b951 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -200,6 +200,7 @@ impl Server { .add_message_handler(start_language_server) .add_message_handler(update_language_server) .add_message_handler(update_diagnostic_summary) + .add_message_handler(update_worktree_settings) .add_request_handler(forward_project_request::) .add_request_handler(forward_project_request::) .add_request_handler(forward_project_request::) @@ -1088,6 +1089,18 @@ async fn rejoin_room( }, )?; } + + for settings_file in worktree.settings_files { + session.peer.send( + session.connection_id, + proto::UpdateWorktreeSettings { + project_id: project.id.to_proto(), + worktree_id: worktree.id, + path: settings_file.path, + content: Some(settings_file.content), + }, + )?; + } } for language_server in &project.language_servers { @@ -1410,6 +1423,18 @@ async fn join_project( }, )?; } + + for settings_file in dbg!(worktree.settings_files) { + session.peer.send( + session.connection_id, + proto::UpdateWorktreeSettings { + project_id: project_id.to_proto(), + worktree_id: worktree.id, + path: settings_file.path, + content: Some(settings_file.content), + }, + )?; + } } for language_server in &project.language_servers { @@ -1525,6 +1550,31 @@ async fn update_diagnostic_summary( Ok(()) } +async fn update_worktree_settings( + message: proto::UpdateWorktreeSettings, + session: Session, +) -> Result<()> { + dbg!(&message); + + let guest_connection_ids = session + .db() + .await + .update_worktree_settings(&message, session.connection_id) + .await?; + + broadcast( + Some(session.connection_id), + guest_connection_ids.iter().copied(), + |connection_id| { + session + .peer + .forward_send(session.connection_id, connection_id, message.clone()) + }, + ); + + Ok(()) +} + async fn start_language_server( request: proto::StartLanguageServer, session: Session, diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index d771f969d8899e0183d95db17a42389dbe706dd0..fb0f63b2438b584739cef83aafbf4f9782da89dc 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -3114,6 +3114,135 @@ async fn test_fs_operations( }); } +#[gpui::test(iterations = 10)] +async fn test_local_settings( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + server + .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) + .await; + let active_call_a = cx_a.read(ActiveCall::global); + + // As client A, open a project that contains some local settings files + client_a + .fs + .insert_tree( + "/dir", + json!({ + ".zed": { + "settings.json": r#"{ "tab_size": 2 }"# + }, + "a": { + ".zed": { + "settings.json": r#"{ "tab_size": 8 }"# + }, + "a.txt": "a-contents", + }, + "b": { + "b.txt": "b-contents", + } + }), + ) + .await; + let (project_a, _) = client_a.build_local_project("/dir", cx_a).await; + let project_id = active_call_a + .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) + .await + .unwrap(); + + // As client B, join that project and observe the local settings. + let project_b = client_b.build_remote_project(project_id, cx_b).await; + let worktree_b = project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap()); + deterministic.run_until_parked(); + cx_b.read(|cx| { + let store = cx.global::(); + assert_eq!( + store.local_settings(worktree_b.id()).collect::>(), + &[ + (Path::new("").into(), r#"{"tab_size":2}"#.to_string()), + (Path::new("a").into(), r#"{"tab_size":8}"#.to_string()), + ] + ) + }); + + // As client A, update a settings file. As Client B, see the changed settings. + client_a + .fs + .insert_file("/dir/.zed/settings.json", r#"{}"#.into()) + .await; + deterministic.run_until_parked(); + cx_b.read(|cx| { + let store = cx.global::(); + assert_eq!( + store.local_settings(worktree_b.id()).collect::>(), + &[ + (Path::new("").into(), r#"{}"#.to_string()), + (Path::new("a").into(), r#"{"tab_size":8}"#.to_string()), + ] + ) + }); + + // As client A, create and remove some settings files. As client B, see the changed settings. + client_a + .fs + .remove_file("/dir/.zed/settings.json".as_ref(), Default::default()) + .await + .unwrap(); + client_a + .fs + .create_dir("/dir/b/.zed".as_ref()) + .await + .unwrap(); + client_a + .fs + .insert_file("/dir/b/.zed/settings.json", r#"{"tab_size": 4}"#.into()) + .await; + deterministic.run_until_parked(); + cx_b.read(|cx| { + let store = cx.global::(); + assert_eq!( + store.local_settings(worktree_b.id()).collect::>(), + &[ + (Path::new("a").into(), r#"{"tab_size":8}"#.to_string()), + (Path::new("b").into(), r#"{"tab_size":4}"#.to_string()), + ] + ) + }); + + // As client B, disconnect. + server.forbid_connections(); + server.disconnect_client(client_b.peer_id().unwrap()); + + // As client A, change and remove settings files while client B is disconnected. + client_a + .fs + .insert_file("/dir/a/.zed/settings.json", r#"{"hard_tabs":true}"#.into()) + .await; + client_a + .fs + .remove_file("/dir/b/.zed/settings.json".as_ref(), Default::default()) + .await + .unwrap(); + deterministic.run_until_parked(); + + // As client B, reconnect and see the changed settings. + server.allow_connections(); + deterministic.advance_clock(RECEIVE_TIMEOUT); + cx_b.read(|cx| { + let store = cx.global::(); + assert_eq!( + store.local_settings(worktree_b.id()).collect::>(), + &[(Path::new("a").into(), r#"{"hard_tabs":true}"#.to_string()),] + ) + }); +} + #[gpui::test(iterations = 10)] async fn test_buffer_conflict_after_save( deterministic: Arc, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c76587ff56328fabdab93abf77965e547f11979b..3cc4a181c55ad18315204c780aa6c6a6da337666 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -462,6 +462,7 @@ impl Project { client.add_model_request_handler(Self::handle_update_buffer); client.add_model_message_handler(Self::handle_update_diagnostic_summary); client.add_model_message_handler(Self::handle_update_worktree); + client.add_model_message_handler(Self::handle_update_worktree_settings); client.add_model_request_handler(Self::handle_create_project_entry); client.add_model_request_handler(Self::handle_rename_project_entry); client.add_model_request_handler(Self::handle_copy_project_entry); @@ -1105,6 +1106,21 @@ impl Project { .log_err(); } + let store = cx.global::(); + for worktree in self.worktrees(cx) { + let worktree_id = worktree.read(cx).id().to_proto(); + for (path, content) in store.local_settings(worktree.id()) { + self.client + .send(proto::UpdateWorktreeSettings { + project_id, + worktree_id, + path: path.to_string_lossy().into(), + content: Some(content), + }) + .log_err(); + } + } + let (updates_tx, mut updates_rx) = mpsc::unbounded(); let client = self.client.clone(); self.client_state = Some(ProjectClientState::Local { @@ -1217,6 +1233,14 @@ impl Project { message_id: u32, cx: &mut ModelContext, ) -> Result<()> { + cx.update_global::(|store, cx| { + for worktree in &self.worktrees { + store + .clear_local_settings(worktree.handle_id(), cx) + .log_err(); + } + }); + self.join_project_response_message_id = message_id; self.set_worktrees_from_proto(message.worktrees, cx)?; self.set_collaborators_from_proto(message.collaborators, cx)?; @@ -4888,8 +4912,12 @@ impl Project { .push(WorktreeHandle::Weak(worktree.downgrade())); } - cx.observe_release(worktree, |this, worktree, cx| { + let handle_id = worktree.id(); + cx.observe_release(worktree, move |this, worktree, cx| { let _ = this.remove_worktree(worktree.id(), cx); + cx.update_global::(|store, cx| { + store.clear_local_settings(handle_id, cx).log_err() + }); }) .detach(); @@ -5174,14 +5202,16 @@ impl Project { .detach(); } - pub fn update_local_worktree_settings( + fn update_local_worktree_settings( &mut self, worktree: &ModelHandle, changes: &UpdatedEntriesSet, cx: &mut ModelContext, ) { + let project_id = self.remote_id(); let worktree_id = worktree.id(); let worktree = worktree.read(cx).as_local().unwrap(); + let remote_worktree_id = worktree.id(); let mut settings_contents = Vec::new(); for (path, _, change) in changes.iter() { @@ -5195,10 +5225,7 @@ impl Project { let removed = *change == PathChange::Removed; let abs_path = worktree.absolutize(path); settings_contents.push(async move { - anyhow::Ok(( - settings_dir, - (!removed).then_some(fs.load(&abs_path).await?), - )) + (settings_dir, (!removed).then_some(fs.load(&abs_path).await)) }); } } @@ -5207,19 +5234,30 @@ impl Project { return; } + let client = self.client.clone(); cx.spawn_weak(move |_, mut cx| async move { - let settings_contents = futures::future::join_all(settings_contents).await; + let settings_contents: Vec<(Arc, _)> = + futures::future::join_all(settings_contents).await; cx.update(|cx| { cx.update_global::(|store, cx| { - for entry in settings_contents { - if let Some((directory, file_content)) = entry.log_err() { - store - .set_local_settings( - worktree_id, - directory, - file_content.as_ref().map(String::as_str), - cx, - ) + for (directory, file_content) in settings_contents { + let file_content = file_content.and_then(|content| content.log_err()); + store + .set_local_settings( + worktree_id, + directory.clone(), + file_content.as_ref().map(String::as_str), + cx, + ) + .log_err(); + if let Some(remote_id) = project_id { + client + .send(proto::UpdateWorktreeSettings { + project_id: remote_id, + worktree_id: remote_worktree_id.to_proto(), + path: directory.to_string_lossy().into_owned(), + content: file_content, + }) .log_err(); } } @@ -5467,6 +5505,30 @@ impl Project { }) } + async fn handle_update_worktree_settings( + this: ModelHandle, + envelope: TypedEnvelope, + _: Arc, + mut cx: AsyncAppContext, + ) -> Result<()> { + this.update(&mut cx, |this, cx| { + let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); + if let Some(worktree) = this.worktree_for_id(worktree_id, cx) { + cx.update_global::(|store, cx| { + store + .set_local_settings( + worktree.id(), + PathBuf::from(&envelope.payload.path).into(), + envelope.payload.content.as_ref().map(String::as_str), + cx, + ) + .log_err(); + }); + } + Ok(()) + }) + } + async fn handle_create_project_entry( this: ModelHandle, envelope: TypedEnvelope, @@ -6557,8 +6619,8 @@ impl Project { } self.metadata_changed(cx); - for (id, _) in old_worktrees_by_id { - cx.emit(Event::WorktreeRemoved(id)); + for id in old_worktrees_by_id.keys() { + cx.emit(Event::WorktreeRemoved(*id)); } Ok(()) @@ -6928,6 +6990,13 @@ impl WorktreeHandle { WorktreeHandle::Weak(handle) => handle.upgrade(cx), } } + + pub fn handle_id(&self) -> usize { + match self { + WorktreeHandle::Strong(handle) => handle.id(), + WorktreeHandle::Weak(handle) => handle.id(), + } + } } impl OpenBuffer { diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 848cc1c2fa3213ce55f317e63b7a6d7db293671f..8351cdfd2dfe6a61bcccaad4d7a8dc40ff00bfc2 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -132,6 +132,8 @@ message Envelope { OnTypeFormatting on_type_formatting = 111; OnTypeFormattingResponse on_type_formatting_response = 112; + + UpdateWorktreeSettings update_worktree_settings = 113; } } @@ -339,6 +341,13 @@ message UpdateWorktree { string abs_path = 10; } +message UpdateWorktreeSettings { + uint64 project_id = 1; + uint64 worktree_id = 2; + string path = 3; + optional string content = 4; +} + message CreateProjectEntry { uint64 project_id = 1; uint64 worktree_id = 2; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 07925a0486e6d210ceac44a7c5a5428b3f48a58e..13794ea64dad1446e579dd00806ccb4afda4758b 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -236,6 +236,7 @@ messages!( (UpdateProject, Foreground), (UpdateProjectCollaborator, Foreground), (UpdateWorktree, Foreground), + (UpdateWorktreeSettings, Foreground), (UpdateDiffBase, Foreground), (GetPrivateUserInfo, Foreground), (GetPrivateUserInfoResponse, Foreground), @@ -345,6 +346,7 @@ entity_messages!( UpdateProject, UpdateProjectCollaborator, UpdateWorktree, + UpdateWorktreeSettings, UpdateDiffBase ); diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 2560d0b752da72881b8ba373772159e07541c74b..bb51fd1ed004911415abc292efc70c33f666685d 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -359,6 +359,21 @@ impl SettingsStore { Ok(()) } + /// Add or remove a set of local settings via a JSON string. + pub fn clear_local_settings(&mut self, root_id: usize, cx: &AppContext) -> Result<()> { + eprintln!("clearing local settings {root_id}"); + self.local_deserialized_settings + .retain(|k, _| k.0 != root_id); + self.recompute_values(Some((root_id, "".as_ref())), cx)?; + Ok(()) + } + + pub fn local_settings(&self, root_id: usize) -> impl '_ + Iterator, String)> { + self.local_deserialized_settings + .range((root_id, Path::new("").into())..(root_id + 1, Path::new("").into())) + .map(|((_, path), content)| (path.clone(), serde_json::to_string(content).unwrap())) + } + pub fn json_schema( &self, schema_params: &SettingsJsonSchemaParams, From eeba72d7755c6f1f2b4b1c8142b26212583deaec Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 09:03:45 -0700 Subject: [PATCH 25/53] Bump protocol version --- crates/rpc/src/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index b929de95961e756d369f9b1549dc693d6536bbe0..bef6efa529fd514b24789a5d294dbc33409974ab 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -6,4 +6,4 @@ pub use conn::Connection; pub use peer::*; mod macros; -pub const PROTOCOL_VERSION: u32 = 56; +pub const PROTOCOL_VERSION: u32 = 57; From 76927b6d95bb8d7baeb38cdb39b59d365776e7c3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 10:29:59 -0700 Subject: [PATCH 26/53] Make active panel's button close its dock --- crates/workspace/src/dock.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 886afe943d0c6ff57c8c2f9fb5c385b8c09f7451..ac52c8f1790c865cdf3a1378b7a994dbe81a3500 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -472,11 +472,22 @@ impl View for PanelButtons { Flex::row() .with_children(panels.into_iter().enumerate().map( |(panel_ix, (view, context_menu))| { - let (tooltip, tooltip_action) = view.icon_tooltip(cx); + let is_active = is_open && panel_ix == active_ix; + let (tooltip, tooltip_action) = if is_active { + ( + format!("Close {} dock", dock_position.to_label()), + Some(match dock_position { + DockPosition::Left => crate::ToggleLeftDock.boxed_clone(), + DockPosition::Bottom => crate::ToggleBottomDock.boxed_clone(), + DockPosition::Right => crate::ToggleRightDock.boxed_clone(), + }), + ) + } else { + view.icon_tooltip(cx) + }; Stack::new() .with_child( MouseEventHandler::::new(panel_ix, cx, |state, cx| { - let is_active = is_open && panel_ix == active_ix; let style = button_style.style_for(state, is_active); Flex::row() .with_child( From ac41564a8f3ac0c575bc29acaf57ede2a7e6753d Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 12:34:06 -0700 Subject: [PATCH 27/53] Dismiss zoomed panels by closing their dock, not zooming them out --- crates/workspace/src/dock.rs | 4 ++ crates/workspace/src/workspace.rs | 110 ++++++++++++++++-------------- 2 files changed, 64 insertions(+), 50 deletions(-) diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index ac52c8f1790c865cdf3a1378b7a994dbe81a3500..a4b71fa5a73fa862f3b28cc4b3785d7c411c4583 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -175,6 +175,10 @@ impl Dock { } } + pub fn position(&self) -> DockPosition { + self.position + } + pub fn is_open(&self) -> bool { self.is_open } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d051f6d80a9f6a2ee8974797333ac3ae0d6ddfe8..d7219970535405a2c29d5bf1367877915d80f5ec 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -908,18 +908,24 @@ impl Workspace { } }); } else if T::should_zoom_in_on_event(event) { - this.zoom_out(cx); dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx)); if panel.has_focus(cx) { this.zoomed = Some(panel.downgrade().into_any()); this.zoomed_position = Some(panel.read(cx).position(cx)); } } else if T::should_zoom_out_on_event(event) { - this.zoom_out(cx); + dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, false, cx)); + if this.zoomed_position == Some(prev_position) { + this.zoomed = None; + this.zoomed_position = None; + } + cx.notify(); } else if T::is_focus_event(event) { + let position = panel.read(cx).position(cx); + this.dismiss_zoomed_items_to_reveal(Some(position), cx); if panel.is_zoomed(cx) { this.zoomed = Some(panel.downgrade().into_any()); - this.zoomed_position = Some(panel.read(cx).position(cx)); + this.zoomed_position = Some(position); } else { this.zoomed = None; this.zoomed_position = None; @@ -1592,7 +1598,7 @@ impl Workspace { DockPosition::Right => &self.right_dock, }; let mut focus_center = false; - let mut zoom_out = false; + let mut reveal_dock = false; dock.update(cx, |dock, cx| { let other_is_zoomed = self.zoomed.is_some() && self.zoomed_position != Some(dock_side); let was_visible = dock.is_open() && !other_is_zoomed; @@ -1607,14 +1613,15 @@ impl Workspace { if active_panel.is_zoomed(cx) { cx.focus(active_panel.as_any()); } - zoom_out = true; + reveal_dock = true; } } }); - if zoom_out { - self.zoom_out_everything_except(dock_side, cx); + if reveal_dock { + self.dismiss_zoomed_items_to_reveal(Some(dock_side), cx); } + if focus_center { cx.focus_self(); } @@ -1623,62 +1630,49 @@ impl Workspace { self.serialize_workspace(cx); } + /// Transfer focus to the panel of the given type. pub fn focus_panel(&mut self, cx: &mut ViewContext) -> Option> { - self.show_or_hide_panel::(cx, |_, _| true)? + self.focus_or_unfocus_panel::(cx, |_, _| true)? .as_any() .clone() .downcast() } + /// Focus the panel of the given type if it isn't already focused. If it is + /// already focused, then transfer focus back to the workspace center. pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { - self.show_or_hide_panel::(cx, |panel, cx| !panel.has_focus(cx)); + self.focus_or_unfocus_panel::(cx, |panel, cx| !panel.has_focus(cx)); } - fn show_or_hide_panel( + /// Focus or unfocus the given panel type, depending on the given callback. + fn focus_or_unfocus_panel( &mut self, cx: &mut ViewContext, - show: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, + should_focus: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, ) -> Option> { - for (dock, position) in [ - self.left_dock.clone(), - self.bottom_dock.clone(), - self.right_dock.clone(), - ] - .into_iter() - .zip( - [ - DockPosition::Left, - DockPosition::Bottom, - DockPosition::Right, - ] - .into_iter(), - ) { + for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { let mut focus_center = false; - let mut zoom_out = false; + let mut reveal_dock = false; let panel = dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); let panel = dock.active_panel().cloned(); if let Some(panel) = panel.as_ref() { - let should_show = show(&**panel, cx); - if should_show { + if should_focus(&**panel, cx) { dock.set_open(true, cx); cx.focus(panel.as_any()); - zoom_out = true; + reveal_dock = true; } else { - if panel.is_zoomed(cx) { - dock.set_open(false, cx); - } + // if panel.is_zoomed(cx) { + // dock.set_open(false, cx); + // } focus_center = true; } } panel }); - if zoom_out { - self.zoom_out_everything_except(position, cx); - } if focus_center { cx.focus_self(); } @@ -1705,28 +1699,38 @@ impl Workspace { cx.notify(); } - fn zoom_out_everything_except( + fn dismiss_zoomed_items_to_reveal( &mut self, - except_position: DockPosition, + except_position: Option, cx: &mut ViewContext, ) { - for pane in &self.panes { - pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); - } - - if except_position != DockPosition::Left { - self.left_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + // If a center pane is zoomed, unzoom it. + if except_position.is_some() { + for pane in &self.panes { + pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + } } - if except_position != DockPosition::Bottom { - self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + // If another dock is zoomed, hide it. + let mut focus_center = false; + for dock in [&self.left_dock, &self.right_dock, &self.bottom_dock] { + dock.update(cx, |dock, cx| { + if Some(dock.position()) != except_position { + if let Some(panel) = dock.active_panel() { + if panel.is_zoomed(cx) { + focus_center |= panel.has_focus(cx); + dock.set_open(false, cx); + } + } + } + }); } - if except_position != DockPosition::Right { - self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + if focus_center { + cx.focus_self(); } - if self.zoomed_position != Some(except_position) { + if self.zoomed_position != except_position { self.zoomed = None; self.zoomed_position = None; } @@ -1937,6 +1941,7 @@ impl Workspace { self.last_active_center_pane = Some(pane.downgrade()); } + self.dismiss_zoomed_items_to_reveal(None, cx); if pane.read(cx).is_zoomed() { self.zoomed = Some(pane.downgrade().into_any()); } else { @@ -1998,7 +2003,6 @@ impl Workspace { } pane::Event::ZoomIn => { if pane == self.active_pane { - self.zoom_out(cx); pane.update(cx, |pane, cx| pane.set_zoomed(true, cx)); if pane.read(cx).has_focus() { self.zoomed = Some(pane.downgrade().into_any()); @@ -2007,7 +2011,13 @@ impl Workspace { cx.notify(); } } - pane::Event::ZoomOut => self.zoom_out(cx), + pane::Event::ZoomOut => { + pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + if self.zoomed_position.is_none() { + self.zoomed = None; + } + cx.notify(); + } } self.serialize_workspace(cx); From a10933c063307fb768bd122a86f1ff359c0e93fe Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 31 May 2023 12:59:04 -0400 Subject: [PATCH 28/53] Update pane/panel zoom styling --- styles/src/styleTree/workspace.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/styles/src/styleTree/workspace.ts b/styles/src/styleTree/workspace.ts index cf5234aa004eb29022a967f6bbdfcd135b0e5dbf..ec992c9c0b368aa7ee792aa3b2ce5c2da3045d2c 100644 --- a/styles/src/styleTree/workspace.ts +++ b/styles/src/styleTree/workspace.ts @@ -13,6 +13,7 @@ import tabBar from "./tabBar" export default function workspace(colorScheme: ColorScheme) { const layer = colorScheme.lowest + const isLight = colorScheme.isLight const itemSpacing = 8 const titlebarButton = { cornerRadius: 6, @@ -120,16 +121,18 @@ export default function workspace(colorScheme: ColorScheme) { }, zoomedBackground: { cursor: "Arrow", - background: withOpacity(background(colorScheme.lowest), 0.85) + background: isLight + ? withOpacity(background(colorScheme.lowest), 0.8) + : withOpacity(background(colorScheme.highest), 0.6) }, zoomedPaneForeground: { - margin: 10, + margin: 16, shadow: colorScheme.modalShadow, - border: border(colorScheme.highest, { overlay: true }), + border: border(colorScheme.lowest, { overlay: true }), }, zoomedPanelForeground: { - margin: 18, - border: border(colorScheme.highest, { overlay: true }), + margin: 16, + border: border(colorScheme.lowest, { overlay: true }), }, dock: { left: { From 1f72f9e18babcd8906d1d550ef4691831b3accaf Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 31 May 2023 12:59:28 -0400 Subject: [PATCH 29/53] Add un-hooked up zoomIcon styles --- styles/src/styleTree/tabBar.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/styles/src/styleTree/tabBar.ts b/styles/src/styleTree/tabBar.ts index 61d30be7e03c8eceb026ea3f0fa1c39eab9cca60..ef1425cd1553c8b98a3d44707da99db5c3692bc5 100644 --- a/styles/src/styleTree/tabBar.ts +++ b/styles/src/styleTree/tabBar.ts @@ -31,6 +31,10 @@ export default function tabBar(colorScheme: ColorScheme) { iconClose: foreground(layer, "variant"), iconCloseActive: foreground(layer, "hovered"), + // Zoom Icons + iconZoom: foreground(layer, "variant"), + iconZoomActive: foreground(layer, "accent"), + // Indicators iconConflict: foreground(layer, "warning"), iconDirty: foreground(layer, "accent"), From 893615236dd721a235bf8afc3fcb446f3dcd5721 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 12:45:48 -0700 Subject: [PATCH 30/53] Only include one border edge for zoomed panels --- crates/workspace/src/workspace.rs | 56 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d7219970535405a2c29d5bf1367877915d80f5ec..1b2fdc80f4e58ca982b1d274795b12fc835f8ac9 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3288,32 +3288,36 @@ impl View for Workspace { enum ZoomBackground {} let zoomed = zoomed.upgrade(cx)?; - let mut foreground_style; - match self.zoomed_position { - Some(DockPosition::Left) => { - foreground_style = - theme.workspace.zoomed_panel_foreground; - foreground_style.margin.left = 0.; - foreground_style.margin.top = 0.; - foreground_style.margin.bottom = 0.; - } - Some(DockPosition::Right) => { - foreground_style = - theme.workspace.zoomed_panel_foreground; - foreground_style.margin.right = 0.; - foreground_style.margin.top = 0.; - foreground_style.margin.bottom = 0.; - } - Some(DockPosition::Bottom) => { - foreground_style = - theme.workspace.zoomed_panel_foreground; - foreground_style.margin.left = 0.; - foreground_style.margin.right = 0.; - foreground_style.margin.bottom = 0.; - } - None => { - foreground_style = - theme.workspace.zoomed_pane_foreground; + let mut foreground_style = + theme.workspace.zoomed_pane_foreground; + if let Some(zoomed_dock_position) = self.zoomed_position { + foreground_style = + theme.workspace.zoomed_panel_foreground; + let margin = foreground_style.margin.top; + let border = foreground_style.border.top; + + // Only include a margin and border on the opposite side. + foreground_style.margin.top = 0.; + foreground_style.margin.left = 0.; + foreground_style.margin.bottom = 0.; + foreground_style.margin.right = 0.; + foreground_style.border.top = false; + foreground_style.border.left = false; + foreground_style.border.bottom = false; + foreground_style.border.right = false; + match zoomed_dock_position { + DockPosition::Left => { + foreground_style.margin.right = margin; + foreground_style.border.right = border; + } + DockPosition::Right => { + foreground_style.margin.left = margin; + foreground_style.border.left = border; + } + DockPosition::Bottom => { + foreground_style.margin.top = margin; + foreground_style.border.top = border; + } } } From 3f6aa94a5f4f3c49457f7c4fb96ac3a46d34f8e3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 12:51:57 -0700 Subject: [PATCH 31/53] Use active color for zoom button in a zoomed pane --- crates/terminal_view/src/terminal_panel.rs | 2 ++ crates/workspace/src/pane.rs | 6 +++++- styles/src/styleTree/tabBar.ts | 7 +++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index e45459e68363169b1bd0b3f2cc8b44621e078271..ac3875af9e10704be06a7a2a047f86ec1fe992b6 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -70,6 +70,7 @@ impl TerminalPanel { .with_child(Pane::render_tab_bar_button( 0, "icons/plus_12.svg", + false, Some(( "New Terminal".into(), Some(Box::new(workspace::NewTerminal)), @@ -94,6 +95,7 @@ impl TerminalPanel { } else { "icons/maximize_8.svg" }, + pane.is_zoomed(), Some(("Toggle Zoom".into(), Some(Box::new(workspace::ToggleZoom)))), cx, move |pane, cx| pane.toggle_zoom(&Default::default(), cx), diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 921ae5e0100d45ced85f1664dfe9a1acf534892a..80a0256389d6799f37e2e73d0b4b527818a33690 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -268,6 +268,7 @@ impl Pane { .with_child(Self::render_tab_bar_button( 0, "icons/plus_12.svg", + false, Some(("New...".into(), None)), cx, |pane, cx| pane.deploy_new_menu(cx), @@ -277,6 +278,7 @@ impl Pane { .with_child(Self::render_tab_bar_button( 1, "icons/split_12.svg", + false, Some(("Split Pane".into(), None)), cx, |pane, cx| pane.deploy_split_menu(cx), @@ -290,6 +292,7 @@ impl Pane { } else { "icons/maximize_8.svg" }, + pane.is_zoomed(), Some(("Toggle Zoom".into(), Some(Box::new(ToggleZoom)))), cx, move |pane, cx| pane.toggle_zoom(&Default::default(), cx), @@ -1401,6 +1404,7 @@ impl Pane { pub fn render_tab_bar_button)>( index: usize, icon: &'static str, + active: bool, tooltip: Option<(String, Option>)>, cx: &mut ViewContext, on_click: F, @@ -1410,7 +1414,7 @@ impl Pane { let mut button = MouseEventHandler::::new(index, cx, |mouse_state, cx| { let theme = &settings::get::(cx).theme.workspace.tab_bar; - let style = theme.pane_button.style_for(mouse_state, false); + let style = theme.pane_button.style_for(mouse_state, active); Svg::new(icon) .with_color(style.color) .constrained() diff --git a/styles/src/styleTree/tabBar.ts b/styles/src/styleTree/tabBar.ts index ef1425cd1553c8b98a3d44707da99db5c3692bc5..39a1ef0407ce92b966e45f19f17a89c3c248c59c 100644 --- a/styles/src/styleTree/tabBar.ts +++ b/styles/src/styleTree/tabBar.ts @@ -31,10 +31,6 @@ export default function tabBar(colorScheme: ColorScheme) { iconClose: foreground(layer, "variant"), iconCloseActive: foreground(layer, "hovered"), - // Zoom Icons - iconZoom: foreground(layer, "variant"), - iconZoomActive: foreground(layer, "accent"), - // Indicators iconConflict: foreground(layer, "warning"), iconDirty: foreground(layer, "accent"), @@ -98,6 +94,9 @@ export default function tabBar(colorScheme: ColorScheme) { hover: { color: foreground(layer, "hovered"), }, + active: { + color: foreground(layer, "accent"), + } }, paneButtonContainer: { background: tab.background, From c48fed26bdebdcb7573e7a06b1ac4fcd0068dc9e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 13:05:50 -0700 Subject: [PATCH 32/53] When revealing items, zoom-out any inactive panes --- crates/workspace/src/workspace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1b2fdc80f4e58ca982b1d274795b12fc835f8ac9..3d55a78e88e228c7c8619ffb2146bbc5921be8bb 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1705,8 +1705,8 @@ impl Workspace { cx: &mut ViewContext, ) { // If a center pane is zoomed, unzoom it. - if except_position.is_some() { - for pane in &self.panes { + for pane in &self.panes { + if pane != &self.active_pane { pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); } } From 193474a346100b4496bc074b3a1efcf5c7cf611a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 13:07:20 -0700 Subject: [PATCH 33/53] :art: --- crates/workspace/src/workspace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 3d55a78e88e228c7c8619ffb2146bbc5921be8bb..b00b8f1102fa0a7bdac0d3d73c182f3751733113 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1701,7 +1701,7 @@ impl Workspace { fn dismiss_zoomed_items_to_reveal( &mut self, - except_position: Option, + dock_to_reveal: Option, cx: &mut ViewContext, ) { // If a center pane is zoomed, unzoom it. @@ -1715,7 +1715,7 @@ impl Workspace { let mut focus_center = false; for dock in [&self.left_dock, &self.right_dock, &self.bottom_dock] { dock.update(cx, |dock, cx| { - if Some(dock.position()) != except_position { + if Some(dock.position()) != dock_to_reveal { if let Some(panel) = dock.active_panel() { if panel.is_zoomed(cx) { focus_center |= panel.has_focus(cx); @@ -1730,7 +1730,7 @@ impl Workspace { cx.focus_self(); } - if self.zoomed_position != except_position { + if self.zoomed_position != dock_to_reveal { self.zoomed = None; self.zoomed_position = None; } From ef80b539d150d67faa0dc821077364975eafea36 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 13:56:41 -0700 Subject: [PATCH 34/53] Fix notification styling, minimize database reads --- crates/workspace/src/notifications.rs | 38 ++++++++++++------ crates/workspace/src/workspace.rs | 57 +++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 4437a960ef250e1a025c3fb1255826823cd42fda..1060227d4ace10dc429af586336b75b7db3d36c7 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -33,7 +33,7 @@ impl From<&dyn NotificationHandle> for AnyViewHandle { } } -struct NotificationTracker { +pub(crate) struct NotificationTracker { notifications_sent: HashMap>, } @@ -65,8 +65,7 @@ impl Workspace { id: usize, cx: &ViewContext, ) -> bool { - cx - .global::() + cx.global::() .get(&TypeId::of::()) .map(|ids| ids.contains(&id)) .unwrap_or(false) @@ -78,8 +77,7 @@ impl Workspace { cx: &mut ViewContext, build_notification: impl FnOnce(&mut ViewContext) -> ViewHandle, ) { - if !self.has_shown_notification_once::(id, cx) - { + if !self.has_shown_notification_once::(id, cx) { cx.update_global::(|tracker, _| { let entry = tracker.entry(TypeId::of::()).or_default(); entry.push(id); @@ -167,7 +165,7 @@ pub mod simple_message_notification { elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text}, impl_actions, platform::{CursorStyle, MouseButton}, - AppContext, Element, Entity, View, ViewContext, + AnyElement, AppContext, Element, Entity, View, ViewContext, fonts::TextStyle, }; use menu::Cancel; use serde::Deserialize; @@ -195,8 +193,13 @@ pub mod simple_message_notification { ) } + enum NotificationMessage { + Text(Cow<'static, str>), + Element(fn(TextStyle, &AppContext) -> AnyElement), + } + pub struct MessageNotification { - message: Cow<'static, str>, + message: NotificationMessage, on_click: Option)>>, click_message: Option>, } @@ -215,7 +218,16 @@ pub mod simple_message_notification { S: Into>, { Self { - message: message.into(), + message: NotificationMessage::Text(message.into()), + on_click: None, + click_message: None, + } + } + + pub fn new_element(message: fn(TextStyle, &AppContext) -> AnyElement) -> MessageNotification + { + Self { + message: NotificationMessage::Element(message), on_click: None, click_message: None, } @@ -254,7 +266,12 @@ pub mod simple_message_notification { enum MessageNotificationTag {} let click_message = self.click_message.clone(); - let message = self.message.clone(); + let message = match &self.message { + NotificationMessage::Text(text) => { + Text::new(text.to_owned(), theme.message.text.clone()).into_any() + } + NotificationMessage::Element(e) => e(theme.message.text.clone(), cx), + }; let on_click = self.on_click.clone(); let has_click_action = on_click.is_some(); @@ -262,8 +279,7 @@ pub mod simple_message_notification { .with_child( Flex::row() .with_child( - Text::new(message, theme.message.text.clone()) - .contained() + message.contained() .with_style(theme.message.container) .aligned() .top() diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 292ec28abc664335caa97d0402d62e3fbc6e5215..823c9c9294ef56c82c65df0c00f0ecde2f9f4e45 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,7 @@ use assets::Assets; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, TypedEnvelope, UserStore, ZED_APP_VERSION, + Client, TypedEnvelope, UserStore, }; use collections::{hash_map, HashMap, HashSet}; use drag_and_drop::DragAndDrop; @@ -60,7 +60,7 @@ use std::{ }; use crate::{ - notifications::simple_message_notification::MessageNotification, + notifications::{simple_message_notification::MessageNotification, NotificationTracker}, persistence::model::{ DockData, DockStructure, SerializedPane, SerializedPaneGroup, SerializedWorkspace, }, @@ -81,7 +81,7 @@ use serde::Deserialize; use shared_screen::SharedScreen; use status_bar::StatusBar; pub use status_bar::StatusItemView; -use theme::Theme; +use theme::{Theme, ThemeSettings}; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; use util::{async_iife, channel::ZedVersion, paths, ResultExt}; pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; @@ -3193,6 +3193,7 @@ async fn open_items( fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppContext) { const NEW_PANEL_BLOG_POST: &str = "https://zed.dev/blog/new-panel-system"; const NEW_DOCK_HINT_KEY: &str = "show_new_dock_key"; + const MESSAGE_ID: usize = 2; if workspace .read_with(cx, |workspace, cx| { @@ -3205,7 +3206,7 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo { return true; } - workspace.has_shown_notification_once::(2, cx) + workspace.has_shown_notification_once::(MESSAGE_ID, cx) }) .unwrap_or(false) { @@ -3218,6 +3219,24 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo .flatten() .is_some() { + if !workspace + .read_with(cx, |workspace, cx| { + workspace.has_shown_notification_once::(MESSAGE_ID, cx) + }) + .unwrap_or(false) + { + cx.update(|cx| { + cx.update_global::(|tracker, _| { + let entry = tracker + .entry(TypeId::of::()) + .or_default(); + if !entry.contains(&MESSAGE_ID) { + entry.push(MESSAGE_ID); + } + }); + }); + } + return; } @@ -3232,11 +3251,33 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo workspace .update(cx, |workspace, cx| { workspace.show_notification_once(2, cx, |cx| { + + cx.add_view(|_| { - MessageNotification::new( - "Looking for the dock? Try 'ctrl-`'!\n'shift-escape' now zooms your pane", - ) - .with_click_message("Click to read more about the new panel system") + MessageNotification::new_element(|text, _| { + Text::new( + "Looking for the dock? Try ctrl-`!\nshift-escape now zooms your pane.", + text, + ) + .with_custom_runs(vec![26..32, 34..46], |_, bounds, scene, cx| { + let code_span_background_color = settings::get::(cx) + .theme + .editor + .document_highlight_read_background; + + scene.push_quad(gpui::Quad { + bounds, + background: Some(code_span_background_color), + border: Default::default(), + corner_radius: 2.0, + }) + }) + .into_any() + }) + // MessageNotification::new_( + // "Looking for the dock? Try 'ctrl-`'!\n'shift-escape' now zooms your pane", + // ) + .with_click_message("Read more about the new panel system") .on_click(|cx| cx.platform().open_url(NEW_PANEL_BLOG_POST)) }) }) From ed0b9acb0a5d16b363b42efbf7f1e2b30a2b95e7 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:06:36 -0700 Subject: [PATCH 35/53] Add panic if version is 0.91 --- crates/workspace/src/notifications.rs | 11 +++++++---- crates/workspace/src/pane.rs | 1 - crates/workspace/src/workspace.rs | 14 ++------------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 1060227d4ace10dc429af586336b75b7db3d36c7..1e3c6044a1651101939453d2ee2e5c6b90df3564 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -163,9 +163,10 @@ pub mod simple_message_notification { use gpui::{ actions, elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text}, + fonts::TextStyle, impl_actions, platform::{CursorStyle, MouseButton}, - AnyElement, AppContext, Element, Entity, View, ViewContext, fonts::TextStyle, + AnyElement, AppContext, Element, Entity, View, ViewContext, }; use menu::Cancel; use serde::Deserialize; @@ -224,8 +225,9 @@ pub mod simple_message_notification { } } - pub fn new_element(message: fn(TextStyle, &AppContext) -> AnyElement) -> MessageNotification - { + pub fn new_element( + message: fn(TextStyle, &AppContext) -> AnyElement, + ) -> MessageNotification { Self { message: NotificationMessage::Element(message), on_click: None, @@ -279,7 +281,8 @@ pub mod simple_message_notification { .with_child( Flex::row() .with_child( - message.contained() + message + .contained() .with_style(theme.message.container) .aligned() .top() diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index fad8cd8864e1a55cec7d214201abb35eb60f9404..63602ffead64ae2429e3c626772dac35b9b2ef63 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -541,7 +541,6 @@ impl Pane { cx.spawn(|_, mut cx| async move { notify_of_new_dock(&workspace_handle, &mut cx) }) .detach(); - if self.zoomed { cx.emit(Event::ZoomOut); } else if !self.items.is_empty() { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 823c9c9294ef56c82c65df0c00f0ecde2f9f4e45..3690db60d070c1fd9df90d16cda1d4c62c66a803 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3198,13 +3198,8 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo if workspace .read_with(cx, |workspace, cx| { let version = cx.global::().0; - if !version.contains("0.88") - && !version.contains("0.89") - && !version.contains("0.90") - && !version.contains("0.91") - && !version.contains("0.92") - { - return true; + if version.contains("0.91") { + panic!("Please remove the dock key binding change notification"); } workspace.has_shown_notification_once::(MESSAGE_ID, cx) }) @@ -3251,8 +3246,6 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo workspace .update(cx, |workspace, cx| { workspace.show_notification_once(2, cx, |cx| { - - cx.add_view(|_| { MessageNotification::new_element(|text, _| { Text::new( @@ -3274,9 +3267,6 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo }) .into_any() }) - // MessageNotification::new_( - // "Looking for the dock? Try 'ctrl-`'!\n'shift-escape' now zooms your pane", - // ) .with_click_message("Read more about the new panel system") .on_click(|cx| cx.platform().open_url(NEW_PANEL_BLOG_POST)) }) From b875d4ed40eac05bf6007a6d9f08f64ca65c446f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:10:50 -0700 Subject: [PATCH 36/53] Remove silly panic --- crates/workspace/src/workspace.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 3690db60d070c1fd9df90d16cda1d4c62c66a803..73cc811e76402b5624afdb2e8ed27c89db355565 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3197,10 +3197,6 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo if workspace .read_with(cx, |workspace, cx| { - let version = cx.global::().0; - if version.contains("0.91") { - panic!("Please remove the dock key binding change notification"); - } workspace.has_shown_notification_once::(MESSAGE_ID, cx) }) .unwrap_or(false) From 705e36827c8e48dd0b2ccfb969806e41148ec935 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:16:37 -0700 Subject: [PATCH 37/53] add version check --- crates/util/src/channel.rs | 2 -- crates/workspace/src/workspace.rs | 12 ++++++++++-- crates/zed/src/main.rs | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/util/src/channel.rs b/crates/util/src/channel.rs index 2b45cb6b6611cb6a036f1cf61768fcd2f5dac184..274fd576a050076511c8c1253b7187fbd437e8c3 100644 --- a/crates/util/src/channel.rs +++ b/crates/util/src/channel.rs @@ -2,8 +2,6 @@ use std::env; use lazy_static::lazy_static; -pub struct ZedVersion(pub &'static str); - lazy_static! { pub static ref RELEASE_CHANNEL_NAME: String = if cfg!(debug_assertions) { env::var("ZED_RELEASE_CHANNEL") diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 73cc811e76402b5624afdb2e8ed27c89db355565..7033530f96e080b8422031439648819ccf8cc9ad 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,7 @@ use assets::Assets; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, TypedEnvelope, UserStore, + Client, TypedEnvelope, UserStore, ZED_APP_VERSION, }; use collections::{hash_map, HashMap, HashSet}; use drag_and_drop::DragAndDrop; @@ -83,7 +83,7 @@ use status_bar::StatusBar; pub use status_bar::StatusItemView; use theme::{Theme, ThemeSettings}; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; -use util::{async_iife, channel::ZedVersion, paths, ResultExt}; +use util::{async_iife, paths, ResultExt}; pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; lazy_static! { @@ -3197,6 +3197,14 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo if workspace .read_with(cx, |workspace, cx| { + let version = ZED_APP_VERSION + .or_else(|| cx.platform().app_version().ok()) + .map(|v| v.to_string()).unwrap_or_default(); + + if !version.contains("0.88") || !version.contains("0.89") || !version.contains("0.90") || !version.contains("0.91") { + return true; + } + workspace.has_shown_notification_once::(MESSAGE_ID, cx) }) .unwrap_or(false) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 558796807bedc4f8151faaa8cf0c6544ac5f5423..31f331ef93ef17eecb4870f3ed23c9f963a5b3aa 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -119,7 +119,6 @@ fn main() { app.run(move |cx| { cx.set_global(*RELEASE_CHANNEL); - cx.set_global(util::channel::ZedVersion(env!("CARGO_PKG_VERSION"))); #[cfg(debug_assertions)] cx.set_global(StaffMode(true)); From 45b42c512d50b96f49c9722793572a0b484b2305 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:17:27 -0700 Subject: [PATCH 38/53] fmt --- crates/workspace/src/workspace.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 7033530f96e080b8422031439648819ccf8cc9ad..c45cdf0c29ad9f103d11b0774891c86a7c62c54a 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3199,9 +3199,14 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo .read_with(cx, |workspace, cx| { let version = ZED_APP_VERSION .or_else(|| cx.platform().app_version().ok()) - .map(|v| v.to_string()).unwrap_or_default(); + .map(|v| v.to_string()) + .unwrap_or_default(); - if !version.contains("0.88") || !version.contains("0.89") || !version.contains("0.90") || !version.contains("0.91") { + if !version.contains("0.88") + || !version.contains("0.89") + || !version.contains("0.90") + || !version.contains("0.91") + { return true; } From 27ef0e2b524755515eab87d37898f6759f15e2d3 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:21:38 -0700 Subject: [PATCH 39/53] De-morgans properly --- crates/workspace/src/workspace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index c45cdf0c29ad9f103d11b0774891c86a7c62c54a..5d1bc2993daa05b4f6da3ec39713f2f4a69affd9 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3203,9 +3203,9 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo .unwrap_or_default(); if !version.contains("0.88") - || !version.contains("0.89") - || !version.contains("0.90") - || !version.contains("0.91") + && !version.contains("0.89") + && !version.contains("0.90") + && !version.contains("0.91") { return true; } From bf2016adf504637b168b3fca76d0e9fb955ea293 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 31 May 2023 14:22:49 -0700 Subject: [PATCH 40/53] Remove version check --- crates/workspace/src/workspace.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 5d1bc2993daa05b4f6da3ec39713f2f4a69affd9..91824f585551ce34f6e0f0ebaa2ea4aadb0d1918 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,7 @@ use assets::Assets; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, TypedEnvelope, UserStore, ZED_APP_VERSION, + Client, TypedEnvelope, UserStore, }; use collections::{hash_map, HashMap, HashSet}; use drag_and_drop::DragAndDrop; @@ -3197,19 +3197,6 @@ fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppCo if workspace .read_with(cx, |workspace, cx| { - let version = ZED_APP_VERSION - .or_else(|| cx.platform().app_version().ok()) - .map(|v| v.to_string()) - .unwrap_or_default(); - - if !version.contains("0.88") - && !version.contains("0.89") - && !version.contains("0.90") - && !version.contains("0.91") - { - return true; - } - workspace.has_shown_notification_once::(MESSAGE_ID, cx) }) .unwrap_or(false) From a2ab7c9eb95f4970b0c2222e4494c83e2cb2779b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 14:42:15 -0700 Subject: [PATCH 41/53] Respect project-specific settings for copilot --- crates/copilot/src/copilot.rs | 2 +- crates/copilot_button/src/copilot_button.rs | 32 +++++++++++-------- crates/editor/src/editor.rs | 15 +++++---- crates/language/src/language_settings.rs | 10 ++++-- crates/project/src/project.rs | 35 +++++++++++---------- crates/project/src/worktree.rs | 2 +- 6 files changed, 56 insertions(+), 40 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 88b0aebd17127765535db8bf8966dd630e95b851..108422264810c27603f937072caf44cc07b5cb49 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -318,7 +318,7 @@ impl Copilot { fn enable_or_disable_copilot(&mut self, cx: &mut ModelContext) { let http = self.http.clone(); let node_runtime = self.node_runtime.clone(); - if all_language_settings(cx).copilot_enabled(None, None) { + if all_language_settings(None, cx).copilot_enabled(None, None) { if matches!(self.server, CopilotServer::Disabled) { let start_task = cx .spawn({ diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 686b3d2dfb3dc222433166f3aeed20f5d869be33..4cb7c15bd94623c1223f2dc64582e80962a82b3a 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -9,7 +9,10 @@ use gpui::{ AnyElement, AppContext, AsyncAppContext, Element, Entity, MouseState, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; -use language::language_settings::{self, all_language_settings, AllLanguageSettings}; +use language::{ + language_settings::{self, all_language_settings, AllLanguageSettings}, + File, +}; use settings::{update_settings_file, SettingsStore}; use std::{path::Path, sync::Arc}; use util::{paths, ResultExt}; @@ -27,7 +30,7 @@ pub struct CopilotButton { editor_subscription: Option<(Subscription, usize)>, editor_enabled: Option, language: Option>, - path: Option>, + file: Option>, fs: Arc, } @@ -41,7 +44,7 @@ impl View for CopilotButton { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let all_language_settings = &all_language_settings(cx); + let all_language_settings = all_language_settings(None, cx); if !all_language_settings.copilot.feature_enabled { return Empty::new().into_any(); } @@ -165,7 +168,7 @@ impl CopilotButton { editor_subscription: None, editor_enabled: None, language: None, - path: None, + file: None, fs, } } @@ -212,9 +215,9 @@ impl CopilotButton { let settings = settings::get::(cx); - if let Some(path) = self.path.as_ref() { - let path_enabled = settings.copilot_enabled_for_path(path); - let path = path.clone(); + if let Some(file) = &self.file { + let path = file.path().clone(); + let path_enabled = settings.copilot_enabled_for_path(&path); menu_options.push(ContextMenuItem::handler( format!( "{} Suggestions for This Path", @@ -279,14 +282,16 @@ impl CopilotButton { let language_name = snapshot .language_at(suggestion_anchor) .map(|language| language.name()); - let path = snapshot.file_at(suggestion_anchor).map(|file| file.path()); + let file = snapshot.file_at(suggestion_anchor).cloned(); self.editor_enabled = Some( - all_language_settings(cx) - .copilot_enabled(language_name.as_deref(), path.map(|p| p.as_ref())), + all_language_settings(self.file.as_ref().map(|f| f.as_ref()), cx).copilot_enabled( + language_name.as_deref(), + file.as_ref().map(|file| file.path().as_ref()), + ), ); self.language = language_name; - self.path = path.cloned(); + self.file = file; cx.notify() } @@ -363,14 +368,15 @@ async fn configure_disabled_globs( } fn toggle_copilot_globally(fs: Arc, cx: &mut AppContext) { - let show_copilot_suggestions = all_language_settings(cx).copilot_enabled(None, None); + let show_copilot_suggestions = all_language_settings(None, cx).copilot_enabled(None, None); update_settings_file::(fs, cx, move |file| { file.defaults.show_copilot_suggestions = Some((!show_copilot_suggestions).into()) }); } fn toggle_copilot_for_language(language: Arc, fs: Arc, cx: &mut AppContext) { - let show_copilot_suggestions = all_language_settings(cx).copilot_enabled(Some(&language), None); + let show_copilot_suggestions = + all_language_settings(None, cx).copilot_enabled(Some(&language), None); update_settings_file::(fs, cx, move |file| { file.languages .entry(language) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f5d109e15bd2138fba6914e058b575a5bdf42e80..4a9237f5632ef73da74b97c68fa45da6f07b4626 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3207,12 +3207,12 @@ impl Editor { snapshot: &MultiBufferSnapshot, cx: &mut ViewContext, ) -> bool { - let path = snapshot.file_at(location).map(|file| file.path().as_ref()); + let file = snapshot.file_at(location); let language_name = snapshot .language_at(location) .map(|language| language.name()); - let settings = all_language_settings(cx); - settings.copilot_enabled(language_name.as_deref(), path) + let settings = all_language_settings(file.map(|f| f.as_ref() as _), cx); + settings.copilot_enabled(language_name.as_deref(), file.map(|f| f.path().as_ref())) } fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool { @@ -7076,11 +7076,13 @@ impl Editor { }; // If None, we are in a file without an extension - let file_extension = file_extension.or(self + let file = self .buffer .read(cx) .as_singleton() - .and_then(|b| b.read(cx).file()) + .and_then(|b| b.read(cx).file()); + let file_extension = file_extension.or(file + .as_ref() .and_then(|file| Path::new(file.file_name(cx)).extension()) .and_then(|e| e.to_str()) .map(|a| a.to_string())); @@ -7091,7 +7093,8 @@ impl Editor { .get("vim_mode") == Some(&serde_json::Value::Bool(true)); let telemetry_settings = *settings::get::(cx); - let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None); + let copilot_enabled = + all_language_settings(file.map(|f| f.as_ref()), cx).copilot_enabled(None, None); let copilot_enabled_for_language = self .buffer .read(cx) diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 70aaca03c408ab0a9995fee88f54144f4ab997d9..e4e283bd7e6743cc17bf858f1e3f6d9964946eeb 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -26,8 +26,14 @@ pub fn language_settings<'a>( .language(language) } -pub fn all_language_settings<'a>(cx: &'a AppContext) -> &'a AllLanguageSettings { - settings::get::(cx) +pub fn all_language_settings<'a>( + file: Option<&dyn File>, + cx: &'a AppContext, +) -> &'a AllLanguageSettings { + settings::get_local::( + file.map(|f| (f.worktree_id(), f.path().as_ref())), + cx, + ) } #[derive(Debug, Clone)] diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3cc4a181c55ad18315204c780aa6c6a6da337666..c871bf0b96ce05394af514a50e57dba8ba9e71f8 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -28,7 +28,7 @@ use gpui::{ ModelHandle, Task, WeakModelHandle, }; use language::{ - language_settings::{all_language_settings, language_settings, FormatOnSave, Formatter}, + language_settings::{language_settings, FormatOnSave, Formatter}, point_to_lsp, proto::{ deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version, @@ -689,18 +689,15 @@ impl Project { } fn on_settings_changed(&mut self, cx: &mut ModelContext) { - let settings = all_language_settings(cx); - let mut language_servers_to_start = Vec::new(); for buffer in self.opened_buffers.values() { if let Some(buffer) = buffer.upgrade(cx) { let buffer = buffer.read(cx); if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) { - if settings - .language(Some(&language.name())) - .enable_language_server - { + let settings = + language_settings(Some(language.name().as_ref()), Some(file), cx); + if settings.enable_language_server { language_servers_to_start.push((file.worktree.clone(), language.clone())); } } @@ -708,18 +705,22 @@ impl Project { } let mut language_servers_to_stop = Vec::new(); - for language in self.languages.to_vec() { - for lsp_adapter in language.lsp_adapters() { - if !settings - .language(Some(&language.name())) + let languages = self.languages.to_vec(); + for (worktree_id, started_lsp_name) in self.language_server_ids.keys() { + let language = languages.iter().find(|l| { + l.lsp_adapters() + .iter() + .any(|adapter| &adapter.name == started_lsp_name) + }); + if let Some(language) = language { + let worktree = self.worktree_for_id(*worktree_id, cx); + let file = worktree.and_then(|tree| tree.update(cx, |tree, cx| tree.root_file(cx))); + // let settings = + // language_settings(Some(language.name().as_ref()), Some(file), cx); + if !language_settings(Some(&language.name()), file.as_ref().map(|f| f as _), cx) .enable_language_server { - let lsp_name = &lsp_adapter.name; - for (worktree_id, started_lsp_name) in self.language_server_ids.keys() { - if lsp_name == started_lsp_name { - language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); - } - } + language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); } } } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7432eb8d40b5ce7da02b3fb06c007aaa74de1730..5d121adc63c39fa433bdebeea5fb4fddf06f52b6 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -679,7 +679,7 @@ impl Worktree { } pub fn root_file(&self, cx: &mut ModelContext) -> Option { - let entry = self.entry_for_path("")?; + let entry = self.root_entry()?; Some(File { worktree: cx.handle(), path: entry.path.clone(), From 38078b93cc1361b58ef4529058ab3e62cc2dc3d3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 14:44:48 -0700 Subject: [PATCH 42/53] v0.90.x dev --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3751b34d3156da64fc0efea74e707fc9222bb324..2b340cf46a917f4faf0f820fb67123a3ceca3877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8777,7 +8777,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.89.0" +version = "0.90.0" dependencies = [ "activity_indicator", "ai", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index e96dff122186cb07e17eff54ff909d36c1454731..c45991cf11fc7a8ed9e654781d6d144a1d6795d5 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.89.0" +version = "0.90.0" publish = false [lib] From 03a351fb26a454c1dbd8eec93a4a05f50f4768e0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 14:57:04 -0700 Subject: [PATCH 43/53] Make language settings accessors take an arc dyn file --- crates/copilot/src/copilot.rs | 2 +- crates/copilot_button/src/copilot_button.rs | 2 +- crates/editor/src/editor.rs | 5 ++-- crates/editor/src/multi_buffer.rs | 4 +-- crates/language/src/buffer.rs | 8 ++---- crates/language/src/language_settings.rs | 4 +-- crates/project/src/lsp_command.rs | 3 +-- crates/project/src/project.rs | 30 +++++++++------------ crates/project/src/project_tests.rs | 20 ++++++++------ crates/project/src/worktree.rs | 17 ++++-------- 10 files changed, 41 insertions(+), 54 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 108422264810c27603f937072caf44cc07b5cb49..9343bd33f6092fb289609c956f7104b99baecfeb 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -787,7 +787,7 @@ impl Copilot { let position = position.to_point_utf16(buffer); let settings = language_settings( buffer.language_at(position).map(|l| l.name()).as_deref(), - buffer.file().map(|f| f.as_ref()), + buffer.file(), cx, ); let tab_size = settings.tab_size; diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 4cb7c15bd94623c1223f2dc64582e80962a82b3a..27fd2dcb7c63b596fce54b0a353d3f4c3d138437 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -285,7 +285,7 @@ impl CopilotButton { let file = snapshot.file_at(suggestion_anchor).cloned(); self.editor_enabled = Some( - all_language_settings(self.file.as_ref().map(|f| f.as_ref()), cx).copilot_enabled( + all_language_settings(self.file.as_ref(), cx).copilot_enabled( language_name.as_deref(), file.as_ref().map(|file| file.path().as_ref()), ), diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4a9237f5632ef73da74b97c68fa45da6f07b4626..1b62192999f480f427d880abb12347a60203545f 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3211,7 +3211,7 @@ impl Editor { let language_name = snapshot .language_at(location) .map(|language| language.name()); - let settings = all_language_settings(file.map(|f| f.as_ref() as _), cx); + let settings = all_language_settings(file, cx); settings.copilot_enabled(language_name.as_deref(), file.map(|f| f.path().as_ref())) } @@ -7093,8 +7093,7 @@ impl Editor { .get("vim_mode") == Some(&serde_json::Value::Bool(true)); let telemetry_settings = *settings::get::(cx); - let copilot_enabled = - all_language_settings(file.map(|f| f.as_ref()), cx).copilot_enabled(None, None); + let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None); let copilot_enabled_for_language = self .buffer .read(cx) diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 597feb832b07c80ed33bdf578377c720c16a393e..1cf30a1676bc46f1ba08d4b3597eb1b9425958b3 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1382,7 +1382,7 @@ impl MultiBuffer { if let Some((buffer, offset)) = self.point_to_buffer_offset(point, cx) { let buffer = buffer.read(cx); language = buffer.language_at(offset).map(|l| l.name()); - file = buffer.file().map(|f| f.as_ref()); + file = buffer.file(); } language_settings(language.as_deref(), file, cx) } @@ -2795,7 +2795,7 @@ impl MultiBufferSnapshot { let mut file = None; if let Some((buffer, offset)) = self.point_to_buffer_offset(point) { language = buffer.language_at(offset).map(|l| l.name()); - file = buffer.file().map(|f| f.as_ref()); + file = buffer.file(); } language_settings(language.as_deref(), file, cx) } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index ddec085e2a622ca84190c5acec9c891512a80b2f..90a86d065cc448e13eff3c231680ab44e21a3473 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1808,11 +1808,7 @@ impl BufferSnapshot { pub fn language_indent_size_at(&self, position: T, cx: &AppContext) -> IndentSize { let language_name = self.language_at(position).map(|language| language.name()); - let settings = language_settings( - language_name.as_deref(), - self.file().map(|f| f.as_ref()), - cx, - ); + let settings = language_settings(language_name.as_deref(), self.file(), cx); if settings.hard_tabs { IndentSize::tab() } else { @@ -2139,7 +2135,7 @@ impl BufferSnapshot { let language = self.language_at(position); language_settings( language.map(|l| l.name()).as_deref(), - self.file.as_ref().map(AsRef::as_ref), + self.file.as_ref(), cx, ) } diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index e4e283bd7e6743cc17bf858f1e3f6d9964946eeb..31d819b4493046c83c0cd05147df1252187066d3 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -16,7 +16,7 @@ pub fn init(cx: &mut AppContext) { pub fn language_settings<'a>( language: Option<&str>, - file: Option<&dyn File>, + file: Option<&Arc>, cx: &'a AppContext, ) -> &'a LanguageSettings { settings::get_local::( @@ -27,7 +27,7 @@ pub fn language_settings<'a>( } pub fn all_language_settings<'a>( - file: Option<&dyn File>, + file: Option<&Arc>, cx: &'a AppContext, ) -> &'a AllLanguageSettings { settings::get_local::( diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 0a8b5f8a2e52f6a33e14bd5bc4a01ebe3dba7601..f34956653509488c2d9e4a147dbdba3a836480cd 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1717,8 +1717,7 @@ impl LspCommand for OnTypeFormatting { let tab_size = buffer.read_with(&cx, |buffer, cx| { let language_name = buffer.language().map(|language| language.name()); - let file = buffer.file().map(|f| f.as_ref()); - language_settings(language_name.as_deref(), file, cx).tab_size + language_settings(language_name.as_deref(), buffer.file(), cx).tab_size }); Ok(Self { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c871bf0b96ce05394af514a50e57dba8ba9e71f8..a106632e3662521cbbc17bf55fe9c933c405ecfd 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -693,12 +693,14 @@ impl Project { for buffer in self.opened_buffers.values() { if let Some(buffer) = buffer.upgrade(cx) { let buffer = buffer.read(cx); - if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) - { + if let Some((file, language)) = buffer.file().zip(buffer.language()) { let settings = language_settings(Some(language.name().as_ref()), Some(file), cx); if settings.enable_language_server { - language_servers_to_start.push((file.worktree.clone(), language.clone())); + if let Some(file) = File::from_dyn(Some(file)) { + language_servers_to_start + .push((file.worktree.clone(), language.clone())); + } } } } @@ -714,10 +716,10 @@ impl Project { }); if let Some(language) = language { let worktree = self.worktree_for_id(*worktree_id, cx); - let file = worktree.and_then(|tree| tree.update(cx, |tree, cx| tree.root_file(cx))); - // let settings = - // language_settings(Some(language.name().as_ref()), Some(file), cx); - if !language_settings(Some(&language.name()), file.as_ref().map(|f| f as _), cx) + let file = worktree.and_then(|tree| { + tree.update(cx, |tree, cx| tree.root_file(cx).map(|f| f as _)) + }); + if !language_settings(Some(&language.name()), file.as_ref(), cx) .enable_language_server { language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); @@ -2362,8 +2364,8 @@ impl Project { Some(&language.name()), worktree .update(cx, |tree, cx| tree.root_file(cx)) - .as_ref() - .map(|f| f as _), + .map(|f| f as _) + .as_ref(), cx, ) .enable_language_server @@ -3464,12 +3466,7 @@ impl Project { for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers { let settings = buffer.read_with(&cx, |buffer, cx| { let language_name = buffer.language().map(|language| language.name()); - language_settings( - language_name.as_deref(), - buffer.file().map(|f| f.as_ref()), - cx, - ) - .clone() + language_settings(language_name.as_deref(), buffer.file(), cx).clone() }); let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save; @@ -4481,10 +4478,9 @@ impl Project { let (position, tab_size) = buffer.read_with(cx, |buffer, cx| { let position = position.to_point_utf16(buffer); let language_name = buffer.language_at(position).map(|l| l.name()); - let file = buffer.file().map(|f| f.as_ref()); ( position, - language_settings(language_name.as_deref(), file, cx).tab_size, + language_settings(language_name.as_deref(), buffer.file(), cx).tab_size, ) }); self.request_lsp( diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 577b22d7309e3afeba8ae1f5a5ccb376c5aeeffb..ee6752412dbb9e2b68fbae69f736826f833fd104 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -99,18 +99,22 @@ async fn test_managing_project_specific_settings( let settings_a = language_settings( None, - Some(&File::for_entry( - tree.entry_for_path("a/a.rs").unwrap().clone(), - worktree.clone(), - )), + Some( + &(File::for_entry( + tree.entry_for_path("a/a.rs").unwrap().clone(), + worktree.clone(), + ) as _), + ), cx, ); let settings_b = language_settings( None, - Some(&File::for_entry( - tree.entry_for_path("b/b.rs").unwrap().clone(), - worktree.clone(), - )), + Some( + &(File::for_entry( + tree.entry_for_path("b/b.rs").unwrap().clone(), + worktree.clone(), + ) as _), + ), cx, ); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 5d121adc63c39fa433bdebeea5fb4fddf06f52b6..a33a0fc050177db96dfbb56a901331bb6928e5ff 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -678,16 +678,9 @@ impl Worktree { } } - pub fn root_file(&self, cx: &mut ModelContext) -> Option { + pub fn root_file(&self, cx: &mut ModelContext) -> Option> { let entry = self.root_entry()?; - Some(File { - worktree: cx.handle(), - path: entry.path.clone(), - mtime: entry.mtime, - entry_id: entry.id, - is_local: self.is_local(), - is_deleted: false, - }) + Some(File::for_entry(entry.clone(), cx.handle())) } } @@ -2463,15 +2456,15 @@ impl language::LocalFile for File { } impl File { - pub fn for_entry(entry: Entry, worktree: ModelHandle) -> Self { - Self { + pub fn for_entry(entry: Entry, worktree: ModelHandle) -> Arc { + Arc::new(Self { worktree, path: entry.path.clone(), mtime: entry.mtime, entry_id: entry.id, is_local: true, is_deleted: false, - } + }) } pub fn from_proto( From 0dd7694ff531a5ae049fd754ddef5787a2a76e11 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 15:10:30 -0700 Subject: [PATCH 44/53] Make language_settings take a language, not a language name --- crates/copilot/src/copilot.rs | 6 +---- crates/copilot_button/src/copilot_button.rs | 27 +++++++++------------ crates/editor/src/display_map.rs | 7 +++--- crates/editor/src/editor.rs | 6 ++--- crates/editor/src/multi_buffer.rs | 8 +++--- crates/language/src/buffer.rs | 10 ++------ crates/language/src/language_settings.rs | 11 +++++---- crates/project/src/lsp_command.rs | 3 +-- crates/project/src/project.rs | 16 +++++------- crates/zed/src/languages/yaml.rs | 7 ++++-- 10 files changed, 41 insertions(+), 60 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 9343bd33f6092fb289609c956f7104b99baecfeb..7834603552fa14a36d81109c2a8030a8fef4efee 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -785,11 +785,7 @@ impl Copilot { let buffer = buffer.read(cx); let uri = registered_buffer.uri.clone(); let position = position.to_point_utf16(buffer); - let settings = language_settings( - buffer.language_at(position).map(|l| l.name()).as_deref(), - buffer.file(), - cx, - ); + let settings = language_settings(buffer.language_at(position).as_ref(), buffer.file(), cx); let tab_size = settings.tab_size; let hard_tabs = settings.hard_tabs; let relative_path = buffer diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 27fd2dcb7c63b596fce54b0a353d3f4c3d138437..e34fddd9b9c5f200bf5bb24120089208bba05a3e 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -11,7 +11,7 @@ use gpui::{ }; use language::{ language_settings::{self, all_language_settings, AllLanguageSettings}, - File, + File, Language, }; use settings::{update_settings_file, SettingsStore}; use std::{path::Path, sync::Arc}; @@ -29,7 +29,7 @@ pub struct CopilotButton { popup_menu: ViewHandle, editor_subscription: Option<(Subscription, usize)>, editor_enabled: Option, - language: Option>, + language: Option>, file: Option>, fs: Arc, } @@ -200,14 +200,13 @@ impl CopilotButton { if let Some(language) = self.language.clone() { let fs = fs.clone(); - let language_enabled = - language_settings::language_settings(Some(language.as_ref()), None, cx) - .show_copilot_suggestions; + let language_enabled = language_settings::language_settings(Some(&language), None, cx) + .show_copilot_suggestions; menu_options.push(ContextMenuItem::handler( format!( "{} Suggestions for {}", if language_enabled { "Hide" } else { "Show" }, - language + language.name() ), move |cx| toggle_copilot_for_language(language.clone(), fs.clone(), cx), )); @@ -279,18 +278,14 @@ impl CopilotButton { let editor = editor.read(cx); let snapshot = editor.buffer().read(cx).snapshot(cx); let suggestion_anchor = editor.selections.newest_anchor().start; - let language_name = snapshot - .language_at(suggestion_anchor) - .map(|language| language.name()); + let language = snapshot.language_at(suggestion_anchor); let file = snapshot.file_at(suggestion_anchor).cloned(); self.editor_enabled = Some( - all_language_settings(self.file.as_ref(), cx).copilot_enabled( - language_name.as_deref(), - file.as_ref().map(|file| file.path().as_ref()), - ), + all_language_settings(self.file.as_ref(), cx) + .copilot_enabled(language, file.as_ref().map(|file| file.path().as_ref())), ); - self.language = language_name; + self.language = language.cloned(); self.file = file; cx.notify() @@ -374,12 +369,12 @@ fn toggle_copilot_globally(fs: Arc, cx: &mut AppContext) { }); } -fn toggle_copilot_for_language(language: Arc, fs: Arc, cx: &mut AppContext) { +fn toggle_copilot_for_language(language: Arc, fs: Arc, cx: &mut AppContext) { let show_copilot_suggestions = all_language_settings(None, cx).copilot_enabled(Some(&language), None); update_settings_file::(fs, cx, move |file| { file.languages - .entry(language) + .entry(language.name()) .or_default() .show_copilot_suggestions = Some(!show_copilot_suggestions); }); diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index f8d6f0bc406a497f13e36f320ed461aff1ddec60..b0483db68dcb781619188791b3f9b3630e902584 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -272,12 +272,11 @@ impl DisplayMap { } fn tab_size(buffer: &ModelHandle, cx: &mut ModelContext) -> NonZeroU32 { - let language_name = buffer + let language = buffer .read(cx) .as_singleton() - .and_then(|buffer| buffer.read(cx).language()) - .map(|language| language.name()); - language_settings(language_name.as_deref(), None, cx).tab_size + .and_then(|buffer| buffer.read(cx).language()); + language_settings(language.as_deref(), None, cx).tab_size } #[cfg(test)] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1b62192999f480f427d880abb12347a60203545f..9a9f36c577a1712a6e999d418761079edc07dc8d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3208,11 +3208,9 @@ impl Editor { cx: &mut ViewContext, ) -> bool { let file = snapshot.file_at(location); - let language_name = snapshot - .language_at(location) - .map(|language| language.name()); + let language = snapshot.language_at(location); let settings = all_language_settings(file, cx); - settings.copilot_enabled(language_name.as_deref(), file.map(|f| f.path().as_ref())) + settings.copilot_enabled(language, file.map(|f| f.path().as_ref())) } fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool { diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 1cf30a1676bc46f1ba08d4b3597eb1b9425958b3..b7b2b89c8ca312667bfb3b5988da8292fd33c6bc 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1381,10 +1381,10 @@ impl MultiBuffer { let mut file = None; if let Some((buffer, offset)) = self.point_to_buffer_offset(point, cx) { let buffer = buffer.read(cx); - language = buffer.language_at(offset).map(|l| l.name()); + language = buffer.language_at(offset); file = buffer.file(); } - language_settings(language.as_deref(), file, cx) + language_settings(language.as_ref(), file, cx) } pub fn for_each_buffer(&self, mut f: impl FnMut(&ModelHandle)) { @@ -2794,10 +2794,10 @@ impl MultiBufferSnapshot { let mut language = None; let mut file = None; if let Some((buffer, offset)) = self.point_to_buffer_offset(point) { - language = buffer.language_at(offset).map(|l| l.name()); + language = buffer.language_at(offset); file = buffer.file(); } - language_settings(language.as_deref(), file, cx) + language_settings(language, file, cx) } pub fn language_scope_at<'a, T: ToOffset>(&'a self, point: T) -> Option { diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 90a86d065cc448e13eff3c231680ab44e21a3473..7acb36a92f8f87ed7f0d18b093a5cefe7068f6b1 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1807,8 +1807,7 @@ impl BufferSnapshot { } pub fn language_indent_size_at(&self, position: T, cx: &AppContext) -> IndentSize { - let language_name = self.language_at(position).map(|language| language.name()); - let settings = language_settings(language_name.as_deref(), self.file(), cx); + let settings = language_settings(self.language_at(position), self.file(), cx); if settings.hard_tabs { IndentSize::tab() } else { @@ -2132,12 +2131,7 @@ impl BufferSnapshot { position: D, cx: &'a AppContext, ) -> &'a LanguageSettings { - let language = self.language_at(position); - language_settings( - language.map(|l| l.name()).as_deref(), - self.file.as_ref(), - cx, - ) + language_settings(self.language_at(position), self.file.as_ref(), cx) } pub fn language_scope_at(&self, position: D) -> Option { diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 31d819b4493046c83c0cd05147df1252187066d3..b03dd6a6b9f363ab7c70a94aca0501b0ec54638f 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -1,4 +1,4 @@ -use crate::File; +use crate::{File, Language}; use anyhow::Result; use collections::HashMap; use globset::GlobMatcher; @@ -15,7 +15,7 @@ pub fn init(cx: &mut AppContext) { } pub fn language_settings<'a>( - language: Option<&str>, + language: Option<&Arc>, file: Option<&Arc>, cx: &'a AppContext, ) -> &'a LanguageSettings { @@ -23,7 +23,7 @@ pub fn language_settings<'a>( file.map(|f| (f.worktree_id(), f.path().as_ref())), cx, ) - .language(language) + .language(language.map(|l| l.name()).as_deref()) } pub fn all_language_settings<'a>( @@ -170,7 +170,7 @@ impl AllLanguageSettings { .any(|glob| glob.is_match(path)) } - pub fn copilot_enabled(&self, language_name: Option<&str>, path: Option<&Path>) -> bool { + pub fn copilot_enabled(&self, language: Option<&Arc>, path: Option<&Path>) -> bool { if !self.copilot.feature_enabled { return false; } @@ -181,7 +181,8 @@ impl AllLanguageSettings { } } - self.language(language_name).show_copilot_suggestions + self.language(language.map(|l| l.name()).as_deref()) + .show_copilot_suggestions } } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index f34956653509488c2d9e4a147dbdba3a836480cd..7dab8eff30770cec4fc16bce9d1f1418b892fbc8 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1716,8 +1716,7 @@ impl LspCommand for OnTypeFormatting { .await?; let tab_size = buffer.read_with(&cx, |buffer, cx| { - let language_name = buffer.language().map(|language| language.name()); - language_settings(language_name.as_deref(), buffer.file(), cx).tab_size + language_settings(buffer.language(), buffer.file(), cx).tab_size }); Ok(Self { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a106632e3662521cbbc17bf55fe9c933c405ecfd..bec43385961647a92f530828e607f32876d673d0 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -694,8 +694,7 @@ impl Project { if let Some(buffer) = buffer.upgrade(cx) { let buffer = buffer.read(cx); if let Some((file, language)) = buffer.file().zip(buffer.language()) { - let settings = - language_settings(Some(language.name().as_ref()), Some(file), cx); + let settings = language_settings(Some(language), Some(file), cx); if settings.enable_language_server { if let Some(file) = File::from_dyn(Some(file)) { language_servers_to_start @@ -719,9 +718,7 @@ impl Project { let file = worktree.and_then(|tree| { tree.update(cx, |tree, cx| tree.root_file(cx).map(|f| f as _)) }); - if !language_settings(Some(&language.name()), file.as_ref(), cx) - .enable_language_server - { + if !language_settings(Some(language), file.as_ref(), cx).enable_language_server { language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); } } @@ -2361,7 +2358,7 @@ impl Project { cx: &mut ModelContext, ) { if !language_settings( - Some(&language.name()), + Some(&language), worktree .update(cx, |tree, cx| tree.root_file(cx)) .map(|f| f as _) @@ -3465,8 +3462,7 @@ impl Project { let mut project_transaction = ProjectTransaction::default(); for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers { let settings = buffer.read_with(&cx, |buffer, cx| { - let language_name = buffer.language().map(|language| language.name()); - language_settings(language_name.as_deref(), buffer.file(), cx).clone() + language_settings(buffer.language(), buffer.file(), cx).clone() }); let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save; @@ -4477,10 +4473,10 @@ impl Project { ) -> Task>> { let (position, tab_size) = buffer.read_with(cx, |buffer, cx| { let position = position.to_point_utf16(buffer); - let language_name = buffer.language_at(position).map(|l| l.name()); ( position, - language_settings(language_name.as_deref(), buffer.file(), cx).tab_size, + language_settings(buffer.language_at(position).as_ref(), buffer.file(), cx) + .tab_size, ) }); self.request_lsp( diff --git a/crates/zed/src/languages/yaml.rs b/crates/zed/src/languages/yaml.rs index d66602ee04cb58da09d8b037020cb1fb483937fa..7f87a7caedb764588a698b5e863fbd418c3859ed 100644 --- a/crates/zed/src/languages/yaml.rs +++ b/crates/zed/src/languages/yaml.rs @@ -3,7 +3,7 @@ use async_trait::async_trait; use futures::{future::BoxFuture, FutureExt, StreamExt}; use gpui::AppContext; use language::{ - language_settings::language_settings, LanguageServerBinary, LanguageServerName, LspAdapter, + language_settings::all_language_settings, LanguageServerBinary, LanguageServerName, LspAdapter, }; use node_runtime::NodeRuntime; use serde_json::Value; @@ -101,13 +101,16 @@ impl LspAdapter for YamlLspAdapter { } fn workspace_configuration(&self, cx: &mut AppContext) -> Option> { + let tab_size = all_language_settings(None, cx) + .language(Some("YAML")) + .tab_size; Some( future::ready(serde_json::json!({ "yaml": { "keyOrdering": false }, "[yaml]": { - "editor.tabSize": language_settings(Some("YAML"), None, cx).tab_size, + "editor.tabSize": tab_size, } })) .boxed(), From 0d281c1b89531547879e666320728a47336b47a9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 15:13:01 -0700 Subject: [PATCH 45/53] :art: --- crates/language/src/language_settings.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index b03dd6a6b9f363ab7c70a94aca0501b0ec54638f..332e789b4d7e364ab24c382a4daa9928291967cd 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -19,21 +19,16 @@ pub fn language_settings<'a>( file: Option<&Arc>, cx: &'a AppContext, ) -> &'a LanguageSettings { - settings::get_local::( - file.map(|f| (f.worktree_id(), f.path().as_ref())), - cx, - ) - .language(language.map(|l| l.name()).as_deref()) + let language_name = language.map(|l| l.name()); + all_language_settings(file, cx).language(language_name.as_deref()) } pub fn all_language_settings<'a>( file: Option<&Arc>, cx: &'a AppContext, ) -> &'a AllLanguageSettings { - settings::get_local::( - file.map(|f| (f.worktree_id(), f.path().as_ref())), - cx, - ) + let location = file.map(|f| (f.worktree_id(), f.path().as_ref())); + settings::get_local(location, cx) } #[derive(Debug, Clone)] From ae7606ce21d089ab10b751fc1a44720fe1592841 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 15:38:26 -0700 Subject: [PATCH 46/53] collab 0.12.5 --- Cargo.lock | 2 +- crates/collab/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b340cf46a917f4faf0f820fb67123a3ceca3877..07a859b058692c2ba7571f75b7cc9a9dd31374cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1246,7 +1246,7 @@ dependencies = [ [[package]] name = "collab" -version = "0.12.4" +version = "0.12.5" dependencies = [ "anyhow", "async-tungstenite", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index cd06b9a70a253eb9668d2704880638c1eeabaaba..07d2cdc60a6439a96a1a93bd9d212e0207bb59ac 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] default-run = "collab" edition = "2021" name = "collab" -version = "0.12.4" +version = "0.12.5" publish = false [[bin]] From d8ce333cf8e347e25e9af9aca3a918e57da9c8af Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 1 Jun 2023 16:51:29 +0300 Subject: [PATCH 47/53] Remove wrong assertion --- crates/workspace/src/workspace.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 364c3cadaf6a3785b8c2cd32295629236c6bcd75..21feea2b4086433eb1b1e0c31788ce78d16464f4 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -974,9 +974,8 @@ impl Workspace { let timestamp = entry.timestamp; match history.entry(project_path) { hash_map::Entry::Occupied(mut entry) => { - let (old_fs_path, old_timestamp) = entry.get(); + let (_, old_timestamp) = entry.get(); if ×tamp > old_timestamp { - assert_eq!(&fs_path, old_fs_path, "Inconsistent nav history"); entry.insert((fs_path, timestamp)); } } From 51c82da8401219cbf8e7487bfd8fd381ca88082c Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 1 Jun 2023 12:04:45 -0400 Subject: [PATCH 48/53] Avoid blocking forever on startup if config files do not exist The files will still get created if the user opens their settings and saves, otherwise everything will transparently work Co-Authored-By: Antonio Scandurra Co-Authored-By: Max Brunsfeld --- crates/settings/src/settings_file.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 4c98dca51a4e661126843b28615e1cdb8a53accc..3505330eda6fb94cc4ded9d90f313c40a11e7866 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -66,15 +66,22 @@ pub fn watch_config_file( .spawn(async move { let events = fs.watch(&path, Duration::from_millis(100)).await; futures::pin_mut!(events); + + let contents = fs.load(&path).await.unwrap_or_default(); + if tx.unbounded_send(contents).is_err() { + return; + } + loop { + if events.next().await.is_none() { + break; + } + if let Ok(contents) = fs.load(&path).await { if !tx.unbounded_send(contents).is_ok() { break; } } - if events.next().await.is_none() { - break; - } } }) .detach(); From 2390815d67a5b30763a7e3a1fa3f53836347e6ef Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 1 Jun 2023 10:09:04 -0700 Subject: [PATCH 49/53] Make settings store handle no user settings co-authored-by: max --- crates/settings/src/settings_store.rs | 191 +++++++++++++------------- 1 file changed, 96 insertions(+), 95 deletions(-) diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index bb51fd1ed004911415abc292efc70c33f666685d..3fdb81dd45cfee2671314ecc902cb38958841579 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{anyhow, Result}; use collections::{btree_map, hash_map, BTreeMap, HashMap}; use gpui::AppContext; use lazy_static::lazy_static; @@ -84,15 +84,26 @@ pub struct SettingsJsonSchemaParams<'a> { } /// A set of strongly-typed setting values defined via multiple JSON files. -#[derive(Default)] pub struct SettingsStore { setting_values: HashMap>, - default_deserialized_settings: Option, - user_deserialized_settings: Option, + default_deserialized_settings: serde_json::Value, + user_deserialized_settings: serde_json::Value, local_deserialized_settings: BTreeMap<(usize, Arc), serde_json::Value>, tab_size_callback: Option<(TypeId, Box Option>)>, } +impl Default for SettingsStore { + fn default() -> Self { + SettingsStore { + setting_values: Default::default(), + default_deserialized_settings: serde_json::json!({}), + user_deserialized_settings: serde_json::json!({}), + local_deserialized_settings: Default::default(), + tab_size_callback: Default::default(), + } + } +} + #[derive(Debug)] struct SettingValue { global_value: Option, @@ -136,27 +147,24 @@ impl SettingsStore { local_values: Vec::new(), })); - if let Some(default_settings) = &self.default_deserialized_settings { - if let Some(default_settings) = setting_value - .deserialize_setting(default_settings) + if let Some(default_settings) = setting_value + .deserialize_setting(&self.default_deserialized_settings) + .log_err() + { + let mut user_values_stack = Vec::new(); + + if let Some(user_settings) = setting_value + .deserialize_setting(&self.user_deserialized_settings) .log_err() { - let mut user_values_stack = Vec::new(); - - if let Some(user_settings) = &self.user_deserialized_settings { - if let Some(user_settings) = - setting_value.deserialize_setting(user_settings).log_err() - { - user_values_stack = vec![user_settings]; - } - } + user_values_stack = vec![user_settings]; + } - if let Some(setting) = setting_value - .load_setting(&default_settings, &user_values_stack, cx) - .log_err() - { - setting_value.set_global_value(setting); - } + if let Some(setting) = setting_value + .load_setting(&default_settings, &user_values_stack, cx) + .log_err() + { + setting_value.set_global_value(setting); } } } @@ -189,9 +197,7 @@ impl SettingsStore { /// This is only for debugging and reporting. For user-facing functionality, /// use the typed setting interface. pub fn untyped_user_settings(&self) -> &serde_json::Value { - self.user_deserialized_settings - .as_ref() - .unwrap_or(&serde_json::Value::Null) + &self.user_deserialized_settings } #[cfg(any(test, feature = "test-support"))] @@ -213,11 +219,7 @@ impl SettingsStore { cx: &AppContext, update: impl FnOnce(&mut T::FileContent), ) { - if self.user_deserialized_settings.is_none() { - self.set_user_settings("{}", cx).unwrap(); - } - let old_text = - serde_json::to_string(self.user_deserialized_settings.as_ref().unwrap()).unwrap(); + let old_text = serde_json::to_string(&self.user_deserialized_settings).unwrap(); let new_text = self.new_text_for_update::(old_text, update); self.set_user_settings(&new_text, cx).unwrap(); } @@ -250,11 +252,7 @@ impl SettingsStore { .setting_values .get(&setting_type_id) .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::())) - .deserialize_setting( - self.user_deserialized_settings - .as_ref() - .expect("no user settings loaded"), - ) + .deserialize_setting(&self.user_deserialized_settings) .unwrap_or_else(|e| { panic!( "could not deserialize setting type {} from user settings: {}", @@ -323,10 +321,14 @@ impl SettingsStore { default_settings_content: &str, cx: &AppContext, ) -> Result<()> { - self.default_deserialized_settings = - Some(parse_json_with_comments(default_settings_content)?); - self.recompute_values(None, cx)?; - Ok(()) + let settings: serde_json::Value = parse_json_with_comments(default_settings_content)?; + if settings.is_object() { + self.default_deserialized_settings = settings; + self.recompute_values(None, cx)?; + Ok(()) + } else { + Err(anyhow!("settings must be an object")) + } } /// Set the user settings via a JSON string. @@ -335,9 +337,14 @@ impl SettingsStore { user_settings_content: &str, cx: &AppContext, ) -> Result<()> { - self.user_deserialized_settings = Some(parse_json_with_comments(user_settings_content)?); - self.recompute_values(None, cx)?; - Ok(()) + let settings: serde_json::Value = parse_json_with_comments(user_settings_content)?; + if settings.is_object() { + self.user_deserialized_settings = settings; + self.recompute_values(None, cx)?; + Ok(()) + } else { + Err(anyhow!("settings must be an object")) + } } /// Add or remove a set of local settings via a JSON string. @@ -361,7 +368,6 @@ impl SettingsStore { /// Add or remove a set of local settings via a JSON string. pub fn clear_local_settings(&mut self, root_id: usize, cx: &AppContext) -> Result<()> { - eprintln!("clearing local settings {root_id}"); self.local_deserialized_settings .retain(|k, _| k.0 != root_id); self.recompute_values(Some((root_id, "".as_ref())), cx)?; @@ -460,68 +466,63 @@ impl SettingsStore { let mut user_settings_stack = Vec::::new(); let mut paths_stack = Vec::>::new(); for setting_value in self.setting_values.values_mut() { - if let Some(default_settings) = &self.default_deserialized_settings { - let default_settings = setting_value.deserialize_setting(default_settings)?; + let default_settings = + setting_value.deserialize_setting(&self.default_deserialized_settings)?; - user_settings_stack.clear(); - paths_stack.clear(); + user_settings_stack.clear(); + paths_stack.clear(); - if let Some(user_settings) = &self.user_deserialized_settings { - if let Some(user_settings) = - setting_value.deserialize_setting(user_settings).log_err() - { - user_settings_stack.push(user_settings); - paths_stack.push(None); - } + if let Some(user_settings) = setting_value + .deserialize_setting(&self.user_deserialized_settings) + .log_err() + { + user_settings_stack.push(user_settings); + paths_stack.push(None); + } + + // If the global settings file changed, reload the global value for the field. + if changed_local_path.is_none() { + if let Some(value) = setting_value + .load_setting(&default_settings, &user_settings_stack, cx) + .log_err() + { + setting_value.set_global_value(value); } + } - // If the global settings file changed, reload the global value for the field. - if changed_local_path.is_none() { - if let Some(value) = setting_value - .load_setting(&default_settings, &user_settings_stack, cx) - .log_err() - { - setting_value.set_global_value(value); + // Reload the local values for the setting. + for ((root_id, path), local_settings) in &self.local_deserialized_settings { + // Build a stack of all of the local values for that setting. + while let Some(prev_entry) = paths_stack.last() { + if let Some((prev_root_id, prev_path)) = prev_entry { + if root_id != prev_root_id || !path.starts_with(prev_path) { + paths_stack.pop(); + user_settings_stack.pop(); + continue; + } } + break; } - // Reload the local values for the setting. - for ((root_id, path), local_settings) in &self.local_deserialized_settings { - // Build a stack of all of the local values for that setting. - while let Some(prev_entry) = paths_stack.last() { - if let Some((prev_root_id, prev_path)) = prev_entry { - if root_id != prev_root_id || !path.starts_with(prev_path) { - paths_stack.pop(); - user_settings_stack.pop(); - continue; - } - } - break; + if let Some(local_settings) = + setting_value.deserialize_setting(&local_settings).log_err() + { + paths_stack.push(Some((*root_id, path.as_ref()))); + user_settings_stack.push(local_settings); + + // If a local settings file changed, then avoid recomputing local + // settings for any path outside of that directory. + if changed_local_path.map_or(false, |(changed_root_id, changed_local_path)| { + *root_id != changed_root_id || !path.starts_with(changed_local_path) + }) { + continue; } - if let Some(local_settings) = - setting_value.deserialize_setting(&local_settings).log_err() + if let Some(value) = setting_value + .load_setting(&default_settings, &user_settings_stack, cx) + .log_err() { - paths_stack.push(Some((*root_id, path.as_ref()))); - user_settings_stack.push(local_settings); - - // If a local settings file changed, then avoid recomputing local - // settings for any path outside of that directory. - if changed_local_path.map_or( - false, - |(changed_root_id, changed_local_path)| { - *root_id != changed_root_id || !path.starts_with(changed_local_path) - }, - ) { - continue; - } - - if let Some(value) = setting_value - .load_setting(&default_settings, &user_settings_stack, cx) - .log_err() - { - setting_value.set_local_value(*root_id, path.clone(), value); - } + setting_value.set_local_value(*root_id, path.clone(), value); } } } From 40c6baf7cbd92bbe700c57e18d7bc442fe12eb71 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 1 Jun 2023 10:49:27 -0700 Subject: [PATCH 50/53] Redraw the terminal on every wakeup co-authored-by: max --- crates/terminal_view/src/terminal_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 3c9836fb75e64d6f7add6e2880bdc409746d4792..9478b3eef14221782050ca9ddf269878a91fef28 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -133,8 +133,8 @@ impl TerminalView { Event::Wakeup => { if !cx.is_self_focused() { this.has_new_content = true; - cx.notify(); } + cx.notify(); cx.emit(Event::Wakeup); } Event::Bell => { From 0065f5715ceaa905b5fa6ba07a2ab9ec923498c7 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 1 Jun 2023 16:40:54 -0400 Subject: [PATCH 51/53] Add panic events --- crates/zed/src/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 31f331ef93ef17eecb4870f3ed23c9f963a5b3aa..9ec3e3d3f6b5c23c33e0a46ec683ad0bd2f98022 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -41,7 +41,7 @@ use std::{ Arc, Weak, }, thread, - time::Duration, + time::{Duration, SystemTime, UNIX_EPOCH}, }; use sum_tree::Bias; use terminal_view::{get_working_directory, TerminalSettings, TerminalView}; @@ -376,6 +376,7 @@ struct Panic { backtrace: Vec, // TODO // stripped_backtrace: String, + time: u128, } #[derive(Serialize)] @@ -413,6 +414,10 @@ fn init_panic_hook(app_version: String) { .map(|line| line.to_string()) .collect(), // modified_backtrace: None, + time: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(), }; if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() { From e67e6e6f70b76907d5e44628117a7cc48d0616c9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 1 Jun 2023 14:07:59 -0700 Subject: [PATCH 52/53] Fix ambiguous glob export warnings in rust 1.70 --- crates/editor/src/editor.rs | 4 +++- crates/gpui/src/elements/uniform_list.rs | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index baf2f062fea13633355ee679e12375aaa1b2b6e3..5c19bb0121bdd0302c41c9b067eb72a9eea2e88b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -31,7 +31,9 @@ use copilot::Copilot; pub use display_map::DisplayPoint; use display_map::*; pub use editor_settings::EditorSettings; -pub use element::*; +pub use element::{ + Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles, +}; use futures::FutureExt; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 9ccd57b2919727ec1c60e8af525d8b6de73e8f77..8344914da0d8f0124fd6ddc5cc1cbc29ab2e4d1d 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -36,7 +36,7 @@ struct StateInner { scroll_to: Option, } -pub struct LayoutState { +pub struct UniformListLayoutState { scroll_max: f32, item_height: f32, items: Vec>, @@ -152,7 +152,7 @@ impl UniformList { } impl Element for UniformList { - type LayoutState = LayoutState; + type LayoutState = UniformListLayoutState; type PaintState = (); fn layout( @@ -169,7 +169,7 @@ impl Element for UniformList { let no_items = ( constraint.min, - LayoutState { + UniformListLayoutState { item_height: 0., scroll_max: 0., items: Default::default(), @@ -263,7 +263,7 @@ impl Element for UniformList { ( size, - LayoutState { + UniformListLayoutState { item_height, scroll_max, items, From 585d13d3db5e589174c89fa141493b2d2196076b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 1 Jun 2023 15:20:15 -0700 Subject: [PATCH 53/53] Unzoom all panes when opening a dock --- crates/workspace/src/workspace.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 21feea2b4086433eb1b1e0c31788ce78d16464f4..795747cfcc5045a8c554b9ca8f206b57bb313dc8 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1705,7 +1705,7 @@ impl Workspace { ) { // If a center pane is zoomed, unzoom it. for pane in &self.panes { - if pane != &self.active_pane { + if pane != &self.active_pane || dock_to_reveal.is_some() { pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); } } @@ -4351,6 +4351,12 @@ mod tests { panel }); + let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); + pane.update(cx, |pane, cx| { + let item = cx.add_view(|_| TestItem::new()); + pane.add_item(Box::new(item), true, true, None, cx); + }); + // Transfer focus from center to panel workspace.update(cx, |workspace, cx| { workspace.toggle_panel_focus::(cx); @@ -4452,6 +4458,25 @@ mod tests { assert!(workspace.zoomed.is_some()); assert!(panel.has_focus(cx)); }); + + // Unzoom and close the panel, zoom the active pane. + panel.update(cx, |panel, cx| panel.set_zoomed(false, cx)); + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx) + }); + pane.update(cx, |pane, cx| pane.toggle_zoom(&Default::default(), cx)); + + // Opening a dock unzooms the pane. + workspace.update(cx, |workspace, cx| { + workspace.toggle_dock(DockPosition::Right, cx) + }); + workspace.read_with(cx, |workspace, cx| { + let pane = pane.read(cx); + assert!(!pane.is_zoomed()); + assert!(pane.has_focus()); + assert!(workspace.right_dock().read(cx).is_open()); + assert!(workspace.zoomed.is_none()); + }); } #[gpui::test]