1
+ import sublime
2
+ import sublime_plugin
3
+ import os
4
+ import functools
5
+ from subprocess import check_output as shell
6
+
7
+
8
+ blame_cache = {}
9
+ template = '''
10
+ <span>
11
+ <style>
12
+ span {{
13
+ background-color: brown;
14
+ }}
15
+ a {{
16
+ text-decoration: none;
17
+ }}
18
+ </style>
19
+ <a href="close">
20
+ <strong>Git Blame:</strong> ({user})
21
+ Last updated: {date} {time} | [{sha}]
22
+ <close>X</close>
23
+ </a>
24
+ </span>
25
+ '''
26
+
27
+ si = subprocess .STARTUPINFO ()
28
+ si .dwFlags |= subprocess .STARTF_USESHOWWINDOW
29
+
30
+
31
+ class BlameCommand (sublime_plugin .TextCommand ):
32
+
33
+ def __init__ (self , view ):
34
+ self .view = view
35
+ self .phantom_set = sublime .PhantomSet (view , 'git-blame' )
36
+
37
+ @functools .lru_cache (128 , False )
38
+ def get_blame (self , line , path ):
39
+ try :
40
+ return shell (["git" , "blame" , "--minimal" , "-w" ,
41
+ "-L {0},{0}" .format (line ), path ],
42
+ cwd = os .path .dirname (os .path .realpath (path )),
43
+ startupinfo = si )
44
+ except Exception as e :
45
+ return
46
+
47
+ def parse_blame (self , blame ):
48
+ sha , file_path , user , date , time , tz_offset , * _ = blame .decode ('utf-8' ).split ()
49
+
50
+ # Was part of the inital commit so no updates
51
+ if file_path [0 ] == '(' :
52
+ user , date , time , tz_offset = file_path , user , date , time
53
+ file_path = None
54
+
55
+ return (sha , user [1 :], date , time )
56
+
57
+ def on_phantom_close (self , href ):
58
+ self .view .erase_phantoms ('git-blame' )
59
+
60
+
61
+ def run (self , edit ):
62
+ phantoms = []
63
+ self .view .erase_phantoms ('git-blame' )
64
+
65
+ for region in self .view .sel ():
66
+ line = self .view .line (region )
67
+ (row , col ) = self .view .rowcol (region .begin ())
68
+ full_path = self .view .file_name ()
69
+ result = self .get_blame (int (row )+ 1 , full_path )
70
+ if not result :
71
+ # Unable to get blame
72
+ return
73
+
74
+ sha , user , date , time = self .parse_blame (result )
75
+ body = template .format (sha = sha , user = user , date = date , time = time )
76
+
77
+ phantom = sublime .Phantom (line , body , sublime .LAYOUT_BLOCK , self .on_phantom_close )
78
+ phantoms .append (phantom )
79
+ self .phantom_set .update (phantoms )
0 commit comments