@@ -92,12 +92,46 @@ function! s:GetLines() abort
9292 endif
9393endfunction
9494
95- function ! blamer#GetMessage (file , line_number, line_count) abort
95+ function ! blamer#CommitDataToMessage (commit_data) abort
96+ let l: message = s: blamer_template
97+ for field in s: blamer_info_fields
98+ let l: message = substitute (l: message , ' \m\C<' . field . ' >' , a: commit_data [field], ' g' )
99+ endfor
100+ return l: message
101+ endfunction
102+
103+ function ! blamer#ParseCommitDataLine (line ) abort
104+ let l: info = {}
105+ let l: words = split (a: line , ' ' )
106+ let l: property = l: words [0 ]
107+ let l: value = join (l: words [1 :], ' ' )
108+ if l: property = ~? ' time'
109+ if (s: blamer_relative_time )
110+ let l: value = s: GetRelativeTime (l: value )
111+ else
112+ let l: value = strftime (s: blamer_date_format , l: value )
113+ endif
114+ endif
115+ let l: value = escape (l: value , ' &' )
116+ let l: value = escape (l: value , ' ~' )
117+
118+ if l: value == ? s: blamer_user_name
119+ let l: value = ' You'
120+ elseif l: value == ? s: blamer_user_email
121+ let l: value = ' You'
122+ endif
123+
124+ let l: info [l: property ] = l: value
125+ return l: info
126+ endfunction
127+
128+ function ! blamer#GetMessages (file , line_number, line_count) abort
129+ let l: end_line = a: line_number + a: line_count - 1
96130 let l: file_path_escaped = shellescape (a: file )
97- let l: command = ' git --no-pager blame -p -L ' . a: line_number . ' ,' . a: line_count . ' -- ' . l: file_path_escaped
131+ let l: command = ' git --no-pager blame --line-porcelain -L ' . a: line_number . ' ,' . l: end_line . ' -- ' . l: file_path_escaped
98132 let l: result = system (l: command )
99-
100133 let l: lines = split (l: result , ' \n' )
134+
101135 let l: info = {}
102136 let l: info [' commit-short' ] = split (l: lines [0 ], ' ' )[0 ][:7 ]
103137 let l: info [' commit-long' ] = split (l: lines [0 ], ' ' )[0 ]
@@ -128,41 +162,37 @@ function! blamer#GetMessage(file, line_number, line_count) abort
128162 return ' '
129163 endif
130164
131- for line in l: lines [1 :]
132- let l: words = split (line , ' ' )
133- let l: property = l: words [0 ]
134- let l: value = join (l: words [1 :], ' ' )
135- if l: property = ~? ' time'
136- if (s: blamer_relative_time )
137- let l: value = s: GetRelativeTime (l: value )
138- else
139- let l: value = strftime (s: blamer_date_format , l: value )
165+ let l: TAB_ASCII = 9
166+
167+ let l: reading_commit_data = 0
168+ let l: commit_data = {}
169+ let l: commit_data_per_line = []
170+
171+ for line in l: lines [0 :]
172+ let l: line_words = split (line , ' ' )
173+ let l: is_line_hash = ! empty (matchstr (l: line_words [0 ],' \c[0-9a-f]\{40}' ))
174+ let l: has_line_tab = char2nr (l: line_words [0 ][0 ]) == l: TAB_ASCII
175+
176+ if l: is_line_hash
177+ " line type HASH
178+ let l: commit_data = {}
179+ elseif l: has_line_tab
180+ " line type TAB
181+ " Change messsage when changes are not commited
182+ if l: commit_data .author == ? " Not Committed Yet"
183+ let l: commit_data .author = ' You'
184+ let l: commit_data .committer = ' You'
185+ let l: commit_data .summary = ' Uncommitted changes'
140186 endif
187+ let l: commit_data_per_line = add (l: commit_data_per_line ,extend ({},l: commit_data ))
188+ else
189+ " line type COMMIT DATA
190+ let l: commit_data_chunk = blamer#ParseCommitDataLine (line )
191+ let l: commit_data = extend (l: commit_data ,l: commit_data_chunk )
141192 endif
142- let l: value = escape (l: value , ' &' )
143- let l: value = escape (l: value , ' ~' )
144-
145- if l: value == ? s: blamer_user_name
146- let l: value = ' You'
147- elseif l: value == ? s: blamer_user_email
148- let l: value = ' You'
149- endif
150-
151- let l: info [l: property ] = l: value
152- endfor
153-
154- if l: result = ~? ' Not committed yet'
155- let l: info .author = ' You'
156- let l: info .committer = ' You'
157- let l: info .summary = ' Uncommitted changes'
158- endif
159-
160- let l: message = s: blamer_template
161- for field in s: blamer_info_fields
162- let l: message = substitute (l: message , ' \m\C<' . field . ' >' , l: info [field], ' g' )
163193 endfor
164194
165- return l: message
195+ return map ( l: commit_data_per_line , " blamer#CommitDataToMessage(v:val) " )
166196endfunction
167197
168198function ! blamer#SetVirtualText (buffer_number, line_number, message) abort
@@ -224,13 +254,18 @@ function! blamer#Show() abort
224254 " return
225255 " endif
226256
257+ let l: line_count = len (l: line_numbers )
258+ let l: messages = blamer#GetMessages (l: file_path , l: line_numbers [0 ], l: line_count )
259+ let l: index = 0
260+
227261 for line_number in l: line_numbers
228- let l: message = blamer#GetMessage ( l: file_path , line_number, ' +1 ' )
262+ let l: message = l: messages [ l: index ]
229263 if has (' nvim' )
230264 call blamer#SetVirtualText (l: buffer_number , line_number, l: message )
231265 else
232266 call blamer#CreatePopup (l: buffer_number , line_number, l: message )
233267 endif
268+ let l: index += 1
234269 endfor
235270endfunction
236271
0 commit comments