gvcode

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2025 License: MIT Imports: 32 Imported by: 2

README

gvcode

gvcode is a Gio based text editor for code editing.

Key Features:

  • Uses a PieceTable backed text buffer for efficient text editing.
  • Optimized undo/redo operations with built-in support in the PieceTable.
  • Supports both hard and soft tabs, ensuring alignment with tab stops.
  • Lines can be unwrapped, with horizontal scrolling supported.
  • Syntax highlighting is available by applying text styles.
  • Built-in line numbers for better readability.
  • Auto-complete of bracket pairs and quote pairs.
  • Auto-indent new lines.
  • Bracket auto-indent.
  • Increase or descease indents of multi-lines using Tab key and Shift+Tab.
  • Expanded shortcuts support (Work in Progress).
  • Large file rendering(Planned).

Why another code editor?

I ported Gio's editor component to gioview and added a few features to support basic code editing, but it is far from a good code editor. Keep expanding the original editor seems a wise decision, but the design of the original editor makes it hard to adding more features. And it is also not performant enough for large file editing/rendering. Most importantly it lacks tab/tab stop support. When I tried to add tab stop support to it, I found it needs a new overall design, so there is gvcode.

Key Design

Gio's text shaper layout the whole document in one pass, although internally the document is processed by paragraphs. After the shaping flow, there is a iterator style API to get the shaped glyphs one by one. This is what Gio's editor does when layouting the texts.

Gvcode has chosen another way. gvcode read and layout in a paragraph by paragrah manner. The outcomes are joined together to assemble the final document view. This gives up the oppertunity to process the text only visible in the viewport, making incremental shaping possible. Besides that we can also process tab expanding & tab stops at line level, because we have full control of the paragraph layout. To achive that goal, gvcode implemented its own line wrapper.

How To Use

Gvcode exports simple APIs to ease the integration with your project. Here is a basic example:

    state := &editor.Editor{}
	var ops op.Ops

	for {
		e := ed.window.Event()

		switch e := e.(type) {
		case app.DestroyEvent:
			return e.Err
		case app.FrameEvent:
			gtx := app.NewContext(&ops, e)
			
            es := gvcode.NewEditor(th, state)
            es.Font.Typeface = "monospace"
            es.TextSize = unit.Sp(12)
            es.LineHeightScale = 1.5
			es.Layout(gtx)

			e.Frame(gtx.Ops)
		}
	}

For a full working example, please see code in the folder ./example.

Cautions

gvcode is not intended to be a drop-in replacement for the official Editor widget as it dropped some features such as single line mode, truncator and max lines limit.

This project is a work in progress, and the APIs may change as development continues. Please use it at your own risk.

Contributing

See the contribution guide for details.

Acknowledgments

This project uses code from the Gio project, which is licensed under the Unlicense OR MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetDebug added in v0.1.0

func SetDebug(enable bool)

SetDebug enable or disable the debug mode. In debug mode, internal buffer state is printed.

Types

type BeforeInsertHook added in v0.1.0

type BeforeInsertHook func(start, end int, text string) string

BeforeInsertHook defines a hook to be called before the editor insert characters, usually via keyboard input. cursor position, previous word

type BeforePasteHook added in v0.1.0

type BeforePasteHook func(text string) string

BeforePasteHook defines a hook to be called before pasting text to transform the text.

type ChangeEvent added in v0.0.2

type ChangeEvent struct{}

A ChangeEvent is generated for every user change to the text.

type Editor added in v0.0.2

type Editor struct {
	// LineNumberGutter specifies the gap between the line number and the main text.
	LineNumberGutter unit.Dp
	// Color used to paint text
	TextMaterial op.CallOp
	// Color used to highlight the selections.
	SelectMaterial op.CallOp
	// Color used to highlight the current paragraph.
	LineMaterial op.CallOp
	// Color used to paint the line number
	LineNumberMaterial op.CallOp
	// Color used to highlight the text snippets, such as search matches.
	TextHighlightMaterial op.CallOp
	// contains filtered or unexported fields
}

Editor implements an editable and scrollable text area.

func (*Editor) CaretCoords added in v0.0.2

func (e *Editor) CaretCoords() f32.Point

CaretCoords returns the coordinates of the caret, relative to the editor itself.

func (*Editor) CaretPos added in v0.0.2

func (e *Editor) CaretPos() (line, col int)

CaretPos returns the line & column numbers of the caret.

func (*Editor) ClearSelection added in v0.0.2

func (e *Editor) ClearSelection()

ClearSelection clears the selection, by setting the selection end equal to the selection start.

func (*Editor) Delete added in v0.0.2

func (e *Editor) Delete(graphemeClusters int) (deletedRunes int)

Delete runes from the caret position. The sign of the argument specifies the direction to delete: positive is forward, negative is backward.

If there is a selection, it is deleted and counts as a single grapheme cluster.

func (*Editor) DeleteLine added in v0.1.0

func (e *Editor) DeleteLine() (deletedRunes int)

DeleteLine delete the current line, and place the caret at the start of the next line.

func (*Editor) Insert added in v0.0.2

func (e *Editor) Insert(s string) (insertedRunes int)

func (*Editor) InsertLine added in v0.1.0

func (e *Editor) InsertLine(s string) (insertedRunes int)

InsertLine insert a line of text before the current line, and place the caret at the start of the current line.

This single line insertion is mainly for paste operation after copying/cutting the current line(paragraph) when there is no selection, but it can also used outside of the editor to insert a entire line(paragraph).

func (*Editor) Layout added in v0.0.2

func (e *Editor) Layout(gtx layout.Context, lt *text.Shaper) layout.Dimensions

func (*Editor) Len added in v0.0.2

func (e *Editor) Len() int

Len is the length of the editor contents, in runes.

func (*Editor) MoveCaret added in v0.0.2

func (e *Editor) MoveCaret(startDelta, endDelta int)

MoveCaret moves the caret (aka selection start) and the selection end relative to their current positions. Positive distances moves forward, negative distances moves backward. Distances are in grapheme clusters, which closely match what users perceive as "characters" even when the characters are multiple code points long.

func (*Editor) ReadOnly added in v0.0.2

func (e *Editor) ReadOnly() bool

func (*Editor) ReplaceAll added in v0.0.2

func (e *Editor) ReplaceAll(texts []TextRange, newStr string) int

ReplaceAll replaces all texts specifed in TextRange with newStr. It returns the number of occurrences replaced.

func (*Editor) ScrollByRatio added in v0.0.2

func (e *Editor) ScrollByRatio(gtx layout.Context, ratio float32)

func (*Editor) SelectedText added in v0.0.2

func (e *Editor) SelectedText() string

SelectedText returns the currently selected text (if any) from the editor.

func (*Editor) Selection added in v0.0.2

func (e *Editor) Selection() (start, end int)

Selection returns the start and end of the selection, as rune offsets. start can be > end.

func (*Editor) SelectionLen added in v0.0.2

func (e *Editor) SelectionLen() int

SelectionLen returns the length of the selection, in runes; it is equivalent to utf8.RuneCountInString(e.SelectedText()).

func (*Editor) SetCaret added in v0.0.2

func (e *Editor) SetCaret(start, end int)

SetCaret moves the caret to start, and sets the selection end to end. start and end are in runes, and represent offsets into the editor text.

func (*Editor) SetHighlights added in v0.0.2

func (e *Editor) SetHighlights(highlights []TextRange)

SetHighlights sets the texts to be highlighted.

func (*Editor) SetText added in v0.0.2

func (e *Editor) SetText(s string)

func (*Editor) TabStyle added in v0.1.1

func (e *Editor) TabStyle() (TabStyle, int)

func (*Editor) Text added in v0.0.2

func (e *Editor) Text() string

Text returns the contents of the editor.

func (*Editor) Update added in v0.0.2

func (e *Editor) Update(gtx layout.Context) (EditorEvent, bool)

Update the state of the editor in response to input events. Update consumes editor input events until there are no remaining events or an editor event is generated. To fully update the state of the editor, callers should call Update until it returns false.

func (*Editor) UpdateTextStyles added in v0.0.2

func (e *Editor) UpdateTextStyles(styles []*TextStyle)

func (*Editor) ViewPortRatio added in v0.0.2

func (e *Editor) ViewPortRatio() (float32, float32)

returns start and end offset ratio of viewport

func (*Editor) WithOptions added in v0.1.0

func (e *Editor) WithOptions(opts ...EditorOption)

WithOptions applies various options to configure the editor.

type EditorEvent added in v0.0.2

type EditorEvent interface {
	// contains filtered or unexported methods
}

type EditorOption added in v0.1.0

type EditorOption func(*Editor)

EditorOption defines a function to configure the editor.

func AddBeforeInsertHook added in v0.1.0

func AddBeforeInsertHook(hook BeforeInsertHook) EditorOption

func AddBeforePasteHook added in v0.1.0

func AddBeforePasteHook(hook BeforePasteHook) EditorOption

func ReadOnlyMode added in v0.1.0

func ReadOnlyMode(enabled bool) EditorOption

ReadOnlyMode controls whether the contents of the editor can be altered by user interaction. If set to true, the editor will allow selecting text and copying it interactively, but not modifying it.

func WithBracketPairs added in v0.1.1

func WithBracketPairs(bracketPairs map[rune]rune) EditorOption

WithBracketPairs configures a set of bracket pairs that can be auto-completed when the left half is entered.

func WithQuotePairs added in v0.1.1

func WithQuotePairs(quotePairs map[rune]rune) EditorOption

WithQuotePairs configures a set of quote pairs that can be auto-completed when the left half is entered.

func WithShaperParams added in v0.1.0

func WithShaperParams(font font.Font, textSize unit.Sp, alignment text.Alignment, lineHeight unit.Sp, lineHeightScale float32) EditorOption

WithShaperParams set the basic shaping params for the editor.

func WithSoftTab added in v0.1.0

func WithSoftTab(enabled bool) EditorOption

WithSoftTab controls the behaviour when user try to insert a Tab character. If set to true, the editor will insert the amount of space characters specified by TabWidth, else the editor insert a \t character.

func WithTabWidth added in v0.1.0

func WithTabWidth(tabWidth int) EditorOption

WithTabWidth set how many spaces to represent a tab character. In the case of soft tab, this determines the number of space characters to insert into the editor. While for hard tab, this controls the maximum width of the 'tab' glyph to expand to.

func WithWordSeperators added in v0.1.0

func WithWordSeperators(seperators string) EditorOption

WithWordSeperators configures a set of characters that will be used as word separators when doing word related operations, like navigating or deleting by word.

func WrapLine added in v0.1.0

func WrapLine(enabled bool) EditorOption

WrapLine configures whether the displayed text will be broken into lines or not.

type Region added in v0.0.2

type Region = lt.Region

Region describes the position and baseline of an area of interest within shaped text.

type SelectEvent added in v0.0.2

type SelectEvent struct{}

A SelectEvent is generated when the user selects some text, or changes the selection (e.g. with a shift-click), including if they remove the selection. The selected text is not part of the event, on the theory that it could be a relatively expensive operation (for a large editor), most applications won't actually care about it, and those that do can call Editor.SelectedText() (which can be empty).

type TabStyle added in v0.1.1

type TabStyle uint8
const (
	Tabs TabStyle = iota
	Spaces
)

func GuessIndentation added in v0.1.1

func GuessIndentation(text string) (TabStyle, bool, int)

GuessIndentation guesses which kind of indentation the editor is using, returing the kind, if mixed indent is used, and the indent size in the case if spaces indentation.

type TextRange added in v0.0.2

type TextRange struct {
	// offset of the start rune in the document.
	Start int
	// offset of the end rune in the document.
	End int
}

TextRange contains the range of text of interest in the document. It can used for search, styling text, or any other purposes.

type TextStyle added in v0.0.2

type TextStyle struct {
	TextRange
	// Color of the text..
	Color op.CallOp
	// Background color of the painted text in the range.
	Background op.CallOp
}

TextStyle defines style for a range of text in the document.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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