From f4b1baac878d99af91916fe27174f8b268320b33 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Thu, 27 Nov 2025 15:34:18 +0000 Subject: [PATCH 1/3] add revv() for reversing whole patterns --- packages/core/pattern.mjs | 19 ++++++++++++++++++- packages/core/test/pattern.test.mjs | 12 ++++++++++++ test/__snapshots__/examples.test.mjs.snap | 13 +++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 4737f0db0..9a9ffe98f 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -2234,7 +2234,7 @@ export const brak = register('brak', function (pat) { }); /** - * Reverse all haps in a pattern + * Reverse all cycles in a pattern. See also `revv` for reversing a whole pattern. * * @name rev * @memberof Pattern @@ -2266,6 +2266,23 @@ export const rev = register( true, ); +/** + * Reverse a whole pattern. See also `revv` for reversing each cycle. + * + * @name rev + * @memberof Pattern + * @returns Pattern + * @example + * // This is the same as `<[g e] [d c]>`. If `rev()` is used, you get + * // the same as `<[d c] [g e]>`, where each cycle reverses, but the order of + * // cycles stays the same. + * note("<[c d] [e g]>").revv() + */ +export const revv = register('revv', function (pat) { + const negateSpan = (span) => new TimeSpan(Fraction(0).sub(span.end), Fraction(0).sub(span.begin)); + return pat.withQuerySpan(negateSpan).withHapSpan(negateSpan); +}); + /** Like press, but allows you to specify the amount by which each * event is shifted. pressBy(0.5) is the same as press, while * pressBy(1/3) shifts each event by a third of its timespan. diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 1df5c8776..408ff274b 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -586,6 +586,18 @@ describe('Pattern', () => { .map((a) => a.value), ).toStrictEqual(['c', 'b', 'a']); }); + it('Does not reverse the order of cycles', () => { + expect(fastcat('a', 'b', 'c', 'd').slow(2).rev().fast(2).sortHapsByPart().firstCycle()).toStrictEqual( + fastcat('b', 'a', 'd', 'c').firstCycle(), + ); + }); + }); + describe('revv()', () => { + it('Does reverse the order of cycles', () => { + expect(fastcat('a', 'b', 'c', 'd').slow(2).revv().fast(2).sortHapsByPart().firstCycle()).toStrictEqual( + fastcat('d', 'c', 'b', 'a').firstCycle(), + ); + }); }); describe('sequence()', () => { it('Can work like fastcat', () => { diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 4fc037b19..064f4c2d5 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -9256,6 +9256,19 @@ exports[`runs examples > example "rev" example index 0 1`] = ` ] `; +exports[`runs examples > example "rev" example index 0 2`] = ` +[ + "[ 0/1 → 1/2 | note:g ]", + "[ 1/2 → 1/1 | note:e ]", + "[ 1/1 → 3/2 | note:d ]", + "[ 3/2 → 2/1 | note:c ]", + "[ 2/1 → 5/2 | note:g ]", + "[ 5/2 → 3/1 | note:e ]", + "[ 3/1 → 7/2 | note:d ]", + "[ 7/2 → 4/1 | note:c ]", +] +`; + exports[`runs examples > example "ribbon" example index 0 1`] = ` [ "[ 0/1 → 1/1 | note:d ]", From cb591815edb75dcd0d52f0ef8f63f211b1c22dad Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 28 Nov 2025 21:35:35 +0000 Subject: [PATCH 2/3] fix copy paste errors --- packages/core/pattern.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 9a9ffe98f..88a0993c9 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -2267,9 +2267,9 @@ export const rev = register( ); /** - * Reverse a whole pattern. See also `revv` for reversing each cycle. + * Reverse a whole pattern. See also `rev` for reversing each cycle. * - * @name rev + * @name revv * @memberof Pattern * @returns Pattern * @example From 956598da18fbfd66256fbcb18e1225c31e32af30 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 28 Nov 2025 22:03:21 +0000 Subject: [PATCH 3/3] snapshot --- test/__snapshots__/examples.test.mjs.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 064f4c2d5..e4b46b97f 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -9256,7 +9256,7 @@ exports[`runs examples > example "rev" example index 0 1`] = ` ] `; -exports[`runs examples > example "rev" example index 0 2`] = ` +exports[`runs examples > example "revv" example index 0 1`] = ` [ "[ 0/1 → 1/2 | note:g ]", "[ 1/2 → 1/1 | note:e ]",