From 5e7d9b7240e043d630e746caa10c11c58882d3bd Mon Sep 17 00:00:00 2001 From: Goto Hayato Date: Sun, 29 Oct 2017 13:14:46 +0900 Subject: [PATCH 1/6] Issue #15: add the function to show all blame output. --- Default.sublime-commands | 16 +++- git-blame.py | 156 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 7 deletions(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index 470d7f9..d3739d2 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -1,6 +1,14 @@ [ -{ - "caption": "Git Blame", - "command": "blame" -} + { + "caption": "Git Blame", + "command": "blame" + }, + { + "caption": "Git Blame Show All", + "command": "blame_show_all" + }, + { + "caption": "Git Blame Erase All", + "command": "blame_erase_all" + } ] diff --git a/git-blame.py b/git-blame.py index 2df5eff..523681c 100644 --- a/git-blame.py +++ b/git-blame.py @@ -1,11 +1,14 @@ import sublime import sublime_plugin import os +import re import functools import subprocess from subprocess import check_output as shell -stylesheet = ''' +PHANTOM_KEY_ALL = 'git-blame-all' + +stylesheet_one = ''' ''' -template = ''' +template_one = ''' {stylesheet}
@@ -58,6 +61,31 @@ ''' +stylesheet_all = ''' + +''' + +template_all = ''' + + {stylesheet} +
+ + {sha} ({user} {date} {time}) + +
+ +''' + # Sometimes this fails on other OS, just error silently try: si = subprocess.STARTUPINFO() @@ -65,6 +93,7 @@ except: si = None + class BlameCommand(sublime_plugin.TextCommand): def __init__(self, view): @@ -148,13 +177,134 @@ def run(self, edit): sha, user, date, time = self.parse_blame(result) - body = template.format(sha=sha, user=user, date=date, time=time, stylesheet=stylesheet) + body = template.format(sha=sha, user=user, date=date, time=time, stylesheet=stylesheet_one) phantom = sublime.Phantom(line, body, sublime.LAYOUT_BLOCK, self.on_phantom_close) phantoms.append(phantom) self.phantom_set.update(phantoms) +class BlameShowAllCommand(sublime_plugin.TextCommand): + + # The fixed length for author names + NAME_LENGTH = 10 + + def __init__(self, view): + super().__init__(view) + self.phantom_set = sublime.PhantomSet(self.view, PHANTOM_KEY_ALL) + self.pattern = None + + def run(self, edit): + if self.view.is_dirty(): + sublime.status_message("The file needs to be saved for git blame.") + return + + self.view.erase_phantoms(PHANTOM_KEY_ALL) + + blame_lines = self.get_blame_lines(self.view.file_name()) + + if not blame_lines: + return + + phantoms = [] + for l in blame_lines: + parsed = self.parse_blame(l) + if not parsed: + continue + + sha, author, date, time, line_number = parsed + + body = template_all.format(sha=sha, + user=self.format_name(author), + date=date, + time=time, + stylesheet=stylesheet_all) + + line_point = self.get_line_point(line_number - 1) + phantom = sublime.Phantom(line_point, body, sublime.LAYOUT_INLINE) + phantoms.append(phantom) + + self.phantom_set.update(phantoms) + + def get_blame_lines(self, path): + '''Run `git blame` and get the output lines. + ''' + try: + output = shell(["git", "blame", "--minimal", "-w", path], + cwd=os.path.dirname(os.path.realpath(path)), + startupinfo=si, + stderr=subprocess.STDOUT) + return output.decode("UTF-8").splitlines() + except subprocess.CalledProcessError as e: + print("Git blame: git error {}:\n{}".format(e.returncode, e.output.decode("UTF-8"))) + except Exception as e: + print("Git blame: Unexpected error:", e) + + def parse_blame(self, blame): + '''Parses git blame output. + ''' + if not self.pattern: + self.prepare_pattern() + + m = self.pattern.match(blame) + if m: + sha = m.group('sha') + author = m.group('author') + date = m.group('date') + time = m.group('time') + line_number = int(m.group('line_number')) + return sha, author, date, time, line_number + else: + return None + + def prepare_pattern(self): + '''Prepares the regex pattern to parse git blame output. + ''' + p_sha = r'(?P\w+)' + p_author = r'(?P.+?)' + p_date = r'(?P\d{4}-\d{2}-\d{2})' + p_time = r'(?P