'Return the tag just before the current cursor as a source line
number and a list of tags defined on that line up to and including the
containing tag. If ``for_position_sync`` is False then the tag
*containing* the cursor is returned instead of the tag just before the
cursor. Note that finding the containing tag is expensive, so
use with care. As an optimization, the last tag matched by
get_extra_selections is used, unless use_matched_tag is False.'

def cursor_position_with_sourceline(self, cursor, for_position_sync=True, use_matched_tag=True):

    (block, offset) = (cursor.block(), cursor.positionInBlock())
    if for_position_sync:
        (nblock, boundary) = next_tag_boundary(block, offset, forward=False)
        if (boundary is None):
            return (None, None)
        if boundary.is_start:
            (start_block, start_offset) = (nblock, boundary.offset)
        else:
            start_block = None
            while ((start_block is None) and block.isValid()):
                ud = block.userData()
                if (ud is not None):
                    for boundary in reversed(ud.tags):
                        if (boundary.is_start and (not boundary.closing) and (boundary.offset <= offset)):
                            (start_block, start_offset) = (block, boundary.offset)
                            break
                (block, offset) = (block.previous(), sys.maxint)
        end_block = None
        if (start_block is not None):
            (end_block, boundary) = next_tag_boundary(start_block, start_offset)
            if ((boundary is None) or boundary.is_start):
                return (None, None)
    else:
        tag = None
        if use_matched_tag:
            tag = self.last_matched_tag
        if (tag is None):
            tag = find_closest_containing_tag(block, offset, max_tags=2000)
        if (tag is None):
            return (None, None)
        (start_block, start_offset, end_block) = (tag.start_block, tag.start_offset, tag.end_block)
    if ((start_block is None) or (end_block is None)):
        return (None, None)
    sourceline = (end_block.blockNumber() + 1)
    ud = start_block.userData()
    if (ud is None):
        return (None, None)
    tags = [t.name for t in ud.tags if (t.is_start and (not t.closing) and (t.offset <= start_offset))]
    if (start_block.blockNumber() != end_block.blockNumber()):
        del tags[:(-1)]
    return (sourceline, tags)
