package tiny_appkits
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Application engines from scratch: a spreadsheet, rich text, paint, draw, CAD, editors and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_appkits.appkit_blocks/Block_edit.ml.html
Source file Block_edit.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Block_edit.mli *) open Scratch_blocks open Block_layout type dragged = Stack of block list | Reporter of block (* a path's steps: those to a block (to its last At: a block in a ring's mouth is down the stacks, into an argument, into its mouth), then those into its slots *) let split steps = let last_at = List.fold_left (fun (i, last) s -> (i + 1, match s with At _ -> i | _ -> last)) (0, -1) steps |> snd in (List.filteri (fun i _ -> i <= last_at) steps, List.filteri (fun i _ -> i > last_at) steps) (* the stack the steps end in, changed by f: down the stacks by At, into a block by its mouths and its arguments *) let rec map_stack steps f blocks = match steps with | [] -> f blocks | At i :: rest -> List.mapi (fun k b -> if k = i then map_in rest f b else b) blocks | _ -> blocks and map_in steps f (b : block) = match steps with | Mouth m :: rest -> { b with mouths = List.mapi (fun j ms -> if j = m then map_stack rest f ms else ms) b.mouths } | Arg a :: rest -> { b with args = List.mapi (fun k x -> match x with Block inner when k = a -> Block (map_in rest f inner) | _ -> x) b.args } | _ -> b (* the block the steps end at, changed by g *) let map_block steps g blocks = match List.rev steps with At i :: prefix -> map_stack (List.rev prefix) (List.mapi (fun k b -> if k = i then g b else b)) blocks | _ -> blocks (* the argument the Arg steps lead to in a block, changed by h *) let rec map_arg args h (b : block) = match args with | [ Arg a ] -> { b with args = List.mapi (fun k x -> if k = a then h x else x) b.args } | Arg a :: rest -> { b with args = List.mapi (fun k x -> match x with Block inner when k = a -> Block (map_arg rest h inner) | _ -> x) b.args } | _ -> b let rec get_stack steps blocks = match steps with | [] -> Some blocks | At i :: rest -> Option.bind (List.nth_opt blocks i) (get_in rest) | _ -> None and get_in steps (b : block) = match steps with | Mouth m :: rest -> Option.bind (List.nth_opt b.mouths m) (get_stack rest) | Arg a :: rest -> ( match List.nth_opt b.args a with Some (Block inner) -> get_in rest inner | _ -> None) | _ -> None let get_block steps blocks = match List.rev steps with At i :: prefix -> Option.bind (get_stack (List.rev prefix) blocks) (fun s -> List.nth_opt s i) | _ -> None let rec get_arg args (b : block) = match args with | [ Arg a ] -> List.nth_opt b.args a | Arg a :: rest -> ( match List.nth_opt b.args a with Some (Block inner) -> get_arg rest inner | _ -> None) | _ -> None let map_script scripts i f = List.mapi (fun k (sc : script) -> if k = i then { sc with blocks = f sc.blocks } else sc) scripts let take scripts (p : path) = match List.nth_opt scripts p.script with | None -> None | Some sc -> ( match split p.steps with | steps, [] -> ( match List.rev steps with | At i :: prefix -> ( let prefix = List.rev prefix in match get_stack prefix sc.blocks with | Some stack when i < List.length stack -> let taken = List.filteri (fun k _ -> k >= i) stack in let scripts = map_script scripts p.script (map_stack prefix (List.filteri (fun k _ -> k < i))) in let scripts = List.filter (fun (s : script) -> s.blocks <> []) scripts in Some (Stack taken, scripts) | _ -> None) | _ -> None) | steps, args -> ( match Option.bind (get_block steps sc.blocks) (get_arg args) with | Some (Block r) -> Some (Reporter r, map_script scripts p.script (map_block steps (map_arg args (fun _ -> Lit "")))) | _ -> None)) let drop ~measure scripts dragged target = match target with | Above i -> (* the script grows upwards, so that what was there stays put *) List.mapi (fun k (sc : script) -> if k = i then { sc with blocks = dragged @ sc.blocks; y = sc.y +. Block_layout.height ~measure dragged } else sc) scripts | Below p -> ( match List.rev p.steps with | At i :: prefix -> map_script scripts p.script (map_stack (List.rev prefix) (fun stack -> List.filteri (fun k _ -> k <= i) stack @ dragged @ List.filteri (fun k _ -> k > i) stack)) | _ -> scripts) | In_mouth (p, m) -> map_script scripts p.script (map_stack (p.steps @ [ Mouth m ]) (fun stack -> dragged @ stack)) let drop_in_slot scripts (p : path) r = let steps, args = split p.steps in map_script scripts p.script (map_block steps (map_arg args (fun _ -> Block r))) let alone scripts (x, y) blocks = scripts @ [ { x; y; blocks } ] let text scripts (p : path) = let steps, args = split p.steps in match Option.bind (List.nth_opt scripts p.script) (fun sc -> Option.bind (get_block steps sc.blocks) (get_arg args)) with | Some (Lit s) -> Some s | _ -> None let set_text scripts (p : path) s = let steps, args = split p.steps in map_script scripts p.script (map_block steps (map_arg args (function Lit _ -> Lit s | a -> a)))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>