@@ -32,6 +32,8 @@ open Std
3232open Typedtree
3333open Browse_raw
3434
35+ type direction = Prev | Next
36+
3537let is_node_fun = function
3638 | Expression { exp_desc = Texp_function _ ; _ } -> true
3739 | _ -> false
@@ -104,6 +106,8 @@ let rec find_map ~f = function
104106
105107exception No_matching_target
106108exception No_predicate of string
109+ exception No_next_match_case
110+ exception No_prev_match_case
107111
108112(* Returns first node on the list matching a predicate *)
109113let rec find_node preds nodes =
@@ -127,19 +131,50 @@ let rec skip_non_moving pos = function
127131 | [] -> []
128132;;
129133
134+ let get_cases_from_match node =
135+ match node with
136+ | Expression { exp_desc = Texp_match (_ , cases , _ ); _ } -> cases
137+ | _ -> []
138+
139+ let find_case_pos cases pos direction =
140+ let rec find_pos pos cases direction =
141+ match cases with
142+ | [] -> None
143+ | { c_lhs = { pat_loc; _ } ; _ } :: tail ->
144+ let check =
145+ match direction with
146+ | Prev ->
147+ pos.Lexing. pos_cnum > pat_loc.loc_start.pos_cnum
148+ | Next ->
149+ pos.Lexing. pos_cnum < pat_loc.loc_start.pos_cnum
150+ in
151+ if check then
152+ Some pat_loc.loc_start
153+ else
154+ find_pos pos tail direction
155+ in
156+ let case = find_pos pos cases direction in
157+ match case with
158+ | Some location -> `Found location
159+ | None ->
160+ (match direction with
161+ | Next -> raise No_next_match_case
162+ | Prev -> raise No_prev_match_case )
163+
130164let get typed_tree pos target =
131165 let roots = Mbrowse. of_typedtree typed_tree in
132166 let enclosings =
133167 match Mbrowse. enclosing pos [roots] with
134168 | [] -> []
135169 | l -> List. map ~f: snd l
136170 in
137-
138171 let all_preds = [
139172 " fun" , fun_pred;
140173 " let" , let_pred;
141174 " module" , module_pred;
142175 " match" , match_pred;
176+ " match-next-case" , match_pred;
177+ " match-prev-case" , match_pred;
143178 ] in
144179 let targets = Str. split (Str. regexp " [, ]" ) target in
145180 try
@@ -152,17 +187,25 @@ let get typed_tree pos target =
152187 in
153188 if String. length target = 0 then
154189 `Error " Specify target"
155- else begin
190+ else
156191 let nodes = skip_non_moving pos enclosings in
157192 let node = find_node preds nodes in
158- let node_loc = Browse_raw. node_real_loc Location. none node in
159- `Found node_loc.Location. loc_start
160- end
193+ match target with
194+ | "match-next-case" -> find_case_pos (get_cases_from_match node) pos Next
195+ | "match-prev-case" ->
196+ find_case_pos (List. rev (get_cases_from_match node)) pos Prev
197+ | _ ->
198+ let node_loc = Browse_raw. node_real_loc Location. none node in
199+ `Found node_loc.Location. loc_start
161200 with
162201 | No_predicate target ->
163202 `Error (" No predicate for " ^ target)
164203 | No_matching_target ->
165204 `Error " No matching target"
205+ | No_next_match_case ->
206+ `Error " No next case found"
207+ | No_prev_match_case ->
208+ `Error " No previous case found"
166209
167210let phrase typed_tree pos target =
168211 let roots = Mbrowse. of_typedtree typed_tree in
0 commit comments