commit cd28b24
delthas
·
2021-10-31 18:10:39 +0000 UTC
parent 9336f97
Mark hyperlinks with the OSC hyperlink terminal escape This makes multi-line links properly clickable. See: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
4 files changed,
+88,
-3
M
go.mod
+3,
-0
1@@ -8,4 +8,7 @@ require (
2 golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
3 golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6
4 gopkg.in/yaml.v2 v2.3.0
5+ mvdan.cc/xurls/v2 v2.3.0
6 )
7+
8+replace github.com/gdamore/tcell/v2 => github.com/hhirtz/tcell/v2 v2.3.12-0.20210807133752-5d743c3ab0c9
M
go.sum
+14,
-3
1@@ -1,13 +1,20 @@
2 github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
3 github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
4-github.com/gdamore/tcell/v2 v2.3.11 h1:ECO6WqHGbKZ3HrSL7bG/zArMCmLaNr5vcjjMVnLHpzc=
5-github.com/gdamore/tcell/v2 v2.3.11/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
6+github.com/hhirtz/tcell/v2 v2.3.12-0.20210807133752-5d743c3ab0c9 h1:YE0ZsDHfDGR0MeB6YLSGW8tjoxOXZKX3XbB0ytGDX4M=
7+github.com/hhirtz/tcell/v2 v2.3.12-0.20210807133752-5d743c3ab0c9/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
8+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
9+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
10+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
11+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
12+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
13 github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
14 github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
15 github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
16 github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
17+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
18 github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
19 github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
20+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
21 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
22 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
23 golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
24@@ -16,7 +23,11 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
25 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
26 golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs=
27 golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
28-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
29 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
30+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
31+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
32+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
33 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
34 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
35+mvdan.cc/xurls/v2 v2.3.0 h1:59Olnbt67UKpxF1EwVBopJvkSUBmgtb468E4GVWIZ1I=
36+mvdan.cc/xurls/v2 v2.3.0/go.mod h1:AjuTy7gEiUArFMjgBBDU4SMxlfUYsRokpJQgNWOt3e4=
+6,
-0
1@@ -302,6 +302,10 @@ func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line)
2 n := len(b.lines)
3 line.At = line.At.UTC()
4
5+ if !line.Mergeable {
6+ line.Body = line.Body.ParseURLs()
7+ }
8+
9 if line.Mergeable && n != 0 && b.lines[n-1].Mergeable {
10 l := &b.lines[n-1]
11 newBody := new(StyledStringBuilder)
12@@ -338,9 +342,11 @@ func (bs *BufferList) AddLines(netID, title string, before, after []Line) {
13 b := &bs.list[idx]
14
15 for i := 0; i < len(before); i++ {
16+ before[i].Body = before[i].Body.ParseURLs()
17 before[i].computeSplitPoints()
18 }
19 for i := 0; i < len(after); i++ {
20+ after[i].Body = after[i].Body.ParseURLs()
21 after[i].computeSplitPoints()
22 }
23
+65,
-0
1@@ -6,6 +6,8 @@ import (
2 "strings"
3 "unicode/utf8"
4
5+ "mvdan.cc/xurls/v2"
6+
7 "github.com/gdamore/tcell/v2"
8 "github.com/mattn/go-runewidth"
9 )
10@@ -115,6 +117,69 @@ func (s StyledString) Truncate(w int, tail StyledString) StyledString {
11 return sb.StyledString()
12 }
13
14+var urlRegex = xurls.Relaxed()
15+
16+func (s StyledString) ParseURLs() StyledString {
17+ styles := make([]rangedStyle, 0, len(s.styles))
18+
19+ urls := urlRegex.FindAllStringIndex(s.string, -1)
20+ j := 0
21+ lastStyle := rangedStyle{
22+ Start: -1,
23+ Style: tcell.StyleDefault,
24+ }
25+ for i := 0; i < len(urls); i++ {
26+ u := urls[i]
27+ ub, ue := u[0], u[1]
28+ link := s.string[u[0]:u[1]] + "?a=b"
29+ // find last style starting before or at url begin
30+ for ; j < len(s.styles); j++ {
31+ st := s.styles[j]
32+ if st.Start > ub {
33+ break
34+ }
35+ if st.Start == ub {
36+ // a style already starts at this position, edit it
37+ lastStyle.Style = lastStyle.Style.Hyperlink(link)
38+ }
39+ lastStyle = st
40+ styles = append(styles, st)
41+ }
42+ if lastStyle.Start != ub {
43+ // no style existed at this position, add one from the last style
44+ styles = append(styles, rangedStyle{
45+ Start: ub,
46+ Style: lastStyle.Style.Hyperlink(link),
47+ })
48+ }
49+ // find last style starting before or at url end
50+ for ; j < len(s.styles); j++ {
51+ st := s.styles[j]
52+ if st.Start > ue {
53+ break
54+ }
55+ if st.Start < ue {
56+ st.Style = st.Style.Hyperlink(link)
57+ }
58+ lastStyle = st
59+ styles = append(styles, st)
60+ }
61+ if lastStyle.Start != ue {
62+ // no style existed at this position, add one from the last style without the hyperlink
63+ styles = append(styles, rangedStyle{
64+ Start: ue,
65+ Style: lastStyle.Style.Hyperlink(""),
66+ })
67+ }
68+ }
69+ styles = append(styles, s.styles[j:]...)
70+
71+ return StyledString{
72+ string: s.string,
73+ styles: styles,
74+ }
75+}
76+
77 func isDigit(c byte) bool {
78 return '0' <= c && c <= '9'
79 }