From 8d0d71a5e890a42bfff39eaf9896783375b3921b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 11 Oct 2011 13:37:23 -0500 Subject: [PATCH] Configurable hyperlinking in gitk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many projects use project-specific notations in changelogs to refer to bug trackers and the like. One example is the "Closes: #12345" notation used in Debian. Make gitk configurable so that arbitrary strings can be turned into clickable links that are opened in a web browser. [zj: updated documentation patch in the description below following Junio's suggestion] Signed-off-by: Jeff Epler Signed-off-by: Zbigniew Jędrzejewski-Szmek The following changes to documentation should go along with this patch: diff --git a/Documentation/config.txt b/Documentation/config.txt index ae9913b..ffc9ccf 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1064,6 +1064,10 @@ All gitcvs variables except for 'gitcvs.usecrlfattr' and is one of "ext" and "pserver") to make them apply only for the given access method. +gitk.browser:: + Specify the browser that will be used to open links generated by + 'linkify' configuration options. + grep.lineNumber:: If set to true, enable '-n' option by default. @@ -1317,6 +1321,28 @@ interactive.singlekey:: setting is silently ignored if portable keystroke input is not available. +linkify..regexp:: + A string that matches this regexp is converted to a hyperlink + using the value of corresponding `linkify..subst` + variable. The regular expression is passed to the regexp + engine of Tcl (in gitk) or Perl (in gitweb). + +linkify..subst:: + A string matching the value of the corresponding + `linkify..regexp` variable is rewritten to this URL. The + value of this variable can contain back-references like `\1` + to refer to capturing groups in the associated regular expression. ++ +For example, to automatically link from Debian-style "Closes: #nnnn" +message to the Debian BTS, ++ +-------- + git config linkify.debian-bts.regexp '#([1-9][0-9]*)' + git config linkify.debian-bts.subst 'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=\1' +-------- ++ +Currently, only linkgit:gitk[1] converts strings to links in this fashion. + log.abbrevCommit:: If true, makes linkgit:git-log[1], linkgit:git-show[1], and linkgit:git-whatchanged[1] assume `\--abbrev-commit`. You may @@ -1870,5 +1896,5 @@ user.signingkey:: web.browser:: Specify a web browser that may be used by some commands. - Currently only linkgit:git-instaweb[1] and linkgit:git-help[1] - may use it. + Currently only linkgit:git-instaweb[1], linkgit:gitk[1], + and linkgit:git-help[1] may use it. --- gitk | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 64ef3c4..2ca22af 100755 --- a/gitk +++ b/gitk @@ -6701,7 +6701,7 @@ proc commit_descriptor {p} { # append some text to the ctext widget, and make any SHA1 ID # that we know about be a clickable link. proc appendwithlinks {text tags} { - global ctext linknum curview + global ctext linknum curview linkmakers set start [$ctext index "end - 1c"] $ctext insert end $text $tags @@ -6716,6 +6716,30 @@ proc appendwithlinks {text tags} { setlink $linkid link$linknum incr linknum } + + if {$linkmakers == {}} return + + set link_re {} + foreach {re rep} $linkmakers { lappend link_re $re } + set link_re "([join $link_re {)|(}])" + + set ee 0 + while {[regexp -indices -start $ee -- $link_re $text l]} { + set s [lindex $l 0] + set e [lindex $l 1] + set linktext [string range $text $s $e] + incr e + set ee $e + + foreach {re rep} $linkmakers { + if {![regsub $re $linktext $rep linkurl]} continue + $ctext tag delete link$linknum + $ctext tag add link$linknum "$start + $s c" "$start + $e c" + seturllink $linkurl link$linknum + incr linknum + break + } + } } proc setlink {id lk} { @@ -6743,6 +6767,53 @@ proc setlink {id lk} { } } +proc get_link_config {} { + if {[catch {exec git config -z --get-regexp {^linkify\.}} linkers]} { + return {} + } + + set linktypes [list] + foreach item [split $linkers "\0"] { + if {$item == ""} continue + if {![regexp {linkify\.(\S+)\.(regexp|subst)\s(.*)} $item _ k t v]} { + continue + } + set linkconfig($t,$k) $v + if {$t == "regexp"} { lappend linktypes $k } + } + + set linkmakers [list] + foreach k $linktypes { + if {![info exists linkconfig(subst,$k)]} { + puts stderr "Warning: link `$k' is missing a substitution string" + } elseif {[catch {regexp -inline -- $linkconfig(regexp,$k) ""} err]} { + puts stderr "Warning: link `$k': $err" + } else { + lappend linkmakers $linkconfig(regexp,$k) $linkconfig(subst,$k) + } + unset linkconfig(regexp,$k) + unset -nocomplain linkconfig(subst,$k) + } + foreach k [array names linkconfig] { + regexp "subst,(.*)" $k _ k + puts stderr "Warning: link `$k' is missing a regular expression" + } + set linkmakers +} + +proc openlink {url} { + exec git web--browse --config=gitk.browser $url & +} + +proc seturllink {url lk} { + set qurl [string map {% %%} $url] + global ctext + $ctext tag conf $lk -foreground blue -underline 1 + $ctext tag bind $lk <1> [list openlink $qurl] + $ctext tag bind $lk {linkcursor %W 1} + $ctext tag bind $lk {linkcursor %W -1} +} + proc appendshortlink {id {pre {}} {post {}}} { global ctext linknum @@ -11713,6 +11784,8 @@ if {[tk windowingsystem] eq "win32"} { focus -force . } +set linkmakers [get_link_config] + getcommits {} # Local variables: