File: 10.3-Pattern-Matching.md

package info (click to toggle)
sonic-pi 3.2.2~repack-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 71,872 kB
  • sloc: ruby: 30,548; cpp: 8,490; sh: 957; ansic: 461; erlang: 360; lisp: 141; makefile: 44
file content (133 lines) | stat: -rw-r--r-- 3,850 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
10.3 Pattern Matching

# Pattern Matching

When getting and setting information into the Time State, it's possible
to use more complex keys than basic symbols such as `:foo` and
`:bar`. You can also use URL style strings called paths such as
`"/foo/bar/baz"`. Once we start working with paths, we can then start
taking advantage of Sonic Pi's sophisticated pattern matching system to
`get` and `sync` with 'similar' rather than 'identical' paths. Let's
take a look.

## Match any path segment

Let's assume we want to wait for the next event that has three path segments:

```
sync "/*/*/*"
```

This will match any Time State event with exactly three path segments,
regardless of their names. For example:

* `cue "/foo/bar/baz"`
* `cue "/foo/baz/quux"`
* `cue "/eggs/beans/toast"`
* `cue "/moog/synths/rule"`

However, it will *not* match paths with fewer or more path segments. The
following will not match:

* `cue "/foo/bar"`
* `cue "/foo/baz/quux/quaax"`
* `cue "/eggs"`

Each `*` means *any content*. So we could match paths with just one segment with `/*` or paths with five segments with `/*/*/*/*/*`

## Matching partial segments

If we know what the segment is going to start or finish with, we can use
a `*` in addition to a partial segment name. For example:
`"/foo/b*/baz"` will match any path that has three segments, the first
of which is `foo`, the last `baz` and the middle segment can be anything
that starts with `b`. So, it would match:

* `cue "/foo/bar/baz"`
* `cue "/foo/baz/baz"`
* `cue "/foo/beans/baz"`

However, it wouldn't match the following:

* `cue "/foo/flibble/baz"`
* `cue "/foo/abaz/baz"`
* `cue "/foo/beans/baz/eggs"`

You can also place the `*` at the start of the segment to specify the
last characters of a segment: `"/foo/*zz/baz"` which will match any 3
segment `cue` or `set` where the first segment is `foo`, the last is
`baz` and the middle segment ends with `zz` such as `"cue
"/foo/whizz/baz"`.

## Matching Nested Path Segments

Sometimes you don't know how many path segments you want to match. In
these cases you can use the powerful double star: `**` such as
`"/foo/**/baz"` which will match:

* `cue "/foo/bar/baz"`
* `cue "/foo/bar/beans/baz"`
* `cue "/foo/baz"`
* `cue "/foo/a/b/c/d/e/f/baz"`

## Matching Single Letters

You can use the `?` character to match against a single char such as `"/?oo/bar/baz"` which will match:


* `cue "/foo/bar/baz"`
* `cue "/goo/bar/baz"`
* `cue "/too/bar/baz"`
* `cue "/woo/bar/baz"`

## Matching Multiple Words

If you know that a segment may be one of a select number of words, you
can use the `{` and `}` matchers to specify a list of choices such as
`"/foo/{bar,beans,eggs}/quux"` which will only match the following:

* `cue "/foo/bar/quux"`
* `cue "/foo/beans/quux"`
* `cue "/foo/eggs/quux"`

## Matching Multiple Letters

Finally, you can match against a selection of letters if you use the
`[` and `]` matchers to specify a list of choices such as
`"/foo/[abc]ux/baz"` which will match only:

* `cue "/foo/aux/baz"`
* `cue "/foo/bux/baz"`
* `cue "/foo/cux/baz"`


You can also use the `-` character to specify ranges of letters. For example `"/foo/[a-e]ux/baz"` which will match only:

* `cue "/foo/aux/baz"`
* `cue "/foo/bux/baz"`
* `cue "/foo/cux/baz"`
* `cue "/foo/dux/baz"`
* `cue "/foo/eux/baz"`

## Combining Matchers

When calling `sync` or `get` you are free to combine matchers in any
order you see fit to powerfully match any Time State event created by
`cue` or `set`. Let's look at a crazy example:

```
in_thread do
  sync "/?oo/[a-z]*/**/ba*/{quux,quaax}/"
  sample :loop_amen
end

sleep 1

cue "/foo/beans/a/b/c/d/e/bark/quux/"
```

## OSC Pattern Matching

For those curious, these matching rules are based on the Open Sound
Control pattern matching specification which is explained in detail
here: http://opensoundcontrol.org/spec-1_0