#viewer/common/view_model

    Injected text, wrapping/folding projection, model/view conversion, and concrete inline/model decoration resolution.

    The model has model lines. The screen shows view lines. They are not the same sequence: one model line can wrap into several view lines, a folded region can hide model lines entirely, and injected text can add content the model does not contain. This package owns that projection and the conversion in both directions.

    flowchart TB M["model lines 1..n<br>viewer/common/model"] M -->|"wrap at wrapping_column"| P["projection"] M -->|"hidden areas (folding)"| P M -->|"injected text decorations"| P P --> V["view lines 1..m"] V -->|convert_view_position_to_model_position| M M -->|convert_model_position_to_view_position| V

    #Building a projection

    ViewModelLinesFromProjectedModel is the projection itself; ViewModel is the live owner that keeps it in sync with the model and publishes outgoing events.

    A wide wrapping column means no wrapping, so view lines and model lines correspond one-to-one — the degenerate case worth seeing first.

    ///|
    fn projection_model(text : String) -> @model.TextModel raise {
    TextModel(
    @base_common.Uri::parse("file:///view-model-doc.mbt"),
    "view-model-doc.mbt",
    "moonbit",
    1,
    "rev-1",
    text,
    )
    }

    ///|
    fn projection(
    text : String,
    wrapping_column~ : Int32,
    ) -> @view_model.ViewModelLinesFromProjectedModel raise {
    ViewModelLinesFromProjectedModel(
    projection_model(text),
    font_info=@config.FontInfo::default(),
    tab_size=4,
    wrapping_column~,
    wrapping_indent=None,
    )
    }

    ///|
    test "with no wrapping, view lines and model lines coincide" {
    let lines = projection("alpha\nbeta\ngamma\n", wrapping_column=200)
    debug_inspect(
    (
    lines.get_view_line_count(),
    lines.get_view_line_content(2),
    lines.model_line_number_of_view_line(2),
    lines.convert_view_position_to_model_position(2, 1),
    ),
    content=(
    #|(4, "beta", 2, { line_number: 2, column: 1 })
    ),
    )
    }

    Narrow the wrapping column and one model line becomes several view lines. The conversion is what keeps a caret, a selection, or a decoration pointing at the right characters afterwards.

    ///|
    test "wrapping splits one model line into several view lines" {
    let lines = projection(
    "aaaa bbbb cccc dddd eeee\nshort\n",
    wrapping_column=10,
    )
    debug_inspect(
    (
    lines.get_view_line_count(),
    [
    for view_line in 1..<=lines.get_view_line_count() => {
    (
    view_line,
    lines.get_view_line_content(view_line),
    lines.model_line_number_of_view_line(view_line),
    )
    }
    ],
    ),
    content=(
    #|(
    #| 5,
    #| [
    #| (1, "aaaa bbbb ", 1),
    #| (2, "cccc dddd ", 1),
    #| (3, "eeee", 1),
    #| (4, "short", 2),
    #| (5, "", 3),
    #| ],
    #|)
    ),
    )
    }

    Conversion round-trips: a model position maps to a view position and back.

    ///|
    test "model and view positions convert in both directions" {
    let lines = projection("aaaa bbbb cccc dddd eeee\n", wrapping_column=10)
    let view = lines.convert_model_position_to_view_position(1, 18)
    debug_inspect(
    (
    view,
    lines.convert_view_position_to_model_position(
    view.line_number,
    view.column,
    ),
    ),
    content=(
    #|({ line_number: 2, column: 8 }, { line_number: 1, column: 18 })
    ),
    )
    }

    #Hidden areas

    Folding is expressed as hidden areas — model ranges the projection omits. Nothing is deleted from the model; the view simply stops producing lines for them, and model_position_is_visible reports the difference.

    ///|
    test "a hidden area removes view lines without touching the model" {
    let lines = projection("one\ntwo\nthree\nfour\n", wrapping_column=200)
    let before = lines.get_view_line_count()
    let changed = lines.set_hidden_areas([Range(2, 1, 3, 6)])
    debug_inspect(
    (
    before,
    changed,
    lines.get_view_line_count(),
    lines.get_view_line_content(2),
    (
    lines.model_position_is_visible(1),
    lines.model_position_is_visible(2),
    lines.model_position_is_visible(4),
    ),
    lines.get_hidden_areas(),
    ),
    content=(
    #|(
    #| 5,
    #| true,
    #| 3,
    #| "four",
    #| (true, false, true),
    #| [
    #| {
    #| start_line_number: 2,
    #| start_column: 1,
    #| end_line_number: 3,
    #| end_column: 1,
    #| },
    #| ],
    #|)
    ),
    )
    }

    Setting the same hidden areas again reports false, which is what lets the folding contribution re-publish its state without forcing a re-render.

    ///|
    test "re-setting identical hidden areas is not a change" {
    let lines = projection("one\ntwo\nthree\n", wrapping_column=200)
    let first = lines.set_hidden_areas([Range(2, 1, 2, 4)])
    let again = lines.set_hidden_areas([Range(2, 1, 2, 4)])
    debug_inspect(
    (first, again),
    content=(
    #|(true, false)
    ),
    )
    }

    #Live view models

    ViewModel wraps a model and keeps the projection current. It exposes the line reads the renderer needs and a CoordinatesConverter for callers that only want the conversion.

    ///|
    test "a live ViewModel exposes line reads and a converter" {
    let model = projection_model("alpha\nbeta\ngamma\n")
    let view_model = @view_model.ViewModel(model)
    debug_inspect(
    (
    view_model.line_count(),
    view_model.get_line_content(2),
    view_model.get_line_max_column(2),
    view_model.language_id(),
    view_model.model_position_is_visible(Position(2, 1)),
    ),
    content=(
    #|(4, "beta", 5, "moonbit", true)
    ),
    )
    }

    to_model_visible_ranges splits a view range into the model ranges it actually covers, which is how a selection that spans a folded region becomes the correct set of model ranges rather than one range straddling hidden text.

    ///|
    test "a view range maps to the model ranges it really covers" {
    let model = projection_model("one\ntwo\nthree\nfour\n")
    let view_model = @view_model.ViewModel(model)
    debug_inspect(
    view_model.to_model_visible_ranges(Range(1, 1, 4, 5)),
    content=(
    #|[
    #| {
    #| start_line_number: 1,
    #| start_column: 1,
    #| end_line_number: 4,
    #| end_column: 5,
    #| },
    #|]
    ),
    )
    }

    validate_model_position clamps into the current document, so a stale position from an earlier generation cannot escape into layout math.

    ///|
    test "positions are validated against the current model" {
    let view_model = @view_model.ViewModel(projection_model("ab\ncd\n"))
    debug_inspect(
    (
    view_model.validate_model_position(Position(1, 1)),
    view_model.validate_model_position(Position(99, 99)),
    ),
    content=(
    #|({ line_number: 1, column: 1 }, { line_number: 3, column: 1 })
    ),
    )
    }

    #Injected text

    Injected text is content the view shows and the model does not contain — an inline type hint, for instance. It arrives as a model decoration, and the projection splices it into the projected line.

    get_injected_text_at answers whether a view position lands inside injected text, which is what stops a caret from being placed in text that has no model counterpart.

    ///|
    test "a plain document has no injected text anywhere" {
    let view_model = @view_model.ViewModel(projection_model("let x = 1\n"))
    debug_inspect(
    (
    view_model.get_injected_text_at(Position(1, 5)),
    view_model.injected_text_index_at(Position(1, 5)),
    ),
    content=(
    #|(None, -1)
    ),
    )
    }

    #Pipeline and API

    ViewModel owns the model, projected line collection, single cursor, ViewLayout, decoration resolver, coordinate converter, and per-source hidden-area sets. It is created once when a model attaches and updated in place.

    model line + grammar tokens + injected-text decorations -> ProjectedTextLine -> soft-wrap ModelLineProjection segments -> hidden-area filtering -> ViewLineData + model/view coordinate conversion -> viewport_data_from_view_model -> view_layout.ViewportData

    • ViewModelLinesFromProjectedModel is always used. With wrapping disabled each line has a cheap identity projection; there is no separate ViewModelLinesFromModelAsIs implementation. Models above the tokenization safety thresholds remain on this projected collection and render default tokens; collection fallback belongs to the separate large-file plan.
    • CoordinatesConverter is the closed concrete converter consumed by ViewModel, cursor closure construction, decorations, and browser input. Its current Projected arm retains ViewModelLinesFromProjectedModel; a future large-file as-is collection adds an identity arm without changing consumers.
    • Injected text is projected before line breaking, so its width affects wrapping; source mappings, tokens, and decorations remain anchored to model offsets.
    • Viewport construction uses one get_view_lines_data batch and a parallel needed mask. Each participating Projected model line constructs Monaco's five-callback injected-decoration context, computes absolute-view-line inline decorations, and performs one passive token-store read before examining the mask; therefore even an all-false mask reads once per projected model line. Identity retains Monaco's distinct early return and reads only when needed. The selected source-shaped decoration Range is adapted to the renderer's line-local offsets after baseViewLineNumber has been observed. No view read invokes the lexer.
    • Configuration or injected-text/content flushes reproject affected state at the current whole-model granularity, invalidate decoration caches, and reproject the cursor from model coordinates. Incremental edit events are not part of the readonly contract.
    • Cursor mutation has one source/reason-aware transition path. Model-side states validate through TextModel; view-side states clamp/normalize in this package and retain their authoritative projected position. Left/Right move by UTF-16 scalar boundaries, Up/Down/Page move across wrapped view lines with visible- column residues, and Home/End choose the source model/view branch. Word/Line pointer continuation dispatches from the stored anchor kind. Source-shaped MoveTo and Line entries accept a required model position plus an optional already-known view position: absent converts model-to-view; supplied is kept only when its normalized view-to-model result matches the validated model position.
    • CursorMoveDirection retains the source's full 15-member Direction enum; SimpleMoveDirection is its exact 11-member simple-move union, and CursorMoveUnit is the exact six-member Unit contract. Unscoped blank/wrapped-position and viewport directions, vertical model/folded units, and Left/Right HalfLine return without mutation at their explicit deferred branches.
    • CursorEventDispatcher is the outgoing-only half of Monaco's ViewModelEventDispatcher: its heterogeneous queue carries cursor-state, ViewZones-changed, hidden-area-changed, and model-token facts. Cursor selection/version no-ops are filtered and queued cursor events can coalesce; the two payload-free change facts are always observable and merge only with their own kind, while model-token wrappers retain the identical source event, are never no-ops, and never merge. The dispatcher recursively drains reentrant outgoing facts and uses separate source-shaped listener-delivery state so a nested fire first finishes the remaining listeners for the current value. The nested value is then delivered before the initiating callback resumes. The root Viewer FIFO separately keeps public event pairs adjacent. It exposes on_cursor_state_changed, on_view_zones_changed, on_hidden_areas_changed, and on_model_tokens_changed; ViewModel::dispose disposes all emitters and clears pending outgoing facts and listener- delivery state. Generic browser View handlers, mixed view/outgoing collectors, and the editor-wide cross-event delivery queue remain outside this reduced common owner.
    • Left/Right movement is surrogate-pair safe and otherwise advances one Unicode code point at a time. Full grapheme-cluster movement and the matching grapheme-segmented visible-column arithmetic remain deferred.
    • set_hidden_areas merges ranges by source, updates line/layout/decorations/ cursor, and preserves the top visible model line when folding changes above the viewport. Two optional owner continuations bridge the browser-package cycle without moving ViewEvents into this common package: the unchanged gate runs before with_event_batch; on a changed mapping, on_line_mapping_changed wraps the cursor continuation so the root appends Flushed/Mapping/Decorations, cursor, layout, and recovery-scroll facts in source order. The payload-free hidden-area outgoing event is emitted only when the projected line collection reports a real mapping change, and only after with_event_batch has returned, so layout and stable-viewport recovery are already complete. Equal inputs and force-updates whose mapping is still equal do not emit. Headless callers omit both continuations but retain the same changed-only outgoing event.
    • model_position_is_hidden_except_source is the narrow ViewZones policy read: it tests the raw per-source ranges without rebuilding the cached union or changing the projected line collection.
    • A ViewModel may borrow the exact attached-view handle owned by its root ModelData. Vertical scroll and content remapping publish current model visible ranges as unstable; initial setup and explicit view-state restore publish the stabilized state. Hidden model ranges are removed in order. Model token events are converted through the current projection, delivered synchronously to the browser ViewEvent callback, and only then enqueued as the original outgoing model event. The listener never forces tokenization.
    • ViewModelDecorations owns the concrete, package-private inline-decoration computer. It queries canonical model decorations, converts ranges through the local CoordinatesConverter, caches resolved view decorations by decoration id, and resolves only the requested viewport. Model-decoration and line-mapping notifications clear that cache at the corresponding source invalidation boundaries.

    #Inline-decoration ownership

    The merged package keeps the Monaco source units distinct:

    • inline_decorations.mbt maps common/viewModel/inlineDecorations.ts;
    • view_model_decoration.mbt maps common/viewModel/viewModelDecoration.ts;
    • view_model_decorations.mbt maps common/viewModel/viewModelDecorations.ts plus its called viewModelLines.ts range-query slice;
    • inline_decorations_reference_wbtest.mbt maps test/common/viewModel/inlineDecorations.test.ts and retains all 23 source test names.
    • inline_decorations_matrix_wbtest.mbt covers the additional branch and behavior-variable matrix recorded by the ownership plan: overlap/adjacency, whole-line and wrapped boundaries, endpoint visibility, invalidation, same-position/empty/wrapped injection edges, option/offset producer pairing, and consumer preconditions.

    The four source-mapped artifacts are pinned to vscode commit checked-in source; the local matrix derives its cases from that same source revision and the approved Gate A behavior matrix. Production uses concrete TextModel, ModelDecoration, ModelDecorationOptions, and CoordinatesConverter values. Only concrete ViewModelDecoration and ViewDecorationsCollection cross the package boundary; computers, contexts, resolved inputs, and renderer-facing inline values stay private. Injected-text decoration computation has one owner beside ModelLineProjection, including the source callback order, wrapped clipping, continuation indent, and absolute base-view-line calculation.

    The following source behavior remains explicitly deferred:

    • comment/string token visibility, because canonical decoration options have no hideInCommentTokens or hideInStringTokens fields;
    • the whole-line allowZero=false and belowHiddenRanges=true converter switches, because the canonical converter exposes affinity only;
    • production beforeContentClassName reach, because the canonical model options lack that field;
    • production affectsFont reach, because the canonical model options lack font-decoration inputs;
    • production injected-text letter-spacing reach, because canonical injected options lack inlineClassNameAffectsLetterSpacing.

    The white-box suite uses private resolved-input adapters for the last three branches. Those cases prove the source algorithms, not product reachability; the five entries remain DEFERRED in the execution-plan ledger.

    Run the exact source-named conformance suite with:

    moon test --target js viewer/common/view_model/inline_decorations_reference_wbtest.mbt moon test --target native viewer/common/view_model/inline_decorations_reference_wbtest.mbt

    Run the additional local branch matrix with:

    moon test --target js viewer/common/view_model/inline_decorations_matrix_wbtest.mbt moon test --target native viewer/common/view_model/inline_decorations_matrix_wbtest.mbt

    There are no FrameSource, FrameViewport, RenderLine, or RenderFrame APIs; browser code consumes ViewModel plus view_layout.ViewportData. Selection/copy helpers belong to viewer/common/core and the root viewer, not this package.

    The upstream map is the pinned src/vs/editor/common/viewModel/ files viewModelImpl.ts, viewModelLines.ts, modelLineProjection.ts, monospaceLineBreaksComputer.ts, inlineDecorations.ts, viewModelDecoration.ts, and viewModelDecorations.ts, plus viewLayout/viewLinesViewportData.ts. This package must remain multi-target and FFI-free, with no root-viewer, browser, server, transport, workspace, or host dependency. See pkg.generated.mbti; run moon test --target js viewer/common/view_model and moon test --target native viewer/common/view_model.

    CoordinatesConverter

    pub enum CoordinatesConverter {
    Projected(ViewModelLinesFromProjectedModel)
    }

    The closed coordinate-converter set owned by the view model. It is the concrete representation of Monaco's ICoordinatesConverter (coordinatesConverter.ts:9-30) and projected CoordinatesConverter (viewModelLines.ts:1073-1119) over the line collections this viewer currently ships. A future large-file as-is collection extends this enum with an identity arm without changing converter consumers.

    CoordinatesConverter::model_position_is_visible

    fn CoordinatesConverter::model_position_is_visible(self : CoordinatesConverter, position :
    Position
    ) -> Bool

    Reports projected model-position visibility through the line collection — CoordinatesConverter.modelPositionIsVisible (viewModelLines.ts:1108-1110). The current collection visibility surface is line-based, so the column remains deliberately unobserved.

    CoordinatesConverter::model_position_to_view_position

    Converts a model position through the projected line collection — CoordinatesConverter.convertModelPositionToViewPosition (viewModelLines.ts:1098-1102). The collection retains the additional zero-line and below-hidden-range switches; this current converter surface exposes the already-shipped affinity switch only.

    CoordinatesConverter::model_range_to_view_range

    Converts a model range through the projected line collection — CoordinatesConverter.convertModelRangeToViewRange (viewModelLines.ts:1104-1106).

    CoordinatesConverter::view_position_to_model_position

    Converts a view position through the projected line collection — CoordinatesConverter.convertViewPositionToModelPosition (viewModelLines.ts:1082-1084).

    CoordinatesConverter::view_range_to_model_range

    Converts a view range through the projected line collection — CoordinatesConverter.convertViewRangeToModelRange (viewModelLines.ts:1086-1088).

    CursorEventDispatcher

    type CursorEventDispatcher

    DOM-free outgoing-only half of Monaco's ViewModelEventDispatcher. Pending cursor/ViewZones/hidden-area events coalesce into their first same-kind slot; delivery is FIFO, discards no-ops, and remains safe when listeners emit reentrantly.

    CursorMoveDirection

    pub(all) enum CursorMoveDirection {
    Left
    Right
    Up
    Down
    PrevBlankLine
    NextBlankLine
    WrappedLineStart
    WrappedLineFirstNonWhitespaceCharacter
    WrappedLineColumnCenter
    WrappedLineEnd
    WrappedLineLastNonWhitespaceCharacter
    ViewPortTop
    ViewPortCenter
    ViewPortBottom
    ViewPortIfOutside
    } derive(Eq,
    Debug
    )

    Source-shaped command adapters for readonly cursor movement.

    Ported from vscode/src/vs/editor/common/cursor/cursorMoveCommands.ts and the scoped Home/End/Page command callers in vscode/src/vs/editor/browser/coreCommands.ts, pinned at checked-in source. Exact 15-member CursorMove.Direction enum contract (cursorMoveCommands.ts:929-948). The viewport members remain behaviorally deferred, but retaining them here keeps the aggregate source type complete.

    CursorMoveDirection::as_simple

    Narrows the full Direction enum to the simple-move union. A viewport member returns None, representing simpleMove's runtime default/null arm under a closed MoonBit type system.

    CursorMoveDirection::equal

    CursorMoveDirection::not_equal

    CursorMoveUnit

    pub(all) enum CursorMoveUnit {
    None
    Line
    WrappedLine
    Character
    HalfLine
    FoldedLine
    } derive(Eq,
    Debug
    )

    Exact CursorMove.Unit enum contract (cursorMoveCommands.ts:971-978). None and WrappedLine are behaviorally scoped; Line, Character, HalfLine, and FoldedLine remain explicit branch deferrals.

    CursorMoveUnit::equal

    CursorMoveUnit::not_equal

    fn CursorMoveUnit::not_equal(x : CursorMoveUnit, y : CursorMoveUnit) -> Bool

    CursorStateChangedEvent

    pub(all) struct CursorStateChangedEvent {
    kind : OutgoingViewModelEventKind
    old_selections : Array[
    Selection
    ]?
    selections : Array[
    Selection
    ]
    old_model_version_id : Int
    model_version_id : Int
    source : String
    reason :
    CursorChangeReason

    reached_max_cursor_count : Bool
    } derive(
    Debug
    )

    Complete outgoing cursor payload owned by the ViewModel. It retains the earliest old state when merged and the latest new state/source/reason.

    CursorStateChangedEvent::is_no_op

    An outgoing cursor event is a no-op only when both the selections and the internal model versions are equal.

    DecorationToRender

    pub struct DecorationToRender {
    start_line_number : Int
    end_line_number : Int
    class_name : String
    z_index : Int
    } derive(Eq,
    Debug
    )

    A decoration to render along margin lines start_line_number through end_line_number — Monaco's DecorationToRender (glyphMargin.ts). tooltip (linesDecorationsTooltip) is not carried by the viewer's decoration options; z_index is kept for parity but — like Monaco's LinesDecorationsOverlay — does not affect the emitted order.

    DecorationToRender::equal

    DecorationToRender::not_equal

    HiddenAreasChangedOutgoingEvent

    pub struct HiddenAreasChangedOutgoingEvent {
    kind : OutgoingViewModelEventKind
    } derive(
    Debug
    )

    Payload-free outgoing hidden-area change event. It is published only after the line mapping, cursor/decorations, layout, and stable viewport have been updated by ViewModel::set_hidden_areas.

    HiddenAreasChangedOutgoingEvent::HiddenAreasChangedOutgoingEvent

    fn HiddenAreasChangedOutgoingEvent::HiddenAreasChangedOutgoingEvent() -> HiddenAreasChangedOutgoingEvent

    Creates one source-shaped hidden-area change event.

    HiddenAreasChangedOutgoingEvent::is_no_op

    A changed hidden-area mapping is always observable.

    InjectedText

    pub struct InjectedText {
    position :
    Position

    text : String
    class_name : String
    source_index : Int
    } derive(Eq,
    Debug
    )

    Text inserted into a rendered line without existing in the source document.

    InjectedText::InjectedText

    fn InjectedText::InjectedText(position :
    Position
    , text : String, class_name : String, source_index? : Int) -> InjectedText

    Builds injected text at a model position.

    InjectedText::equal

    InjectedText::not_equal

    fn InjectedText::not_equal(x : InjectedText, y : InjectedText) -> Bool

    LineBreaksComputer

    type LineBreaksComputer

    Monaco ILineBreaksComputer: requests batch up through add_request and finalize computes them in one pass.

    LineBreaksComputer::add_request

    fn LineBreaksComputer::add_request(self : LineBreaksComputer, model_line_number : Int, line_text : String, injected_text : Array[InjectedText]) -> Unit

    LineBreaksComputer::finalize

    Computes every batched request. None is Monaco's null result: a line with no injected text that needs no wrapping projects as Identity.

    ModelLineProjection

    pub enum ModelLineProjection {
    Identity
    Hidden
    Projected(ModelLineProjectionData, is_visible~ : Bool)
    }

    Per-model-line projection, Monaco's IModelLineProjection (modelLineProjection.ts:16) with the package's enum dispatch standing in for interface polymorphism. Identity is Monaco's IdentityModelLineProjection.INSTANCE: a visible line with no wrapping and no injected text that delegates straight to the model, so the common no-wrap document allocates no per-line projection data at all. Hidden is Monaco's HiddenModelLineProjection.INSTANCE: a line hidden by setHiddenAreas (folding), producing zero view lines. Projected is Monaco's ModelLineProjection class, used to wrap model lines and inject text; it carries its own visibility like Monaco's _isVisible.

    Content queries on an invisible projection abort — the Hidden arms are the port of both HiddenModelLineProjection's throw new Error('Notsupported') and ModelLineProjection._assertVisible (an invisible Projected is not asserted per method; only valid view lines reach these accessors).

    ModelLineProjection::get_model_column_of_view_position

    fn ModelLineProjection::get_model_column_of_view_position(self : ModelLineProjection, output_line_index : Int, output_column : Int) -> Int

    Model column for a view position on one view line — getModelColumnOfViewPosition (translateToInputOffset, which undoes the continuation indent and clamps into the segment).

    ModelLineProjection::get_view_line_content

    fn ModelLineProjection::get_view_line_content(self : ModelLineProjection, model :
    TextModel
    , model_line_number : Int, output_line_index : Int) -> String

    Text of one view line — getViewLineContent: the projected segment's slice with the continuation indent prepended (spaces(...) + r), or the model line as-is.

    ModelLineProjection::get_view_line_count

    fn ModelLineProjection::get_view_line_count(self : ModelLineProjection) -> Int

    Number of view lines this model line produces — getViewLineCount: zero while hidden.

    ModelLineProjection::get_view_line_data

    fn ModelLineProjection::get_view_line_data(self : ModelLineProjection, model :
    TextModel
    , model_line_number : Int, output_line_index : Int, base_view_line_number : Int) -> ViewLineData

    The view-line data of one view line — getViewLineData. The identity arm is Monaco's IdentityModelLineProjection.getViewLineData (modelLineProjection.ts:298): the model line whole, tokens inflated, no injected inline decorations.

    ModelLineProjection::get_view_line_max_column

    fn ModelLineProjection::get_view_line_max_column(self : ModelLineProjection, model :
    TextModel
    , model_line_number : Int, output_line_index : Int) -> Int

    Maximum one-based column of one view line — getViewLineMaxColumn.

    ModelLineProjection::get_view_line_min_column

    fn ModelLineProjection::get_view_line_min_column(self : ModelLineProjection, output_line_index : Int) -> Int

    Minimum one-based column of one view line — getViewLineMinColumn (modelLineProjection.ts:141-144): getMinOutputOffset + 1, i.e. the continuation indent width plus one (view columns are segment-local; the segment's start_column is a projected-line column, a different axis).

    ModelLineProjection::get_view_position_of_model_position

    fn ModelLineProjection::get_view_position_of_model_position(self : ModelLineProjection, delta_line_number : Int, input_column : Int, affinity? :
    PositionAffinity
    ) ->
    Position

    View position of a model column — getViewPositionOfModelPosition (translateToOutputPosition(inputColumn - 1, affinity).toPosition(delta)). delta_line_number is the model line's first view line, so a continuation segment adds its index; the view column regains the continuation indent (Monaco's getOutputPositionOfInputOffset).

    ModelLineProjection::injected_text_index_at

    fn ModelLineProjection::injected_text_index_at(self : ModelLineProjection, output_line_index : Int, column : Int) -> Int

    The injected-text source index at a 0-based view column of one view line, or -1 for source text (including the synthetic continuation indent) — the index-valued form of Monaco's getInjectedTextAt.

    ModelLineProjection::is_visible

    fn ModelLineProjection::is_visible(self : ModelLineProjection) -> Bool

    Whether this model line is visible — isVisible.

    ModelLineProjection::normalize_position

    Snaps a view position at an injected-text or wrap boundary to the side the affinity asks for — normalizePosition (modelLineProjection.ts:237-241) over normalizeOutputPosition (modelLineProjectionData.ts:169-192).

    ModelLineProjection::set_visible

    fn ModelLineProjection::set_visible(self : ModelLineProjection, is_visible : Bool) -> ModelLineProjection

    Returns this projection with the given visibility — setVisible (modelLineProjection.ts:22, "this invalidates the current instance"): callers store the returned projection back, exactly Monaco's projections[i] = projections[i].setVisible(v) pattern. The identity singletons swap between Identity and Hidden.

    ModelLineProjectionData

    pub struct ModelLineProjectionData {
    model_line_number : Int
    line_length : Int
    projected_line : ProjectedTextLine
    segments : Array[ModelLineProjectionSegment]
    } derive(Eq,
    Debug
    )

    Projection data for one model line.

    ModelLineProjectionData::ModelLineProjectionData

    fn ModelLineProjectionData::ModelLineProjectionData(model_line_number : Int, line_length : Int, projected_line : ProjectedTextLine, segments : Array[ModelLineProjectionSegment]) -> ModelLineProjectionData

    Builds projection data for one model line.

    ModelLineProjectionData::equal

    ModelLineProjectionData::not_equal

    ModelLineProjectionData::segment_at_view_line_index

    fn ModelLineProjectionData::segment_at_view_line_index(self : ModelLineProjectionData, index : Int) -> ModelLineProjectionSegment

    Segment at a zero-based view-line index, clamped into range.

    ModelLineProjectionData::view_line_count

    fn ModelLineProjectionData::view_line_count(self : ModelLineProjectionData) -> Int

    Number of view-line segments for this model line.

    ModelLineProjectionData::view_line_index_for_model_column

    fn ModelLineProjectionData::view_line_index_for_model_column(self : ModelLineProjectionData, column : Int) -> Int

    View-line index containing the given model column.

    ModelLineProjectionData::view_line_index_for_projected_column

    fn ModelLineProjectionData::view_line_index_for_projected_column(self : ModelLineProjectionData, column : Int, affinity? :
    PositionAffinity
    ) -> Int

    View-line index containing the given projected display column.

    The break-offset search of offsetInInputWithInjectionsToOutputPosition (modelLineProjectionData.ts:130-167): only Left treats a break offset as belonging to the segment that ends there ((start, end] bounds); every other affinity starts the next segment with it ([start, end)).

    ModelLineProjectionSegment

    pub struct ModelLineProjectionSegment {
    model_line_number : Int
    start_offset : Int
    end_offset : Int
    start_column : Int
    end_column : Int
    start_visible_column : Double
    continues_with_wrapped_line : Bool
    wrapped_text_indent_length : Int
    } derive(Eq,
    Debug
    )

    One view-line segment produced from a model line after projection/wrapping. wrapped_text_indent_length is the continuation indent applied to this segment's rendered view line (Monaco's getMinOutputOffset): 0 for a model line's first segment, the model line's wrapped indent for continuations.

    ModelLineProjectionSegment::equal

    ModelLineProjectionSegment::not_equal

    ModelTokensChangedOutgoingEvent

    Source-shaped outgoing wrapper for one original model-token event (viewModelEventDispatcher.ts:545-551). The wrapper deliberately retains the exact event object; view-coordinate conversion belongs to the earlier browser ViewEvent delivery.

    ModelTokensChangedOutgoingEvent::ModelTokensChangedOutgoingEvent

    Builds the distinct outgoing model-token wrapper.

    ModelTokensChangedOutgoingEvent::is_no_op

    Model-token outgoing events are always observable, including an empty range array (viewModelEventDispatcher.ts:552-554).

    MonospaceLineBreaksComputerFactory

    type MonospaceLineBreaksComputerFactory

    Monaco MonospaceLineBreaksComputerFactory.

    MonospaceLineBreaksComputerFactory::MonospaceLineBreaksComputerFactory

    fn MonospaceLineBreaksComputerFactory::MonospaceLineBreaksComputerFactory(break_before_chars : String, break_after_chars : String) -> MonospaceLineBreaksComputerFactory

    MonospaceLineBreaksComputerFactory::create

    Monaco MonospaceLineBreaksComputerFactory.create, over the wordWrapBreakBeforeCharacters/wordWrapBreakAfterCharacters defaults.

    MonospaceLineBreaksComputerFactory::create_line_breaks_computer

    Monaco createLineBreaksComputer (wrapping_column <= 0 is the viewer's form of Monaco's wrappingColumn === -1, wrapping off).

    OutgoingViewModelEventKind

    pub(all) enum OutgoingViewModelEventKind {
    ViewZonesChanged
    HiddenAreasChanged
    CursorStateChanged
    ModelTokensChanged
    } derive(Eq,
    Debug
    )

    Semantic kind of the scoped outgoing events. Monaco's const-enum values are 4 for ViewZones and 7 for cursor state; MoonBit deliberately exposes no numeric ABI for these variants.

    OutgoingViewModelEventKind::equal

    OutgoingViewModelEventKind::not_equal

    ProjectedLinePart

    pub struct ProjectedLinePart {
    start : Int
    end : Int
    kind : ProjectedLinePartKind
    } derive(Eq,
    Debug
    )

    Half-open projected text segment with its source/injected identity.

    ProjectedLinePart::equal

    ProjectedLinePart::not_equal

    fn ProjectedLinePart::not_equal(x : ProjectedLinePart, y : ProjectedLinePart) -> Bool

    ProjectedLinePartKind

    pub enum ProjectedLinePartKind {
    SourceSegment(model_start~ : Int, model_end~ : Int)
    InjectedSegment(model_column~ : Int, injected_text_index~ : Int, class_name~ : String)
    } derive(Eq,
    Debug
    )

    Segment kind inside a projected line: source text or injected text.

    ProjectedLinePartKind::equal

    ProjectedLinePartKind::not_equal

    ProjectedTextLine

    pub struct ProjectedTextLine {
    text : String
    model_line_length : Int
    model_columns : Array[Int]
    injected_text_indices : Array[Int]
    model_to_projected_columns : Array[Int]
    parts : Array[ProjectedLinePart]
    } derive(Eq,
    Debug
    )

    One model line after injected text has been projected into display text, with column maps in both directions.

    Monaco's ModelLineProjectionData maps columns with offset arithmetic and binary search (translateToOutputPosition / translateToInputOffset); this type precomputes per-column lookup tables (model_to_projected_columns, model_columns) for O(1) .get(). The tables are first-write-wins, so a boundary column resolves to the left of the injections anchored there — exactly Monaco's non-Right affinity behavior; model_column_to_projected_column surfaces the Right side and normalize_projected_column_around_injections ports the normalization branches.

    ProjectedTextLine::equal

    ProjectedTextLine::from_injected_text

    fn ProjectedTextLine::from_injected_text(line_text : String, injected_text : Array[InjectedText]) -> ProjectedTextLine

    Builds projected text and column maps for one model line plus injected text.

    ProjectedTextLine::identity

    fn ProjectedTextLine::identity(line_text : String) -> ProjectedTextLine

    Projection for a line with no injected text.

    ProjectedTextLine::injected_text_index_at_projected_column

    fn ProjectedTextLine::injected_text_index_at_projected_column(self : ProjectedTextLine, projected_column : Int) -> Int

    Returns the injected-text source index at a projected display column, or -1 for source text.

    ProjectedTextLine::model_column_to_projected_column

    fn ProjectedTextLine::model_column_to_projected_column(self : ProjectedTextLine, model_column : Int, affinity? :
    PositionAffinity
    ) -> Int

    Maps a model column to a projected display column.

    The injection branch of translateToOutputPosition (modelLineProjectionData.ts:111-128): only Right resolves a boundary column to the far side of every injection anchored there; every other affinity (the None default included) stays left of them, which is what the first-write-wins lookup table already encodes.

    ProjectedTextLine::normalize_projected_column_around_injections

    fn ProjectedTextLine::normalize_projected_column_around_injections(self : ProjectedTextLine, projected_column : Int, affinity :
    PositionAffinity
    ) -> Int

    Snaps a projected column that touches injected text to one of its sides, normalizeOffsetInInputWithInjectionsAroundInjections (modelLineProjectionData.ts:204-252). Containment mirrors getInjectedTextAtOffset (:255-284): inclusive on both ends, first match wins. The viewer's injected text carries no cursorStops, so None behaves as Monaco's default InjectedTextCursorStops.Both: only strictly-inside columns snap (to the injection start); boundary columns already are cursor stops.

    ProjectedTextLine::not_equal

    fn ProjectedTextLine::not_equal(x : ProjectedTextLine, y : ProjectedTextLine) -> Bool

    ProjectedTextLine::projected_column_to_model_column

    fn ProjectedTextLine::projected_column_to_model_column(self : ProjectedTextLine, projected_column : Int) -> Int

    Maps a projected display column back to a model column.

    SimpleMoveArguments

    pub struct SimpleMoveArguments {
    direction : SimpleMoveDirection
    unit : CursorMoveUnit
    select : Bool
    value : Int
    } derive(Eq,
    Debug
    )

    Exact typed argument contract consumed by the bound simple-move commands.

    SimpleMoveArguments::SimpleMoveArguments

    fn SimpleMoveArguments::SimpleMoveArguments(direction : SimpleMoveDirection, unit : CursorMoveUnit, select : Bool, value : Int) -> SimpleMoveArguments

    SimpleMoveArguments::equal

    SimpleMoveArguments::not_equal

    SimpleMoveDirection

    pub(all) enum SimpleMoveDirection {
    Left
    Right
    Up
    Down
    PrevBlankLine
    NextBlankLine
    WrappedLineStart
    WrappedLineFirstNonWhitespaceCharacter
    WrappedLineColumnCenter
    WrappedLineEnd
    WrappedLineLastNonWhitespaceCharacter
    } derive(Eq,
    Debug
    )

    MoonBit representation of the source's exact 11-member SimpleMoveDirection union (cursorMoveCommands.ts:950-962).

    SimpleMoveDirection::equal

    SimpleMoveDirection::not_equal

    ViewDecorationsCollection

    pub struct ViewDecorationsCollection {
    decorations : Array[ViewModelDecoration]
    // private fields
    }

    Decorations in a range of lines: ungrouped, grouped per line as inline decorations, and a per-line affects-font flag (Monaco IViewDecorationsCollection). Only the resolved decoration list crosses the package boundary.

    ViewLineData

    pub struct ViewLineData {
    content : String
    continues_with_wrapped_line : Bool
    min_column : Int
    max_column : Int
    start_visible_column : Int
    tokens :
    ViewLineTokens

    inline_decorations : Array[
    InlineDecoration
    ]
    }

    One view line's data, Monaco's ViewLineData (common/viewModel.ts) — field-for-field. The view↔model coordinate mapping and injected-text identity queries live on the CoordinatesConverter and ViewModel::injected_text_index_at, not on the line data.

    ViewModel

    Backend-neutral document view model: the backing text model plus line projection, decorations, and coordinate conversion. Long-lived like Monaco's ViewModel (viewModelImpl.ts): constructed once at model attach and updated in place through on_configuration_changed and on_did_change_content_or_injected_text. Like Monaco, the line collection is always ViewModelLinesFromProjectedModel — no-wrap documents stay cheap through per-line Identity projections, not through a swapped collection.

    ViewModel::ViewModel

    Creates a view model with default no-wrap options.

    ViewModel::change_whitespace

    Delegates one nonraising whitespace transaction to ViewLayout and returns whether any accessor operation was requested. Browser-safe callback containment happens before this common-tier boundary.

    ViewModel::clamp_window

    Clamps a 1-based half-open view-line window to the document, the same clamping the viewport-data builder applies (viewport_data_from_view_model) so window consumers (the DOM recycler, hit tests) agree on the rendered range.

    ViewModel::coordinates_converter

    fn ViewModel::coordinates_converter(self : ViewModel) -> CoordinatesConverter

    Concrete coordinate converter owned by this view model. Callers erase it only at lower-tier boundaries that genuinely retain heterogeneous converters, such as CursorContext.

    ViewModel::cursor_page_size

    fn ViewModel::cursor_page_size(self : ViewModel) -> Int

    CursorConfiguration.pageSize (cursorCommon.ts:129): exactly

    max(1, floor(layoutHeight / lineHeight) - 2).

    ViewModel::decorations

    fn ViewModel::decorations(self : ViewModel) -> ViewModelDecorations

    ModelDecorationOptions buckets for this view model.

    ViewModel::dispose

    fn ViewModel::dispose(self : ViewModel) -> Unit

    Detaches this view model from its model — the live half of Monaco's ViewModel.dispose (viewModelImpl.ts:172-181): this.model.unregisterViewModel(this). The outgoing dispatcher owns its registered cursor listeners and is retired here before layout teardown. Called from the Viewer's ModelData::dispose.

    ViewModel::emit_view_zones_changed

    fn ViewModel::emit_view_zones_changed(self : ViewModel) -> Unit

    Emits one outgoing ViewZones fact after the browser tier has completed its internal ViewZonesChanged delivery.

    ViewModel::get_hidden_areas

    Merged one-based hidden model-line intervals, Monaco's ViewModel.getHiddenAreas (this._lines.getHiddenAreas()).

    ViewModel::get_injected_text_at

    fn ViewModel::get_injected_text_at(self : ViewModel, position :
    Position
    ) -> InjectedText?

    Monaco ViewModel.getInjectedTextAt (viewModelImpl.ts): the injected text at a view position, or None on source text. The object is re-derived from the position's model line (the projections retain only per-column indices); source_index is the decoration's attached_index, the same value injected_text_index_at reports.

    ViewModel::get_line_content

    fn ViewModel::get_line_content(self : ViewModel, line_number : Int) -> String

    Monaco ViewModel.getLineContent: the text of a view line.

    ViewModel::get_line_last_non_whitespace_column

    fn ViewModel::get_line_last_non_whitespace_column(self : ViewModel, line_number : Int) -> Int

    View-model side of ICursorSimpleModel.getLineLastNonWhitespaceColumn.

    ViewModel::get_line_length

    fn ViewModel::get_line_length(self : ViewModel, line_number : Int) -> Int

    Monaco ViewModel.getLineLength: the text length of a view line.

    ViewModel::get_line_max_column

    fn ViewModel::get_line_max_column(self : ViewModel, view_line_number : Int) -> Int

    Maximum one-based column of a view line, Monaco's getLineMaxColumn.

    ViewModel::get_line_min_column

    fn ViewModel::get_line_min_column(self : ViewModel, view_line_number : Int) -> Int

    Minimum one-based column of a view line, Monaco's getLineMinColumn.

    ViewModel::get_whitespaces

    Returns a shallow snapshot of every current ID-bearing whitespace.

    ViewModel::injected_text_index_at

    fn ViewModel::injected_text_index_at(self : ViewModel, position :
    Position
    ) -> Int

    The injected-text source index at a view position, or -1 for source text — the viewer's index-valued form of Monaco's ViewModel.getInjectedTextAt (viewModelImpl.ts, delegating to the line projection).

    ViewModel::language_id

    fn ViewModel::language_id(self : ViewModel) -> String

    Source document language id.

    ViewModel::line_count

    fn ViewModel::line_count(self : ViewModel) -> Int

    Number of view lines.

    ViewModel::lines

    The line collection for this view model.

    ViewModel::model_line_max_column

    fn ViewModel::model_line_max_column(self : ViewModel, model_line_number : Int) -> Int

    Maximum one-based column of a model line, Monaco's model.getLineMaxColumn (content length + 1). Used to close a split visible range at a hidden region's boundary line.

    ViewModel::model_position_is_hidden_except_source

    fn ViewModel::model_position_is_hidden_except_source(self : ViewModel, position :
    Position
    , ignored_source : String) -> Bool

    Whether a validated ViewZone anchor is hidden by any source other than the named owner. This is intentionally narrower than the merged coordinate converter: it reads the raw source lists without mutating their cached union or the projected line collection.

    ViewModel::model_position_is_visible

    fn ViewModel::model_position_is_visible(self : ViewModel, position :
    Position
    ) -> Bool

    Whether a model position lands on a visible (non-hidden) line, Monaco's CoordinatesConverter.modelPositionIsVisible. The read API gates getLineHeightForPosition on this.

    ViewModel::model_position_to_view_position

    Converts one validated-or-untrusted model position to view coordinates, forwarding the ViewZones affinity and allowZeroLineNumber seam exactly. The projected collection performs source-shaped model validation first.

    ViewModel::move_cursor

    fn ViewModel::move_cursor(self : ViewModel, direction : SimpleMoveDirection, in_selection_mode : Bool, value? : Int, unit? : CursorMoveUnit, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    CursorMoveCommands.simpleMove's approved LTR branches (cursorMoveCommands.ts:276-353,475-538). A zero value follows the source parser's args.value || 1 fallback. Up/Down accept only WrappedLine; logical/folded lines are approved deferrals. The return value reports a changed state, not whether the winning keybinding was handled: the root

    registry consumes a matched command even at a document boundary.

    ViewModel::move_cursor_direction

    fn ViewModel::move_cursor_direction(self : ViewModel, direction : CursorMoveDirection, in_selection_mode : Bool, value? : Int, unit? : CursorMoveUnit, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    Full-Direction adapter that owns simpleMove's runtime default/null arm. The four viewport members are valid Direction values but not members of the SimpleMoveDirection union, so they return without mutation here.

    ViewModel::move_cursor_line

    fn ViewModel::move_cursor_line(self : ViewModel, model_position :
    Position
    , in_selection_mode : Bool, view_position? :
    Position
    , source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    Source-shaped CursorMoveCommands.line entry. It accepts the required model position plus the optional already-known view position, covering the supplied/absent validation branches before either the new Line anchor or the continuing-selection branches execute.

    ViewModel::move_cursor_line_select_to

    CoreNavigationCommands.LineSelectDrag (coreCommands.ts:1705-1730) always applies the Line continuation algorithm, even when Shift-gutter begins from a Simple cursor. This dedicated entry therefore does not dispatch on the stored anchor kind (unlike generic move_cursor_to). The validated view position remains authoritative across wrapping and injected text.

    ViewModel::move_cursor_page

    fn ViewModel::move_cursor_page(self : ViewModel, direction : SimpleMoveDirection, in_selection_mode : Bool, page_size? : Int, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    CursorPageUp/Down's dynamic page argument (coreCommands.ts:913-936): the static PAGE_SIZE_MARKER = -1, an omitted argument, or an exact-zero dynamic override falls back to the live cursor page size; a positive override is used unchanged. Movement is wrapped-view-line

    simpleMove, not viewport scrolling.

    ViewModel::move_cursor_to

    fn ViewModel::move_cursor_to(self : ViewModel, view_position :
    Position
    , in_selection_mode : Bool, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    CursorMoveCommands.moveTo (cursorMoveCommands.ts:251-274): continuing Word/Line selections dispatch by the stored anchor kind before the Simple view-side move. Model validation belongs to the shared controller seam;

    the supplied view position remains authoritative under wrap/injected text.

    ViewModel::move_cursor_to_line_end

    fn ViewModel::move_cursor_to_line_end(self : ViewModel, in_selection_mode : Bool, sticky? : Bool, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    CursorMoveCommands._moveToLineEnd (cursorMoveCommands.ts:78-117). sticky=true is deliberately rejected:

    the large-leftover sticky arm is the approved CMO-059 deferral.

    ViewModel::move_cursor_to_line_start

    fn ViewModel::move_cursor_to_line_start(self : ViewModel, in_selection_mode : Bool, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    CursorMoveCommands._moveToLineStart (cursorMoveCommands.ts:41-76). The first wrapped segment uses logical model indentation; a continuation that is not already at its own first

    nonblank column uses view-line indentation.

    ViewModel::move_cursor_to_model_position

    fn ViewModel::move_cursor_to_model_position(self : ViewModel, model_position :
    Position
    , in_selection_mode : Bool, view_position? :
    Position
    , source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    Source-shaped CursorMoveCommands.moveTo entry. The model position is required and the already-known view position is optional, so tests and root command adapters can exercise both source branches directly.

    ViewModel::move_cursor_with_arguments

    fn ViewModel::move_cursor_with_arguments(self : ViewModel, args : SimpleMoveArguments, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    Consumes the exact SimpleMoveArguments record retained by the bound commands.

    ViewModel::move_cursor_word

    fn ViewModel::move_cursor_word(self : ViewModel, model_position :
    Position
    , in_selection_mode : Bool, source? : String, reason? :
    CursorChangeReason
    ) -> Bool

    Reduced CursorMoveCommands.word command entry. The required model position is validated before the selected-case readonly word seam runs; complete token-aware WordOperations remains the approved CMC-033 deferral.

    ViewModel::normalize_position

    Snaps a view position at injected-text/wrap boundaries per the affinity — ViewModel.normalizePosition (viewModelImpl.ts:1281-1283).

    ViewModel::on_configuration_changed

    fn ViewModel::on_configuration_changed(self : ViewModel, options : ViewModelOptions) -> Bool

    Applies changed options to the live view model — Monaco's ViewModel._onConfigurationChanged (viewModelImpl.ts:274) over the one options struct: _lines.setWrappingSettings + setTabSize update the collection in place, and a changed decoration filter input (renderValidationDecorations, editorId) rotates the decoration provider (Monaco's _decorations.reset() — the viewer's provider closes over the filter at construction). Returns whether the view-line mapping changed (Monaco emits ViewFlushedEvent/ViewLineMappingChangedEvent), so the caller re-flushes the layout.

    ViewModel::on_cursor_state_changed

    fn ViewModel::on_cursor_state_changed(self : ViewModel, listener : (CursorStateChangedEvent) -> Unit) ->
    Disposable

    Subscribes to the ViewModel's outgoing cursor event alias.

    ViewModel::on_did_change_content_or_injected_text

    Content or injected text changed — Monaco's onDidChangeContentOrInjectedText (viewModelImpl.ts:319-457, called directly by the text model), reduced to the two forms the viewer produces. e = None is the ModelInjectedTextChangedEvent arm (the union member is not ported — text_model_events.mbt header): Monaco re-runs the line-breaks computer per changed line, the viewer reprojects whole. e = Some(_) is the InternalModelContentChangeEvent arm, whose only constructed change today is Flush (:356-363); the per-line branches (:364-408) are the tier-2 lane. The root Viewer brackets the reduced whole-document projection and emits the corresponding typed ViewFlushed/mapping/decoration events through its View collector.

    ViewModel::on_hidden_areas_changed

    Subscribes to changed hidden-area mappings. Delivery occurs after the synchronous projection/layout/stable-viewport transaction has completed.

    ViewModel::on_model_tokens_changed

    Subscribes to the source-shaped outgoing model-token wrapper. The browser root uses this instead of listening to TextModel directly.

    ViewModel::on_view_zones_changed

    fn ViewModel::on_view_zones_changed(self : ViewModel, listener : (ViewZonesChangedEvent) -> Unit) ->
    Disposable

    Subscribes to the ViewModel's dedicated outgoing ViewZones event alias. The shared CodeEditorWidget cross-event delivery queue remains absent.

    ViewModel::set_cursor_state

    Applies one source-shaped partial state through the common controller and outgoing-dispatcher spine. None preserves the source's both-null no-op.

    ViewModel::set_hidden_areas

    fn ViewModel::set_hidden_areas(self : ViewModel, ranges : Array[
    Range
    ], source? : String, force_update? : Bool, with_event_batch? : (() -> Bool) -> Bool, on_line_mapping_changed? : (() -> Unit) -> Unit) -> Bool

    Applies one source's hidden-area set — ViewModel.setHiddenAreas (viewModelImpl.ts:592). Merges all sources, short-circuits when the union is unchanged (unless force_update), pushes the result into the line collection, and re-points everything hanging off the view-line axis: the cursor (_cursor.onLineMappingChanged), the decoration caches (_decorations.onLineMappingChanged), and the layout's line count (viewLayout.onFlushed + onHeightMaybeChanged). The viewport stays pinned to its first visible model line unless that line itself was hidden. Returns whether the view-line mapping changed — Monaco's ViewFlushedEvent/ViewLineMappingChangedEvent/HiddenAreasChangedEvent emissions, which the frame-based caller turns into a re-render.

    flowchart LR A[Replace one<br>source range set] --> B[Merge every source] B --> C{Union changed<br>or forced?} C -->|no| D[Return false] C -->|yes| E[Capture top anchor,<br>apply projected ranges] E --> F{Line mapping<br>changed?} F -->|yes| G[Re-point cursor,<br>decorations, layout] F -->|no| H[Keep mapping] G --> I[Restore visible<br>viewport anchor] H --> I I --> J[Emit changed-only<br>outgoing event]

    ViewModel::set_model_cursor_state

    Applies a model-side state through the common transition/dispatcher spine.

    ViewModel::set_view_cursor_state

    Applies a view-side state after source-shaped normalization, then emits the resulting outgoing cursor fact when its model side changed.

    ViewModel::to_model_visible_ranges

    Splits a completely-visible view range into the model ranges it covers, Monaco's ViewModelImpl._toModelVisibleRanges (viewModelImpl.ts:655). With no hidden regions the converted model range is returned whole; otherwise each hidden region carves the visible span into the model ranges actually on screen above/below it.

    ViewModel::validate_model_position

    Validates a model position before ViewZones derives its before/after position — TextModel.validatePosition at viewZones.ts:159-173.

    ViewModel::version

    fn ViewModel::version(self : ViewModel) -> Int

    Source document version.

    ViewModel::visible_lines_stabilized

    fn ViewModel::visible_lines_stabilized(self : ViewModel) -> Unit

    Publishes the current model-visible ranges as stabilized. Only the host's explicit handle_initialized boundary and view-state restore call this source method (viewModelImpl.ts:234-237). Model attach itself deliberately does not own the initialization publication.

    ViewModel::with_options

    fn ViewModel::with_options(model :
    TextModel
    , options : ViewModelOptions, smooth_scrolling? : Bool, schedule_at_next_animation_frame? : (() -> Unit) ->
    Disposable
    , now? : () -> Double, attached_view? :
    AttachedViewImpl
    , emit_view_tokens_changed? : (Array[ViewTokensChangedRange]) -> Unit) -> ViewModel

    Creates a view model with wrapping/tab options — the line-collection construction of Monaco's ViewModel constructor (viewModelImpl.ts:98-122).

    ViewModelDecoration

    Faithful 1:1 port of Monaco's viewModel/viewModelDecoration.ts declarations used by the viewer, from checked-in vscode submodule.

    A model decoration resolved into view coordinates (Monaco ViewModelDecoration).

    ViewModelDecorations

    type ViewModelDecorations

    ViewModelDecorations (viewModelDecorations.ts:16): the lazy, viewport-cached decoration provider for one view model.

    ViewModelDecorations::get_decorations_viewport_data

    getDecorationsViewportData (viewModelDecorations.ts:69-77): one-entry cache keyed by the exact view range.

    ViewModelDecorations::on_model_decorations_changed

    fn ViewModelDecorations::on_model_decorations_changed(self : ViewModelDecorations) -> Unit

    onModelDecorationsChanged (viewModelDecorations.ts:54-57).

    ViewModelLinesFromProjectedModel

    pub struct ViewModelLinesFromProjectedModel {
    model :
    TextModel

    font_info :
    FontInfo

    tab_size : Int
    wrapping_column : Int
    wrapping_indent :
    WrappingIndent

    model_line_projections : Array[ModelLineProjection]
    projected_model_line_line_counts : Array[Int]
    hidden_areas_decoration_ids : Array[String]
    // private fields
    }

    The line collection for every view model — Monaco's ViewModelLinesFromProjectedModel (viewModelLines.ts:60), which Monaco uses for all normal editors, wrapping on or off (its ViewModelLinesFromModelAsIs is only the too-large-for-tokenization escape hatch, which a readonly viewer never needs). Lines that need no mapping project as Identity and stay allocation-free; wrapping and injected text produce per-line Projected data.

    ViewModelLinesFromProjectedModel::ViewModelLinesFromProjectedModel

    Builds the collection and its projections — the constructor tail of Monaco's ViewModelLinesFromProjectedModel (viewModelLines.ts:85-112), minus the DOM/monospace computer-factory split (the viewer is monospace-only, so the monospace factory is the only one).

    ViewModelLinesFromProjectedModel::convert_model_position_to_view_position

    fn ViewModelLinesFromProjectedModel::convert_model_position_to_view_position(self : ViewModelLinesFromProjectedModel, model_line_number : Int, model_column : Int, affinity? :
    PositionAffinity
    , allow_zero_line_number? : Bool, below_hidden_ranges? : Bool) ->
    Position

    Converts a model position to view coordinates — convertModelPositionToViewPosition (viewModelLines.ts:848). A position on a hidden (folded) line walks up to the nearest visible line's end — or, with below_hidden_ranges, down to the next visible line's start. The affinity picks the boundary side at injected text and wrap breaks; absent it behaves as Monaco's default None.

    ViewModelLinesFromProjectedModel::convert_model_range_to_view_range

    Converts a model range to view coordinates — convertModelRangeToViewRange (viewModelLines.ts:892-901): the default affinity is Left and only applies to empty ranges; a non-empty range excludes injected text at its edges (start Right, end Left).

    ViewModelLinesFromProjectedModel::convert_view_position_to_model_position

    fn ViewModelLinesFromProjectedModel::convert_view_position_to_model_position(self : ViewModelLinesFromProjectedModel, view_line_number : Int, view_column : Int) ->
    Position

    Converts a view position to model coordinates — convertViewPositionToModelPosition (viewModelLines.ts:834).

    ViewModelLinesFromProjectedModel::convert_view_range_to_model_range

    Converts a view range to model coordinates — convertViewRangeToModelRange (viewModelLines.ts:842).

    ViewModelLinesFromProjectedModel::create_coordinates_converter

    Creates the coordinate converter over this collection — createCoordinatesConverter (viewModelLines.ts:118).

    ViewModelLinesFromProjectedModel::dispose

    Releases the owner-0 tracking decorations used for hidden areas — ViewModelLinesFromProjectedModel.dispose (viewModelLines.ts:114-116). Assigning the returned empty id array makes repeated disposal harmless.

    ViewModelLinesFromProjectedModel::get_hidden_areas

    Merged one-based hidden model-line ranges — getHiddenAreas (viewModelLines.ts:168), read back from the tracking decorations.

    ViewModelLinesFromProjectedModel::get_view_line_content

    fn ViewModelLinesFromProjectedModel::get_view_line_content(self : ViewModelLinesFromProjectedModel, view_line_number : Int) -> String

    Returns text for a one-based view line — getViewLineContent.

    ViewModelLinesFromProjectedModel::get_view_line_count

    Total number of view lines — getViewLineCount.

    ViewModelLinesFromProjectedModel::get_view_line_data

    fn ViewModelLinesFromProjectedModel::get_view_line_data(self : ViewModelLinesFromProjectedModel, view_line_number : Int) -> ViewLineData

    The view-line data of a one-based view line — getViewLineData.

    ViewModelLinesFromProjectedModel::get_view_line_max_column

    fn ViewModelLinesFromProjectedModel::get_view_line_max_column(self : ViewModelLinesFromProjectedModel, view_line_number : Int) -> Int

    Maximum one-based column for a view line — getViewLineMaxColumn.

    ViewModelLinesFromProjectedModel::get_view_line_min_column

    fn ViewModelLinesFromProjectedModel::get_view_line_min_column(self : ViewModelLinesFromProjectedModel, view_line_number : Int) -> Int

    Minimum one-based column for a view line — getViewLineMinColumn.

    ViewModelLinesFromProjectedModel::get_view_lines_data

    fn ViewModelLinesFromProjectedModel::get_view_lines_data(self : ViewModelLinesFromProjectedModel, view_start_line_number : Int, view_end_line_number : Int, needed : Array[Bool]) -> Array[ViewLineData?]

    Batch view-line data (viewModelLines.ts:763-795). The needed mask is indexed from view_start_line_number; hidden model lines are skipped and each participating projected model line shares one passive token read.

    ViewModelLinesFromProjectedModel::injected_text_index_at

    fn ViewModelLinesFromProjectedModel::injected_text_index_at(self : ViewModelLinesFromProjectedModel, view_line_number : Int, column : Int) -> Int

    The injected-text source index at a 0-based view column of a view line, or -1 for source text — the index-valued form of Monaco's getInjectedTextAt (viewModelLines.ts:991).

    ViewModelLinesFromProjectedModel::model_line_number_of_view_line

    fn ViewModelLinesFromProjectedModel::model_line_number_of_view_line(self : ViewModelLinesFromProjectedModel, view_line_number : Int) -> Int

    Maps a one-based view line to its one-based model line — the line-number half of Monaco's getViewLineInfo, kept as the viewer's shorthand for consumers that only need the line.

    ViewModelLinesFromProjectedModel::model_position_is_visible

    fn ViewModelLinesFromProjectedModel::model_position_is_visible(self : ViewModelLinesFromProjectedModel, model_line_number : Int) -> Bool

    Whether a one-based model line is visible (not folded away) — modelPositionIsVisible (viewModelLines.ts:250).

    ViewModelLinesFromProjectedModel::normalize_position

    Snaps a view position at injected-text/wrap boundaries per the affinity — normalizePosition (viewModelLines.ts:996).

    ViewModelLinesFromProjectedModel::on_injected_text_changed

    fn ViewModelLinesFromProjectedModel::on_injected_text_changed(self : ViewModelLinesFromProjectedModel) -> Unit

    Reprojects after an injected-text delta. Deviation: Monaco routes injected-text changes through per-line onModelLineChanged events (viewModelLines.ts:352), which keep hidden areas; the viewer's granularity is the whole-document reproject, so this is the per-line path's whole-document stand-in — hidden areas survive, unlike on_model_flushed.

    ViewModelLinesFromProjectedModel::on_model_flushed

    Reprojects after the document was replaced — onModelFlushed (viewModelLines.ts:325): constructLines(resetHiddenAreas=true). A flush replaces the document, so hidden (folded) areas reset; the stale hidden_areas_decoration_ids left by the model-side decoration wipe delta-remove as a no-op (delta_decorations skips unknown ids), exactly the source's tolerance.

    ViewModelLinesFromProjectedModel::set_hidden_areas

    Applies a new hidden-area set — setHiddenAreas (viewModelLines.ts:174). Returns whether the view-line mapping changed. Ranges are validated, normalized into merged whole-line ranges, and diffed against the current decoration-tracked set before any projection is touched.

    ViewModelLinesFromProjectedModel::set_tab_size

    fn ViewModelLinesFromProjectedModel::set_tab_size(self : ViewModelLinesFromProjectedModel, new_tab_size : Int) -> Bool

    Applies a changed tab size in place — setTabSize (viewModelLines.ts:266). Returns whether the view-line mapping changed.

    ViewModelLinesFromProjectedModel::set_wrapping_settings

    Applies changed wrapping settings in place — setWrappingSettings (viewModelLines.ts:277, which equally takes the fontInfo whose full-width/half-width ratio feeds the break widths). Returns whether the view-line mapping changed.

    ViewModelLinesFromProjectedModel::view_line_rendering_data

    Builds line-renderer input data for a one-based view line — the viewer's bridge to ViewLineRenderingData (Monaco builds it in ViewModel.getViewLineRenderingData).

    ViewModelOptions

    Backend-neutral view-model options derived from browser layout settings.

    ViewModelOptions::ViewModelOptions

    Builds options while clamping wrapping column and tab size. wrapping_indent defaults to Same, Monaco's default.

    ViewModelOptions::equal

    ViewModelOptions::is_soft_wrap_enabled

    fn ViewModelOptions::is_soft_wrap_enabled(self : ViewModelOptions) -> Bool

    Whether wrapping should produce projected view lines.

    ViewModelOptions::no_wrap

    Options with soft wrapping disabled.

    ViewModelOptions::not_equal

    fn ViewModelOptions::not_equal(x : ViewModelOptions, y : ViewModelOptions) -> Bool

    ViewModelOptions::soft_wrap

    fn ViewModelOptions::soft_wrap(column : Int, tab_size? : Int, wrapping_indent? :
    WrappingIndent
    ) -> ViewModelOptions

    Options with soft wrapping enabled at the given column.

    ViewTokensChangedRange

    pub struct ViewTokensChangedRange {
    from_line_number : Int
    to_line_number : Int
    } derive(Eq,
    Debug
    )

    Browser-neutral inclusive view-line range produced by the common ViewModel before the browser tier constructs its frozen ViewTokensChangedEvent.

    ViewTokensChangedRange::equal

    ViewTokensChangedRange::not_equal

    ViewZonesChangedEvent

    pub struct ViewZonesChangedEvent {
    kind : OutgoingViewModelEventKind
    } derive(
    Debug
    )

    Payload-free outgoing ViewZones change event. Its kind is semantic rather than Monaco's numeric const-enum ordinal 4.

    ViewZonesChangedEvent::ViewZonesChangedEvent

    fn ViewZonesChangedEvent::ViewZonesChangedEvent() -> ViewZonesChangedEvent

    Creates one source-shaped ViewZones change event.

    ViewZonesChangedEvent::is_no_op

    fn ViewZonesChangedEvent::is_no_op(_self : ViewZonesChangedEvent) -> Bool

    ViewZones changes are always observable.

    WordBreak

    pub(all) enum WordBreak {
    Normal
    KeepAll
    } derive(Eq,
    Debug
    )

    Monaco's wordBreak editor option ('normal' | 'keepAll'): KeepAll disables the ideographic (CJK) break points.

    WordBreak::equal

    fn WordBreak::equal(WordBreak, WordBreak) -> Bool

    WordBreak::not_equal

    fn WordBreak::not_equal(x : WordBreak, y : WordBreak) -> Bool

    create_model_line_projection

    fn create_model_line_projection(data : ModelLineProjectionData?, is_visible : Bool) -> ModelLineProjection

    createModelLineProjection (modelLineProjection.ts:52): None line-break data means no mapping is needed.

    dedup_margin_decorations

    fn dedup_margin_decorations(visible_start_line_number : Int, visible_end_line_number : Int, decorations : Array[DecorationToRender]) -> Array[Array[String]]

    DedupOverlay._render: expands the decorations into one class-name list per visible line, skipping a class name already emitted on a line by an earlier decoration of the same class. Sorting groups equal class names so the previous-decoration dedup window works; @base_common.compare also preserves JavaScript's UTF-16 lexicographic order for different classes.

    filter_validation_decorations

    filterValidationDecorations (editorOptions.ts): editable defers to readOnly, which is constantly true for this viewer.

    lines_decorations_to_render

    fn lines_decorations_to_render(decorations : Array[ViewModelDecoration]) -> Array[DecorationToRender]

    LinesDecorationsOverlay._getDecorations: the viewport decorations that carry a linesDecorationsClassName — plus, on their first line only, a firstLineDecorationClassName (the folding chevron's lane) — as render entries. Ranges are view-space (the viewport decoration collection already converted them).

    monospace_line_breaks_computer_factory

    let monospace_line_breaks_computer_factory : MonospaceLineBreaksComputerFactory

    The factory singleton the view-model line collection uses (Monaco creates one factory per code editor widget and hands it to the view model).

    render_line_input_from_view_line_data

    fn render_line_input_from_view_line_data(line : ViewLineData, line_decorations? : Array[
    LineDecoration
    ], space_width? : Double, render_whitespace? :
    RenderWhitespace
    , render_control_characters? : Bool, vertical_scrollbar_size? : Double) ->
    RenderLineInput

    Builds full line-renderer input from view-line data and its per-line decorations. The line's own injected-text inline decorations are always merged in — callers pass only the model-decoration spans (the viewport path in line_decorations_for_line produces both).

    view_line_rendering_data_from_view_line_data

    Converts view-line data to line-renderer data. Decorations arrive as per-line @view_layout.LineDecorations already produced by the faithful chain (ViewModelDecoration → per-line InlineDecoration → LineDecoration, see line_decorations_for_line).