@@ -118,34 +118,40 @@ let create_script coqtop source_buffer =
118
118
119
119
let misc () = CDebug. (get_flag misc)
120
120
121
+ type action_stack = Gtk .text_mark list option
122
+
123
+ let call_coq_or_cancel_action coqtop coqops (buffer : GText.buffer ) it =
124
+ let () = try buffer#delete_mark (`NAME " target" ) with GText. No_such_mark _ -> () in
125
+ let mark = buffer#create_mark ~name: " target" it in
126
+ let action = coqops#go_to_mark (`MARK mark) in
127
+ ignore @@ Coq. try_grab coqtop action (fun () -> () )
128
+
129
+ let init_user_action (stack : action_stack ref ) = match ! stack with
130
+ | None -> stack := Some []
131
+ | Some _ -> assert false
132
+
133
+ let close_user_action (stack : action_stack ref ) = match ! stack with
134
+ | None -> assert false
135
+ | Some marks ->
136
+ let () = stack := None in
137
+ marks
138
+
139
+ let handle_iter coqtop coqops (buffer : GText.buffer ) it stack = match it with
140
+ | None -> ()
141
+ | Some it ->
142
+ match ! stack with
143
+ | Some marks ->
144
+ (* We are inside an user action, deferring to its end *)
145
+ let mark = buffer#create_mark it in
146
+ stack := Some (mark :: marks)
147
+ | None ->
148
+ (* Otherwise we move to the mark now *)
149
+ call_coq_or_cancel_action coqtop coqops buffer it
150
+
121
151
let set_buffer_handlers
122
152
(buffer : GText.buffer ) script (coqops : CoqOps.ops ) coqtop
123
153
=
124
- let action_was_cancelled = ref true in
125
- let no_coq_action_required = ref true in
126
- let cur_action = ref 0 in
127
- let new_action_id =
128
- let id = ref 0 in
129
- fun () -> incr id; ! id in
130
- let running_action = ref None in
131
- let cancel_signal ?(stop_emit =true ) reason =
132
- Minilib. log (" user_action cancelled: " ^ reason);
133
- action_was_cancelled := true ;
134
- if stop_emit then GtkSignal. stop_emit () in
135
- let del_mark () =
136
- try buffer#delete_mark (`NAME " target" )
137
- with GText. No_such_mark _ -> () in
138
- let add_mark it = del_mark () ; buffer#create_mark ~name: " target" it in
139
- let call_coq_or_cancel_action f =
140
- no_coq_action_required := false ;
141
- let action = ! cur_action in
142
- let action, fallback =
143
- Coq. seq (Coq. lift (fun () -> running_action := Some action)) f,
144
- fun () -> (* If Coq is busy due to the current action, we don't cancel *)
145
- match ! running_action with
146
- | Some aid when aid = action -> ()
147
- | _ -> cancel_signal ~stop_emit: false " Coq busy" in
148
- ignore @@ Coq. try_grab coqtop action fallback in
154
+ let action_stack = ref None in
149
155
let get_start () = buffer#get_iter_at_mark (`NAME " start_of_input" ) in
150
156
let get_stop () = buffer#get_iter_at_mark (`NAME " stop_of_input" ) in
151
157
let ensure_marks_exist () =
@@ -172,63 +178,55 @@ let set_buffer_handlers
172
178
aux it it#copy in
173
179
let insert_cb it s = if String. length s = 0 then () else begin
174
180
if misc () then Minilib. log (" insert_cb " ^ string_of_int it#offset);
175
- let text_mark = add_mark it in
176
181
let () = update_prev it in
177
- if it#has_tag Tags.Script. to_process ||
178
- it#has_tag Tags.Script. incomplete then
179
- cancel_signal " Altering the script being processed is not implemented"
180
- else if it#has_tag Tags.Script. processed then
181
- (* note code in Wg_scriptview.keypress_cb *)
182
- call_coq_or_cancel_action (coqops#go_to_mark (`MARK text_mark))
183
- else if it#has_tag Tags.Script. error_bg then begin
184
- match processed_sentence_just_before_error it with
185
- | None -> ()
186
- | Some prev_sentence_end ->
187
- let text_mark = add_mark prev_sentence_end in
188
- call_coq_or_cancel_action (coqops#go_to_mark (`MARK text_mark))
189
- end end in
182
+ let iter =
183
+ if it#has_tag Tags.Script. processed then Some it
184
+ else if it#has_tag Tags.Script. error_bg then
185
+ processed_sentence_just_before_error it
186
+ else None
187
+ in
188
+ handle_iter coqtop coqops buffer iter action_stack
189
+ end
190
+ in
190
191
let delete_cb ~start ~stop =
191
192
if misc () then Minilib. log (Printf. sprintf " delete_cb %d %d" start#offset stop#offset);
192
193
let min_iter, max_iter =
193
194
if start#compare stop < 0 then start, stop else stop, start in
194
195
let () = update_prev min_iter in
195
- let text_mark = add_mark min_iter in
196
- let rec aux min_iter =
197
- if min_iter#equal max_iter then ()
198
- else if min_iter#has_tag Tags.Script. to_process ||
199
- min_iter#has_tag Tags.Script. incomplete then
200
- cancel_signal " Altering the script being processed is not implemented"
201
- else if min_iter#has_tag Tags.Script. processed then
202
- call_coq_or_cancel_action (coqops#go_to_mark (`MARK text_mark))
203
- else if min_iter#has_tag Tags.Script. error_bg then
204
- match processed_sentence_just_before_error min_iter with
205
- | None -> ()
206
- | Some prev_sentence_end ->
207
- let text_mark = add_mark prev_sentence_end in
208
- call_coq_or_cancel_action (coqops#go_to_mark (`MARK text_mark))
209
- else aux min_iter#forward_char in
210
- aux min_iter in
196
+ let rec aux iter =
197
+ if iter#equal max_iter then None
198
+ else if iter#has_tag Tags.Script. processed then
199
+ Some min_iter
200
+ else if iter#has_tag Tags.Script. error_bg then
201
+ processed_sentence_just_before_error iter
202
+ else aux iter#forward_char
203
+ in
204
+ let iter = aux min_iter in
205
+ handle_iter coqtop coqops buffer iter action_stack
206
+ in
211
207
let begin_action_cb () =
212
- if misc () then Minilib. log " begin_action_cb" ;
213
- action_was_cancelled := false ;
214
- no_coq_action_required := true ;
215
- cur_action := new_action_id () ;
208
+ let () = if misc () then Minilib. log " begin_action_cb" in
209
+ let () = init_user_action action_stack in
216
210
let where = get_insert () in
217
- buffer#move_mark (`NAME " prev_insert" ) ~where in
211
+ buffer#move_mark (`NAME " prev_insert" ) ~where
212
+ in
218
213
let end_action_cb () =
219
- if misc () then Minilib. log " end_action_cb" ;
220
- ensure_marks_exist () ;
221
- if not ! action_was_cancelled then begin
214
+ let () = if misc () then Minilib. log " end_action_cb" in
215
+ let marks = close_user_action action_stack in
216
+ let () = ensure_marks_exist () in
217
+ if CList. is_empty marks then
218
+ let start, stop = get_start () , get_stop () in
219
+ let () = List. iter (fun tag -> buffer#remove_tag tag ~start ~stop ) Tags.Script. ephemere in
220
+ Sentence. tag_on_insert buffer
221
+ else
222
222
(* If coq was asked to backtrack, the cleanup must be done by the
223
223
backtrack_until function, since it may move the stop_of_input
224
224
to a point indicated by coq. *)
225
- if ! no_coq_action_required then begin
226
- let start, stop = get_start () , get_stop () in
227
- List. iter (fun tag -> buffer#remove_tag tag ~start ~stop )
228
- Tags.Script. ephemere;
229
- Sentence. tag_on_insert buffer
230
- end ;
231
- end in
225
+ let iters = List. map (fun mark -> buffer#get_iter_at_mark (`MARK mark)) marks in
226
+ let iter = List. hd @@ List. sort (fun it1 it2 -> it1#compare it2) iters in
227
+ let () = List. iter (fun mark -> try buffer#delete_mark (`MARK mark) with GText. No_such_mark _ -> () ) marks in
228
+ call_coq_or_cancel_action coqtop coqops buffer iter
229
+ in
232
230
let mark_deleted_cb m =
233
231
match GtkText.Mark. get_name m with
234
232
| Some "insert" -> ()
@@ -244,7 +242,13 @@ let set_buffer_handlers
244
242
| Some s -> if misc () then Minilib. log (s^ " moved" )
245
243
| None -> ()
246
244
in
245
+ let set_busy b =
246
+ let prop = `EDITABLE b in
247
+ let tags = [Tags.Script. processed] in
248
+ List. iter (fun tag -> tag#set_property prop) tags
249
+ in
247
250
(* Pluging callbacks *)
251
+ let () = Coq. setup_script_editable coqtop set_busy in
248
252
let _ = buffer#connect#insert_text ~callback: insert_cb in
249
253
let _ = buffer#connect#delete_range ~callback: delete_cb in
250
254
let _ = buffer#connect#begin_user_action ~callback: begin_action_cb in
@@ -409,7 +413,6 @@ let create file coqtop_args =
409
413
let reset () = Coq. reset_coqtop coqtop in
410
414
let buffer = create_buffer () in
411
415
let script = create_script coqtop buffer in
412
- Coq. setup_script_editable coqtop (fun v -> script#set_editable2 v);
413
416
let proof = create_proof () in
414
417
incr next_sid;
415
418
let sid = ! next_sid in
@@ -421,7 +424,6 @@ let create file coqtop_args =
421
424
let messages = create_messages () in
422
425
let segment = new Wg_Segment. segment () in
423
426
let finder = new Wg_Find. finder basename (script :> GText.view ) in
424
- finder#setup_is_script_editable (fun _ -> script#editable2);
425
427
let debugger = Wg_Debugger. debugger (Printf. sprintf " Debugger (%s)" basename) sid in
426
428
let fops = new FileOps. fileops (buffer :> GText.buffer ) file reset in
427
429
let _ = fops#update_stats in
0 commit comments