Documentation ¶
Overview ¶
Package rosed is a library for manipulating and laying out fixed-width text. It assumes that all text is encoded in UTF-8, the default encoding of source code string literals in Go.
"rosed" is pronounced as "Rose-Edd" but any pronunciation that can be understood to mean this library is accepted.
Grapheme-Awareness ¶
Functions in rosed that operate on text in a way that indexes characters or otherwise needs to count them (for instance, for wrapping purposes) do so by their grapheme clusters, not their Unicode codepoints, runes, or bytes. A grapheme is a single graphical unit that a human viewer would call a single character, but may in fact consist of several Unicode codepoints and their constituent runes and bytes; one or more codepoints that make up a single grapheme is known as a grapheme cluster.
For example, the sequence "é" is a single grapheme, as is "e". But in the case of "é", it may be represented in Unicode either by the single codepoint U+00E9 ("Latin Small Letter E With Acute"), or by the codepoint sequence U+0065, U+0301 ("Latin Small Letter E" followed by "Combining Acute Accent"). In Go source code, the later would be represented in UTF-8 strings as two runes (and whatever bytes it would take to make up those runes), meaning that both iteration over the string and unicode/utf8.RuneCountInString would return a higher number of runes than perhaps would be expected.
// This word appears to be 7 characters long: precomposed := "fiancée" decomposed := "fiance\u0301e" // and in fact, if printed, both show the same sequence to a human // user: fmt.Println(precomposed) // shows "fiancée" fmt.Println(decomposed) // ALSO shows "fiancée" fmt.Println(utf8.RuneCountInString(precomposed)) // prints 7 fmt.Println(utf8.RuneCountInString(decomposed)) // prints 8 (?!)
Try it on the Go Playground: https://go.dev/play/p/UiyXIHhWn_0
See UAX #15: Unicode Normalization Forms for more info on the forms that a Unicode string can take based on how it represents graphemes.
This library implements the algorithms described in UAX #29: Unicode Text Segmentation to recognize where in text the boundaries of each grapheme cluster are and correctly index by grapheme. This means it transparently handles all ways that a single "human-readable" character could be represented.
wrapped1 := rosed.Edit("My fiancée and I went to the bistro").Wrap(10).String() wrapped2 := rosed.Edit("My fiance\u0301e and I went to the bistro").Wrap(10).String() // because rosed is grapheme aware, both representations are wrapped the // same way fmt.Println(wrapped1) fmt.Println("") fmt.Println(wrapped2) // Both of the above print out: // // My fiancée // and I went // to the // bistro.
Try it on the Go Playground: https://go.dev/play/p/3CNStlPoWmE
Note that this library does not handle Unicode-normalized collation; that may be covered at a later time but for now it was deemed too much to implement for version 1.0, given the large amount of data from Unicode that must be added to the library for it to function and possible dependence on locale-specific settings.
Basic Usage ¶
All editing starts with an Editor. The zero-value can be used to start with blank text, otherwise Edit can be called to give the text to work with. Additionally, if desired, the Editor can have its Text property set to the text to operate on.
ed1 := rosed.Editor{} ed2 := rosed.Edit("my text") ed3 := rosed.Editor{Text: "my text"}
From that point, Editor functions can be called to modify the text in it. Editors are considered to be immutable by all functions that operate on them; these functions will return a new Editor with its Text set to the result of an operation as opposed to actually modifying the Text of the Editor they are called on.
// Here's an example of using Overtype to replace some text: ed := rosed.Edit("How are you, Miss Lalonde?") overtypedEd := ed.Overtype(4, "goes it") // The original Editor is unchanged: originalText := ed.String() fmt.Printf("originalText: %q\n", originalText) // Output: // originalText: "How are you, Miss Lalonde?" // But the text in the editor returned by Overtype is modified: output1 := overtypedEd.String() fmt.Printf("output1 : %q\n", output1) // Output: // output1 : "How goes it, Miss Lalonde?" // Alternatively, all calls can be chained: output2 := rosed.Edit("How are you, Miss Lalonde?").Overtype(4, "goes it").String() fmt.Printf("output2 : %q\n", output2) // Output: // output2 : "How goes it, Miss Lalonde?"
Try it on the Go Playground: https://go.dev/play/p/XjP0123dDtQ
Editor.Overtype is not a particularly exciting example of this library's use; Editor.Wrap, Editor.InsertTwoColumns, and Editor.InsertDefinitionsTable are some examples of the more complex operations that can be performed on an Editor.
Options For Behavior Control ¶
Some aspects of this library are controlled using consistent options set on an Editor. These are stored in an Options struct, and can be applied to an Editor either by assignment directly to Editor.Options or by calling Editor.WithOptions to get an Editor with those options set on it.
The Options struct itself supports a fluent interface for changing its values, using its WithX methods.
// can create Options struct with members set directly: opts1 := rosed.Options{PreserveParagraphs: true} // or by taking an existing Options and calling WithX functions on it: opts2 := rosed.Options{}.WithPreserveParagraphs(true)
Editor functions will mention which options they are affected by and how they are affected by them in the documentation comment for the function.
Note that Editor.WithOptions, like all other Editor functions, treats the Editor it operates on as immutable. It returns an Editor that has those options set on it, but the Editor it is called on is itself unchanged. To permanently set the Options on a particular Editor, you can assign an Options struct to Editor.Options manually.
// this is perfectly acceptable: ed := rosed.Editor{ Options: rosed.Options{ LineSeparator: "\r\n", }, }
If you want to avoid setting the options on the Editor and thus affecting all further operations, you can give the options for a particular call of an Editor function by calling the Opts version of it. If there is no Opts version, then that function is not affected by any options.
input := "More then ever, you feel, what's the word you're looking for? Of course. Housetrapped." opts := rosed.Options{PreserveParagraphs: true} ed := rosed.Edit(input) // Options can be set by giving them to the Editor prior to calling a function: output := ed.WithOptions(opts).Wrap(10).String() // ...or by calling the Opts version of the function: output := ed.WrapOpts(10, opts).String()
Editing Partial Sections ¶
To edit only a portion of the text in an Editor, a sub-editor can be created using Editor.Chars, Editor.CharsFrom, Editor.CharsTo, Editor.Lines, Editor.LinesFrom, or Editor.LinesTo. The Editor retured from these functions will perform operations only on the section specified, and any positions or lengths used in it will be relative to that sub-section's start and end. Writing past the end of the sub-editor's text is allowed and does not affect the text outside of the subsection.
These changes can be rolled up to the parent text by calling Editor.Commit. This will produce an Editor that consists of the full text prior to selecting a particular section, with all changes made to the sub-section merged in.
ed := rosed.Edit("Hello, World!") // edits only the ", " part subEd := ed.Chars(5, 7) // Make subEd.Text be "\t, " subEd = subEd.Indent(1) // And bring it all back together ed = subEd.Commit() // Get the result string, which will be "Hello\t, world!" output1 := ed.String() // The same steps using the fluent style: output2 := rosed.Edit("Hello, World!").Chars(5, 7).Indent(1).Commit().String()
If multiple sub-editors have been made, Editor.CommitAll can be used to apply all changes recursively and return an Editor operating on the full text. Calling Editor.String on a sub-editor will also cause CommitAll to be called, making it an excellent choice to get Editor.Text without needing to be concerned with whether it is a sub-editor.
// Commit() or CommitAll() is not needed before string: output := rosed.Edit("Hello, World!").Chars(5, 7).Indent(1).String()
Note that it is possible to create a sub-editor, and then create another sub-editor off of the same original Editor. This may have unexpected results and is not the intended use of sub-editors.
Negative Indexing ¶
Some Editor functions accept one or more indexes, either of characters (graphemes specifically, in the context of this library), lines, or other textual elements. The rosed library has implemented the use of negative indexes to make it a easier to reference positions releative to the end of the sequence they are in.
What this means is that a function such as Editor.Insert can receive a negative index for its position argument, and it will interpret it as relative to the end of the text. For instance, -1 would be the last character, -2 would be the second-to-last character, etc. If a negative index would specify someting before the start of the collection, it is automatically assumed to be 0.
ed := rosed.Edit("John, Dave, and Jade") // whoops, we forget to add someone 9 characters before the end! ed = ed.Insert(-9, "Rose, ") // this will be the correct "John, Dave, Rose, and Jade" output := ed.String()
Many functions that do this will mention it explicitly, but all functions that accept positions can interpret negative positions.
Custom Operations ¶
The rosed package supports several operations on Editor text out of the box, however these are insufficient for all uses. To address cases where custom functionality may be needed, two functions are provided. They are Editor.Apply and Editor.ApplyParagraphs. These allow the user to provide a custom function to operate on text on a per-line or per-paragraph basis.
textBody := "John\nRose\nDave\nJade" namerFunc := func(lineIdx int, line string) []string { newStr := fmt.Sprintf("Beta Kid #%d: %s", lineIdx + 1, line) return []string{newStr} } output := rosed.Edit(textBody).Apply(namerFunc).String() // The output will be: // // Beta Kid #1: John // Beta Kid #2: Rose // Beta Kid #3: Dave // Beta Kid #4: Jade
Do note that as the LineOperation or ParagraphOperation passed to the above functions will be user-defined, they will not be grapheme-aware unless the user ensures that this is the case.
Example (End) ¶
This example uses the rosed.End constant to specify the end of the text as the editor is modified.
fullText := Edit("Hello!\n"). Insert(End, "This is a line\n"). Insert(End, "And this is another"). String() fmt.Println(fullText)
Output: Hello! This is a line And this is another
Index ¶
- Constants
- type Alignment
- type Editor
- func (ed Editor) Align(align Alignment, width int) Editor
- func (ed Editor) AlignOpts(align Alignment, width int, opts Options) Editor
- func (ed Editor) Apply(op LineOperation) Editor
- func (ed Editor) ApplyOpts(op LineOperation, opts Options) Editor
- func (ed Editor) ApplyParagraphs(op ParagraphOperation) Editor
- func (ed Editor) ApplyParagraphsOpts(op ParagraphOperation, opts Options) Editor
- func (ed Editor) CharCount() int
- func (ed Editor) Chars(start, end int) Editor
- func (ed Editor) CharsFrom(start int) Editor
- func (ed Editor) CharsTo(end int) Editor
- func (ed Editor) CollapseSpace() Editor
- func (ed Editor) CollapseSpaceOpts(opts Options) Editor
- func (ed Editor) Commit() Editor
- func (ed Editor) CommitAll() Editor
- func (ed Editor) Delete(start, end int) Editor
- func (ed Editor) Indent(level int) Editor
- func (ed Editor) IndentOpts(level int, opts Options) Editor
- func (ed Editor) Insert(charPos int, text string) Editor
- func (ed Editor) InsertDefinitionsTable(pos int, definitions [][2]string, width int) Editor
- func (ed Editor) InsertDefinitionsTableOpts(pos int, definitions [][2]string, width int, opts Options) Editor
- func (ed Editor) InsertTable(pos int, data [][]string, width int) Editor
- func (ed Editor) InsertTableOpts(pos int, data [][]string, width int, opts Options) Editor
- func (ed Editor) InsertTwoColumns(pos int, leftText string, rightText string, minSpaceBetween int, width int, ...) Editor
- func (ed Editor) InsertTwoColumnsOpts(pos int, leftText string, rightText string, minSpaceBetween int, width int, ...) Editor
- func (ed Editor) IsSubEditor() bool
- func (ed Editor) Justify(width int) Editor
- func (ed Editor) JustifyOpts(width int, opts Options) Editor
- func (ed Editor) LineCount() int
- func (ed Editor) Lines(start, end int) Editor
- func (ed Editor) LinesFrom(start int) Editor
- func (ed Editor) LinesTo(end int) Editor
- func (ed Editor) Overtype(charPos int, text string) Editor
- func (ed Editor) String() string
- func (ed Editor) WithOptions(opts Options) Editor
- func (ed Editor) Wrap(width int) Editor
- func (ed Editor) WrapOpts(width int, opts Options) Editor
- type LineOperation
- type Options
- func (opts Options) String() string
- func (opts Options) WithDefaults() Options
- func (opts Options) WithIndentStr(str string) Options
- func (opts Options) WithJustifyLastLine(justifyLastLine bool) Options
- func (opts Options) WithLineSeparator(sep string) Options
- func (opts Options) WithNoTrailingLineSeparators(noTrailingLineSeps bool) Options
- func (opts Options) WithParagraphSeparator(sep string) Options
- func (opts Options) WithPreserveParagraphs(preserve bool) Options
- func (opts Options) WithTableBorders(borders bool) Options
- func (opts Options) WithTableCharSet(charSet string) Options
- func (opts Options) WithTableHeaders(headers bool) Options
- type ParagraphOperation
Examples ¶
- Package (End)
- Edit
- Editor.Align (Center)
- Editor.Align (Left)
- Editor.Align (Right)
- Editor.AlignOpts
- Editor.Apply
- Editor.ApplyOpts
- Editor.ApplyParagraphs
- Editor.ApplyParagraphsOpts
- Editor.CharCount
- Editor.Chars
- Editor.CharsFrom
- Editor.CharsTo
- Editor.CollapseSpace
- Editor.CollapseSpaceOpts
- Editor.Commit (ManualReplacement)
- Editor.Commit (Operation)
- Editor.CommitAll
- Editor.Delete
- Editor.Indent
- Editor.IndentOpts (IndentStr)
- Editor.IndentOpts (PreserveParagraphs)
- Editor.Insert
- Editor.InsertDefinitionsTable
- Editor.InsertDefinitionsTableOpts
- Editor.InsertTable
- Editor.InsertTableOpts (TableBorders)
- Editor.InsertTableOpts (TableBordersAndHeaders)
- Editor.InsertTableOpts (TableCharSet)
- Editor.InsertTableOpts (TableHeaders)
- Editor.InsertTwoColumns
- Editor.InsertTwoColumnsOpts
- Editor.IsSubEditor
- Editor.Justify
- Editor.JustifyOpts (JustifyLastLine)
- Editor.JustifyOpts (ParagraphSeparator)
- Editor.LineCount
- Editor.LineCount (Options)
- Editor.Lines
- Editor.LinesFrom
- Editor.LinesTo
- Editor.Overtype
- Editor.String
- Editor.String (SubEditor)
- Editor.WithOptions
- Editor.Wrap
- Editor.WrapOpts
- Options.String
- Options.WithDefaults
- Options.WithIndentStr
- Options.WithJustifyLastLine
- Options.WithLineSeparator
- Options.WithNoTrailingLineSeparators
- Options.WithParagraphSeparator
- Options.WithPreserveParagraphs
- Options.WithTableBorders
- Options.WithTableCharSet
- Options.WithTableHeaders
Constants ¶
const ( // DefaultIndentString is the default string used for a single horizontal // indent. DefaultIndentString = "\t" // DefaultLineSeparator is the default line separator sequence. DefaultLineSeparator = "\n" // DefaultParagraphSeparator is the default sequence that separates // paragraphs. DefaultParagraphSeparator = "\n\n" // DefaultTableCharSet is the default characters used to draw table borders. DefaultTableCharSet = "+|-" )
const End = -int(^uint(0)>>1) - 1
End is a constant that if passed to a position argument, represents a contextual "end of text" as of the calling of the operation it is passed to. Will always refer to the end of text.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Alignment ¶ added in v1.1.0
type Alignment int
Alignment is the type of alignment to apply to text. It is used in the Editor.Align function.
type Editor ¶
type Editor struct { // Text is the string that will be operated on. Text string // The Options that the Editor will use for the next operation. These can // be modified prior to the operation. Options Options // contains filtered or unexported fields }
Editor performs transformations on text. It is the primary way to edit text using the rosed package.
The zero value is an Editor ready to operate on the empty string. Alternatively, Edit can be called to produce an Editor ready to operate on the passed-in string. There is no functional difference between a zero-value Editor having its Text property set manually and calling Edit with a string; they will produce identical Editors.
All operations on an Editor treat it as immutable; calling an operation returns a new Editor with its Text property set to the result of the operation. It is valid to manually set properties of an Editor and this will not break the assumptions made by operations called on it.
Editor has an Options member for including an Options instance to control the behavior of certain functions called on it. If left unset, functions called on the Editor will treat it as though it has been set with the equivalent of calling Options.WithDefaults on an empty Options struct.
Sub-Editor Functions ¶
Some Editor functions produce a sub-editor, whose Text field will contain only the sub-section of text specified. Editing the parent's Text field after the sub-editor has been created will have no effect on the sub-editor or any Editor produced from it, but note that it may have an affect on the result of calling Commit() on the sub-editor and as a result is not the inteded usage of sub-editors.
The sub-editor can be merged back into the original Editor by calling Editor.Commit on the sub-editor. Alternatively, all such sub-editors can be merged recursively up to the root Editor by calling Editor.CommitAll on the sub-editor.
func Edit ¶
Edit creates an Editor with its Text property set to the given string and with Options set to their default values.
Example ¶
ed := Edit("sample text") fmt.Println(ed.Text)
Output: sample text
func (Editor) Align ¶ added in v1.1.0
Align makes each line follow the given alignment. If None is given for the alignment, this operation has no effect. If a line is not the given width, spaces are added to the unaligned-to end until the line is that width. If a line (minus any leading/trailing space being removed by the alignment) is already more than the given width, it will not be affected.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This function is affected by the following Options:
- LineSeparator is used to separate lines of input.
- ParagraphSeparator is the separator used to split paragraphs. It will only have effect if PreserveParagraphs is set to true.
- PreserveParagraphs gives whether to respect paragraphs instead of considering them text to be aligned. If set to true, the text is split into paragraphs by ParagraphSeparator, then the align is applied to each paragraph.
- NoTrailingLineSeparators specifies whether the function should consider a final instance of LineSeparator to be ending the prior line or giving the start of a new line. If NoTrailingLineSeparators is true, a trailing LineSeparator is considered to start a new (empty) line; additionally, the align will be called at least once for an empty string. If NoTrailingLineSeparators is set to false and the Editor text is set to an empty string, the align will not be called even once.
Example (Center) ¶
This example shows use of Align to center each line of text.
text := "Your name is TEREZI PYROPE.\n" text += "\n" text += "You are pretty enthusiastic about dragons.\n" text += "But you have a PARTICULAR AFFECTION\n" text += "for their COLORFUL SCALES, which you gather\n" text += "and use to decorate your hive.\n" ed := Edit(text) ed = ed.Align(Center, 45) // also add a pipe char at start and end of each line to show that space is // added to fill out each line to the specified width: ed = ed.Apply(func(idx int, line string) []string { return []string{"|" + line + "|"} }) fmt.Println(ed.String())
Output: | Your name is TEREZI PYROPE. | | | | You are pretty enthusiastic about dragons. | | But you have a PARTICULAR AFFECTION | | for their COLORFUL SCALES, which you gather | | and use to decorate your hive. |
Example (Left) ¶
This example shows use of Align to take inconsistently tabbed input and normalize each line to no indent before doing further operations.
text := "\t\t\tYour name is TEREZI PYROPE.\n" text += "\n" text += "\t You are pretty enthusiastic about dragons.\n" text += " But you have a PARTICULAR AFFECTION\n" text += "\t for their COLORFUL SCALES, which you gather\n" text += "\t\tand use to decorate your hive.\n" ed := Edit(text) ed = ed.Align(Left, 45) // also add a pipe char at start and end of each line to show that space is // added to fill out each line to the specified width: ed = ed.Apply(func(idx int, line string) []string { return []string{"|" + line + "|"} }) fmt.Println(ed.String())
Output: |Your name is TEREZI PYROPE. | | | |You are pretty enthusiastic about dragons. | |But you have a PARTICULAR AFFECTION | |for their COLORFUL SCALES, which you gather | |and use to decorate your hive. |
Example (Right) ¶
This example shows use of Align to make every line align to the right side.
text := "Your name is TEREZI PYROPE.\n" text += "\n" text += "You are pretty enthusiastic about dragons.\n" text += "But you have a PARTICULAR AFFECTION\n" text += "for their COLORFUL SCALES, which you gather\n" text += "and use to decorate your hive.\n" ed := Edit(text) ed = ed.Align(Right, 45) // also add a pipe char at start and end of each line to show that space is // added to fill out each line to the specified width: ed = ed.Apply(func(idx int, line string) []string { return []string{"|" + line + "|"} }) fmt.Println(ed.String())
Output: | Your name is TEREZI PYROPE.| | | | You are pretty enthusiastic about dragons.| | But you have a PARTICULAR AFFECTION| | for their COLORFUL SCALES, which you gather| | and use to decorate your hive.|
func (Editor) AlignOpts ¶ added in v1.1.0
AlignOpts makes each line follow the given alignment using the provided options.
This is identical to Editor.Align but provides the ability to set Options for the invocation.
Example ¶
This example shows use of a custom line separator with Align to respect text that uses the HTML tag "<br/>\n" to separate lines.
text := "Your name is TEREZI PYROPE.<br/>\n" text += "<br/>\n" text += "You are pretty enthusiastic about dragons.<br/>\n" text += "But you have a PARTICULAR AFFECTION<br/>\n" text += "for their COLORFUL SCALES, which you gather<br/>\n" text += "and use to decorate your hive.<br/>\n" opts := Options{ LineSeparator: "<br/>\n", } ed := Edit(text) ed = ed.AlignOpts(Center, 45, opts) // also add a pipe char at start and end of each line to show that space is // added to fill out each line to the specified width: /*ed = ed.Apply(func(idx int, line string) []string { return []string{"|" + line + "|"} })*/ fmt.Println(ed.String())
Output: Your name is TEREZI PYROPE. <br/> <br/> You are pretty enthusiastic about dragons. <br/> But you have a PARTICULAR AFFECTION <br/> for their COLORFUL SCALES, which you gather <br/> and use to decorate your hive. <br/>
func (Editor) Apply ¶
func (ed Editor) Apply(op LineOperation) Editor
Apply applies the given LineOperation to each line in the text. Line termination at the last line is transparently handled as per the options set on the Editor.
The LineOperation should assume it will receive each line without its line terminator, and must assume that anything it returns will have re-adding the separator to it handled by the caller.
This function is affected by the following Options:
- LineSeparator specifies what string in the source text should be used to delimit lines to be passed to the LineOperation.
- NoTrailingLineSeparators specifies whether the function should consider a final instance of LineSeparator to be ending the prior line or giving the start of a new line. If NoTrailingLineSeparators is true, a trailing LineSeparator is considered to start a new (empty) line; additionally, the LineOperation will be called at least once for an empty string. If NoTrailingLineSeparators is set to false and the Editor text is set to an empty string, the LineOperation will not be called.
Example ¶
This example shows the use of Apply to add a numbered prefix to every line.
namerFunc := func(lineIdx int, line string) []string { newStr := fmt.Sprintf("Alpha Kid #%d: %s", lineIdx+1, line) return []string{newStr} } ed := Edit("Jane\nJake\nDirk\nRoxy").Apply(namerFunc) fmt.Println(ed.String())
Output: Alpha Kid #1: Jane Alpha Kid #2: Jake Alpha Kid #3: Dirk Alpha Kid #4: Roxy
func (Editor) ApplyOpts ¶
func (ed Editor) ApplyOpts(op LineOperation, opts Options) Editor
ApplyOpts applies the given LineOperation to each line in the text, using the provided options.
This is identical to Editor.Apply but provides the ability to set Options for the invocation.
Example ¶
This example uses options to tell the Editor to use a custom LineSeparator of the HTML tag "<br/>", and it tells it that any trailing line ending is in fact the start of a new, empty line, which should be processed by the function.
alphaKids := 0 namerFunc := func(lineIdx int, line string) []string { if line == "" { return []string{"Nobody here!"} } alphaKids++ newStr := fmt.Sprintf("Alpha Kid #%d: %s", alphaKids, line) return []string{newStr} } opts := Options{ NoTrailingLineSeparators: true, LineSeparator: "<br/>", } // have a trailing line separator so we get the extra call of our func // due to NoTrailingLineSeparators ed := Edit("Jane<br/><br/>Dirk<br/>Roxy<br/>").ApplyOpts(namerFunc, opts) fmt.Println(ed.String())
Output: Alpha Kid #1: Jane<br/>Nobody here!<br/>Alpha Kid #2: Dirk<br/>Alpha Kid #3: Roxy<br/>Nobody here!
func (Editor) ApplyParagraphs ¶
func (ed Editor) ApplyParagraphs(op ParagraphOperation) Editor
ApplyParagraphs applies the given ParagraphOperation to each paragraph in the text of the Editor.
The ParagraphOperation should assume it will receive each paragraph without its paragraph separator, and must assume that anything it returns will have re-adding the separator to it handled by the caller.
When the ParagraphSeparator of the Editor's options is set to a sequence that includes non-whitespace characters that take up horizontal space, the ParagraphOperation will receive the prefix and suffix of the paragraph that would be in the joined string due to the separator, with variables sepPrefix and sepSuffix. This is not intended to allow the operation to add them back in manually, as that is handled by the caller, but for it to perform book-keeping and length checks and act accordingly, such when attempting to output something that is intended to be aligned.
Unlike with LineSeparator, a ParagraphSeparator is always considered a separator, not a terminator, so the affixes may vary per paragraph if the ParagraphSeparator has line breaks in it; in that case the first paragraph will have an empty prefix, the last paragraph will have an empty suffix, and all other paragraphs will have non-empty prefixes and suffixes.
For an example of a ParagraphOperator that uses sepPrefix and sepSuffix and a custom ParagraphSeparator that makes them non-empty, see the example for Editor.ApplyParagraphsOpts.
Note that treating the paragraph separator as a splitter and not a terminator means that the ParagraphOperation is always called at least once, even for an empty editor.
This function is affected by the following Options:
- ParagraphSeparator specifies the string that paragraphs are split by.
Example ¶
This example names the people in each paragraph in the input text based on who is present. Since no options are specified, it uses the default ParagraphSeparator of "\n\n".
text := "" text += "John\n" // paragraph 1 text += "Rose\n" text += "Dave\n" text += "Jade\n" text += "\n" text += "Jane\n" // paragraph 2 text += "Jake\n" text += "Dirk\n" text += "Roxy\n" text += "\n" text += "Aradia\n" // paragraph 3 text += "Tavros\n" text += "Sollux\n" text += "Karkat" paraOp := func(idx int, para, sepPrefix, sepSuffix string) []string { var newPara string if strings.Contains(para, "John") { newPara = "Beta Kids:\n" + para } else if strings.Contains(para, "Jane") { newPara = "Alpha Kids:\n" + para } else { newPara = "Someone Else:\n" + para } return []string{newPara} } ed := Edit(text).ApplyParagraphs(paraOp) fmt.Println(ed.String())
Output: Beta Kids: John Rose Dave Jade Alpha Kids: Jane Jake Dirk Roxy Someone Else: Aradia Tavros Sollux Karkat
func (Editor) ApplyParagraphsOpts ¶
func (ed Editor) ApplyParagraphsOpts(op ParagraphOperation, opts Options) Editor
ApplyParagraphsOpts applies the given ParagraphOperation to each paragraph in the text of the Editor, using the provided options.
This is identical to Editor.ApplyParagraphs but provides the ability to set Options for the invocation.
Example ¶
This example uses options to tell the Editor to use a custom ParagraphSeparator for splitting paragrahs, and also shows how sepPrefix and sepSuffix are set.
opts := Options{ParagraphSeparator: "<P1>\n<P2>"} ed := Edit("para1<P1>\n<P2>para2<P1>\n<P2>para3<P1>\n<P2>para4") paraOp := func(idx int, para, sepPrefix, sepSuffix string) []string { newPara := fmt.Sprintf("(PREFIX=%s,PARA=%s,SUFFIX=%s)", sepPrefix, para, sepSuffix) return []string{newPara} } ed = ed.ApplyParagraphsOpts(paraOp, opts) fmt.Println(ed.String())
Output: (PREFIX=,PARA=para1,SUFFIX=<P1>)<P1> <P2>(PREFIX=<P2>,PARA=para2,SUFFIX=<P1>)<P1> <P2>(PREFIX=<P2>,PARA=para3,SUFFIX=<P1>)<P1> <P2>(PREFIX=<P2>,PARA=para4,SUFFIX=)
func (Editor) CharCount ¶ added in v1.1.0
CharCount returns the number of grapheme clusters in the Editor's text. This is the number of characters a human viewer would count if the text were displayed or printed.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
Example ¶
This example gets the length of several different strings.
emptyCount := Edit("").CharCount() fmt.Println(emptyCount) testCount := Edit("test").CharCount() fmt.Println(testCount) //lint:ignore ST1018 because go-staticcheck dislikes emoji literals with ZWJ sequences emojiCount := Edit("👩❤️💋👩").CharCount() fmt.Println(emojiCount)
Output: 0 4 1
func (Editor) Chars ¶
Chars produces an Editor to operate on a subset of the characters in the Editor's text. The returned Editor operates on text from the nth character up to (but not including) the ith character, where n is start and i is end.
The start or end parameter may be negative, in which case it will be relative to the end of the string; -1 would be the index of the last character, -2 would be the index of the second-to-last character, etc.
If one of the parameters specifies an index that is past the end of the string, that index is assumed to be the end of the string. If either specify an index that is before the start of the string, it is assumed to be 0.
If end is less than start, it is assumed to be equal to start.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This is a Sub-Editor function. See the note on Editor for more info.
Example ¶
This example gets a sub-Editor for the the "ell" part of "Hello!".
ed := Edit("Hello!") subEd := ed.Chars(1, 4) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(subEd.Text)
Output: ell
func (Editor) CharsFrom ¶
CharsFrom produces an Editor to operate on a subset of the characters in the Editor's text. The returned Editor operates on text from the nth character up to the end of the text, where n is start.
Calling this function is identical to calling Editor.Chars with the given start and with end set to the end of the text.
Example ¶
This example gets a sub-Editor for the the "ello!" part of "Hello!".
ed := Edit("Hello!") subEd := ed.CharsFrom(1) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(subEd.Text)
Output: ello!
func (Editor) CharsTo ¶
CharsTo produces an Editor to operate on a subset of the characters in the Editor's text. The returned Editor operates on text from the first character up to but not including the nth character, where n is end.
Calling this function is identical to calling Editor.Chars with the given end and with start set to the start of the text.
Example ¶
This example gets a sub-Editor for the the "He" part of "Hello!".
ed := Edit("Hello!") subEd := ed.CharsTo(2) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(subEd.Text)
Output: He
func (Editor) CollapseSpace ¶
CollapseSpace converts all consecutive whitespace characters to a single space character.
This function is affected by the following Options:
- LineSeparator is always considered whitespace, and will be collapsed into a space regardless of the classification of the characters within it.
Example ¶
This example shows how CollapseSpace collapses all whitespace sequences into a single space, even those that have characters not typically encountered. As long as Unicode considers it a whitespace character, it will be collapsed.
text := "Some \n\n\n sample text \t\n\t \t with \u2002 \v\v whitespace" ed := Edit(text).CollapseSpace() fmt.Println(ed.String())
Output: Some sample text with whitespace
func (Editor) CollapseSpaceOpts ¶
CollapseSpaceOpts converts all consecutive whitespace characters to a single space character using the provided options.
This is identical to Editor.CollapseSpace but provides the ability to set Options for the invocation.
Example ¶
This example shows the use of Options with CollapseSpace to specify a LineSeparator that contains no whitespace. It shows that even LineSeparators without any Unicode space characters will be collapsed.
text := "Some \n\n\n sample<P>text \u202f <P> \t\n\t \t with \u2002 <P> whitespace" opts := Options{ LineSeparator: "<P>", } ed := Edit(text).CollapseSpaceOpts(opts) fmt.Println(ed.String())
Output: Some sample text with whitespace
func (Editor) Commit ¶
Commit takes the substring that a sub-editor is operating on and merges it with its parent. It returns an Editor which is a copy of the current one but with its text set to the merged string.
If the Editor is already a full-text Editor, the merge operation simply copies the current text since there is nothing to merge with, so calling Commit returns an identical copy of the Editor.
Example (ManualReplacement) ¶
This example shows how Commit can be used to commit the results of manually assigning a subeditor's Text field.
// get a subeditor on the first 7 chars, "Initial" subEd := Edit("Initial string").Chars(0, 7) // any Editor operation may be done, in our case we will manually update // the Text of the subeditor to replace the word entirely subEd.Text = "Test" // now call Commit to send it back up and get our original editor mergedEd := subEd.Commit() fmt.Println(mergedEd.String())
Output: Test string
Example (Operation) ¶
This example shows how Commit can be used to commit the results of a normal Editor operation called on a subeditor.
// get a subeditor on the last 6 chars, "string" subEd := Edit("Test string").CharsFrom(-6) // any Editor operation may be done, in our case we will call the operation // Indent to give it some leading whitespace subEd = subEd.Indent(2) // now call Commit to get the results merged in mergedEd := subEd.Commit() fmt.Println(mergedEd.String())
Output: Test string
func (Editor) CommitAll ¶
CommitAll takes the substring that a sub-editor is operating on and merges it with its parent recursively. Returns an Editor which is a copy of the current one but with its text set to the result of merging every sub-editor from the one CommitAll is called on up to the root Editor.
If the Editor is already a full-text Editor, the merge operation simply copies the current text since there is nothing to merge with, so calling CommitAll returns an identical copy of the Editor.
Example ¶
This example shows the use of CommitAll to commit all outstanding subeditors. It edits a simple essay outline.
text := "" text += "\t\tLine 1: An intro\n" text += "Line 2: A body\n" text += "\t\tLine 3: A conclusion" startingEd := Edit(text) // get a sub-editor for the second line, and fix the missing indent firstLineSubEd := startingEd.Lines(1, 2) firstLineSubEd = firstLineSubEd.Indent(2) // 'body' is a boring word, let's get a subeditor on that part and do // something about that. // -5 to -1 because that is the last 4 chars other than the trailing newline bodySubSubEd := firstLineSubEd.Chars(-5, -1) bodySubSubEd = bodySubSubEd.Overtype(0, "rationale") // changes are done, so commit all to get all changes merged mergedEd := bodySubSubEd.CommitAll() fmt.Println(mergedEd.String())
Output: Line 1: An intro Line 2: A rationale Line 3: A conclusion
func (Editor) Delete ¶ added in v0.2.0
Delete removes text from the Editor. All text after the deleted sequence is moved left to the starting position of the deleted sequence.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
Example ¶
This example shows the deletion of unwanted text in the editor.
ed := Edit("Here is some EXTRA text") ed = ed.Delete(13, 19) fmt.Println(ed.String())
Output: Here is some text
func (Editor) Indent ¶
Indent adds an indent string at the start of each line in the Editor. The string used for a single level of indent is determined by Editor options and will be applied level times. If level is 0 or less, the text will be unchanged.
With default options set, this operation has no effect on an empty editor.
This function is affected by the following Options:
- IndentStr is the sequence to use to indent a single level.
- LineSeparator is the string that delimits lines.
- NoTrailingLineSeparators alters whether LineSeparator is expected to be at the end of a complete line. If this is set to true, then a LineSeparator does not need to be present at the end of a complete line. Any trailing line separator for a non-empty editor is then considered to split the last line from a new, empty line, which will be indented. In addition, the empty editor will be considered to have a single line, which will be indented.
- ParagraphSeparator is the separator used to split paragraphs. It will only have effect if PreserveParagraphs is set to true.
- PreserveParagraphs gives whether to respect paragraphs instead of treating paragraph breaks as normal text. If set to true, the text is first split into paragraphs by ParagraphSeparator, then the indent is applied to each paragraph.
Example ¶
This example shows a typical indent being applied to a list of people.
text := "" text += "* Aradia\n" text += "* Tavros\n" text += "* Sollux\n" text += "* Karkat\n" ed := Edit(text) ed = ed.Indent(1) fmt.Println(ed.String())
Output: * Aradia * Tavros * Sollux * Karkat
func (Editor) IndentOpts ¶
IndentOpts adds an indent string at the start of each line in the Editor using the provided options.
This is identical to Editor.Indent but provides the ability to set Options for the invocation.
Example (IndentStr) ¶
This example shows using options to specify a custom string to use for the indent.
text := "" text += "* Nepeta\n" text += "* Kanaya\n" text += "* Terezi\n" text += "* Vriska\n" opts := Options{ IndentStr: "==>", } ed := Edit(text) ed = ed.IndentOpts(2, opts) fmt.Println(ed.String())
Output: ==>==>* Nepeta ==>==>* Kanaya ==>==>* Terezi ==>==>* Vriska
Example (PreserveParagraphs) ¶
This example shows using options to respect paragraph breaks.
text := "" text += "Beta Kids:\n" text += "* John\n" text += "* Rose\n" text += "* Dave\n" text += "* Jade\n" text += "\n" text += "Alpha Kids:\n" text += "* Jane\n" text += "* Jake\n" text += "* Dirk\n" text += "* Roxy\n" opts := Options{ PreserveParagraphs: true, } ed := Edit(text) ed = ed.IndentOpts(1, opts) fmt.Println(ed.String())
Output: Beta Kids: * John * Rose * Dave * Jade Alpha Kids: * Jane * Jake * Dirk * Roxy
func (Editor) Insert ¶
Insert adds a string to the text at the given position. The position is zero-indexed and refers to the visible characters in the text. At whatever position is given, the existing text is moved forward to make room for the new text.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
Example ¶
This example inserts the text "burb" in the middle of the editor text.
ed := Edit("S world!") ed = ed.Insert(1, "burb") fmt.Println(ed.String())
Output: Sburb world!
func (Editor) InsertDefinitionsTable ¶
InsertDefinitionsTable creates a table of term definitions and inserts it into the text of the Editor. A definitions table is a two-column table that puts the terms being defined on the left and their definitions on the right. The terms are indented by two space characters.
A sample definitions table: John - Has a passion for REALLY TERRIBLE MOVIES. Likes to program computers but is NOT VERY GOOD AT IT. Rose - Has a passion for RATHER OBSCURE LITERATURE. Enjoys creative writing and is SOMEWHAT SECRETIVE ABOUT IT. Dave - Has a penchant for spinning out UNBELIEVABLY ILL JAMS with his TURNTABLES AND MIXING GEAR. Likes to rave about BANDS NO ONE'S EVER HEARD OF BUT HIM. Jade - Has so many INTERESTS, she has trouble keeping track of them all, even with an assortment of COLORFUL REMINDERS on her fingers to help sort out everything on her mind.
The character position to insert the table at is given by the pos argument. The definitions themselves are given as a slice of 2-tuples of strings, where the first item in each tuple is the term and the second item is the definition. If no definitions are given, or an empty slice is passed in, there will be no output.
The complete maximum width of the table to output including the leading indent is given by the width argument. Note that not every line will be this long; wrapping will often cause them to be shorter.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This function is affected by the following Options:
- LineSeparator is used to separate each line of the table output.
- ParagraphSeparator is used to separate each term/definition pair from the other definitions.
- NoTrailingLineSeparators sets whether to include a trailing LineSeparator at the end of the table. If set to true, it will be omitted, otherwise the table will end with a LineSeparator.
Example ¶
This example produces the table seen above.
ed := Edit("") var johnDef, roseDef, daveDef, jadeDef string johnDef += "Has a passion for REALLY TERRIBLE MOVIES. Likes " johnDef += "to program computers but is NOT VERY GOOD AT IT." roseDef += "Has a passion for RATHER OBSCURE LITERATURE. " roseDef += "Enjoys creative writing and is SOMEWHAT " roseDef += "SECRETIVE ABOUT IT." daveDef += "Has a penchant for spinning out UNBELIEVABLY ILL " daveDef += "JAMS with his TURNTABLES AND MIXING GEAR. Likes " daveDef += "to rave about BANDS NO ONE'S EVER HEARD OF BUT HIM." jadeDef += "Has so many INTERESTS, she has trouble keeping " jadeDef += "track of them all, even with an assortment of " jadeDef += "COLORFUL REMINDERS on her fingers to help sort out " jadeDef += "everything on her mind." defs := [][2]string{ {"John", johnDef}, {"Rose", roseDef}, {"Dave", daveDef}, {"Jade", jadeDef}, } ed = ed.InsertDefinitionsTable(0, defs, 76) fmt.Println("TABLE:") fmt.Println(ed.String())
Output: TABLE: John - Has a passion for REALLY TERRIBLE MOVIES. Likes to program computers but is NOT VERY GOOD AT IT. Rose - Has a passion for RATHER OBSCURE LITERATURE. Enjoys creative writing and is SOMEWHAT SECRETIVE ABOUT IT. Dave - Has a penchant for spinning out UNBELIEVABLY ILL JAMS with his TURNTABLES AND MIXING GEAR. Likes to rave about BANDS NO ONE'S EVER HEARD OF BUT HIM. Jade - Has so many INTERESTS, she has trouble keeping track of them all, even with an assortment of COLORFUL REMINDERS on her fingers to help sort out everything on her mind.
func (Editor) InsertDefinitionsTableOpts ¶
func (ed Editor) InsertDefinitionsTableOpts(pos int, definitions [][2]string, width int, opts Options) Editor
InsertDefinitionsTableOpts creates a table of term definitions using the provided options and inserts it into the text of the Editor.
This is identical to Editor.InsertDefinitionsTable but provides the ability to set Options for the invocation.
Example ¶
This example uses options to set a custom paragraph separator so that terms are separated by dashes instead of blank lines.
ed := Edit("") defs := [][2]string{ {"Apple", "A delicious fruit that can be eaten by pretty much anybody who likes fruit."}, {"Bottle", "Holds liquids."}, {"Crow's Egg", "The egg of a crow, who may or may not go CAW-CAW."}, {"Dog Pinata", "If you hit it, candy will come out."}, } opts := Options{ ParagraphSeparator: "\n------------------------------------------------------------\n", } ed = ed.InsertDefinitionsTableOpts(0, defs, 60, opts) fmt.Println("TABLE:") fmt.Println(ed.String())
Output: TABLE: Apple - A delicious fruit that can be eaten by pretty much anybody who likes fruit. ------------------------------------------------------------ Bottle - Holds liquids. ------------------------------------------------------------ Crow's Egg - The egg of a crow, who may or may not go CAW-CAW. ------------------------------------------------------------ Dog Pinata - If you hit it, candy will come out.
func (Editor) InsertTable ¶ added in v1.2.0
InsertTable creates a table from the provided data and inserts it into the text of the Editor.
By default, this will create a table with equally-sized columns spaced out to reach width, with every row of data treated the same. The options TableHeaders, TableBorders, and TableCharSet are all consulted to determine how to draw the table and can be set to customize the table output.
The parameter data is a slice of rows, each of which is a slice of cells of table data. The resulting table will have as many columns as the row in data with the most cells; if any row has fewer than that, an empty string is substituted for the missing cells. If data is empty or nil, no output is produced. If data consists only of empty rows, no output is produced.
This function is affected by the following Options:
- LineSeparator is used to separate each line of the output.
- NoTrailingLineSeparators sets whether to include a trailing LineSeparator at the end of the generated table. If set to true, it will be omitted, otherwise the table will end with a LineSeparator. Note that this does not apply to any case where InsertTable output is empty (e.g. if given an empty set of data).
- TableBorders controls whether the table will have a border.
- TableHeaders controls whether the first row of data is layed out as headers for the table. They will be separated from the rest of the data with a horizontal rule (or an additional border if TableBorders is also set to true).
- TableCharSet gives the characters to use to represent lines in the table, used for drawing borders. If TableBorders is enabled, the characters in TableCharSet are used to draw the borders. If TableBorders is disabled but TableHeaders is enabled, the characters in TableCharSet are used to draw the horizontal rule separating the headers from the data.
Example ¶
This example shows the creation of a table from data. Options are used to control the table formatting; see InsertTableOpts examples for a demonstration of this.
data := [][]string{ {"John", "Egbert", "Heir", "Breath", "Human"}, {"Kanaya", "Maryam", "Sylph", "Space", "Troll"}, {"Roxy", "Lalonde", "Rogue", "Void", "Human"}, {"Rose", "Lalonde", "Seer", "Light", "Human"}, } const width = 50 const position = 0 ed := Edit("").InsertTable(position, data, width) fmt.Println(ed.String())
Output: John Egbert Heir Breath Human Kanaya Maryam Sylph Space Troll Roxy Lalonde Rogue Void Human Rose Lalonde Seer Light Human
func (Editor) InsertTableOpts ¶ added in v1.2.0
InsertTableOpts creates a table from the provided data using the provided options and inserts it into the text of the Editor.
This is identical to Editor.InsertTable but provides the ability to set Options for the invocation.
Example (TableBorders) ¶
This example shows the use of the TableBorders option to add a border to table output.
data := [][]string{ {"John", "Egbert", "Heir", "Breath", "Human"}, {"Kanaya", "Maryam", "Sylph", "Space", "Troll"}, {"Wayward", "Vagabond", "", "", "Carapacian"}, {"Roxy", "Lalonde", "Rogue", "Void", "Human"}, {"Rose", "Lalonde", "Seer", "Light", "Human"}, {"Caliborn", "", "Lord", "Time", "Cherub"}, } opts := Options{ TableBorders: true, } const width = 65 const position = 0 ed := Edit("").InsertTableOpts(position, data, width, opts) fmt.Println(ed.String())
Output: +-------------+-------------+---------+----------+--------------+ | John | Egbert | Heir | Breath | Human | | Kanaya | Maryam | Sylph | Space | Troll | | Wayward | Vagabond | | | Carapacian | | Roxy | Lalonde | Rogue | Void | Human | | Rose | Lalonde | Seer | Light | Human | | Caliborn | | Lord | Time | Cherub | +-------------+-------------+---------+----------+--------------+
Example (TableBordersAndHeaders) ¶
This example shows how the TableHeaders and TableBorders options can be combined to both add a border and create a header from the first row in the data. The result is slightly different from just setting TableBorders, as when both are set, the headers will be centered within their cells and the header break line is changed to the TableBorders-style horizontal rule.
data := [][]string{ {"Name", "Surname", "Class", "Aspect", "Species"}, {"John", "Egbert", "Heir", "Breath", "Human"}, {"Kanaya", "Maryam", "Sylph", "Space", "Troll"}, {"Wayward", "Vagabond", "", "", "Carapacian"}, {"Roxy", "Lalonde", "Rogue", "Void", "Human"}, {"Rose", "Lalonde", "Seer", "Light", "Human"}, {"Caliborn", "", "Lord", "Time", "Cherub"}, } opts := Options{ TableBorders: true, TableHeaders: true, } const width = 65 const position = 0 ed := Edit("").InsertTableOpts(position, data, width, opts) fmt.Println(ed.String())
Output: +-------------+-------------+---------+----------+--------------+ | NAME | SURNAME | CLASS | ASPECT | SPECIES | +-------------+-------------+---------+----------+--------------+ | John | Egbert | Heir | Breath | Human | | Kanaya | Maryam | Sylph | Space | Troll | | Wayward | Vagabond | | | Carapacian | | Roxy | Lalonde | Rogue | Void | Human | | Rose | Lalonde | Seer | Light | Human | | Caliborn | | Lord | Time | Cherub | +-------------+-------------+---------+----------+--------------+
Example (TableCharSet) ¶
This example shows how to override the character set used to draw table borders and horizontal rules within the table.
borderData := [][]string{ {"John", "Egbert", "Heir", "Breath", "Human"}, {"Kanaya", "Maryam", "Sylph", "Space", "Troll"}, {"Wayward", "Vagabond", "", "", "Carapacian"}, {"Roxy", "Lalonde", "Rogue", "Void", "Human"}, {"Rose", "Lalonde", "Seer", "Light", "Human"}, {"Caliborn", "", "Lord", "Time", "Cherub"}, } opts := Options{ TableBorders: true, // First character is used for corners/intersections // Second character is used for vertical lines // Third character is used for horizontal lines TableCharSet: "#*=", } const width = 65 const position = 0 edBorders := Edit("").InsertTableOpts(position, borderData, width, opts) fmt.Println("With borders:") fmt.Println() fmt.Println(edBorders.String()) // you can also do this for headers only; in this case, the third character // of TableCharSet is used for drawing the horizontal rule: smallDataSet := [][]string{ {"Surname", "Name"}, {"Egbert", "John"}, {"Lalonde", "Rose"}, } // use a smaller width for this one, it's a smaller table const smallTableWidth = 15 opts = opts.WithTableBorders(false).WithTableHeaders(true) edHeaders := Edit("").InsertTableOpts(position, smallDataSet, smallTableWidth, opts) fmt.Println("With headers:") fmt.Println() fmt.Println(edHeaders.String())
Output: With borders: #=============#=============#=========#==========#==============# * John * Egbert * Heir * Breath * Human * * Kanaya * Maryam * Sylph * Space * Troll * * Wayward * Vagabond * * * Carapacian * * Roxy * Lalonde * Rogue * Void * Human * * Rose * Lalonde * Seer * Light * Human * * Caliborn * * Lord * Time * Cherub * #=============#=============#=========#==========#==============# With headers: SURNAME NAME =============== Egbert John Lalonde Rose
Example (TableHeaders) ¶
This example shows the use of the TableHeaders option to set the first row of data apart from the rest with a horizontal rule and to format the first row of data as a header row.
data := [][]string{ {"Aspect", "Class", "Surname", "Name"}, {"Breath", "Heir", "Egbert", "John"}, {"Light", "Seer", "Lalonde", "Rose"}, {"Time", "Knight", "Strider", "Dave"}, {"Space", "Witch", "Harley", "Jade"}, {"Void", "Rogue", "Lalonde", "Roxy"}, {"Heart", "Prince", "Strider", "Dirk"}, {"Hope", "Page", "English", "Jake"}, {"Life", "Maid", "Crocker", "Jane"}, } opts := Options{ TableHeaders: true, } const width = 65 const position = 0 ed := Edit("").InsertTableOpts(position, data, width, opts) fmt.Println(ed.String())
Output: ASPECT CLASS SURNAME NAME ----------------------------------------------------------------- Breath Heir Egbert John Light Seer Lalonde Rose Time Knight Strider Dave Space Witch Harley Jade Void Rogue Lalonde Roxy Heart Prince Strider Dirk Hope Page English Jake Life Maid Crocker Jane
func (Editor) InsertTwoColumns ¶
func (ed Editor) InsertTwoColumns(pos int, leftText string, rightText string, minSpaceBetween int, width int, leftColPercent float64) Editor
InsertTwoColumns builds a two-column layout of side-by-side text from two sequences of text and inserts it into the text of the Editor. The leftText and the rightText do not need any special preparation to be used as the body of each column, as they will be automatically wrapped to fit.
This function has several parameters:
- pos gives the position to insert the columns at within the Editor.
- leftText is the text to put into the left column.
- rightText is the text to put into the right column.
- minSpaceBetween is the amount of space between the two columns at the left column's widest possible length.
- width is how much horizontal space the two columns along with the space between them should be wrapped to.
- leftColPercent is a number from 0.0 to 1.0 that gives how much of the available width (width - minSpaceBetween) the left column should take up. The right column will infer its width from what remains. If leftColPercent is less than 0.0, it will be assumed to be 0.0. If greater than 1.0, it will be assumed to be 1.0.
The minimum width that a column can be is always 2 characters wide.
If the left column ends up taking more vertical space than the right column, the left column will have spaces added on subsequent lines to meet with where the right column would have started if it had had more lines.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This function is affected by the following Options:
- LineSeparator is used to separate each line of the output.
- NoTrailingLineSeparators sets whether to include a trailing LineSeparator at the end of the generated columns. If set to true, it will be omitted, otherwise the columns will end with a LineSeparator.
Example ¶
This example creates two columns from two runs of text.
leftText := "Karkalicious, definition: makes Terezi loco. " leftText += "She wants to know the secrets that she can't " leftText += "taste in my photo." rightText := "A young man stands in his bedroom. It just so happens that " rightText += "today, the 13th of April, 2009, is this young man's birthday. " rightText += "Though it was thirteen years ago he was given life, it is " rightText += "only today he will be given a name!" // insert it at the start of the editor pos := 0 // minimum 3 spaces between each column at their closest point minSpace := 3 // wrap the entire layout to 50 chars width := 50 // make the left column take up 40% of the available space leftPercent := 0.4 ed := Edit("").InsertTwoColumns(pos, leftText, rightText, minSpace, width, leftPercent) fmt.Println(ed.String())
Output: Karkalicious, A young man stands in his definition: makes bedroom. It just so happens Terezi loco. She that today, the 13th of wants to know the April, 2009, is this young secrets that she man's birthday. Though it was can't taste in my thirteen years ago he was photo. given life, it is only today he will be given a name!
func (Editor) InsertTwoColumnsOpts ¶
func (ed Editor) InsertTwoColumnsOpts(pos int, leftText string, rightText string, minSpaceBetween int, width int, leftColPercent float64, opts Options) Editor
InsertTwoColumnsOpts builds a two-column layout of side-by-side text from two sequences of text using the options provided and inserts it into the text of the Editor.
This is identical to Editor.InsertTwoColumns but provides the ability to set Options for the invocation.
Example ¶
This example uses options to tell the Editor to include the HTML tag "<br/>" followed by a literal newline to separate lines in the output columns.
left := "A sample short text run that wraps once." right := "This run of text should also take up 2 lines." pos := 0 minSpace := 3 width := 50 leftPercent := 0.5 opts := Options{ LineSeparator: "<br/>\n", } ed := Edit("").InsertTwoColumnsOpts(pos, left, right, minSpace, width, leftPercent, opts) fmt.Println(ed.String())
Output: A sample short text run This run of text should<br/> that wraps once. also take up 2 lines.<br/>
func (Editor) IsSubEditor ¶
IsSubEditor returns whether the Editor was created to edit a sub-set of the text in some parent editor. Calls to Editor.Lines, Editor.LinesFrom, Editor.LinesTo, Editor.Chars, Editor.CharsFrom, and Editor.CharsTo will result in such an Editor.
If IsSubEditor returns true, then Editor.Text may be set to an incomplete subset of the original text. To get the full text from a sub-editor, use Editor.CommitAll to get the root parent editor with all sub-editor changes applied, including the ones in this sub-editor.
This is a Sub-Editor function. See the note on Editor for more info.
Example ¶
This example shows that only Editors created from a sub-editor producing function will return true for IsSubEditor.
notASubEd := Edit("Hello, world!") subEd := Edit("Sub, Sburb?").CharsFrom(5) fmt.Println(notASubEd.IsSubEditor()) fmt.Println(subEd.IsSubEditor())
Output: false true
func (Editor) Justify ¶
Justify edits the whitespace in each line of the Editor's text such that all words are spaced approximately equally and the line as a whole spans the given width.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This function is affected by the following Options:
- JustifyLastLine is used to determine whether the last line of input text will be justified. The default behavior with JustifyLastLine set to false is to leave the last line alone. If the option is set to true, the last line is justified the same way as every other line. Note that if JustifyLastLine is set to false, Justify will have no effect on an Editor with only 1 line of text.
- LineSeparator is used to separate lines of input.
- ParagraphSeparator is the separator used to split paragraphs. It will only have effect if PreserveParagraphs is set to true.
- PreserveParagraphs gives whether to respect paragraphs instead of considering them text to be justified. If set to true, the text is split into paragraphs by ParagraphSeparator, then the justify is applied to each paragraph.
- NoTrailingLineSeparators specifies whether the function should consider a final instance of LineSeparator to be ending the prior line or giving the start of a new line. If NoTrailingLineSeparators is true, a trailing LineSeparator is considered to start a new (empty) line; additionally, the justify will be called at least once for an empty string. If NoTrailingLineSeparators is set to false and the Editor text is set to an empty string, the justify will not be called even once.
Example ¶
This example shows justification of input text to a length of 60 chars.
input := "Some words that will have spacing justified.\n" input += "This occurs on a per-line basis.\n" input += "Lines closer to the justified length have less adjustment.\n" input += "By default the last line is unmodified." ed := Edit(input) ed = ed.Justify(60) fmt.Println(ed.String())
Output: Some words that will have spacing justified. This occurs on a per-line basis. Lines closer to the justified length have less adjustment. By default the last line is unmodified.
func (Editor) JustifyOpts ¶
JustifyOpts edits the whitespace in each line of the Editor's text such that all words are spaced approximately equally and the line as a whole spans the given width using the provided options.
This is identical to Editor.Justify but provides the ability to set Options for the invocation.
Example (JustifyLastLine) ¶
This example shows the use of options to force the last line to be justified.
input := "Your name is GAMZEE MAKARA. You get pretty\n" input += "excited by CLOWNS OF A GRIM PERSUASION WHICH MAY\n" input += "NOT BE IN FULL POSSESSION OF THEIR MENTAL\n" input += "FACULTIES. You belong to a RATHER OBSCURE CULT,\n" input += "which foretells of a BAND OF ROWDY AND CAPRICIOUS\n" input += "MINSTRELS which will rise one day on a MYTHICAL\n" input += "PARADISE PLANET that does not exist yet." opts := Options{ JustifyLastLine: true, } ed := Edit(input) ed = ed.JustifyOpts(50, opts) fmt.Println(ed.String())
Output: Your name is GAMZEE MAKARA. You get pretty excited by CLOWNS OF A GRIM PERSUASION WHICH MAY NOT BE IN FULL POSSESSION OF THEIR MENTAL FACULTIES. You belong to a RATHER OBSCURE CULT, which foretells of a BAND OF ROWDY AND CAPRICIOUS MINSTRELS which will rise one day on a MYTHICAL PARADISE PLANET that does not exist yet.
Example (ParagraphSeparator) ¶
This example shows the use of options to make the justification respect a rather contrived paragraph splitter of "\nPARA SPLIT\n"
input := "Some words that will have spacing justified.\n" input += "This occurs on a per-line basis.\n" input += "Lines closer to the justified length have less adjustment.\n" input += "By default the last line is unmodified.\n" input += "PARA SPLIT\n" input += "This is a second paragraph that is used to show how\n" input += "paragraphs can be respected with options.\n" input += "And the last paragraph line is still unmodified.\n" opts := Options{ PreserveParagraphs: true, ParagraphSeparator: "\nPARA SPLIT\n", } ed := Edit(input) ed = ed.JustifyOpts(60, opts) fmt.Println(ed.String())
Output: Some words that will have spacing justified. This occurs on a per-line basis. Lines closer to the justified length have less adjustment. By default the last line is unmodified. PARA SPLIT This is a second paragraph that is used to show how paragraphs can be respected with options. And the last paragraph line is still unmodified.
func (Editor) LineCount ¶
LineCount returns the number of lines in the Editor's text. Lines are considered to be split by the currently set LineSeparator in the Editor's Options property; if one has not yet been set, DefaultLineSeparator is used.
By default, an Editor whose text is set to the empty string will cause this function to return 0. This can be altered with the options set on the Editor.
This function is affected by the following Options:
- LineSeparator is used to determine what splits lines to be counted.
- NoTrailingLineSeparators sets whether a trailing LineSeparator should be expected in a full line. If set to true, it will consider the empty string to be a non-terminated line as opposed to 0 lines.
Example ¶
This example shows querying the number of lines for a variety of text.
zeroLinesEd := Edit("") fmt.Println(zeroLinesEd.LineCount()) oneLineEd := Edit("Line 1") fmt.Println(oneLineEd.LineCount()) twoLinesEd := Edit("Line 1\nLine 2") fmt.Println(twoLinesEd.LineCount())
Output: 0 1 2
Example (Options) ¶
This example shows the two different ways currently-set options affect the output of LineCount. In the first case, it shows how NoTrailingLineSeparators affects the number of lines in an empty editor, and the in the second case, it shows the use of a custom LineSeparator to change how lines are counted.
noTrailingOpts := Options{NoTrailingLineSeparators: true} emptyButNoTrailingEd := Edit("").WithOptions(noTrailingOpts) fmt.Println(emptyButNoTrailingEd.LineCount()) customLineOpts := Options{LineSeparator: "<br/>"} customLineEndEd := Edit("Line 1<br/>Line 2").WithOptions(customLineOpts) fmt.Println(customLineEndEd.LineCount())
Output: 1 2
func (Editor) Lines ¶
Lines produces an Editor to operate on a subset of the lines in the Editor's text. The returned Editor operates on text from the nth line up to (but not including) the ith line, where n is start and i is end.
The start or end parameter may be negative, in which case it will be relative to the end of the text; -1 would be the index of the last line, -2 would be the index of the second-to-last line, etc.
If one of the parameters specifies an index that is past the end of the string, that index is assumed to be the end of the string. If either specify an index that is before the start of the string, it is assumed to be 0.
If end is less than start, it is assumed to be equal to start.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This is a Sub-Editor function. See the note on Editor for more info.
This function is affected by the following Options:
- LineSeparator specifies what string should be used to delimit lines.
- NoTrailingLineSeparators specifies whether the function should consider a trailing instance of LineSeparator to end the prior line, or to start a new line. If NoTrailingLineSeparators is true, a trailing LineSeparator is considered to start a new (empty) line.
Example ¶
This example gets a subeditor on the middle three lines of a five-line string.
ed := Edit("Act 1\nAct 2\nAct 3\nAct 4\nAct 5") ed = ed.Lines(1, 4) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(ed.Text)
Output: Act 2 Act 3 Act 4
func (Editor) LinesFrom ¶
LinesFrom produces an Editor to operate on a subset of the lines in the Editor's text. The returned Editor operates on text from the nth line up to the end of the text, where n is start.
Calling this function is identical to calling Editor.Lines with the given start and with end set to the end of the text.
Example ¶
This example gets a subeditor on the last two lines of a five-line string.
ed := Edit("Act 1\nAct 2\nAct 3\nAct 4\nAct 5") ed = ed.LinesFrom(3) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(ed.Text)
Output: Act 4 Act 5
func (Editor) LinesTo ¶
LinesTo produces an Editor to operate on a subset of the characters in the Editor's text. The returned Editor operates on text from the first line up to but not including the nth line, where n is end.
Calling this function is identical to calling Editor.Lines with the given end and with start set to the start of the text.
Example ¶
This example gets a subeditor on the first three lines of a five-line string.
ed := Edit("Act 1\nAct 2\nAct 3\nAct 4\nAct 5") ed = ed.LinesTo(3) // Not doing Editor.String for the example because that would call Commit // and get back the starting string. fmt.Println(ed.Text)
Output: Act 1 Act 2 Act 3
func (Editor) Overtype ¶ added in v0.2.0
Overtype adds characters at the given position, writing over any that already exist. If the added text would extend beyond the current end of the Editor text, the Editor text is extended to make room for it.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
Example ¶
This example uses Overtype to replace a part of a greeting message. This works so nicely in the example because the replacement is the exact same length as the replaced text. If it were of a longer length, it would end up overwriting the text that comes after the replaced text; if it were shorter, it would end up not replacing the entire intended section.
ed := Edit("How are you, Miss Lalonde?") ed = ed.Overtype(4, "goes it") fmt.Println(ed.String())
Output: How goes it, Miss Lalonde?
func (Editor) String ¶
String returns the finished, fully edited string. If the Editor is a sub-editor, CommitAll() is called first and Editor.Text from the resulting editor is returned; otherwise, the current Editor's Text is returned.
Example ¶
This example uses String on a normal Editor to get its text.
ed := Edit("Some text") text := ed.String() fmt.Println(text)
Output: Some text
Example (SubEditor) ¶
This example uses String on a sub-editor to avoid having to explicitly call Editor.Commit or Editor.CommitAll after performing an operation on the sub-editor.
ed := Edit("Act 1\nAct 2\nAct BLAH\nAct 4\nAct 5") subEd := ed.Lines(2, 3) subEd = subEd.Delete(4, 8).Insert(4, "3") fullText := subEd.String() fmt.Println(fullText)
Output: Act 1 Act 2 Act 3 Act 4 Act 5
func (Editor) WithOptions ¶
WithOptions returns an Editor identical to the current one but with its Options replaced by the given Options. This does not affect the Editor it was called on.
This function has the same effect as manually setting Editor.Options but provides a way to do so in a fluent convention.
To get a set of Options that are identical to the current ones but with a single item changed, get the Editor's current Options value and call one of the Options.WithX functions on it.
Example ¶
This example sets the IndentStr property of the Options on the Editor.
ed := Edit("Vriska Serket") ed = ed.WithOptions(ed.Options.WithIndentStr("-->")) fmt.Println(ed.Options.IndentStr)
Output: -->
func (Editor) Wrap ¶
Wrap wraps the Editor text to the given width. All runs of whitespace are collapsed automatically prior to the wrap.
If width is less than 2, it is assumed to be 2 because no meaningful wrap algorithm can be applied to anything smaller.
This function is grapheme-aware and indexes text by human-readable characters, not by the bytes or runes that make it up. See the note on Grapheme-Awareness in the rosed package docs for more info.
This function is affected by the following Options:
- LineSeparator is placed at the end of each wrapped line. In addition, any sequence of LineSeparator that exists in the text prior to calling this function will be treated as whitespace and collapsed into a single space character.
- ParagraphSeparator is the separator used to split paragraphs. It will only have effect if PreserveParagraphs is set to true.
- PreserveParagraphs gives whether to respect paragraphs instead of considering them text to be wrapped. If set to true, the text is first split into paragraphs by ParagraphSeparator, then the wrap is applied to each paragraph.
Example ¶
This example shows wrapping applied to a long string.
ed := Edit("Your name is VRISKA SERKET. You are a master of EXTREME ROLEPLAYING.") ed = ed.Wrap(25) fmt.Println(ed.String())
Output: Your name is VRISKA SERKET. You are a master of EXTREME ROLEPLAYING.
func (Editor) WrapOpts ¶
WrapOpts wraps the Editor text to the given width using the supplied options.
This is identical to Editor.Wrap but provides the ability to set Options for the invocation.
Example ¶
This example uses options to tell the wrap to use a line ending consisting of the HTML tag "<br/>" followed by a new-line, and to respect paragraphs separated by a double "<br/>\n". It also shows how pre-wrapped text will have the hard wraps removed prior to the new wrap.
text := "Your name is VRISKA SERKET.<br/>\n" text += "<br/>\n" text += "You are a master of EXTREME ROLEPLAYING. You can't get enough<br/>\n" text += "of it, or really any game of high stakes and chance. You have<br/>\n" text += "persisted with the habit even in spite of your ACCIDENT. But<br/>\n" text += "then again, you don't have much choice.<br/>\n" text += "<br/>\n" text += "You are something of an APOCALYPSE BUFF, which is something you<br/>\n" text += "can be on Alternia. You are fascinated by end of the world<br/>\n" text += "scenarios." opts := Options{ LineSeparator: "<br/>\n", ParagraphSeparator: "<br/>\n<br/>\n", PreserveParagraphs: true, } ed := Edit(text) ed = ed.WrapOpts(50, opts) fmt.Println(ed.String())
Output: Your name is VRISKA SERKET.<br/> <br/> You are a master of EXTREME ROLEPLAYING. You can't<br/> get enough of it, or really any game of high<br/> stakes and chance. You have persisted with the<br/> habit even in spite of your ACCIDENT. But then<br/> again, you don't have much choice.<br/> <br/> You are something of an APOCALYPSE BUFF, which is<br/> something you can be on Alternia. You are<br/> fascinated by end of the world scenarios.
type LineOperation ¶
LineOperation is a function that accepts a zero-indexed line number and the contents of that line and performs some operation to produce zero or more new lines to replace the contents of the line with.
The return value for a LineOperation is a slice of lines to insert at the old line position. This can be used to delete the line or insert additional new ones; to insert, include the new lines in the returned slice in the proper position relative to the old line in the slice, and to delete the original line, a slice with len < 1 can be returned.
The parameter idx will always be the index of the line before any transformations were applied; e.g. if used in Editor.Apply, a call to a LineOperation with idx = 4 will always be after a call with idx = 3, regardless of the size of the returned slice in the prior call.
type Options ¶
type Options struct { // IndentStr is the string that is used for a single horizontal indent. If // this is set to "", it will be interpreted as though it were set to // DefaultIndentString. IndentStr string // LineSeparator is the string that the Editor considers to signify the // end of a line. If this is set to "", it will be interpreted as though it // were set to DefaultLineSeparator. LineSeparator string // NoTrailingLineSeparators is whether the Editor considers lines to not end // with the separator, and thus would assume that a properly formatted line // does not include a line separator at the end even if it is the last line. // // This has a variety of effects depending on the function that is being // called on an Editor; functions that are affected will call it out in // their documentation. // // If this is set to false (the default), line separator chars are assumed // to signify the end of the line. NoTrailingLineSeparators bool // ParagraphSeparator is the sequence that is considered to separate // paragraphs in the text. Paragraphs are considered to have separators // rather than terminators; i.e. this sequence does not occur at the start // of the first paragraph or at the end of the final paragraph. It may or // may not include LineSeparator as a substring; every mode of operation of // Editor is intended to transparantly handle this case. // // If this is set to "", it will be interpreted as though it were set to // DefaultParagraphSeparator. ParagraphSeparator string // PreserveParagraphs says whether operations that adjust separator // characters (such as wrap) should preserve paragraphs and their // separators. If not set, certain operations may modify paragraph // separators. PreserveParagraphs bool // JustifyLastLine gives whether text justify operations should apply to // the last line of a block of text (or paragraph if PreserveParagraphs is // set to true and is respected). Conventionally, justifications are not // applied to the last line of a block of text and this is the default // behavior. JustifyLastLine bool // TableBorders sets whether created tables draw cell and table borders on // them. TableBorders bool // TableHeaders sets whether table creation functions should consider the // first row of data to be data headers. If so, they will be layed out // separately from the other data and separated by a horizontal rule. TableHeaders bool // TableCharSet is the set of characters used to draw tables. It can be up // to 3 characters long. The first char is used to draw table corners and // line crossings, the second char is used to draw vertical lines, and the // third char is used to draw horizontal lines. // // Any characters beyond the first three are ignored. // // If this is set to "", it will be interpreted as though it were set to // DefaultTableCharSet. If it is set to less than three characters, the // missing characters up to 3 will be filled in from the remaining chars in // DefaultTableCharSet; e.g. setting TableCharSet to "#" will result in an // interpreted TableCharSet of "#|-". TableCharSet string }
Options control the behavior of an Editor. The zero-value is an Options with all members set to defaults.
IndentStr, LineSeparator, ParagraphSeparator, and TableChars have special behavior if not set manually. In a zero-valued Options, each one will be the empty string. When interpreting the options in the course of performing an operation, functions that use those values will treat an empty string as DefaultIndentString, DefaultLineSeparator, DefaultParagraphSeparator, or [DefaultTableChars] respectively.
func (Options) String ¶
String gets the string representation of the Options.
Example ¶
opts := Options{IndentStr: "-->"} str := opts.String() fmt.Println(str)
Output: Options{ParagraphSeparator: "", LineSeparator: "", IndentStr: "-->", NoTrailingLineSeparators: false, PreserveParagraphs: false, JustifyLastLine: false, TableBorders: false, TableHeaders: false, TableCharSet: ""}
func (Options) WithDefaults ¶
WithDefaults returns a copy of the options with all blank members filled with their defaults. Internally, this function is used on user-provided Options structs in order to get ready-to-use copies.
This function does not modify the Options it is called on.
Example ¶
This example shows how WithDefaults can be called to set all currently unset properties to their default values while leaving the set values alone.
opts := Options{ LineSeparator: "<br/>", PreserveParagraphs: true, TableCharSet: "#", } optsDefault := opts.WithDefaults() fmt.Printf("IndentStr: %q\n", optsDefault.IndentStr) fmt.Printf("LineSeparator: %q\n", optsDefault.LineSeparator) fmt.Printf("PreserveParagraphs: %v\n", optsDefault.PreserveParagraphs) // TableCharSet, instead of being all or nothing for settedness, allows the // user to specify fewer characters than are required. If that is the case, // as it was above, additional characters are added to it on a call to // WithDefaults to make a complete char set fmt.Printf("TableCharSet: %q\n", optsDefault.TableCharSet)
Output: IndentStr: "\t" LineSeparator: "<br/>" PreserveParagraphs: true TableCharSet: "#|-"
func (Options) WithIndentStr ¶
WithIndentStr returns a new Options identical to this one but with IndentStr set to str. If str is the empty string, the indent str is interpreted as DefaultIndentString.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ IndentStr: "", } opts = opts.WithIndentStr("-->") fmt.Println(opts.IndentStr)
Output: -->
func (Options) WithJustifyLastLine ¶ added in v1.1.0
WithJustifyLastLine returns a new Options identical to this one but with JustifyLastLine set to justifyLastLine.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ JustifyLastLine: false, } opts = opts.WithJustifyLastLine(true) fmt.Println(opts.JustifyLastLine)
Output: true
func (Options) WithLineSeparator ¶
WithLineSeparator returns a new Options identical to this one but with the LineSeparator member set to sep. If sep is the empty string, the line separator is interpreted as DefaultLineSeparator.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ LineSeparator: "\n", } opts = opts.WithLineSeparator("<br/>") fmt.Println(opts.LineSeparator)
Output: <br/>
func (Options) WithNoTrailingLineSeparators ¶
WithNoTrailingLineSeparators returns a new Options identical to this one but with NoTrailingLineSeparators set to noTrailingLineSeps.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ NoTrailingLineSeparators: false, } opts = opts.WithNoTrailingLineSeparators(true) fmt.Println(opts.NoTrailingLineSeparators)
Output: true
func (Options) WithParagraphSeparator ¶
WithParagraphSeparator returns a new Options identical to this one but with ParagraphSeparator set to sep. If sep is the empty string, the paragraph separator is interpreted as DefaultParagraphSeparator.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ ParagraphSeparator: "\n\n", } opts = opts.WithParagraphSeparator("<P>") fmt.Println(opts.ParagraphSeparator)
Output: <P>
func (Options) WithPreserveParagraphs ¶
WithPreserveParagraphs returns a new Options identical to this one but with PreserveParagraphs set to preserve.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ PreserveParagraphs: false, } opts = opts.WithPreserveParagraphs(true) fmt.Println(opts.PreserveParagraphs)
Output: true
func (Options) WithTableBorders ¶ added in v1.2.0
WithTableBorders returns a new Options identical to this one but with TableBorders set to borders.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ TableBorders: false, } opts = opts.WithTableBorders(true) fmt.Println(opts.TableBorders)
Output: true
func (Options) WithTableCharSet ¶ added in v1.2.0
WithTableCharSet returns a new Options identical to this one but with TableCharSet set to charSet.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ TableCharSet: "123", } opts = opts.WithTableCharSet("@IK") fmt.Println(opts.TableCharSet)
Output: @IK
func (Options) WithTableHeaders ¶ added in v1.2.0
WithTableHeaders returns a new Options identical to this one but with TableHeaders set to headers.
This function does not modify the Options it is called on.
Example ¶
opts := Options{ TableHeaders: false, } opts = opts.WithTableHeaders(true) fmt.Println(opts.TableHeaders)
Output: true
type ParagraphOperation ¶
ParagraphOperation is a function that accepts a zero-indexed paragraph number and the contents of that paragraph and performs some operation to produce zero or more new paragraphs to replace the contents of the paragraph with.
The return value for a ParagraphOperation is a slice of paragraphs to insert at the old paragraph position. This can be used to delete the paragraph or insert additional new ones; to insert, include the new paragraph in the returned slice in the proper position relative to the old paragraph in the slice; to delete the original paragraph, a slice with len < 1 can be returned.
The parameter idx will always be the index of the paragraph before any transformations were applied; e.g. if used in Editor.ApplyParagraphs, a call to a ParagraphOperation with idx = 4 will always be after a call with idx = 3, regardless of the size of the returned slice in the prior call.
The paragraphs may have additional contents at the beginning and end as part of the currently defined ParagraphSeparator. In this case, such content that would come at the start of the paragraph is provided in sepPrefix, and such content that would come at the end of the paragraph is provied in sepSuffix. These values are provided for reference within a ParagraphOperation, but a ParagraphOperation should assume the caller of it will automatically add the separators (which will include the affixes) as needed to the returned paragraph(s).
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
gem
Package gem provides operations for individual user-perceived characters and implements UAX #29 by Unicode for grapheme boundary finding.
|
Package gem provides operations for individual user-perceived characters and implements UAX #29 by Unicode for grapheme boundary finding. |
manip
Package manip contains manipulation primitives used by Editor functions to manipulate text.
|
Package manip contains manipulation primitives used by Editor functions to manipulate text. |
tb
Package tb holds the primitives for working with blocks of gem.String text.
|
Package tb holds the primitives for working with blocks of gem.String text. |