Struct EditorSession

Source
pub struct EditorSession {
    pub buffer: TextBuffer,
    pub edit: TextEditState,
    pub config: EditorConfig,
    pub click_state: EditorClickState,
}
Expand description

Mutable editor session state: text buffer plus edit, viewport, and click state.

§Examples

use ailloli_ui_editor::{EditorSession, EditorWrapMode};
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::from_string("hello"));
assert_eq!(session.buffer.as_str(), "hello");
assert_eq!(session.config.wrap_mode, EditorWrapMode::SoftWrap);
assert_eq!(session.edit.caret_byte, 0);

Fields§

§buffer: TextBuffer

Editable rope-backed UTF-8 buffer.

§edit: TextEditState

Caret, selection, IME, scroll, drag, and undo/redo state.

§config: EditorConfig

Current style and wrapping policy.

§click_state: EditorClickState

Multi-click recognition history.

Implementations§

Source§

impl EditorSession

Applies input and configuration transitions to an editor session.

Source

pub fn new(buffer: TextBuffer) -> Self

Creates a session with default configuration and empty edit/click state.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::from_string("abc"));
assert_eq!(session.edit.caret_byte, 0);
assert_eq!(session.buffer.as_str(), "abc");
Source

pub fn with_config(buffer: TextBuffer, config: EditorConfig) -> Self

Creates a session with an explicit configuration.

Edit and click state still start empty; configuration is stored verbatim.

§Examples
use ailloli_ui_editor::{EditorConfig, EditorSession, EditorWrapMode};
use ailloli_ui_text::TextBuffer;
let config = EditorConfig { wrap_mode: EditorWrapMode::NoWrap, ..EditorConfig::default() };
let session = EditorSession::with_config(TextBuffer::new(), config);
assert_eq!(session.config.wrap_mode, EditorWrapMode::NoWrap);
Source

pub fn set_config(&mut self, config: EditorConfig) -> bool

Replaces configuration when different.

Returns false for exact equality. Switching to soft wrap also forces horizontal scroll to zero; switching to no-wrap preserves it. An equal soft-wrap configuration does not repair a manually nonzero scroll value.

§Examples
use ailloli_ui_editor::{EditorConfig, EditorSession, EditorWrapMode};
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::new());
session.edit.scroll_x = 20.0;
let nowrap = EditorConfig { wrap_mode: EditorWrapMode::NoWrap, ..EditorConfig::default() };
assert!(session.set_config(nowrap));
assert_eq!(session.edit.scroll_x, 20.0);
assert!(session.set_config(EditorConfig::default()));
assert_eq!(session.edit.scroll_x, 0.0);
Source

pub fn replace_buffer_if_changed(&mut self, buffer: TextBuffer) -> bool

Replaces the buffer only when its text differs.

Equal text returns false and retains the existing buffer, even if the supplied buffer has different internal revisions. A replacement clamps generic edit state to valid UTF-8 bounds.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("long"));
session.edit.caret_byte = 4;
assert!(session.replace_buffer_if_changed(TextBuffer::from_string("x")));
assert_eq!(session.edit.caret_byte, 1);
assert!(!session.replace_buffer_if_changed(TextBuffer::from_string("x")));
Source

pub fn apply_edit_action( &mut self, action: TextEditAction, ) -> EditorInputOutcome

Applies one text-edit action and returns its neutral side effects.

Buffer mutation, undo/redo, selection, IME, and clipboard semantics are inherited from [TextEditState::apply].

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::{TextBuffer, TextEditAction};
let mut session = EditorSession::new(TextBuffer::new());
let outcome = session.apply_edit_action(TextEditAction::InsertText { text: "hi".into() });
assert!(outcome.text_changed);
assert_eq!(session.buffer.as_str(), "hi");
Source

pub fn scroll_by(&mut self, delta: Offset, metrics: ScrollMetrics) -> bool

Applies a logical-pixel scroll delta and clamps it to content metrics.

Soft wrap disables horizontal movement. Returns whether either stored offset changed; non-finite values are normalized by scroll primitives.

§Examples
use ailloli_ui_core::{Offset, ScrollMetrics, Size};
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::new());
let metrics = ScrollMetrics::new(Size::new(100.0, 50.0), Size::new(100.0, 200.0));
assert!(session.scroll_by(Offset::new(20.0, 30.0), metrics));
assert_eq!((session.edit.scroll_x, session.edit.scroll_y), (0.0, 30.0));
Source

pub fn begin_pointer_selection(&mut self, byte: usize, extend: bool) -> bool

Starts pointer selection and moves or extends the caret.

drag_anchor stores the supplied byte verbatim, while the caret setter clamps backward to a valid UTF-8 boundary. Returns whether caret, selection, or desired horizontal position changed; setting only a new drag anchor can therefore return false.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("abc"));
session.begin_pointer_selection(2, false);
assert_eq!(session.edit.drag_anchor, Some(2));
assert_eq!(session.edit.caret_byte, 2);
Source

pub fn update_pointer_selection(&mut self, anchor: usize, byte: usize)

Updates a drag selection from supplied byte offsets.

Both offsets are stored verbatim in [TextSelection]. The separate edit.caret_byte is numerically clamped to buffer length but not repaired to a UTF-8 boundary. Hit-test callers must therefore provide valid, in-range boundaries. This method reports no change flag and does not modify drag_anchor or desired_x.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("abc"));
session.update_pointer_selection(1, 99);
assert_eq!(session.edit.selection.unwrap().normalized(), (1, 99));
assert_eq!(session.edit.caret_byte, 3);
Source

pub fn end_pointer_selection(&mut self) -> bool

Ends an active pointer drag.

Returns true only when a drag anchor was present. Selection and caret remain unchanged.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("abc"));
session.begin_pointer_selection(1, false);
assert!(session.end_pointer_selection());
assert!(!session.end_pointer_selection());
Source

pub fn register_pointer_click( &mut self, now: Instant, pos: Point, byte: usize, zone: EditorClickZone, ) -> u8

Registers a click using a process-local monotonic Instant.

Returns a count in 1..=3. A sequence continues only within 500 ms and four logical pixels at the identical byte and zone. Legacy and explicit event timestamps never mix into one sequence.

§Examples
use std::time::Instant;
use ailloli_ui_core::Point;
use ailloli_ui_editor::{EditorClickZone, EditorSession};
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::new());
let now = Instant::now();
assert_eq!(session.register_pointer_click(now, Point::new(0.0, 0.0), 0, EditorClickZone::Text), 1);
assert_eq!(session.register_pointer_click(now, Point::new(4.0, 0.0), 0, EditorClickZone::Text), 2);
Source

pub fn register_pointer_click_at( &mut self, timestamp: Duration, pos: Point, byte: usize, zone: EditorClickZone, ) -> u8

Registers a click using a provider-neutral monotonic event timestamp.

This is the deterministic counterpart to Self::register_pointer_click for hosts that attach an explicit timestamp to each input event. Backward timestamps reset the sequence. Counts saturate at three.

§Examples
use std::time::Duration;
use ailloli_ui_core::Point;
use ailloli_ui_editor::{EditorClickZone, EditorSession};
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::new());
for expected in [1, 2, 3, 3] {
    let count = session.register_pointer_click_at(Duration::from_millis(expected as u64), Point::new(0.0, 0.0), 0, EditorClickZone::Text);
    assert_eq!(count, expected.min(3));
}
Source

pub fn select_word_at_byte( &mut self, byte: usize, syntax_tokens: Option<&[SyntaxToken]>, language: EditorLanguage, ) -> bool

Selects a syntax token or lexical word around a byte offset.

If no selectable unit exists, this instead moves the caret and clears selection. Otherwise selection is ordered start-to-end and the caret is placed at its end. Returns whether editor state changed.

§Examples
use ailloli_ui_editor::{EditorLanguage, EditorSession};
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("hello world"));
assert!(session.select_word_at_byte(7, None, EditorLanguage::PlainText));
assert_eq!(session.edit.selection.unwrap().normalized(), (6, 11));
Source

pub fn select_line_at_byte(&mut self, byte: usize) -> bool

Selects the logical line containing a byte, excluding its newline.

The byte is clamped to a UTF-8 boundary by the line selector. The caret moves to the range end and drag/desired-x state is cleared. Returns whether those stored values changed.

§Examples
use ailloli_ui_editor::EditorSession;
use ailloli_ui_text::TextBuffer;
let mut session = EditorSession::new(TextBuffer::from_string("one\ntwo"));
assert!(session.select_line_at_byte(5));
assert_eq!(session.edit.selection.unwrap().normalized(), (4, 7));

Trait Implementations§

Source§

impl Clone for EditorSession

Source§

fn clone(&self) -> EditorSession

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EditorSession

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> ErasedDestructor for T
where T: 'static,