Skip to content

Commit

Permalink
Merge pull request #174 from terrastruct/globs
Browse files Browse the repository at this point in the history
Globs
  • Loading branch information
alixander authored Jul 31, 2023
2 parents 2caab19 + bd49ec0 commit 9b0fade
Show file tree
Hide file tree
Showing 26 changed files with 2,282 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ci/render.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
236 changes: 236 additions & 0 deletions docs/tour/globs.md
Original file line number Diff line number Diff line change
@@ -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
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-intro.svg2')}}></div>

## Globs are case insensitive

```d2
diddy kong
Donkey Kong
*kong.style.fill: brown
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-casing.svg2')}}></div>

## Globs can appear multiple times

```d2
teacher
thriller
thrifter
t*h*r.shape: person
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-multiple.svg2')}}></div>

```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
* -> *: 👉
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-connections.svg2')}}></div>

:::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
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-indexed-connections.svg2')}}></div>

## 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
}
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-scope.svg2')}}></div>

## Recursive globs

`**` means target recursively.

```d2
a: {
b: {
c
}
}
**.style.border-radius: 7
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-recursive.svg2')}}></div>

```d2
zone-A: {
machine A
machine B: {
submachine A
submachine B
}
}
zone-A.** -> load balancer
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-recursive-2.svg2')}}></div>


:::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
}
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-filter.svg2')}}></div>

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
}
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-filter-2.svg2')}}></div>

:::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}
}
```

<div style={{width: 600}} className="embedSVG" dangerouslySetInnerHTML={{__html: require('@site/static/img/generated/globs-nested.svg2')}}></div>
2 changes: 1 addition & 1 deletion docs/tour/overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const sidebars = {
items: [
"tour/strings",
"tour/vars",
"tour/globs",
"tour/comments",
"tour/overrides",
"tour/auto-formatter",
Expand Down
4 changes: 4 additions & 0 deletions static/d2/globs-casing.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
diddy kong
Donkey Kong

*kong.style.fill: brown
11 changes: 11 additions & 0 deletions static/d2/globs-connections.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
vars: {
d2-config: {
layout-engine: elk
}
}

Spiderman 1
Spiderman 2
Spiderman 3

* -> *: 👉
14 changes: 14 additions & 0 deletions static/d2/globs-filter-2.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
the-little-cannon: {
class: [server; deployed]
}
dino: {
class: [internal; deployed]
}
catapult: {
class: [server]
}

*: {
&class: server
style.multiple: true
}
9 changes: 9 additions & 0 deletions static/d2/globs-filter.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
bravo team.shape: person
charlie team.shape: person
command center.shape: cloud
hq.shape: rectangle

*: {
&shape: person
style.multiple: true
}
9 changes: 9 additions & 0 deletions static/d2/globs-indexed-connections.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
lady 1
lady 2

barbie

lady 1 -> barbie: hi barbie
lady 2 -> barbie: hi barbie

(lady* -> barbie)[*].style.stroke: pink
9 changes: 9 additions & 0 deletions static/d2/globs-intro.d2
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions static/d2/globs-multiple.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
teacher
thriller
thrifter

t*h*r.shape: person
17 changes: 17 additions & 0 deletions static/d2/globs-nested.d2
Original file line number Diff line number Diff line change
@@ -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}
}
9 changes: 9 additions & 0 deletions static/d2/globs-recursive-2.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
zone-A: {
machine A
machine B: {
submachine A
submachine B
}
}

zone-A.** -> load balancer
7 changes: 7 additions & 0 deletions static/d2/globs-recursive.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
a: {
b: {
c
}
}

**.style.border-radius: 7
14 changes: 14 additions & 0 deletions static/d2/globs-scope.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
foods: {
pizzas: {
cheese
sausage
pineapple
*.shape: circle
}
humans: {
john
james
*.shape: person
}
humans.* -> pizzas.pineapple: eats
}
Loading

0 comments on commit 9b0fade

Please sign in to comment.