4GUZZYJSWKA44VKYZ2U3G7SQ32JHHHPBSYUWWNNWWBOEDUN7RLKAC ZSBXK2GGVYHLXXMAIIEXW45COI3GSP5CLBRUSY5JNRDSHTLGGBVAC BVKFLEK2IK7AOIXLU3KGN7XNWP7KSJLGOPJKJIR7MU4LGN4J5EGQC TKAAHADV62OQORAO7MYRRRHTGPMG3GKXU4Z4MFNLAO6DLTSDU3CAC 6W6OJAUT3KLOXXKYR4GA3MG4ACLO2T4KX3SGD2KZDX6MYEZYTPHAC WRBKZMYVNHRWT7TTUGTDJ3TMWZB32QYW5PCLKTTVAJ2YF6OI3LTAC CNJGJCJZ6LRHHIRSRATSE3D3Z5OQGSSTDMXCPVXSKRQLYJFME6IAC WBKXA5RVL5DSEJZ4OBDBCTNRT3Q4VFEVQNA344CET3BHY7CY7H5AC MESNWCLGM5N5HTO35HVLZTJDJ2BE74MHBRWXISACW7L5FNAB3LNAC ZL7ZSOEOGP2E24UEFC5VVPN5GTL3EUL34FA7F47WWWFPHJH2RS2AC else if s.mode == .visualLine thenlet cursor := s.getCursorlet minRow := (min startPt.row cursor.row).vallet maxRow := (max startPt.row cursor.row).vallet lines := (List.range (maxRow - minRow + 1)).map fun i =>ViE.getLineFromBuffer buffer ⟨minRow + i⟩ |>.getD ""if lines.isEmpty then "" else String.intercalate "\n" lines ++ "\n"
else if s.mode == .visualLine thenlet cursor := s.getCursorlet minRow := (min startPt.row cursor.row).vallet maxRow := (max startPt.row cursor.row).vallet text := s.getSelectedTextlet reg : Register := {kind := .linewisetext := textblockLines := []blockWidth := 0}let s' := s.updateActiveBuffer fun buffer =>match buffer.table.getLineRange minRow with| some (startOff, _) =>let endOff :=match buffer.table.getLineRange (maxRow + 1) with| some (nextStart, _) => nextStart| none => buffer.table.tree.lengthlet len := endOff - startOffif len > 0 then{ buffer with table := buffer.table.delete startOff len startOff, dirty := true }elsebuffer| none => bufferlet newBuffer := s'.getActiveBufferlet newRowVal := min minRow (newBuffer.lineCount.pred)let newRow : Row := ⟨newRowVal⟩let lineStr := ViE.getLineFromBuffer newBuffer newRow |>.getD ""let newCol := firstNonBlankCol lineStr tabStop{ s'.exitVisualMode with clipboard := some reg } |>.setCursor { row := newRow, col := ⟨newCol⟩ }
if state.mode == .visual || state.mode == .visualBlock then
if state.mode == .visual || state.mode == .visualLine || state.mode == .visualBlock thenlet cursor :=if state.mode == .visualLine thenlet activeBuf := state.getActiveBufferlet anchorRow := anchor.row.vallet cursorRow := state.getCursor.row.vallet endRow := max anchorRow cursorRowlet endLine := ViE.getLineFromBuffer activeBuf ⟨endRow⟩ |>.getD ""let endCol := ViE.Unicode.stringWidthWithTabStop endLine state.config.tabStop{ row := endRow, col := endCol }elsetoBlikuCursor state.getCursorlet anchor' :=if state.mode == .visualLine thenlet anchorRow := anchor.row.vallet cursorRow := state.getCursor.row.val{ row := min anchorRow cursorRow, col := 0 }elsetoBlikuCursor anchor
let s_linewise0 ← runKeys s0 ([Key.char 'i'] ++ keys "aa\nbb\ncc" ++ [Key.esc] ++ [Key.char 'g', Key.char 'g'])let s_linewiseD ← runKeys s_linewise0 [Key.char 'V', Key.char 'j', Key.char 'd']assertBuffer "visual line d deletes full lines" s_linewiseD "cc"match s_linewiseD.clipboard with| some reg =>assertEqual "visual line d register kind" RegisterKind.linewise reg.kindassertEqual "visual line d register text" "aa\nbb\n" reg.text| none => assertEqual "visual line d register set" true falselet s_linewiseY ← runKeys s_linewise0 [Key.char 'V', Key.char 'j', Key.char 'y']let s_linewiseP ← runKeys s_linewiseY [Key.char 'G', Key.char 'p']assertBuffer "visual line y/p pastes linewise" s_linewiseP "aa\nbb\ncc\naa\nbb\n"