edit

package
v0.0.0-...-2842cdc Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2018 License: ISC Imports: 14 Imported by: 0

Documentation

Overview

Package edit provides a language and functions for editing text. This package is heavily inspired by the text editor Sam. In fact, the edit language of this package is a dialect of the edit language of Sam. For background, see the sam(1) manual page: http://swtch.com/plan9port/man/man1/sam.html.

Text and Addresses

The Text interface provides methods to operate on a read-only text. The text is accessed using Spans, defined by an inclusive start point and an exclusive end point. The units of a Span are unspecified, but are defined by a Text implementation, by way of its Size and ReadRune method.

Addresses provide a high-level language for identifying Spans of a Text. They can be constructed in two different ways. The first way is by parsing a string in T's Address language. The Address language is parsed by the Addr function. Here's an example:

// This Address identifies the Span from 3 runes past the end of line 1
// until the end of 8th line following the next occurrence of "the".
addr, err := Addr(strings.NewReader("1+#3,/the/+8"))

See the documentation of the Addr function for more details.

The second way to construct an Address is by using functions and methods. This is intended for creating Addresses programmatically or in source code. Unlike the Addr function, which reports errors at run-time, errors that occur while creating Addresses using these functions and methods are reported by the compiler at compile-time. Here's an example; it creates the same address as above:

addr := Line(1).Plus(Rune(3)).To(Regexp("the").Plus(Line(8)))

Once created, whether by the Address language or using functions and methodts, Addresses can be evaluated on a Text using their Where method. The Where method returns the Span of the Text identified by the Address.

Editor and Edits

The Editor interface provides methods to operate on a read/write text. A text is modified with the Change, Apply, Undo, and Redo methods of the Editor. The Change method stages a change to a specified Span of the Text. It does not modify the Text itself. The Apply method modifies the Text by applying all staged changes in sequence. Undo and Redo, undo and redo batches of changes made with Apply.

Edits provide a high-level language for modifying a Text. Like Addresses, they can be constructed in two different ways. The first way is by parsing a string in T's Edit language. The Edit language goes hand-in-hand with the Address language. In fact, the Address language is a subset of the Edit language. The Edit language is parsed by the Ed function. Here's an example:

// This Edit changes the Span from 3 runes past the end of line 1
// until the end of 8th line following the next occurrence of "the",
// to have the text "new text".
e, err := Ed(strings.NewReader("1+#3,/the/+8 c/new text/"))

See the documentation of the Ed function for more details.

The second way to construct an Edit is by using functions. This is intended for creating Edits programmatically or in source code. Unlike the Ed function, which reports errors at run-time, errors that occur while creating Edits using these functions are reported by the compiler at compile-time. Here's example; it makes the same modification as above:

addr := Line(1).Plus(Rune(3)).To(Regexp("the").Plus(Line(8)))
edit := Change(addr, "new text")

Once created, whether by the Edit language or using functions, Edits can be applied to an Editor using their Do method. The Do method can either modify Text, change the Editor's state based on the contents of the Text, print text from the Text or information about the Text to an io.Writer, or a combination of the above of the above. It all depends on the Edit being performed.

Buffer

The Buffer type provides an implementation of the Editor interface. A Buffer is an infinite-capacity, disk-backed, buffers of runes.

Index

Examples

Constants

View Source
const DefaultShell = "/bin/sh"

DefaultShell is the default shell which is used to execute commands if the SHELL environment variable is not set.

Variables

View Source
var (
	// ErrInvalidArgument indicates an invalid, out-of-range Span.
	ErrInvalidArgument = errors.New("invalid argument")

	// ErrOutOfSequence indicates that a change modifies text
	// overlapping or preceeding the previous, staged change.
	ErrOutOfSequence = errors.New("out of sequence")
)
View Source
var ErrNoMatch = errors.New("no match")

ErrNoMatch is returned when a regular expression fails to match.

Functions

func Escape

func Escape(str string, esc ...rune) string

Escape returns the string, with \ inserted before all occurrences of \, raw newlines, and runes in esc.

func Unescape

func Unescape(str string) string

Unescape returns the string, with all occurrences of \n replaced by a raw newline, and all occurrences of \ followed by any other rune with the rune.

If the last rune is \ that is not preceded by a \, it remains unchanged as a trailing \.

Types

type AdditiveAddress

type AdditiveAddress interface {
	Address
	Plus(SimpleAddress) AdditiveAddress
	Minus(SimpleAddress) AdditiveAddress
	// contains filtered or unexported methods
}

A AdditiveAddress identifies a Span within a Text. AdditiveAddress can be composed using the methods of the Address interface, and the Plus and Minus methods to form more-complex Addresses.

type Address

type Address interface {
	// String returns the string representation of the Address.
	// The returned string will result in an equivalent Address
	// when parsed with Addr().
	String() string

	// To returns an Address identifying the string
	// from the start of the receiver to the end of the argument.
	To(AdditiveAddress) Address

	// Then returns an Address like To,
	// but with dot set to the receiver Address
	// during evaluation of the argument.
	Then(AdditiveAddress) Address

	// To returns an Address identifying the string
	// between the receiver Address and the argument Address.
	// The start of the string is the minimum
	// of the start of the receiver and the start of the argument.
	// The end of the string is the maximum
	// of the end of the receiver and the end of the argument.
	Between(AdditiveAddress) Address

	// Where returns the Span of the Address evaluated on a Text.
	Where(Text) (Span, error)
}

An Address identifies a Span within a Text.

Example
buf := NewBuffer()
defer buf.Close()
if err := Append(All, "Hello, 世界!").Do(buf, ioutil.Discard); err != nil {
	panic(err)
}

// The Addr function parses an address from a []rune.
// It is intended to be called with runes input by a UI.
// This wrapper makes it a bit more friendly for our example.
parseAddr := func(s string) Address {
	a, err := Addr(strings.NewReader(s))
	if err != nil {
		panic(err)
	}
	return a
}

// Create various addresses.
// Addresses can be created in two ways:
// 1) With the T address language, parsing them with Addr.
// 2) With functions.
addrs := []Address{
	// 0,$ is how T specifies the address of the entire buffer.
	parseAddr("0,$"),
	// , is short-hand for 0,$
	parseAddr(","),
	// The address can also be constructed directly.
	Rune(0).To(End),
	// All is a convenient variable for the address of the entire buffer.
	All,

	// Regular expressions.
	parseAddr("/Hello/"),
	Regexp("Hello"),
	// A regular expression, searching in reverse.
	End.Minus(Regexp("Hello")),

	// Line addresses.
	parseAddr("1"),
	Line(1),

	// Range addresses.
	parseAddr("#1,#5"),
	Rune(1).To(Rune(5)),

	// Addresses relative to other addresses.
	parseAddr("#0+/l/,#5"),
	Rune(0).Plus(Regexp("l")).To(Rune(5)),
	parseAddr("$-/l/,#5"),
	End.Minus(Regexp("l")).To(Rune(5)),
}

// Print the contents of the editor at each address to os.Stdout.
for _, a := range addrs {
	s, err := a.Where(buf)
	if err != nil {
		panic(err)
	}
	if _, err := io.Copy(os.Stdout, buf.Reader(s)); err != nil {
		panic(err)
	}
	os.Stdout.WriteString("\n")
}
Output:

Hello, 世界!
Hello, 世界!
Hello, 世界!
Hello, 世界!
Hello
Hello
Hello
Hello, 世界!
Hello, 世界!
ello
ello
llo
llo
lo
lo

func Addr

func Addr(rs io.RuneScanner) (Address, error)

Addr parses and returns an address.

The address syntax for address a is:

a: {a} , {aa} | {a} ; {aa} | {aa}
aa: {aa} + {sa} | {aa} - {sa} | {aa} {sa} | {!} {sa}
sa: $ | . | 'r | #{n} | n | / regexp {/}
n: [0-9]+
r: any non-space rune
regexp: any valid re1 regular expression

All operators are left-associative.

Production sa describes a simple addresse:

$ is the empty string at the end of the buffer.
. is the current address of the editor, called dot.
'{r} is the address of the non-space rune, r. If r is missing, . is used.
#{n} is the empty string after rune number n. If n is missing then 1 is used.
n is the nth line in the buffer. 0 is the string before the first full line.
'/' regexp {'/'} is the first match of the regular expression.
	The regexp uses the syntax of the standard library regexp package,
	except that \, raw newlines, and / must be escaped with \.
	The regexp is wrapped in (?m:<regexp>), making it multi-line by default.

Simple addresses may be prefixed with !. Such an address is clamped to the beginning or end of the text whenever it would return an out of range error. For example,

.+25 is the 25th line after dot, or an error if there are fewer than 25 lines after dot.
.+!25 is the 25th line after dot, or $ if there are fewer than 25 lines after dot.

Production aa describes an additive address:

{aa} '+' {sa} is the second address evaluated from the end of the first.
	If the first address is missing, . is used.
	If the second address is missing, 1 is used.
{aa} '-' {sa} is the second address evaluated in reverse from the start of the first.
	If the first address is missing, . is used.
	If the second address is missing, 1 is used.
If two addresses of the form aa sa are present and distinct
then a '+' is inserted, as in aa + as.

Production a describes a range address:

{a} ',' {aa} is the string from the start of the first address to the end of the second.
	If the first address is missing, 0 is used.
	If the second address is missing, $ is used.
{a} ';' {aa} is like the previous,
	but with dot set to the receiver Address
	during evaluation of the argument.
	If the first address is missing, 0 is used.
	If the second address is missing, $ is used.
{a} '~' {aa} is the string between the first address and the second.
	The start of the string is the minimum
	of the start of the first and the start of the second.
	The end of the string is the maximum
	of the end of the first and the end of the second.
	If the first address is missing, 0 is used.
	If the second address is missing, $ is used.

Addresses are terminated by a newline, end of input, or end of the address. For example:

1,5
-1
	Is terminated at the newline precceding -.
	The newline is not consumed.

1,5-6
	Is terminated at 6 at the end of the input.

1,5dabc
	Is terminated at 5, the end of the address.

type Buffer

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

A Buffer implements the Editor interface, editing an unbounded sequence of runes.

func NewBuffer

func NewBuffer() *Buffer

NewBuffer returns a new, empty Buffer.

func (*Buffer) Apply

func (buf *Buffer) Apply() error

func (*Buffer) Change

func (buf *Buffer) Change(s Span, r io.Reader) (n int64, err error)

func (*Buffer) Close

func (buf *Buffer) Close() error

Close closes the Buffer and releases its resources.

func (*Buffer) Mark

func (buf *Buffer) Mark(m rune) Span

func (*Buffer) Reader

func (buf *Buffer) Reader(s Span) io.Reader

func (*Buffer) Redo

func (buf *Buffer) Redo() error

func (*Buffer) RuneReader

func (buf *Buffer) RuneReader(s Span) io.RuneReader

RuneReader implements the Runes method of the Text interface.

Each non-error ReadRune operation returns a width of 1.

func (*Buffer) SetMark

func (buf *Buffer) SetMark(m rune, s Span) error

func (*Buffer) Size

func (buf *Buffer) Size() int64

Size implements the Size method of the Text interface.

It returns the number of Runes in the Buffer.

func (*Buffer) Undo

func (buf *Buffer) Undo() error

type Edit

type Edit interface {
	// String returns the string representation of the edit.
	// The returned string will result in an equivalent edit
	// when parsed with Ed().
	String() string

	// Do performs the Edit on an Editor.
	// Anything printed by the Edit is written to the Writer.
	Do(Editor, io.Writer) error
}

An Edit is an operation that can be made on a Buffer by an Editor.

Example
buf := NewBuffer()
defer buf.Close()
if err := Append(All, "Hello, World!\n").Do(buf, ioutil.Discard); err != nil {
	panic(err)
}

// The Ed function parses an Edit from a []rune.
// It is intended to be called with runes input by a UI.
// This wrapper makes it a bit more friendly for our example.
parseEd := func(s string) Edit {
	e, err := Ed(strings.NewReader(s))
	if err != nil {
		panic(err)
	}
	return e
}

// Create various Edits.
// Edits can be created in two ways:
// 1) With the T command language, parsing them with Ed.
// 2) With functions.
edits := []Edit{
	// p prints the contents at the address preceeding it.
	parseEd("0,$p"),
	// Here is the same Edit built with a funciton.
	Print(All),
	// This prints a different address.
	Print(Regexp(",").Plus(Rune(1)).To(End)),

	// c changes the buffer at a given address preceeding it.
	// After this change, the buffer will contain: "Hello, 世界!\n"
	parseEd("/World/c/世界"),
	parseEd(",p"),

	// Or you can do it with functions.
	// After this change, the buffer will contain: "Hello, World!\n" again.
	Change(Regexp("世界"), "World"),
	Print(All),

	// There is infinite Undo…
	parseEd("u"),
	Undo(1),

	// … and infinite Redo.
	parseEd("r"),
	Redo(1),
	Print(All),

	// You can also edit with regexp substitution.
	Change(All, "...===...\n"),
	Sub(All, "(=+)", "---${1}---"),
	Print(All),
	parseEd(`,s/[.]/_/g`),
	Print(All),

	// And various other things…
}

// Perform the Edits.
// Printed output is written to os.Stdout.
for _, e := range edits {
	if err := e.Do(buf, os.Stdout); err != nil {
		panic(err)
	}
}
Output:

Hello, World!
Hello, World!
World!
Hello, 世界!
Hello, World!
Hello, World!
...---===---...
___---===---___

func Append

func Append(a Address, str string) Edit

Append returns an Edit that appends str after the string at a, and sets dot to the appended runes.

func Block

func Block(a Address, e ...Edit) Edit

Block returns an Edit that performs a group of Edits insequence. Dot is set to the Address a before performing each Edit in the group. After the sequence, dot is set to the modified Address a.

func Change

func Change(a Address, str string) Edit

Change returns an Edit that changes the string at a to str, and sets dot to the changed runes.

func Copy

func Copy(src, dst Address) Edit

Copy returns an Edit that copies runes from src to after dst and sets dot to the copied runes.

func Delete

func Delete(a Address) Edit

Delete returns an Edit that deletes the string at a, and sets dot to the empty string that was deleted.

func Ed

func Ed(rs io.RuneScanner) (Edit, error)

Ed parses and returns an Edit.

Edits are terminated by a newline, end of input, or the end of the edit. For example:

1,5
d
	Is terminated at the newline precceding d.
	The newline is not consumed.

1,5a/xyz
	Is terminated at z at the end of the input.

1,5dabc
	Is terminated at d, the end of the edit.

In the following, text surrounded by / represents delimited text. The delimiter can be any character, it need not be /. Trailing delimiters may be elided, but the opening delimiter must be present. In delimited text, \ is an escape; the following character is interpreted literally, except \n which represents a literal newline. Items in brackets, [], are optional.

The edit language is:

addr
	Sets the address of Dot.
[addr] a/text/
or
[addr] a
lines of text
.
	Appends text after the address.
	In the text, all \, raw newlines, and / must be escaped with \.
	If an address is not supplied, dot is used.
	Dot is set to the address.
[addr] c
[addr] i
	Just like a, but c changes the addressed text
	and i inserts before the addressed text.
	Dot is set to the address.
[addr] d
	Deletes the addressed text.
	If an address is not supplied, dot is used.
	Dot is set to the address.
[addr] t [addr]
[addr] m [addr]
	Copies or moves runes from the first address to after the second.
	Dot is set to the newly inserted or moved runes.
[addr] s[n]/regexp/text/[g]
	Substitute substitutes matches of regexp within the address.

	The regexp uses the syntax of the standard library regexp package.
	The regexp is wrapped in (?m:<regexp>), making it multi-line by default.
	The replacement text uses the systax of Regexp.Expand method,
	described here: https://golang.org/pkg/regexp/#Regexp.Expand.,
	The runes \, raw newlines, and / must be escaped with \
	in both the regexp and replacement text.
	For example, ,s/\\s+/\\/g replaces runs of whitespace with \.

	A number n after s indicates we substitute the Nth match in the
	address range. If n == 0 set n = 1.
	If the delimiter after the text is followed by the letter g
	then all matches in the address range are substituted.
	If a number n and the letter g are both present then the Nth match
	and all subsequent matches in the address range are substituted.

	If an address is not supplied, dot is used.
	Dot is set to the modified address.

[addr] x/regexp/edit
	Executes an edit for each match of regexp within the Address.
	The edit is executed with dot set to the match.

	The regexp uses the same syntax as described for substitute.
	However, if the regexp is empty, ".*\n" is used.

	If an address is not supplied, dot is used.
	After all matches, dot is set to the last match;
	if there were no matches then it is set to the Address.

[addr] k [name]
	Sets the named mark to the address.
	If an address is not supplied, dot is used.
	The name is any non-whitespace rune.
	If name is not supplied or is the rune . then dot is set.
	Regardless of which mark is set,
	dot is also set to the address.
[addr] p
	Returns the runes identified by the address.
	If an address is not supplied, dot is used.
	Dot is set to the address.
[addr] =[#]
	Without '#' returns the line offset(s) of the address.
	With '#' returns the rune offsets of the address.
	If an address is not supplied, dot is used.
	Dot is set to the address.
[addr] | cmd
[addr] < cmd
[addr] > cmd
	| pipes the addressed string to standard input
	of a shell command and overwrites the address
	by the standard output of the command.
	< and > are like |,
	but < only overwrites with the command's standard output,
	and > only pipes to the command's standard input.
	If an address is not supplied, dot is used.
	Dot is set to the address.

 	The command is passed as the argument of -c
	to the shell in the SHELL environment variable.
	If SHELL is unset, the value of DefaultShell is used.

	Parsing of cmd is termiated by
	either a newline or the end of input.
	Within cmd, \n is interpreted as a newline literal.
u[n]
	Undoes the n most recent changes
	made to the buffer by any Editor.
	If n is not specified, it defaults to 1.
	Dot is set to the address covering
	the last undone change.
r[n]
	Redoes the n most recent changes
	undone by any Editor.
	If n is not specified, it defaults to 1.
	Dot is set to the address covering
	the last redone change.

[addr] {
	edit
	…
}
	Performs a sequence of sub-edits.
	Dot is set to the given address before each sub-edit.
	It is an error if the sub-edits make changes that are not in ascending order.
	The sub-edits do not see the modifications made by previous sub-edits.
	Each sees the text in the original state, before any changes are made.

	If an address is not supplied, dot is used.
	After the sequence of edits, dot is set to the given address.

	If EOF is encountered before }, the block is closed at EOF.
	An empty group performs no edits and simply sets dot.

func Insert

func Insert(a Address, str string) Edit

Insert returns an Edit that inserts str before the string at a, and sets dot to the inserted runes.

func Loop

func Loop(a Address, re string, body Edit) Edit

Loop returns an Edit that performs another Edit, body, for each match of a regular expression within an Address. The body edit is executed with dot set to the corresponding match. After all matches, dot is set to the last match; if there were no matches then it is set to the Address.

If the regexp is empty, ".*\n" is used.

func Move

func Move(src, dst Address) Edit

Move returns an Edit that moves runes from src to after dst and sets dot to the moved runes. It is an error if the end of dst is within src.

func Pipe

func Pipe(a Address, cmd string) Edit

Pipe returns an Edit that sends the string at an address to the standard input of a command and replaces the string with the command's standard output. If the command outputs to standard error, that is written to the io.Writer supplied to Editor.Do.

The command is executed through the shell as an argument to "-c". The shell is either the value of the SHELL environment variable or DefaultShell if SHELL is unset.

func PipeFrom

func PipeFrom(a Address, cmd string) Edit

PipeFrom returns an Edit like Pipe, but the standard input of the command is connected to an empty reader.

func PipeTo

func PipeTo(a Address, cmd string) Edit

PipeTo returns an Edit like Pipe, but the standard output of the command is written to the writer, and does not overwrite the address a.

func Print

func Print(a Address) Edit

Print returns an Edit that prints the string at a to an io.Writer and sets dot to the printed string.

func Redo

func Redo(n int) Edit

Redo returns an Edit that redoes the n most recent changes undone by an Undo edit, and sets dot to the address covering the last redone change. If n ≤ 0 then 1 change is redone.

func Set

func Set(a Address, m rune) Edit

Set returns an Edit that sets the dot or mark m to a. The mark m can by any rune. If the mark is . or whitespace then dot is set to a.

func Sub

func Sub(a Address, re, with string) Edit

Sub returns a Substitute Edit that substitutes the first occurrence of the regular expression within a and sets dot to the modified Address a.

func SubGlobal

func SubGlobal(a Address, re, with string) Edit

SubGlobal returns a Substitute Edit that substitutes the all occurrences of the regular expression within a and sets dot to the modified Address a.

func Undo

func Undo(n int) Edit

Undo returns an Edit that undoes the n most recent changes made to the buffer, and sets dot to the address covering the last undone change. If n ≤ 0 then 1 change is undone.

func Where

func Where(a Address) Edit

Where returns an Edit that prints the rune location of a to an io.Writer and sets dot to the a.

func WhereLine

func WhereLine(a Address) Edit

WhereLine returns an Edit that prints both the rune address and the lines containing a to an io.Writer and sets dot to the a.

type Editor

type Editor interface {
	Text

	// SetMark sets the Span of a mark.
	//
	// ErrInvalidArgument is returned
	// if either endpoint of the Span is negative
	// or greater than the Size of the Text.
	SetMark(rune, Span) error

	// Change stages a change that modifies a Span of text
	// to contain the data from a Reader,
	// to be applied on the next call to Apply,
	// and returns the size of text read from the Reader.
	// This method does not modify the Text.
	//
	// It is an error if a change modifies text
	// overlapping or preceding a previously staged, unapplied change.
	// In such a case, ErrOutOfSequence is returned.
	//
	// If an error is returned, previously staged changes are canceled.
	// They will not be performed on the next call to Apply.
	Change(Span, io.Reader) (int64, error)

	// Apply applies all changes since the previous call to Apply,
	// updates all marks to reflect the changes,
	// logs the applied changes to the Undo stack,
	// and clears the Redo stack.
	Apply() error

	// Undo undoes the changes at the top of the Undo stack.
	// It updates all marks to reflect the changes,
	// and logs the undone changes to the Redo stack.
	Undo() error

	// Redo redoes the changes at the top of the Redo stack.
	// It updates all marks to reflect the changes,
	// and logs the redone changes to the Undo stack.
	Redo() error
}

An Editor provides a read-write view of a sequence of text.

An Editor changes the Text using a two-step procedure.

The first step is to stage a batch of changes using repeated calls to the Change method. The Change method does not modify the Text, but logs the desired change to a staging buffer.

The second step is to apply the staged changes by calling the Apply method. The Apply method applies the changes to the Text in the order that they were added to the staging log.

An Editor also has an Undo stack and a Redo stack. The stacks hold batches of changes, providing support for unlimited undoing and redoing of changes made by calls to Apply, Undo, and Redo.

type RangeError

type RangeError int64

A RangeError is returned if an Address is out of range of the buffer. The value of the error is the bounding endpoint of the buffer.

func (RangeError) Error

func (err RangeError) Error() string

type SimpleAddress

type SimpleAddress interface {
	AdditiveAddress
	// contains filtered or unexported methods
}

A SimpleAddress identifies a Span within a Text. SimpleAddresses can be composed using the methods of the AdditiveAddress interface to form more-complex Addresses.

var (
	// All is the Address of the entire Text: 0,$.
	All = Line(0).To(End)

	// Dot is the Address of the dot mark.
	Dot SimpleAddress = Mark('.')

	// End is the Address of the empty string at the end of the Text.
	End SimpleAddress = end{}
)

func Clamp

Clamp returns the SimpleAddress, a, clamped to the endpoints of the Text. Where a would return a RangeError, Clamp(a) returns the empty Address at the beginning or end of the text.

func Line

func Line(n int) SimpleAddress

Line returns the Address of the nth full line. A negative n is interpreted as n=0.

func Mark

func Mark(r rune) SimpleAddress

Mark returns the Address of the named mark rune. If the rune is a space character, . is used.

func Regexp

func Regexp(regexp string) SimpleAddress

Regexp returns an Address identifying the next match of a regular expression. If Regexp is the right-hand operand of + or -, next is relative to the left-hand operand. Otherwise, next is relative to the . mark.

If a forward search reaches the end of the Text without finding a match, it wraps to the beginning of the Text. If a reverse search reaches the beginning of the Text without finding a match, it wraps to the end of the Text.

The regular expression syntax is that of the standard library regexp package. The syntax is documented here: https://github.com/google/re2/wiki/Syntax. All regular expressions are wrapped in (?m:<re>), making them multi-line by default. In a forward search, the relative start location (the . mark or the right-hand operand of +) is considered to be the beginning of text. So, for example, given:

abcabc
abc

The address #3+/^abc will match the runes #3,#6, the second "abc" in the first line. Likewise, in a reverse search, the relative start location is considered to be the end of text.

func Rune

func Rune(n int64) SimpleAddress

Rune returns the Address of the empty Span after rune n. A negative n is interpreted as n=0.

type Span

type Span [2]int64

A Span identifies a string within a Text.

func (Span) Contains

func (s Span) Contains(l int64) bool

Contains returns whether a location is within the Span.

func (Span) Size

func (s Span) Size() int64

Size returns the size of the Span.

func (Span) Update

func (s Span) Update(t Span, n int64) Span

Update updates s to account for t changing to size n.

type Substitute

type Substitute struct {
	// Address is the address in which to search for matches.
	// After performing the edit, Dot is set the modified Address A.
	Address Address

	// Regexp is the regular expression to match.
	//
	// The regular expression syntax is that of the standard library regexp package.
	// The syntax is documented here: https://github.com/google/re2/wiki/Syntax.
	// All regular expressions are wrapped in (?m:<re>), making them multi-line by default.
	// The beginning and end of the address A
	// are the beginning and end of text for the regexp match.
	// So given:
	// 	xyzabc123
	// The substitution #3,#6s/^abc$/αβξ will result in:
	// 	xyzαβξ123
	Regexp string

	// With is the template with which to replace each match of Regexp.
	// The syntax is that of the standard regexp package's Regexp.Expand method
	// described here: https://golang.org/pkg/regexp/#Regexp.Expand.
	With string

	// Global is whether to replace all matches, or just one.
	// If Global is false, only one match is replaced.
	// If Global is true, all matches are replaced.
	//
	// When Global is true, matches skipped via From (see below)
	// are not replaced.
	Global bool

	// From is the number of the first match to begin substituting.
	// For example:
	// If From is 1, substitution begins with the first match.
	// If From is 2, substitution begins with the second match,
	// and the first match is left unchanged.
	//
	// If From is less than 1, substitution begins with the first match.
	From int
}

Substitute is an Edit that substitutes regular expression matches.

func (Substitute) Do

func (e Substitute) Do(ed Editor, _ io.Writer) error

func (Substitute) String

func (e Substitute) String() string

type Text

type Text interface {
	// Size returns the size of the Text.
	Size() int64

	// Mark returns the Span of a mark.
	// If the range was never set, Mark returns Span{}.
	Mark(rune) Span

	// RuneReader returns a RuneReader that reads runes from the given Span.
	//
	// If the Size of the Span is negative, the reader returns runes in reverse.
	//
	// If either endpoint of the Span is negative or greater than the Size of the Text,
	// an ErrInvalidArgument is retured by the RuneReader.ReadRune method.
	RuneReader(Span) io.RuneReader

	// Reader returns a Reader that reads the Span as bytes.
	//
	// An ErrInvalidArgument error is returned by the Reader.Read method if
	// either endpoint of the Span is negative or greater than the Size of the Text,
	// or if the Size of the Span is negative.
	Reader(Span) io.Reader
}

A Text provides a read-only view of a sequence of text.

Strings of the text are identified by Spans. The unit of measurement for a Span is unspecified; it is determined by the implementation using the Size method and the width return of RuneReader.RuneRead.

Directories

Path Synopsis
Package edittest contains utility functions for testing edits.
Package edittest contains utility functions for testing edits.
Package runes provides unbounded, file-backed rune buffers and io-package-style interfaces for reading and writing rune slices.
Package runes provides unbounded, file-backed rune buffers and io-package-style interfaces for reading and writing rune slices.

Jump to

Keyboard shortcuts

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