mirror of
https://github.com/c-cube/linol.git
synced 2025-12-12 22:10:58 -05:00
git-subtree-dir: thirdparty/lsp git-subtree-split: aae6986391a8519de3da6a7a341f2bd3376e0d2f
191 lines
4.8 KiB
OCaml
191 lines
4.8 KiB
OCaml
open Stdune
|
|
module String_zipper = Lsp.Private.String_zipper
|
|
module Substring = Lsp.Private.Substring
|
|
|
|
let to_dyn { String_zipper.Private.left; rel_pos; current; right; line; abs_pos } =
|
|
let open Dyn in
|
|
let sub x = string (Substring.to_string x) in
|
|
let subs = list sub in
|
|
record
|
|
[ "left", subs left
|
|
; "rel_pos", int rel_pos
|
|
; "abs_pos", int abs_pos
|
|
; "current", sub current
|
|
; "right", subs right
|
|
; "line", int line
|
|
]
|
|
;;
|
|
|
|
type op =
|
|
[ `Goto_line of int
|
|
| `Insert of string
|
|
]
|
|
|
|
let test ?(which = `All) mode start operations =
|
|
let results =
|
|
List.fold_left
|
|
operations
|
|
~init:[ `Hide, start ]
|
|
~f:(fun acc (op : [ op | `Hide of op ]) ->
|
|
let final =
|
|
let _, last = List.hd acc in
|
|
let commit_op op =
|
|
match op with
|
|
| `Insert s -> String_zipper.insert last s
|
|
| `Goto_line g -> String_zipper.goto_line last g
|
|
in
|
|
match op with
|
|
| `Hide op -> `Hide, commit_op op
|
|
| #op as x -> `Show, commit_op x
|
|
in
|
|
final :: acc)
|
|
|> List.rev
|
|
|> List.tl
|
|
in
|
|
let results =
|
|
match which with
|
|
| `All -> results
|
|
| `Last -> [ List.rev results |> List.hd ]
|
|
in
|
|
List.filter_map results ~f:(fun (display, res) ->
|
|
match display with
|
|
| `Hide -> None
|
|
| `Show -> Some res)
|
|
|> List.iter ~f:(fun res ->
|
|
let res =
|
|
match mode with
|
|
| `Dyn -> String_zipper.Private.reflect res |> to_dyn |> Dyn.to_string
|
|
| `String ->
|
|
let line = (String_zipper.Private.reflect res).line in
|
|
Printf.sprintf "line %d: %S" line (String_zipper.to_string_debug res)
|
|
in
|
|
Printf.printf "%s\n" res)
|
|
;;
|
|
|
|
let%expect_test "goto line" =
|
|
let foo = String_zipper.of_string "foo\nX\nY" in
|
|
test `String foo [ `Goto_line 0 ];
|
|
[%expect {| line 0: "|foo\nX\nY" |}];
|
|
test
|
|
`String
|
|
foo
|
|
[ `Goto_line 0
|
|
; `Goto_line 1
|
|
; `Goto_line 2
|
|
; `Goto_line 3
|
|
; `Goto_line 2
|
|
; `Goto_line 1
|
|
; `Goto_line 0
|
|
; `Goto_line 0
|
|
];
|
|
[%expect
|
|
{|
|
|
line 0: "|foo\nX\nY"
|
|
line 1: "foo\n|X\nY"
|
|
line 2: "foo\nX\n|Y"
|
|
line 2: "foo\nX\nY|"
|
|
line 2: "foo\nX\n|Y"
|
|
line 1: "foo\n|X\nY"
|
|
line 0: "|foo\nX\nY"
|
|
line 0: "|foo\nX\nY" |}];
|
|
test `String (String_zipper.of_string "") [ `Goto_line 100; `Goto_line 0 ];
|
|
[%expect
|
|
{|
|
|
line 0: "|"
|
|
line 0: "|" |}];
|
|
test `String foo [ `Insert "baz"; `Goto_line 1; `Insert "1" ];
|
|
[%expect
|
|
{|
|
|
line 0: "|bazfoo\nX\nY"
|
|
line 1: "bazfoo\n|X\nY"
|
|
line 1: "bazfoo\n|1X\nY" |}]
|
|
;;
|
|
|
|
let%expect_test "insertions" =
|
|
let foo = String_zipper.of_string "foo" in
|
|
test `String foo [ `Insert "" ];
|
|
[%expect
|
|
{|
|
|
line 0: "|foo" |}];
|
|
test `String foo [ `Insert "a" ];
|
|
[%expect
|
|
{|
|
|
line 0: "|afoo" |}];
|
|
test `String foo [ `Insert "a"; `Insert "b" ];
|
|
[%expect
|
|
{|
|
|
line 0: "|afoo"
|
|
line 0: "|bafoo" |}]
|
|
;;
|
|
|
|
let%expect_test "mixed insert goto" =
|
|
let foo = String_zipper.of_string "foo" in
|
|
test `String foo [ `Insert "XXX"; `Insert "YYY"; `Insert "zzz" ];
|
|
[%expect
|
|
{|
|
|
line 0: "|XXXfoo"
|
|
line 0: "|YYYXXXfoo"
|
|
line 0: "|zzzYYYXXXfoo" |}]
|
|
;;
|
|
|
|
let%expect_test "drop_until" =
|
|
let t = String_zipper.of_string "foo\nbar\nxxx" in
|
|
let t = String_zipper.goto_line t 1 in
|
|
let t' = String_zipper.goto_line t 2 in
|
|
let t = String_zipper.drop_until t t' in
|
|
printfn "%S" (String_zipper.to_string_debug t);
|
|
[%expect
|
|
{|
|
|
"foo\n|xxx" |}];
|
|
let t = String_zipper.of_string "foo\nbar\n" in
|
|
let t = String_zipper.goto_line t 2 in
|
|
let t = String_zipper.drop_until t t in
|
|
printfn "%S" (String_zipper.to_string_debug t);
|
|
[%expect
|
|
{|
|
|
"foo\nbar\n|" |}];
|
|
let t = String_zipper.of_string "123\n" in
|
|
let t = String_zipper.goto_line t 1 in
|
|
let t = String_zipper.drop_until t t in
|
|
printfn "%S" (String_zipper.to_string_debug t);
|
|
[%expect {| "123\n|" |}]
|
|
;;
|
|
|
|
let%expect_test "squashing" =
|
|
let str = "foo\nbar" in
|
|
let t = String_zipper.of_string str in
|
|
let t = String_zipper.goto_line t 1 in
|
|
let t, str' = String_zipper.squash t in
|
|
assert (String.equal str str');
|
|
printfn "squashing: %S" (String_zipper.to_string_debug t);
|
|
[%expect
|
|
{|
|
|
squashing: "foo\n|bar" |}]
|
|
;;
|
|
|
|
let%expect_test "add buffer between" =
|
|
let str = "foo\nbar" in
|
|
let t = String_zipper.of_string str in
|
|
let t' = String_zipper.goto_line t 1 in
|
|
let b = Buffer.create 0 in
|
|
String_zipper.add_buffer_between b t t';
|
|
printfn "result: %S" (Buffer.contents b);
|
|
[%expect
|
|
{|
|
|
result: "foo\n" |}]
|
|
;;
|
|
|
|
let%expect_test "drop_until bug" =
|
|
let t = String_zipper.of_string "foo\nbar\nxxx" in
|
|
let t' = String_zipper.goto_line t 10 in
|
|
let t = String_zipper.goto_line t 2 in
|
|
let t = String_zipper.drop_until t t' in
|
|
printfn "%S" (String_zipper.to_string_debug t);
|
|
[%expect
|
|
{|
|
|
"foo\nbar\n|" |}];
|
|
printfn "abs_pos: %d" (String_zipper.Private.reflect t).abs_pos;
|
|
[%expect
|
|
{|
|
|
abs_pos: 8 |}]
|
|
;;
|