internal

package
v0.1.122 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package internal provides internal implementation details for text input.

Index

Constants

This section is empty.

Variables

View Source
var AsteriskMaskTransformation = NewMaskCodepointTransformation('*')

AsteriskMaskTransformation masks all characters with an asterisk (*).

View Source
var DotMaskTransformation = NewMaskCodepointTransformation('•')

DotMaskTransformation masks all characters with a dot (•).

View Source
var IdentityCodepointTransformation = CodepointTransformationFunc(func(codepointIndex int, codepoint rune) rune {
	return codepoint
})

IdentityCodepointTransformation returns each codepoint unchanged.

View Source
var PasswordMaskTransformation = NewMaskCodepointTransformation('●')

PasswordMaskTransformation masks all characters with the password bullet (●).

Functions

func ApplyCodepointTransformation

func ApplyCodepointTransformation(text string, transform CodepointTransformation) string

ApplyCodepointTransformation applies a CodepointTransformation to a string. Returns the transformed string.

Types

type Change

type Change struct {
	// OriginalStart is the start position in the original text.
	OriginalStart int
	// OriginalEnd is the end position in the original text.
	OriginalEnd int
	// CurrentStart is the start position in the current (modified) text.
	CurrentStart int
	// CurrentEnd is the end position in the current (modified) text.
	CurrentEnd int
}

Change represents a single tracked text change.

type ChangeList

type ChangeList interface {
	// ChangeCount returns the number of discrete changes.
	ChangeCount() int

	// GetRange returns the range in the current (modified) text for the change at index.
	GetRange(changeIndex int) text.TextRange

	// GetOriginalRange returns the range in the original (unmodified) text that was replaced.
	GetOriginalRange(changeIndex int) text.TextRange
}

ChangeList represents a list of non-overlapping, ordered text changes.

This interface is implemented by ChangeTracker and used by InputTransformation to inspect what changes were made during an edit session.

Changes are ordered by their position in the current text. Each change has both a "current" range (position in the modified text) and an "original" range (position in the text before any changes).

type ChangeTracker

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

ChangeTracker implements ChangeList and records changes as they occur.

It maintains a list of non-overlapping changes ordered by position. Adjacent or overlapping changes are merged automatically.

The tracker handles the complexity of maintaining consistent coordinate mappings between the original text and the current text as edits accumulate.

This is a port of androidx.compose.foundation.text.input.internal.ChangeTracker.

func NewChangeTracker

func NewChangeTracker(initialChanges *ChangeTracker) *ChangeTracker

NewChangeTracker creates a new ChangeTracker. If initialChanges is provided, it copies the changes from that tracker.

func (*ChangeTracker) ChangeCount

func (c *ChangeTracker) ChangeCount() int

ChangeCount returns the number of tracked changes.

func (*ChangeTracker) ClearChanges

func (c *ChangeTracker) ClearChanges()

ClearChanges removes all tracked changes.

func (*ChangeTracker) ForEachChange

func (c *ChangeTracker) ForEachChange(fn func(originalRange, currentRange text.TextRange))

ForEachChange calls the given function for each tracked change.

func (*ChangeTracker) GetOriginalRange

func (c *ChangeTracker) GetOriginalRange(changeIndex int) text.TextRange

GetOriginalRange returns the range in the original text for change at index.

func (*ChangeTracker) GetRange

func (c *ChangeTracker) GetRange(changeIndex int) text.TextRange

GetRange returns the range in the current text for change at index.

func (*ChangeTracker) TrackChange

func (c *ChangeTracker) TrackChange(preStart, preEnd, postLength int)

TrackChange records a change at the given position.

Parameters:

  • preStart: Start position in pre-change text (before this change)
  • preEnd: End position in pre-change text (before this change)
  • postLength: Length of the replacement text

The change is merged with existing tracking data if it overlaps or is adjacent.

type CodepointTransformation

type CodepointTransformation interface {
	// Transform maps a codepoint at the given index to another codepoint.
	// The codepoint is represented as a rune in Go.
	Transform(codepointIndex int, codepoint rune) rune
}

CodepointTransformation provides 1:1 codepoint mapping for visual rendering.

This interface maps each codepoint in the input to another codepoint (or the same). The transformation must be 1:1, meaning it preserves text length. This is used for effects like password masking where each character is replaced with a dot.

This is a port of androidx.compose.foundation.text.input.internal.CodepointTransformation.

var SingleLineCodepointTransformation CodepointTransformation = &singleLineCodepointTransformation{}

SingleLineCodepointTransformation converts newlines to spaces and carriage returns to zero-width spaces. This ensures content appears as a single line while preserving text length.

func NewMaskCodepointTransformation

func NewMaskCodepointTransformation(mask rune) CodepointTransformation

NewMaskCodepointTransformation creates a CodepointTransformation that masks all characters with the given rune.

type CodepointTransformationFunc

type CodepointTransformationFunc func(codepointIndex int, codepoint rune) rune

CodepointTransformationFunc is a function type that implements CodepointTransformation.

func (CodepointTransformationFunc) Transform

func (f CodepointTransformationFunc) Transform(codepointIndex int, codepoint rune) rune

Transform implements CodepointTransformation.

type Constraints

type Constraints struct {
	MinWidth  int
	MaxWidth  int
	MinHeight int
	MaxHeight int
}

Constraints represents size constraints for layout.

type GapBuffer

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

GapBuffer provides efficient text editing via a gap-based data structure.

The gap buffer maintains a "gap" (empty space) in the buffer that moves to the insertion/deletion point. This provides O(1) operations near the cursor while maintaining O(n) worst case for distant operations.

This is a port of androidx.compose.foundation.text.input.internal.GapBuffer.

func NewGapBuffer

func NewGapBuffer(text string) *GapBuffer

NewGapBuffer creates a new GapBuffer with the given initial text.

func (*GapBuffer) Append

func (g *GapBuffer) Append(text string)

Append adds text at the end.

func (*GapBuffer) ContentEquals

func (g *GapBuffer) ContentEquals(other string) bool

ContentEquals returns true if the content equals the given string.

func (*GapBuffer) Delete

func (g *GapBuffer) Delete(start, end int)

Delete removes characters from start (inclusive) to end (exclusive).

func (*GapBuffer) Get

func (g *GapBuffer) Get(index int) rune

Get returns the rune at the given index.

func (*GapBuffer) Insert

func (g *GapBuffer) Insert(index int, text string)

Insert adds text at the given index.

func (*GapBuffer) Length

func (g *GapBuffer) Length() int

Length returns the logical length of the text (excluding the gap).

func (*GapBuffer) Replace

func (g *GapBuffer) Replace(start, end int, text string)

Replace replaces text from start to end with the given text.

func (*GapBuffer) String

func (g *GapBuffer) String() string

String returns the complete text content.

func (*GapBuffer) SubSequence

func (g *GapBuffer) SubSequence(start, end int) string

SubSequence returns a substring from start (inclusive) to end (exclusive).

type Key

type Key int

Key represents a keyboard key.

const (
	KeyUnknown Key = iota
	KeyA
	KeyB
	KeyC
	KeyD
	KeyE
	KeyF
	KeyG
	KeyH
	KeyI
	KeyJ
	KeyK
	KeyL
	KeyM
	KeyN
	KeyO
	KeyP
	KeyQ
	KeyR
	KeyS
	KeyT
	KeyU
	KeyV
	KeyW
	KeyX
	KeyY
	KeyZ
	KeyBackspace
	KeyDelete
	KeyTab
	KeyEnter
	KeyEscape
	KeyLeft
	KeyRight
	KeyUp
	KeyDown
	KeyHome
	KeyEnd
	KeyPageUp
	KeyPageDown
)

Common key constants

type KeyCommand

type KeyCommand int

KeyCommand represents a text editing command derived from a key event.

const (
	KeyCommandNone KeyCommand = iota

	// Character manipulation
	KeyCommandDeletePrevChar
	KeyCommandDeleteNextChar
	KeyCommandDeletePrevWord
	KeyCommandDeleteNextWord
	KeyCommandDeleteToLineStart
	KeyCommandDeleteToLineEnd

	// Cursor movement
	KeyCommandMovePrevChar
	KeyCommandMoveNextChar
	KeyCommandMovePrevWord
	KeyCommandMoveNextWord
	KeyCommandMoveLineStart
	KeyCommandMoveLineEnd
	KeyCommandMoveTextStart
	KeyCommandMoveTextEnd
	KeyCommandMovePrevLine
	KeyCommandMoveNextLine
	KeyCommandMovePrevPage
	KeyCommandMoveNextPage

	// Selection
	KeyCommandSelectPrevChar
	KeyCommandSelectNextChar
	KeyCommandSelectPrevWord
	KeyCommandSelectNextWord
	KeyCommandSelectLineStart
	KeyCommandSelectLineEnd
	KeyCommandSelectTextStart
	KeyCommandSelectTextEnd
	KeyCommandSelectPrevLine
	KeyCommandSelectNextLine
	KeyCommandSelectPrevPage
	KeyCommandSelectNextPage
	KeyCommandSelectAll

	// Clipboard
	KeyCommandCopy
	KeyCommandCut
	KeyCommandPaste

	// Undo/Redo
	KeyCommandUndo
	KeyCommandRedo

	// Misc
	KeyCommandNewLine
	KeyCommandTab
)

type KeyEvent

type KeyEvent struct {
	// Key is the key that was pressed (e.g., KeyA, KeyBackspace).
	Key Key

	// Type is whether this is a key down or key up event.
	Type KeyEventType

	// Modifiers indicates which modifier keys were held.
	Modifiers KeyModifiers
}

KeyEvent represents a hardware keyboard event. This is a stub type that would be provided by the platform layer.

type KeyEventType

type KeyEventType int

KeyEventType indicates key press or release.

const (
	KeyEventTypeDown KeyEventType = iota
	KeyEventTypeUp
)

type KeyModifiers

type KeyModifiers struct {
	Ctrl  bool
	Shift bool
	Alt   bool
	Meta  bool // Command on Mac, Windows key on Windows
}

KeyModifiers represents modifier key states.

type LayoutDirection

type LayoutDirection int

LayoutDirection represents text direction (LTR or RTL).

const (
	LayoutDirectionLTR LayoutDirection = iota
	LayoutDirectionRTL
)

type MaskCodepointTransformation

type MaskCodepointTransformation struct {
	Mask rune
}

MaskCodepointTransformation masks all characters with the given rune.

func (*MaskCodepointTransformation) Transform

func (m *MaskCodepointTransformation) Transform(codepointIndex int, codepoint rune) rune

Transform implements CodepointTransformation.

type Offset

type Offset struct {
	X float64
	Y float64
}

Offset represents a 2D position.

type OffsetMappingCalculator

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

OffsetMappingCalculator builds bidirectional offset mappings after edit operations.

This class tracks offset transformations between an original text and a transformed text that has had one or more edit operations applied. It supports mapping offsets in both directions:

  • Forward: original → transformed
  • Reverse: transformed → original

When mappings are ambiguous (e.g., a point mapping to a deleted range), the result is returned as a TextRange indicating all valid mappings.

This is a port of androidx.compose.foundation.text.input.internal.OffsetMappingCalculator.

func NewOffsetMappingCalculator

func NewOffsetMappingCalculator() *OffsetMappingCalculator

NewOffsetMappingCalculator creates a new OffsetMappingCalculator.

func (*OffsetMappingCalculator) MapFromDest

func (o *OffsetMappingCalculator) MapFromDest(offset int) text.TextRange

MapFromDest maps an offset in the transformed string to the corresponding offset or range of offsets in the original string.

func (*OffsetMappingCalculator) MapFromSource

func (o *OffsetMappingCalculator) MapFromSource(offset int) text.TextRange

MapFromSource maps an offset in the original string to the corresponding offset or range of offsets in the transformed string.

func (*OffsetMappingCalculator) RecordEditOperation

func (o *OffsetMappingCalculator) RecordEditOperation(sourceStart, sourceEnd, newLength int)

RecordEditOperation records a replacement from [sourceStart, sourceEnd) with newLength chars.

Parameters:

  • sourceStart: Start of the range being replaced (in source text)
  • sourceEnd: End of the range being replaced (in source text)
  • newLength: Length of the replacement text

func (*OffsetMappingCalculator) Reset

func (o *OffsetMappingCalculator) Reset()

Reset clears all recorded operations.

type PartialGapBuffer

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

PartialGapBuffer wraps text with a localized gap buffer around the cursor.

Unlike GapBuffer, this implementation doesn't convert the entire text to a mutable buffer. Instead, it only converts the cursor-adjacent region, saving construction time and memory for large texts. If editing moves away from the buffer region, the buffer is flushed and a new region is created.

This is a port of androidx.compose.foundation.text.input.internal.PartialGapBuffer.

func NewPartialGapBuffer

func NewPartialGapBuffer(text string) *PartialGapBuffer

NewPartialGapBuffer creates a new PartialGapBuffer with the given text.

func (*PartialGapBuffer) ContentEquals

func (p *PartialGapBuffer) ContentEquals(other string) bool

ContentEquals returns true if the content equals the given string.

func (*PartialGapBuffer) Get

func (p *PartialGapBuffer) Get(index int) rune

Get returns the rune at the given index.

func (*PartialGapBuffer) Length

func (p *PartialGapBuffer) Length() int

Length returns the logical length of the text.

func (*PartialGapBuffer) Replace

func (p *PartialGapBuffer) Replace(start, end int, replacement string)

Replace replaces text from start to end with the given string.

func (*PartialGapBuffer) String

func (p *PartialGapBuffer) String() string

String returns the complete text content.

func (*PartialGapBuffer) SubSequence

func (p *PartialGapBuffer) SubSequence(start, end int) string

SubSequence returns a substring from start (inclusive) to end (exclusive).

type Size

type Size struct {
	Width  int
	Height int
}

Size represents dimensions.

type TextFieldKeyEventHandler

type TextFieldKeyEventHandler interface {
	// HandleKeyEvent processes a key event and returns whether it was consumed.
	//
	// Parameters:
	//   - event: The keyboard event
	//   - state: The transformed text field state
	//   - textLayoutState: The text layout state for cursor positioning
	//
	// Returns true if the event was handled, false to propagate it.
	HandleKeyEvent(
		event KeyEvent,
		state TransformedTextFieldStateInterface,
		textLayoutState TextLayoutState,
	) bool
}

TextFieldKeyEventHandler processes keyboard events for text fields.

This is a stub interface that documents the operational semantics. A full implementation requires platform-specific key mapping and integration with the text editing commands.

Operational Semantics:

Character Input:

  • Printable characters are inserted at the cursor
  • If selection exists, it is replaced

Navigation Keys:

  • Left/Right: Move cursor one character
  • Shift+Left/Right: Extend selection by one character
  • Ctrl+Left/Right: Move cursor by word
  • Ctrl+Shift+Left/Right: Extend selection by word
  • Home/End: Move to line start/end
  • Ctrl+Home/End: Move to text start/end
  • Up/Down: Move to previous/next line (multi-line only)

Deletion Keys:

  • Backspace: Delete character before cursor (or selection)
  • Delete: Delete character after cursor (or selection)
  • Ctrl+Backspace: Delete word before cursor
  • Ctrl+Delete: Delete word after cursor

Selection and Clipboard:

  • Ctrl+A: Select all
  • Ctrl+C: Copy selection
  • Ctrl+X: Cut selection
  • Ctrl+V: Paste from clipboard

Undo/Redo:

  • Ctrl+Z: Undo
  • Ctrl+Shift+Z or Ctrl+Y: Redo

Platform Variations:

  • On Mac, Cmd replaces Ctrl for most shortcuts
  • Some platforms have additional shortcuts

This is a port of key handling logic from androidx.compose.foundation.text.input.internal.TextFieldDecoratorModifier.

type TextLayoutResult

type TextLayoutResult struct {
	// Stub - would include size, line info, bounding boxes, etc.
	Size Size
}

TextLayoutResult contains the result of text layout.

type TextLayoutState

type TextLayoutState interface {
	// UpdateNonMeasureInputs updates properties that don't require re-measurement.
	// Called when text field properties change outside the measure phase.
	//
	// Parameters:
	//   - textFieldState: The transformed text field state
	//   - textStyle: The text style to apply
	//   - singleLine: Whether the field is single-line
	//   - softWrap: Whether to enable soft wrapping
	UpdateNonMeasureInputs(
		textFieldState TransformedTextFieldStateInterface,
		textStyle TextStyle,
		singleLine bool,
		softWrap bool,
	)

	// LayoutWithNewMeasureInputs performs layout and returns the result.
	// Called during measure phase with current constraints.
	//
	// Parameters:
	//   - density: The display density
	//   - layoutDirection: LTR or RTL
	//   - constraints: Size constraints for the layout
	//
	// Returns the text layout result which contains:
	//   - Measured size
	//   - Line information
	//   - Bounding boxes for text ranges
	LayoutWithNewMeasureInputs(
		density float64,
		layoutDirection LayoutDirection,
		constraints Constraints,
	) TextLayoutResult

	// GetOffsetForPosition converts a screen position to a text offset.
	// Returns the character offset closest to the position.
	// Returns -1 if layout has not been performed.
	//
	// Parameters:
	//   - position: Position in decoration box coordinates
	//   - coerceInVisibleBounds: If true, coerce position to visible text bounds
	GetOffsetForPosition(position Offset, coerceInVisibleBounds bool) int

	// IsPositionOnText returns true if the position is over rendered text.
	// Returns false if position is in empty space left/right of text.
	IsPositionOnText(position Offset) bool

	// CoercedInVisibleBoundsOfInputText coerces a position to visible text bounds.
	// Used when clicks happen outside the visible inner text field.
	CoercedInVisibleBoundsOfInputText(offset Offset) Offset
}

TextLayoutState manages text layout for TextField.

This is a stub interface that documents the operational semantics. A full implementation requires integration with the text layout engine.

Operational Semantics:

  • Caches TextLayoutResult for efficient re-layout
  • Manages coordinate translations between decoration box and inner text
  • Provides offset↔position conversion for gesture handling
  • Updates when text, style, or constraints change

Coordinate Spaces:

  • Window coordinates: Absolute screen position
  • Decoration coordinates: Relative to the decorated text field container
  • TextLayout coordinates: Relative to the text layout rectangle
  • Core coordinates: Internal text rendering coordinates

This is a port of androidx.compose.foundation.text.input.internal.TextLayoutState.

type TextStyle

type TextStyle struct {
}

TextStyle represents text styling configuration. This would be imported from compose/ui/text in a full implementation.

type TransformedTextFieldStateInterface

type TransformedTextFieldStateInterface interface {
	OutputText() *text.TextRange
	VisualText() string
}

TransformedTextFieldStateInterface is the interface for transformed state. See TransformedTextFieldState for the full implementation requirements.

Directories

Path Synopsis
Package selection provides selection state management for text fields.
Package selection provides selection state management for text fields.
Package undo provides undo/redo infrastructure for text editing.
Package undo provides undo/redo infrastructure for text editing.

Jump to

Keyboard shortcuts

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