Skip to content
This repository
Newer
Older
100644 124 lines (110 sloc) 3.877 kb
fccc6851 » MLstate
2011-06-21 Initial open-source release
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18
19 type anim = string array array
20
21 type t = {
22 och : out_channel ;
23 step : int ref ;
24 auto_walking : bool ;
25 walk_anim : anim ;
26 turn_anim : anim ;
27 walk_anim_rev : anim ;
28 turn_anim_rev : anim ;
29 }
30
31 (* please, extend it if needed *)
32 let reverse_char = function
33 | '\\' -> '/'
34 | '/' -> '\\'
35 | '(' -> ')'
36 | ')' -> '('
37 | '[' -> ']'
38 | ']' -> '['
39 | '{' -> '}'
40 | '}' -> '{'
41 | '<' -> '>'
42 | '>' -> '<'
43 | c -> c
44
45 (* sorry, we can't use String.init because Base depends on Journal *)
46 let reverse_string s =
47 let len = String.length s in
48 let s' = String.make len ' ' in
49 for i = 0 to len - 1 do
50 s'.[i] <- reverse_char s.[len - 1 - i]
51 done;
52 s'
53
54 let print_frame och pos frame =
55 let output s = Pervasives.output_string och s in
56 let flush () = Pervasives.flush och in
57 let reset =
58 let n = Array.length frame in
59 if n > 1 then Printf.sprintf "\027[%dA\r" (n-1) else "\r" in
60 output "\r";
61 (* Print the frame *)
62 Array.iteri
63 (fun i l ->
64 if i <> 0 then output "\027E";
65 if pos <> 0 then output (Printf.sprintf "\027[%dC" pos);
66 output l)
67 frame;
68 output reset;
69 (* Then flush and clear, so that it's absent in further console printings *)
70 flush ();
71 (* if pos <> 0 then output (Printf.sprintf "\027[%dC" pos); *)
72 (* if Array.length frame <> 0 *)
73 (* then output (String.make (String.length frame.(0)) ' '); *)
74 Array.iteri
75 (fun i l ->
76 if i <> 0 then output "\027E";
77 if pos <> 0 then output (Printf.sprintf "\027[%dC" pos);
78 output (String.make (String.length l) ' '))
79 frame;
80 (* Replace the cursor where it was found *)
81 output reset
82
83 let anim t x =
84 let print_frame = print_frame t.och in
85 let walk_length = Array.length t.walk_anim in
86 let turn_length = Array.length t.turn_anim in
87 let i = x mod ((60 * walk_length + turn_length) * 2) in
88 if i < 60 * walk_length then
89 print_frame (if t.auto_walking then i / walk_length else 0) t.walk_anim.(i mod walk_length)
90 else if i < 60 * walk_length + turn_length then
91 print_frame (if t.auto_walking then 59 else 0) t.turn_anim.(i - 60 * walk_length)
92 else if i < 120 * walk_length + turn_length then
93 let j = i - 60 * walk_length - turn_length in
94 print_frame (if t.auto_walking then 60 - j / walk_length else 0) t.walk_anim_rev.(j mod walk_length)
95 else
96 let j = i - 120 * walk_length - turn_length in
97 print_frame 0 t.turn_anim_rev.(j)
98
99 let check ~auto_walking walk_anim turn_anim =
100 if auto_walking then begin
101 let check_frame frame =
102 if Array.length frame > 0 then
103 let l = String.length frame.(0) in
104 Array.iter (fun s -> if String.length s <> l then failwith "Different frame lengths") frame
105 in
106 Array.iter check_frame walk_anim;
107 Array.iter check_frame turn_anim
108 end
109
110 let init ?(och=stdout) ~auto_walking walk_anim turn_anim =
111 check ~auto_walking walk_anim turn_anim;
112 {
113 och = och ;
114 step = ref 0 ;
115 auto_walking = auto_walking ;
116 walk_anim = walk_anim ;
117 turn_anim = turn_anim ;
118 walk_anim_rev = Array.map (Array.map reverse_string) walk_anim ;
119 turn_anim_rev = Array.map (Array.map reverse_string) turn_anim ;
120 }
121
122 let reset t = t.step := 0
123
124 let update t = anim t !(t.step); incr t.step
Something went wrong with that request. Please try again.