from abjad.tools.componenttools.component_to_score_index import component_to_score_index
from abjad.tools.componenttools.iterate_components_forward_in_expr import iterate_components_forward_in_expr


def iterate_timeline_forward_in_expr(expr, klass=None):
    r'''.. versionadded:: 2.0

    Iterate timeline forward in `expr`::

        abjad> score = Score([])
        abjad> score.append(Staff(notetools.make_repeated_notes(4, Duration(1, 4))))
        abjad> score.append(Staff(notetools.make_repeated_notes(4)))
        abjad> pitchtools.set_ascending_named_diatonic_pitches_on_nontied_pitched_components_in_expr(score)
        abjad> f(score)
        \new Score <<
            \new Staff {
                c'4
                d'4
                e'4
                f'4
            }
            \new Staff {
                g'8
                a'8
                b'8
                c''8
            }
        >>
        abjad> for leaf in componenttools.iterate_timeline_forward_in_expr(score):
        ...     leaf
        ...
        Note("c'4")
        Note("g'8")
        Note("a'8")
        Note("d'4")
        Note("b'8")
        Note("c''8")
        Note("e'4")
        Note("f'4")

    Iterate leaves when `klass` is none.

    .. todo:: optimize to avoid behind-the-scenes full-score traversal.
    '''
    from abjad.tools.leaftools.Leaf import Leaf

    if klass is None:
        klass = Leaf

    component_generator = iterate_components_forward_in_expr(expr, klass = klass)
    components = list(component_generator)

    def _sort_helper(component_1, component_2):
        result = cmp(component_1._offset.start,
            component_2._offset.start)
        if result == 0:
            return cmp(
                component_to_score_index(component_1),
                component_to_score_index(component_2))
        else:
            return result

    components.sort(_sort_helper)

    for component in components:
        yield component
