BVKFLEK2IK7AOIXLU3KGN7XNWP7KSJLGOPJKJIR7MU4LGN4J5EGQC 4V7W7A6YX2J57RZUANMZKMKFHIDFNTXRMDR6M57DC6M3B4AHOK6AC MESNWCLGM5N5HTO35HVLZTJDJ2BE74MHBRWXISACW7L5FNAB3LNAC FAVK3BZP62D4KKDVNGX323UOVRPCW2NFLAHTVYBGQHRJSDI24XCQC 6W6OJAUT3KLOXXKYR4GA3MG4ACLO2T4KX3SGD2KZDX6MYEZYTPHAC TKAAHADV62OQORAO7MYRRRHTGPMG3GKXU4Z4MFNLAO6DLTSDU3CAC A6E5SE5JPWUJJYIUS4CF7NMB5GM2SIIUXUZASSOVD467YWI5SCQQC WBKXA5RVL5DSEJZ4OBDBCTNRT3Q4VFEVQNA344CET3BHY7CY7H5AC ZL7ZSOEOGP2E24UEFC5VVPN5GTL3EUL34FA7F47WWWFPHJH2RS2AC TIAIRD7L5GWH22TOLDAGCIDCJDZ53YWK3KHQOH3EIU7RZEOEP32AC XCVPXP4UBFU25NF6VQC3MEYHHH45RL2UXM5TA6O23NA64FPCCCJQC YILSJ2SNU6DNZVSFL4MD6QSNLQHUNSBSTGGEQCFTWFTRR62IXBWAC 2CFNOXLKFVAGON3Z2KISH4LNIALNY4VTBILJLQIE45YUKQI6ZHPQC namespace ViE.UI.Syntaxend ViE.UI.Syntaxabbrev highlightLine := Bliku.Tui.Syntax.highlightLineimport ViE.UI.Syntax.Typesimport ViE.UI.Syntax.Leanimport ViE.UI.Syntax.Markdownimport Bliku.Tui.Syntax
namespace ViE.UI.Syntaxend ViE.UI.Syntaxabbrev detectLanguage := Bliku.Tui.Syntax.detectLanguageabbrev styleForByteRange := Bliku.Tui.Syntax.styleForByteRangeabbrev markdownHeadingStyle := Bliku.Tui.Syntax.markdownHeadingStyleabbrev markdownCodeStyle := Bliku.Tui.Syntax.markdownCodeStyleabbrev markdownLinkStyle := Bliku.Tui.Syntax.markdownLinkStyleabbrev markdownEmphasisStyle := Bliku.Tui.Syntax.markdownEmphasisStyleabbrev leanKeywordStyle := Bliku.Tui.Syntax.leanKeywordStyleabbrev leanCommentStyle := Bliku.Tui.Syntax.leanCommentStyleabbrev leanStringStyle := Bliku.Tui.Syntax.leanStringStyleabbrev leanNumberStyle := Bliku.Tui.Syntax.leanNumberStyleabbrev Language := Bliku.Tui.Syntax.Languageabbrev Span := Bliku.Tui.Syntax.Spanimport Bliku.Tui.Syntax.Types
import ViE.UI.Syntax.Typesnamespace ViE.UI.Syntaxend ViE.UI.Syntaxabbrev highlightMarkdownLine := Bliku.Tui.Syntax.highlightMarkdownLineimport Bliku.Tui.Syntax.Markdown
import ViE.UI.Syntax.Typesnamespace ViE.UI.Syntaxend ViE.UI.Syntaxabbrev highlightLeanLine := Bliku.Tui.Syntax.highlightLeanLineimport Bliku.Tui.Syntax.Lean
private partial def setSplitRatioForPair (layout : Layout) (leftId rightId : Nat) (ratio : Float) : Layout :=match layout with| .window _ _ => layout| .hsplit left right currentRatio =>let leftHasLeft := left.containsWindow leftIdlet leftHasRight := left.containsWindow rightIdlet rightHasLeft := right.containsWindow leftIdlet rightHasRight := right.containsWindow rightIdif (leftHasLeft && rightHasRight) || (leftHasRight && rightHasLeft) then.hsplit left right ratioelse if leftHasLeft && leftHasRight then.hsplit (setSplitRatioForPair left leftId rightId ratio) right currentRatioelse if rightHasLeft && rightHasRight then.hsplit left (setSplitRatioForPair right leftId rightId ratio) currentRatioelse.hsplit left right currentRatio| .vsplit top bottom currentRatio =>let topHasLeft := top.containsWindow leftIdlet topHasRight := top.containsWindow rightIdlet bottomHasLeft := bottom.containsWindow leftIdlet bottomHasRight := bottom.containsWindow rightIdif topHasLeft && topHasRight then.vsplit (setSplitRatioForPair top leftId rightId ratio) bottom currentRatioelse if bottomHasLeft && bottomHasRight then.vsplit top (setSplitRatioForPair bottom leftId rightId ratio) currentRatioelse.vsplit top bottom currentRatioprivate def applyExplorerPreviewRatio (state : EditorState) (explorerWinId previewWinId : Nat) : EditorState :=state.updateCurrentWorkspace fun ws =>{ ws withlayout := setSplitRatioForPair ws.layout explorerWinId previewWinId state.config.explorerPreviewSplitRatio}
private def containsBoth (l : Bliku.Tui.Layout) (a b : Nat) : Bool :=l.containsWindow a && l.containsWindow bprivate partial def wrapClusterSubtree(l : Bliku.Tui.Layout) (clusterId paneA paneB : Nat) : Bliku.Tui.Layout :=if !(containsBoth l paneA paneB) thenlelsematch l with| .group gid body =>if containsBoth body paneA paneB then.group gid (wrapClusterSubtree body clusterId paneA paneB)elsel| .hsplit left right ratio =>if containsBoth left paneA paneB then.hsplit (wrapClusterSubtree left clusterId paneA paneB) right ratioelse if containsBoth right paneA paneB then.hsplit left (wrapClusterSubtree right clusterId paneA paneB) ratioelse.group clusterId l| .vsplit top bottom ratio =>if containsBoth top paneA paneB then.vsplit (wrapClusterSubtree top clusterId paneA paneB) bottom ratioelse if containsBoth bottom paneA paneB then.vsplit top (wrapClusterSubtree bottom clusterId paneA paneB) ratioelse.group clusterId l| .pane _ _ => l
if c.cursorSpaceStyle.isEmpty then (ViE.Color.toBg .white) ++ (ViE.Color.toFg .black) else c.cursorSpaceStyle
if c.cursorSpaceStyle.isEmpty then(ViE.Color.toBg .white) ++ (ViE.Color.toFg .black)elsec.cursorSpaceStylelet floatingChromeActiveStyle :=if c.statusBarStyle.isEmpty then(ViE.Color.toFg .cyan)elsec.statusBarStylelet floatingChromeInactiveStyle :=if c.statusBarStyle.isEmpty then(ViE.Color.toFg .white)elsec.statusBarStyle
private def explorerClusterSpecs (state : ViE.EditorState) : Array (Nat × Nat × Nat) := Id.run dolet ws := state.getCurrentWorkspacelet mut specs : Array (Nat × Nat × Nat) := #[]for (bufId, explorer) in state.explorers.reverse domatch ws.layout.findWindowIdByBufferId bufId, explorer.previewWindowId with| some explorerWinId, some previewWinId =>if ws.layout.containsWindow previewWinId thenspecs := specs.push (bufId, explorerWinId, previewWinId)| _, _ => pure ()return specsprivate def toBlikuDesktop (state : ViE.EditorState) : Bliku.DesktopLayout :=let ws := state.getCurrentWorkspacelet clusterSpecs := explorerClusterSpecs statelet groupedLayout :=clusterSpecs.foldl(fun acc (clusterId, explorerWinId, previewWinId) =>wrapClusterSubtree acc clusterId explorerWinId previewWinId)(toBlikuLayout ws.layout)let clusteredPaneIds := clusterSpecs.foldl (fun acc (_, explorerWinId, previewWinId) =>acc.push explorerWinId |>.push previewWinId) #[]let paneClusters :=ws.getFloatingWindowIds.foldl (fun acc wid =>if clusteredPaneIds.contains wid thenaccelselet (rowOff, colOff) := ws.getFloatingWindowOffset widacc.push { root := .pane wid, rowOffset := rowOff, colOffset := colOff, sizePolicy := .default }) #[]let groupClusters :=clusterSpecs.map fun (clusterId, explorerWinId, _) =>let (rowOff, colOff) := ws.getFloatingWindowOffset explorerWinId{root := .group clusterIdrowOffset := rowOffcolOffset := colOffsizePolicy := .multiPanechrome := { kind := .bordered, title := some "Explorer" }}{layout := groupedLayoutactivePaneId := ws.activeWindowIdfloating := { clusters := paneClusters ++ groupClusters }}private def toBlikuSelection (state : ViE.EditorState) : Option Bliku.Tui.SelectionState :=match state.selectionStart with| none => none| some anchor =>if state.mode == .visual || state.mode == .visualBlock thensome {anchor := toBlikuCursor anchorcursor := toBlikuCursor state.getCursorblock := state.mode == .visualBlock}elsenoneprivate def toBlikuCommandLine (state : ViE.EditorState) : Option Bliku.Tui.CommandLineState :=let text := state.inputState.commandBuffermatch state.mode with| .command => some { leader := ":", text := text, cursorCol := text.length }| .searchForward => some { leader := "/", text := text, cursorCol := text.length }| .searchBackward => some { leader := "?", text := text, cursorCol := text.length }| _ => noneprivate def statusLine (state : ViE.EditorState) : String :=let ws := state.getCurrentWorkspacelet buf := state.getActiveBufferlet fileName := buf.filename.getD "[No Name]"let eolMark := if buf.missingEol then " [noeol]" else ""s!"-- {state.mode} -- {fileName}{eolMark} [W:{ws.activeWindowId} B:{buf.id}] [{state.getCurrentWorkgroup.name}] {ws.name}"private def toRenderInput (state : ViE.EditorState) : Bliku.Tui.RenderInput :={selection := toBlikuSelection statecommandLine := toBlikuCommandLine statemessageLine := state.messagestatusLine := statusLine stateoverlay := state.floatingOverlay.map toBlikuOverlaycompletion := state.completionPopup.map toBlikuCompletionhideTerminalCursor :=state.mode != .command &&state.mode != .searchForward &&state.mode != .searchBackward &&state.floatingOverlay.isNone}
match s12c.getFloatingWindowBounds wsPrev.activeWindowId, s12c.getFloatingWindowBounds previewWinId with| some (et, el, eh, ew), some (pt, pl, ph, pw) =>
match (ViE.Window.getAllWindowBounds wsPrev.layout (if s12c.windowHeight > 0 then s12c.windowHeight - 1 else 0) s12c.windowWidth).find? (fun (id, _, _, _, _) => id == wsPrev.activeWindowId),(ViE.Window.getAllWindowBounds wsPrev.layout (if s12c.windowHeight > 0 then s12c.windowHeight - 1 else 0) s12c.windowWidth).find? (fun (id, _, _, _, _) => id == previewWinId) with| some (_, et, el, eh, ew), some (_, pt, pl, ph, pw) =>
match s2.getFloatingWindowBounds wsPrev.activeWindowId, s2.getFloatingWindowBounds previewWinId with| some (et, el, eh, ew), some (pt, pl, ph, pw) =>
match (ViE.Window.getAllWindowBounds wsPrev.layout (if s2.windowHeight > 0 then s2.windowHeight - 1 else 0) s2.windowWidth).find? (fun (id, _, _, _, _) => id == wsPrev.activeWindowId),(ViE.Window.getAllWindowBounds wsPrev.layout (if s2.windowHeight > 0 then s2.windowHeight - 1 else 0) s2.windowWidth).find? (fun (id, _, _, _, _) => id == previewWinId) with| some (_, et, el, eh, ew), some (_, pt, pl, ph, pw) =>
assertEqual "Lean keyword style" (some ViE.UI.Syntax.leanKeywordStyle) (ViE.UI.Syntax.styleForByteRange spans defS defE)assertEqual "Lean number style" (some ViE.UI.Syntax.leanNumberStyle) (ViE.UI.Syntax.styleForByteRange spans numS numE)assertEqual "Lean comment style" (some ViE.UI.Syntax.leanCommentStyle) (ViE.UI.Syntax.styleForByteRange spans comS comE)
assertEqual "Lean keyword style" (Bliku.Tui.Syntax.defaultPalette.faceFor .keyword)(Bliku.Tui.Syntax.faceForByteRange Bliku.Tui.Syntax.defaultPalette spans defS defE)assertEqual "Lean number style" (Bliku.Tui.Syntax.defaultPalette.faceFor .numberLiteral)(Bliku.Tui.Syntax.faceForByteRange Bliku.Tui.Syntax.defaultPalette spans numS numE)assertEqual "Lean comment style" (Bliku.Tui.Syntax.defaultPalette.faceFor .comment)(Bliku.Tui.Syntax.faceForByteRange Bliku.Tui.Syntax.defaultPalette spans comS comE)
assertEqual "Markdown code style" (some ViE.UI.Syntax.markdownCodeStyle) (ViE.UI.Syntax.styleForByteRange spans codeS codeE)assertEqual "Markdown link style" (some ViE.UI.Syntax.markdownLinkStyle) (ViE.UI.Syntax.styleForByteRange spans linkS linkE)
assertEqual "Markdown code style" (Bliku.Tui.Syntax.defaultPalette.faceFor .code)(Bliku.Tui.Syntax.faceForByteRange Bliku.Tui.Syntax.defaultPalette spans codeS codeE)assertEqual "Markdown link style" (Bliku.Tui.Syntax.defaultPalette.faceFor .link)(Bliku.Tui.Syntax.faceForByteRange Bliku.Tui.Syntax.defaultPalette spans linkS linkE)
assert "File explorer opens in floating window" (ws1.isFloatingWindow ws1.activeWindowId)
assert "File explorer opens in regular window" (!ws1.isFloatingWindow ws1.activeWindowId)let model1 := ViE.BlikuAdapter.toModel s1let explorerClustered :=match model1.workspace.floatingClusters[0]? with| some cluster =>match cluster.root, cluster.sizePolicy with| .group gid, .multiPane => gid == buf.id| _, _ => false| none => falseassert "Bliku adapter lifts explorer/preview into floating multi-pane cluster" explorerClustered
let ws1 := s1.getCurrentWorkspacematch s1.getFloatingWindowBounds ws1.activeWindowId, s1.getFloatingWindowBounds wid with| some (et, el, eh, ew), some (pt, pl, ph, pw) =>
let bounds := ViE.Window.getAllWindowBounds s1.getCurrentWorkspace.layout(if s1.windowHeight > 0 then s1.windowHeight - 1 else 0) s1.windowWidthmatch bounds.find? (fun (id, _, _, _, _) => id == s1.getCurrentWorkspace.activeWindowId),bounds.find? (fun (id, _, _, _, _) => id == wid) with| some (_, et, el, eh, ew), some (_, pt, pl, ph, pw) =>
-- SplitsvSplitStr := "│"hSplitStr := "─"-- Cursor / selection / searchsearchHighlightStyle := (toBg Color.white) ++ (toFg Color.black)searchHighlightCursorStyle := (toBg Color.yellow) ++ (toFg Color.black)visualSelectionStyle := "\x1b[7m"cursorCharStyle := (toBg Color.white) ++ (toFg Color.black)cursorSpaceStyle := (toBg Color.white) ++ (toFg Color.black)-- Explorer / previewexplorerPreviewSplitRatio := 0.5-- Editing
--fileIcon := "File: "--dirIcon := "Dir : "
resetStyle := ViE.Color.reset-- Explorer iconsfileIcon := "📄 "dirIcon := "📁 "-- Search bloom cachesearchBloomCacheMax := 1024searchBloomBuildLeafBits := truesearchBloomBuildOnEdit := false-- HistoryhistoryLimit := 200-- Examples:-- fileIcon := "File: "-- dirIcon := "Dir : "-- explorerPreviewSplitRatio := 0.62-- tabStop := 4-- showLineNumbers := false