aboutsummaryrefslogtreecommitdiffhomepage
path: root/ide/session.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ide/session.ml')
-rw-r--r--ide/session.ml130
1 files changed, 102 insertions, 28 deletions
diff --git a/ide/session.ml b/ide/session.ml
index ac23e2f0a..13950cd4c 100644
--- a/ide/session.ml
+++ b/ide/session.ml
@@ -26,17 +26,7 @@ type session = {
tab_label : GMisc.label;
}
-type print_items =
- (Coq.PrintOpt.t list * string * string * string * bool) list
-
-let create file coqtop_args print_items =
- let basename = match file with
- |None -> "*scratch*"
- |Some f -> Glib.Convert.filename_to_utf8 (Filename.basename f)
- in
- let coqtop = Coq.spawn_coqtop coqtop_args in
- let reset () = Coq.reset_coqtop coqtop
- in
+let create_buffer () =
let buffer = GSourceView2.source_buffer
~tag_table:Tags.Script.table
~highlight_matching_brackets:true
@@ -47,38 +37,122 @@ let create file coqtop_args print_items =
let _ = buffer#create_mark ~name:"start_of_input" buffer#start_iter in
let _ = buffer#create_mark ~name:"prev_insert" buffer#start_iter in
let _ = buffer#place_cursor ~where:buffer#start_iter in
- let _ = buffer#add_selection_clipboard Ideutils.cb
- in
- let script = Wg_ScriptView.script_view coqtop ~source_buffer:buffer
+ let _ = buffer#add_selection_clipboard Ideutils.cb in
+ buffer
+
+let create_script coqtop source_buffer =
+ let script = Wg_ScriptView.script_view coqtop ~source_buffer
~show_line_numbers:true ~wrap_mode:`NONE ()
in
let _ = script#misc#set_name "ScriptWindow"
in
+ script
+
+(** NB: Events during text edition:
+
+ - [begin_user_action]
+ - [insert_text] (or [delete_range] when deleting)
+ - [changed]
+ - [end_user_action]
+
+ When pasting a text containing tags (e.g. the sentence terminators),
+ there is actually many [insert_text] and [changed]. For instance,
+ for "a. b.":
+
+ - [begin_user_action]
+ - [insert_text] (for "a")
+ - [changed]
+ - [insert_text] (for ".")
+ - [changed]
+ - [apply_tag] (for the tag of ".")
+ - [insert_text] (for " b")
+ - [changed]
+ - [insert_text] (for ".")
+ - [changed]
+ - [apply_tag] (for the tag of ".")
+ - [end_user_action]
+
+ Since these copy-pasted tags may interact badly with the retag mechanism,
+ we now don't monitor the "changed" event, but rather the "begin_user_action"
+ and "end_user_action". We begin by setting a mark at the initial cursor
+ point. At the end, the zone between the mark and the cursor is to be
+ untagged and then retagged. *)
+
+let set_buffer_handlers buffer script =
+ let start_of_input () = buffer#get_iter_at_mark (`NAME "start_of_input") in
+ let get_insert () = buffer#get_iter_at_mark `INSERT
+ in
+ let _ = buffer#connect#insert_text
+ ~callback:(fun it s ->
+ (* If a #insert happens in the locked zone, we discard it.
+ Other solution: always use #insert_interactive and similar *)
+ if (it#compare (start_of_input ()))<0 then
+ GtkSignal.stop_emit ();
+ if String.length s > 1 then
+ let () = Minilib.log "insert_text: Placing cursor" in
+ buffer#place_cursor ~where:it;
+ if String.contains s '\n' then
+ let () = Minilib.log "insert_text: Recentering" in
+ script#recenter_insert)
+ in
+ let _ = buffer#connect#begin_user_action
+ ~callback:(fun () ->
+ (* We remove any error red zone, and place the [prev_insert] mark *)
+ let where = get_insert () in
+ buffer#move_mark (`NAME "prev_insert") ~where;
+ let start = start_of_input () in
+ let stop = buffer#end_iter in
+ buffer#remove_tag Tags.Script.error ~start ~stop)
+ in
+ let _ = buffer#connect#end_user_action
+ ~callback:(fun () -> Sentence.tag_on_insert buffer)
+ in
+ let _ = buffer#connect#after#mark_set
+ ~callback:(fun it m ->
+ let ins = get_insert () in
+ !Ideutils.set_location
+ (Printf.sprintf "Line: %5d Char: %3d"
+ (ins#line + 1)
+ (ins#line_offset + 1));
+ match GtkText.Mark.get_name m with
+ | Some "insert" -> ()
+ | Some s -> Minilib.log (s^" moved")
+ | None -> ())
+ in ()
+
+let create_proof () =
let proof = Wg_ProofView.proof_view () in
let _ = proof#misc#set_can_focus true in
- let _ =
- GtkBase.Widget.add_events proof#as_widget [`ENTER_NOTIFY;`POINTER_MOTION]
+ let _ = GtkBase.Widget.add_events proof#as_widget
+ [`ENTER_NOTIFY;`POINTER_MOTION]
in
+ proof
+
+let create_messages () =
let messages = Wg_MessageView.message_view () in
- let _ = messages#misc#set_can_focus true
+ let _ = messages#misc#set_can_focus true in
+ messages
+
+let create file coqtop_args =
+ let basename = match file with
+ |None -> "*scratch*"
+ |Some f -> Glib.Convert.filename_to_utf8 (Filename.basename f)
in
+ let coqtop = Coq.spawn_coqtop coqtop_args in
+ let reset () = Coq.reset_coqtop coqtop in
+ let buffer = create_buffer () in
+ let script = create_script coqtop buffer in
+ let _ = set_buffer_handlers (buffer :> GText.buffer) script in
+ let proof = create_proof () in
+ let messages = create_messages () in
let command = new Wg_Command.command_window coqtop in
let finder = new Wg_Find.finder (script :> GText.view) in
let fops = new FileOps.fileops (buffer :> GText.buffer) file reset in
+ let _ = fops#update_stats in
let cops = new CoqOps.coqops script proof messages (fun () -> fops#filename)
in
let _ = Coq.set_reset_handler coqtop cops#handle_reset_initial in
- let _ = fops#update_stats in
- let _ = Coq.init_coqtop coqtop
- (fun h k ->
- cops#include_file_dir_in_path h
- (fun () ->
- let fold accu (opts, _, _, _, dflt) =
- List.fold_left (fun accu opt -> (opt, dflt) :: accu) accu opts
- in
- let options = List.fold_left fold [] print_items in
- Coq.PrintOpt.set options h k))
- in
+ let _ = Coq.init_coqtop coqtop cops#initialize in
{
buffer = (buffer :> GText.buffer);
script=script;