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. Signed-off-by: Jeff Epler <jepler@xxxxxxxxxxxxxx> --- This v3 patch didn't generate any discussion last time around (~3 weeks ago), so I've taken the liberty of reposting it. I'm aware of no problems with this patch, and a number of people have commented that it is useful to them. For URLs that contain "&" and other shell metacharacters, it *does* depend on r480f062c "git-web--browse: avoid the use of eval" which is in next but not maint. Since the V2 patch, I * Renamed configuration variables to get rid of the "gitk" prefix to encourage other git-related programs to adopt the same functionality. * Renamed configuration variables from cryptic "re", "sub" to less cryptic "regexp" and "subst" * Changed the example RE to be an ERE (no \d or \M) * Documented that these are POSIX EREs; hopefully that's OK. I see in CodingGuidelines that in git itself "a subset of BREs" are used, so maybe even this is too much power. And hopefully tcl's re_syntax really is close enough to an ERE superset that this isn't a terrible lie about the initial implementation either. * Added a Signed-Off-By, since I've had a number of positive feedbacks and the only problems I've heard of (since patch v2) are the ones related to 'eval' in git-web--browse. In v2 of the patch, I had fixed a problem with %-signs in URLs and changed the documentation example. Documentation/config.txt | 30 +++++++++++++++++- gitk-git/gitk | 75 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) 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.<name>.regexp:: + Specify a regular expression in the POSIX Extended Regular Expression + syntax defining a class of strings to automatically convert to + hyperlinks. This regular expression many not span multiple lines. + You must also specify 'linkify.<name>.subst'. + +linkify.<name>.subst:: + Specify a substitution that results in the target URL for the + related regular expression. Back-references like '\1' refer + to capturing groups in the associated regular expression. + You must also specify 'linkify.<name>.regexp'. ++ +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. diff --git a/gitk-git/gitk b/gitk-git/gitk index 4cde0c4..9db5525 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -6684,7 +6684,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 @@ -6699,6 +6699,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} { @@ -6726,6 +6750,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 <Enter> {linkcursor %W 1} + $ctext tag bind $lk <Leave> {linkcursor %W -1} +} + proc appendshortlink {id {pre {}} {post {}}} { global ctext linknum @@ -11693,6 +11764,8 @@ if {[tk windowingsystem] eq "win32"} { focus -force . } +set linkmakers [get_link_config] + getcommits {} # Local variables: -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html