Esempio n. 1
0
def add_scope(commit_msg):
    Ansi.print_info(
        wrap_width(
            "\nWhat is the scope / a noun describing section of repo? (try to keep under 15 characters)"
        ))
    text = Ansi.colour(Ansi.fg.bright_green, "Scope (optional): ")
    history_file_path = os.path.join(CONFIG_HOME_DIR, "scope_history")
    c_scope = prompt(ANSI(text),
                     history=FileHistory(history_file_path),
                     key_bindings=bindings).strip()

    if c_scope != "":
        commit_msg += "({})".format(c_scope)

    return commit_msg
Esempio n. 2
0
def add_footer(commit_msg):
    Ansi.print_info(
        wrap_width([
            "\nThe footer MUST contain meta-information about the commit:",
            " - Related pull-requests, reviewers, breaking changes",
            " - GitHub close/fix/resolve #issue or username/repository#issue",
            " - One piece of meta-information per-line",
            " - To submit, press the Esc key before Enter",
        ]))

    text = Ansi.colour(Ansi.fg.bright_green, "Footer (optional) ┃ ")
    history_file_path = os.path.join(CONFIG_HOME_DIR, "footer_history")
    session = PromptSession(
        completer=FooterCompleter(),
        multiline=False,
        prompt_continuation=custom_prompt_continuation,
        history=FileHistory(history_file_path),
        key_bindings=bindings,
    )
    c_footer = session.prompt(ANSI(text),
                              validator=FooterValidator(session)).strip()

    if c_footer != "":
        f_lines = c_footer.split("\n")
        f_lines = [l for l in f_lines
                   if l.strip() != ""]  # remove any lines that are empty: ""

        for i, line in enumerate(f_lines):
            line = line.strip()  # clean up extraneous whitespace

            # format each line with forced line breaks to maintain maximum line length
            f_lines[i] = "\n".join(
                textwrap.wrap(
                    line,
                    width=72,
                    break_long_words=False,
                    break_on_hyphens=False,
                    subsequent_indent="  ",
                ))

        # recombine all user defined footer lines
        formatted_footer = "\n".join(f_lines)
        commit_msg += "\n\n" + formatted_footer

    return commit_msg
Esempio n. 3
0
def run(args):
    # print(sys.version + "/n")

    if len(args) > 0 and args[0] in ["version", "update"]:
        check_for_update(verbose=True)
        return  # Exit early

    # Ensure the config directory exists
    os.makedirs(CONFIG_HOME_DIR, exist_ok=True)

    commits_file_path = os.path.join(CONFIG_HOME_DIR, "commit_msg_history")
    commit_msg_history = FileHistory(commits_file_path)

    if WINDOW_WIDTH < 80:
        Ansi.print_error(
            f"It is recommended you increase your window width ({WINDOW_WIDTH}) to at least 80."
        )

    commit_msg = ""
    if len(args) > 0 and args[0] == "retry":
        args = args[1:]  # consume the "retry" first arg
        cm_histories_iter = commit_msg_history.load_history_strings()
        last_commit_msg = next(cm_histories_iter, "")
        if last_commit_msg == "":
            Ansi.print_error("Could not find a previous commit message")
        commit_msg = last_commit_msg

    if commit_msg == "":
        print("Starting a conventional git commit...")
        print(
            Ansi.colour(Ansi.fg.bright_red,
                        "Tip: Press the up arrow key to recall history!"))
        commit_msg = add_type(commit_msg)
        commit_msg = add_scope(commit_msg)
        check_if_breaking_change()
        commit_msg = add_description(commit_msg)
        commit_msg = add_body(commit_msg)
        commit_msg = add_footer(commit_msg)
        print()

    Ansi.print_ok("This is your commit message:")
    print()
    print(commit_msg)
    print()

    # print("\nNOTE: This was a dry run and no commit was made.\n")

    # It is expected that all remaining args at this point are for the git
    # commit command
    args_string = " ".join(args)
    text = Ansi.colour(Ansi.fg.bright_yellow, "Extra args for git commit: ")
    extra_args_file_path = os.path.join(CONFIG_HOME_DIR, "extra_args_history")
    extra_args_str = prompt(
        ANSI(text),
        default=args_string,
        history=FileHistory(extra_args_file_path),
        key_bindings=bindings,
    )
    if extra_args_str != "":
        argv_passthrough = extra_args_str.split(" ")
    else:
        argv_passthrough = []

    # Ask for confirmation to commit
    confirmation_validator = YesNoValidator(answer_required=True)
    text = Ansi.b_yellow("Do you want to make your commit? [y/n] ")
    confirm = prompt(ANSI(text),
                     validator=confirmation_validator,
                     key_bindings=bindings).lower()

    if confirm in confirmation_validator.confirmations:
        commit_msg_history.store_string(commit_msg)
        cmds = ["git", "commit", "-m", commit_msg] + argv_passthrough
        returncode = subprocess.run(cmds).returncode
        print()
        if returncode == 0:
            Ansi.print_ok(
                "\nCommit has been made to conventional commits standards!")
        else:
            Ansi.print_error(
                "\nThere was an error whilst attempting the commit!")

    elif confirm in confirmation_validator.rejections:
        print("Aborting the commit...")

    check_for_update()
Esempio n. 4
0
def add_body(commit_msg):
    if IS_BREAKING_CHANGE is None:
        raise ValueError(
            "Global variable `IS_BREAKING_CHANGE` has not been set.")

    history_file_path = os.path.join(CONFIG_HOME_DIR, "body_history")
    session = PromptSession(
        prompt_continuation=custom_prompt_continuation,
        history=FileHistory(history_file_path),
        key_bindings=bindings,
    )
    body_validator = BodyValidator(session, IS_BREAKING_CHANGE)

    if IS_BREAKING_CHANGE:
        Ansi.print_info(
            wrap_width([
                "\nExplain what has changed in this commit to cause breaking changes.",
                "Press Esc before Enter to submit.",
            ]))
        # text = Ansi.b_green("Body (required) ┃ ")
        text = Ansi.colour(Ansi.fg.bright_green, Ansi.bold, "Body ┃ ")
    else:
        Ansi.print_info(
            wrap_width([
                "\nProvide additional contextual information about the changes here.",
                "Press Esc before Enter to submit.",
            ]))
        text = Ansi.colour(Ansi.fg.bright_green, "Body (optional) ┃ ")

    c_body = session.prompt(ANSI(text), validator=body_validator)
    c_body = c_body.strip()  # remove leading/trailing whitespace
    c_body = capitaliseFirst(c_body)  # capital first letter

    if c_body != "":
        if IS_BREAKING_CHANGE:
            c_body = "BREAKING CHANGE: " + c_body

        b_lines = c_body.split("\n")
        num_blank_lines = 0  # track the number of consecutive blank lines

        condensed_b_lines = []
        for line in b_lines:
            l_stripped = line.strip()
            if l_stripped == "":
                num_blank_lines += 1
            else:
                num_blank_lines = 0

            if num_blank_lines > 1:
                continue  # ignore any blank lines after the first
            elif l_stripped == "":
                # skip any processing and add to output if blank
                condensed_b_lines.append(l_stripped)
            else:
                # check if we are dealing with a bulleted line
                bulleted_line = False
                if l_stripped[0] in ["*", "-"]:
                    bulleted_line = True
                    line_after_bullet = l_stripped[1:].strip()
                    l_stripped = " " + l_stripped[0] + " " + line_after_bullet

                # format each line with forced line breaks to maintain maximum line length
                wrapped_line = "\n".join(
                    textwrap.wrap(
                        l_stripped,
                        width=72,
                        break_long_words=False,
                        break_on_hyphens=False,
                        subsequent_indent="   " if bulleted_line else "",
                    ))
                condensed_b_lines.append(wrapped_line)

        # recombine all user defined lines
        full_body = "\n".join(condensed_b_lines)

        # append to commit message
        commit_msg += "\n\n" + full_body

    return commit_msg
Esempio n. 5
0
def custom_prompt_continuation(width, line_number, is_soft_wrap):
    text_continuation = " " * (width - 2) + "┃ "
    return ANSI(Ansi.colour(Ansi.fg.bright_green, text_continuation))