Last active
November 16, 2024 19:59
-
-
Save stanislaw/e31f6dd84426ef7aedb6c110d9237729 to your computer and use it in GitHub Desktop.
Revisions
-
stanislaw revised this gist
Nov 16, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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", "--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: -
stanislaw created this gist
Nov 16, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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()