core/text/edit
text_edit
Types
5Command
Command :: enum u32 {
None = 0,
Undo = 1,
Redo = 2,
New_Line = 3, // multi-lines
Cut = 4,
Copy = 5,
Paste = 6,
Select_All = 7,
Backspace = 8,
Delete = 9,
Delete_Word_Left = 10,
Delete_Word_Right = 11,
Left = 12,
Right = 13,
Up = 14, // multi-lines
Down = 15, // multi-lines
Word_Left = 16,
Word_Right = 17,
Start = 18,
End = 19,
Line_Start = 20,
Line_End = 21,
Select_Left = 22,
Select_Right = 23,
Select_Up = 24, // multi-lines
Select_Down = 25, // multi-lines
Select_Word_Left = 26,
Select_Word_Right = 27,
Select_Start = 28,
Select_End = 29,
Select_Line_Start = 30,
Select_Line_End = 31,
}SourceCommand_Set
Command_Set :: bit_set[Command; u32]SourceState
State :: struct {
selection: [2]int,
line_start: int,
line_end: int,
// initialized each "frame" with `begin`
builder: ^strings.Builder,
up_index: int,
down_index: int,
translate_by_grapheme: bool,
// undo
undo: [dynamic]^Undo_State,
redo: [dynamic]^Undo_State,
undo_text_allocator: runtime.Allocator,
id: u64,
// Timeout information
current_time: time.Tick,
last_edit_time: time.Tick,
undo_timeout: time.Duration,
// Set these if you want cut/copy/paste functionality
set_clipboard: proc(user_data: rawptr, text: string) -> (ok: bool),
user_data: rawptr,
text: string,
ok: bool,
get_clipboard: proc(user_data: rawptr) -> (text: string, ok: bool),
user_data: rawptr,
text: string,
ok: bool,
clipboard_user_data: rawptr,
}SourceTranslation
Translation :: enum u32 {
Start = 0,
End = 1,
Left = 2,
Right = 3,
Up = 4,
Down = 5,
Word_Left = 6,
Word_Right = 7,
Word_Start = 8,
Word_End = 9,
Soft_Line_Start = 10,
Soft_Line_End = 11,
}SourceUndo_State
Undo_State :: struct {
selection: [2]int,
len: int,
text: [0]u8,
}SourceConstants
2DEFAULT_UNDO_TIMEOUT
DEFAULT_UNDO_TIMEOUT :: _ = 300 * time.MillisecondSourceMULTILINE_COMMANDS
MULTILINE_COMMANDS :: Command_Set = Command_Set{.New_Line, .Up, .Down, .Select_Up, .Select_Down}SourceProcedures
29begin
begin :: proc(s: ^State, id: u64, builder: ^strings.Builder)SourceCall at the beginning of each frame
clear_all
clear_all :: proc(s: ^State) -> (cleared: bool)Sourcereturns true when the builder had content to be cleared clear builder&selection and the undo|redo stacks
copy
copy :: proc(s: ^State) -> (bool)Sourcetry and copy the currently selected text to the clipboard State.set_clipboard needs to be assigned
current_selected_text
current_selected_text :: proc(s: ^State) -> (string)Sourcereturn the currently selected text
cut
cut :: proc(s: ^State) -> (bool)Sourcecopy & delete the current selection when copy() succeeds
delete_to
delete_to :: proc(s: ^State, t: Translation)SourceDeletes everything between the caret and resultant position
destroy
destroy :: proc(s: ^State)Sourceclear undo|redo strings and delete their stacks
end
end :: proc(s: ^State)SourceCall at the end of each frame
has_selection
has_selection :: proc(s: ^State) -> (bool)Sourcetrue if selection head and tail dont match and form a selection of multiple characters
init
init :: proc(s: ^State, undo_text_allocator: runtime.Allocator, undo_state_allocator: runtime.Allocator, undo_timeout = DEFAULT_UNDO_TIMEOUT)Sourceinit the state to some timeout and set the respective allocators
- undo_state_allocator dictates the dynamic undo|redo arrays allocators
- undo_text_allocator is the allocator which allocates strings only
input_rune
input_rune :: proc(s: ^State, r: rune)Sourceinsert a single rune into the edit state - deletes the current selection
input_runes
input_runes :: proc(s: ^State, text: []rune)Sourceinsert slice of runes into the edit state - deletes the current selection
input_text
input_text :: proc(s: ^State, text: string) -> (int)Sourceinsert text into the edit state - deletes the current selection
insert
insert :: proc(s: ^State, at: int, text: string) -> (int)Sourceinsert a single rune into the edit state - deletes the current selection
is_continuation_byte
is_continuation_byte :: proc(b: u8) -> (bool)Sourcemove_to
move_to :: proc(s: ^State, t: Translation)SourceMoves the position of the caret (both sides of the selection)
paste
paste :: proc(s: ^State) -> (bool)Sourcereinsert whatever the get_clipboard would return State.get_clipboard needs to be assigned
perform_command
perform_command :: proc(s: ^State, cmd: Command)Sourceremove
remove :: proc(s: ^State, lo: int, hi: int)Sourceremove the wanted range withing, usually the selection within byte indices
select_to
select_to :: proc(s: ^State, t: Translation)SourceMoves only the head of the selection and leaves the tail uneffected
selection_delete
selection_delete :: proc(s: ^State)Sourcedelete the current selection range and set the proper selection afterwards
setup_once
setup_once :: proc(s: ^State, builder: ^strings.Builder)Sourcesetup the builder, selection and undo|redo state once allowing to retain selection
sorted_selection
sorted_selection :: proc(s: ^State) -> (lo: int, hi: int)Sourcereturn the clamped lo/hi of the current selection since the selection[0] moves around and could be ahead of selection[1] useful when rendering and needing left->right
translate_position
translate_position :: proc(s: ^State, t: Translation) -> (int)Sourcetranslates the caret position
undo
undo :: proc(s: ^State, undo: ^[dynamic]^Undo_State, redo: ^[dynamic]^Undo_State)Sourcepop undo|redo state - push to redo|undo - set selection & text
undo_check
undo_check :: proc(s: ^State)Sourceclear redo stack and check if the undo timeout gets hit
undo_clear
undo_clear :: proc(s: ^State, undo: ^[dynamic]^Undo_State)Sourceiteratively clearn the undo|redo stack and free each allocated text state
undo_state_push
undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> (mem.Allocator_Error)Sourcepush current text state to the wanted undo|redo stack
update_time
update_time :: proc(s: ^State)Sourceupdate current time so "insert" can check for timeouts