<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step1:  Class collaboration
Step7:  2. Extend our music-maker
How can we extend our existing music-maker class to handle instances of our new indicator command? One way to do it is to pass a list of of commands to our music-maker at initialization time. The initializer of the revised music-maker implements a keyword argument to do this. Additionally, we've added a method to our music-maker to call these commands, one after the other in a stack. We've also made our music-maker callable. This means that we'll pass time signatures to our music-maker itself, rather than to any of the music-maker's public methods. And we've prefixed the music-maker's methods with underscores. This indicates that users doesn't need to know anything about these methods
Step8:  3.  Initializing commands
Now that we've extended our music-maker to handle indicator commands, we can use the two classes in conjunction. Let's try it out by making indicator commands and passing them to our music-maker
Step9:  4. Making the score
Then we enclose the staff in a score, and the score in a LilyPond file. The stylesheet is housed in the same directory as this notebook
<ASSISTANT_TASK:>
Python Code:
class IndicatorCommand:
    
    Indicator command.
    
    def __init__(self, indicator, selector):
        self.indicator = indicator
        self.selector = selector
    def __call__(self, music):
        for selection in self.selector(music):
            indicator = copy.copy(self.indicator)
            abjad.attach(indicator, selection)
Explanation: Class collaboration: designing interactions between classes
In the previous notebook we defined a music-maker class. In this notebook we'll define a command class. Then we'll extend our music-maker to handle these commands. This gives us the chance to study class collaboration.
1. Define the command class
First we'll define an indicator command. The class will attach indicators to components picked out by a selector:
End of explanation
class MusicMaker:
    def __init__(
        self, 
        counts, 
        denominator, 
        pitches,
        commands=None,
        ):
        self.counts = counts
        self.denominator = denominator
        self.pitches = pitches
        self.commands = commands or ()
        
    def __call__(self, time_signatures):
        
        Calls music-maker on time signatures.
        
        time_signatures = [abjad.TimeSignature(_) for _ in time_signatures]
        staff = self._make_notes_and_rests(
            self.counts,
            self.denominator,
            time_signatures,
            )
        self._impose_time_signatures(staff, time_signatures)
        self._pitch_notes(staff, self.pitches)
        self._call_commands(staff)
        return staff
    def _make_notes_and_rests(self, counts, denominator, time_signatures):
        
        Makes notes and rests.
        
        durations = [_.duration for _ in time_signatures]
        total_duration = sum(durations)
        talea = rmakers.Talea(counts, denominator)
        talea_index = 0
        leaves = []
        current_duration = abjad.Duration(0)
        while current_duration < total_duration:
            leaf_duration = talea[talea_index]
            if 0 < leaf_duration: 
                pitch = abjad.NamedPitch("c'")
            else:
                pitch = None
                leaf_duration = abs(leaf_duration)
            if total_duration < (leaf_duration + current_duration):
                leaf_duration = total_duration - current_duration
            leaves_ = abjad.LeafMaker()([pitch], [leaf_duration])
            leaves.extend(leaves_)
            current_duration += leaf_duration
            talea_index += 1
        staff = abjad.Staff(leaves)
        return staff
    def _impose_time_signatures(self, staff, time_signatures):
        
        Imposes time signatures.
        
        selections = abjad.mutate.split(staff[:], time_signatures, cyclic=True)
        for time_signature, selection in zip(time_signatures, selections):
            abjad.attach(time_signature, selection[0])
        measure_selections = abjad.select(staff).leaves().group_by_measure()
        for time_signature, measure_selection in zip(time_signatures, measure_selections):
            abjad.Meter.rewrite_meter(measure_selection, time_signature)
    def _pitch_notes(self, staff, pitches):
        
        Pitches notes.
        
        pitches = abjad.CyclicTuple(pitches)
        plts = abjad.select(staff).logical_ties(pitched=True)
        for i, plt in enumerate(plts):
            pitch = pitches[i]
            for note in plt:
                note.written_pitch = pitch
    def _call_commands(self, staff):
        
        Calls commands.
        
        for command in self.commands:
            command(staff) 
Explanation: 2. Extend our music-maker
How can we extend our existing music-maker class to handle instances of our new indicator command? One way to do it is to pass a list of of commands to our music-maker at initialization time. The initializer of the revised music-maker implements a keyword argument to do this. Additionally, we've added a method to our music-maker to call these commands, one after the other in a stack. We've also made our music-maker callable. This means that we'll pass time signatures to our music-maker itself, rather than to any of the music-maker's public methods. And we've prefixed the music-maker's methods with underscores. This indicates that users doesn't need to know anything about these methods:  users initialize a music-maker and then call it. Everything else happens behind the scenes:
End of explanation
start_beam_command = IndicatorCommand(
    indicator=abjad.StartBeam(),
    selector=abjad.select().runs().map(abjad.select().leaf(0)),
)
stop_beam_command = IndicatorCommand(
    indicator=abjad.StopBeam(),
    selector=abjad.select().runs().map(abjad.select().leaf(-1)),
)
start_slur_command = IndicatorCommand(
    indicator=abjad.StartSlur(),
    selector=abjad.select().runs().get([0], 2).map(abjad.select().leaf(0)),
)
stop_slur_command = IndicatorCommand(
    indicator=abjad.StopSlur(),
    selector=abjad.select().runs().get([0], 2).map(abjad.select().leaf(-1)),
)
accent_command = IndicatorCommand(
    indicator=abjad.Articulation("accent"),
    selector=abjad.select().runs().map(abjad.select().leaf(0)),
)
staccato_command = IndicatorCommand(
    indicator=abjad.Articulation("staccato"),
    selector=abjad.select().runs().map(abjad.select().leaves()[1:]).flatten(),
)
fast_music_maker = MusicMaker(
    counts=[1, 1, 1, 1, 1, -1],
    denominator=16,
    pitches="d' fs' a' d'' g' ef'".split(),
    commands=[
        start_beam_command,
        stop_beam_command,
        start_slur_command,
        stop_slur_command,
        accent_command,
        staccato_command,
    ],
)
staff = fast_music_maker(6 * [(3, 4), (5, 8), (4, 4)])
Explanation: 3.  Initializing commands
Now that we've extended our music-maker to handle indicator commands, we can use the two classes in conjunction. Let's try it out by making indicator commands and passing them to our music-maker:
End of explanation
score = abjad.Score([staff])
lilypond_file = abjad.LilyPondFile.new(
    music=score,
    includes=["stylesheet.ily"],
)
abjad.show(lilypond_file)
Explanation: 4. Making the score
Then we enclose the staff in a score, and the score in a LilyPond file. The stylesheet is housed in the same directory as this notebook:
End of explanation
<END_TASK>