import os
import re
import shutil
import sys

import click
import six

from great_expectations import DataContext
from great_expectations.cli.init_messages import (
    NEW_TEMPLATE_INSTALLED,
    NEW_TEMPLATE_PROMPT,
)

try:
    from termcolor import colored
except ImportError:
    colored = None


def cli_message(string):
    # the DOTALL flag means that `.` includes newlines for multiline comments inside these tags
    flags = re.DOTALL
    mod_string = re.sub(
        "<blue>(.*?)</blue>", colored("\g<1>", "blue"), string, flags=flags
    )
    mod_string = re.sub(
        "<cyan>(.*?)</cyan>", colored("\g<1>", "cyan"), mod_string, flags=flags
    )
    mod_string = re.sub(
        "<green>(.*?)</green>", colored("\g<1>", "green"), mod_string, flags=flags
    )
    mod_string = re.sub(
        "<yellow>(.*?)</yellow>", colored("\g<1>", "yellow"), mod_string, flags=flags
    )
    mod_string = re.sub(
        "<red>(.*?)</red>", colored("\g<1>", "red"), mod_string, flags=flags
    )

    six.print_(colored(mod_string))


def cli_message_list(string_list, list_intro_string=None):
    if list_intro_string:
        cli_message(list_intro_string)
    for string in string_list:
        cli_message(string)


def is_sane_slack_webhook(url):
    """Really basic sanity checking."""
    if url is None:
        return False

    return "https://hooks.slack.com/" in url.strip()

@@ -1214,24 +1214,2074 @@
 e(string)%0A%0A%0A
+def action_list_to_string(action_list):%0A    action_list_string = %22%22%0A    for idx, action in enumerate(action_list):%0A        action_list_string += %22%7B%7D (%7B%7D)%22.format(action%5B%22name%22%5D, action%5B%22action%22%5D%5B%22class_name%22%5D)%0A        if idx == len(action_list) - 1:%0A            continue%0A        action_list_string += %22 =%3E %22%0A    return action_list_string%0A%0A%0Adef cli_message_dict(dict_, indent=3, bullet_char=%22-%22, message_list=None, recursion_flag=False):%0A    if message_list is None:%0A        message_list = %5B%5D%0A    if dict_.get(%22name%22):%0A        name = dict_.pop(%22name%22)%0A        message = %22%7B%7D%3Ccyan%3Ename:%3C/cyan%3E %7B%7D%22.format(%22 %22 * indent, name)%0A        message_list.append(message)%0A    if dict_.get(%22module_name%22):%0A        module_name = dict_.pop(%22module_name%22)%0A        message = %22%7B%7D%3Ccyan%3Emodule_name:%3C/cyan%3E %7B%7D%22.format(%22 %22 * indent, module_name)%0A        message_list.append(message)%0A    if dict_.get(%22class_name%22):%0A        class_name = dict_.pop(%22class_name%22)%0A        message = %22%7B%7D%3Ccyan%3Eclass_name:%3C/cyan%3E %7B%7D%22.format(%22 %22 * indent, class_name)%0A        message_list.append(message)%0A    if dict_.get(%22action_list%22):%0A        action_list = dict_.pop(%22action_list%22)%0A        action_list_string = action_list_to_string(action_list)%0A        message = %22%7B%7D%3Ccyan%3Eaction_list:%3C/cyan%3E %7B%7D%22.format(%22 %22 * indent, action_list_string)%0A        message_list.append(message)%0A    for key, val in dict_.items():%0A        if key == %22credentials%22:%0A            continue%0A        if isinstance(val, dict):%0A            message = %22%7B%7D%3Ccyan%3E%7B%7D:%3C/cyan%3E%22.format(%22 %22 * indent, key)%0A            message_list.append(message)%0A            cli_message_dict(val, indent=indent + 2, message_list=message_list, recursion_flag=True)%0A        else:%0A            message = %22%7B%7D%3Ccyan%3E%7B%7D:%3C/cyan%3E %7B%7D%22.format(%22 %22 * indent, key, str(val))%0A            message_list.append(message)%0A    if recursion_flag == False:%0A        if bullet_char and indent %3E 1:%0A            first = message_list%5B0%5D%0A            new_first = first%5B:1%5D + bullet_char + first%5B2:%5D%0A            message_list%5B0%5D = new_first%0A        cli_message_list(message_list)%0A%0A%0A
 def is_sane_

Add util function for printing dicts in cli