def add_description(commit_msg): if IS_BREAKING_CHANGE is None: raise ValueError( "Global variable `IS_BREAKING_CHANGE` has not been set.") if IS_BREAKING_CHANGE: commit_msg += "!: " else: commit_msg += ": " num_chars_remaining = 50 - len(commit_msg) Ansi.print_info( wrap_width( "\nWhat is the commit description / title. A short summary of the code changes. Use the imperative mood. No more than {} characters." .format(num_chars_remaining))) c_descr = "" history_file_path = os.path.join(CONFIG_HOME_DIR, "description_history") session = PromptSession(history=FileHistory(history_file_path), key_bindings=bindings) length_prompt = LineLengthPrompt(num_chars_remaining, session) while c_descr == "": text = Ansi.b_green("Description: ") c_descr = session.prompt( ANSI(text), validator=DescriptionValidator(num_chars_remaining), rprompt=length_prompt.get_text, ) # Sanitise c_descr = c_descr.strip() # remove whitespace c_descr = capitaliseFirst(c_descr) # capital first letter if c_descr[-1] == ".": c_descr = c_descr[:-1] # remove period if last character c_descr = c_descr.strip() # remove further whitespace commit_msg += c_descr return commit_msg
def add_type(commit_msg): valid_types = { "feat": "MUST be used the commit adds/builds toward a new feature", "fix": "MUST be used when a commit represents a bug fix", "chore": "Any change to build system, dependencies, config files, scripts (no production code)", "docs": "Changes to documentation", "perf": "Changes that improves performance", "refactor": "Refactoring production code, e.g. renaming a variable/restructuring existing logic", "revert": "Any commit that explicitly reverts part/all changes introduced in a previous commit", "style": "Changes to white-space, formatting, missing semi-colons, etc.", "test": "Changes to tests e.g. adding a new/missing test or fixing/correcting existing tests", "wip": "Any code changes that are work in progress; they may not build (use these sparingly!)", } Ansi.print_info( wrap_width([ "Please specify the type of this commit using one of the available keywords. Accepted types: ", "TAB to autocomplete...", ])) type_names = sorted(valid_types.keys()) # create prefixes e.g. " 0 chore" prefixes = [" " + str(i) + " " + t for i, t in enumerate(type_names)] prefix_length = max([len(p) for p in prefixes]) + 2 for i in range(len(type_names)): # type descriptions type_descr_width = WINDOW_WIDTH - prefix_length descr_lines = textwrap.wrap( valid_types[type_names[i]], width=type_descr_width, subsequent_indent=" " * prefix_length, break_long_words=False, ) # ensure each line has trailing whitespace, then do join type_descr_str = "".join( map(lambda l: l.ljust(type_descr_width), descr_lines)) # Combine type name with type description type_print = prefixes[i].ljust(prefix_length) + type_descr_str # Print the type Ansi.print_warning(type_print) valid_numeric_types = [str(n) for n in range(len(type_names))] valid_inputs = list(valid_types.keys()) + valid_numeric_types print() text = Ansi.b_green("Type: ") history_file_path = os.path.join(CONFIG_HOME_DIR, "type_history") c_type = prompt( ANSI(text), completer=TypeCompleter(), validator=TypeValidator(valid_inputs), history=FileHistory(history_file_path), key_bindings=bindings, ) # Convert from number back to proper type name if c_type in valid_numeric_types: c_type = type_names[int(c_type)] commit_msg += c_type return commit_msg