Skip to content

Instantly share code, notes, and snippets.

@rodrigobdz
Created January 20, 2018 16:47
Show Gist options
  • Save rodrigobdz/dbcdcaac6c5af7276c63ec920ba894b0 to your computer and use it in GitHub Desktop.
Save rodrigobdz/dbcdcaac6c5af7276c63ec920ba894b0 to your computer and use it in GitHub Desktop.
Show Git Blame info for the current line in the Sublime status bar
import sublime
import sublime_plugin
import os
import subprocess
from subprocess import check_output as shell
from datetime import datetime
try:
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
except:
si = None
class GitBlameStatusbarCommand(sublime_plugin.EventListener):
def parse_blame(self, blame):
sha, file_path, user, date, time, tz_offset, *_ = blame.decode('utf-8').split()
# Was part of the inital commit so no updates
if file_path[0] == '(':
user, date, time, tz_offset = file_path, user, date, time
file_path = None
# Fix an issue where the username has a space
# Im going to need to do something better though if people
# start to have multiple spaces in their names.
if not date[0].isdigit():
user = "{0} {1}".format(user, date)
date, time = time, tz_offset
return(sha, user[1:], date, time)
def get_blame(self, line, path):
try:
return shell(["git", "blame", "--minimal", "-w",
"-L {0},{0}".format(line), path],
cwd=os.path.dirname(os.path.realpath(path)),
startupinfo=si,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
pass
# print("Git blame: git error {}:\n{}".format(e.returncode, e.output.decode("UTF-8")))
except Exception as e:
pass
# print("Git blame: Unexpected error:", e)
def days_between(self, d):
# now = datetime.strptime(datetime.now(), "%Y-%m-%d")
now = datetime.now()
d = datetime.strptime(d, "%Y-%m-%d")
return abs((now - d).days)
def on_selection_modified_async(self, view):
current_line = view.substr(view.line(view.sel()[0]))
(row,col) = view.rowcol(view.sel()[0].begin())
path = view.file_name()
blame = self.get_blame(int(row) + 1, path)
output = ''
if blame:
sha, user, date, time = self.parse_blame(blame)
# try:
# time = '( ' + str(self.days_between(time)) + ' days ago )'
# except Exception as e:
# time = ''
# print("Git blame: days_between ", e)
time = ''
output = '☞ ' + user + ' ' + time
view.set_status('git_blame', output)
@rodrigobdz
Copy link
Author

rodrigobdz commented Jan 20, 2018

subl-gitblame

Installation

  1. Download git_blame_sublime_status_bar.py.
  2. Save it under ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/User/.
  3. Re-open Sublime.

Usage

Open a file from a Git repository and select a line with the cursor. The author of that line is automatically shown in the status bar.
Preview of subl-gitblame

Credits

@justageek
Copy link

Hi, thanks for this. I don't know much python, and I'd love to pull out the first x characters of the commit message in the blame and put it in the status bar as well, could you possibly point me in the right direction?

@rodrigobdz
Copy link
Author

You will have to modify the script as follows. The variable commit_msg contains the first line of the commit message.

@@ -43,6 +43,13 @@ class GitBlameStatusbarCommand(sublime_plugin.EventListener):
         pass
         # print("Git blame: Unexpected error:", e)

+  def get_commit_msg(self,line,path):
+    return shell(["git", "log", " --pretty=oneline", "--abbrev-commit",
+            "-L {0},{0}".format(line), path],
+            cwd=os.path.dirname(os.path.realpath(path)),
+            startupinfo=si,
+            stderr=subprocess.STDOUT)
+
   def days_between(self, d):
     # now = datetime.strptime(datetime.now(), "%Y-%m-%d")
     now = datetime.now()
@@ -54,6 +61,11 @@ class GitBlameStatusbarCommand(sublime_plugin.EventListener):
     (row,col) = view.rowcol(view.sel()[0].begin())
     path = view.file_name()
     blame = self.get_blame(int(row) + 1, path)
+
+    commit_log = self.get_commit_msg(int(row) + 1, path)
+    # Strip commit hash and leading whitespace from log
+    commit_msg = commit_log[commit_log.index(" "):].lstrip()
+
     output = ''
     if blame:
         sha, user, date, time = self.parse_blame(blame)

Here is an example on how to get the first four characters from a string in python.

"Lorem ipsum"[:4] # returns "Lore"

@gangelo
Copy link

gangelo commented Aug 29, 2018

Doesn't seem to work under Linux, although, I placed the .py file in the /home/dev/.config/sublime-text-3/Packages/User folder

@rodrigobdz
Copy link
Author

Do you get any warning or error in the Sublime console?
In the screenshot attached you can see some sample output from the Sublime console as reference.
image

@AVJLabs
Copy link

AVJLabs commented Dec 14, 2019

It does not work , I have copied the file under - Roaming\Sublime Text 3\Packages\User , reopened sublime does not see any git blame for highlighted line . But this the plugin i was looking for . what is this path all about - ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/User/ ???

@rodrigobdz
Copy link
Author

Which OS are you using?
Could you share the log shown in the Sublime console to identify any errors or issues?

@AVJLabs
Copy link

AVJLabs commented Dec 14, 2019

Which OS are you using?
windows-10, sublime version - 3.22 (which has a basic git features )
Could you share the log shown in the Sublime console to identify any errors or issues?

Traceback (most recent call last):
File "C:\Program Files\Sublime Text 3\sublime_plugin.py", line 610, in on_selection_modified_async
callback.on_selection_modified_async(v)
File "C:\Users----\AppData\Roaming\Sublime Text 3\Packages\User\git_blame_sublime_statusbar.py", line 53, in on_selection_modified_async
current_line = view.substr(view.line(view.sel()[0]))
File "C:\Program Files\Sublime Text 3\sublime.py", line 649, in getitem
raise IndexError()
IndexError

@aarbi
Copy link

aarbi commented Jul 25, 2023

Still working in sublime 4 on Mac, thank you sir!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment