let from_string s =
Leaf (s, 0, (String.length s))
+(******************************************************************************)
+
let length = function
| Leaf (_,_,l) -> l
| Node (_,_,_,l) -> l
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
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
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
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)
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
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
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
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
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
);
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