{"thread":{"id":"55106","subject":"[PATCH] [RFC] gitk: tag add right click options","startedAt":"2021-02-04T08:19:11Z","lastAt":"2021-02-25T04:39:47Z","messageCount":5,"participants":["阿德烈 via GitGitGadget","ZheNing Hu via GitGitGadget"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"416141","messageId":"pull.866.git.1612426689172.gitgitgadget@gmail.com","threadId":"55106","inReplyTo":null,"subject":"[PATCH] [RFC] gitk: tag add right click options","fromName":"阿德烈 via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-02-04T08:18:08Z","receivedAt":"2021-02-04T08:19:11Z","isPatch":true,"sender":{"key":"name:阿德烈","avatar":null},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nIn gitk, we can right-click on the icon of the branch,\nand a directory will pop up to provide us with functions\nsuch as \"Checkout this branch\", \"Rename this branch\"...,\nbut we found that the right-click tag icon does not have such\na function , So I learned how to write the branch icon, and\nadded the following functions \"Rename this tag\",\"Remove this tag\",\n\"Copy tag name\" to right-click the tag icon. This function is\ntemporarily supported work on the branch with <=3 tags.\n\nBut now I may need a little help:\nafter we successfully deleted or modified the tag,the content\nshow on gitk has not changed, and I am stuck here.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n    [RFC] gitk: tag add right click options\n    \n    This patch want to fix: https://github.com/gitgitgadget/git/issues/855\n    \n    We can provide for right-clicking the tag icon in gitk Rename this tag\",\n    \"Remove this tag\", \"Copy tag name\" function.\n    \n    For convenience, only the tags on the branch with the number of tags <=3\n    are processed temporarily.\n    \n    Now I may need a little help: after we successfully deleted or modified\n    the tag name,the content show on gitk has not changed, and I am stuck\n    here.\n    \n    In addition,I just learned part of the syntax of the tcl/tk language,\n    and there may be some bad uses in my patch.\n    \n    Thanks!\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-866%2Fadlternative%2Fgitk_tag_new_opt-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-866/adlternative/gitk_tag_new_opt-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/866\n\n gitk-git/gitk | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 149 insertions(+)\n\ndiff --git a/gitk-git/gitk b/gitk-git/gitk\nindex 23d9dd1fe0d0..f69834d52785 100755\n--- a/gitk-git/gitk\n+++ b/gitk-git/gitk\n@@ -1874,6 +1874,28 @@ proc removehead {id name} {\n     unset headids($name)\n }\n \n+proc movetag {id name} {\n+    global tagids idtags\n+\n+    removetag $tagids($name) $name\n+    set tagids($name) $id\n+    lappend idtags($id) $name\n+}\n+\n+proc removetag {id name} {\n+    global tagids idtags\n+\n+    if {$idtags($id) eq $name} {\n+        unset idtags($id)\n+    } else {\n+        set i [lsearch -exact $idtags($id) $name]\n+        if {$i >= 0} {\n+            set idtags($id) [lreplace $idtags($id) $i $i]\n+        }\n+    }\n+    unset tagids($name)\n+}\n+\n proc ttk_toplevel {w args} {\n     global use_ttk\n     eval [linsert $args 0 ::toplevel $w]\n@@ -2077,6 +2099,7 @@ proc makewindow {} {\n     global filesepbgcolor filesepfgcolor\n     global mergecolors foundbgcolor currentsearchhitbgcolor\n     global headctxmenu progresscanv progressitem progresscoords statusw\n+    global tagctxmenu\n     global fprogitem fprogcoord lastprogupdate progupdatepending\n     global rprogitem rprogcoord rownumsel numcommits\n     global have_tk85 use_ttk NS\n@@ -2685,6 +2708,14 @@ proc makewindow {} {\n     }\n     $headctxmenu configure -tearoff 0\n \n+    set tagctxmenu .tagctxmenu\n+    makemenu $tagctxmenu {\n+        {mc \"Rename this tag\" command mvtag}\n+        {mc \"Remove this tag\" command rmtag}\n+        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n+    }\n+    $tagctxmenu configure -tearoff 0\n+\n     global flist_menu\n     set flist_menu .flistctxmenu\n     makemenu $flist_menu {\n@@ -6581,6 +6612,7 @@ proc drawtags {id x xt y1} {\n \n     set marks {}\n     set ntags 0\n+    set ntags_copy 0\n     set nheads 0\n     set singletag 0\n     set maxtags 3\n@@ -6592,6 +6624,7 @@ proc drawtags {id x xt y1} {\n     if {[info exists idtags($id)]} {\n         set marks $idtags($id)\n         set ntags [llength $marks]\n+        set ntags_copy $ntags\n         if {$ntags > $maxtags ||\n             [totalwidth $marks mainfont $extra] > $maxwidth} {\n             # show just a single \"n tags...\" tag\n@@ -6678,6 +6711,9 @@ proc drawtags {id x xt y1} {\n                    -font $font -tags [list tag.$id text]]\n         if {$ntags >= 0} {\n             $canv bind $t <1> $tagclick\n+            if {$ntags_copy < $maxtags} {\n+              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n+            }\n         } elseif {$nheads >= 0} {\n             $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]\n         }\n@@ -9531,6 +9567,57 @@ proc mkbranch {} {\n     branchdia $top val ui\n }\n \n+proc mvtag {} {\n+    global NS\n+    global tagmenuid tagmenutag\n+\n+    set top .tagdialog\n+\n+    set val(name) $tagmenutag\n+    set val(id) $tagmenuid\n+    set val(command) [list mvtago $top $tagmenutag]\n+\n+    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n+    set ui(accept) [mc \"Rename\"]\n+\n+    tagdia $top val ui\n+}\n+\n+proc tagdia {top valvar uivar} {\n+    global NS commitinfo\n+    upvar $valvar val $uivar ui\n+\n+    catch {destroy $top}\n+    ttk_toplevel $top\n+    make_transient $top .\n+    ${NS}::label $top.title -text $ui(title)\n+    grid $top.title - -pady 10\n+    ${NS}::label $top.id -text [mc \"ID:\"]\n+    ${NS}::entry $top.sha1 -width 40\n+    $top.sha1 insert 0 $val(id)\n+    $top.sha1 conf -state readonly\n+    grid $top.id $top.sha1 -sticky w\n+    ${NS}::entry $top.head -width 60\n+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]\n+    $top.head conf -state readonly\n+    grid x $top.head -sticky ew\n+    grid columnconfigure $top 1 -weight 1\n+    ${NS}::label $top.nlab -text [mc \"Name:\"]\n+    ${NS}::entry $top.name -width 40\n+    $top.name insert 0 $val(name)\n+    grid $top.nlab $top.name -sticky w\n+    ${NS}::frame $top.buts\n+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)\n+    ${NS}::button $top.buts.can -text [mc \"Cancel\"] -command \"catch {destroy $top}\"\n+    bind $top <Key-Return> $val(command)\n+    bind $top <Key-Escape> \"catch {destroy $top}\"\n+    grid $top.buts.go $top.buts.can\n+    grid columnconfigure $top.buts 0 -weight 1 -uniform a\n+    grid columnconfigure $top.buts 1 -weight 1 -uniform a\n+    grid $top.buts - -pady 10 -sticky ew\n+    focus $top.name\n+}\n+\n proc mvbranch {} {\n     global NS\n     global headmenuid headmenuhead\n@@ -9582,6 +9669,38 @@ proc branchdia {top valvar uivar} {\n     focus $top.name\n }\n \n+proc mvtago {top prevname} {\n+    global tagids idheads mainhead mainheadid\n+\n+    set name [$top.name get]\n+    set id [$top.sha1 get]\n+    if {$name eq $prevname} {\n+          catch {destroy $top}\n+          return\n+    }\n+    if {$name eq {}} {\n+      error_popup [mc \"Please specify a new name for the tag\"] $top\n+      return\n+    }\n+    catch {destroy $top}\n+    nowbusy renametag\n+    update\n+    if {[catch {\n+        eval exec \"git tag $name $prevname\"\n+        eval exec \"git tag -d $prevname\"\n+    } err]} {\n+        notbusy renametag\n+        error_popup $err\n+    } else {\n+        notbusy renametag\n+        removetag $id $prevname\n+        set tagids($name) $id\n+        lappend idtags($id) $name\n+        run refill_reflist\n+    }\n+\n+}\n+\n proc mkbrgo {top} {\n     global headids idheads\n \n@@ -9915,6 +10034,17 @@ proc headmenu {x y id head} {\n     tk_popup $headctxmenu $x $y\n }\n \n+# context menu for a tag\n+proc tagmenu {x y id tag} {\n+    global tagmenuid tagmenutag tagctxmenu mainhead\n+\n+    stopfinding\n+    set tagmenuid $id\n+    set tagmenutag $tag\n+\n+    tk_popup $tagctxmenu $x $y\n+}\n+\n proc cobranch {} {\n     global headmenuid headmenuhead headids\n     global showlocalchanges\n@@ -10019,6 +10149,25 @@ proc rmbranch {} {\n     run refill_reflist\n }\n \n+proc rmtag {} {\n+    global tagmenuid tagmenutag\n+    global idtags\n+\n+    set tag $tagmenutag\n+    set id $tagmenuid\n+\n+    nowbusy rmtag\n+    update\n+    if {[catch {exec git tag -d $tag} err]} {\n+        notbusy rmtag\n+        error_popup $err\n+        return\n+    }\n+    removetag $id $tag\n+    notbusy rmtag\n+    run refill_reflist\n+}\n+\n # Display a list of tags and heads\n proc showrefs {} {\n     global showrefstop bgcolor fgcolor selectbgcolor NS\n\nbase-commit: e6362826a0409539642a5738db61827e5978e2e4\n-- \ngitgitgadget\n"},{"id":"417050","messageId":"pull.866.v2.git.1613483622881.gitgitgadget@gmail.com","threadId":"55106","inReplyTo":"pull.866.git.1612426689172.gitgitgadget@gmail.com","subject":"[PATCH v2] gitk: tag add right click options","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-02-16T13:53:42Z","receivedAt":"2021-02-16T13:54:39Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nIn gitk, we can right-click on the icon of the branch,\nand a directory will pop up to provide us with functions\nsuch as \"Checkout this branch\", \"Rename this branch\"...,\nbut we found that the right-click tag icon does not have such\na function , So I learned how to write the branch icon, and\nadded the following functions \"Rename this tag\",\"Remove this tag\",\n\"Copy tag name\" to right-click the tag icon. This function is\ntemporarily supported work on the branch with <=3 tags.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n    gitk: tag add right click options\n    \n    This patch want to fix: https://github.com/gitgitgadget/git/issues/855\n    \n    We can provide for right-clicking the tag icon in gitk Rename this tag\",\n    \"Remove this tag\", \"Copy tag name\" function.\n    \n    For convenience, only the tags on the branch with the number of tags <=3\n    are processed temporarily.\n    \n    Thanks!\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-866%2Fadlternative%2Fgitk_tag_new_opt-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-866/adlternative/gitk_tag_new_opt-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/866\n\nRange-diff vs v1:\n\n 1:  b246cdf06d6e ! 1:  f3a5d7d3be9f [RFC] gitk: tag add right click options\n     @@ Metadata\n      Author: ZheNing Hu <adlternative@gmail.com>\n      \n       ## Commit message ##\n     -    [RFC] gitk: tag add right click options\n     +    gitk: tag add right click options\n      \n          In gitk, we can right-click on the icon of the branch,\n          and a directory will pop up to provide us with functions\n     @@ Commit message\n          \"Copy tag name\" to right-click the tag icon. This function is\n          temporarily supported work on the branch with <=3 tags.\n      \n     -    But now I may need a little help:\n     -    after we successfully deleted or modified the tag,the content\n     -    show on gitk has not changed, and I am stuck here.\n     -\n          Signed-off-by: ZheNing Hu <adlternative@gmail.com>\n      \n       ## gitk-git/gitk ##\n     @@ gitk-git/gitk: proc removehead {id name} {\n           unset headids($name)\n       }\n       \n     -+proc movetag {id name} {\n     -+    global tagids idtags\n     -+\n     -+    removetag $tagids($name) $name\n     -+    set tagids($name) $id\n     -+    lappend idtags($id) $name\n     -+}\n     -+\n      +proc removetag {id name} {\n      +    global tagids idtags\n      +\n     @@ gitk-git/gitk: proc mkbranch {} {\n      +\n      +    set val(name) $tagmenutag\n      +    set val(id) $tagmenuid\n     -+    set val(command) [list mvtago $top $tagmenutag]\n     ++    set val(command) [list mvtaggo $top $tagmenutag]\n      +\n      +    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n      +    set ui(accept) [mc \"Rename\"]\n     @@ gitk-git/gitk: proc branchdia {top valvar uivar} {\n           focus $top.name\n       }\n       \n     -+proc mvtago {top prevname} {\n     -+    global tagids idheads mainhead mainheadid\n     ++proc mvtaggo {top prevname} {\n     ++    global tagids idtags idheads mainhead mainheadid\n      +\n      +    set name [$top.name get]\n      +    set id [$top.sha1 get]\n     @@ gitk-git/gitk: proc branchdia {top valvar uivar} {\n      +    nowbusy renametag\n      +    update\n      +    if {[catch {\n     ++        # NOTE: for an annotated tag, the new tag points to the old tag object\n     ++        # where the old primary tag name is still recorded inside. Acceptable.\n      +        eval exec \"git tag $name $prevname\"\n      +        eval exec \"git tag -d $prevname\"\n     -+    } err]} {\n     ++        } err]} {\n      +        notbusy renametag\n      +        error_popup $err\n      +    } else {\n     @@ gitk-git/gitk: proc branchdia {top valvar uivar} {\n      +        removetag $id $prevname\n      +        set tagids($name) $id\n      +        lappend idtags($id) $name\n     ++        redrawtags $id\n     ++        addedtag $id\n     ++        dispneartags 0\n      +        run refill_reflist\n      +    }\n      +\n     @@ gitk-git/gitk: proc rmbranch {} {\n      +        return\n      +    }\n      +    removetag $id $tag\n     ++    redrawtags $id\n      +    notbusy rmtag\n      +    run refill_reflist\n      +}\n\n\n gitk-git/gitk | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 147 insertions(+)\n\ndiff --git a/gitk-git/gitk b/gitk-git/gitk\nindex 23d9dd1fe0d0..7ff4b3603e98 100755\n--- a/gitk-git/gitk\n+++ b/gitk-git/gitk\n@@ -1874,6 +1874,20 @@ proc removehead {id name} {\n     unset headids($name)\n }\n \n+proc removetag {id name} {\n+    global tagids idtags\n+\n+    if {$idtags($id) eq $name} {\n+        unset idtags($id)\n+    } else {\n+        set i [lsearch -exact $idtags($id) $name]\n+        if {$i >= 0} {\n+            set idtags($id) [lreplace $idtags($id) $i $i]\n+        }\n+    }\n+    unset tagids($name)\n+}\n+\n proc ttk_toplevel {w args} {\n     global use_ttk\n     eval [linsert $args 0 ::toplevel $w]\n@@ -2077,6 +2091,7 @@ proc makewindow {} {\n     global filesepbgcolor filesepfgcolor\n     global mergecolors foundbgcolor currentsearchhitbgcolor\n     global headctxmenu progresscanv progressitem progresscoords statusw\n+    global tagctxmenu\n     global fprogitem fprogcoord lastprogupdate progupdatepending\n     global rprogitem rprogcoord rownumsel numcommits\n     global have_tk85 use_ttk NS\n@@ -2685,6 +2700,14 @@ proc makewindow {} {\n     }\n     $headctxmenu configure -tearoff 0\n \n+    set tagctxmenu .tagctxmenu\n+    makemenu $tagctxmenu {\n+        {mc \"Rename this tag\" command mvtag}\n+        {mc \"Remove this tag\" command rmtag}\n+        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n+    }\n+    $tagctxmenu configure -tearoff 0\n+\n     global flist_menu\n     set flist_menu .flistctxmenu\n     makemenu $flist_menu {\n@@ -6581,6 +6604,7 @@ proc drawtags {id x xt y1} {\n \n     set marks {}\n     set ntags 0\n+    set ntags_copy 0\n     set nheads 0\n     set singletag 0\n     set maxtags 3\n@@ -6592,6 +6616,7 @@ proc drawtags {id x xt y1} {\n     if {[info exists idtags($id)]} {\n         set marks $idtags($id)\n         set ntags [llength $marks]\n+        set ntags_copy $ntags\n         if {$ntags > $maxtags ||\n             [totalwidth $marks mainfont $extra] > $maxwidth} {\n             # show just a single \"n tags...\" tag\n@@ -6678,6 +6703,9 @@ proc drawtags {id x xt y1} {\n                    -font $font -tags [list tag.$id text]]\n         if {$ntags >= 0} {\n             $canv bind $t <1> $tagclick\n+            if {$ntags_copy < $maxtags} {\n+              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n+            }\n         } elseif {$nheads >= 0} {\n             $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]\n         }\n@@ -9531,6 +9559,57 @@ proc mkbranch {} {\n     branchdia $top val ui\n }\n \n+proc mvtag {} {\n+    global NS\n+    global tagmenuid tagmenutag\n+\n+    set top .tagdialog\n+\n+    set val(name) $tagmenutag\n+    set val(id) $tagmenuid\n+    set val(command) [list mvtaggo $top $tagmenutag]\n+\n+    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n+    set ui(accept) [mc \"Rename\"]\n+\n+    tagdia $top val ui\n+}\n+\n+proc tagdia {top valvar uivar} {\n+    global NS commitinfo\n+    upvar $valvar val $uivar ui\n+\n+    catch {destroy $top}\n+    ttk_toplevel $top\n+    make_transient $top .\n+    ${NS}::label $top.title -text $ui(title)\n+    grid $top.title - -pady 10\n+    ${NS}::label $top.id -text [mc \"ID:\"]\n+    ${NS}::entry $top.sha1 -width 40\n+    $top.sha1 insert 0 $val(id)\n+    $top.sha1 conf -state readonly\n+    grid $top.id $top.sha1 -sticky w\n+    ${NS}::entry $top.head -width 60\n+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]\n+    $top.head conf -state readonly\n+    grid x $top.head -sticky ew\n+    grid columnconfigure $top 1 -weight 1\n+    ${NS}::label $top.nlab -text [mc \"Name:\"]\n+    ${NS}::entry $top.name -width 40\n+    $top.name insert 0 $val(name)\n+    grid $top.nlab $top.name -sticky w\n+    ${NS}::frame $top.buts\n+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)\n+    ${NS}::button $top.buts.can -text [mc \"Cancel\"] -command \"catch {destroy $top}\"\n+    bind $top <Key-Return> $val(command)\n+    bind $top <Key-Escape> \"catch {destroy $top}\"\n+    grid $top.buts.go $top.buts.can\n+    grid columnconfigure $top.buts 0 -weight 1 -uniform a\n+    grid columnconfigure $top.buts 1 -weight 1 -uniform a\n+    grid $top.buts - -pady 10 -sticky ew\n+    focus $top.name\n+}\n+\n proc mvbranch {} {\n     global NS\n     global headmenuid headmenuhead\n@@ -9582,6 +9661,43 @@ proc branchdia {top valvar uivar} {\n     focus $top.name\n }\n \n+proc mvtaggo {top prevname} {\n+    global tagids idtags idheads mainhead mainheadid\n+\n+    set name [$top.name get]\n+    set id [$top.sha1 get]\n+    if {$name eq $prevname} {\n+          catch {destroy $top}\n+          return\n+    }\n+    if {$name eq {}} {\n+      error_popup [mc \"Please specify a new name for the tag\"] $top\n+      return\n+    }\n+    catch {destroy $top}\n+    nowbusy renametag\n+    update\n+    if {[catch {\n+        # NOTE: for an annotated tag, the new tag points to the old tag object\n+        # where the old primary tag name is still recorded inside. Acceptable.\n+        eval exec \"git tag $name $prevname\"\n+        eval exec \"git tag -d $prevname\"\n+        } err]} {\n+        notbusy renametag\n+        error_popup $err\n+    } else {\n+        notbusy renametag\n+        removetag $id $prevname\n+        set tagids($name) $id\n+        lappend idtags($id) $name\n+        redrawtags $id\n+        addedtag $id\n+        dispneartags 0\n+        run refill_reflist\n+    }\n+\n+}\n+\n proc mkbrgo {top} {\n     global headids idheads\n \n@@ -9915,6 +10031,17 @@ proc headmenu {x y id head} {\n     tk_popup $headctxmenu $x $y\n }\n \n+# context menu for a tag\n+proc tagmenu {x y id tag} {\n+    global tagmenuid tagmenutag tagctxmenu mainhead\n+\n+    stopfinding\n+    set tagmenuid $id\n+    set tagmenutag $tag\n+\n+    tk_popup $tagctxmenu $x $y\n+}\n+\n proc cobranch {} {\n     global headmenuid headmenuhead headids\n     global showlocalchanges\n@@ -10019,6 +10146,26 @@ proc rmbranch {} {\n     run refill_reflist\n }\n \n+proc rmtag {} {\n+    global tagmenuid tagmenutag\n+    global idtags\n+\n+    set tag $tagmenutag\n+    set id $tagmenuid\n+\n+    nowbusy rmtag\n+    update\n+    if {[catch {exec git tag -d $tag} err]} {\n+        notbusy rmtag\n+        error_popup $err\n+        return\n+    }\n+    removetag $id $tag\n+    redrawtags $id\n+    notbusy rmtag\n+    run refill_reflist\n+}\n+\n # Display a list of tags and heads\n proc showrefs {} {\n     global showrefstop bgcolor fgcolor selectbgcolor NS\n\nbase-commit: e6362826a0409539642a5738db61827e5978e2e4\n-- \ngitgitgadget\n"},{"id":"417329","messageId":"pull.866.v3.git.1613663704128.gitgitgadget@gmail.com","threadId":"55106","inReplyTo":"pull.866.v2.git.1613483622881.gitgitgadget@gmail.com","subject":"[PATCH v3] gitk: tag add right click options","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-02-18T15:55:03Z","receivedAt":"2021-02-18T16:57:00Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nIn gitk, we can right-click on the icon of the branch,\nand a directory will pop up to provide us with functions\nsuch as \"Checkout this branch\", \"Rename this branch\"...,\nbut we found that the right-click tag icon does not have such\na function , So I learned how to write the branch icon, and\nadded the following functions \"Rename this tag\",\"Remove this tag\",\n\"Copy tag name\" to right-click the tag icon. This function is\ntemporarily supported work on the branch with <=3 tags.\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n    gitk: tag add right click options\n    \n    This patch want to fix: https://github.com/gitgitgadget/git/issues/855\n    \n    We can provide for right-clicking the tag icon in gitk Rename this tag\",\n    \"Remove this tag\", \"Copy tag name\" function.\n    \n    For convenience, only the tags on the branch with the number of tags <=3\n    are processed temporarily.\n    \n    Thanks!\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-866%2Fadlternative%2Fgitk_tag_new_opt-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-866/adlternative/gitk_tag_new_opt-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/866\n\nRange-diff vs v2:\n\n 1:  f3a5d7d3be9f ! 1:  52ca9bcfa52f gitk: tag add right click options\n     @@ gitk-git/gitk: proc makewindow {} {\n           global rprogitem rprogcoord rownumsel numcommits\n           global have_tk85 use_ttk NS\n      @@ gitk-git/gitk: proc makewindow {} {\n     +     set headctxmenu .headctxmenu\n     +     makemenu $headctxmenu {\n     +         {mc \"Check out this branch\" command cobranch}\n     +-        {mc \"Rename this branch\" command mvbranch}\n     ++        {mc \"Rename this branch...\" command mvbranch}\n     +         {mc \"Remove this branch\" command rmbranch}\n     +         {mc \"Copy branch name\" command {clipboard clear; clipboard append $headmenuhead}}\n           }\n           $headctxmenu configure -tearoff 0\n       \n      +    set tagctxmenu .tagctxmenu\n      +    makemenu $tagctxmenu {\n     -+        {mc \"Rename this tag\" command mvtag}\n     -+        {mc \"Remove this tag\" command rmtag}\n     ++        {mc \"Rename this tag...\" command mvtag}\n     ++        {mc \"Remove this tag...\" command rmtag}\n      +        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n      +    }\n      +    $tagctxmenu configure -tearoff 0\n     @@ gitk-git/gitk: proc branchdia {top valvar uivar} {\n      +    } else {\n      +        notbusy renametag\n      +        removetag $id $prevname\n     ++        removedtag $id $tag\n      +        set tagids($name) $id\n      +        lappend idtags($id) $name\n     -+        redrawtags $id\n      +        addedtag $id\n     ++        redrawtags $id\n      +        dispneartags 0\n      +        run refill_reflist\n      +    }\n     @@ gitk-git/gitk: proc rmbranch {} {\n      +\n      +    set tag $tagmenutag\n      +    set id $tagmenuid\n     -+\n     ++    if {![confirm_popup [mc \"Really delete tag %s?\" $tag]]} return\n      +    nowbusy rmtag\n      +    update\n      +    if {[catch {exec git tag -d $tag} err]} {\n     @@ gitk-git/gitk: proc rmbranch {} {\n      +        return\n      +    }\n      +    removetag $id $tag\n     ++    removedtag $id $tag\n      +    redrawtags $id\n      +    notbusy rmtag\n     ++    dispneartags 0\n      +    run refill_reflist\n      +}\n      +\n       # Display a list of tags and heads\n       proc showrefs {} {\n           global showrefstop bgcolor fgcolor selectbgcolor NS\n     +@@ gitk-git/gitk: proc addedtag {id} {\n     +     unset -nocomplain cached_atags\n     + }\n     + \n     ++proc removedtag {id tag} {\n     ++    global cached_dtags cached_atags cached_tagcontent\n     ++\n     ++    unset -nocomplain cached_tagcontent\n     ++    unset -nocomplain cached_dtags\n     ++    unset -nocomplain cached_atags\n     ++}\n     ++\n     + proc addedhead {hid head} {\n     +     global arcnos arcout cached_dheads\n     + \n\n\n gitk-git/gitk | 160 +++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 159 insertions(+), 1 deletion(-)\n\ndiff --git a/gitk-git/gitk b/gitk-git/gitk\nindex 23d9dd1fe0d0..99b667d4db3e 100755\n--- a/gitk-git/gitk\n+++ b/gitk-git/gitk\n@@ -1874,6 +1874,20 @@ proc removehead {id name} {\n     unset headids($name)\n }\n \n+proc removetag {id name} {\n+    global tagids idtags\n+\n+    if {$idtags($id) eq $name} {\n+        unset idtags($id)\n+    } else {\n+        set i [lsearch -exact $idtags($id) $name]\n+        if {$i >= 0} {\n+            set idtags($id) [lreplace $idtags($id) $i $i]\n+        }\n+    }\n+    unset tagids($name)\n+}\n+\n proc ttk_toplevel {w args} {\n     global use_ttk\n     eval [linsert $args 0 ::toplevel $w]\n@@ -2077,6 +2091,7 @@ proc makewindow {} {\n     global filesepbgcolor filesepfgcolor\n     global mergecolors foundbgcolor currentsearchhitbgcolor\n     global headctxmenu progresscanv progressitem progresscoords statusw\n+    global tagctxmenu\n     global fprogitem fprogcoord lastprogupdate progupdatepending\n     global rprogitem rprogcoord rownumsel numcommits\n     global have_tk85 use_ttk NS\n@@ -2679,12 +2694,20 @@ proc makewindow {} {\n     set headctxmenu .headctxmenu\n     makemenu $headctxmenu {\n         {mc \"Check out this branch\" command cobranch}\n-        {mc \"Rename this branch\" command mvbranch}\n+        {mc \"Rename this branch...\" command mvbranch}\n         {mc \"Remove this branch\" command rmbranch}\n         {mc \"Copy branch name\" command {clipboard clear; clipboard append $headmenuhead}}\n     }\n     $headctxmenu configure -tearoff 0\n \n+    set tagctxmenu .tagctxmenu\n+    makemenu $tagctxmenu {\n+        {mc \"Rename this tag...\" command mvtag}\n+        {mc \"Remove this tag...\" command rmtag}\n+        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n+    }\n+    $tagctxmenu configure -tearoff 0\n+\n     global flist_menu\n     set flist_menu .flistctxmenu\n     makemenu $flist_menu {\n@@ -6581,6 +6604,7 @@ proc drawtags {id x xt y1} {\n \n     set marks {}\n     set ntags 0\n+    set ntags_copy 0\n     set nheads 0\n     set singletag 0\n     set maxtags 3\n@@ -6592,6 +6616,7 @@ proc drawtags {id x xt y1} {\n     if {[info exists idtags($id)]} {\n         set marks $idtags($id)\n         set ntags [llength $marks]\n+        set ntags_copy $ntags\n         if {$ntags > $maxtags ||\n             [totalwidth $marks mainfont $extra] > $maxwidth} {\n             # show just a single \"n tags...\" tag\n@@ -6678,6 +6703,9 @@ proc drawtags {id x xt y1} {\n                    -font $font -tags [list tag.$id text]]\n         if {$ntags >= 0} {\n             $canv bind $t <1> $tagclick\n+            if {$ntags_copy < $maxtags} {\n+              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n+            }\n         } elseif {$nheads >= 0} {\n             $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]\n         }\n@@ -9531,6 +9559,57 @@ proc mkbranch {} {\n     branchdia $top val ui\n }\n \n+proc mvtag {} {\n+    global NS\n+    global tagmenuid tagmenutag\n+\n+    set top .tagdialog\n+\n+    set val(name) $tagmenutag\n+    set val(id) $tagmenuid\n+    set val(command) [list mvtaggo $top $tagmenutag]\n+\n+    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n+    set ui(accept) [mc \"Rename\"]\n+\n+    tagdia $top val ui\n+}\n+\n+proc tagdia {top valvar uivar} {\n+    global NS commitinfo\n+    upvar $valvar val $uivar ui\n+\n+    catch {destroy $top}\n+    ttk_toplevel $top\n+    make_transient $top .\n+    ${NS}::label $top.title -text $ui(title)\n+    grid $top.title - -pady 10\n+    ${NS}::label $top.id -text [mc \"ID:\"]\n+    ${NS}::entry $top.sha1 -width 40\n+    $top.sha1 insert 0 $val(id)\n+    $top.sha1 conf -state readonly\n+    grid $top.id $top.sha1 -sticky w\n+    ${NS}::entry $top.head -width 60\n+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]\n+    $top.head conf -state readonly\n+    grid x $top.head -sticky ew\n+    grid columnconfigure $top 1 -weight 1\n+    ${NS}::label $top.nlab -text [mc \"Name:\"]\n+    ${NS}::entry $top.name -width 40\n+    $top.name insert 0 $val(name)\n+    grid $top.nlab $top.name -sticky w\n+    ${NS}::frame $top.buts\n+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)\n+    ${NS}::button $top.buts.can -text [mc \"Cancel\"] -command \"catch {destroy $top}\"\n+    bind $top <Key-Return> $val(command)\n+    bind $top <Key-Escape> \"catch {destroy $top}\"\n+    grid $top.buts.go $top.buts.can\n+    grid columnconfigure $top.buts 0 -weight 1 -uniform a\n+    grid columnconfigure $top.buts 1 -weight 1 -uniform a\n+    grid $top.buts - -pady 10 -sticky ew\n+    focus $top.name\n+}\n+\n proc mvbranch {} {\n     global NS\n     global headmenuid headmenuhead\n@@ -9582,6 +9661,44 @@ proc branchdia {top valvar uivar} {\n     focus $top.name\n }\n \n+proc mvtaggo {top prevname} {\n+    global tagids idtags idheads mainhead mainheadid\n+\n+    set name [$top.name get]\n+    set id [$top.sha1 get]\n+    if {$name eq $prevname} {\n+          catch {destroy $top}\n+          return\n+    }\n+    if {$name eq {}} {\n+      error_popup [mc \"Please specify a new name for the tag\"] $top\n+      return\n+    }\n+    catch {destroy $top}\n+    nowbusy renametag\n+    update\n+    if {[catch {\n+        # NOTE: for an annotated tag, the new tag points to the old tag object\n+        # where the old primary tag name is still recorded inside. Acceptable.\n+        eval exec \"git tag $name $prevname\"\n+        eval exec \"git tag -d $prevname\"\n+        } err]} {\n+        notbusy renametag\n+        error_popup $err\n+    } else {\n+        notbusy renametag\n+        removetag $id $prevname\n+        removedtag $id $tag\n+        set tagids($name) $id\n+        lappend idtags($id) $name\n+        addedtag $id\n+        redrawtags $id\n+        dispneartags 0\n+        run refill_reflist\n+    }\n+\n+}\n+\n proc mkbrgo {top} {\n     global headids idheads\n \n@@ -9915,6 +10032,17 @@ proc headmenu {x y id head} {\n     tk_popup $headctxmenu $x $y\n }\n \n+# context menu for a tag\n+proc tagmenu {x y id tag} {\n+    global tagmenuid tagmenutag tagctxmenu mainhead\n+\n+    stopfinding\n+    set tagmenuid $id\n+    set tagmenutag $tag\n+\n+    tk_popup $tagctxmenu $x $y\n+}\n+\n proc cobranch {} {\n     global headmenuid headmenuhead headids\n     global showlocalchanges\n@@ -10019,6 +10147,28 @@ proc rmbranch {} {\n     run refill_reflist\n }\n \n+proc rmtag {} {\n+    global tagmenuid tagmenutag\n+    global idtags\n+\n+    set tag $tagmenutag\n+    set id $tagmenuid\n+    if {![confirm_popup [mc \"Really delete tag %s?\" $tag]]} return\n+    nowbusy rmtag\n+    update\n+    if {[catch {exec git tag -d $tag} err]} {\n+        notbusy rmtag\n+        error_popup $err\n+        return\n+    }\n+    removetag $id $tag\n+    removedtag $id $tag\n+    redrawtags $id\n+    notbusy rmtag\n+    dispneartags 0\n+    run refill_reflist\n+}\n+\n # Display a list of tags and heads\n proc showrefs {} {\n     global showrefstop bgcolor fgcolor selectbgcolor NS\n@@ -11228,6 +11378,14 @@ proc addedtag {id} {\n     unset -nocomplain cached_atags\n }\n \n+proc removedtag {id tag} {\n+    global cached_dtags cached_atags cached_tagcontent\n+\n+    unset -nocomplain cached_tagcontent\n+    unset -nocomplain cached_dtags\n+    unset -nocomplain cached_atags\n+}\n+\n proc addedhead {hid head} {\n     global arcnos arcout cached_dheads\n \n\nbase-commit: e6362826a0409539642a5738db61827e5978e2e4\n-- \ngitgitgadget\n"},{"id":"417674","messageId":"pull.866.v4.git.1614164317030.gitgitgadget@gmail.com","threadId":"55106","inReplyTo":"pull.866.v3.git.1613663704128.gitgitgadget@gmail.com","subject":"[PATCH v4] gitk: tag add right click options","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-02-24T10:58:36Z","receivedAt":"2021-02-24T10:59:33Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nIn gitk, we can right-click on the icon of the branch,\nand a directory will pop up to provide us with functions\nsuch as \"Checkout this branch\", \"Rename this branch\"...,\nbut we found that the right-click tag icon does not have\nsuch a function , So I learned how to write the branch icon,\nand added the following functions \"Rename this tag\",\n\"Remove this tag\", \"Copy tag name\" to right-click the tag icon.\n\nThis function temporarily only supports those labels independently\ndisplayed tag(s), and cannot work on label aggregated display\n\"tag...\" or \"n tags...\".\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n    gitk: tag add right click options\n    \n    This patch want to fix: https://github.com/gitgitgadget/git/issues/855\n    \n    We can provide for right-clicking the tag icon in gitk Rename this tag\",\n    \"Remove this tag\", \"Copy tag name\" function.\n    \n    For convenience, only the tags on the branch with the number of tags <=3\n    are processed temporarily.\n    \n    Thanks!\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-866%2Fadlternative%2Fgitk_tag_new_opt-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-866/adlternative/gitk_tag_new_opt-v4\nPull-Request: https://github.com/gitgitgadget/git/pull/866\n\nRange-diff vs v3:\n\n 1:  52ca9bcfa52f ! 1:  c8b0dfa6628e gitk: tag add right click options\n     @@ Commit message\n          In gitk, we can right-click on the icon of the branch,\n          and a directory will pop up to provide us with functions\n          such as \"Checkout this branch\", \"Rename this branch\"...,\n     -    but we found that the right-click tag icon does not have such\n     -    a function , So I learned how to write the branch icon, and\n     -    added the following functions \"Rename this tag\",\"Remove this tag\",\n     -    \"Copy tag name\" to right-click the tag icon. This function is\n     -    temporarily supported work on the branch with <=3 tags.\n     +    but we found that the right-click tag icon does not have\n     +    such a function , So I learned how to write the branch icon,\n     +    and added the following functions \"Rename this tag\",\n     +    \"Remove this tag\", \"Copy tag name\" to right-click the tag icon.\n     +\n     +    This function temporarily only supports those labels independently\n     +    displayed tag(s), and cannot work on label aggregated display\n     +    \"tag...\" or \"n tags...\".\n      \n          Signed-off-by: ZheNing Hu <adlternative@gmail.com>\n      \n     @@ gitk-git/gitk: proc drawtags {id x xt y1} {\n           if {[info exists idtags($id)]} {\n               set marks $idtags($id)\n               set ntags [llength $marks]\n     +-        if {$ntags > $maxtags ||\n     +-            [totalwidth $marks mainfont $extra] > $maxwidth} {\n      +        set ntags_copy $ntags\n     -         if {$ntags > $maxtags ||\n     -             [totalwidth $marks mainfont $extra] > $maxwidth} {\n     ++        set out_of_bounds [expr {[totalwidth $marks mainfont $extra] > $maxwidth}]\n     ++        if {$ntags > $maxtags || $out_of_bounds} {\n                   # show just a single \"n tags...\" tag\n     +             set singletag 1\n     +             if {$ntags == 1} {\n      @@ gitk-git/gitk: proc drawtags {id x xt y1} {\n                          -font $font -tags [list tag.$id text]]\n               if {$ntags >= 0} {\n                   $canv bind $t <1> $tagclick\n     -+            if {$ntags_copy < $maxtags} {\n     ++            if {$ntags_copy <= $maxtags && !$out_of_bounds} {\n      +              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n      +            }\n               } elseif {$nheads >= 0} {\n\n\n gitk-git/gitk | 164 +++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 161 insertions(+), 3 deletions(-)\n\ndiff --git a/gitk-git/gitk b/gitk-git/gitk\nindex 23d9dd1fe0d0..7f0edf4a108d 100755\n--- a/gitk-git/gitk\n+++ b/gitk-git/gitk\n@@ -1874,6 +1874,20 @@ proc removehead {id name} {\n     unset headids($name)\n }\n \n+proc removetag {id name} {\n+    global tagids idtags\n+\n+    if {$idtags($id) eq $name} {\n+        unset idtags($id)\n+    } else {\n+        set i [lsearch -exact $idtags($id) $name]\n+        if {$i >= 0} {\n+            set idtags($id) [lreplace $idtags($id) $i $i]\n+        }\n+    }\n+    unset tagids($name)\n+}\n+\n proc ttk_toplevel {w args} {\n     global use_ttk\n     eval [linsert $args 0 ::toplevel $w]\n@@ -2077,6 +2091,7 @@ proc makewindow {} {\n     global filesepbgcolor filesepfgcolor\n     global mergecolors foundbgcolor currentsearchhitbgcolor\n     global headctxmenu progresscanv progressitem progresscoords statusw\n+    global tagctxmenu\n     global fprogitem fprogcoord lastprogupdate progupdatepending\n     global rprogitem rprogcoord rownumsel numcommits\n     global have_tk85 use_ttk NS\n@@ -2679,12 +2694,20 @@ proc makewindow {} {\n     set headctxmenu .headctxmenu\n     makemenu $headctxmenu {\n         {mc \"Check out this branch\" command cobranch}\n-        {mc \"Rename this branch\" command mvbranch}\n+        {mc \"Rename this branch...\" command mvbranch}\n         {mc \"Remove this branch\" command rmbranch}\n         {mc \"Copy branch name\" command {clipboard clear; clipboard append $headmenuhead}}\n     }\n     $headctxmenu configure -tearoff 0\n \n+    set tagctxmenu .tagctxmenu\n+    makemenu $tagctxmenu {\n+        {mc \"Rename this tag...\" command mvtag}\n+        {mc \"Remove this tag...\" command rmtag}\n+        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n+    }\n+    $tagctxmenu configure -tearoff 0\n+\n     global flist_menu\n     set flist_menu .flistctxmenu\n     makemenu $flist_menu {\n@@ -6581,6 +6604,7 @@ proc drawtags {id x xt y1} {\n \n     set marks {}\n     set ntags 0\n+    set ntags_copy 0\n     set nheads 0\n     set singletag 0\n     set maxtags 3\n@@ -6592,8 +6616,9 @@ proc drawtags {id x xt y1} {\n     if {[info exists idtags($id)]} {\n         set marks $idtags($id)\n         set ntags [llength $marks]\n-        if {$ntags > $maxtags ||\n-            [totalwidth $marks mainfont $extra] > $maxwidth} {\n+        set ntags_copy $ntags\n+        set out_of_bounds [expr {[totalwidth $marks mainfont $extra] > $maxwidth}]\n+        if {$ntags > $maxtags || $out_of_bounds} {\n             # show just a single \"n tags...\" tag\n             set singletag 1\n             if {$ntags == 1} {\n@@ -6678,6 +6703,9 @@ proc drawtags {id x xt y1} {\n                    -font $font -tags [list tag.$id text]]\n         if {$ntags >= 0} {\n             $canv bind $t <1> $tagclick\n+            if {$ntags_copy <= $maxtags && !$out_of_bounds} {\n+              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n+            }\n         } elseif {$nheads >= 0} {\n             $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]\n         }\n@@ -9531,6 +9559,57 @@ proc mkbranch {} {\n     branchdia $top val ui\n }\n \n+proc mvtag {} {\n+    global NS\n+    global tagmenuid tagmenutag\n+\n+    set top .tagdialog\n+\n+    set val(name) $tagmenutag\n+    set val(id) $tagmenuid\n+    set val(command) [list mvtaggo $top $tagmenutag]\n+\n+    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n+    set ui(accept) [mc \"Rename\"]\n+\n+    tagdia $top val ui\n+}\n+\n+proc tagdia {top valvar uivar} {\n+    global NS commitinfo\n+    upvar $valvar val $uivar ui\n+\n+    catch {destroy $top}\n+    ttk_toplevel $top\n+    make_transient $top .\n+    ${NS}::label $top.title -text $ui(title)\n+    grid $top.title - -pady 10\n+    ${NS}::label $top.id -text [mc \"ID:\"]\n+    ${NS}::entry $top.sha1 -width 40\n+    $top.sha1 insert 0 $val(id)\n+    $top.sha1 conf -state readonly\n+    grid $top.id $top.sha1 -sticky w\n+    ${NS}::entry $top.head -width 60\n+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]\n+    $top.head conf -state readonly\n+    grid x $top.head -sticky ew\n+    grid columnconfigure $top 1 -weight 1\n+    ${NS}::label $top.nlab -text [mc \"Name:\"]\n+    ${NS}::entry $top.name -width 40\n+    $top.name insert 0 $val(name)\n+    grid $top.nlab $top.name -sticky w\n+    ${NS}::frame $top.buts\n+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)\n+    ${NS}::button $top.buts.can -text [mc \"Cancel\"] -command \"catch {destroy $top}\"\n+    bind $top <Key-Return> $val(command)\n+    bind $top <Key-Escape> \"catch {destroy $top}\"\n+    grid $top.buts.go $top.buts.can\n+    grid columnconfigure $top.buts 0 -weight 1 -uniform a\n+    grid columnconfigure $top.buts 1 -weight 1 -uniform a\n+    grid $top.buts - -pady 10 -sticky ew\n+    focus $top.name\n+}\n+\n proc mvbranch {} {\n     global NS\n     global headmenuid headmenuhead\n@@ -9582,6 +9661,44 @@ proc branchdia {top valvar uivar} {\n     focus $top.name\n }\n \n+proc mvtaggo {top prevname} {\n+    global tagids idtags idheads mainhead mainheadid\n+\n+    set name [$top.name get]\n+    set id [$top.sha1 get]\n+    if {$name eq $prevname} {\n+          catch {destroy $top}\n+          return\n+    }\n+    if {$name eq {}} {\n+      error_popup [mc \"Please specify a new name for the tag\"] $top\n+      return\n+    }\n+    catch {destroy $top}\n+    nowbusy renametag\n+    update\n+    if {[catch {\n+        # NOTE: for an annotated tag, the new tag points to the old tag object\n+        # where the old primary tag name is still recorded inside. Acceptable.\n+        eval exec \"git tag $name $prevname\"\n+        eval exec \"git tag -d $prevname\"\n+        } err]} {\n+        notbusy renametag\n+        error_popup $err\n+    } else {\n+        notbusy renametag\n+        removetag $id $prevname\n+        removedtag $id $tag\n+        set tagids($name) $id\n+        lappend idtags($id) $name\n+        addedtag $id\n+        redrawtags $id\n+        dispneartags 0\n+        run refill_reflist\n+    }\n+\n+}\n+\n proc mkbrgo {top} {\n     global headids idheads\n \n@@ -9915,6 +10032,17 @@ proc headmenu {x y id head} {\n     tk_popup $headctxmenu $x $y\n }\n \n+# context menu for a tag\n+proc tagmenu {x y id tag} {\n+    global tagmenuid tagmenutag tagctxmenu mainhead\n+\n+    stopfinding\n+    set tagmenuid $id\n+    set tagmenutag $tag\n+\n+    tk_popup $tagctxmenu $x $y\n+}\n+\n proc cobranch {} {\n     global headmenuid headmenuhead headids\n     global showlocalchanges\n@@ -10019,6 +10147,28 @@ proc rmbranch {} {\n     run refill_reflist\n }\n \n+proc rmtag {} {\n+    global tagmenuid tagmenutag\n+    global idtags\n+\n+    set tag $tagmenutag\n+    set id $tagmenuid\n+    if {![confirm_popup [mc \"Really delete tag %s?\" $tag]]} return\n+    nowbusy rmtag\n+    update\n+    if {[catch {exec git tag -d $tag} err]} {\n+        notbusy rmtag\n+        error_popup $err\n+        return\n+    }\n+    removetag $id $tag\n+    removedtag $id $tag\n+    redrawtags $id\n+    notbusy rmtag\n+    dispneartags 0\n+    run refill_reflist\n+}\n+\n # Display a list of tags and heads\n proc showrefs {} {\n     global showrefstop bgcolor fgcolor selectbgcolor NS\n@@ -11228,6 +11378,14 @@ proc addedtag {id} {\n     unset -nocomplain cached_atags\n }\n \n+proc removedtag {id tag} {\n+    global cached_dtags cached_atags cached_tagcontent\n+\n+    unset -nocomplain cached_tagcontent\n+    unset -nocomplain cached_dtags\n+    unset -nocomplain cached_atags\n+}\n+\n proc addedhead {hid head} {\n     global arcnos arcout cached_dheads\n \n\nbase-commit: e6362826a0409539642a5738db61827e5978e2e4\n-- \ngitgitgadget\n"},{"id":"417782","messageId":"pull.866.v5.git.1614227923637.gitgitgadget@gmail.com","threadId":"55106","inReplyTo":"pull.866.v4.git.1614164317030.gitgitgadget@gmail.com","subject":"[PATCH v5] gitk: add right-click context menu for tags","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-02-25T04:38:43Z","receivedAt":"2021-02-25T04:39:47Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nAdds a context menu for tag icons with commands similar to what\nexits for branches: \"Rename this tag\", \"Remove this tag\",\n\"Copy tag name\".\n\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n    gitk: add right-click context menu for tags\n    \n    This patch want to fix: https://github.com/gitgitgadget/git/issues/855\n    \n    We can provide for right-clicking the tag icon in gitk Rename this tag\",\n    \"Remove this tag\", \"Copy tag name\" function.\n    \n    For convenience, only the tags on the branch with the number of tags <=3\n    are processed temporarily.\n    \n    Thanks!\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-866%2Fadlternative%2Fgitk_tag_new_opt-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-866/adlternative/gitk_tag_new_opt-v5\nPull-Request: https://github.com/gitgitgadget/git/pull/866\n\nRange-diff vs v4:\n\n 1:  c8b0dfa6628e ! 1:  e7cdb01c1b0f gitk: tag add right click options\n     @@ Metadata\n      Author: ZheNing Hu <adlternative@gmail.com>\n      \n       ## Commit message ##\n     -    gitk: tag add right click options\n     +    gitk: add right-click context menu for tags\n      \n     -    In gitk, we can right-click on the icon of the branch,\n     -    and a directory will pop up to provide us with functions\n     -    such as \"Checkout this branch\", \"Rename this branch\"...,\n     -    but we found that the right-click tag icon does not have\n     -    such a function , So I learned how to write the branch icon,\n     -    and added the following functions \"Rename this tag\",\n     -    \"Remove this tag\", \"Copy tag name\" to right-click the tag icon.\n     -\n     -    This function temporarily only supports those labels independently\n     -    displayed tag(s), and cannot work on label aggregated display\n     -    \"tag...\" or \"n tags...\".\n     +    Adds a context menu for tag icons with commands similar to what\n     +    exits for branches: \"Rename this tag\", \"Remove this tag\",\n     +    \"Copy tag name\".\n      \n          Signed-off-by: ZheNing Hu <adlternative@gmail.com>\n      \n     @@ gitk-git/gitk: proc branchdia {top valvar uivar} {\n      +    } else {\n      +        notbusy renametag\n      +        removetag $id $prevname\n     -+        removedtag $id $tag\n     ++        removedtag $id $prevname\n      +        set tagids($name) $id\n      +        lappend idtags($id) $name\n      +        addedtag $id\n\n\n gitk-git/gitk | 164 +++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 161 insertions(+), 3 deletions(-)\n\ndiff --git a/gitk-git/gitk b/gitk-git/gitk\nindex 23d9dd1fe0d0..a91491ef8088 100755\n--- a/gitk-git/gitk\n+++ b/gitk-git/gitk\n@@ -1874,6 +1874,20 @@ proc removehead {id name} {\n     unset headids($name)\n }\n \n+proc removetag {id name} {\n+    global tagids idtags\n+\n+    if {$idtags($id) eq $name} {\n+        unset idtags($id)\n+    } else {\n+        set i [lsearch -exact $idtags($id) $name]\n+        if {$i >= 0} {\n+            set idtags($id) [lreplace $idtags($id) $i $i]\n+        }\n+    }\n+    unset tagids($name)\n+}\n+\n proc ttk_toplevel {w args} {\n     global use_ttk\n     eval [linsert $args 0 ::toplevel $w]\n@@ -2077,6 +2091,7 @@ proc makewindow {} {\n     global filesepbgcolor filesepfgcolor\n     global mergecolors foundbgcolor currentsearchhitbgcolor\n     global headctxmenu progresscanv progressitem progresscoords statusw\n+    global tagctxmenu\n     global fprogitem fprogcoord lastprogupdate progupdatepending\n     global rprogitem rprogcoord rownumsel numcommits\n     global have_tk85 use_ttk NS\n@@ -2679,12 +2694,20 @@ proc makewindow {} {\n     set headctxmenu .headctxmenu\n     makemenu $headctxmenu {\n         {mc \"Check out this branch\" command cobranch}\n-        {mc \"Rename this branch\" command mvbranch}\n+        {mc \"Rename this branch...\" command mvbranch}\n         {mc \"Remove this branch\" command rmbranch}\n         {mc \"Copy branch name\" command {clipboard clear; clipboard append $headmenuhead}}\n     }\n     $headctxmenu configure -tearoff 0\n \n+    set tagctxmenu .tagctxmenu\n+    makemenu $tagctxmenu {\n+        {mc \"Rename this tag...\" command mvtag}\n+        {mc \"Remove this tag...\" command rmtag}\n+        {mc \"Copy tag name\" command {clipboard clear; clipboard append $tagmenutag}}\n+    }\n+    $tagctxmenu configure -tearoff 0\n+\n     global flist_menu\n     set flist_menu .flistctxmenu\n     makemenu $flist_menu {\n@@ -6581,6 +6604,7 @@ proc drawtags {id x xt y1} {\n \n     set marks {}\n     set ntags 0\n+    set ntags_copy 0\n     set nheads 0\n     set singletag 0\n     set maxtags 3\n@@ -6592,8 +6616,9 @@ proc drawtags {id x xt y1} {\n     if {[info exists idtags($id)]} {\n         set marks $idtags($id)\n         set ntags [llength $marks]\n-        if {$ntags > $maxtags ||\n-            [totalwidth $marks mainfont $extra] > $maxwidth} {\n+        set ntags_copy $ntags\n+        set out_of_bounds [expr {[totalwidth $marks mainfont $extra] > $maxwidth}]\n+        if {$ntags > $maxtags || $out_of_bounds} {\n             # show just a single \"n tags...\" tag\n             set singletag 1\n             if {$ntags == 1} {\n@@ -6678,6 +6703,9 @@ proc drawtags {id x xt y1} {\n                    -font $font -tags [list tag.$id text]]\n         if {$ntags >= 0} {\n             $canv bind $t <1> $tagclick\n+            if {$ntags_copy <= $maxtags && !$out_of_bounds} {\n+              $canv bind $t $ctxbut [list tagmenu %X %Y $id $tag_quoted]\n+            }\n         } elseif {$nheads >= 0} {\n             $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]\n         }\n@@ -9531,6 +9559,57 @@ proc mkbranch {} {\n     branchdia $top val ui\n }\n \n+proc mvtag {} {\n+    global NS\n+    global tagmenuid tagmenutag\n+\n+    set top .tagdialog\n+\n+    set val(name) $tagmenutag\n+    set val(id) $tagmenuid\n+    set val(command) [list mvtaggo $top $tagmenutag]\n+\n+    set ui(title) [mc \"Rename tag %s\" $tagmenutag]\n+    set ui(accept) [mc \"Rename\"]\n+\n+    tagdia $top val ui\n+}\n+\n+proc tagdia {top valvar uivar} {\n+    global NS commitinfo\n+    upvar $valvar val $uivar ui\n+\n+    catch {destroy $top}\n+    ttk_toplevel $top\n+    make_transient $top .\n+    ${NS}::label $top.title -text $ui(title)\n+    grid $top.title - -pady 10\n+    ${NS}::label $top.id -text [mc \"ID:\"]\n+    ${NS}::entry $top.sha1 -width 40\n+    $top.sha1 insert 0 $val(id)\n+    $top.sha1 conf -state readonly\n+    grid $top.id $top.sha1 -sticky w\n+    ${NS}::entry $top.head -width 60\n+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]\n+    $top.head conf -state readonly\n+    grid x $top.head -sticky ew\n+    grid columnconfigure $top 1 -weight 1\n+    ${NS}::label $top.nlab -text [mc \"Name:\"]\n+    ${NS}::entry $top.name -width 40\n+    $top.name insert 0 $val(name)\n+    grid $top.nlab $top.name -sticky w\n+    ${NS}::frame $top.buts\n+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)\n+    ${NS}::button $top.buts.can -text [mc \"Cancel\"] -command \"catch {destroy $top}\"\n+    bind $top <Key-Return> $val(command)\n+    bind $top <Key-Escape> \"catch {destroy $top}\"\n+    grid $top.buts.go $top.buts.can\n+    grid columnconfigure $top.buts 0 -weight 1 -uniform a\n+    grid columnconfigure $top.buts 1 -weight 1 -uniform a\n+    grid $top.buts - -pady 10 -sticky ew\n+    focus $top.name\n+}\n+\n proc mvbranch {} {\n     global NS\n     global headmenuid headmenuhead\n@@ -9582,6 +9661,44 @@ proc branchdia {top valvar uivar} {\n     focus $top.name\n }\n \n+proc mvtaggo {top prevname} {\n+    global tagids idtags idheads mainhead mainheadid\n+\n+    set name [$top.name get]\n+    set id [$top.sha1 get]\n+    if {$name eq $prevname} {\n+          catch {destroy $top}\n+          return\n+    }\n+    if {$name eq {}} {\n+      error_popup [mc \"Please specify a new name for the tag\"] $top\n+      return\n+    }\n+    catch {destroy $top}\n+    nowbusy renametag\n+    update\n+    if {[catch {\n+        # NOTE: for an annotated tag, the new tag points to the old tag object\n+        # where the old primary tag name is still recorded inside. Acceptable.\n+        eval exec \"git tag $name $prevname\"\n+        eval exec \"git tag -d $prevname\"\n+        } err]} {\n+        notbusy renametag\n+        error_popup $err\n+    } else {\n+        notbusy renametag\n+        removetag $id $prevname\n+        removedtag $id $prevname\n+        set tagids($name) $id\n+        lappend idtags($id) $name\n+        addedtag $id\n+        redrawtags $id\n+        dispneartags 0\n+        run refill_reflist\n+    }\n+\n+}\n+\n proc mkbrgo {top} {\n     global headids idheads\n \n@@ -9915,6 +10032,17 @@ proc headmenu {x y id head} {\n     tk_popup $headctxmenu $x $y\n }\n \n+# context menu for a tag\n+proc tagmenu {x y id tag} {\n+    global tagmenuid tagmenutag tagctxmenu mainhead\n+\n+    stopfinding\n+    set tagmenuid $id\n+    set tagmenutag $tag\n+\n+    tk_popup $tagctxmenu $x $y\n+}\n+\n proc cobranch {} {\n     global headmenuid headmenuhead headids\n     global showlocalchanges\n@@ -10019,6 +10147,28 @@ proc rmbranch {} {\n     run refill_reflist\n }\n \n+proc rmtag {} {\n+    global tagmenuid tagmenutag\n+    global idtags\n+\n+    set tag $tagmenutag\n+    set id $tagmenuid\n+    if {![confirm_popup [mc \"Really delete tag %s?\" $tag]]} return\n+    nowbusy rmtag\n+    update\n+    if {[catch {exec git tag -d $tag} err]} {\n+        notbusy rmtag\n+        error_popup $err\n+        return\n+    }\n+    removetag $id $tag\n+    removedtag $id $tag\n+    redrawtags $id\n+    notbusy rmtag\n+    dispneartags 0\n+    run refill_reflist\n+}\n+\n # Display a list of tags and heads\n proc showrefs {} {\n     global showrefstop bgcolor fgcolor selectbgcolor NS\n@@ -11228,6 +11378,14 @@ proc addedtag {id} {\n     unset -nocomplain cached_atags\n }\n \n+proc removedtag {id tag} {\n+    global cached_dtags cached_atags cached_tagcontent\n+\n+    unset -nocomplain cached_tagcontent\n+    unset -nocomplain cached_dtags\n+    unset -nocomplain cached_atags\n+}\n+\n proc addedhead {hid head} {\n     global arcnos arcout cached_dheads\n \n\nbase-commit: e6362826a0409539642a5738db61827e5978e2e4\n-- \ngitgitgadget\n"}]}