# Path: shovel/tasks.py
# class Shovel(object):
#     '''A collection of tasks contained in a file or folder'''
#     @classmethod
#     def load(cls, path, base=None):
#         '''Either load a path and return a shovel object or return None'''
#         obj = cls()
#         obj.read(path, base)
#         return obj
# 
#     def __init__(self, tasks=None):
#         self.overrides = None
#         self._tasks = tasks or []
#         self.map = defaultdict(Shovel)
#         self.extend(tasks or [])
# 
#     def extend(self, tasks):
#         '''Add tasks to this particular shovel'''
#         self._tasks.extend(tasks)
#         for task in tasks:
#             # We'll now go through all of our tasks and group them into
#             # sub-shovels
#             current = self.map
#             modules = task.fullname.split('.')
#             for module in modules[:-1]:
#                 if not isinstance(current[module], Shovel):
#                     logger.warn('Overriding task %s with a module' %
#                         current[module].file)
#                     shovel = Shovel()
#                     shovel.overrides = current[module]
#                     current[module] = shovel
#                 current = current[module].map
# 
#             # Now we'll put the task in this particular sub-shovel
#             name = modules[-1]
#             if name in current:
#                 logger.warn('Overriding %s with %s' % (
#                     '.'.join(modules), task.file))
#                 task.overrides = current[name]
#             current[name] = task
# 
#     def read(self, path, base=None):
#         '''Import some tasks'''
#         if base == None:
#             base = os.getcwd()
#         absolute = os.path.abspath(path)
#         if os.path.isfile(absolute):
#             # Load that particular file
#             logger.info('Loading %s' % absolute)
#             self.extend(Task.load(path, base))
#         elif os.path.isdir(absolute):
#             # Walk this directory looking for tasks
#             tasks = []
#             for root, _, files in os.walk(absolute):
#                 files = [f for f in files if f.endswith('.py')]
#                 for child in files:
#                     absolute = os.path.join(root, child)
#                     logger.info('Loading %s' % absolute)
#                     tasks.extend(Task.load(absolute, base))
#             self.extend(tasks)
# 
#     def __getitem__(self, key):
#         '''Find a task with the provided name'''
#         current = self.map
#         split = key.split('.')
#         for module in split[:-1]:
#             if module not in current:
#                 raise KeyError('Module not found')
#             current = current[module].map
#         if split[-1] not in current:
#             raise KeyError('Task not found')
#         return current[split[-1]]
# 
#     def __contains__(self, key):
#         try:
#             return bool(self.__getitem__(key))
#         except KeyError:
#             return False
# 
#     def keys(self):
#         '''Return all valid keys'''
#         keys = []
#         for key, value in self.map.items():
#             if isinstance(value, Shovel):
#                 keys.extend([key + '.' + k for k in value.keys()])
#             else:
#                 keys.append(key)
#         return sorted(keys)
# 
#     def items(self):
#         '''Return a list of tuples of all the keys and tasks'''
#         pairs = []
#         for key, value in self.map.items():
#             if isinstance(value, Shovel):
#                 pairs.extend([(key + '.' + k, v) for k, v in value.items()])
#             else:
#                 pairs.append((key, value))
#         return sorted(pairs)
# 
#     def tasks(self, name):
#         '''Get all the tasks that match a name'''
#         found = self[name]
#         if isinstance(found, Shovel):
#             return [v for _, v in found.items()]
#         return [found]


import re
from shovel.tasks import Shovel
    '''Given a shovel of tasks, display a heirarchical list of the tasks'''
    result = []
    tuples = heirarchical_helper(shovel, prefix)
    if not tuples:
        return ''

    # We need to figure out the longest fullname length
    longest = max(len(name + '    ' * level) for name, _, level in tuples)
    fmt = '%%%is => %%-50s' % longest
    for name, docstring, level in tuples:
        if docstring == None:
            result.append('    ' * level + name + '/')
        else:
            docstring = re.sub(r'\s+', ' ', docstring).strip()
            if len(docstring) > 50:
                docstring = docstring[:47] + '...'
            result.append(fmt % (name, docstring))
    return '\n'.join(result)


def shovel_help(shovel, *names):
    '''Return a string about help with the tasks, or lists tasks available'''
    # If names are provided, and the name refers to a group of tasks, print out
    # the tasks and a brief docstring. Otherwise, just enumerate all the tasks
    # available
    if not len(names):
        return heirarchical_help(shovel, '')
    else:
        for name in names:
            task = shovel[name]

# Path: shovel/tasks.py
# class Shovel(object):
#     '''A collection of tasks contained in a file or folder'''
#     @classmethod
#     def load(cls, path, base=None):
#         '''Either load a path and return a shovel object or return None'''
#         obj = cls()
#         obj.read(path, base)
#         return obj
# 
#     def __init__(self, tasks=None):
#         self.overrides = None
#         self._tasks = tasks or []
#         self.map = defaultdict(Shovel)
#         self.extend(tasks or [])
# 
#     def extend(self, tasks):
#         '''Add tasks to this particular shovel'''
#         self._tasks.extend(tasks)
#         for task in tasks:
#             # We'll now go through all of our tasks and group them into
#             # sub-shovels
#             current = self.map
#             modules = task.fullname.split('.')
#             for module in modules[:-1]:
#                 if not isinstance(current[module], Shovel):
#                     logger.warn('Overriding task %s with a module' %
#                         current[module].file)
#                     shovel = Shovel()
#                     shovel.overrides = current[module]
#                     current[module] = shovel
#                 current = current[module].map
# 
#             # Now we'll put the task in this particular sub-shovel
#             name = modules[-1]
#             if name in current:
#                 logger.warn('Overriding %s with %s' % (
#                     '.'.join(modules), task.file))
#                 task.overrides = current[name]
#             current[name] = task
# 
#     def read(self, path, base=None):
#         '''Import some tasks'''
#         if base == None:
#             base = os.getcwd()
#         absolute = os.path.abspath(path)
#         if os.path.isfile(absolute):
#             # Load that particular file
#             logger.info('Loading %s' % absolute)
#             self.extend(Task.load(path, base))
#         elif os.path.isdir(absolute):
#             # Walk this directory looking for tasks
#             tasks = []
#             for root, _, files in os.walk(absolute):
#                 files = [f for f in files if f.endswith('.py')]
#                 for child in files:
#                     absolute = os.path.join(root, child)
#                     logger.info('Loading %s' % absolute)
#                     tasks.extend(Task.load(absolute, base))
#             self.extend(tasks)
# 
#     def __getitem__(self, key):
#         '''Find a task with the provided name'''
#         current = self.map
#         split = key.split('.')
#         for module in split[:-1]:
#             if module not in current:
#                 raise KeyError('Module not found')
#             current = current[module].map
#         if split[-1] not in current:
#             raise KeyError('Task not found')
#         return current[split[-1]]
# 
#     def __contains__(self, key):
#         try:
#             return bool(self.__getitem__(key))
#         except KeyError:
#             return False
# 
#     def keys(self):
#         '''Return all valid keys'''
#         keys = []
#         for key, value in self.map.items():
#             if isinstance(value, Shovel):
#                 keys.extend([key + '.' + k for k in value.keys()])
#             else:
#                 keys.append(key)
#         return sorted(keys)
# 
#     def items(self):
#         '''Return a list of tuples of all the keys and tasks'''
#         pairs = []
#         for key, value in self.map.items():
#             if isinstance(value, Shovel):
#                 pairs.extend([(key + '.' + k, v) for k, v in value.items()])
#             else:
#                 pairs.append((key, value))
#         return sorted(pairs)
# 
#     def tasks(self, name):
#         '''Get all the tasks that match a name'''
#         found = self[name]
#         if isinstance(found, Shovel):
#             return [v for _, v in found.items()]
#         return [found]


# Path: shovel/help.py
import re
from shovel.tasks import Shovel

    '''Given a shovel of tasks, display a heirarchical list of the tasks'''
    result = []
    tuples = heirarchical_helper(shovel, prefix)
    if not tuples:
        return ''

    # We need to figure out the longest fullname length
    longest = max(len(name + '    ' * level) for name, _, level in tuples)
    fmt = '%%%is => %%-50s' % longest
    for name, docstring, level in tuples:
        if docstring == None:
            result.append('    ' * level + name + '/')
        else:
            docstring = re.sub(r'\s+', ' ', docstring).strip()
            if len(docstring) > 50:
                docstring = docstring[:47] + '...'
            result.append(fmt % (name, docstring))
    return '\n'.join(result)


def shovel_help(shovel, *names):
    '''Return a string about help with the tasks, or lists tasks available'''
    # If names are provided, and the name refers to a group of tasks, print out
    # the tasks and a brief docstring. Otherwise, just enumerate all the tasks
    # available
    if not len(names):
        return heirarchical_help(shovel, '')
    else:
        for name in names:
            task = shovel[name]

            if isinstance(task, Shovel):