Documentation
¶
Overview ¶
Package link finds the things in a piece of text that point somewhere.
A terminal that speaks OSC 8 will make a range of cells clickable, and [grid.Cell] carries the target for exactly that. What it cannot do is work out which part of a line points somewhere in the first place — that is this package, and it is a surprising amount of care for what looks like two regular expressions.
Two kinds, because they are two things ¶
A URL and a file path are not one destination with two spellings. A URL is opened by a browser and can be handed to a terminal as an OSC 8 target; a file is opened by an editor, at a line, and handing the terminal a file:// for it is usually worse than saying nothing — see Link.Hyperlink.
In an agent's output the file is the commoner one. A model saying which file it changed, and where, is the thing a reader most wants to click.
What is not here ¶
Opening one. Which browser, which editor, whether the process is sandboxed, whether a path from tool output should be opened at all — none of that is a terminal library's to decide, and a library that decided would be a framework for one program. The answer is a byte range and a destination; what happens on a click is the caller's.
Nor is the filesystem. This package reads text and nothing else, which is why the one rule that needs the filesystem takes it as an argument — see DetectIn.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Link ¶
type Link struct {
// Start and End are the byte range of the text that was matched, which is what a
// caller stamps onto cells with [text.StampLink].
Start, End int
// Kind says which sort of destination Target is.
Kind Kind
// Target is the destination. It is not always the matched text: a bare host is
// given the scheme it was written without, a quoted path loses its quotes, and a
// line and column suffix is taken off and reported separately.
Target string
// Line and Column are where in a file the reference points, counting from one, or
// zero when it did not say. Both are always zero for a URL.
//
// "src/main.go:42" is the shape a compiler, a stack trace and a model all use, and
// a link that opened the file at the top would throw away the useful half of what
// was written.
Line, Column int
}
Link is one thing in a piece of text that points somewhere.
func At ¶ added in v0.0.2
At is the link covering a byte offset, and whether there is one.
Start is inclusive and End exclusive, so a click on the character after a link is not a click on the link. The scan is linear because a line holds a handful of these and an index over them would cost more to build than to skip.
func Detect ¶
Detect finds every link in s, in the order they appear, as byte ranges into s.
Only what can be recognised from the text alone. A bare filename cannot be — see DetectIn, which is this with the one question this package cannot answer handed in.
func DetectIn ¶ added in v0.0.2
DetectIn finds every link in s, asking exists about the shapes that cannot be told from prose by looking at them.
exists is given a path exactly as it was written, relative and unexpanded, and answers whether there is a file there. A nil exists asks nothing and leaves the ambiguous shapes out, which is Detect and which is the right answer for text whose paths belong to somebody else's machine.
It is an argument rather than a call into the operating system because this package reads text. A library that quietly stat'd every word of a model's output would be doing something no reader of its documentation had reason to expect.
func (Link) Hyperlink ¶ added in v0.0.2
Hyperlink is what to give a terminal as an OSC 8 target, and whether to give it one at all.
A URL is given as it is. A relative path is not given at all, and that refusal is the interesting half: terminals find paths in their own output, know the directory the program is running in, and offer to open one in the editor the user actually uses. Wrapping a path in a link takes all of that away and replaces it with a destination the terminal will hand to a browser.
An absolute path is the exception. There a file:// target says exactly what it means, and a terminal that does nothing with it is no worse off than before.
type Map ¶ added in v0.0.2
type Map struct {
// contains filtered or unexported fields
}
Map records where links were drawn, so that a click can be answered.
It is filled while drawing and read when a click arrives. That is the only arrangement of these two that cannot fall out of step: the record is produced by the pass that drew the cells, so there is nothing to invalidate, no second detection over text that may have changed since, and no cache to be wrong.
A Map holds screen positions, so it belongs to a frame. Reset it at the start of each one — see Map.Reset for why that is cheap.
func (*Map) Add ¶ added in v0.0.2
Add records that w columns from (x, y) carry url. A run of no width records nothing, which is what a link scrolled off the edge comes to.
func (*Map) At ¶ added in v0.0.2
At is the target at a screen position, and whether there is one.
Later records win, which is what overlapping draws mean: something drawn over a link covers it, and a click lands on what is in front.