Skip to content

Commit

Permalink
Allow filtering chord definition by tag selector
Browse files Browse the repository at this point in the history
Related to #983
  • Loading branch information
martijnversluis committed Dec 15, 2024
1 parent 00fbbc3 commit 6c7f5b2
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 102 deletions.
10 changes: 8 additions & 2 deletions src/chord_sheet/song.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import Tag, {
import SongBuilder from '../song_builder';
import ChordDefinition from './chord_pro/chord_definition';
import Chord from '../chord';
import FormattingContext from '../formatter/formatting_context';
import { testSelector } from '../helpers';

type EachItemCallback = (_item: Item) => void;

Expand Down Expand Up @@ -455,15 +457,19 @@ Or set the song key before changing key:
* @see https://chordpro.org/chordpro/directives-define/
* @see https://chordpro.org/chordpro/directives-chord/
*/
getChordDefinitions(): Record<string, ChordDefinition> {
getChordDefinitions(context?: FormattingContext): Record<string, ChordDefinition> {
const chordDefinitions: Record<string, ChordDefinition> = {};

this.foreachItem((item: Item) => {
if (!(item instanceof Tag)) {
return;
}

const { chordDefinition } = (item as Tag);
const { chordDefinition, selector, isNegated } = (item as Tag);

if (selector && context && !testSelector({ selector, isNegated }, context)) {
return;
}

if (chordDefinition) {
chordDefinitions[chordDefinition.name] = chordDefinition.clone();
Expand Down
4 changes: 4 additions & 0 deletions src/chord_sheet/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,14 @@ class Tag extends AstComponent {
value: string | null = null,
traceInfo: TraceInfo | null = null,
attributes: Record<string, string> = {},
selector: string | null = null,
isNegated = false,
) {
super(traceInfo);
this.parseNameValue(name, value);
this.attributes = attributes;
this.selector = selector;
this.isNegated = isNegated;
}

private parseNameValue(name: string, value: string | null): void {
Expand Down
9 changes: 9 additions & 0 deletions src/formatter/formatting_context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Configuration from './configuration/configuration';
import Metadata from '../chord_sheet/metadata';

interface FormattingContext {
configuration: Configuration;
metadata: Metadata;
}

export default FormattingContext;
17 changes: 3 additions & 14 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { capos, majorKeys, minorKeys } from './key_config';
import Song from './chord_sheet/song';
import { CAPO, CHORD_STYLE, ChordType } from './chord_sheet/tag';
import Line from './chord_sheet/line';
import Configuration from './formatter/configuration/configuration';
import Metadata from './chord_sheet/metadata';
import FormattingContext from './formatter/formatting_context';

export function transposeDistance(transposeKey: string, songKey: string): number {
if (/^\d+$/.test(transposeKey)) {
Expand Down Expand Up @@ -113,18 +112,8 @@ export function getKeys(key: Key | string): string[] {
}

export function testSelector(
{
selector,
isNegated,
configuration,
metadata,
}:
{
selector: string,
isNegated: boolean,
configuration: Configuration,
metadata: Metadata
},
{ selector, isNegated }: { selector: string, isNegated: boolean },
{ configuration, metadata }: FormattingContext,
) {
if (selector === configuration.instrument?.type) {
return !isNegated;
Expand Down
42 changes: 42 additions & 0 deletions test/chord_sheet/song.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { exampleSongSolfege, exampleSongSymbol } from '../fixtures/song';
import { serializedSongSolfege, serializedSongSymbol } from '../fixtures/serialized_song';
import { changedSongSolfege, changedSongSymbol } from '../fixtures/changed_song';
import Song from '../../src/chord_sheet/song';
import Configuration from '../../src/formatter/configuration/configuration';
import Metadata from '../../src/chord_sheet/metadata';

const createLineStub = ({ renderable }) => (
{
Expand Down Expand Up @@ -374,5 +376,45 @@ describe('Song', () => {

expect(song.getChordDefinitions()).toEqual({});
});

it('leaves out chord definitions with non-matching selector', () => {
const cm7 = createChordDefinition('CM7', 3, ['x', '0', 1]);
const dm = createChordDefinition('Dm', 3, ['x', 3, 5]);

const configuration = new Configuration({ instrument: { type: 'ukulele' } });
const metadata = new Metadata();

const song = createSong([
createLine([
createTag('chord', 'CM7', cm7, 'guitar'),
]),
createLine([]),
createLine([
createTag('define', 'Dm', dm, 'ukulele'),
]),
]);

expect(song.getChordDefinitions({ configuration, metadata })).toEqual({ Dm: dm });
});

it('leaves out chord definitions with a negated matching selector', () => {
const cm7 = createChordDefinition('CM7', 3, ['x', '0', 1]);
const dm = createChordDefinition('Dm', 3, ['x', 3, 5]);

const configuration = new Configuration({ instrument: { type: 'guitar' } });
const metadata = new Metadata();

const song = createSong([
createLine([
createTag('chord', 'CM7', cm7, 'guitar', true),
]),
createLine([]),
createLine([
createTag('define', 'Dm', dm),
]),
]);

expect(song.getChordDefinitions({ configuration, metadata })).toEqual({ Dm: dm });
});
});
});
140 changes: 56 additions & 84 deletions test/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'guitar',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'guitar', isNegated: false },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -52,12 +50,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'piano',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'piano', isNegated: false },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -66,12 +62,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'john',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'john', isNegated: false },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -80,12 +74,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'jane',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'jane', isNegated: false },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -94,12 +86,10 @@ describe('testSelector', () => {
const metadata = new Metadata({ 'horns': 'true' });

expect(
testSelector({
selector: 'horns',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: false },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -108,12 +98,10 @@ describe('testSelector', () => {
const metadata = new Metadata({ 'horns': '' });

expect(
testSelector({
selector: 'horns',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: false },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -122,12 +110,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'horns',
isNegated: false,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: false },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -137,12 +123,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'guitar',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'guitar', isNegated: true },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -151,12 +135,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'piano',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'piano', isNegated: true },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -165,12 +147,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'john',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'john', isNegated: true },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -179,12 +159,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'jane',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'jane', isNegated: true },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -193,12 +171,10 @@ describe('testSelector', () => {
const metadata = new Metadata({ 'horns': 'true' });

expect(
testSelector({
selector: 'horns',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: true },
{ configuration, metadata },
),
).toEqual(false);
});

Expand All @@ -207,12 +183,10 @@ describe('testSelector', () => {
const metadata = new Metadata({ 'horns': '' });

expect(
testSelector({
selector: 'horns',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: true },
{ configuration, metadata },
),
).toEqual(true);
});

Expand All @@ -221,12 +195,10 @@ describe('testSelector', () => {
const metadata = new Metadata();

expect(
testSelector({
selector: 'horns',
isNegated: true,
configuration,
metadata,
}),
testSelector(
{ selector: 'horns', isNegated: true },
{ configuration, metadata },
),
).toEqual(true);
});
});
Expand Down
10 changes: 8 additions & 2 deletions test/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,14 @@ export function createChordLyricsPair(chords, lyrics) {
return new ChordLyricsPair(chords, lyrics);
}

export function createTag(name: string, value = '', chordDefinition: ChordDefinition | null = null): Tag {
const newTag = new Tag(name, value);
export function createTag(
name: string,
value = '',
chordDefinition: ChordDefinition | null = null,
selector: string | null = null,
isNegated = false,
): Tag {
const newTag = new Tag(name, value, null, {}, selector, isNegated);
if (chordDefinition) newTag.chordDefinition = chordDefinition;
return newTag;
}
Expand Down

0 comments on commit 6c7f5b2

Please sign in to comment.