Walk the Salt install tree and return a dictionary or a list
    of the functions therein as well as their arguments.

    :param modules: Walk the modules directory if True
    :param states: Walk the states directory if True
    :param names_only: Return only a list of the callable functions instead of a dictionary with arguments
    :return: An OrderedDict with callable function names as keys and lists of arguments as
             values (if ``names_only``==False) or simply an ordered list of callable
             function nanes (if ``names_only``==True).

    CLI Example:
    (example truncated for brevity)

    .. code-block:: bash

        salt myminion baredoc.modules_and_args

        myminion:
            ----------
        [...]
            at.atrm:
            at.jobcheck:
            at.mod_watch:
                - name
            at.present:
                - unique_tag
                - name
                - timespec
                - job
                - tag
                - user
            at.watch:
                - unique_tag
                - name
                - timespec
                - job
                - tag
                - user
        [...]

def modules_and_args(modules=True, states=False, names_only=False):
    '''
    Walk the Salt install tree and return a dictionary or a list
    of the functions therein as well as their arguments.

    :param modules: Walk the modules directory if True
    :param states: Walk the states directory if True
    :param names_only: Return only a list of the callable functions instead of a dictionary with arguments
    :return: An OrderedDict with callable function names as keys and lists of arguments as
             values (if ``names_only``==False) or simply an ordered list of callable
             function nanes (if ``names_only``==True).

    CLI Example:
    (example truncated for brevity)

    .. code-block:: bash

        salt myminion baredoc.modules_and_args

        myminion:
            ----------
        [...]
            at.atrm:
            at.jobcheck:
            at.mod_watch:
                - name
            at.present:
                - unique_tag
                - name
                - timespec
                - job
                - tag
                - user
            at.watch:
                - unique_tag
                - name
                - timespec
                - job
                - tag
                - user
        [...]
    '''
    dirs = []
    module_dir = os.path.dirname(os.path.realpath(__file__))
    state_dir = os.path.join(os.path.dirname(module_dir), 'states')

    if modules:
        dirs.append(module_dir)
    if states:
        dirs.append(state_dir)

    ret = _mods_with_args(dirs)
    if names_only:
        return sorted(ret.keys())
    else:
        return OrderedDict(sorted(ret.items()))