diff --git a/ci/render.sh b/ci/render.sh index 33c2730b..6bd58a9d 100755 --- a/ci/render.sh +++ b/ci/render.sh @@ -4,7 +4,7 @@ set -eu cd -- "$(dirname "$0")/.." _normal() { - sh_c d2 --dark-theme=200 -l dagre -c --pad 0 ./static/d2/${ex}.d2 ./static/img/generated/${ex}.svg2 + sh_c d2 --dark-theme=200 -c --pad 0 ./static/d2/${ex}.d2 ./static/img/generated/${ex}.svg2 } _bespoke() { diff --git a/docs/tour/globs.md b/docs/tour/globs.md new file mode 100644 index 00000000..57c6ed8d --- /dev/null +++ b/docs/tour/globs.md @@ -0,0 +1,236 @@ +# Globs + +:::caution Alpha +Globs are an alpha feature in 0.6.0. It is likely to change in behavior in followup minor +releases. In particular, the current plan is for globs to be lazy evaluated, so that it +can be used to set defaults, as opposed to the current implementation where it is +evaluated as it appears. +::: + +:::note Etymology +> The glob command, short for global, originates in the earliest versions of Bell Labs' Unix... to expand wildcard characters in unquoted arguments ... + +[https://en.wikipedia.org/wiki/Glob_(programming)](https://en.wikipedia.org/wiki/Glob_(programming)) +::: + +Globs are a powerful language feature to make global changes in one line. + +```d2 +iphone 10 +iphone 11 mini +iphone 11 pro +iphone 12 mini + +*.height: 300 +*.width: 140 +*mini.height: 200 +*pro.height: 400 +``` + +
+ +## Globs are case insensitive + +```d2 +diddy kong +Donkey Kong + +*kong.style.fill: brown +``` + + + +## Globs can appear multiple times + +```d2 +teacher +thriller +thrifter + +t*h*r.shape: person +``` + + + +```d2 +a: { + b + c +} + +a.*.c -> c +``` + +## Glob connections + +You can use globs to create connections. + +```d2 +vars: { + d2-config: { + layout-engine: elk + } +} + +Spiderman 1 +Spiderman 2 +Spiderman 3 + +* -> *: 👉 +``` + + + +:::info +Notice how self-connections were omitted. While not entirely consistent with what you may +expect from globs, we feel it is more pragmatic for this to be the behavior. +::: + +You can also use globs to target modifying existing connections. + +```d2 +lady 1 +lady 2 + +barbie + +lady 1 -> barbie: hi barbie +lady 2 -> barbie: hi barbie + +(lady* -> barbie)[*].style.stroke: pink +``` + + + +## Scoped globs + +Notice that in the below example, globs only apply to the scope they are specified in. + +```d2 +foods: { + pizzas: { + cheese + sausage + pineapple + *.shape: circle + } + humans: { + john + james + *.shape: person + } + humans.* -> pizzas.pineapple: eats +} +``` + + + +## Recursive globs + +`**` means target recursively. + +```d2 +a: { + b: { + c + } +} + +**.style.border-radius: 7 +``` + + + +```d2 +zone-A: { + machine A + machine B: { + submachine A + submachine B + } +} + +zone-A.** -> load balancer +``` + + + + +:::info +Notice how `machine B` was not captured. Similar to the exception with `* -> *` omitting +self-connections, recursive globs in connections also make an exception for practical +diagramming: it only applies to non-container (AKA leaf) shapes. +::: + +## Filters + +Use `&` to filter what globs target. + +```d2 +bravo team.shape: person +charlie team.shape: person +command center.shape: cloud +hq.shape: rectangle + +*: { + &shape: person + style.multiple: true +} +``` + + + +If the filtered attribute has an array value, the filter will match if it matches any +element of the array. + +```d2 +the-little-cannon: { + class: [server; deployed] +} +dino: { + class: [internal; deployed] +} +catapult: { + class: [server] +} + +*: { + &class: server + style.multiple: true +} +``` + + + +:::info +We are working on adding more filters. +::: + +## Nested globs + +You can nest globs, combining the features above. + +```d2 +conversation 1: { + shape: sequence_diagram + alice -> bob: hi + bob -> alice: hi +} + +conversation 2: { + shape: sequence_diagram + alice -> bob: hello again + alice -> bob: hello? + bob -> alice: hello +} + +# Recursively target all shapes... +**: { + # ... that are sequence diagrams + &shape: sequence_diagram + # Then recursively set all shapes in them to person + **: {shape: person} +} +``` + + diff --git a/docs/tour/overrides.md b/docs/tour/overrides.md index afd72516..2ec39c4b 100644 --- a/docs/tour/overrides.md +++ b/docs/tour/overrides.md @@ -51,7 +51,7 @@ When is this useful? - [Import](/tour/imports) a diagram from a colleague and remove the things you don't want. - [Multi-board compositions](/tour/composition) where you inherit all the objects from a board with some exceptions. -- (Coming soon) Use globs to define connections between a batch of objects except one in +- Use [globs](/tour/globs) to define connections between a batch of objects except one in particular you want to leave out. ### Nulling a connection diff --git a/sidebars.js b/sidebars.js index a251fa6c..9d2c9390 100644 --- a/sidebars.js +++ b/sidebars.js @@ -73,6 +73,7 @@ const sidebars = { items: [ "tour/strings", "tour/vars", + "tour/globs", "tour/comments", "tour/overrides", "tour/auto-formatter", diff --git a/static/d2/globs-casing.d2 b/static/d2/globs-casing.d2 new file mode 100644 index 00000000..273dfd3f --- /dev/null +++ b/static/d2/globs-casing.d2 @@ -0,0 +1,4 @@ +diddy kong +Donkey Kong + +*kong.style.fill: brown diff --git a/static/d2/globs-connections.d2 b/static/d2/globs-connections.d2 new file mode 100644 index 00000000..e8dfde65 --- /dev/null +++ b/static/d2/globs-connections.d2 @@ -0,0 +1,11 @@ +vars: { + d2-config: { + layout-engine: elk + } +} + +Spiderman 1 +Spiderman 2 +Spiderman 3 + +* -> *: 👉 diff --git a/static/d2/globs-filter-2.d2 b/static/d2/globs-filter-2.d2 new file mode 100644 index 00000000..e362d589 --- /dev/null +++ b/static/d2/globs-filter-2.d2 @@ -0,0 +1,14 @@ +the-little-cannon: { + class: [server; deployed] +} +dino: { + class: [internal; deployed] +} +catapult: { + class: [server] +} + +*: { + &class: server + style.multiple: true +} diff --git a/static/d2/globs-filter.d2 b/static/d2/globs-filter.d2 new file mode 100644 index 00000000..d0f1b9ee --- /dev/null +++ b/static/d2/globs-filter.d2 @@ -0,0 +1,9 @@ +bravo team.shape: person +charlie team.shape: person +command center.shape: cloud +hq.shape: rectangle + +*: { + &shape: person + style.multiple: true +} diff --git a/static/d2/globs-indexed-connections.d2 b/static/d2/globs-indexed-connections.d2 new file mode 100644 index 00000000..250e107e --- /dev/null +++ b/static/d2/globs-indexed-connections.d2 @@ -0,0 +1,9 @@ +lady 1 +lady 2 + +barbie + +lady 1 -> barbie: hi barbie +lady 2 -> barbie: hi barbie + +(lady* -> barbie)[*].style.stroke: pink diff --git a/static/d2/globs-intro.d2 b/static/d2/globs-intro.d2 new file mode 100644 index 00000000..a18f71ea --- /dev/null +++ b/static/d2/globs-intro.d2 @@ -0,0 +1,9 @@ +iphone 10 +iphone 11 mini +iphone 11 pro +iphone 12 mini + +*.height: 300 +*.width: 140 +*mini.height: 200 +*pro.height: 400 diff --git a/static/d2/globs-multiple.d2 b/static/d2/globs-multiple.d2 new file mode 100644 index 00000000..b05665c7 --- /dev/null +++ b/static/d2/globs-multiple.d2 @@ -0,0 +1,5 @@ +teacher +thriller +thrifter + +t*h*r.shape: person diff --git a/static/d2/globs-nested.d2 b/static/d2/globs-nested.d2 new file mode 100644 index 00000000..facb38f4 --- /dev/null +++ b/static/d2/globs-nested.d2 @@ -0,0 +1,17 @@ +conversation 1: { + shape: sequence_diagram + alice -> bob: hi + bob -> alice: hi +} + +conversation 2: { + shape: sequence_diagram + alice -> bob: hello again + alice -> bob: hello? + bob -> alice: hello +} + +**: { + &shape: sequence_diagram + **: {shape: person} +} diff --git a/static/d2/globs-recursive-2.d2 b/static/d2/globs-recursive-2.d2 new file mode 100644 index 00000000..767f8909 --- /dev/null +++ b/static/d2/globs-recursive-2.d2 @@ -0,0 +1,9 @@ +zone-A: { + machine A + machine B: { + submachine A + submachine B + } +} + +zone-A.** -> load balancer diff --git a/static/d2/globs-recursive.d2 b/static/d2/globs-recursive.d2 new file mode 100644 index 00000000..542f3c0e --- /dev/null +++ b/static/d2/globs-recursive.d2 @@ -0,0 +1,7 @@ +a: { + b: { + c + } +} + +**.style.border-radius: 7 diff --git a/static/d2/globs-scope.d2 b/static/d2/globs-scope.d2 new file mode 100644 index 00000000..3c7048ce --- /dev/null +++ b/static/d2/globs-scope.d2 @@ -0,0 +1,14 @@ +foods: { + pizzas: { + cheese + sausage + pineapple + *.shape: circle + } + humans: { + john + james + *.shape: person + } + humans.* -> pizzas.pineapple: eats +} diff --git a/static/img/generated/globs-casing.svg2 b/static/img/generated/globs-casing.svg2 new file mode 100644 index 00000000..464e5c26 --- /dev/null +++ b/static/img/generated/globs-casing.svg2 @@ -0,0 +1,168 @@ + diff --git a/static/img/generated/globs-connections.svg2 b/static/img/generated/globs-connections.svg2 new file mode 100644 index 00000000..a0d69ef0 --- /dev/null +++ b/static/img/generated/globs-connections.svg2 @@ -0,0 +1,182 @@ +