def generate(categorize=unicodedata.category, group_class=RangeGroup):
    '''
    Generate a dict of RangeGroups for each unicode character category,
    including general ones.

    :param categorize: category function, defaults to unicodedata.category.
    :type categorize: callable
    :param group_class: class for range groups, defaults to RangeGroup
    :type group_class: type
    :returns: dictionary of categories and range groups
    :rtype: dict of RangeGroup
    '''
    categories = collections.defaultdict(list)
    last_category = None
    last_range = None
    for c in range(sys.maxunicode + 1):
        category = categorize(chr(c))
        if category != last_category:
            last_category = category
            last_range = [c, c + 1]
            categories[last_category].append(last_range)
        else:
            last_range[1] += 1
    categories = {k: group_class(v) for k, v in categories.items()}
    categories.update({
        k: merge(*map(categories.__getitem__, g))
        for k, g in itertools.groupby(sorted(categories), key=lambda k: k[0])
        })
    return categories