WXZC34LZCQADXI3LEPDFDWHCVKYDC54WPCVYSUN3XSABH4VRHVJAC LRMCXRWTFARDTVVEPFYEQ6MJHUMU3BYHVI22CLXYEHLOQQWTGC6AC O27AXDRWCFLPVPLPZJTRUJRJFGXXCSR623MJADCSQTUUIEF5ZARAC MDJSREIO7F3IHOEGBAZBS4VIFPV2ETK6BAEM64AO2P5OBV6XOF2QC 6W6OJAUT3KLOXXKYR4GA3MG4ACLO2T4KX3SGD2KZDX6MYEZYTPHAC GSOBCC5UYHCUY53WEYJ4WG5RUQACOQSBCLEGA5W6GRPHARU4ZWEAC WBKXA5RVL5DSEJZ4OBDBCTNRT3Q4VFEVQNA344CET3BHY7CY7H5AC 4V7W7A6YX2J57RZUANMZKMKFHIDFNTXRMDR6M57DC6M3B4AHOK6AC WRBKZMYVNHRWT7TTUGTDJ3TMWZB32QYW5PCLKTTVAJ2YF6OI3LTAC NVJSIX3GL5WPI3FQ6U7TQQE5T4EDEHSI6SDQM7TPJTGBKCPILJFAC TIAIRD7L5GWH22TOLDAGCIDCJDZ53YWK3KHQOH3EIU7RZEOEP32AC A6E5SE5JPWUJJYIUS4CF7NMB5GM2SIIUXUZASSOVD467YWI5SCQQC LSCUXT3235I5ZZPZM2MMGLECHU2LAX2TKLRHDULONDAS5JEWTB7QC KJLCU4X5Z3CZM4AORMWIKOPBWPVTDMLK4LYH7UXBJFUGL7AUQCSQC 5SFTBD4FW6GQPKRUJBAII5R2EZPDYG6CH57BIJD4IVZBE6JZB2ZQC CNJGJCJZ6LRHHIRSRATSE3D3Z5OQGSSTDMXCPVXSKRQLYJFME6IAC U45XPF3YKPXXRJ4MN24T2RV7GOL4FZKQSWX5P5I7WT4HC5XF4FHAC ZL7ZSOEOGP2E24UEFC5VVPN5GTL3EUL34FA7F47WWWFPHJH2RS2AC 32SDOYNGPOAAMEQMZLZUE3XE6D5CFSZU6M3JDRERUVPAB4TLZOOAC 25KGF2W2ORVH3Z7RIBDBRKILMM624MNHIMN5QXNMZOWQ5DOJUCZAC NBG3GUEJJMWS2FRJDU26KRQLA6O2YK77PDAPBMD3SKWLDTK23BVAC GUD2J453E3UTRJZIEEUUJ3ZIGL72ETUXTO57XQIZ2Y3ZU3C2R55QC KFKFELOTH4NL4DMXXWJ36OK62HWNJ7JJTHWA76CYHWGTGXMRGYFQC SEIYD7YXZ5XI4W7UVF5O2UFLA6OCZZCOLV2XB46RKJ5EN6UQC4UAC private def diagnosticsShardCount : Nat := 16private abbrev DiagnosticsMap := Lean.RBMap String (Array DiagnosticInfo) compareinitialize diagnosticsShards : Array (IO.Ref DiagnosticsMap) ← dolet mut shards : Array (IO.Ref DiagnosticsMap) := #[]for _ in [0:diagnosticsShardCount] dolet r ← IO.mkRef (Lean.RBMap.empty : DiagnosticsMap)shards := shards.push rpure shards
private def diagnosticsShardIdx (uri : String) : Nat :=(hash uri).toNat % diagnosticsShardCountprivate def diagnosticsGet (uri : String) : IO (Array DiagnosticInfo) := dolet idx := diagnosticsShardIdx urimatch diagnosticsShards[idx]? with| none => pure #[]| some shard =>let m ← shard.getpure ((m.find? uri).getD #[])private def diagnosticsInsert (uri : String) (items : Array DiagnosticInfo) : IO Unit := dolet idx := diagnosticsShardIdx urimatch diagnosticsShards[idx]? with| none => pure ()| some shard =>shard.modify fun m => m.insert uri itemsprivate def diagnosticsClearAll : IO Unit := dofor shard in diagnosticsShards doshard.set (Lean.RBMap.empty : DiagnosticsMap)
let st ← uiStateRef.getlet pending := st.pendingHoverlet hoverMap := pending.erase reqIdmatch pending.find? reqId with| none =>uiStateRef.set { st with pendingHover := hoverMap }| some (uri, line, col) =>let hover :=match parseHoverText result with| some txt =>let range? := parseHoverRange resultsome { uri := uri, line := line, col := col, range? := range?, text := txt }| none =>match st.hover with| some h =>if h.uri == uri && h.line == line && h.col == col then some h else none| none => noneuiStateRef.set { st with pendingHover := hoverMap, hover := hover }
uiStateRef.modify fun st =>let pending := st.pendingHoverlet hoverMap := pending.erase reqIdmatch pending.find? reqId with| none =>{ st with pendingHover := hoverMap }| some (uri, line, col) =>let hover :=match parseHoverText result with| some txt =>let range? := parseHoverRange resultsome { uri := uri, line := line, col := col, range? := range?, text := txt }| none =>match st.hover with| some h =>if h.uri == uri && h.line == line && h.col == col then some h else none| none => none{ st with pendingHover := hoverMap, hover := hover }
let st ← uiStateRef.getlet pending := st.pendingCompletionlet pending' := pending.erase reqIdlet isLatest := st.latestCompletionReqId == some reqIdmatch pending.find? reqId with| none =>uiStateRef.set { st with pendingCompletion := pending' }| some (uri, row, col, query) =>if !isLatest thenuiStateRef.set { st with pendingCompletion := pending' }elselet items := rankAndSelectCompletions query (parseCompletionItems result) 40let completion :=if items.isEmpty thennoneelsesome (uri, { items := items, selected := 0, anchorRow := row, anchorCol := col })uiStateRef.set {st withpendingCompletion := pending'latestCompletionReqId := nonecompletion := completion}
uiStateRef.modify fun st =>let pending := st.pendingCompletionlet pending' := pending.erase reqIdlet isLatest := st.latestCompletionReqId == some reqIdmatch pending.find? reqId with| none =>{ st with pendingCompletion := pending' }| some (uri, row, col, query) =>if !isLatest then{ st with pendingCompletion := pending' }elselet items := rankAndSelectCompletions query (parseCompletionItems result) 40let completion :=if items.isEmpty thennoneelsesome (uri, { items := items, selected := 0, anchorRow := row, anchorCol := col }){st withpendingCompletion := pending'latestCompletionReqId := nonecompletion := completion}
let st ← uiStateRef.getlet clearCompletion := st.latestCompletionReqId == some reqIduiStateRef.set {st withpendingHover := st.pendingHover.erase reqIdpendingCompletion := st.pendingCompletion.erase reqIdlatestCompletionReqId := if clearCompletion then none else st.latestCompletionReqIdcompletion := if clearCompletion then none else st.completion}
uiStateRef.modify fun st =>let clearCompletion := st.latestCompletionReqId == some reqId{st withpendingHover := st.pendingHover.erase reqIdpendingCompletion := st.pendingCompletion.erase reqIdlatestCompletionReqId := if clearCompletion then none else st.latestCompletionReqIdcompletion := if clearCompletion then none else st.completion}
let st ← uiStateRef.getuiStateRef.set {st withpendingCompletion := st.pendingCompletion.insert reqId (uri, row, col, query)latestCompletionReqId := some reqId}
uiStateRef.modify fun st =>{st withpendingCompletion := st.pendingCompletion.insert reqId (uri, row, col, query)latestCompletionReqId := some reqId}
return some <| ViE.Lsp.Lean.clearCompletionPopup ((state.commitEdit.moveCursorLeft).setMode Mode.normal)
let s' ← ViE.Buffer.EditQueue.awaitActiveInsertOps statereturn some <| ViE.Lsp.Lean.clearCompletionPopup ((s'.commitEdit.moveCursorLeft).setMode Mode.normal)
| Key.esc => pure $ (s.commitEdit.moveCursorLeft).setMode Mode.normal| Key.backspace => pure $ s.deleteBeforeCursor| Key.char c => pure $ s.insertChar c| Key.enter => pure { s.insertNewline with completionPopup := none }
| Key.esc => dolet s' ← ViE.Buffer.EditQueue.awaitActiveInsertOps spure $ (s'.commitEdit.moveCursorLeft).setMode Mode.normal| Key.backspace => dolet s' ← ViE.Buffer.EditQueue.enqueueBackspace sViE.Buffer.EditQueue.awaitActiveInsertOps s'| Key.char c => ViE.Buffer.EditQueue.enqueueInsertChar s c| Key.enter => dolet s' ← ViE.Buffer.EditQueue.enqueueInsertNewline slet s'' ← ViE.Buffer.EditQueue.awaitActiveInsertOps s'pure { s'' with completionPopup := none }
/-- Build line-start offsets by walking the piece tree in document order. -/private def buildLineIndex (pt : PieceTable) : Array Nat := Id.run dolet capacity := PieceTree.lineBreaks pt.tree + 1let mut starts : Array Nat := (Array.mkEmpty capacity).push 0let mut docOff := 0let mut stack : List PieceTree := [pt.tree]while !stack.isEmpty domatch stack with| [] => pure ()| node :: rest =>stack := restmatch node with| PieceTree.empty => pure ()| PieceTree.leaf pieces _ _ =>for p in pieces dolet buf := PieceTableHelper.getBuffer pt p.sourcelet stop := p.start.toNat + p.length.toNatlet mut i := p.start.toNatwhile i < stop doif buf[i]! == 10 thenstarts := starts.push (docOff + 1)i := i + 1docOff := docOff + 1| PieceTree.internal children _ _ _ =>let mut i := children.sizewhile i > 0 dolet j := i - 1stack := children[j]! :: stacki := jreturn starts
private def updateLineIndexOnInsert (_pt : PieceTable) (_offset : Nat) (_text : String) : Option (Array Nat) :=none
-- Split bytes into chunks while collecting line starts in one pass.let rec splitChunks (start : Nat) (pieces : Array Piece) (starts : Array Nat) : (Array Piece × Array Nat) :=
-- Split bytes into chunks.let rec splitChunks (start : Nat) (pieces : Array Piece) : Array Piece :=
let idx := pt.lineIndexmatch idx[lineIdx]? with| none => none| some startOff =>let totalLen := pt.tree.lengthmatch idx[lineIdx + 1]? with| some nextStart =>let len := if nextStart > startOff then (nextStart - startOff - 1) else 0some (startOff, len)| none =>some (startOff, totalLen - startOff)
PieceTree.getLineRange pt.tree lineIdx pt
private def PieceTable.findLineForOffsetCore (pt : PieceTable) (target : Nat) (low highExcl : Nat) : Option (Nat × Nat) :=if low >= highExcl then noneelselet mid := low + (highExcl - low) / 2match pt.getLineRange mid with| some (start, len) =>let endOff := start + lenif target >= start && target <= endOff thensome (mid, target - start)else if target < start thenPieceTable.findLineForOffsetCore pt target low midelsePieceTable.findLineForOffsetCore pt target (mid + 1) highExcl| none => nonetermination_by highExcl - lowdecreasing_by· simp_wfomega· simp_wfomegadef PieceTable.findLineForOffset (pt : PieceTable) (target : Nat) (low high : Nat) : Option (Nat × Nat) :=PieceTable.findLineForOffsetCore pt target low (high + 1)
let hi := pt.lineCount - 1match PieceTable.findLineForOffset pt offset 0 hi with| some (r, c) =>match PieceTable.getLineRange pt r with| some (startOff, len) =>let rel := if c <= len then c else len
let clamped := min offset pt.lengthlet r := PieceTree.getLineIndexAtOffset pt.tree clamped ptmatch PieceTable.getLineRange pt r with| some (startOff, len) =>let rel0 := if clamped >= startOff then clamped - startOff else 0let rel := min rel0 len
left := midelseright := mid - 1return left/-- Binary search to find child index containing the given line-break index. -/def findChildForLine (imeta : ViE.InternalMeta) (lineIdx : UInt64) : Nat :=Id.run dolet arr := imeta.cumulativeLinesif arr.isEmpty then return 0if arr.size == 1 then return 0let mut left := 0let mut right := arr.size - 2while left < right dolet mid := (left + right + 1) / 2if arr[mid]! <= lineIdx then
/-- Parallel byte extraction for large ranges. Falls back to `getBytes` for small reads. -/def getBytesParallelIO (t : ViE.PieceTree) (offset : Nat) (len : Nat) (pt : ViE.PieceTable)(chunkSize : Nat := 128 * 1024) (parallelChunks : Nat := 4) : IO ByteArray := doif len == 0 || parallelChunks <= 1 || len <= chunkSize thenpure (getBytes t offset len pt)elselet chunks : Array (Nat × Nat) := Id.run dolet mut out : Array (Nat × Nat) := #[]let mut off := offsetlet endOff := offset + lenwhile off < endOff dolet readLen := min chunkSize (endOff - off)out := out.push (off, readLen)off := off + readLenreturn outif chunks.size <= 1 thenpure (getBytes t offset len pt)elselet mut out : ByteArray := ByteArray.mk (Array.mkEmpty len)let mut i := 0while i < chunks.size dolet mut batch : Array (Task (Except IO.Error ByteArray)) := #[]let mut j := 0while j < parallelChunks && i + j < chunks.size dolet (off, l) := chunks[i + j]!let task ← IO.asTask (pure (getBytes t off l pt))batch := batch.push taskj := j + 1for task in batch domatch task.get with| .ok part =>for b in part.data doout := out.push b| .error e => throw ei := i + batch.sizepure out
/-- Parallel substring extraction for large ranges. -/def getSubstringParallelIO (t : ViE.PieceTree) (offset : Nat) (len : Nat) (pt : ViE.PieceTable)(chunkSize : Nat := 128 * 1024) (parallelChunks : Nat := 4) : IO String := dolet bytes ← getBytesParallelIO t offset len pt chunkSize parallelChunkspure (String.fromUTF8! bytes)
| ViE.PieceTree.internal children _ _ _ =>let mut i := 0let mut found := falsewhile i < children.size && !found dolet child := children[i]!let childLines := lineBreaks childif currN < childLines thennode := childfound := trueelsecurrN := currN - childLinescurrOff := currOff + length childi := i + 1if !found then
| ViE.PieceTree.internal children _ _ imeta =>if children.isEmpty then
/-- Get line index (0-based) containing the byte offset.Newline byte itself belongs to the previous line (same as getLineRange semantics). -/def getLineIndexAtOffset (t : ViE.PieceTree) (offset : Nat) (pt : ViE.PieceTable) : Nat := Id.run dolet target := min offset (length t)let mut node := tlet mut currLines := 0let mut rem := targetwhile true domatch node with| ViE.PieceTree.empty =>return currLines| ViE.PieceTree.leaf pieces _ _ =>let mut i := 0while i < pieces.size && rem > 0 dolet p := pieces[i]!let pLen := p.length.toNatif rem >= pLen thencurrLines := currLines + p.lineBreaks.toNatrem := rem - pLenelselet buf := PieceTableHelper.getBuffer pt p.sourcelet (lines, _) := ViE.Unicode.countNewlinesAndChars buf p.start.toNat remcurrLines := currLines + linesrem := 0i := i + 1return currLines| ViE.PieceTree.internal children _ _ imeta =>if children.isEmpty thenreturn currLineslet childIdx := findChildForOffset imeta rem.toUInt64currLines := currLines + imeta.cumulativeLines[childIdx]!.toNatlet childStart := imeta.cumulativeBytes[childIdx]!.toNatrem := rem - childStartnode := children[childIdx]!return currLines
import ViE.Buffer.EditQueue
private def loadCacheShardCount : Nat := 16private abbrev LoadCacheMap := Lean.RBMap String FileBuffer compareinitialize loadCacheShards : Array (IO.Ref LoadCacheMap) ← dolet mut shards : Array (IO.Ref LoadCacheMap) := #[]for _ in [0:loadCacheShardCount] dolet r ← IO.mkRef (Lean.RBMap.empty : LoadCacheMap)shards := shards.push rpure shardsprivate def loadCacheKey (filename : String) (buildLeafBits buildOnEdit : Bool) : String :=s!"{filename}#bits={if buildLeafBits then "1" else "0"}#edit={if buildOnEdit then "1" else "0"}"private def loadCacheShardIdx (key : String) : Nat :=(hash key).toNat % loadCacheShardCountprivate def loadCacheGet (key : String) : IO (Option FileBuffer) := dolet idx := loadCacheShardIdx keymatch loadCacheShards[idx]? with| none => pure none| some shard =>let m ← shard.getpure (m.find? key)private def loadCacheInsert (key : String) (buf : FileBuffer) : IO Unit := dolet idx := loadCacheShardIdx keymatch loadCacheShards[idx]? with| none => pure ()| some shard =>shard.modify fun m => m.insert key buf
let data ← IO.FS.readBinFile filenamereturn bufferFromData filename data buildLeafBits buildOnEdit
match (← loadCacheGet key) with| some cached => return cached| none =>let data ← IO.FS.readBinFile filenamelet buf := bufferFromData filename data buildLeafBits buildOnEditloadCacheInsert key bufreturn buf
import ViE.Stateimport ViE.Unicodenamespace ViE.Buffer.EditQueueopen ViEinductive InsertOp where| char (c : Char)| newline| backspacederiving Inhabitedstructure WorkerState wherebuffer : FileBuffercursor : PointtabStop : Natderiving Inhabitedstructure WorkerKey wheresessionId : NatbufferId : Natderiving Repr, BEq, Ord, Inhabitedstructure WorkerEntry wherebaseSig : UInt64submitted : Natapplied : Nattask : Task (Except IO.Error WorkerState)private def bufferSig (b : FileBuffer) : UInt64 :=mixHash (hash b.table.tree.length) (hash b.table.tree.lineBreaks)initialize workersRef : IO.Ref (Lean.RBMap WorkerKey WorkerEntry compare) ←IO.mkRef Lean.RBMap.emptyinitialize sessionCounterRef : IO.Ref Nat ← IO.mkRef 1def ensureSessionId (s : EditorState) : IO EditorState := doif s.editSessionId != 0 thenpure selselet sid ← sessionCounterRef.modifyGet fun n => (n, n + 1)pure { s with editSessionId := sid }private def applyInsertOp (ws : WorkerState) (op : InsertOp) : WorkerState :=match op with| .char c =>match ViE.getOffsetFromPointInBufferWithTabStop ws.buffer ws.cursor.row ws.cursor.col ws.tabStop with| none => ws| some offset =>let b' := { ws.buffer with table := ws.buffer.table.insert offset (c.toString) offset, dirty := true }let b'' := FileBuffer.clearCache (FileBuffer.recomputeMissingEol b')let delta := ViE.Unicode.charWidthAt ws.tabStop ws.cursor.col.val c{ ws with buffer := b'', cursor := { ws.cursor with col := ⟨ws.cursor.col.val + delta⟩ } }| .newline =>match ViE.getOffsetFromPointInBufferWithTabStop ws.buffer ws.cursor.row ws.cursor.col ws.tabStop with| none => ws| some offset =>let b' := { ws.buffer with table := ws.buffer.table.insert offset "\n" offset, dirty := true }let b'' := FileBuffer.clearCache (FileBuffer.recomputeMissingEol b'){ ws with buffer := b'', cursor := { row := ⟨ws.cursor.row.val + 1⟩, col := 0 } }| .backspace =>if ws.cursor.col.val > 0 thenlet prevC := ViE.prevCol ws.tabStop ws.buffer ws.cursor.row ws.cursor.colmatch ViE.getOffsetFromPointInBufferWithTabStop ws.buffer ws.cursor.row prevC ws.tabStop,ViE.getOffsetFromPointInBufferWithTabStop ws.buffer ws.cursor.row ws.cursor.col ws.tabStop with| some startOff, some endOff =>let len := endOff - startOffif len > 0 thenlet b' := { ws.buffer with table := ws.buffer.table.delete startOff len endOff, dirty := true }let b'' := FileBuffer.clearCache (FileBuffer.recomputeMissingEol b'){ ws with buffer := b'', cursor := { ws.cursor with col := prevC } }elsews| _, _ => wselse if ws.cursor.row.val > 0 thenlet prevRow : Row := ⟨ws.cursor.row.val - 1⟩match ws.buffer.table.getLineRange prevRow.val with| some (start, len) =>let b' := { ws.buffer with table := ws.buffer.table.delete (start + len) 1 (start + len), dirty := true }let b'' := FileBuffer.clearCache (FileBuffer.recomputeMissingEol b')let newLen := ViE.lineDisplayWidth ws.tabStop b'' prevRow{ ws with buffer := b'', cursor := { row := prevRow, col := ⟨newLen⟩ } }| none => wselsewsprivate def applyWorkerStateToBuffer (s : EditorState) (bufferId : Nat) (ws : WorkerState) : EditorState :=let s1 := s.updateCurrentWorkspace fun cur =>{ cur withbuffers := cur.buffers.map fun b =>if b.id == bufferId then{ ws.buffer with id := b.id, filename := b.filename, loaded := true, dirty := true }elseb}let active := s1.getCurrentWorkspace.layout.findView s1.getCurrentWorkspace.activeWindowIdlet s2 :=match active with| some v =>if v.bufferId == bufferId thens1.setCursor ws.cursorelses1| none => s1{ s2 with dirty := true }private def enqueueInsertOp (s : EditorState) (op : InsertOp) : IO EditorState := dolet ws := s.getCurrentWorkspacematch ws.layout.findView ws.activeWindowId with| none => pure s| some view =>let bufferId := view.bufferIdlet key : WorkerKey := { sessionId := s.editSessionId, bufferId := bufferId }let snapshot : WorkerState := {buffer := s.getActiveBuffercursor := view.cursortabStop := s.config.tabStop}let sig := bufferSig snapshot.bufferlet workers ← workersRef.getmatch workers.find? key with| none =>let t ← IO.asTask (pure (applyInsertOp snapshot op))let e : WorkerEntry := { baseSig := sig, submitted := 1, applied := 0, task := t }workersRef.set (workers.insert key e)| some e =>if e.baseSig == sig thenlet prev := e.tasklet t ← IO.asTask domatch prev.get with| .ok st => pure (applyInsertOp st op)| .error err => throw errlet e' : WorkerEntry := { e with submitted := e.submitted + 1, task := t }workersRef.set (workers.insert key e')elselet t ← IO.asTask (pure (applyInsertOp snapshot op))let e' : WorkerEntry := { baseSig := sig, submitted := 1, applied := 0, task := t }workersRef.set (workers.insert key e')let s' :=match op with| .char c =>let delta := ViE.Unicode.charWidthAt s.config.tabStop view.cursor.col.val cs.setCursor { view.cursor with col := ⟨view.cursor.col.val + delta⟩ }| .newline =>s.setCursor { row := ⟨view.cursor.row.val + 1⟩, col := 0 }| .backspace =>if view.cursor.col.val > 0 thenlet prevC := ViE.prevCol s.config.tabStop s.getActiveBuffer view.cursor.row view.cursor.cols.setCursor { view.cursor with col := prevC }else if view.cursor.row.val > 0 thenlet prevRow : Row := ⟨view.cursor.row.val - 1⟩let newLen := ViE.lineDisplayWidth s.config.tabStop s.getActiveBuffer prevRows.setCursor { row := prevRow, col := ⟨newLen⟩ }elsespure { s' with dirty := true }def enqueueInsertChar (s : EditorState) (c : Char) : IO EditorState :=enqueueInsertOp s (.char c)def enqueueInsertNewline (s : EditorState) : IO EditorState :=enqueueInsertOp s .newlinedef enqueueBackspace (s : EditorState) : IO EditorState :=enqueueInsertOp s .backspacedef awaitActiveInsertOps (s : EditorState) : IO EditorState := dolet ws := s.getCurrentWorkspacematch ws.layout.findView ws.activeWindowId with| none => pure s| some view =>let bufferId := view.bufferIdlet key : WorkerKey := { sessionId := s.editSessionId, bufferId := bufferId }let workers ← workersRef.getmatch workers.find? key with| none => pure s| some e =>if e.applied >= e.submitted thenworkersRef.set (workers.erase key)pure selselet res := e.task.getworkersRef.set (workers.erase key)match res with| .ok wsState => pure (applyWorkerStateToBuffer s bufferId wsState)| .error err => pure { s with message := s!"Insert worker error: {err}" }def drainCompletedInsertOps (s : EditorState) : IO (EditorState × Bool) := dolet workers ← workersRef.getlet keys : Array WorkerKey := workers.fold (init := #[]) (fun acc k _ => acc.push k)let mut map := workerslet mut st := slet mut changed := falsefor k in keys domatch map.find? k with| none => pure ()| some e =>if e.applied >= e.submitted thenmap := map.erase kelselet done ← IO.hasFinished e.taskif done thenlet res := e.task.getmap := map.erase kmatch res with| .ok wsState =>if k.sessionId == s.editSessionId thenst := applyWorkerStateToBuffer st k.bufferId wsStateelsepure ()changed := true| .error err =>st := { st with message := s!"Insert worker error (session {k.sessionId}, buffer {k.bufferId}): {err}", dirty := true }changed := trueworkersRef.set mappure (st, changed)end ViE.Buffer.EditQueue
let mut loadTasks : Array (Task (Except IO.Error FileBuffer)) := #[]for i in [0:filesArr.size] dolet fname := filesArr[i]!if i == safeActiveIdx thenlet t ← IO.asTask (loadBufferByteArrayWithConfig fname settings)loadTasks := loadTasks.push telse-- Keep lazy placeholders semantically, but warm file cache in parallel.prefetchBufferByteArrayWithConfig fname settingslet t ← IO.asTask (pure (emptyBuffer (some fname) buildLeafBits settings.searchBloomBuildOnEdit))loadTasks := loadTasks.push t
let buf ← loadBufferByteArrayWithConfig fname settings
let bufResult :=match loadTasks[i]? with| some t => t.get| none => Except.ok (emptyBuffer (some fname) buildLeafBits settings.searchBloomBuildOnEdit)let buf :=match bufResult with| Except.ok b => b| Except.error _ => emptyBuffer (some fname) buildLeafBits settings.searchBloomBuildOnEdit
let s_gbase ← runKeys s0 ([Key.char 'i'] ++ keys "line1\nline2\nline3" ++ [Key.esc])let s_gg_insert ← runKeys s_gbase [Key.char 'G', Key.char 'g', Key.char 'g', Key.char 'i', Key.char 'X', Key.esc]assertBuffer "insert after gg applies at moved cursor" s_gg_insert "Xline1\nline2\nline3"let s_G_insert ← runKeys s_gbase [Key.char 'g', Key.char 'g', Key.char 'G', Key.char 'i', Key.char 'Z', Key.esc]assertBuffer "insert after G applies at moved cursor" s_G_insert "line1\nline2\nZline3"