package tiny_libs
Source file Text.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(* 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 Text.mli *) (*****************************************************************************) (* Characters, not bytes *) (*****************************************************************************) (* a byte whose top bits are 10 continues the character before it *) let continues s i = Char.code s.[i] land 0xC0 = 0x80 let rec start_of_char s i = if i <= 0 then 0 else if continues s i then start_of_char s (i - 1) else i let prev_char s i = if i <= 0 then 0 else start_of_char s (i - 1) let next_char s i = let n = String.length s in let rec go i = if i >= n || not (continues s i) then i else go (i + 1) in if i >= n then n else go (i + 1) (*****************************************************************************) (* Cells *) (*****************************************************************************) let chars s = let rec go i acc = if i >= String.length s then List.rev acc else let j = next_char s i in go j (String.sub s i (j - i) :: acc) in go 0 [] let column s i = List.length (chars (String.sub s 0 (min i (String.length s)))) let byte_of_column s col = let rec go i col = if col <= 0 || i >= String.length s then i else go (next_char s i) (col - 1) in go 0 col (*****************************************************************************) (* One frame of typing *) (*****************************************************************************) let edit ~typed ~pressed text caret = let caret = max 0 (min (String.length text) caret) in let text, caret = if typed = "" then (text, caret) else ( String.sub text 0 caret ^ typed ^ String.sub text caret (String.length text - caret), caret + String.length typed ) in let text, caret = if pressed "Backspace" && caret > 0 then let from = prev_char text caret in (String.sub text 0 from ^ String.sub text caret (String.length text - caret), from) else (text, caret) in let text, caret = if pressed "Delete" && caret < String.length text then let upto = next_char text caret in (String.sub text 0 caret ^ String.sub text upto (String.length text - upto), caret) else (text, caret) in let caret = if pressed "ArrowLeft" then prev_char text caret else caret in let caret = if pressed "ArrowRight" then next_char text caret else caret in let caret = if pressed "Home" then 0 else caret in let caret = if pressed "End" then String.length text else caret in (text, caret)