Skip to content

Instantly share code, notes, and snippets.

@stanislaw
Last active November 16, 2024 19:59
Show Gist options
  • Select an option

  • Save stanislaw/e31f6dd84426ef7aedb6c110d9237729 to your computer and use it in GitHub Desktop.

Select an option

Save stanislaw/e31f6dd84426ef7aedb6c110d9237729 to your computer and use it in GitHub Desktop.

Revisions

  1. stanislaw revised this gist Nov 16, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion hotkey.py
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ def branch_latest(self, all=False):
    args = [
    "git",
    "for-each-ref",
    "--sort=committerdate",
    "--sort=committerdate",
    "--format=%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))"
    ]
    if not all:
  2. stanislaw created this gist Nov 16, 2024.
    394 changes: 394 additions & 0 deletions hotkey.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,394 @@
    #! /usr/bin/env python

    import sys
    import subprocess
    import termios
    import tty
    from datetime import datetime
    from pathlib import Path
    from typing import Optional


    class RFXCustomFormatter:
    inverted = "\x1b[7;90m"
    reset = "\x1b[0m"

    @staticmethod
    def print(message: str, color: str):
    print(RFXCustomFormatter.format(message, color))

    @staticmethod
    def format(message: str, color: str):
    return color + message + RFXCustomFormatter.reset


    class GitClient:
    def add_all(self):
    command = "git add -A"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(command.split(" "), capture_output=False, text=True)

    def branch_latest(self, all=False):
    args = [
    "git",
    "for-each-ref",
    "--sort=committerdate",
    "--format=%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))"
    ]
    if not all:
    args.append("refs/heads/")
    command = " ".join(args)
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def commit(self, amend=False, no_edit=False, message=None):
    args = ["git", "commit"]
    if amend:
    args.append("--amend")
    if no_edit:
    args.append("--no-edit")
    if message is not None:
    args.append("-m")
    args.append(message)
    command = " ".join(args)
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def commit_new_or_amend_existing(self):
    result = subprocess.run(["git", "show", "--summary"], capture_output=True, text=True)
    if "Merge:" in result.stdout:
    self.commit(message="WIP: ...")
    return
    self.commit(amend=True, no_edit=True)

    def diff(self, target=None):
    args = ["git", "diff"]
    if target is not None:
    args.append(target)
    command = " ".join(args)
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def fetch(self):
    command = "git fetch"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(command.split(" "), capture_output=False, text=True)

    def log(self, commits: Optional[int] = None):
    args = ["git", "log"]
    if commits is not None:
    assert isinstance(commits, int), commits
    args.append(f"-l{commits}")
    command = " ".join(args)
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def push(self, force=False):
    args = ["git", "push"]
    if force:
    args.append("--force")
    command_color = RFXCustomFormatter.inverted
    command = " ".join(args)
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def pull(self):
    args = ["git", "pull"]
    command_color = RFXCustomFormatter.inverted
    command = " ".join(args)
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def rebase(self, branch: str):
    assert isinstance(branch, str)
    command = f"git rebase {branch}"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(command.split(" "), capture_output=False, text=True)

    def rebase_interactive(self):
    command = "git rebase origin/main -i"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(command.split(" "), capture_output=False, text=True)

    def show(self):
    command = "git show"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(command.split(" "), capture_output=False, text=True)

    def status(self):
    status_command = "git status"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(status_command, command_color)
    subprocess.run(status_command.split(" "), capture_output=False, text=True)

    def switch_to_main(self):
    switch_command = "git switch main"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(switch_command, command_color)
    subprocess.run(switch_command.split(" "), capture_output=False, text=True)

    def switch_to_previous_branch(self):
    switch_command = "git switch -"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(switch_command, command_color)
    subprocess.run(switch_command.split(" "), capture_output=False, text=True)

    def reset_soft_unstage(self, target=None):
    args = ["git", "reset"]
    if target is not None:
    args.append(target)
    command = " ".join(args)
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(command, command_color)
    subprocess.run(args, capture_output=False, text=True)

    def reset_hard(self):
    # First, preserve the diff.
    print("")
    self._apply_patch()
    print("")

    reset_command = "git reset --hard"
    command_color = RFXCustomFormatter.inverted
    RFXCustomFormatter.print(reset_command, command_color)
    subprocess.run(reset_command.split(" "), capture_output=False, text=True)

    def _apply_patch(self):
    result = subprocess.run("git diff HEAD".split(" "), capture_output=True, text=True)
    assert result.returncode == 0
    if len(result.stdout) == 0:
    print(
    f"**********************************************************************"
    )
    print(f"The diff is empty. Not creating a patch.")
    print(
    f"**********************************************************************"
    )
    return

    path_to_user_dir = Path.home()
    patches_dir = path_to_user_dir.joinpath("patches")
    patches_dir.mkdir(parents=True, exist_ok=True)

    now = datetime.now()
    formatted_date = now.strftime('%Y%m%d_%H%M%S_%f')
    path_to_out_patch = patches_dir.joinpath(f"{formatted_date}.patch")

    with open(path_to_out_patch, "w") as out_patch:
    out_patch.write(result.stdout)
    print(f"**********************************************************************")
    print(f"Created a patch: {path_to_out_patch}")
    print(f"**********************************************************************")


    def get_key():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
    tty.setraw(sys.stdin.fileno())
    ch = sys.stdin.read(1)
    finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch


    def main():
    git_client = GitClient()

    debug = False
    current_pattern = ""

    escape = False

    while True:
    c = get_key()
    current_pattern += c

    if debug:
    print(c, ord(c), end=None)
    print(f"PATT: '{current_pattern}'")

    if ord(c) == 3:
    print("")
    sys.exit(0)

    # TAB
    if ord(c) == 9:
    git_client.fetch()
    git_client.rebase("origin/main")
    git_client.status()
    sys.exit(0)

    # Escape sequence
    if ord(c) == 27:
    escape = True
    current_pattern = "27"
    continue

    # Backspace
    if ord(c) == 127:
    current_pattern = current_pattern[:-2]
    print(f"Correcting pattern: {current_pattern}")
    continue

    if escape:
    # Up
    if current_pattern == "27[A":
    git_client.push()
    git_client.status()
    sys.exit(0)

    # Shift + Up
    elif current_pattern == "27[1;2A":
    git_client.push(force=True)
    git_client.status()
    sys.exit(0)

    # Down
    elif current_pattern == "27[B":
    git_client.pull()
    git_client.status()
    sys.exit(0)

    # Shift + Down
    elif current_pattern == "27[1;2B":
    git_client.rebase("origin/main")
    git_client.status()
    sys.exit(0)

    # Left
    elif current_pattern == "27[D":
    git_client.switch_to_previous_branch()
    git_client.status()
    sys.exit(0)

    # Shift+TAB
    elif current_pattern == "27[Z":
    git_client.fetch()
    git_client.rebase_interactive()
    git_client.status()
    sys.exit(0)

    else:
    if c == "A":
    git_client.add_all()
    git_client.status()
    sys.exit(0)

    elif c == "B":
    git_client.branch_latest()
    sys.exit(0)

    elif c == "C":
    git_client.commit()
    git_client.status()
    sys.exit(0)

    elif c == "D":
    git_client.diff()
    sys.exit(0)

    elif c == "F":
    git_client.fetch()
    git_client.status()
    sys.exit(0)

    elif c == "H":
    git_client.show()
    sys.exit(0)

    elif c == "L":
    git_client.log()
    sys.exit(0)

    elif c == "P":
    git_client.push()
    git_client.status()
    sys.exit(0)

    elif c == "R":
    git_client.rebase("origin/main")
    git_client.status()
    sys.exit(0)

    elif c == "S":
    git_client.status()
    sys.exit(0)

    elif c == "M":
    git_client.switch_to_main()
    git_client.status()
    sys.exit(0)

    if c == "!":
    git_client.reset_hard()
    git_client.status()
    sys.exit(0)

    elif c == '-':
    git_client.reset_soft_unstage()
    git_client.status()
    sys.exit(0)

    elif c == '_':
    git_client.reset_soft_unstage("HEAD^")
    git_client.status()
    sys.exit(0)

    elif c == "+":
    git_client.add_all()
    git_client.status()
    git_client.commit_new_or_amend_existing()
    git_client.status()
    sys.exit(0)

    elif current_pattern == "bl1":
    git_client.branch_latest()
    sys.exit(0)

    elif current_pattern == "bl2":
    git_client.branch_latest(all=True)
    sys.exit(0)

    elif current_pattern == "cm1":
    git_client.commit()
    git_client.status()
    sys.exit(0)

    elif current_pattern == "cm2":
    git_client.commit(amend=True)
    git_client.status()
    sys.exit(0)

    elif current_pattern == "cm3":
    git_client.commit(amend=True, no_edit=True)
    git_client.status()
    sys.exit(0)

    elif current_pattern == "di1":
    git_client.diff()
    sys.exit(0)

    elif current_pattern == "di2":
    git_client.diff(target="HEAD")
    sys.exit(0)

    elif current_pattern == "l1":
    git_client.log(commits=1)
    sys.exit(0)

    elif current_pattern == "l2":
    git_client.log(commits=2)
    sys.exit(0)

    if __name__ == "__main__":
    main()