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_editor/Turbo_menus.ml.html
Source file Turbo_menus.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 122 123 124 125 126 127 128 129 130(* 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 Turbo_menus.mli *) open Turbo_model let item label hot shortcut action = { label; hot; shortcut; action } let : (string * item list) list = [ ( "File", [ item "Open..." 'O' "F3" Open; item "New" 'N' "" New; item "Save" 'S' "F2" Save; item "Save as..." 'a' "" Save_as; item "Exit" 'x' "Alt+X" Exit ] ); ("Search", [ item "Find..." 'F' "" Find; item "Search again" 'S' "Ctrl+L" Find_again; item "Go to line number..." 'G' "" Goto_line ]); ( "Run", [ item "Run" 'R' "Ctrl+F9" Run; item "Step over" 'S' "F8" Step_over; item "Trace into" 'T' "F7" Trace_into; item "Go to cursor" 'G' "F4" Go_to_cursor; item "Program reset" 'P' "Ctrl+F2" Reset; item "User screen" 'U' "Alt+F5" User_screen ] ); ("Compile", [ item "Compile" 'C' "Alt+F9" Compile; item "Make" 'M' "F9" Compile; item "P-code" 'P' "" Pcode_listing ]); ( "Debug", [ item "Call stack" 'C' "Ctrl+F3" Call_stack; item "Add watch..." 'W' "Ctrl+F7" Add_watch; item "Toggle breakpoint" 'B' "Ctrl+F8" Toggle_breakpoint; item "Remove all watches" 'R' "" Clear_watches ] ); ("Help", [ item "Keys" 'K' "F1" Keys; item "About..." 'A' "" About ]) ] (*****************************************************************************) (* Menus and dialogs *) (*****************************************************************************) let files (m : model) : string list = List.sort compare (List.map fst m.disk) let write (m : model) (file : string) : model = { m with disk = (file, Turbo_edit.text m) :: List.remove_assoc file m.disk; file; modified = false } let act (m : model) (a : action) : model = let m = { m with mode = Editing } in match a with | Open -> { m with mode = Open_dialog 0 } | New -> { (Turbo_edit.load m "") with lines = [| "" |]; file = Turbo_edit.noname } | Save -> if m.file = Turbo_edit.noname then { m with mode = Input { title = "Save File As"; label = "Save file as"; text = ""; purpose = Saving_as } } else write m m.file | Save_as -> { m with mode = Input { title = "Save File As"; label = "Save file as"; text = ""; purpose = Saving_as } } | Exit -> { m with quit = true } | Find -> { m with mode = Input { title = "Find"; label = "Text to find"; text = m.search; purpose = Finding } } | Find_again -> Turbo_edit.find m m.search | Goto_line -> { m with mode = Input { title = "Go to Line Number"; label = "Enter new line number"; text = ""; purpose = Going_to } } | Run -> Turbo_debug.go m (Continue m.breakpoints) | Trace_into -> Turbo_debug.go m Trace_into | Step_over -> Turbo_debug.go m Step_over | Go_to_cursor -> Turbo_debug.go m (To_line (m.row + 1)) | Reset -> { m with session = None } | User_screen -> ( match (m.session, m.last_screen) with | Some s, _ -> { m with mode = Showing s.user } | None, Some vt -> { m with mode = Showing vt } | None, None -> { m with mode = Showing (Vt.create ~rows:24 ~cols:80) }) | Call_stack -> if m.session = None then { m with mode = Info ("Call Stack", [ "No program is running:"; "F7 or F8 starts one." ]) } else { m with mode = Stack } | Add_watch -> { m with mode = Input { title = "Add Watch"; label = "Watch expression"; text = Turbo_debug.word_at m; purpose = Watching } } | Toggle_breakpoint -> let l = m.row + 1 in { m with breakpoints = (if List.mem l m.breakpoints then List.filter (( <> ) l) m.breakpoints else l :: m.breakpoints) } | Clear_watches -> { m with watches = [] } | Compile -> ( match Turbo_debug.compile m with Ok (p, m) -> Turbo_debug.compiled_box m p | Error m -> m) | Pcode_listing -> ( match Turbo_debug.compile m with | Error m -> m | Ok (p, m) -> (* from the first instruction of the cursor's line *) let first = ref 0 in (try Array.iteri (fun i l -> if l >= m.row + 1 then (first := i; raise Exit)) p.lines with Exit -> ()); { m with mode = Listing (max 0 (!first - 3)) }) | Keys -> { m with mode = Info ( "Keys", [ "F9 Make Alt+F9 Compile Ctrl+F9 Run"; "Alt+F5 User screen F2 Save F3 Open"; "F10 or Alt+letter: the menus Alt+X Exit"; ""; "F7 Trace into F8 Step over F4 Go to cursor"; "Ctrl+F8 Breakpoint Ctrl+F7 Watch Ctrl+F3 Calls"; "Ctrl+F2 Reset Ctrl+C Break"; ""; "Arrows, or Ctrl+E X S D Ctrl+A F words"; "Ctrl+Y delete a line Insert: overwrite"; "Ctrl+L search again"; ""; "No F keys? Esc then 1 to 0 (or Alt+1 to Alt+0): F1 to F10,"; "Ctrl+1 to Ctrl+0: Ctrl+F1 to Ctrl+F10 (Ctrl+9 Run)" ] ) } | About -> { m with mode = Info ( "About", [ "Tiny Turbo Pascal"; ""; "after Turbo Pascal 7.0"; "Anders Hejlsberg, Borland, 1983-1992"; ""; "compiled to P-code, as Wirth's Pascal-P"; "and UCSD Pascal did" ] ) } (* Alt and a letter, as xterm sends it: Escape then the letter *) let alt_letter (k : string) : char option = if String.length k = 2 && k.[0] = '\x1b' then Some (Char.lowercase_ascii k.[1]) else None let (c : char) : int option = let rec go i = function [] -> None | (title, _) :: rest -> if Char.lowercase_ascii title.[0] = c then Some i else go (i + 1) rest in go 0 menus let (m : model) (bar : int) (sel : int) (k : string) : model = let items = snd (List.nth menus bar) in let n = List.length items and nbar = List.length menus in match k with | "\x1b" -> { m with mode = Editing } | "\x1b[D" -> { m with mode = Menu ((bar + nbar - 1) mod nbar, 0) } | "\x1b[C" -> { m with mode = Menu ((bar + 1) mod nbar, 0) } | "\x1b[A" -> { m with mode = Menu (bar, (sel + n - 1) mod n) } | "\x1b[B" -> { m with mode = Menu (bar, (sel + 1) mod n) } | "\r" -> act m (List.nth items sel).action | _ -> ( match alt_letter k with | Some c -> ( match menu_of_letter c with Some b -> { m with mode = Menu (b, 0) } | None -> m) | None -> ( let c = if String.length k = 1 then Some (Char.lowercase_ascii k.[0]) else None in match List.find_opt (fun it -> Some (Char.lowercase_ascii it.hot) = c) items with Some it -> act m it.action | None -> m)) let input_key (m : model) (title, label, text, purpose) (k : string) : model = let again text = { m with mode = Input { title; label; text; purpose } } in match k with | "\x1b" -> { m with mode = Editing } | "\r" -> ( let m = { m with mode = Editing } in match purpose with | Saving_as -> if text = "" then m else write m (String.uppercase_ascii text) | Finding -> Turbo_edit.find m text | Going_to -> ( match int_of_string_opt (String.trim text) with Some n -> { m with row = n - 1; col = 0 } | None -> m) | Watching -> if String.trim text = "" then m else { m with watches = m.watches @ [ String.trim text ] }) | "\x7f" | "\b" -> again (if text = "" then "" else String.sub text 0 (String.length text - 1)) | _ when String.length k = 1 && k.[0] >= ' ' -> again (text ^ k) | _ -> m
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>