lines

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2025 License: BSD-3-Clause Imports: 35 Imported by: 0

README

lines: manages lines of text

The lines package manages multi-line monospaced text with a given line width in runes, so that all text wrapping, editing, and navigation logic can be managed purely in text space, allowing rendering and GUI layout to be relatively fast. lines does not import core, and does not directly have any GUI functionality: it is focused purely on the text-level representation, using rich Text to represent styled text.

This package is suitable for text editing and terminal applications, among others. The text is encoded as runes along with a corresponding [rich.Text] markup representation with syntax highlighting, using either chroma or the parse package where available. A subsequent update will add support for the gopls system and LSP more generally. The markup is updated in a separate goroutine for efficiency.

Everything is protected by an overall sync.Mutex and is safe to concurrent access, and thus nothing is exported and all access is through protected accessor functions. In general, all unexported methods do NOT lock, and all exported methods do.

Views

Multiple different views onto the same underlying text content are supported, through the unexported view type. Each view can have a different width of characters in its formatting, which is the extent of formatting support for the view: it just manages line wrapping and maintains the total number of view lines (wrapped lines). The Lines object manages its own views directly, to ensure everything is updated when the content changes, with a unique ID (int) assigned to each view, which is passed with all view-related methods.

A widget will get its own view via the NewView method, and use SetWidth to update the view width accordingly (no problem to call even when no change in width). See the textcore Base for a base widget implementation.

With a view, there are two coordinate systems:

  • Original source line and char position, in Lines object and lines runes slices.
  • View position, where the line and char are for the wrapped lines and char offset within that view line.

The runes remain in 1-to-1 correspondence between these views, and can be translated using these methods:

  • PosToView maps a source position to a view position
  • PosFromView maps a view position to a source position.

Note that the view position is not quite a render location, due to the special behavior of tabs, which upset the basic "one rune, one display letter" principle.

Events

Three standard events are sent to listeners (always with no mutex lock on Lines):

  • events.Input (use OnInput to register a function to receive) is sent for every edit large or small.
  • events.Change (OnChange) is sent for major changes: new text, opening files, saving files, EditDone.
  • events.Close is sent when the Lines is closed (e.g., a user closes a file and is done editing it). The viewer should clear any pointers to the Lines at this point.

The listeners are attached to a specific view so that they are naturally removed when the view is deleted (it is not possible to delete listeners because function pointers are not comparable)

Widgets should listen to these to update rendering and send their own events. Other widgets etc should only listen to events on the Widgets, not on the underlying Lines object, in general.

Files

Full support for a file associated with the text lines is engaged by calling SetFilename. This will then cause it to check if the file has been modified prior to making any changes, and to save an autosave file (in a separate goroutine) after modifications, if SetAutosave is set. Otherwise, no such file-related behavior occurs.

An Editor dealing with file-backed Lines should set the FileModPromptFunc to a function that prompts the user for what they want to do if the file on disk has been modified at the point when an edit is made to the in-memory Lines. The textcore package has standard functions for this, and other file-specific GUI functions.

Syntax highlighting

Syntax highlighting depends on detecting the type of text represented. This happens automatically via SetFilename, but must also be triggered using ?? TODO.

Tabs

The markup rich.Text spans are organized so that each tab in the input occupies its own individual span. The rendering GUI is responsible for positioning these tabs and subsequent text at the correct location, with initial tabs at the start of a source line indenting by Settings.TabSize, but any subsequent tabs after that are positioned at a modulo 8 position. This is how the word wrapping layout is computed.

The presence of tabs means that you cannot directly map from a view Char index to a final rendered location on the screen: tabs will occupy more than one such char location and shift everyone else over correspondingly.

Editing

  • InsertText, DeleteText and ReplaceText are the core editing functions.
  • InsertTextRect and DeleteTextRect support insert and delete on rectangular region defined by upper left and lower right coordinates, instead of a contiguous region.

All editing functionality uses textpos types including Pos, Region, and Edit, which are based on the logical Line, Char coordinates of a rune in the original source text. For example, these are the indexes into lines[pos.Line][pos.Char]. In general, everything remains in these logical source coordinates, and the navigation functions (below) convert back and forth from these to the wrapped display layout, but this display layout is not really exposed.

Undo / Redo

Every edit generates a textpos.Edit record, which is recorded by the undo system (if it is turned on, via SetUndoOn -- on by default). The Undo and Redo methods thus undo and redo these edits. The NewUndoGroup method is important for grouping edits into groups that will then be done all together, so a bunch of small edits are not painful to undo / redo.

The Settings parameters has an EmacsUndo option which adds undos to the undo record, so you can get fully nested undo / redo functionality, as is standard in emacs.

Navigating (moving a cursor position)

The Move* functions provide support for moving a textpos.Pos position around the text:

  • MoveForward, MoveBackward and their *Word variants move by chars or words.
  • MoveDown and MoveUp take into account the wrapped display lines, and also take a column parameter that provides a target column to move along: in editors you may notice that it will try to maintain a target column when moving vertically, even if some of the lines are shorter.

Documentation

Index

Constants

View Source
const (
	// ReplaceMatchCase is used for MatchCase arg in ReplaceText method
	ReplaceMatchCase = true

	// ReplaceNoMatchCase is used for MatchCase arg in ReplaceText method
	ReplaceNoMatchCase = false
)

Variables

View Source
var UndoGroupDelay = 250 * time.Millisecond

UndoGroupDelay is the amount of time above which a new group is started, for grouping undo events

View Source
var UndoTrace = false

UndoTrace; set to true to get a report of undo actions

Functions

func ApplyOneDiff

func ApplyOneDiff(op difflib.OpCode, bedit *[]string, aorig []string, blmap []int)

ApplyOneDiff applies given diff operator to given "B" lines using original "A" lines and given b line map

func BytesToLineStrings

func BytesToLineStrings(txt []byte, addNewLn bool) []string

BytesToLineStrings returns []string lines from []byte input. If addNewLn is true, each string line has a \n appended at end.

func CountWordsLines

func CountWordsLines(reader io.Reader) (words, lines int)

CountWordsLines counts the number of words (aka Fields, space-separated strings) and lines given io.Reader input

func CountWordsLinesRegion

func CountWordsLinesRegion(src [][]rune, reg textpos.Region) (words, lines int)

CountWordsLinesRegion counts the number of words (aka Fields, space-separated strings) and lines in given region of source (lines = 1 + End.Line - Start.Line)

func DiffLinesUnified

func DiffLinesUnified(astr, bstr []string, context int, afile, adate, bfile, bdate string) []byte

DiffLinesUnified computes the diff between two string arrays (one string per line), returning a unified diff with given amount of context (default of 3 will be used if -1), with given file names and modification dates.

func DiffOpReverse

func DiffOpReverse(op difflib.OpCode) difflib.OpCode

func DiffOpString

func DiffOpString(op difflib.OpCode) string

func FileBytes

func FileBytes(fpath string) ([]byte, error)

FileBytes returns the bytes of given file.

func FileRegionBytes

func FileRegionBytes(fpath string, stLn, edLn int, preComments bool, lnBack int) []byte

FileRegionBytes returns the bytes of given file within given start / end lines, either of which might be 0 (in which case full file is returned). If preComments is true, it also automatically includes any comments that might exist just prior to the start line if stLn is > 0, going back a maximum of lnBack lines.

func KnownComments

func KnownComments(fpath string) (comLn, comSt, comEd string)

KnownComments returns the comment strings for supported file types, and returns the standard C-style comments otherwise.

func NextSpace

func NextSpace(txt []rune, pos int) int

func PreCommentStart

func PreCommentStart(lns [][]byte, stLn int, comLn, comSt, comEd string, lnBack int) int

PreCommentStart returns the starting line for comment line(s) that just precede the given stLn line number within the given lines of bytes, using the given line-level and block start / end comment chars. returns stLn if nothing found. Only looks back a total of lnBack lines.

func StringLinesToByteLines

func StringLinesToByteLines(str []string) [][]byte

StringLinesToByteLines returns [][]byte lines from []string lines

Types

type DiffSelectData

type DiffSelectData struct {
	// original text
	Orig []string

	// edits applied
	Edit []string

	// mapping of original line numbers (index) to edited line numbers,
	// accounting for the edits applied so far
	LineMap []int

	// Undos: stack of diffs applied
	Undos Diffs

	// undo records
	EditUndo [][]string

	// undo records for ALineMap
	LineMapUndo [][]int
}

DiffSelectData contains data for one set of text

func (*DiffSelectData) SaveUndo

func (ds *DiffSelectData) SaveUndo(op difflib.OpCode)

func (*DiffSelectData) SetStringLines

func (ds *DiffSelectData) SetStringLines(s []string)

SetStringLines sets the data from given lines of strings The Orig is set directly and Edit is cloned if the input will be modified during the processing, call slices.Clone first

func (*DiffSelectData) Undo

func (ds *DiffSelectData) Undo() bool

type DiffSelected

type DiffSelected struct {
	A DiffSelectData
	B DiffSelectData

	// Diffs are the diffs between A and B
	Diffs Diffs
}

DiffSelected supports the incremental application of selected diffs between two files (either A -> B or B <- A), with Undo

func NewDiffSelected

func NewDiffSelected(astr, bstr []string) *DiffSelected

func (*DiffSelected) AtoB

func (ds *DiffSelected) AtoB(idx int)

AtoB applies given diff index from A to B

func (*DiffSelected) BtoA

func (ds *DiffSelected) BtoA(idx int)

BtoA applies given diff index from B to A

func (*DiffSelected) SetStringLines

func (ds *DiffSelected) SetStringLines(astr, bstr []string)

SetStringLines sets the data from given lines of strings

type Diffs

type Diffs []difflib.OpCode

Diffs are raw differences between text, in terms of lines, reporting a sequence of operations that would convert one buffer (a) into the other buffer (b). Each operation is either an 'r' (replace), 'd' (delete), 'i' (insert) or 'e' (equal).

func DiffLines

func DiffLines(astr, bstr []string) Diffs

DiffLines computes the diff between two string arrays (one string per line), reporting a sequence of operations that would convert buffer a into buffer b. Each operation is either an 'r' (replace), 'd' (delete), 'i' (insert) or 'e' (equal). Everything is line-based (0, offset).

func (Diffs) DiffForLine

func (di Diffs) DiffForLine(line int) (int, difflib.OpCode)

func (Diffs) Reverse

func (di Diffs) Reverse() Diffs

Reverse returns the reverse-direction diffs, switching a vs. b

func (Diffs) String

func (di Diffs) String() string

String satisfies the Stringer interface

func (Diffs) ToPatch

func (dif Diffs) ToPatch(bstr []string) Patch

ToPatch creates a Patch list from given Diffs output from DiffLines and the b strings from which the needed lines of source are copied. ApplyPatch with this on the a strings will result in the b strings. The resulting Patch is independent of bstr slice.

type Lines

type Lines struct {

	// Settings are the options for how text editing and viewing works.
	Settings Settings

	// Highlighter does the syntax highlighting markup, and contains the
	// parameters thereof, such as the language and style.
	Highlighter highlighting.Highlighter

	// Autosave specifies whether an autosave copy of the file should
	// be automatically saved after changes are made.
	Autosave bool

	// FileModPromptFunc is called when a file has been modified in the filesystem
	// and it is about to be modified through an edit, in the fileModCheck function.
	// The prompt should determine whether the user wants to revert, overwrite, or
	// save current version as a different file. It must block until the user responds.
	FileModPromptFunc func()

	// Meta can be used to maintain misc metadata associated with the Lines text,
	// which allows the Lines object to be the primary data type for applications
	// dealing with text data, if there are just a few additional data elements needed.
	// Use standard Go camel-case key names, standards in [metadata].
	Meta metadata.Data

	// use Lock(), Unlock() directly for overall mutex on any content updates
	sync.Mutex
	// contains filtered or unexported fields
}

Lines manages multi-line monospaced text with a given line width in runes, so that all text wrapping, editing, and navigation logic can be managed purely in text space, allowing rendering and GUI layout to be relatively fast. This is suitable for text editing and terminal applications, among others. The text encoded as runes along with a corresponding rich.Text markup representation with syntax highlighting etc. The markup is updated in a separate goroutine for efficiency. Everything is protected by an overall sync.Mutex and is safe to concurrent access, and thus nothing is exported and all access is through protected accessor functions. In general, all unexported methods do NOT lock, and all exported methods do.

func NewLines

func NewLines() *Lines

NewLines returns a new empty Lines, with no views.

func NewLinesFromBytes

func NewLinesFromBytes(filename string, width int, src []byte) (*Lines, int)

NewLinesFromBytes returns a new Lines representation of given bytes of text, using given filename to determine the type of content that is represented in the bytes, based on the filename extension, and given initial display width. A width-specific view is created, with the unique view id returned: this id must be used for all subsequent view-specific calls. This uses all default styling settings.

func (*Lines) AddTag

func (ls *Lines) AddTag(ln, st, ed int, tag token.Tokens)

AddTag adds a new custom tag for given line, at given position.

func (*Lines) AddTagEdit

func (ls *Lines) AddTagEdit(tbe *textpos.Edit, tag token.Tokens)

AddTagEdit adds a new custom tag for given line, using Edit for location.

func (*Lines) AdjustRegion

func (ls *Lines) AdjustRegion(reg textpos.Region) textpos.Region

AdjustRegion adjusts given text region for any edits that have taken place since time stamp on region (using the Undo stack). If region was wholly within a deleted region, then RegionNil will be returned, otherwise it is clipped appropriately as function of deletes.

func (*Lines) AdjustedTags

func (ls *Lines) AdjustedTags(ln int) lexer.Line

AdjustedTags updates tag positions for edits, for given line and returns the new tags

func (*Lines) AdjustedTagsLine

func (ls *Lines) AdjustedTagsLine(tags lexer.Line, ln int) lexer.Line

AdjustedTagsLine updates tag positions for edits, for given list of tags, associated with given line of text.

func (*Lines) AppendTextMarkup

func (ls *Lines) AppendTextMarkup(text [][]rune, markup []rich.Text) *textpos.Edit

AppendTextMarkup appends new text to end of lines, using insert, returns edit, and uses supplied markup to render it, for preformatted output. Calls sendInput to send an Input event to views, so they update.

func (*Lines) AutoIndent

func (ls *Lines) AutoIndent(ln int) (tbe *textpos.Edit, indLev, chPos int)

AutoIndent indents given line to the level of the prior line, adjusted appropriately if the current line starts with one of the given un-indent strings, or the prior line ends with one of the given indent strings. Returns any edit that took place (could be nil), along with the auto-indented level and character position for the indent of the current line. Calls sendInput to send an Input event to views, so they update.

func (*Lines) AutoIndentRegion

func (ls *Lines) AutoIndentRegion(start, end int)

AutoIndentRegion does auto-indent over given region; end is *exclusive*. Calls sendInput to send an Input event to views, so they update.

func (*Lines) AutosaveCheck

func (ls *Lines) AutosaveCheck() bool

AutosaveCheck checks if an autosave file exists; logic for dealing with it is left to larger app; call this before opening a file.

func (*Lines) AutosaveDelete

func (ls *Lines) AutosaveDelete()

AutosaveDelete deletes any existing autosave file.

func (*Lines) AutosaveFilename

func (ls *Lines) AutosaveFilename() string

AutosaveFilename returns the autosave filename.

func (*Lines) BraceMatch

func (ls *Lines) BraceMatch(pos textpos.Pos) (textpos.Pos, bool)

BraceMatch finds the brace, bracket, or parens that is the partner of the one at the given position, if there is one of those at this position.

func (*Lines) BraceMatchRune

func (ls *Lines) BraceMatchRune(r rune, pos textpos.Pos) (textpos.Pos, bool)

BraceMatchRune finds the brace, bracket, or parens that is the partner of the given rune, starting at given position.

func (*Lines) ClearNotSaved

func (ls *Lines) ClearNotSaved()

ClearNotSaved sets Changed and NotSaved to false.

func (*Lines) Close

func (ls *Lines) Close()

Close should be called when done using the Lines. It first sends Close events to all views. An Editor widget will likely want to check IsNotSaved() and prompt the user to save or cancel first.

func (*Lines) CommentRegion

func (ls *Lines) CommentRegion(start, end int)

CommentRegion inserts comment marker on given lines; end is *exclusive*. Calls sendInput to send an Input event to views, so they update.

func (*Lines) ConfigKnown

func (ls *Lines) ConfigKnown() bool

ConfigKnown configures options based on the supported language info in parse. Returns true if supported.

func (*Lines) CountWordsLinesRegion

func (ls *Lines) CountWordsLinesRegion(reg textpos.Region) (words, lines int)

CountWordsLinesRegion returns the count of words and lines in given region.

func (*Lines) Defaults

func (ls *Lines) Defaults()

func (*Lines) DeleteLineColor

func (ls *Lines) DeleteLineColor(ln int)

DeleteLineColor deletes the line color at the given line. Passing a -1 clears all current line colors.

func (*Lines) DeleteText

func (ls *Lines) DeleteText(st, ed textpos.Pos) *textpos.Edit

DeleteText is the primary method for deleting text from the lines. It deletes region of text between start and end positions. Sets the timestamp on resulting Edit to now. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) DeleteTextRect

func (ls *Lines) DeleteTextRect(st, ed textpos.Pos) *textpos.Edit

DeleteTextRect deletes rectangular region of text between start, end defining the upper-left and lower-right corners of a rectangle. Fails if st.Char >= ed.Char. Sets the timestamp on resulting Edit to now. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) DeleteView

func (ls *Lines) DeleteView(vid int)

DeleteView deletes view for given unique view id. It is important to delete unused views to maintain efficient updating of existing views.

func (*Lines) Diffs

func (ls *Lines) Diffs(ob *Lines) Diffs

Diffs computes the diff between this lines and the other lines, reporting a sequence of operations that would convert this lines (a) into the other lines (b). Each operation is either an 'r' (replace), 'd' (delete), 'i' (insert) or 'e' (equal). Everything is line-based (0, offset).

func (*Lines) DiffsUnified

func (ls *Lines) DiffsUnified(ob *Lines, context int) []byte

DiffsUnified computes the diff between this lines and the other lines, returning a unified diff with given amount of context (default of 3 will be used if -1)

func (*Lines) EditDone

func (ls *Lines) EditDone()

EditDone is called externally (e.g., by Editor widget) when the user has indicated that editing is done, and the results are to be consumed.

func (*Lines) EmacsUndoSave

func (ls *Lines) EmacsUndoSave()

EmacsUndoSave is called by an editor at end of latest set of undo commands. If EmacsUndo mode is active, saves the current UndoStack to the regular Undo stack at the end, and moves undo to the very end; undo is a constant stream.

func (*Lines) EndPos

func (ls *Lines) EndPos() textpos.Pos

EndPos returns the ending position at end of lines.

func (*Lines) FileInfo

func (ls *Lines) FileInfo() *fileinfo.FileInfo

FileInfo returns the current fileinfo

func (*Lines) FileModCheck

func (ls *Lines) FileModCheck() bool

FileModCheck checks if the underlying file has been modified since last Stat (open, save); if haven't yet prompted, user is prompted to ensure that this is OK. It returns true if the file was modified.

func (*Lines) Filename

func (ls *Lines) Filename() string

Filename returns the current filename

func (*Lines) FontStyle

func (ls *Lines) FontStyle() *rich.Style

FontStyle returns the font style used for this lines.

func (*Lines) HiTagAtPos

func (ls *Lines) HiTagAtPos(pos textpos.Pos) (*lexer.Lex, int)

HiTagAtPos returns the highlighting (markup) lexical tag at given position using current Markup tags, and index, -- could be nil if none or out of range.

func (*Lines) HiTags

func (ls *Lines) HiTags(ln int) lexer.Line

HiTags returns the highlighting tags for given line, nil if invalid

func (*Lines) InComment

func (ls *Lines) InComment(pos textpos.Pos) bool

InComment returns true if the given text position is within a commented region.

func (*Lines) InLitString

func (ls *Lines) InLitString(pos textpos.Pos) bool

InLitString returns true if position is in a string literal.

func (*Lines) InTokenCode

func (ls *Lines) InTokenCode(pos textpos.Pos) bool

InTokenCode returns true if position is in a Keyword, Name, Operator, or Punctuation. This is useful for turning off spell checking in docs

func (*Lines) InTokenSubCat

func (ls *Lines) InTokenSubCat(pos textpos.Pos, subCat token.Tokens) bool

InTokenSubCat returns true if the given text position is marked with lexical type in given SubCat sub-category.

func (*Lines) IndentLine

func (ls *Lines) IndentLine(ln, ind int) *textpos.Edit

IndentLine indents line by given number of tab stops, using tabs or spaces, for given tab size (if using spaces). Either inserts or deletes to reach target. Returns edit record for any change. Calls sendInput to send an Input event to views, so they update.

func (*Lines) InsertText

func (ls *Lines) InsertText(st textpos.Pos, text []rune) *textpos.Edit

InsertText is the primary method for inserting text, at given starting position. Sets the timestamp on resulting Edit to now. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) InsertTextBytes

func (ls *Lines) InsertTextBytes(st textpos.Pos, text []byte) *textpos.Edit

InsertTextBytes is the primary method for inserting text, at given starting position. Sets the timestamp on resulting Edit to now. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) InsertTextLines

func (ls *Lines) InsertTextLines(st textpos.Pos, text [][]rune) *textpos.Edit

InsertTextLines is the primary method for inserting text, at given starting position. Sets the timestamp on resulting Edit to now. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) InsertTextRect

func (ls *Lines) InsertTextRect(tbe *textpos.Edit) *textpos.Edit

InsertTextRect inserts a rectangle of text defined in given Edit record, (e.g., from RegionRect or DeleteRect). Returns a copy of the Edit record with an updated timestamp. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) IsChanged

func (ls *Lines) IsChanged() bool

IsChanged reports whether any edits have been applied to text

func (*Lines) IsNotSaved

func (ls *Lines) IsNotSaved() bool

IsNotSaved returns true if buffer was changed (edited) since last Save.

func (*Lines) IsValidLine

func (ls *Lines) IsValidLine(ln int) bool

IsValidLine returns true if given line number is in range.

func (*Lines) IsValidPos

func (ls *Lines) IsValidPos(pos textpos.Pos) bool

IsValidPos returns an true if the position is valid.

func (*Lines) IsWordEnd

func (ls *Lines) IsWordEnd(pos textpos.Pos) bool

IsWordEnd returns true if the cursor is just past the last letter of a word.

func (*Lines) IsWordMiddle

func (ls *Lines) IsWordMiddle(pos textpos.Pos) bool

IsWordMiddle returns true if the cursor is anywhere inside a word, i.e. the character before the cursor and the one after the cursor are not classified as word break characters

func (*Lines) JoinParaLines

func (ls *Lines) JoinParaLines(startLine, endLine int)

JoinParaLines merges sequences of lines with hard returns forming paragraphs, separated by blank lines, into a single line per paragraph, within the given line regions; endLine is *inclusive*. Calls sendInput to send an Input event to views, so they update.

func (*Lines) LexObjPathString

func (ls *Lines) LexObjPathString(ln int, lx *lexer.Lex) string

LexObjPathString returns the string at given lex, and including prior lex-tagged regions that include sequences of PunctSepPeriod and NameTag which are used for object paths -- used for e.g., debugger to pull out variable expressions that can be evaluated.

func (*Lines) Line

func (ls *Lines) Line(ln int) []rune

Line returns a (copy of) specific line of runes.

func (*Lines) LineChar

func (ls *Lines) LineChar(ln, ch int) rune

LineChar returns rune at given line and character position. returns a 0 if character position is not valid

func (*Lines) LineColor

func (ls *Lines) LineColor(ln int) (image.Image, bool)

LineColor returns the line color for given line, and bool indicating if set.

func (*Lines) LineLen

func (ls *Lines) LineLen(ln int) int

LineLen returns the length of the given source line, in runes.

func (*Lines) LineLexDepth

func (ls *Lines) LineLexDepth(ln int) int

LineLexDepth returns the starting lexical depth in terms of brackets, parens, etc

func (*Lines) LinkAt

func (ls *Lines) LinkAt(pos textpos.Pos) *rich.Hyperlink

LinkAt returns a hyperlink at given source position, if one exists, nil otherwise. this is fast so no problem to call frequently.

func (ls *Lines) Links() map[int][]rich.Hyperlink

Links returns the full list of hyperlinks

func (*Lines) MarkupLines

func (ls *Lines) MarkupLines(st, ed int) bool

MarkupLines generates markup of given range of lines. end is *inclusive* line. Called after edits, under Lock(). returns true if all lines were marked up successfully.

func (*Lines) Metadata

func (ls *Lines) Metadata() *metadata.Data

func (*Lines) MoveBackward

func (ls *Lines) MoveBackward(pos textpos.Pos, steps int) textpos.Pos

MoveBackward moves given source position backward given number of rune steps.

func (*Lines) MoveBackwardWord

func (ls *Lines) MoveBackwardWord(pos textpos.Pos, steps int) textpos.Pos

MoveBackwardWord moves given source position backward given number of word steps.

func (*Lines) MoveDown

func (ls *Lines) MoveDown(vid int, pos textpos.Pos, steps, col int) textpos.Pos

MoveDown moves given source position down given number of display line steps, always attempting to use the given column position if the line is long enough.

func (*Lines) MoveForward

func (ls *Lines) MoveForward(pos textpos.Pos, steps int) textpos.Pos

MoveForward moves given source position forward given number of rune steps.

func (*Lines) MoveForwardWord

func (ls *Lines) MoveForwardWord(pos textpos.Pos, steps int) textpos.Pos

MoveForwardWord moves given source position forward given number of word steps.

func (*Lines) MoveLineEnd

func (ls *Lines) MoveLineEnd(vid int, pos textpos.Pos) textpos.Pos

MoveLineEnd moves given source position to end of view line.

func (*Lines) MoveLineStart

func (ls *Lines) MoveLineStart(vid int, pos textpos.Pos) textpos.Pos

MoveLineStart moves given source position to start of view line.

func (*Lines) MoveUp

func (ls *Lines) MoveUp(vid int, pos textpos.Pos, steps, col int) textpos.Pos

MoveUp moves given source position up given number of display line steps, always attempting to use the given column position if the line is long enough.

func (*Lines) NewUndoGroup

func (ls *Lines) NewUndoGroup()

NewUndoGroup increments the undo group counter for batchiung the subsequent actions.

func (*Lines) NewView

func (ls *Lines) NewView(width int) int

NewView makes a new view with given initial width, with a layout of the existing text at this width. The return value is a unique int handle that must be used for all subsequent calls that depend on the view.

func (ls *Lines) NextLink(pos textpos.Pos) (*rich.Hyperlink, int)

NextLink returns the next hyperlink after given source position, if one exists, and the line it is on. nil, -1 otherwise.

func (*Lines) NumLines

func (ls *Lines) NumLines() int

NumLines returns the number of lines.

func (*Lines) OnChange

func (ls *Lines) OnChange(vid int, fun func(e events.Event))

OnChange adds an event listener function to the view with given unique id, for the events.Change event. This is used for large-scale changes in the text, such as opening a new file or setting new text, or EditDone or Save.

func (*Lines) OnClose

func (ls *Lines) OnClose(vid int, fun func(e events.Event))

OnClose adds an event listener function to the view with given unique id, for the events.Close event. This event is sent in the Close function.

func (*Lines) OnInput

func (ls *Lines) OnInput(vid int, fun func(e events.Event))

OnInput adds an event listener function to the view with given unique id, for the events.Input event. This is sent after every fine-grained change in the text, and is used by text widgets to drive updates. It is blocked during batchUpdating.

func (*Lines) Open

func (ls *Lines) Open(filename string) error

Open loads the given file into the buffer.

func (*Lines) OpenFS

func (ls *Lines) OpenFS(fsys fs.FS, filename string) error

OpenFS loads the given file in the given filesystem into the buffer.

func (*Lines) ParseFileState

func (ls *Lines) ParseFileState() *parse.FileState

ParseFileState returns the parsed file state if this is a parse-supported known language, nil otherwise. Note: this API will change when LSP is implemented, and current use is likely to create race conditions / conflicts with markup.

func (*Lines) ParseState

func (ls *Lines) ParseState() (*parse.LanguageProperties, *parse.FileStates)

ParseState returns the current language properties and ParseState if it is a parse-supported known language, nil otherwise. Note: this API will change when LSP is implemented, and current use is likely to create race conditions / conflicts with markup.

func (*Lines) PatchFrom

func (ls *Lines) PatchFrom(ob *Lines, diffs Diffs) bool

PatchFrom patches (edits) using content from other, according to diff operations (e.g., as generated from Diffs).

func (*Lines) PosFromView

func (ls *Lines) PosFromView(vid int, pos textpos.Pos) textpos.Pos

PosFromView returns the original source position from given view position in terms of ViewLines and Char offset into that view line. If the Char position is beyond the end of the line, it returns the end of the given line.

func (*Lines) PosHistoryAt

func (ls *Lines) PosHistoryAt(idx int) (textpos.Pos, bool)

PosHistoryAt returns the position history at given index. returns false if not a valid index.

func (*Lines) PosHistoryLen

func (ls *Lines) PosHistoryLen() int

PosHistoryLen returns the length of the position history stack.

func (*Lines) PosHistorySave

func (ls *Lines) PosHistorySave(pos textpos.Pos) bool

PosHistorySave saves the cursor position in history stack of cursor positions. Tracks across views. Returns false if position was on same line as last one saved.

func (*Lines) PosToView

func (ls *Lines) PosToView(vid int, pos textpos.Pos) textpos.Pos

PosToView returns the view position in terms of ViewLines and Char offset into that view line for given source line, char position.

func (ls *Lines) PrevLink(pos textpos.Pos) (*rich.Hyperlink, int)

PrevLink returns the previous hyperlink before given source position, if one exists, and the line it is on. nil, -1 otherwise.

func (*Lines) ReMarkup

func (ls *Lines) ReMarkup()

ReMarkup starts a background task of redoing the markup

func (*Lines) Redo

func (ls *Lines) Redo() []*textpos.Edit

Redo redoes next group of items on the undo stack, and returns all the edits performed. Calls sendInput to send an Input event to views, so they update.

func (*Lines) Region

func (ls *Lines) Region(st, ed textpos.Pos) *textpos.Edit

Region returns a Edit representation of text between start and end positions. returns nil if not a valid region. sets the timestamp on the Edit to now.

func (*Lines) RegionFromView

func (ls *Lines) RegionFromView(vid int, reg textpos.Region) textpos.Region

RegionFromView converts the given region in view coordinates into source coordinates.

func (*Lines) RegionRect

func (ls *Lines) RegionRect(st, ed textpos.Pos) *textpos.Edit

RegionRect returns a Edit representation of text between start and end positions as a rectangle, returns nil if not a valid region. sets the timestamp on the Edit to now.

func (*Lines) RegionToView

func (ls *Lines) RegionToView(vid int, reg textpos.Region) textpos.Region

RegionToView converts the given region in source coordinates into view coordinates.

func (*Lines) RemoveTag

func (ls *Lines) RemoveTag(pos textpos.Pos, tag token.Tokens) (reg lexer.Lex, ok bool)

RemoveTag removes tag (optionally only given tag if non-zero) at given position if it exists. returns tag.

func (*Lines) ReplaceText

func (ls *Lines) ReplaceText(delSt, delEd, insPos textpos.Pos, insTxt string, matchCase bool) *textpos.Edit

ReplaceText does DeleteText for given region, and then InsertText at given position (typically same as delSt but not necessarily). if matchCase is true, then the lexer.MatchCase function is called to match the case (upper / lower) of the new inserted text to that of the text being replaced. returns the Edit for the inserted text. An Undo record is automatically saved depending on Undo.Off setting. Calls sendInput to send an Input event to views, so they update.

func (*Lines) Revert

func (ls *Lines) Revert() bool

Revert re-opens text from the current file, if the filename is set; returns false if not. It uses an optimized diff-based update to preserve existing formatting, making it very fast if not very different.

func (*Lines) SaveFile

func (ls *Lines) SaveFile(filename string) error

SaveFile writes current buffer to file, with no prompting, etc

func (*Lines) Search

func (ls *Lines) Search(find []byte, ignoreCase, lexItems bool) (int, []textpos.Match)

Search looks for a string (no regexp) within buffer, with given case-sensitivity, returning number of occurrences and specific match position list. Column positions are in runes.

func (*Lines) SearchRegexp

func (ls *Lines) SearchRegexp(re *regexp.Regexp) (int, []textpos.Match)

SearchRegexp looks for a string (regexp) within buffer, returning number of occurrences and specific match position list. Column positions are in runes.

func (*Lines) SendChange

func (ls *Lines) SendChange()

SendChange sends an [event.Change] to the views of this lines, causing them to update.

func (*Lines) SendInput

func (ls *Lines) SendInput()

SendInput sends an [event.Input] to the views of this lines, causing them to update.

func (*Lines) SetChanged

func (ls *Lines) SetChanged(changed bool)

SetChanged sets the changed flag to given value (e.g., when file saved)

func (*Lines) SetFileExt

func (ls *Lines) SetFileExt(ext string) *Lines

SetFileExt sets syntax highlighting and other parameters based on the given file extension (without the . prefix), for cases where an actual file with fileinfo.FileInfo is not available.

func (*Lines) SetFileInfo

func (ls *Lines) SetFileInfo(info *fileinfo.FileInfo) *Lines

SetFileInfo sets the syntax highlighting and other parameters based on the type of file specified by given fileinfo.FileInfo.

func (*Lines) SetFileModOK

func (ls *Lines) SetFileModOK(ok bool)

SetFileModOK sets the flag indicating that it is OK to edit even though the underlying file on disk has been edited.

func (*Lines) SetFilename

func (ls *Lines) SetFilename(fn string) *Lines

SetFilename sets the filename associated with the buffer and updates the code highlighting information accordingly.

func (*Lines) SetFontStyle

func (ls *Lines) SetFontStyle(fs *rich.Style) *Lines

SetFontStyle sets the font style to use in styling and rendering text. The Family of the font MUST be set to Monospace.

func (*Lines) SetHighlighting

func (ls *Lines) SetHighlighting(style highlighting.HighlightingName)

SetHighlighting sets the highlighting style.

func (*Lines) SetLanguage

func (ls *Lines) SetLanguage(ftyp fileinfo.Known) *Lines

SetFileType sets the syntax highlighting and other parameters based on the given fileinfo.Known file type

func (*Lines) SetLineColor

func (ls *Lines) SetLineColor(ln int, color image.Image)

SetLineColor sets the color to use for rendering a circle next to the line number at the given line.

func (*Lines) SetReadOnly

func (ls *Lines) SetReadOnly(readonly bool) *Lines

SetReadOnly sets whether the buffer is read-only.

func (*Lines) SetString

func (ls *Lines) SetString(txt string) *Lines

SetString sets the text to the given string.

func (*Lines) SetTags

func (ls *Lines) SetTags(ln int, tags lexer.Line)

SetTags tags for given line.

func (*Lines) SetText

func (ls *Lines) SetText(text []byte) *Lines

SetText sets the text to the given bytes, and does full markup update and sends a Change event. Pass nil to initialize an empty lines.

func (*Lines) SetTextLines

func (ls *Lines) SetTextLines(lns [][]byte)

SetTextLines sets the source lines from given lines of bytes.

func (*Lines) SetUndoOn

func (ls *Lines) SetUndoOn(on bool)

SetUndoOn turns on or off the recording of undo records for every edit.

func (*Lines) SetWidth

func (ls *Lines) SetWidth(vid int, wd int) bool

SetWidth sets the width for line wrapping, for given view id. If the width is different than current, the layout is updated, and a true is returned, else false.

func (*Lines) SpacesToTabs

func (ls *Lines) SpacesToTabs(start, end int)

SpacesToTabs replaces tabs with spaces over given region; end is *exclusive* Calls sendInput to send an Input event to views, so they update.

func (*Lines) StartDelayedReMarkup

func (ls *Lines) StartDelayedReMarkup()

StartDelayedReMarkup starts a timer for doing markup after an interval.

func (*Lines) Stat

func (ls *Lines) Stat() error

Stat gets info about the file, including the highlighting language.

func (*Lines) StopDelayedReMarkup

func (ls *Lines) StopDelayedReMarkup()

StopDelayedReMarkup stops the timer for doing markup after an interval.

func (*Lines) String

func (ls *Lines) String() string

String returns the current text as a string. It does NOT call EditDone or send a Change event: that should happen prior or separately from this call.

func (*Lines) Strings

func (ls *Lines) Strings(addNewLine bool) []string

strings returns the current text as []string array. If addNewLine is true, each string line has a \n appended at end.

func (*Lines) TabsToSpaces

func (ls *Lines) TabsToSpaces(start, end int)

TabsToSpaces replaces tabs with spaces over given region; end is *exclusive*. Calls sendInput to send an Input event to views, so they update.

func (*Lines) Text

func (ls *Lines) Text() []byte

Text returns the current text lines as a slice of bytes, with an additional line feed at the end, per POSIX standards. It does NOT call EditDone or send a Change event: that should happen prior or separately from this call.

func (*Lines) TransposeChar

func (ls *Lines) TransposeChar(vid int, pos textpos.Pos) bool

TransposeChar swaps the character at the cursor with the one before it.

func (*Lines) Undo

func (ls *Lines) Undo() []*textpos.Edit

Undo undoes next group of items on the undo stack, and returns all the edits performed. Calls sendInput to send an Input event to views, so they update.

func (*Lines) UndoReset

func (ls *Lines) UndoReset()

UndoReset resets all current undo records.

func (*Lines) ValidPos

func (ls *Lines) ValidPos(pos textpos.Pos) textpos.Pos

ValidPos returns a position based on given pos that is valid.

func (*Lines) ViewLineLen

func (ls *Lines) ViewLineLen(vid int, vln int) int

ViewLineLen returns the length in chars (runes) of the given view line.

func (*Lines) ViewLineRegion

func (ls *Lines) ViewLineRegion(vid int, vln int) textpos.Region

ViewLineRegion returns the region in view coordinates of the given view line.

func (*Lines) ViewLineRegionNoLock

func (ls *Lines) ViewLineRegionNoLock(vid int, vln int) textpos.Region

ViewLineRegionNoLock returns the region in view coordinates of the given view line, for case where Lines is already locked.

func (*Lines) ViewLines

func (ls *Lines) ViewLines(vid int) int

ViewLines returns the total number of line-wrapped view lines, for given view id.

func (*Lines) ViewMarkupLine

func (ls *Lines) ViewMarkupLine(vid, line int) rich.Text

ViewMarkupLine returns the markup rich.Text line for given view and view line number. This must be called under the mutex Lock! It is the api for rendering the lines.

func (*Lines) Width

func (ls *Lines) Width(vid int) int

Width returns the width for line wrapping for given view id.

func (*Lines) WordAt

func (ls *Lines) WordAt(pos textpos.Pos) textpos.Region

WordAt returns a Region for a word starting at given position. If the current position is a word break then go to next break after the first non-break.

func (*Lines) WordBefore

func (ls *Lines) WordBefore(pos textpos.Pos) *textpos.Edit

WordBefore returns the word before the given source position. uses IsWordBreak to determine the bounds of the word

type Patch

type Patch []*PatchRec

Patch is a collection of patch records needed to turn original a buffer into b

func (Patch) Apply

func (pt Patch) Apply(astr []string) []string

Apply applies given Patch to given file as list of strings this does no checking except range checking so it won't crash so if input string is not appropriate for given Patch, results may be nonsensical.

func (Patch) NumBlines

func (pt Patch) NumBlines() int

NumBlines returns the total number of Blines source code in the patch

type PatchRec

type PatchRec struct {

	// diff operation: 'r', 'd', 'i', 'e'
	Op difflib.OpCode

	// lines from B buffer needed for 'r' and 'i' operations
	Blines []string
}

PatchRec is a self-contained record of a DiffLines result that contains the source lines of the b buffer needed to patch a into b

type Settings

type Settings struct {
	text.EditorSettings

	// CommentLine are character(s) that start a single-line comment;
	// if empty then multi-line comment syntax will be used.
	CommentLine string

	// CommentStart are character(s) that start a multi-line comment
	// or one that requires both start and end.
	CommentStart string

	// Commentend are character(s) that end a multi-line comment
	// or one that requires both start and end.
	CommentEnd string
}

Settings contains settings for editing text lines.

func (*Settings) CommentStrings

func (tb *Settings) CommentStrings() (comst, comed string)

CommentStrings returns the comment start and end strings, using line-based CommentLn first if set and falling back on multi-line / general purpose start / end syntax.

func (*Settings) ConfigKnown

func (tb *Settings) ConfigKnown(sup fileinfo.Known) bool

ConfigKnown configures options based on the supported language info in parse. Returns true if supported.

func (*Settings) IndentChar

func (tb *Settings) IndentChar() indent.Character

IndentChar returns the indent character based on SpaceIndent option

type Undo

type Undo struct {

	// if true, saving and using undos is turned off (e.g., inactive buffers)
	Off bool

	// undo stack of edits
	Stack []*textpos.Edit

	// undo stack of *undo* edits -- added to whenever an Undo is done -- for emacs-style undo
	UndoStack []*textpos.Edit

	// undo position in stack
	Pos int

	// group counter
	Group int

	// mutex protecting all updates
	Mu sync.Mutex `json:"-" xml:"-"`
}

Undo is the textview.Buf undo manager

func (*Undo) AdjustRegion

func (un *Undo) AdjustRegion(reg textpos.Region) textpos.Region

AdjustRegion adjusts given text region for any edits that have taken place since time stamp on region (using the Undo stack). If region was wholly within a deleted region, then RegionNil will be returned -- otherwise it is clipped appropriately as function of deletes.

func (*Undo) NewGroup

func (un *Undo) NewGroup()

NewGroup increments the Group counter so subsequent undos will be grouped separately

func (*Undo) RedoNext

func (un *Undo) RedoNext() *textpos.Edit

RedoNext returns the current item on Stack for Redo, and increments the position returns nil if at end of stack.

func (*Undo) RedoNextIfGroup

func (un *Undo) RedoNextIfGroup(gp int) *textpos.Edit

RedoNextIfGroup returns the current item on Stack for Redo if it is same group and increments the position. returns nil if at end of stack.

func (*Undo) Reset

func (un *Undo) Reset()

Reset clears all undo records

func (*Undo) Save

func (un *Undo) Save(tbe *textpos.Edit)

Save saves given edit to undo stack, with current group marker unless timer interval exceeds UndoGroupDelay since last item.

func (*Undo) SaveUndo

func (un *Undo) SaveUndo(tbe *textpos.Edit)

SaveUndo saves given edit to UndoStack (stack of undoes that have have undone..) for emacs mode.

func (*Undo) UndoPop

func (un *Undo) UndoPop() *textpos.Edit

UndoPop pops the top item off of the stack for use in Undo. returns nil if none.

func (*Undo) UndoPopIfGroup

func (un *Undo) UndoPopIfGroup(gp int) *textpos.Edit

UndoPopIfGroup pops the top item off of the stack if it is the same as given group

func (*Undo) UndoStackSave

func (un *Undo) UndoStackSave()

UndoStackSave if EmacsUndo mode is active, saves the UndoStack to the regular Undo stack, at the end, and moves undo to the very end. Undo is a constant stream..

Jump to

Keyboard shortcuts

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