git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RESEND PATCH v3] Configurable hyperlinking in gitk

From
Jeff Epler <jepler@unpythonic.net>
Date
Oct 11, 2011, 18:37 UTC
Message-ID
<20111011183722.GA26646@unpythonic.net>
In-Reply-To
<20110922013101.GB26880@unpythonic.net>

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@unpythonic.net>
---
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
Previous: Jeff EplerNext: Junio C Hamano
Message 31 of 33 in “Configurable hyperlinking in gitk”
  1. Configurable hyperlinking in gitkJeff Epler, Sep 17, 2011
  2. Chris PackhamSep 17, 2011
  3. Chris PackhamSep 17, 2011
  4. Jeff EplerSep 17, 2011
  5. Chris PackhamSep 17, 2011
  6. git web--browse error handling URL with & in it (Was Re: [RFC/PATCH] Configurable hyperlinking in gitk)Chris Packham, Sep 18, 2011
  7. Chris PackhamSep 18, 2011
  8. Jeff KingSep 18, 2011
  9. git-web--browse: invoke kfmclient directlyChris Packham, Sep 18, 2011
  10. Jeff KingSep 18, 2011
  11. [RFC/PATCHv2] git-web--browse: avoid the use of evalChris Packham, Sep 19, 2011
  12. Jeff KingSep 19, 2011
  13. Chris PackhamSep 20, 2011
  14. Jeff KingSep 20, 2011
  15. Junio C HamanoSep 20, 2011
  16. Junio C HamanoSep 19, 2011
  17. Jeff KingSep 19, 2011
  18. Junio C HamanoSep 19, 2011
  19. Jeff KingSep 19, 2011
  20. Junio C HamanoSep 19, 2011
  21. Andreas SchwabSep 19, 2011
  22. Jeff KingSep 19, 2011
  23. Junio C HamanoSep 19, 2011
  24. Andreas SchwabSep 19, 2011
  25. Jakub NarebskiSep 19, 2011
  26. Christian CouderSep 18, 2011
  27. Marc BranchaudSep 19, 2011
  28. Jakub NarebskiSep 18, 2011
  29. Jeff EplerSep 22, 2011
  30. Configurable hyperlinking in gitkJeff Epler, Sep 22, 2011
  31. Configurable hyperlinking in gitkJeff Epler, Oct 11, 2011
  32. Junio C HamanoOct 11, 2011
  33. Chris PackhamOct 12, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.