From: Alexander Gavrilov <angavrilov@gmail.com>
To: git@vger.kernel.org
Cc: Paul Mackerras <paulus@samba.org>
Subject: [PATCH 3/7] gitk: Allow starting gui blame for a specific line.
Date: Wed, 8 Oct 2008 11:05:36 +0400 [thread overview]
Message-ID: <1223449540-20457-4-git-send-email-angavrilov@gmail.com> (raw)
In-Reply-To: <1223449540-20457-3-git-send-email-angavrilov@gmail.com>
Adds a context menu item to the diff viewer pane that
calls blame, focusing it on the clicked line. In case
of combined diffs, it also automatically deduces which
parent is to be blamed.
The context menu itself is added by this patch. It is
possible to populate it with commands from the flist
menu.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
gitk | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 133 insertions(+), 2 deletions(-)
diff --git a/gitk b/gitk
index 96ca965..3c77909 100755
--- a/gitk
+++ b/gitk
@@ -2184,6 +2184,7 @@ proc makewindow {} {
bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
global ctxbut
bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
+ bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
set maincursor [. cget -cursor]
set textcursor [$ctext cget -cursor]
@@ -2233,6 +2234,12 @@ proc makewindow {} {
-command {external_diff}
$flist_menu add command -label [mc "Blame parent commit"] \
-command {external_blame 1}
+
+ global diff_menu
+ set diff_menu .diffctxmenu
+ menu $diff_menu -tearoff 0
+ $diff_menu add command -label [mc "Blame parent commit"] \
+ -command {external_blame_diff}
}
# Windows sends all mouse wheel events to the current focused window, not
@@ -2935,6 +2942,34 @@ proc pop_flist_menu {w X Y x y} {
tk_popup $flist_menu $X $Y
}
+proc find_ctext_fileinfo {line} {
+ global ctext_file_names ctext_file_lines
+
+ set ok [bsearch $ctext_file_lines $line]
+ set tline [lindex $ctext_file_lines $ok]
+
+ if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
+ return {}
+ } else {
+ return [list [lindex $ctext_file_names $ok] $tline]
+ }
+}
+
+proc pop_diff_menu {w X Y x y} {
+ global ctext diff_menu flist_menu_file
+ global diff_menu_txtpos diff_menu_line
+ global diff_menu_filebase
+
+ stopfinding
+ set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
+ set diff_menu_line [lindex $diff_menu_txtpos 0]
+ set f [find_ctext_fileinfo $diff_menu_line]
+ if {$f eq {}} return
+ set flist_menu_file [lindex $f 0]
+ set diff_menu_filebase [lindex $f 1]
+ tk_popup $diff_menu $X $Y
+}
+
proc flist_hl {only} {
global flist_menu_file findstring gdttype
@@ -3041,7 +3076,84 @@ proc external_diff {} {
}
}
-proc external_blame {parent_idx} {
+proc find_hunk_blamespec {base line} {
+ global ctext
+
+ # Find and parse the hunk header
+ set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
+ if {$s_lix eq {}} return
+
+ set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
+ if {![regexp {^@@@?(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
+ s_line old_specs osz osz1 new_line nsz]} {
+ return
+ }
+
+ # base lines for the parents
+ set old_lines [list]
+ foreach old_spec [lrange [split $old_specs " "] 1 end] {
+ if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
+ old_spec old_line osz]} {
+ return
+ }
+ lappend old_lines $old_line
+ }
+
+ # Now scan the lines to determine offset within the hunk
+ set parent {}
+ set dline 0
+ set s_lno [lindex [split $s_lix "."] 0]
+
+ for {set i $line} {$i > $s_lno} {incr i -1} {
+ set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
+ if {$parent eq {}} {
+ # find first preceeding line that belongs to some parent
+ for {set j 0} {$j < [llength $old_lines]} {incr j} {
+ set code [string index $c_line $j]
+ if {$code ne {-} && $code ne { }} continue
+ if {$code eq { } && $parent ne {}} continue
+ set parent $j
+ if {$code eq {-}} break
+ }
+ }
+ if {$parent ne {}} {
+ # then count other lines that belong to it
+ set code [string index $c_line $parent]
+ if {$code ne {+}} {
+ incr dline
+ }
+ }
+ }
+
+ if {$parent eq {}} { set parent 0 }
+ incr dline [lindex $old_lines $parent]
+ incr parent
+ return [list $parent $dline]
+}
+
+proc external_blame_diff {} {
+ global currentid diffmergeid cmitmode
+ global diff_menu_txtpos diff_menu_line
+ global diff_menu_filebase flist_menu_file
+
+ if {$cmitmode eq "tree"} {
+ set parent_idx 1
+ set line [expr {$diff_menu_line - $diff_menu_filebase - 1}]
+ } else {
+ set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
+ if {$hinfo ne {}} {
+ set parent_idx [lindex $hinfo 0]
+ set line [lindex $hinfo 1]
+ } else {
+ set parent_idx 1
+ set line 0
+ }
+ }
+
+ external_blame $parent_idx $line
+}
+
+proc external_blame {parent_idx {line {}}} {
global flist_menu_file
global nullid nullid2
global parentlist selectedline currentid
@@ -3057,7 +3169,12 @@ proc external_blame {parent_idx} {
return
}
- if {[catch {exec git gui blame $base_commit $flist_menu_file &} err]} {
+ set cmdline [list git gui blame]
+ if {$line ne {} && $line > 1} {
+ lappend cmdline "--line=$line"
+ }
+ lappend cmdline $base_commit $flist_menu_file
+ if {[catch {eval exec $cmdline &} err]} {
error_popup "[mc "git gui blame: command failed:"] $err"
}
}
@@ -6305,6 +6422,7 @@ proc gettreeline {gtf id} {
proc showfile {f} {
global treefilelist treeidlist diffids nullid nullid2
+ global ctext_file_names ctext_file_lines
global ctext commentend
set i [lsearch -exact $treefilelist($diffids) $f]
@@ -6328,6 +6446,8 @@ proc showfile {f} {
filerun $bf [list getblobline $bf $diffids]
$ctext config -state normal
clear_ctext $commentend
+ lappend ctext_file_names $f
+ lappend ctext_file_lines [lindex [split $commentend "."] 0]
$ctext insert end "\n"
$ctext insert end "$f\n" filesep
$ctext config -state disabled
@@ -6387,6 +6507,7 @@ proc mergediff {id} {
proc getmergediffline {mdf id np} {
global diffmergeid ctext cflist mergemax
global difffilestart mdifffd
+ global ctext_file_names ctext_file_lines
global diffencoding
$ctext conf -state normal
@@ -6404,6 +6525,8 @@ proc getmergediffline {mdf id np} {
set here [$ctext index "end - 1c"]
lappend difffilestart $here
add_flist [list $fname]
+ lappend ctext_file_names $fname
+ lappend ctext_file_lines [lindex [split $here "."] 0]
set diffencoding [get_cached_encoding $fname]
set l [expr {(78 - [string length $fname]) / 2}]
set pad [string range "----------------------------------------" 1 $l]
@@ -6661,11 +6784,13 @@ proc setinlist {var i val} {
proc makediffhdr {fname ids} {
global ctext curdiffstart treediffs
+ global ctext_file_names
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
+ set ctext_file_names [lreplace $ctext_file_names end end $fname]
set l [expr {(78 - [string length $fname]) / 2}]
set pad [string range "----------------------------------------" 1 $l]
$ctext insert $curdiffstart "$pad $fname $pad" filesep
@@ -6674,6 +6799,7 @@ proc makediffhdr {fname ids} {
proc getblobdiffline {bdf ids} {
global diffids blobdifffd ctext curdiffstart
global diffnexthead diffnextnote difffilestart
+ global ctext_file_names ctext_file_lines
global diffinhdr treediffs
global diffencoding
@@ -6691,6 +6817,8 @@ proc getblobdiffline {bdf ids} {
# start of a new file
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names ""
+ lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "\n" filesep
# If the name hasn't changed the length will be odd,
# the middle char will be a space, and the two bits either
@@ -6827,6 +6955,7 @@ proc nextfile {} {
proc clear_ctext {{first 1.0}} {
global ctext smarktop smarkbot
+ global ctext_file_names ctext_file_lines
global pendinglinks
set l [lindex [split $first .] 0]
@@ -6840,6 +6969,8 @@ proc clear_ctext {{first 1.0}} {
if {$first eq "1.0"} {
catch {unset pendinglinks}
}
+ set ctext_file_names {}
+ set ctext_file_lines {}
}
proc settabs {{firstab {}}} {
--
1.6.0.20.g6148bc
next prev parent reply other threads:[~2008-10-08 7:09 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-08 7:05 [PATCH 0/7] gitk: UI enhancements Alexander Gavrilov
2008-10-08 7:05 ` [PATCH 1/7] gitk: Enhance UI popup and accelerator handling Alexander Gavrilov
2008-10-08 7:05 ` [PATCH 2/7] gitk: Allow forcing branch creation if it already exists Alexander Gavrilov
2008-10-08 7:05 ` Alexander Gavrilov [this message]
2008-10-08 7:05 ` [PATCH 4/7] gitk: Fix file list context menu for merge commits Alexander Gavrilov
2008-10-08 7:05 ` [PATCH 5/7] gitk: Make cherry-pick call git-citool on conflicts Alexander Gavrilov
2008-10-08 7:05 ` [PATCH 6/7] gitk: Implement a user-friendly Edit View dialog Alexander Gavrilov
2008-10-08 7:05 ` [PATCH 7/7] gitk: Explicitly position popup windows Alexander Gavrilov
2008-10-21 11:41 ` Paul Mackerras
2008-10-21 12:52 ` Alexander Gavrilov
2008-10-09 7:42 ` [PATCH 5/7] gitk: Make cherry-pick call git-citool on conflicts Paul Mackerras
2008-10-09 8:24 ` Alexander Gavrilov
2008-10-09 10:57 ` Paul Mackerras
2008-10-21 11:39 ` [PATCH 4/7] gitk: Fix file list context menu for merge commits Paul Mackerras
2008-10-23 11:58 ` [PATCH 3/7] gitk: Allow starting gui blame for a specific line Paul Mackerras
2008-10-24 8:13 ` Alexander Gavrilov
2008-10-25 11:57 ` Paul Mackerras
2008-10-25 16:45 ` Alexander Gavrilov
2008-10-26 3:58 ` Paul Mackerras
2008-10-21 11:38 ` [PATCH 2/7] gitk: Allow forcing branch creation if it already exists Paul Mackerras
2008-10-09 0:27 ` [PATCH 1/7] gitk: Enhance UI popup and accelerator handling Paul Mackerras
2008-10-09 8:12 ` Alexander Gavrilov
2008-10-09 11:02 ` Paul Mackerras
2008-10-16 21:55 ` Paul Mackerras
2008-10-16 22:08 ` Alexander Gavrilov
2008-10-21 11:35 ` Paul Mackerras
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1223449540-20457-4-git-send-email-angavrilov@gmail.com \
--to=angavrilov@gmail.com \
--cc=git@vger.kernel.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).