buffer

package
v0.0.0-...-721981a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2022 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LF   = "\n"
	CRLF = "\r\n"
)

Variables

This section is empty.

Functions

func Clamp

func Clamp(v, a, b int) int

Clamp keeps `v` within `a` and `b` numerically. `a` must be smaller than `b`. Returns clamped `v`.

func DetectLineDelim

func DetectLineDelim(contents []byte) string

DetectLineDelim searches for a CRLF "\r\n" or LF "\n", and if neither is found, it produces a default value LF "\n".

func Max

func Max(a, b int) int

Max returns the larger integer.

func Min

func Min(a, b int) int

Min returns the smaller integer.

Types

type Buffer

type Buffer interface {
	// Line gets a slice of the provided line with the delimiter if delim is true,
	// and one is present. Returns line bytes and whether a delimiter is included in
	// the result. Data returned may or may not be a copy: do not write to it.
	Line(line int, delim bool) (bytes []byte, hasDelim bool)

	// Returns a slice of the buffer from startLine, startCol, to endLine, endCol,
	// inclusive bounds. The returned value may or may not be a copy of the data,
	// so do not write to it.
	Slice(startLine, startCol, endLine, endCol int) []byte

	// RuneAtPos returns the UTF-8 rune at the byte position `pos` of the buffer and the
	// size of the rune in bytes. The position must be valid, otherwise zero will be
	// returned.
	RuneAtPos(pos int) (r rune, size int)

	// EachRuneFromPos executes the function `f` for each rune from byte position `pos`.
	// This function should be used as opposed to performing a "per character" operation
	// manually, as it enables caching buffer operations and safety checks. The function
	// returns when the end of the buffer is met or `f` returns true.
	EachRuneFromPos(pos int, f func(pos int, r rune) bool)

	// Bytes returns all of the bytes in the buffer. This function is very likely
	// to copy all of the data in the buffer. Use sparingly. Try using other methods,
	// where possible.
	Bytes() []byte

	// Insert copies a byte slice (inserting it) into the position at line, col.
	Insert(line, col int, bytes []byte)

	// Remove deletes any characters between startLine, startCol, and endLine,
	// endCol, inclusive bounds.
	Remove(startLine, startCol, endLine, endCol int)

	// Returns the number of occurrences of 'sequence' in the buffer, within the range
	// of start line and col, to end line and col, inclusive bounds.
	Count(startLine, startCol, endLine, endCol int, sequence []byte) int

	// Len counts the number of bytes in the buffer.
	Len() int

	// Lines counts the number of lines in the buffer. If the buffer is empty, 1 is
	// returned, because there is always at least one line. This function basically
	// counts 1 + the number of delimiters in a buffer.
	Lines() int

	// Returns the line delimiter being used by the Buffer to separate lines. A Buffer
	// should have their delimiter set automatically, most likely when provided text.
	LineDelimiter() string

	// SetLineDelimiter overwrites the current delimiter being used by the Buffer to
	// separate the contents into lines.
	SetLineDelimiter(delim string)

	// LineHasDelimiter returns true if the line ends with the value of the Buffer's
	// set line delimiter. You can get the line delimiter string with LineDelimiter(),
	// and change it with SetLineDelimiter(delim).
	LineHasDelimiter(line int) bool

	// RunesInLine returns the number of runes in the given line. That is, the
	// number of UTF-8 codepoints in the line, not bytes. delim can be true to include
	// the line delimiter if present. Returns the number of runes and whether a
	// line delimiter is included in the result.
	RunesInLine(line int, delim bool) (runes int, hasDelim bool)

	// ClampLineCol is a utility function to clamp any provided line and col to
	// only possible values within the buffer pointing to runes. It first clamps
	// the line, then clamps the column. The column is clamped between zero and
	// the last rune before the line delimiter if one is present.
	ClampLineCol(line, col int) (int, int)

	// LineColToPos returns the index of the byte at line, col. If col is greater
	// than the length of the line, the position of the last byte in the line is
	// returned, instead. May include a delimiter. Use LineHasDelimiter(line) to
	// check if one is present.
	LineColToPos(line, col int) int

	// PosToLineCol converts a byte offset (position) of the buffer's bytes, into
	// a line and column. Position will be clamped.
	PosToLineCol(pos int) (line, col int)

	// Writes the Buffer to the provided io.Writer. Returns the number of bytes
	// written, and any error that may have occurred.
	WriteTo(w io.Writer) (int64, error)

	// RegisterCursor adds the Cursor to a slice which the Buffer manages to update
	// each Cursor based on changes that occur in the Buffer. Various functions are
	// called on the Cursor depending upon where the edits occurred and how it should
	// modify the Cursor's position.
	//
	// It is a good idea to call UnregisterCursor() when the cursor is no longer needed,
	// otherwise it will persist.
	RegisterCursor(cursor *Cursor)

	// UnregisterCursor will remove the cursor from the list of watched Cursors.
	UnregisterCursor(cursor *Cursor)
}

A Buffer is wrapper around any buffer data structure like a rope or gap buffer that can be used for editing text. One way this interface helps is by making all API function parameters line and column indexes, so it is simple and easy to index and use like a text editor. All lines and columns start at zero, and all "end" ranges are inclusive.

Any bounds out of range are panics! If you are unsure your position or range may be out of bounds, use ClampLineCol() or compare with Lines() or ColsInLine().

type ByCol

type ByCol []Match

ByCol implements sort.Interface for []Match based on the Col field.

func (ByCol) Len

func (c ByCol) Len() int

func (ByCol) Less

func (c ByCol) Less(i, j int) bool

func (ByCol) Swap

func (c ByCol) Swap(i, j int)

type Colorscheme

type Colorscheme map[Syntax]tcell.Style

func (*Colorscheme) GetStyle

func (c *Colorscheme) GetStyle(s Syntax) tcell.Style

Gets the tcell.Style from the Colorscheme map for the given Syntax. If the Syntax cannot be found in the map, either the `Default` Syntax is used, or `tcell.DefaultStyle` is returned if the Default is not assigned.

type Cursor

type Cursor struct {
	Line int
	Col  int
	// contains filtered or unexported fields
}

A Cursor's functions emulate common cursor actions. To have a Cursor be automatically updated when the buffer has text prepended or appended -- one should register the Cursor with the Buffer's function `RegisterCursor()` which makes the Cursor "anchored" to the Buffers contents when they change.

func NewCursor

func NewCursor(in Buffer) *Cursor

func (*Cursor) Down

func (c *Cursor) Down()

func (*Cursor) Eq

func (c *Cursor) Eq(other *Cursor) bool

func (*Cursor) Left

func (c *Cursor) Left()

func (*Cursor) LineCol

func (c *Cursor) LineCol(line, col int)

LineCol sets the Line and Col of the Cursor to those provided. `line` is clamped within the range [0, lines in buffer). `col` is then clamped within the range [0, line length in runes minus delimiter).

func (*Cursor) NextWordBoundaryEnd

func (c *Cursor) NextWordBoundaryEnd()

NextWordBoundaryEnd proceeds to the position after the last character of the next word boundary to the right of the Cursor. A word boundary is the beginning or end of any sequence of similar or same-classed characters. Whitespace is skipped.

func (*Cursor) PrevWordBoundaryStart

func (c *Cursor) PrevWordBoundaryStart()

func (*Cursor) Right

func (c *Cursor) Right()

func (*Cursor) Up

func (c *Cursor) Up()

type Highlighter

type Highlighter struct {
	Buffer      Buffer
	Language    *Language
	Colorscheme *Colorscheme
	// contains filtered or unexported fields
}

A Highlighter can answer how to color any part of a provided Buffer. It does so by applying regular expressions over a region of the buffer.

func NewHighlighter

func NewHighlighter(buffer Buffer, lang *Language, colorscheme *Colorscheme) *Highlighter

func (*Highlighter) GetLineMatches

func (h *Highlighter) GetLineMatches(line int) []Match

func (*Highlighter) GetStyle

func (h *Highlighter) GetStyle(match Match) tcell.Style

func (*Highlighter) HasInvalidatedLines

func (h *Highlighter) HasInvalidatedLines(startLine, endLine int) bool

func (*Highlighter) InvalidateLines

func (h *Highlighter) InvalidateLines(startLine, endLine int)

func (*Highlighter) UpdateInvalidatedLines

func (h *Highlighter) UpdateInvalidatedLines(startLine, endLine int)

UpdateInvalidatedLines only updates the highlighting for lines that are invalidated between lines startLine and endLine, inclusively.

func (*Highlighter) UpdateLines

func (h *Highlighter) UpdateLines(startLine, endLine int)

UpdateLines forces the highlighting matches for lines between startLine to endLine, inclusively, to be updated. It is more efficient to mark lines as invalidated when changes occur and call UpdateInvalidatedLines(...).

type Language

type Language struct {
	Name      string
	Filetypes []string // .go, .c, etc.
	Rules     map[*RegexpRegion]Syntax
}

type Match

type Match struct {
	Col     int
	EndLine int // Inclusive
	EndCol  int // Inclusive
	Syntax  Syntax
}

type RegexpRegion

type RegexpRegion struct {
	Start    *regexp.Regexp
	End      *regexp.Regexp   // Should be "$" by default
	Skip     *regexp.Regexp   // Optional
	Error    *regexp.Regexp   // Optional
	Specials []*regexp.Regexp // Optional (nil or zero len)
}

type Region

type Region struct {
	Start *Cursor
	End   *Cursor
}

A Selection represents a region of the buffer to be selected for text editing purposes. It is asserted that the start position is less than the end position. The start and end are inclusive. If the EndCol of a Region is one more than the last column of a line, then it points to the line delimiter at the end of that line. It is understood that as a Region spans multiple lines, those connecting line-delimiters are included in the selection, as well.

func NewRegion

func NewRegion(in Buffer) Region

type RopeBuffer

type RopeBuffer struct {
	// contains filtered or unexported fields
}

func NewRopeBuffer

func NewRopeBuffer(contents []byte) *RopeBuffer

func (*RopeBuffer) Bytes

func (b *RopeBuffer) Bytes() []byte

func (*RopeBuffer) ClampLineCol

func (b *RopeBuffer) ClampLineCol(line, col int) (int, int)

ClampLineCol is a utility function to clamp any provided line and col to only possible values within the buffer, pointing to runes. It first clamps the line, then clamps the column. The column is clamped between zero and the last rune before the line delimiter.

func (*RopeBuffer) Count

func (b *RopeBuffer) Count(startLine, startCol, endLine, endCol int, sequence []byte) int

func (*RopeBuffer) EachRuneFromPos

func (b *RopeBuffer) EachRuneFromPos(pos int, f func(pos int, r rune) bool)

func (*RopeBuffer) Insert

func (b *RopeBuffer) Insert(line, col int, value []byte)

func (*RopeBuffer) Len

func (b *RopeBuffer) Len() int

func (*RopeBuffer) Line

func (b *RopeBuffer) Line(line int, delim bool) (bytes []byte, hasDelim bool)

func (*RopeBuffer) LineColToPos

func (b *RopeBuffer) LineColToPos(line, col int) int

func (*RopeBuffer) LineDelimiter

func (b *RopeBuffer) LineDelimiter() string

func (*RopeBuffer) LineHasDelimiter

func (b *RopeBuffer) LineHasDelimiter(line int) bool

func (*RopeBuffer) Lines

func (b *RopeBuffer) Lines() int

func (*RopeBuffer) PosToLineCol

func (b *RopeBuffer) PosToLineCol(pos int) (int, int)

PosToLineCol converts a byte offset (position) of the buffer's bytes, into a line and column. Unless you are working with the Bytes() function, this is unlikely to be useful to you. Position will be clamped.

func (*RopeBuffer) RegisterCursor

func (b *RopeBuffer) RegisterCursor(cursor *Cursor)

RegisterCursor adds the Cursor to a slice which the Buffer uses to update each Cursor based on changes that occur in the Buffer. Various functions are called on the Cursor depending upon where the edits occurred and how it should modify the Cursor's position. Unregister a Cursor before deleting it from memory, or forgetting it, with UnregisterPosition.

func (*RopeBuffer) Remove

func (b *RopeBuffer) Remove(startLine, startCol, endLine, endCol int)

func (*RopeBuffer) RuneAtPos

func (b *RopeBuffer) RuneAtPos(pos int) (r rune, size int)

func (*RopeBuffer) RunesInLine

func (b *RopeBuffer) RunesInLine(line int, delim bool) (runes int, hasDelim bool)

func (*RopeBuffer) SetLineDelimiter

func (b *RopeBuffer) SetLineDelimiter(delim string)

func (*RopeBuffer) Slice

func (b *RopeBuffer) Slice(startLine, startCol, endLine, endCol int) []byte

func (*RopeBuffer) UnregisterCursor

func (b *RopeBuffer) UnregisterCursor(cursor *Cursor)

UnregisterCursor will remove the cursor from the list of watched Cursors. It is mandatory that a Cursor be unregistered before being freed from memory, or otherwise being forgotten.

func (*RopeBuffer) WriteTo

func (b *RopeBuffer) WriteTo(w io.Writer) (int64, error)

type Syntax

type Syntax uint8
const (
	Default Syntax = iota
	Column         // Not necessarily a Syntax; useful for Colorscheming editor column
	Keyword
	String
	Special
	Type
	Number
	Builtin
	Comment
	DocComment
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL