From: Michael D. Lowis Date: Sat, 4 Nov 2017 03:38:29 +0000 (-0400) Subject: added and tested nextc and prevc functions. Updated scrollmap to use them X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=a5a3cd157b901e985d4a04da5aebd119802a42d2;p=archive%2Ftide-ocaml.git added and tested nextc and prevc functions. Updated scrollmap to use them --- diff --git a/lib/rope.ml b/lib/rope.ml index 9956d51..5c078db 100644 --- a/lib/rope.ml +++ b/lib/rope.ml @@ -12,6 +12,8 @@ let empty = Leaf ("", 0, 0) let from_string s = Leaf (s, 0, (String.length s)) +(******************************************************************************) + let length = function | Leaf (_,_,l) -> l | Node (_,_,_,l) -> l @@ -33,6 +35,8 @@ let check_index rope i = if i < 0 || i >= (length rope) then raise (Out_of_bounds "Rope.check_index") +(******************************************************************************) + let join left right = let llen = (length left) and rlen = (length right) in if llen == 0 then right @@ -40,11 +44,15 @@ let join left right = else let lh = (height left) and rh = (height right) in let nh = 1 + lh + rh in + Node (left, right, nh, llen + rlen) + +(* let n = Node (left, right, nh, llen + rlen) in match (lh - rh) with | 0 -> n | 1 -> n | -1 -> n +*) let rec split rope i = if i < 0 || i > (length rope) then @@ -66,6 +74,8 @@ let del rope i j = let (r_left,r_right) = split l_right (j - i) in (join l_left r_right) +(******************************************************************************) + let rec getb rope i = check_index rope i; match rope with @@ -98,6 +108,8 @@ let rec getc rope i = let putc rope i c = rope +(******************************************************************************) + let rec iter_from fn rope pos = if pos < (length rope) && (fn (getc rope pos)) then iter_from fn rope (pos + 1) @@ -106,6 +118,8 @@ let rec iteri_from fn rope pos = if pos < (length rope) && (fn pos (getc rope pos)) then iteri_from fn rope (pos + 1) +(******************************************************************************) + let gets rope i j = let buf = Bytes.create (j - i) in iteri_from @@ -120,17 +134,38 @@ let rec puts rope s i = let middle = from_string s in (join (join left middle) right) +(******************************************************************************) + +let nextc rope pos = + let next = limit_index rope (pos + 1) in + if (getb rope pos) == '\r' && (getb rope next) == '\n' then + limit_index rope (pos + 2) + else + next + +let prevc rope pos = + let prev1 = limit_index rope (pos - 1) in + let prev2 = limit_index rope (pos - 2) in + if (getb rope prev2) == '\r' && (getb rope prev1) == '\n' then + prev2 + else + prev1 + +(******************************************************************************) + let is_bol rope pos = if pos == 0 then true - else ((getc rope (pos-1)) == 0x0A) + else let prev = (prevc rope pos) in + ((getc rope prev) == 0x0A) let is_eol rope pos = if pos >= (last rope) then true - else ((getc rope (pos+1)) == 0x0A) + else ((getc rope pos) == 0x0A) let rec move_till step testfn rope pos = + let adjust_pos = if step < 0 then prevc else nextc in if (testfn rope pos) then pos - else (move_till step testfn rope (pos + step)) + else (move_till step testfn rope (adjust_pos rope pos)) let to_bol rope pos = move_till (-1) is_bol rope pos diff --git a/lib/rope.mli b/lib/rope.mli index 0f7e63f..227323b 100644 --- a/lib/rope.mli +++ b/lib/rope.mli @@ -28,6 +28,9 @@ val putc : rope -> int -> rune -> rope val gets : rope -> int -> int -> string val puts : rope -> string -> int -> rope +val nextc : rope -> int -> int +val prevc : rope -> int -> int + val is_bol : rope -> int -> bool val is_eol : rope -> int -> bool diff --git a/lib/scrollmap.ml b/lib/scrollmap.ml index a8368fd..6852a26 100644 --- a/lib/scrollmap.ml +++ b/lib/scrollmap.ml @@ -28,12 +28,12 @@ let first map = map.lines.(map.index) let bopl buf off = - let next = ((Rope.to_bol (Buf.rope buf) off) - 2) in - Rope.limit_index (Buf.rope buf) next + let rope = (Buf.rope buf) in + Rope.prevc rope (Rope.to_bol rope off) let bonl buf off = - let next = ((Rope.to_eol (Buf.rope buf) off) + 2) in - Rope.limit_index (Buf.rope buf) next + let rope = (Buf.rope buf) in + Rope.nextc rope (Rope.to_eol rope off) let scroll_up map buf = let next = map.index - 1 in diff --git a/tests/rope_tests.ml b/tests/rope_tests.ml index 5ec2bbf..7524569 100644 --- a/tests/rope_tests.ml +++ b/tests/rope_tests.ml @@ -112,6 +112,34 @@ let () = assert( (getc rope (2)) == Char.code 'c' ); ); + (* nextc() tests *) + test "nextc : should return pos if at end of buffer" (fun () -> + let rope = Leaf("abc", 0, 3) in + assert( 2 == (nextc rope 2) ); + ); + test "nextc : should return pos of next char" (fun () -> + let rope = Leaf("a\na", 0, 3) in + assert( 2 == (nextc rope 1) ); + ); + test "nextc : should return pos of next char" (fun () -> + let rope = Leaf("a\r\na", 0, 4) in + assert( 3 == (nextc rope 1) ); + ); + + (* prevc() tests *) + test "prevc : should return pos if at start of buffer" (fun () -> + let rope = Leaf("abc", 0, 3) in + assert( 0 == (prevc rope 0) ); + ); + test "prevc : should return pos of prev char" (fun () -> + let rope = Leaf("a\na", 0, 3) in + assert( 1 == (prevc rope 2) ); + ); + test "prevc : should return pos of prev char" (fun () -> + let rope = Leaf("a\r\na", 0, 4) in + assert( 1 == (prevc rope 3) ); + ); + (* is_bol() tests *) test "is_bol : should return true if pos is 0" (fun () -> let rope = Leaf("abc", 0, 3) in @@ -137,7 +165,7 @@ let () = ); test "is_eol : should return true if pos is last char of line with \n ending" (fun () -> let rope = Leaf("abc\n", 0, 4) in - assert( is_eol rope 2 ); + assert( is_eol rope 3 ); ); test "is_eol : should return true if pos is last char of line with \r\n ending" (fun () -> let rope = Leaf("abc\r\n", 0, 5) in