Documentation
¶
Overview ¶
Package diff models a unified diff: the files it touches, their hunks, and the lines within them, down to the runs that changed inside a single line.
It knows nothing about terminals. The review screen renders what this package produces and addresses it by index, which is what lets the awkward parts — line numbering, intra-line spans, mapping a selection back to the position a provider will accept — be tested without a terminal at all.
Index ¶
- type Doc
- func (d *Doc) AllFolded() bool
- func (d *Doc) Current() (Row, bool)
- func (d *Doc) CurrentFile() (File, int, bool)
- func (d *Doc) Cursor() int
- func (d *Doc) CursorToFile(file int)
- func (d *Doc) CycleMode() Mode
- func (d *Doc) DropSelection()
- func (d *Doc) ExtendSubLine(delta int)
- func (d *Doc) InSelection(row int) bool
- func (d *Doc) Len() int
- func (d *Doc) Mode() Mode
- func (d *Doc) Move(delta, height int)
- func (d *Doc) MoveFile(delta, height int)
- func (d *Doc) MoveTo(row, height int)
- func (d *Doc) Progress() (read, total int)
- func (d *Doc) Row(i int) (Row, bool)
- func (d *Doc) Rows() []Row
- func (d *Doc) Scroll(delta, height int)
- func (d *Doc) ScrollIntoView(height int)
- func (d *Doc) SelectHunk()
- func (d *Doc) SelectedLines() []Line
- func (d *Doc) SelectedText() string
- func (d *Doc) Selecting() bool
- func (d *Doc) Selection() Selection
- func (d *Doc) SetAllFolded(collapsed bool)
- func (d *Doc) SetFold(file int, collapsed bool)
- func (d *Doc) SetNotes(notes map[NoteKey][]string)
- func (d *Doc) Snippet() string
- func (d *Doc) State(file int) (collapsed, read bool)
- func (d *Doc) SubLineRange(row int) (start, end int, ok bool)
- func (d *Doc) ToggleFold()
- func (d *Doc) ToggleRead(height int)
- func (d *Doc) ToggleSelect()
- func (d *Doc) Top() int
- type File
- type Files
- type Highlighter
- type Hunk
- type Kind
- type Line
- type Mode
- type NoteKey
- type Row
- type RowKind
- type Segment
- type Selection
- type Token
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Doc ¶
type Doc struct {
Files Files
// contains filtered or unexported fields
}
Doc is a diff being reviewed: the files, how they are folded, and where the caret and selection are.
func (*Doc) CurrentFile ¶
CurrentFile is the file the caret is in.
func (*Doc) CursorToFile ¶
CursorToFile puts the caret on a file's header row.
func (*Doc) CycleMode ¶
CycleMode steps line → word → char → line.
One key rather than three: the modes are a progression, and a reviewer reaching for finer detail wants the next notch, not to remember which key means which.
func (*Doc) DropSelection ¶
func (d *Doc) DropSelection()
DropSelection clears the selection, leaving the caret alone.
func (*Doc) ExtendSubLine ¶
ExtendSubLine grows or shrinks the sub-line selection by one unit of the current mode: a word in Words, a rune in Chars.
func (*Doc) InSelection ¶
InSelection reports whether a row is inside the selection.
func (*Doc) Move ¶
Move steps the caret, dragging a selection with it and scrolling to keep it on screen.
func (*Doc) MoveFile ¶
MoveFile jumps to the next or previous file, stopping at the ends rather than wrapping — wrapping past the last file reads as a bug.
func (*Doc) Scroll ¶
Scroll moves the window without moving the caret, which is what a mouse wheel does.
func (*Doc) ScrollIntoView ¶
ScrollIntoView moves the window the least it can to show the caret.
func (*Doc) SelectHunk ¶
func (d *Doc) SelectHunk()
SelectHunk marks every content line of the hunk the caret is in.
func (*Doc) SelectedLines ¶
SelectedLines is the content lines the selection covers, in order.
func (*Doc) SelectedText ¶
SelectedText is what the selection actually covers: the marked span of one line in a sub-line mode, the whole lines otherwise.
func (*Doc) Selection ¶
Selection is the marked range, normalised so From <= To.
With nothing selected it is the caret's own row, so every action that works on a selection also works on where you are standing — there is no state in which `c` has nothing to comment on.
func (*Doc) SetAllFolded ¶
SetAllFolded folds or unfolds everything.
func (*Doc) SetNotes ¶
SetNotes pins remarks under the lines they were made about. Passing a fresh map replaces the lot, which is what happens when one is added or dropped.
func (*Doc) Snippet ¶
Snippet is the selection as diff text, markers and all, for quoting back in a comment.
func (*Doc) SubLineRange ¶
SubLineRange is the byte range selected within a row, and whether there is one. Only a sub-line selection on the caret's own row has one.
func (*Doc) ToggleFold ¶
func (d *Doc) ToggleFold()
ToggleFold folds or unfolds the file the caret is in — whichever file that is, which is the point of hanging it off the caret rather than off an index the screen has to track separately.
func (*Doc) ToggleRead ¶
ToggleRead marks the caret's file read and folds it, so the list shrinks to what is left to review; unmarking restores it.
func (*Doc) ToggleSelect ¶
func (d *Doc) ToggleSelect()
ToggleSelect starts a selection at the caret, or drops the one there is.
type File ¶
type File struct {
// OldPath and NewPath differ on a rename, and one is empty when the file
// was added or deleted.
OldPath, NewPath string
Hunks []Hunk
Added, Removed int
Binary bool
// Mode records a change the diff reports but has no lines for, such as a
// permission change, so the file is not shown as empty for no reason.
Mode string
}
File is one file's worth of a diff.
type Files ¶
type Files []File
Files is a whole diff.
func Parse ¶
Parse reads a unified diff.
It is written to survive whatever the providers actually send rather than only well-formed output: a file with no hunks, a hunk with no counts, a deleted file with no "+++ b/" line. Anything it cannot place is dropped rather than guessed at, because a diff that lies about line numbers would anchor a comment to the wrong line.
type Highlighter ¶
type Highlighter struct {
// contains filtered or unexported fields
}
Highlighter tokenises source lines for one file.
It works per line rather than per file because the review screen only ever draws the visible window, and lexing a ten-thousand-line diff to show forty rows of it is work nobody asked for. The cost is that a lexer cannot see across lines — a multi-line string or comment is highlighted as if each line stood alone. For a diff that is the right trade: a diff is already a set of fragments, and hunks routinely start inside a construct anyway.
func NewHighlighter ¶
func NewHighlighter(path string) *Highlighter
NewHighlighter picks a lexer from the file's name. A file whose language is unknown gets a highlighter that returns the line unchanged, so callers never have to check for nil.
func (*Highlighter) Enabled ¶
func (h *Highlighter) Enabled() bool
Enabled reports whether the file's language was recognised.
func (*Highlighter) Tokens ¶
func (h *Highlighter) Tokens(line string) []Token
Tokens splits one line into its syntactic runs.
A line that cannot be lexed comes back as a single untyped run rather than an error: losing colour on one line is not worth failing a review screen over.
type Hunk ¶
type Hunk struct {
OldStart, OldCount int
NewStart, NewCount int
// Section is the text after the closing @@, which git fills with the
// enclosing function.
Section string
Lines []Line
}
Hunk is one @@ block.
type Line ¶
type Line struct {
Kind Kind
// Old and New are the line's number on each side, zero where the line does
// not exist on that side.
Old, New int
Text string
// Segments splits Text into runs that changed and runs that did not, for a
// changed line paired with its counterpart. A line with no counterpart
// carries a single Equal segment covering the whole of it.
Segments []Segment
// NoNewline marks the line git flagged with "\ No newline at end of file",
// which must survive a suggestion round-trip.
NoNewline bool
}
Line is one line of one hunk.
type Mode ¶
type Mode int
Mode is how far a selection reaches at a time.
The three granularities, in the order the cycle key steps through them.
type NoteKey ¶
NoteKey identifies the line a note hangs under. It is the line's numbers rather than its row index, because folding moves rows and does not move lines.
type Row ¶
type Row struct {
Kind RowKind
File int
Hunk int
// Line is the content the row shows; the zero value for a header row.
Line Line
// Note is the text of a NoteRow — a remark pinned under the line it is
// about, so an unpublished comment is visible where it was made.
Note string
}
Row is one line on screen: what it shows, and where it came from.
Rows are how the screen and the model agree on a position. The caret is a row index, so folding a file, marking it read, scrolling and selecting all work on the same number, and none of them can drift apart from the others.
func (Row) Selectable ¶
Selectable reports whether the row is something a comment can be made about.
type Segment ¶
type Segment struct {
Kind Kind
Text string
// Start is the byte offset of the run within the line, so a character
// selection and a word selection address the same string.
Start int
}
Segment is a run within a line: the text, and whether it is part of what changed.
type Selection ¶
type Selection struct {
Mode Mode
// From and To are row indices, ordered.
From, To int
// Start and End are byte offsets into the row's line, used only in Words
// and Chars mode.
Start, End int
Active bool
}
Selection is what the caret has marked.
Line selections span rows. Word and character selections stay within one line — which is not a shortcut but the truth of what can be expressed: neither provider anchors a comment to a column, so a sub-line selection describes a span *within* a line, and a span across lines is a line selection by definition.
type Token ¶
type Token struct {
Text string
// Type is chroma's classification. The renderer maps it to a colour; a
// zero value means "no opinion", which is what an unknown language gives.
Type chroma.TokenType
// Start is the byte offset within the line, so highlighting and selection
// address the same string.
Start int
}
Token is a run of a line with a syntactic role, ready to be coloured.