def test_grid(self):
        chart = chords.ChordChart()
        chart.load_tuning_by_name("Soprano Uke")
        self.assertEqual(chart.grid_as_md("F#7"), chart.grid_as_md("F#7!"))
        #chart.get_default("F#7").show()

        self.assertEqual(
            chart.get_default("Gbm7").to_chordpro(),
            chart.get_default("F#m7").to_chordpro())

        F_sharp_chord_def = "{define: F#m7 base-fret 7 frets 2 1 2 0}"
        Gb_chord_def = "{define: Gbm7 base-fret 7 frets 2 1 2 0}"
        c = chords.ChordChart()
        c.add_grid(Gb_chord_def)
        self.assertEqual(
            c.get_default("Gbm7").to_chordpro(), F_sharp_chord_def)

        c = chords.ChordChart()
        c.add_grid(Gb_chord_def)
        self.assertEqual(
            c.get_default("F#m7").to_chordpro(), F_sharp_chord_def)
        self.assertEqual(
            c.get_default("F#m7//").to_chordpro(), F_sharp_chord_def)
        self.assertEqual(
            c.get_default("F#m7!").to_chordpro(), F_sharp_chord_def)
    def test_normalisation(self):
        chart = chords.ChordChart()
        chart.load_tuning_by_name("Soprano Uke")

        #Check normalisation code
        self.assertEqual(chart.grid_as_md("F#7///"), chart.grid_as_md("F#7"))

        self.assertEqual(chart.normalise_chord_name("Am7-5"), "Am7-5")
        self.assertEqual(chart.normalise_chord_name("Cmaj"), "C")
        self.assertEqual(chart.normalise_chord_name("CM7"), "Cmaj7")
        self.assertEqual(chart.normalise_chord_name("Cmaj7"), "Cmaj7")
        self.assertEqual(chart.normalise_chord_name("C+"), "Caug")

        self.assertEqual(chart.clean_chord_name("A!"), "A")
        self.assertEqual(chart.normalise_chord_name("AM7 / / /"), "Amaj7")

        # Clean removes rhythm marks but does not change chord names
        self.assertEqual(chart.clean_chord_name("Amaj7 / / /"), "Amaj7")
        self.assertEqual(chart.clean_chord_name("AM7 / / /"), "AM7")
Example #3
0
  def test_nashvillization(self):
      #TODO refactor code so this is no longer hanging off the ChordChart class
      chart = chords.ChordChart()
      self.assertEqual(chart.nashvillize("C","C"), "I")
      self.assertEqual(chart.nashvillize("C7","C"), "I⁷")
      self.assertEqual(chart.nashvillize("Cm","C"), "i")
      self.assertEqual(chart.nashvillize("Bb","Bb"), "I")
      self.assertEqual(chart.nashvillize("G/F#","C"), "V/♭5")
      self.assertEqual(chart.nashvillize("Bb/A","Bb"), "I/7")
      self.assertEqual(chart.nashvillize("Bb/A","Bb"), "I/7")
      self.assertEqual(chart.nashvillize("Am","Am"), "i")
      self.assertEqual(chart.nashvillize("Am/G","Am"), "i/7")
      self.assertEqual(chart.nashvillize("Am/C","Am"), "i/3")

      self.assertEqual(chart.nashvillize("Am/C","Am", major_chart=True), "vi/1")
      self.assertEqual(chart.nashvillize("Am","Am", major_chart=True), "vi")

      self.assertEqual(chart.nashvillize("C","C", major_chart=True), "I")
      self.assertEqual(chart.nashvillize("Cmaj7","C", major_chart=True), "IΔ")
Example #4
0
def generate_defs():
    transposer = chords.transposer()
    parser = argparse.ArgumentParser()
    parser.add_argument('tuning', default=None, help='tuning')
    args = vars(parser.parse_args())
    tuning = args["tuning"]
    chordpro_definitions = ""
    for note_index in range(0, 12):
        for variant in [
                "", "7", "6", "sus4", "m", "maj7", "m7", "Add9", "dim"
        ]:
            chord_name = transposer.get_note(note_index) + variant
            defs = generate_grids(chord_name, tuning)
            grids = chords.ChordChart()
            grids.load(defs)
            norm_chord_name = grids.normalise_chord_name(chord_name)
            grids.sort_by_playability(norm_chord_name)
            chordpro_definitions += "{c: %s}\n%s\n" % (
                norm_chord_name, str(grids.to_chordpro(norm_chord_name)))

    open("%s_chords.cho" % tuning.replace(" ", ""),
         'w').write(chordpro_definitions)
Example #5
0
    def format(self, transpose=None, instrument_name=None, stand_alone=True):
        """
        Create a markdown version of the song, transposed if necessary,
        does the last-minute formatting on the song incuding transposition
        and fetching chord grids """
        self.pages = 1
        if instrument_name == None:
            instrument_name = self.instrument_name
        self.local_grids = None
        self.grids = None

        if transpose:
            self.transpose = transpose
        #self.transpose = transpose
        if instrument_name != None:
            instrument = self.instruments.get_instrument_by_name(
                instrument_name)
            if instrument != None:
                instrument.load_chord_chart(lefty=self.lefty)
                self.grids = instrument.chart

            if self.local_instruments != None and instrument_name in self.local_instrument_names:
                self.local_grids = self.local_instruments.get_instrument_by_name(
                    instrument_name).chart

        if transpose and self.original_key:
            self.key = self.transposer.transpose_chord(self.original_key)

        key_string = self.get_key_string()
        title = "%s %s" % (self.title, key_string)

        self.chords_used = []

        # TODO Move this to a stand-alone-function
        nv = chordprobook.chords.ChordChart(
        ) if self.nashville and self.original_key else None

        def format_chord(chord):
            if nv:
                chord = nv.nashvillize(chord,
                                       key=key,
                                       major_chart=self.major_chart)
            else:
                if self.transposer.offset != 0:
                    chord = self.transposer.transpose_chord(chord)

                if self.grids != None:
                    clean_chord = self.grids.clean_chord_name(chord)
                    if not clean_chord in self.chords_used:
                        self.chords_used.append(clean_chord)

            return ("[%s]" % chord)

        key = self.original_key
        song = ""
        tr = chordprobook.chords.transposer(key=key,
                                            major_chart=self.major_chart)

        if self.major_chart:
            song += "*NOTE: Chart is for relative major key* \n"

        for line in self.text.split("\n"):
            dir = directive(line)
            if dir.type == directive.key:
                key = dir.value.strip()
                if self.original_key:
                    # TODO fix minors
                    tr = chordprobook.chords.transposer(key=key)
                    minor = " (minor)" if tr.minor else ""
                    if self.nashville:
                        chart = chords.ChordChart()
                        song += "\n### Modulate: %s (%+d semitones%s)  \n" % (
                            chart.nashvillize(key,
                                              self.original_key), tr.offset -
                            tr.get_note_index(self.original_key) % 12, minor)
                    else:
                        song += "\n### Change key to %s\n" % self.transposer.transpose_chord(
                            key)
            else:
                song += re.sub("\[(.*?)\]", lambda m: format_chord(m.group(1)),
                               line) + "\n"

        if stand_alone and instrument_name != None:
            title = "%s (%s %s)" % (title, "Left-handed" if self.lefty else "",
                                    instrument_name)

        self.md = song
        self.formatted_title = title
Example #6
0
    def parse(self):
        """ Deal with directives and turn song into markdown"""
        in_tab = False
        in_block = False
        new_text = ""
        current_instrument = None
        add_extra_newline = True
        for line in self.text.split("\n"):
            dir = directive(line)
            if dir.type == None:
                if not line.startswith('#'):
                    line = normalize_chord_markup(line)

                    if in_tab:
                        #Four spaces in Markdown means preformatted
                        pass
                    else:
                        #Highlight chords
                        line = line.replace("][", "] [").strip()
                        line = re.sub(
                            '\[(.*?)\]',
                            '<span class="chord-bracket">[<span class="chord">\\1</span>]</span>',
                            line)
                        if line.startswith("."):
                            line = re.sub("^\.(.*?) (.*)",
                                          "<span class='\\1'>\\1 \\2</span>",
                                          line)

                    if add_extra_newline:
                        new_text += '<div class="spacer"></div>'
                        add_extra_newline = False

                    new_text += "%s\n" % line
            else:

                if dir.type == directive.comment:
                    if in_block:
                        new_text += "</div>"
                        in_block = False
                    if dir.value.startswith("."):
                        dir.value = dir.value[1:]
                        classs = dir.value.split(" ")[0]
                        if classs:
                            in_block = True
                            new_text += "<div class='%s'>" % classs

                    new_text += "\n**%s**\n" % dir.value

                elif dir.type == directive.title:
                    self.title += dir.value

                elif dir.type == directive.subtitle:
                    new_text += "\n**%s**\n" % dir.value

                elif dir.type == directive.artist:
                    new_text += "\n***Artist: ***%s\n" % dir.value

                elif dir.type == directive.composer:
                    new_text += "\n***Composer: ***%s\n" % dir.value

                elif dir.type == directive.lyricist:
                    new_text += "\n***Lyricist: ***%s\n" % dir.value

                elif dir.type == directive.time:
                    new_text += "\n***Time: ***%s\n" % dir.value

                elif dir.type == directive.tempo:
                    new_text += "\n***Tempo: ***%s\n" % dir.value

                elif dir.type == directive.key:
                    if self.original_key:
                        new_text += "%s\n" % line
                    else:
                        self.original_key = dir.value
                        self.key = self.transposer.transpose_chord(
                            self.original_key)

                elif dir.type == directive.transpose:
                    trans = dir.value.split(" ")
                    self.standard_transpositions += [int(x) for x in trans]

                elif dir.type == directive.start_chorus:
                    new_text += "<blockquote class='chorus'>\n"

                elif dir.type == directive.start_bridge:
                    new_text += "<blockquote class='bridge'>\n"

                elif dir.type in [directive.end_chorus, directive.end_bridge]:
                    new_text += "</blockquote>\n"

                elif dir.type == directive.start_tab and not in_tab:
                    in_tab = True
                    new_text += "```\n"

                elif dir.type == directive.end_tab and in_tab:
                    new_text += "```\n"
                    in_tab = False

                elif dir.type == directive.new_page:
                    if in_block:
                        new_text += "</div>\n"
                        in_block = False
                    new_text += "\n<!-- new_page -->\n"
                    self.pages += 1

                elif dir.type == directive.page_image:
                    if in_block:
                        new_text += "</div>\n"
                        in_block = False
                    new_text += "<img src='file://%s/%s' width='680'/>" % (
                        self.dir, dir.value)

                elif dir.type == directive.instrument:
                    inst_name = dir.value
                    if self.local_instruments == None:
                        self.local_instruments = chordprobook.instruments.Instruments(
                        )
                    current_instrument = self.local_instruments.get_instrument_by_name(
                        inst_name)
                    self.local_instrument_names.append(inst_name)
                    if current_instrument == None:
                        current_instrument = chordprobook.instruments.Instrument(
                            name=inst_name)
                        console.log("Loading lefty instrument", inst_name)
                        current_instrument.chart = chords.ChordChart(
                            lefty=self.lefty)
                        self.local_instruments.add_instrument(
                            current_instrument)
                    else:
                        current_instrument.load_chord_chart()

                elif dir.type == directive.define:
                    if current_instrument != None:
                        current_instrument.chart.add_grid(line)

            self.text = new_text
            #Add four spaces to mid-stanza line ends to force Markdown to add breaks
            self.text = re.sub("(.)\n(.)", "\\1    \\n\\2", self.text)
Example #7
0
    def parse(self):
        """ Deal with directives and turn song into markdown"""
        in_chorus = False
        in_tab = False
        in_block = False
        new_text = ""
        current_instrument = None
        for line in self.text.split("\n"):
            dir = directive(line)
            if dir.type == None:
                if not line.startswith('#'):
                    line = normalize_chord_markup(line)
                    if in_chorus:
                        #">" is Markdown for blockquote
                        new_text += "> "

                    if in_tab:
                        #Four spaces in Markdown means preformatted
                        pass
                    else:
                        #Highlight chords
                        line = line.replace("][", "] [").strip()
                        line = re.sub("\[(.*?)\]", "**[\\1]**", line)
                        if line.startswith("."):
                            line = re.sub("^\.(.*?) (.*)",
                                          "<span class='\\1'>\\1 \\2</span>",
                                          line)
                    new_text += "%s\n" % line
            else:

                if dir.type == directive.comment:
                    if in_block:
                        new_text += "</div>"
                        in_block = False
                    if dir.value.startswith("."):
                        dir.value = dir.value[1:]
                        classs = dir.value.split(" ")[0]
                        if classs:
                            in_block = True
                            new_text += "<div class='%s'>" % classs
                    if in_chorus:
                        #">" is Markdown for blockquote
                        new_text += "\n> **%s**\n" % dir.value
                    else:
                        new_text += "\n**%s**\n" % dir.value

                elif dir.type == directive.title:
                    self.title += dir.value

                elif dir.type == directive.subtitle:
                    new_text += "\n**%s**\n" % dir.value

                elif dir.type == directive.key:
                    if self.original_key:
                        new_text += "%s\n" % line
                    else:
                        self.original_key = dir.value
                        self.key = self.transposer.transpose_chord(
                            self.original_key)

                elif dir.type == directive.transpose:
                    trans = dir.value.split(" ")
                    self.standard_transpositions += [int(x) for x in trans]

                elif dir.type in [
                        directive.start_chorus, directive.start_bridge
                ]:
                    #Treat bridge and chorus formatting the same
                    in_chorus = True

                elif dir.type in [directive.end_chorus, directive.end_bridge]:
                    in_chorus = False

                elif dir.type == directive.start_tab and not in_tab:
                    in_tab = True
                    new_text += "```\n"

                elif dir.type == directive.end_tab and in_tab:
                    new_text += "```\n"
                    in_tab = False

                elif dir.type == directive.new_page:
                    if in_block:
                        new_text += "</div>\n"
                        in_block = False
                    new_text += "\n<!-- new_page -->\n"
                    self.pages += 1

                elif dir.type == directive.instrument:
                    inst_name = dir.value
                    if self.local_instruments == None:
                        self.local_instruments = chordprobook.instruments.Instruments(
                        )
                    current_instrument = self.local_instruments.get_instrument_by_name(
                        inst_name)
                    self.local_instrument_names.append(inst_name)
                    if current_instrument == None:
                        current_instrument = chordprobook.instruments.Instrument(
                            name=inst_name)
                        current_instrument.chart = chords.ChordChart()
                        self.local_instruments.add_instrument(
                            current_instrument)
                    else:
                        current_instrument.load_chord_chart()

                elif dir.type == directive.define:
                    if current_instrument != None:
                        current_instrument.chart.add_grid(line)

            self.text = new_text
            #Add four spaces to mid-stanza line ends to force Markdown to add breaks
            self.text = re.sub("(.)\n(.)", "\\1    \\n\\2", self.text)