def post_preview(body, char_limit):
    """
    Returns a preview of the post body. Will include all complete words as
    long as char_limit is not surpassed. If any words are omitted due to going
    over the character limit, appends '...' at the end.

    :param body: the post body.
    :type body: str
    :param char_limit: the character limit for the preview.
    :type char_limit: int
    :return: a string with all words from body that fit in char_limit.
    :rtype: str
    """
    if len(body) <= char_limit:
        return body

    preview = body[:char_limit]

    last_char = char_limit - 1
    while preview[last_char].isalpha():
        preview = preview[:last_char]
        last_char -= 1

    while not preview[last_char].isalpha():
        preview = preview[:last_char]
        last_char -= 1

    preview += '...'

    return preview