diff options
author | monate <monate@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2003-05-07 16:57:39 +0000 |
---|---|---|
committer | monate <monate@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2003-05-07 16:57:39 +0000 |
commit | ee280ef0957206a0cae7d510806a8667f87a510c (patch) | |
tree | dbcebf3d3d2016553cd5b13101e939f3f494ca58 /ide | |
parent | dd53f04b22a4ba3b539fb25ba23d7757e5af2349 (diff) |
coqide: toolbar/autosave
Hugo: Suppression du type dans les notations == et <> entre
Suppression du type dans les notations == et <> entre
volution second traducteur selon discussion TYPES
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@3993 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'ide')
-rw-r--r-- | ide/.coqide-gtk2rc | 11 | ||||
-rw-r--r-- | ide/FAQ | 39 | ||||
-rw-r--r-- | ide/command_windows.ml | 10 | ||||
-rw-r--r-- | ide/config_lexer.mll | 10 | ||||
-rw-r--r-- | ide/config_parser.mly | 9 | ||||
-rw-r--r-- | ide/coq.ml | 47 | ||||
-rw-r--r-- | ide/coq.mli | 16 | ||||
-rw-r--r-- | ide/coq_commands.ml | 10 | ||||
-rw-r--r-- | ide/coq_tactics.ml | 13 | ||||
-rw-r--r-- | ide/coqide.ml | 1197 | ||||
-rw-r--r-- | ide/extract_index.mll | 9 | ||||
-rw-r--r-- | ide/find_phrase.mll | 10 | ||||
-rw-r--r-- | ide/highlight.mll | 15 | ||||
-rw-r--r-- | ide/ideutils.ml | 28 | ||||
-rw-r--r-- | ide/preferences.ml | 205 | ||||
-rw-r--r-- | ide/undo.ml | 10 | ||||
-rw-r--r-- | ide/undo.mli | 10 | ||||
-rw-r--r-- | ide/utils/configwin_ihm.ml | 10 | ||||
-rw-r--r-- | ide/utils/editable_cells.ml | 102 |
19 files changed, 1181 insertions, 580 deletions
diff --git a/ide/.coqide-gtk2rc b/ide/.coqide-gtk2rc index 11099742e..7a74a469d 100644 --- a/ide/.coqide-gtk2rc +++ b/ide/.coqide-gtk2rc @@ -6,9 +6,12 @@ gtk-key-theme-name = "Emacs" +#pixmap_path "/home/" + binding "text" { bind "<ctrl>k" { "set-anchor" () "move-cursor" (display-line-ends,1,0) + "move-cursor" (visual-positions,1,0) "cut-clipboard" () } bind "<ctrl>w" { "cut-clipboard" () } @@ -22,6 +25,7 @@ class "GtkTextView" binding "text" style "views" { base[NORMAL] = "CornSilk" +# bg_pixmap[NORMAL] = "background.jpg" } class "GtkTextView" style "views" @@ -36,3 +40,10 @@ font_name = "Monospace 10" } widget "*location*" style "location" + +gtk-can-change-accels = 1 + +style "men" { +# +} +widget "GtkMenu" style "men" @@ -1,36 +1,38 @@ + CoqIde FAQ + +Q0) What is CoqIde? +R0: A powerfull graphical interface for Coq. See http://coq.inria.fr. for more informations + Q1) How to enable Emacs keybindings? R1: Insert gtk-key-theme-name = "Emacs" in your ".coqide-gtk2rc" file. It may be in the current dir or in $HOME dir. This is done by default. - Q2) How to enable antialiased fonts? R2) Set the GDK_USE_XFT variable to 1. This is by default with Gtk >= 2.2. - If some of your fonts seem not to be available, set to 0. + If some of your fonts are not available, set GDK_USE_XFT to 0. -Q4) How can use Forall and Exists pretty symbols ? +Q4) How to use those Forall and Exists pretty symbols? R4) Thanks to the Notation features in Coq, you just need to insert these lines in your Coq Buffer : ====================================================================== Notation "∀ x : t | P" := (x:t)P (at level 1, x,t,P at level 10). Notation "∃ x : t | P" := (EXT x:t|P) (at level 1, x,t,P at level 10). ====================================================================== -Copy/Paste from this file will not work. +Copy/Paste of these lines from this file will not work outside of CoqIde. You need to load a file containing these lines or to enter the "∀" -using an input method. As a convenience, you may put these lines in +using an input method (see Q5). As a convenience, you may put these lines in a utf8.v file and start coqide with : coqide -l utf8.v -In the ide subdir of Coq sources, you will find a sample utf8.v with some -notations - +In the ide subdir of Coq library, you will find a sample utf8.v with some +pretty notations. - -Input Methods: --First solution : type "<CONTROL><SHIFT>2200" to enter a forall in the script widow. +Q5) How to define an input method for non ASCII symbols? +R5)-First solution : type "<CONTROL><SHIFT>2200" to enter a forall in the script widow. 2200 is the hexadecimal code for forall in unicode charts and is encoded as "∀" in UTF-8. - 2203 is for exists. See http://www.unicode.org for more. + 2203 is for exists. See http://www.unicode.org for more codes. -Second solution : rebind "<AltGr>a" to forall and "<AltGr>e" to exists. Under X11, you need to use something like xmodmap -e "keycode 24 = a A F13 F13" @@ -40,7 +42,16 @@ Input Methods: bind "F14" {"insert-at-cursor" ("∃")} to your "binding "text"" section in .coqiderc-gtk2rc. The strange ("∀") argument is the UTF-8 encoding for - 0x2200. It is computed by lablgtk2 by + 0x2200. + You can compute these encodings using the lablgtk2 toplevel with Glib.Utf8.from_unichar 0x2200;; - Further symbols can be bound on higher Fxx key symbols. + Further symbols can be bound on higher Fxx keys or on even on other keys you + do not need . + +Q6) How to build a custom CoqIde with user ml code? +R6) Use + coqmktop -ide -byte m1.cmo...mi.cmo + or + coqmktop -ide -opt m1.cmx...mi.cmx + diff --git a/ide/command_windows.ml b/ide/command_windows.ml index 7a08d209c..6c0048ca3 100644 --- a/ide/command_windows.ml +++ b/ide/command_windows.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + let decompose_tab w = let vbox = new GPack.box ((Gobject.try_cast w "GtkBox"):Gtk.box Gtk.obj) in let l = vbox#children in diff --git a/ide/config_lexer.mll b/ide/config_lexer.mll index 480f04e24..778a9c7e7 100644 --- a/ide/config_lexer.mll +++ b/ide/config_lexer.mll @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + { open Lexing diff --git a/ide/config_parser.mly b/ide/config_parser.mly index fe9071964..19da4887c 100644 --- a/ide/config_parser.mly +++ b/ide/config_parser.mly @@ -1,3 +1,12 @@ +/***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************/ + +/* $Id$ */ %{ diff --git a/ide/coq.ml b/ide/coq.ml index c31306131..01a1c4c13 100644 --- a/ide/coq.ml +++ b/ide/coq.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open Vernac open Vernacexpr open Pfedit @@ -310,3 +320,40 @@ let concl_menu (_,_,concl,_) = "Right", "Right."; ] + + +let id_of_name = function + | Names.Anonymous -> id_of_string "x" + | Names.Name x -> x + +let make_cases s = + let qualified_name = Libnames.qualid_of_string s in + let glob_ref = Nametab.locate qualified_name in + match glob_ref with + | Libnames.IndRef i -> + let _, + { + Declarations.mind_nparams = np ; + Declarations.mind_consnames = carr ; + Declarations.mind_nf_lc = tarr } + = Global.lookup_inductive i + in + Util.array_fold_right2 + (fun n t l -> + let (al,_) = Term.decompose_prod t in + let al,_ = Util.list_chop (List.length al - np) al in + let rec rename avoid = function + | [] -> [] + | (n,_)::l -> + let n' = Tactics.next_global_ident_away + (id_of_name n) + avoid + in (string_of_id n')::(rename (n'::avoid) l) + in + let al' = rename [] (List.rev al) in + (string_of_id n :: al') :: l + ) + carr + tarr + [] + | _ -> raise Not_found diff --git a/ide/coq.mli b/ide/coq.mli index b2881a70d..7769a037b 100644 --- a/ide/coq.mli +++ b/ide/coq.mli @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open Names open Term open Environ @@ -24,10 +34,6 @@ val print_no_goal : unit -> string val process_exn : exn -> string*((int*int) option) -type word_class = Normal | Kwd | Reserved - -val word_class : string -> word_class - type reset_info = NoReset | Reset of Names.identifier * bool ref val compute_reset_info : Vernacexpr.vernac_expr -> reset_info @@ -40,3 +46,5 @@ val concl_menu : concl -> (string * string) list val is_in_coq_lib : string -> bool +val make_cases : string -> string list list + diff --git a/ide/coq_commands.ml b/ide/coq_commands.ml index a2db621fd..9cd851820 100644 --- a/ide/coq_commands.ml +++ b/ide/coq_commands.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + let commands = [ ["Abort"; "Add Abstract Ring"; diff --git a/ide/coq_tactics.ml b/ide/coq_tactics.ml index 7cac14da4..1d6783b6d 100644 --- a/ide/coq_tactics.ml +++ b/ide/coq_tactics.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + let tactics = [ "Abstract"; "Absurd"; @@ -119,6 +129,3 @@ let tactics = [ "Unfold"; "Unfold ... in"; ] - - - diff --git a/ide/coqide.ml b/ide/coqide.ml index 2708fb825..0a258c741 100644 --- a/ide/coqide.ml +++ b/ide/coqide.ml @@ -1,9 +1,21 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open Preferences open Vernacexpr open Coq open Ideutils +open Format -let out_some s = match s with | None -> failwith "toto" | Some f -> f +let out_some s = match s with + | None -> failwith "Internal error in out_some." | Some f -> f let cb_ = ref None let cb () = out_some !cb_ @@ -17,22 +29,18 @@ let warning_icon = `DIALOG_WARNING let dialog_size = `DIALOG let small_size = `SMALL_TOOLBAR -let window_width = 800 -let window_height = 600 - let initial_cwd = Sys.getcwd () let status = ref None let push_info = ref (function s -> failwith "not ready") let pop_info = ref (function s -> failwith "not ready") -let flash_info = ref (function s -> failwith "not ready") +let flash_info = ref (fun ?delay s -> failwith "not ready") let set_location = ref (function s -> failwith "not ready") let pulse = ref (function () -> failwith "not ready") -let (font_selector:GWindow.font_selection_dialog option ref) = ref None let (message_view:GText.view option ref) = ref None let (proof_view:GText.view option ref) = ref None @@ -129,12 +137,18 @@ object('self) val mutable read_only : bool val mutable filename : string option val mutable stats : Unix.stats option + val mutable detached_views : GWindow.window list + method kill_detached_views : unit -> unit + method add_detached_view : GWindow.window -> unit + method remove_detached_view : GWindow.window -> unit + method view : Undo.undoable_view method filename : string option method stats : Unix.stats option method set_filename : string option -> unit method update_stats : unit method revert : unit + method auto_save : unit method save : string -> bool method save_as : string -> bool method read_only : bool @@ -191,7 +205,7 @@ let crash_save i = (let filename = match av#filename with | None -> incr count; - "Unamed_coqscript_"^(string_of_int !count)^".crashcoqide" + "Unnamed_coqscript_"^(string_of_int !count)^".crashcoqide" | Some f -> f^".crashcoqide" in try @@ -281,6 +295,9 @@ let set_current_view i = (notebook ())#goto_page i let kill_input_view i = let v = Vector.get input_views i in + (match v.analyzed_view with + | Some v -> v#kill_detached_views () + | None -> ()); v.view#destroy (); v.analyzed_view <- None; Vector.remove input_views i @@ -342,6 +359,9 @@ let rec complete_forward w (it:GText.iter) = (* Reset this to None on page change ! *) let (last_completion:(string*int*int*bool) option ref) = ref None +let () = to_do_on_page_switch := + (fun i -> last_completion := None)::!to_do_on_page_switch + let complete input_buffer w (offset:int) = match !last_completion with | Some (lw,loffset,lpos,backward) @@ -392,6 +412,8 @@ let get_current_word () = let it = av#get_insert in let start = find_word_start it in let stop = find_word_end start in + av#view#buffer#move_mark `SEL_BOUND start; + av#view#buffer#move_mark `INSERT stop; av#view#buffer#get_text ~slice:true ~start ~stop () | Some t -> prerr_endline "Some selected"; @@ -511,75 +533,117 @@ object(self) val mutable read_only = false val mutable filename = None val mutable stats = None + val mutable last_modification_time = 0. + val mutable last_auto_save_time = 0. + val mutable detached_views = [] + + method add_detached_view (w:GWindow.window) = + detached_views <- w::detached_views + method remove_detached_view (w:GWindow.window) = + detached_views <- List.filter (fun e -> w#misc#get_oid<>e#misc#get_oid) detached_views + + method kill_detached_views () = + List.iter (fun w -> w#destroy ()) detached_views; + detached_views <- [] + method view = input_view method filename = filename method stats = stats method set_filename f = filename <- f; match f with - | Some f -> stats <- my_stat f - | None -> () + | Some f -> stats <- my_stat f + | None -> () method update_stats = match filename with - | Some f -> stats <- my_stat f - | _ -> () + | Some f -> stats <- my_stat f + | _ -> () method revert = match filename with - | Some f -> begin - let do_revert () = begin - !push_info "Reverting buffer"; - try - if is_active then self#reset_initial; - let b = Buffer.create 1024 in - with_file f ~f:(input_channel b); - let s = try_convert (Buffer.contents b) in - input_buffer#set_text s; - self#update_stats; - input_buffer#place_cursor input_buffer#start_iter; - input_buffer#set_modified false; - !pop_info (); - !flash_info "Buffer reverted"; - Highlight.highlight_all input_buffer; - with _ -> - !pop_info (); - !flash_info "Warning: could not revert buffer"; - end - in - if input_buffer#modified then - match (GToolbox.question_box - ~title:"Modified buffer changed on disk" - ~buttons:["Revert from File"; - "Overwrite File"; - "Disable Auto Revert"] - ~default:0 - ~icon:(let img = GMisc.image () - in img#set_stock warning_icon ~size:dialog_size; - img#coerce) - "Some unsaved buffers changed on disk" - ) - with 1 -> do_revert () - | 2 -> if self#save f then !flash_info "Overwritten" else - !flash_info "Could not overwrite file" - | _ -> - prerr_endline "Auto revert set to false"; - !current.global_auto_revert <- false; - disconnect_revert_timer () - else do_revert () + | Some f -> begin + let do_revert () = begin + !push_info "Reverting buffer"; + try + if is_active then self#reset_initial; + let b = Buffer.create 1024 in + with_file f ~f:(input_channel b); + let s = try_convert (Buffer.contents b) in + input_buffer#set_text s; + self#update_stats; + input_buffer#place_cursor input_buffer#start_iter; + input_buffer#set_modified false; + !pop_info (); + !flash_info "Buffer reverted"; + Highlight.highlight_all input_buffer; + with _ -> + !pop_info (); + !flash_info "Warning: could not revert buffer"; end - | None -> () - + in + if input_buffer#modified then + match (GToolbox.question_box + ~title:"Modified buffer changed on disk" + ~buttons:["Revert from File"; + "Overwrite File"; + "Disable Auto Revert"] + ~default:0 + ~icon:(stock_to_widget warning_icon) + "Some unsaved buffers changed on disk" + ) + with 1 -> do_revert () + | 2 -> if self#save f then !flash_info "Overwritten" else + !flash_info "Could not overwrite file" + | _ -> + prerr_endline "Auto revert set to false"; + !current.global_auto_revert <- false; + disconnect_revert_timer () + else do_revert () + end + | None -> () + method save f = if try_export f (input_buffer#get_text ()) then begin filename <- Some f; input_buffer#set_modified false; stats <- my_stat f; + (match self#auto_save_name with + | None -> () + | Some fn -> try Sys.remove fn with _ -> ()); true end else false - + method private auto_save_name = + match filename with + | None -> None + | Some f -> + let dir = Filename.dirname f in + let base = (fst !current.auto_save_name) ^ + (Filename.basename f) ^ + (snd !current.auto_save_name) + in Some (Filename.concat dir base) + + method private need_auto_save = + input_buffer#modified && + last_modification_time > last_auto_save_time + + method auto_save = + if self#need_auto_save then begin + match self#auto_save_name with + | None -> () + | Some fn -> + try + last_auto_save_time <- Unix.time(); + prerr_endline ("Autosave time : "^(string_of_float (Unix.time()))); + if try_export fn (input_buffer#get_text ()) then begin + !flash_info ~delay:1000 "Autosaved" + end + else !flash_info "Autosave failed" + with _ -> !flash_info "Autosave error" + end + method save_as f = if Sys.file_exists f then match (GToolbox.question_box ~title:"File exists on disk" @@ -593,7 +657,7 @@ object(self) ("File "^f^"already exists") ) with 1 -> self#save f - | _ -> false + | _ -> false else self#save f method set_read_only b = read_only<-b @@ -617,12 +681,12 @@ object(self) method recenter_insert = (* BUG : to investigate further: FIXED : Never call GMain.* in thread ! - PLUS : GTK BUG ??? Cannot be called from a thread...*) + PLUS : GTK BUG ??? Cannot be called from a thread...*) try ignore (GtkThread.sync (input_view#scroll_to_mark - ~use_align:false - ~yalign:0.75 - ~within_margin:0.25) + ~use_align:false + ~yalign:0.75 + ~within_margin:0.25) `INSERT) with _ -> prerr_endline "Could not recenter ERROR ignored" @@ -631,22 +695,125 @@ object(self) proof_view#buffer#set_text ""; let s = Coq.get_current_goals () in match s with + | [] -> proof_buffer#insert (Coq.print_no_goal ()) + | (hyps,concl)::r -> + let goal_nb = List.length s in + proof_buffer#insert (Printf.sprintf "%d subgoal%s\n" + goal_nb + (if goal_nb<=1 then "" else "s")); + List.iter + (fun ((_,_,_,(s,_)) as hyp) -> + proof_buffer#insert (s^"\n")) + hyps; + proof_buffer#insert (String.make 38 '_' ^ "(1/"^ + (string_of_int goal_nb)^ + ")\n") + ; + let _,_,_,sconcl = concl in + proof_buffer#insert sconcl; + proof_buffer#insert "\n"; + let my_mark = `NAME "end_of_conclusion" in + proof_buffer#move_mark + ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark; + proof_buffer#insert "\n\n"; + let i = ref 1 in + List.iter + (function (_,(_,_,_,concl)) -> + incr i; + proof_buffer#insert (String.make 38 '_' ^"("^ + (string_of_int !i)^ + "/"^ + (string_of_int goal_nb)^ + ")\n"); + proof_buffer#insert concl; + proof_buffer#insert "\n\n"; + ) + r; + ignore (proof_view#scroll_to_mark my_mark) + with e -> prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e) + + + method show_goals_full = + begin + try + proof_view#buffer#set_text ""; + let s = Coq.get_current_goals () in + let last_shown_area = proof_buffer#create_tag [`BACKGROUND "light green"] + in + match s with | [] -> proof_buffer#insert (Coq.print_no_goal ()) | (hyps,concl)::r -> let goal_nb = List.length s in proof_buffer#insert (Printf.sprintf "%d subgoal%s\n" goal_nb (if goal_nb<=1 then "" else "s")); + let coq_menu commands = + let tag = proof_buffer#create_tag [] + in + ignore + (tag#connect#event ~callback: + (fun ~origin ev it -> + match GdkEvent.get_type ev with + | `BUTTON_PRESS -> + let ev = (GdkEvent.Button.cast ev) in + if (GdkEvent.Button.button ev) = 3 + then begin + let loc_menu = GMenu.menu () in + let factory = new GMenu.factory loc_menu in + let add_coq_command (cp,ip) = + ignore + (factory#add_item cp + ~callback: + (fun () -> ignore + (self#insert_this_phrase_on_success + true + true + false + (ip^"\n") + (ip^"\n")) + ) + ) + in + List.iter add_coq_command commands; + loc_menu#popup + ~button:3 + ~time:(GdkEvent.Button.time ev); + end + | `MOTION_NOTIFY -> + proof_buffer#remove_tag + ~start:proof_buffer#start_iter + ~stop:proof_buffer#end_iter + last_shown_area; + prerr_endline "Before find_tag_limits"; + + let s,e = find_tag_limits tag + (new GText.iter it) + in + prerr_endline "After find_tag_limits"; + proof_buffer#apply_tag + ~start:s + ~stop:e + last_shown_area; + + prerr_endline "Applied tag"; + () + | _ -> ()) + ); + tag + in List.iter (fun ((_,_,_,(s,_)) as hyp) -> - proof_buffer#insert (s^"\n")) + let tag = coq_menu (hyp_menu hyp) in + proof_buffer#insert ~tags:[tag] (s^"\n")) hyps; - proof_buffer#insert (String.make 38 '_' ^ "(1/"^ - (string_of_int goal_nb)^ - ")\n") + proof_buffer#insert + (String.make 38 '_' ^"(1/"^ + (string_of_int goal_nb)^ + ")\n") ; + let tag = coq_menu (concl_menu concl) in let _,_,_,sconcl = concl in - proof_buffer#insert sconcl; + proof_buffer#insert ~tags:[tag] sconcl; proof_buffer#insert "\n"; let my_mark = `NAME "end_of_conclusion" in proof_buffer#move_mark @@ -656,117 +823,17 @@ object(self) List.iter (function (_,(_,_,_,concl)) -> incr i; - proof_buffer#insert (String.make 38 '_' ^"("^ - (string_of_int !i)^ - "/"^ - (string_of_int goal_nb)^ - ")\n"); + proof_buffer#insert + (String.make 38 '_' ^"("^ + (string_of_int !i)^ + "/"^ + (string_of_int goal_nb)^ + ")\n"); proof_buffer#insert concl; proof_buffer#insert "\n\n"; ) r; - ignore (proof_view#scroll_to_mark my_mark) - with e -> prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e) - - - method show_goals_full = - begin - try - proof_view#buffer#set_text ""; - let s = Coq.get_current_goals () in - let last_shown_area = proof_buffer#create_tag [`BACKGROUND "light green"] - in - match s with - | [] -> proof_buffer#insert (Coq.print_no_goal ()) - | (hyps,concl)::r -> - let goal_nb = List.length s in - proof_buffer#insert (Printf.sprintf "%d subgoal%s\n" - goal_nb - (if goal_nb<=1 then "" else "s")); - let coq_menu commands = - let tag = proof_buffer#create_tag [] - in - ignore - (tag#connect#event ~callback: - (fun ~origin ev it -> - match GdkEvent.get_type ev with - | `BUTTON_PRESS -> - let ev = (GdkEvent.Button.cast ev) in - if (GdkEvent.Button.button ev) = 3 - then begin - let loc_menu = GMenu.menu () in - let factory = new GMenu.factory loc_menu in - let add_coq_command (cp,ip) = - ignore (factory#add_item cp - ~callback: - (fun () -> ignore - (self#insert_this_phrase_on_success - true - true - false - (ip^"\n") - (ip^"\n")) - ) - ) - in - List.iter add_coq_command commands; - loc_menu#popup - ~button:3 - ~time:(GdkEvent.Button.time ev); - end - | `MOTION_NOTIFY -> - proof_buffer#remove_tag - ~start:proof_buffer#start_iter - ~stop:proof_buffer#end_iter - last_shown_area; - prerr_endline "Before find_tag_limits"; - - let s,e = find_tag_limits tag - (new GText.iter it) - in - prerr_endline "After find_tag_limits"; - proof_buffer#apply_tag - ~start:s - ~stop:e - last_shown_area; - - prerr_endline "Applied tag"; - () - | _ -> ()) - ); - tag - in - List.iter - (fun ((_,_,_,(s,_)) as hyp) -> - let tag = coq_menu (hyp_menu hyp) in - proof_buffer#insert ~tags:[tag] (s^"\n")) - hyps; - proof_buffer#insert (String.make 38 '_' ^"(1/"^ - (string_of_int goal_nb)^ - ")\n") - ; - let tag = coq_menu (concl_menu concl) in - let _,_,_,sconcl = concl in - proof_buffer#insert ~tags:[tag] sconcl; - proof_buffer#insert "\n"; - let my_mark = `NAME "end_of_conclusion" in - proof_buffer#move_mark - ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark; - proof_buffer#insert "\n\n"; - let i = ref 1 in - List.iter - (function (_,(_,_,_,concl)) -> - incr i; - proof_buffer#insert (String.make 38 '_' ^"("^ - (string_of_int !i)^ - "/"^ - (string_of_int goal_nb)^ - ")\n"); - proof_buffer#insert concl; - proof_buffer#insert "\n\n"; - ) - r; - ignore (proof_view#scroll_to_mark my_mark) ; + ignore (proof_view#scroll_to_mark my_mark) ; with e -> prerr_endline (Printexc.to_string e) end @@ -785,17 +852,18 @@ object(self) message_view#misc#draw None; if localize then (match loc with - | None -> () - | Some (start,stop) -> - let convert_pos = byte_offset_to_char_offset phrase in - let start = convert_pos start in - let stop = convert_pos stop in - let i = self#get_start_of_input in - let starti = i#forward_chars start in - let stopi = i#forward_chars stop in - input_buffer#apply_tag_by_name "error" - ~start:starti - ~stop:stopi + | None -> () + | Some (start,stop) -> + let convert_pos = byte_offset_to_char_offset phrase in + let start = convert_pos start in + let stop = convert_pos stop in + let i = self#get_start_of_input in + let starti = i#forward_chars start in + let stopi = i#forward_chars stop in + input_buffer#apply_tag_by_name "error" + ~start:starti + ~stop:stopi; + input_buffer#place_cursor starti; )); None @@ -852,14 +920,14 @@ object(self) in prerr_endline ("Completion of prefix : " ^ w); match complete input_buffer w offset with - | None -> () - | Some (start,stop) -> - let completion = input_buffer#get_text ~start ~stop () in - ignore (input_buffer#delete_selection ()); - ignore (input_buffer#insert_interactive completion); - input_buffer#move_mark `INSERT (it()); - () - + | None -> () + | Some (start,stop) -> + let completion = input_buffer#get_text ~start ~stop () in + ignore (input_buffer#delete_selection ()); + ignore (input_buffer#insert_interactive completion); + input_buffer#move_mark `INSERT (it()); + () + method process_next_phrase display_goals do_highlight = begin try self#clear_message; @@ -868,51 +936,51 @@ object(self) !push_info "Coq is computing"; input_view#set_editable false; end; - begin match (self#find_phrase_starting_at self#get_start_of_input) + begin match (self#find_phrase_starting_at self#get_start_of_input) with - | None -> - if do_highlight then begin - input_view#set_editable true; - !pop_info (); - end; false - | Some(start,stop) -> - prerr_endline "process_next_phrase : to_process highlight"; - let b = input_buffer in - if do_highlight then begin - input_buffer#apply_tag_by_name ~start ~stop "to_process"; - prerr_endline "process_next_phrase : to_process applied"; - process_pending () - end; - prerr_endline "process_next_phrase : getting phrase"; - let phrase = start#get_slice ~stop in - let r = - match self#send_to_coq phrase true true true with - | Some ast -> + | None -> + if do_highlight then begin + input_view#set_editable true; + !pop_info (); + end; false + | Some(start,stop) -> + prerr_endline "process_next_phrase : to_process highlight"; + let b = input_buffer in + if do_highlight then begin + input_buffer#apply_tag_by_name ~start ~stop "to_process"; + prerr_endline "process_next_phrase : to_process applied"; + process_pending () + end; + prerr_endline "process_next_phrase : getting phrase"; + let phrase = start#get_slice ~stop in + let r = + match self#send_to_coq phrase true true true with + | Some ast -> + begin + b#move_mark ~where:stop (`NAME "start_of_input"); + b#apply_tag_by_name "processed" ~start ~stop; + if (self#get_insert#compare) stop <= 0 then begin - b#move_mark ~where:stop (`NAME "start_of_input"); - b#apply_tag_by_name "processed" ~start ~stop; - if (self#get_insert#compare) stop <= 0 then - begin - b#place_cursor stop; - self#recenter_insert - end; - let start_of_phrase_mark = `MARK (b#create_mark start) - in - let end_of_phrase_mark = `MARK (b#create_mark stop) in - push_phrase - start_of_phrase_mark - end_of_phrase_mark ast; - if display_goals then self#show_goals; - true - end - | None -> false - in - if do_highlight then begin - b#remove_tag_by_name ~start ~stop "to_process" ; - input_view#set_editable true; - !pop_info (); - end; - r; + b#place_cursor stop; + self#recenter_insert + end; + let start_of_phrase_mark = `MARK (b#create_mark start) + in + let end_of_phrase_mark = `MARK (b#create_mark stop) in + push_phrase + start_of_phrase_mark + end_of_phrase_mark ast; + if display_goals then self#show_goals; + true + end + | None -> false + in + if do_highlight then begin + b#remove_tag_by_name ~start ~stop "to_process" ; + input_view#set_editable true; + !pop_info (); + end; + r; end with e -> raise e end @@ -920,48 +988,49 @@ object(self) method insert_this_phrase_on_success show_output show_msg localize coqphrase insertphrase = match self#send_to_coq coqphrase show_output show_msg localize with - | Some ast -> - begin + | Some ast -> + begin + let stop = self#get_start_of_input in + if stop#starts_line then + input_buffer#insert ~iter:stop insertphrase + else input_buffer#insert ~iter:stop ("\n"^insertphrase); + let start = self#get_start_of_input in + input_buffer#move_mark ~where:stop (`NAME "start_of_input"); + input_buffer#apply_tag_by_name "processed" ~start ~stop; + if (self#get_insert#compare) stop <= 0 then + input_buffer#place_cursor stop; + let start_of_phrase_mark = `MARK (input_buffer#create_mark start) + in + let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in + push_phrase start_of_phrase_mark end_of_phrase_mark ast; + self#show_goals; + (*Auto insert save on success... + try (match Coq.get_current_goals () with + | [] -> + (match self#send_to_coq "Save.\n" true true true with + | Some ast -> + begin let stop = self#get_start_of_input in if stop#starts_line then - input_buffer#insert ~iter:stop insertphrase - else input_buffer#insert ~iter:stop ("\n"^insertphrase); + input_buffer#insert ~iter:stop "Save.\n" + else input_buffer#insert ~iter:stop "\nSave.\n"; let start = self#get_start_of_input in input_buffer#move_mark ~where:stop (`NAME "start_of_input"); input_buffer#apply_tag_by_name "processed" ~start ~stop; if (self#get_insert#compare) stop <= 0 then - input_buffer#place_cursor stop; + input_buffer#place_cursor stop; let start_of_phrase_mark = `MARK (input_buffer#create_mark start) in let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in - push_phrase start_of_phrase_mark end_of_phrase_mark ast; - self#show_goals; - (*Auto insert save on success... - try (match Coq.get_current_goals () with - | [] -> - (match self#send_to_coq "Save.\n" true true true with - | Some ast -> - begin - let stop = self#get_start_of_input in - if stop#starts_line then - input_buffer#insert ~iter:stop "Save.\n" - else input_buffer#insert ~iter:stop "\nSave.\n"; - let start = self#get_start_of_input in - input_buffer#move_mark ~where:stop (`NAME "start_of_input"); - input_buffer#apply_tag_by_name "processed" ~start ~stop; - if (self#get_insert#compare) stop <= 0 then - input_buffer#place_cursor stop; - let start_of_phrase_mark = `MARK (input_buffer#create_mark start) in - let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in - push_phrase start_of_phrase_mark end_of_phrase_mark ast - end - | None -> ()) - | _ -> ()) - with _ -> ()*) - true - end - | None -> self#insert_message ("Unsuccesfully tried: "^coqphrase); - false + push_phrase start_of_phrase_mark end_of_phrase_mark ast + end + | None -> ()) + | _ -> ()) + with _ -> ()*) + true + end + | None -> self#insert_message ("Unsuccesfully tried: "^coqphrase); + false method process_until_iter_or_error stop = let start = self#get_start_of_input#copy in @@ -1016,14 +1085,14 @@ object(self) else begin let t = pop () in begin match t.reset_info with - | Reset (id, ({contents=true} as v)) -> v:=false; - (match snd t.ast with - | VernacBeginSection _ | VernacDefineModule _ - | VernacDeclareModule _ | VernacDeclareModuleType _ - | VernacEndSegment _ - -> reset_to_mod id - | _ -> reset_to id) - | _ -> synchro () + | Reset (id, ({contents=true} as v)) -> v:=false; + (match snd t.ast with + | VernacBeginSection _ | VernacDefineModule _ + | VernacDeclareModule _ | VernacDeclareModuleType _ + | VernacEndSegment _ + -> reset_to_mod id + | _ -> reset_to id) + | _ -> synchro () end; interp_last t.ast; repush_phrase t @@ -1050,8 +1119,8 @@ object(self) begin try (match undos with - | None -> synchro () - | Some n -> try Pfedit.undo n with _ -> synchro ()); + | None -> synchro () + | Some n -> try Pfedit.undo n with _ -> synchro ()); let start = if is_empty () then input_buffer#start_iter else input_buffer#get_iter_at_mark (top ()).stop in @@ -1074,7 +1143,7 @@ Please restart and report NOW."; method backtrack_to i = if Mutex.try_lock coq_may_stop then (!push_info "Undoing...";self#backtrack_to_no_lock i ; Mutex.unlock coq_may_stop; - !pop_info ()) + !pop_info ()) else prerr_endline "backtrack_to : discarded (lock is busy)" method backtrack_to_insert = @@ -1103,37 +1172,37 @@ Please restart and report NOW."; self#clear_message in begin match last_command with - | {ast=_,VernacSolve _} -> - begin - try Pfedit.undo 1; ignore (pop ()); update_input () - with _ -> self#backtrack_to_no_lock start - end - | {ast=_,t;reset_info=Reset (id, {contents=true})} -> - ignore (pop ()); - (match t with - | VernacBeginSection _ | VernacDefineModule _ - | VernacDeclareModule _ | VernacDeclareModuleType _ - | VernacEndSegment _ - -> reset_to_mod id - | _ -> reset_to id); - update_input () - | { ast = _, ( VernacStartTheoremProof _ - | VernacDefinition (_,_,ProveBody _,_,_)); - reset_info=Reset(id,{contents=false})} -> - ignore (pop ()); - (try - Pfedit.delete_current_proof () - with e -> - begin - prerr_endline "WARNING : found a closed environment"; - raise e - end); - update_input () - | _ -> - self#backtrack_to_no_lock start + | {ast=_,VernacSolve _} -> + begin + try Pfedit.undo 1; ignore (pop ()); update_input () + with _ -> self#backtrack_to_no_lock start + end + | {ast=_,t;reset_info=Reset (id, {contents=true})} -> + ignore (pop ()); + (match t with + | VernacBeginSection _ | VernacDefineModule _ + | VernacDeclareModule _ | VernacDeclareModuleType _ + | VernacEndSegment _ + -> reset_to_mod id + | _ -> reset_to id); + update_input () + | { ast = _, ( VernacStartTheoremProof _ + | VernacDefinition (_,_,ProveBody _,_,_)); + reset_info=Reset(id,{contents=false})} -> + ignore (pop ()); + (try + Pfedit.delete_current_proof () + with e -> + begin + prerr_endline "WARNING : found a closed environment"; + raise e + end); + update_input () + | _ -> + self#backtrack_to_no_lock start end; with - | Size 0 -> (* !flash_info "Nothing to Undo"*)() + | Size 0 -> (* !flash_info "Nothing to Undo"*)() ); !pop_info (); Mutex.unlock coq_may_stop) @@ -1146,40 +1215,41 @@ Please restart and report NOW."; self#clear_message; ignore (List.exists (fun (cp,ip) -> - self#insert_this_phrase_on_success true false false cp ip) l) + self#insert_this_phrase_on_success true false false + (cp^"\n") (ip^"\n")) l) method active_keypress_handler k = let state = GdkEvent.Key.state k in begin match state with - | l when List.mem `MOD1 l -> - let k = GdkEvent.Key.keyval k in - if GdkKeysyms._Return=k - then ignore( - if (input_buffer#insert_interactive "\n") then - begin - let i= self#get_insert#backward_word_start in - prerr_endline "active_kp_hf: Placing cursor"; - input_buffer#place_cursor i; - self#process_until_insert_or_error - end); - true - | l when List.mem `CONTROL l -> - let k = GdkEvent.Key.keyval k in - if GdkKeysyms._m=k - then break (); - false - | l -> false - end - method disconnected_keypress_handler k = - match GdkEvent.Key.state k with + | l when List.mem `MOD1 l -> + let k = GdkEvent.Key.keyval k in + if GdkKeysyms._Return=k + then ignore( + if (input_buffer#insert_interactive "\n") then + begin + let i= self#get_insert#backward_word_start in + prerr_endline "active_kp_hf: Placing cursor"; + input_buffer#place_cursor i; + self#process_until_insert_or_error + end); + true | l when List.mem `CONTROL l -> let k = GdkEvent.Key.keyval k in - if GdkKeysyms._c=k + if GdkKeysyms._m=k then break (); false | l -> false - + end + method disconnected_keypress_handler k = + match GdkEvent.Key.state k with + | l when List.mem `CONTROL l -> + let k = GdkEvent.Key.keyval k in + if GdkKeysyms._c=k + then break (); + false + | l -> false + val mutable deact_id = None val mutable act_id = None @@ -1187,11 +1257,11 @@ Please restart and report NOW."; method deactivate () = is_active <- false; (match act_id with None -> () - | Some id -> - reset_initial (); - input_view#misc#disconnect id; - prerr_endline "DISCONNECTED old active : "; - print_id id; + | Some id -> + reset_initial (); + input_view#misc#disconnect id; + prerr_endline "DISCONNECTED old active : "; + print_id id; ); deact_id <- Some (input_view#event#connect#key_press self#disconnected_keypress_handler); @@ -1201,9 +1271,9 @@ Please restart and report NOW."; method activate () = is_active <- true; (match deact_id with None -> () - | Some id -> input_view#misc#disconnect id; - prerr_endline "DISCONNECTED old inactive : "; - print_id id + | Some id -> input_view#misc#disconnect id; + prerr_endline "DISCONNECTED old inactive : "; + print_id id ); act_id <- Some (input_view#event#connect#key_press self#active_keypress_handler); @@ -1213,8 +1283,8 @@ Please restart and report NOW."; (out_some ((Vector.get input_views index).analyzed_view)) #filename with - | None -> initial_cwd - | Some f -> Filename.dirname f + | None -> initial_cwd + | Some f -> Filename.dirname f ) in if not (is_in_coq_lib dir) then @@ -1251,25 +1321,25 @@ Please restart and report NOW."; tag; if x = "" then () else match x.[String.length x - 1] with - | ')' -> - let hit = self#get_insert in - let count = ref 0 in - if hit#nocopy#backward_find_char - (fun c -> - if c = oparen_code && !count = 0 then true - else if c = cparen_code then - (incr count;false) - else if c = oparen_code then - (decr count;false) - else false - ) - then - begin - prerr_endline "Found matching parenthesis"; - input_buffer#apply_tag tag ~start:hit ~stop:hit#forward_char - end - else () - | _ -> ()) + | ')' -> + let hit = self#get_insert in + let count = ref 0 in + if hit#nocopy#backward_find_char + (fun c -> + if c = oparen_code && !count = 0 then true + else if c = cparen_code then + (incr count;false) + else if c = oparen_code then + (decr count;false) + else false + ) + then + begin + prerr_endline "Found matching parenthesis"; + input_buffer#apply_tag tag ~start:hit ~stop:hit#forward_char + end + else () + | _ -> ()) ) method help_for_keyword () = browse_keyword (get_current_word ()) @@ -1304,13 +1374,14 @@ Please restart and report NOW."; if input_buffer#modified then set_tab_image index (match (out_some (current_all.analyzed_view))#filename with - | None -> saveas_icon - | Some _ -> save_icon + | None -> saveas_icon + | Some _ -> save_icon ) else set_tab_image index yes_icon; )); ignore (input_buffer#connect#changed ~callback:(fun () -> + last_modification_time <- Unix.time (); let r = input_view#visible_rect in let stop = input_view#get_iter_at_location @@ -1335,22 +1406,22 @@ Please restart and report NOW."; "Line: %5d Char: %3d" (self#get_insert#line + 1) (self#get_insert#line_offset + 1)); match GtkText.Mark.get_name m with - | Some "insert" -> - input_buffer#remove_tag - ~start:input_buffer#start_iter - ~stop:input_buffer#end_iter - paren_highlight_tag; - | Some s -> - prerr_endline (s^" moved") - | None -> () ) + | Some "insert" -> + input_buffer#remove_tag + ~start:input_buffer#start_iter + ~stop:input_buffer#end_iter + paren_highlight_tag; + | Some s -> + prerr_endline (s^" moved") + | None -> () ) ); ignore (input_buffer#connect#insert_text - (fun it s -> - prerr_endline "Should recenter ?"; - if String.contains s '\n' then begin - prerr_endline "Should recenter : yes"; - self#recenter_insert - end)) + (fun it s -> + prerr_endline "Should recenter ?"; + if String.contains s '\n' then begin + prerr_endline "Should recenter : yes"; + self#recenter_insert + end)) end let create_input_tab filename = @@ -1417,17 +1488,38 @@ let create_input_tab filename = let main files = (* Statup preferences *) - load_pref current; + load_pref (); (* Main window *) let w = GWindow.window ~allow_grow:true ~allow_shrink:true - ~width:window_width ~height:window_height + ~width:!current.window_width ~height:!current.window_height ~title:"CoqIde" () in - (* let accel_group = GtkData.AccelGroup.create () in *) let vbox = GPack.vbox ~homogeneous:false ~packing:w#add () in + + + (* Menu bar *) let menubar = GMenu.menu_bar ~packing:vbox#pack () in + + (* Tearable Toolbar *) + let handle = GBin.handle_box + ~show:!current.show_toolbar + ~handle_position:`LEFT + ~snap_edge:`LEFT + ~packing:vbox#pack + () + in + let toolbar = GButton.toolbar + ~orientation:`HORIZONTAL + ~style:`BOTH + ~tooltips:true + ~packing:handle#add + () + in + show_toolbar := + (fun b -> if b then handle#misc#show () else handle#misc#hide ()); + let factory = new GMenu.factory menubar in let accel_group = factory#accel_group in @@ -1480,7 +1572,7 @@ let main files = | None -> () | (Some f) as fn -> load f in - ignore (load_m#connect#activate (do_if_not_computing load_f)); + ignore (load_m#connect#activate (load_f)); (* File/Save Menu *) let save_m = file_factory#add_item "_Save" ~key:GdkKeysyms._S in @@ -1716,14 +1808,14 @@ let main files = GtkText.View.Signals.paste_clipboard with _ -> prerr_endline "EMIT PASTE FAILED"))); ignore (edit_f#add_separator ()); - let read_only_i = edit_f#add_check_item "_Read only" ~active:false + let read_only_i = edit_f#add_check_item "Expert" ~active:false + ~key:GdkKeysyms._Z ~callback:(fun b -> - let v = get_current_view () in - v.view#set_editable (not b); - (out_some v.analyzed_view)#set_read_only b + GtkData.AccelGroup.save "tutu.l" ) in read_only_i#misc#set_state `INSENSITIVE; + let search_if = edit_f#add_item "Search _forward" ~key:GdkKeysyms._greater in @@ -1735,8 +1827,8 @@ let main files = ~callback: (do_if_not_computing (fun b -> - let v =out_some (get_current_view ()).analyzed_view in - v#complete_at_offset (v#get_insert#offset) + let v =out_some (get_current_view ()).analyzed_view + in v#complete_at_offset (v#get_insert#offset) )) in @@ -1760,37 +1852,64 @@ let main files = if analyzed_view#is_active then ignore (f analyzed_view) else - activate_input (notebook ())#current_page + begin + !flash_info "New proof started"; + activate_input (notebook ())#current_page + end in let do_or_activate f = do_if_not_computing (do_or_activate f) in - ignore (navigation_factory#add_item "_Break computations" - ~key:GdkKeysyms._Break - ~callback:(fun () -> break ())); - ignore (navigation_factory#add_item "_Forward" - ~key:GdkKeysyms._Down - ~callback:(do_or_activate (fun a -> - a#process_next_phrase true true))); - ignore (navigation_factory#add_item "_Backward" - ~key:GdkKeysyms._Up - ~callback:(do_or_activate (fun a -> a#undo_last_step))); - ignore (navigation_factory#add_item "_Forward to" - ~key:GdkKeysyms._Right - ~callback:(do_or_activate (fun a -> a#process_until_insert_or_error)) - ); - ignore (navigation_factory#add_item "_Backward to" - ~key:GdkKeysyms._Left - ~callback:(do_or_activate (fun a-> a#backtrack_to_insert)) - ); - ignore (navigation_factory#add_item "_Start" - ~key:GdkKeysyms._Home - ~callback:(do_or_activate (fun a -> a#reset_initial)) - ); - ignore (navigation_factory#add_item "_End" - ~key:GdkKeysyms._End - ~callback:(do_or_activate (fun a -> a#process_until_end_or_error)) - ); + let add_to_menu_toolbar text ~tooltip ~key ~callback icon = + ignore (navigation_factory#add_item text ~key ~callback); + ignore (toolbar#insert_button + ~tooltip + ~text:tooltip + ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR icon) + ~callback + ()) + in + add_to_menu_toolbar "_Interrupt computations" + ~tooltip:"Interrupt computations" + ~key:GdkKeysyms._Break + ~callback:break + `STOP + ; + add_to_menu_toolbar + "_Forward" + ~tooltip:"Forward" + ~key:GdkKeysyms._Down + ~callback:(do_or_activate (fun a -> a#process_next_phrase true true)) + `GO_DOWN; + add_to_menu_toolbar "_Backward" + ~tooltip:"Backward" + ~key:GdkKeysyms._Up + ~callback:(do_or_activate (fun a -> a#undo_last_step)) + `GO_UP; + add_to_menu_toolbar + "_Forward to" + ~tooltip:"Forward to" + ~key:GdkKeysyms._Right + ~callback:(do_or_activate (fun a -> a#process_until_insert_or_error)) + `GOTO_LAST; + add_to_menu_toolbar + "_Backward to" + ~tooltip:"Backward to" + ~key:GdkKeysyms._Left + ~callback:(do_or_activate (fun a-> a#backtrack_to_insert)) + `GOTO_FIRST; + add_to_menu_toolbar + "_Start" + ~tooltip:"Start" + ~key:GdkKeysyms._Home + ~callback:(do_or_activate (fun a -> a#reset_initial)) + `GOTO_TOP; + add_to_menu_toolbar + "_End" + ~tooltip:"End" + ~key:GdkKeysyms._End + ~callback:(do_or_activate (fun a -> a#process_until_end_or_error)) + `GOTO_BOTTOM; (* Tactics Menu *) let tactics_menu = factory#add_submenu "_Try Tactics" in @@ -1846,6 +1965,17 @@ let main files = ~key:GdkKeysyms._v ~callback:(do_if_active( fun a -> a#insert_command "Progress Trivial.\n" "Trivial.\n" )) ); + + + ignore (toolbar#insert_button + ~tooltip:"Proof Wizzard" + ~text:"Wizzard" + ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR `DIALOG_INFO) + ~callback:(do_if_active (fun a -> a#insert_commands + !current.automatic_tactics + )) + ()); + ignore (tactics_factory#add_item "<Proof _Wizzard>" ~key:GdkKeysyms._dollar ~callback:(do_if_active (fun a -> a#insert_commands @@ -1887,6 +2017,47 @@ let main files = add_complex_template ("_Inductive __", "Inductive ident : :=\n | : .\n", 14, 5, Some GdkKeysyms._I); + add_complex_template("_Scheme __", +"Scheme new_scheme := Induction for _ Sort _ +with _ := Induction for _ Sort _.\n",61,10, Some GdkKeysyms._S); + +(* Template for Cases *) + let callback = (fun () -> + let w = get_current_word () in + try + let cases = Coq.make_cases w + in + let print c = function + | [x] -> fprintf c " | %s => _@\n" x + | x::l -> fprintf c " | (%s%a) => _@\n" x + (print_list (fun c s -> fprintf c " %s" s)) l + | [] -> assert false + in + let b = Buffer.create 1024 in + let fmt = formatter_of_buffer b in + fprintf fmt "@[Cases var of@\n%aend@]@." + (print_list print) cases; + let s = Buffer.contents b in + prerr_endline s; + let {view = view } = get_current_view () in + ignore (view#buffer#delete_selection ()); + let m = view#buffer#create_mark + (view#buffer#get_iter `INSERT) + in + if view#buffer#insert_interactive s then + let i = view#buffer#get_iter (`MARK m) in + let _ = i#nocopy#forward_chars 9 in + view#buffer#place_cursor i; + view#buffer#move_mark ~where:(i#backward_chars 3) + `SEL_BOUND + with Not_found -> !flash_info "Not an inductive type" + ) + in + ignore (templates_factory#add_item "Cases ..." + ~key:GdkKeysyms._C + ~callback + ); + let add_simple_template (factory: GMenu.menu GMenu.factory) (menu_text, text) = ignore (factory#add_item menu_text @@ -2006,7 +2177,6 @@ let main files = in let _ = externals_factory#add_item "_Make Makefile" ~callback:coq_makefile_f in - (* Configuration Menu *) let reset_revert_timer () = disconnect_revert_timer (); @@ -2019,6 +2189,29 @@ let main files = true)) in reset_revert_timer (); (* to enable statup preferences timer *) + let auto_save_f () = + Vector.iter + (function + {view = view ; analyzed_view = Some av} as full -> + (try + av#auto_save + with _ -> ()) + | _ -> () + ) + input_views + in + + let reset_auto_save_timer () = + disconnect_auto_save_timer (); + if !current.auto_save then + auto_save_timer := Some + (GMain.Timeout.add ~ms:!current.auto_save_delay + ~callback: + (fun () -> + do_if_not_computing (fun () -> auto_save_f ()) (); + true)) + in reset_auto_save_timer (); (* to enable statup preferences timer *) + let configuration_menu = factory#add_submenu "Confi_guration" in let configuration_factory = new GMenu.factory configuration_menu ~accel_group in @@ -2028,28 +2221,15 @@ let main files = in let save_prefs_m = configuration_factory#add_item "_Save preferences" - ~callback:(fun () -> save_pref !current) - in - font_selector := - Some (GWindow.font_selection_dialog - ~title:"Select font..." - ~modal:true ()); - let font_selector = out_some !font_selector in - font_selector#selection#set_font_name (Pango.Font.to_string !current.text_font); - font_selector#selection#set_preview_text - "Lemma Truth: ∀ p:Prover, `p < Coq`. Proof. Auto with *. Save."; - let customize_fonts_m = - configuration_factory#add_item "Customize _fonts" - ~callback:(fun () -> font_selector#present ()) + ~callback:(fun () -> save_pref ()) in - let detach_menu = configuration_factory#add_item "_Detach Scripting Window" ~callback: (do_if_not_computing (fun () -> let nb = notebook () in - if nb#misc#toplevel#get_oid=w#coerce#get_oid then + if nb#misc#toplevel#get_oid=w#coerce#get_oid then begin let nw = GWindow.window ~show:true () in let parent = out_some nb#misc#parent in @@ -2061,6 +2241,35 @@ let main files = end )) in + let detach_current_view = configuration_factory#add_item + "De_tach View" + ~callback: + (do_if_not_computing + (fun () -> + match get_current_view () with + | {view=v;analyzed_view=Some av} -> + let w = GWindow.window ~show:true + ~title:(match av#filename with + | None -> "*Unnamed*" + | Some f -> f) + () + in + let sb = GBin.scrolled_window + ~packing:w#add () + in + let nv = GText.view + ~buffer:v#buffer + ~packing:sb#add + () + in + ignore (w#connect#destroy + ~callback: + (fun () -> av#remove_detached_view w)); + av#add_detached_view w + | _ -> () + + )) + in (* Help Menu *) let help_menu = factory#add_submenu "_Help" in @@ -2078,10 +2287,12 @@ let main files = av#help_for_keyword ()) in let _ = help_factory#add_separator () in + let faq_m = help_factory#add_item "_FAQ" in let about_m = help_factory#add_item "_About" in - (* Window layout *) + (* End of menu *) + (* The vertical Separator between Scripts and Goals *) let hb = GPack.paned `HORIZONTAL ~border_width:3 ~packing:vbox#add () in _notebook := Some (GPack.notebook ~scrollable:true ~packing:hb#add1 @@ -2101,13 +2312,13 @@ let main files = let status_bar = GMisc.statusbar ~packing:(lower_hbox#pack ~expand:true) () in let search_lbl = GMisc.label ~text:"Search:" - ~show:true + ~show:false ~packing:(lower_hbox#pack ~expand:false) () in let search_history = ref [] in let search_input = GEdit.combo ~popdown_strings:!search_history ~use_arrows:`DEFAULT - ~show:true + ~show:false ~packing:(lower_hbox#pack ~expand:false) () in search_input#disable_activate (); @@ -2128,16 +2339,21 @@ let main files = let v = (get_current_view ()).view in v#buffer#move_mark `SEL_BOUND (v#buffer#get_iter_at_mark `INSERT); v#coerce#misc#grab_focus (); - search_input#entry#set_text ""; + search_input#entry#set_text ""; + search_lbl#misc#hide (); + search_input#misc#hide () in ignore (search_input#entry#connect#activate ~callback:end_search); - to_do_on_page_switch := (fun i -> start_of_search := None; ready_to_wrap_search:=false)::!to_do_on_page_switch; + let rec search_f () = + search_lbl#misc#show (); + search_input#misc#show (); + prerr_endline "search_f called"; if !start_of_search = None then start_of_search := @@ -2147,8 +2363,9 @@ let main files = let v = (get_current_view ()).view in let iit = v#buffer#get_iter_at_mark `SEL_BOUND in prerr_endline ("SELBOUND="^(string_of_int iit#offset)); - prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset)); - + prerr_endline ("INSERT="^(string_of_int + (v#buffer#get_iter_at_mark `INSERT)#offset)); + (match if !search_forward then iit#forward_search txt else let npi = iit#forward_chars (Glib.Utf8.length txt) in @@ -2164,33 +2381,33 @@ let main files = | _,false -> (iit#backward_search txt) - with - | None -> - if !ready_to_wrap_search then begin - ready_to_wrap_search := false; - !flash_info "Search wrapped"; - v#buffer#place_cursor - (if !search_forward then v#buffer#start_iter else - v#buffer#end_iter); - search_f () - end else begin - if !search_forward then !flash_info "Search at end" - else !flash_info "Search at start"; - ready_to_wrap_search := true - end - | Some (start,stop) -> - prerr_endline "search: before moving marks"; - prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset)); - prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset)); - - v#buffer#move_mark `SEL_BOUND start; - v#buffer#move_mark `INSERT stop; - prerr_endline "search: after moving marks"; - prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset)); - prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset)); - v#scroll_to_mark `SEL_BOUND - ) - in + with + | None -> + if !ready_to_wrap_search then begin + ready_to_wrap_search := false; + !flash_info "Search wrapped"; + v#buffer#place_cursor + (if !search_forward then v#buffer#start_iter else + v#buffer#end_iter); + search_f () + end else begin + if !search_forward then !flash_info "Search at end" + else !flash_info "Search at start"; + ready_to_wrap_search := true + end + | Some (start,stop) -> + prerr_endline "search: before moving marks"; + prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset)); + prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset)); + + v#buffer#move_mark `SEL_BOUND start; + v#buffer#move_mark `INSERT stop; + prerr_endline "search: after moving marks"; + prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset)); + prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset)); + v#scroll_to_mark `SEL_BOUND + ) + in ignore (search_input#entry#event#connect#key_release ~callback: (fun ev -> @@ -2198,10 +2415,10 @@ let main files = let v = (get_current_view ()).view in (match !start_of_search with | None -> - prerr_endline "search_key_rel: Placing sel_bound"; + prerr_endline "search_key_rel: Placing sel_bound"; v#buffer#move_mark - `SEL_BOUND - (v#buffer#get_iter_at_mark `INSERT) + `SEL_BOUND + (v#buffer#get_iter_at_mark `INSERT) | Some mk -> let it = v#buffer#get_iter_at_mark (`MARK mk) in prerr_endline "search_key_rel: Placing cursor"; @@ -2212,9 +2429,9 @@ let main files = v#coerce#misc#grab_focus (); end; false - )) ; + )); ignore (search_input#entry#connect#changed search_f); - + ignore (search_if#connect#activate ~callback:(fun b -> search_forward:= true; @@ -2241,7 +2458,7 @@ let main files = status := Some status_bar; push_info := (fun s -> ignore (status_context#push s)); pop_info := (fun () -> status_context#pop ()); - flash_info := (fun s -> flash_context#flash ~delay:5000 s); + flash_info := (fun ?(delay=5000) s -> flash_context#flash ~delay s); (* Location display *) let l = GMisc.label @@ -2249,7 +2466,7 @@ let main files = ~packing:lower_hbox#pack () in l#coerce#misc#set_name "location"; set_location := l#set_text; - load_pref current; + (* Progress Bar *) pulse := (GRange.progress_bar ~text:"CoqIde started" ~pulse_step:0.2 ~packing:lower_hbox#pack ())#pulse; @@ -2292,23 +2509,14 @@ let main files = false)) e; false) in - ignore (font_selector#cancel_button#connect#released - ~callback:font_selector#misc#hide); - ignore (font_selector#ok_button#connect#released - ~callback:(fun () -> - (match font_selector#selection#font_name with - | None -> () - | Some n -> - let pango_font = Pango.Font.from_string n in - tv2#misc#modify_font pango_font; - tv3#misc#modify_font pango_font; - Vector.iter - (fun {view=view} -> view#misc#modify_font pango_font) - input_views; - !current.text_font <- pango_font - ); - font_selector#misc#hide ())); - + change_font := + (fun fd -> + tv2#misc#modify_font fd; + tv3#misc#modify_font fd; + Vector.iter + (fun {view=view} -> view#misc#modify_font fd) + input_views; + ); (try let image = Filename.concat lib_ide "coq.png" in let startup_image = GdkPixbuf.from_file image in @@ -2335,7 +2543,7 @@ let main files = w#show (); message_view := Some tv3; proof_view := Some tv2; - let view = create_input_tab "*Unamed Buffer*" in + let view = create_input_tab "*Unnamed Buffer*" in let index = add_input_view {view = view; analyzed_view = None; } @@ -2348,6 +2556,15 @@ let main files = tv3#misc#modify_font !current.text_font; ignore (about_m#connect#activate ~callback:(fun () -> tv3#buffer#set_text "by Benjamin Monate")); + ignore (faq_m#connect#activate + ~callback:(fun () -> + load (Filename.concat lib_ide "FAQ"))); + + resize_window := (fun () -> + w#resize + ~width:!current.window_width + ~height:!current.window_height); + ignore (w#misc#connect#size_allocate (let old_w = ref 0 and old_h = ref 0 in @@ -2357,7 +2574,9 @@ let main files = old_h := h; old_w := w; hb#set_position (w/2); - hb2#set_position (h*4/5) + hb2#set_position (h*4/5); + !current.window_height <- h; + !current.window_width <- w; end )); ignore(nb#connect#switch_page @@ -2374,7 +2593,7 @@ let main files = false)); List.iter load files; if List.length files >=1 then activate_input 1 - +;; let start () = let files = Coq.init () in diff --git a/ide/extract_index.mll b/ide/extract_index.mll index 1eb2c13d6..f3fbe0752 100644 --- a/ide/extract_index.mll +++ b/ide/extract_index.mll @@ -1,3 +1,12 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) { open Lexing diff --git a/ide/find_phrase.mll b/ide/find_phrase.mll index 16d1cd83e..ed124461f 100644 --- a/ide/find_phrase.mll +++ b/ide/find_phrase.mll @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + { exception Lex_error of string let length = ref 0 diff --git a/ide/highlight.mll b/ide/highlight.mll index c751ff3f2..cdfc51f98 100644 --- a/ide/highlight.mll +++ b/ide/highlight.mll @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + { open Lexing @@ -33,14 +43,14 @@ let keyword = "Section" | "Show" | "Syntactic" | "Syntax" | "Tactic" | "Unset" | ("Set" space+ "Implicit" space+ "Arguments") | - ("Implicit" space+ "Arguments" space+ ("On" | "Off")) + ("Implicit" space+ "Arguments" space+ ("On" | "Off")) | "Cases" let declaration = "Lemma" | "Axiom" | "CoFixpoint" | "Definition" | ("Tactic" space+ "Definition") | "Fixpoint" | "Hypothesis" | "Inductive" | "Parameter" | "Remark" | "Theorem" | - "Variable" | "Variables" + "Variable" | "Variables" rule next_order = parse | "(*" { comment_start := lexeme_start lexbuf; comment lexbuf } @@ -73,7 +83,6 @@ and comment = parse let lb = Lexing.from_string s in try while true do - (* process_pending (); This is VERY DANGEROUS *) let b,e,o=next_order lb in let b,e = convert_pos b,convert_pos e in let start = input_buffer#get_iter_at_char (offset + b) in diff --git a/ide/ideutils.ml b/ide/ideutils.ml index f0f54650e..671b12410 100644 --- a/ide/ideutils.ml +++ b/ide/ideutils.ml @@ -1,9 +1,18 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open Preferences exception Forbidden - let debug = Options.debug let prerr_endline s = @@ -116,8 +125,7 @@ let url_for_keyword = let browse_keyword text = - try - let u = url_for_keyword text in browse (!current.doc_url ^ u) + try let u = url_for_keyword text in browse (!current.doc_url ^ u) with _ -> () let my_stat f = try Some (Unix.stat f) with _ -> None @@ -127,6 +135,11 @@ let disconnect_revert_timer () = match !revert_timer with | None -> () | Some id -> GMain.Timeout.remove id; revert_timer := None +let auto_save_timer = ref None +let disconnect_auto_save_timer () = match !auto_save_timer with + | None -> () + | Some id -> GMain.Timeout.remove id; auto_save_timer := None + let highlight_timer = ref None let set_highlight_timer f = match !highlight_timer with @@ -202,3 +215,12 @@ let async = if Sys.os_type <> "Unix" then GtkThread.async else (fun x -> x) +let stock_to_widget ?(size=`DIALOG) s = + let img = GMisc.image () + in img#set_stock ~size s ; + img#coerce + +let rec print_list print fmt = function + | [] -> () + | [x] -> print fmt x + | x :: r -> print fmt x; print_list print fmt r diff --git a/ide/preferences.ml b/ide/preferences.ml index 10071161b..c6a1aabdd 100644 --- a/ide/preferences.ml +++ b/ide/preferences.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open Configwin open Printf open Util @@ -67,9 +77,63 @@ type pref = mutable doc_url : string; mutable library_url : string; + + mutable show_toolbar : bool; + mutable window_width : int; + mutable window_height :int; + } -let save_pref p = +let (current:pref ref) = + ref { + cmd_coqc = "coqc"; + cmd_make = "make"; + cmd_coqmakefile = "coq_makefile -o Makefile *.v"; + cmd_coqdoc = "coqdoc -q -g"; + cmd_print = "lpr"; + + global_auto_revert = false; + global_auto_revert_delay = 10000; + + auto_save = false; + auto_save_delay = 10000; + auto_save_name = "#","#"; + + automatic_tactics = ["Progress Trivial.","Trivial."; + "Progress Auto.","Auto."; + "Tauto.","Tauto."; + "Omega.","Omega."; + "Progress Auto with *.","Auto with *."; + "Progress Intuition.","Intuition."; + ]; + + modifier_for_navigation = [`CONTROL; `MOD1]; + modifier_for_templates = [`MOD4]; + modifier_for_tactics = [`CONTROL; `MOD1]; + modifiers_valid = [`SHIFT; `CONTROL; `MOD1; `MOD4]; + + + cmd_browse = "netscape -remote \"OpenURL(", ")\""; + + text_font = Pango.Font.from_string "Monospace 12"; + + doc_url = "http://coq.inria.fr/doc/"; + library_url = "http://coq.inria.fr/library/"; + + show_toolbar = true; + window_width = 800; + window_height = 600; + } + + +let change_font = ref (fun f -> ()) + +let show_toolbar = ref (fun x -> ()) + +let resize_window = ref (fun () -> ()) + +let save_pref () = + let p = !current in try let add = Stringmap.add in let (++) x f = f x in @@ -101,51 +165,18 @@ let save_pref p = add "doc_url" [p.doc_url] ++ add "library_url" [p.library_url] ++ + add "show_toolbar" [string_of_bool p.show_toolbar] ++ + add "window_height" [string_of_int p.window_height] ++ + add "window_width" [string_of_int p.window_width] ++ Config_lexer.print_file pref_file with _ -> prerr_endline "Could not save preferences." -let (current:pref ref) = - ref { - cmd_coqc = "coqc"; - cmd_make = "make"; - cmd_coqmakefile = "coq_makefile -o Makefile *.v"; - cmd_coqdoc = "coqdoc -q -g"; - cmd_print = "lpr"; - - global_auto_revert = false; - global_auto_revert_delay = 10000; - - auto_save = false; - auto_save_delay = 10000; - auto_save_name = "#","#"; - - automatic_tactics = ["Progress Trivial.\n","Trivial.\n"; - "Progress Auto.\n","Auto.\n"; - "Tauto.\n","Tauto.\n"; - "Omega.\n","Omega.\n"; - "Progress Auto with *.\n","Auto with *.\n"; - "Progress Intuition.\n","Intuition.\n"; - ]; - - modifier_for_navigation = [`CONTROL; `MOD1]; - modifier_for_templates = [`MOD4]; - modifier_for_tactics = [`CONTROL; `MOD1]; - modifiers_valid = [`SHIFT; `CONTROL; `MOD1; `MOD4]; - - - cmd_browse = "netscape -remote \"OpenURL(", ")\""; - - text_font = Pango.Font.from_string "Monospace 12"; - - doc_url = "http://coq.inria.fr/doc/"; - library_url = "http://coq.inria.fr/library/"; - } - -let load_pref p = +let load_pref () = + let p = !current in try let m = Config_lexer.load_file pref_file in - let np = { !p with cmd_coqc = !p.cmd_coqc } in + let np = { p with cmd_coqc = p.cmd_coqc } in let set k f = try let v = Stringmap.find k m in f v with _ -> () in let set_hd k f = set k (fun v -> f (List.hd v)) in let set_bool k f = set_hd k (fun v -> f (bool_of_string v)) in @@ -181,10 +212,15 @@ let load_pref p = set_hd "text_font" (fun v -> np.text_font <- Pango.Font.from_string v); set_hd "doc_url" (fun v -> np.doc_url <- v); set_hd "library_url" (fun v -> np.library_url <- v); + set_bool "show_toolbar" (fun v -> np.show_toolbar <- v); + set_int "window_width" (fun v -> np.window_width <- v); + set_int "window_height" (fun v -> np.window_height <- v); + current := np with e -> prerr_endline ("Could not load preferences ("^ (Printexc.to_string e)^").") + let configure () = let cmd_coqc = @@ -198,6 +234,48 @@ let configure () = let cmd_print = string ~f:(fun s -> !current.cmd_print <- s) "Print ps" !current.cmd_print in + let config_font = + let box = GPack.hbox () in + let w = GMisc.font_selection () in + w#set_preview_text + "Lemma Truth: ∀ p:Prover, `p < Coq`. Proof. Auto with *. Save."; + box#pack w#coerce; + ignore (w#misc#connect#realize + ~callback:(fun () -> w#set_font_name + (Pango.Font.to_string !current.text_font))); + custom + ~label:"Fonts for text" + box + (fun () -> match w#font_name with + | None -> () + | Some fd -> !current.text_font <- (Pango.Font.from_string fd) ; !change_font !current.text_font) + true + in + let show_toolbar = + bool + ~f:(fun s -> + !current.show_toolbar <- s; + !show_toolbar s) + "Show toolbar" !current.show_toolbar + in + let window_height = + string + ~f:(fun s -> !current.window_height <- (try int_of_string s with _ -> 600); + !resize_window (); + ) + "Window height" + (string_of_int !current.window_height) + in + let window_width = + string + ~f:(fun s -> !current.window_width <- + (try int_of_string s with _ -> 800)) + "Window width" + (string_of_int !current.window_width) + in + + let config_appearance = [show_toolbar; window_width; window_height] in + let global_auto_revert = bool ~f:(fun s -> !current.global_auto_revert <- s) @@ -211,6 +289,19 @@ let configure () = (string_of_int !current.global_auto_revert_delay) in + let auto_save = + bool + ~f:(fun s -> !current.auto_save <- s) + "Enable auto save" !current.auto_save + in + let auto_save_delay = + string + ~f:(fun s -> !current.auto_save_delay <- + (try int_of_string s with _ -> 10000)) + "Auto save delay (ms)" + (string_of_int !current.auto_save_delay) + in + let modifier_for_tactics = modifiers ~allow:!current.modifiers_valid @@ -238,6 +329,12 @@ let configure () = "Allowed modifiers" !current.modifiers_valid in + let mod_msg = + string + "Needs restart to apply!" + ~editable:false + "" + in let cmd_browse = string @@ -265,27 +362,35 @@ let configure () = let automatic_tactics = let box = GPack.hbox () in - let w = Editable_cells.create !current.automatic_tactics in - box#pack w#coerce; + let (w,get_data) = Editable_cells.create !current.automatic_tactics in + box#add w#coerce; custom - ~label:"Wizzard tactics to try in order (WORK IN PROGRESS)" + ~label:"Wizzard tactics to try in order" box - (fun () -> ()) + (fun () -> let d = get_data () in !current.automatic_tactics <- d) true in let cmds = - [Section("Commands", + [Section("Fonts", + [config_font]); + Section("Appearance", + config_appearance); + Section("Commands", [cmd_coqc;cmd_make;cmd_coqmakefile; cmd_coqdoc; cmd_print]); Section("Files", - [global_auto_revert;global_auto_revert_delay]); + [global_auto_revert;global_auto_revert_delay; + auto_save; auto_save_delay; (* auto_save_name*) + ]); Section("Browser", [cmd_browse;doc_url;library_url]); Section("Tactics Wizzard", [automatic_tactics]); - Section("Shortcuts(need restart)", - [modifiers_valid; modifier_for_tactics;modifier_for_templates; modifier_for_navigation])] + Section("Shortcuts", + [modifiers_valid; modifier_for_tactics; + modifier_for_templates; modifier_for_navigation;mod_msg])] in - match edit "Customizations" cmds - with | Return_apply | Return_ok -> save_pref !current + match edit ~width:500 "Customizations" cmds + with + | Return_apply | Return_ok -> save_pref () | Return_cancel -> () diff --git a/ide/undo.ml b/ide/undo.ml index e8fc305c7..10d5e0ab5 100644 --- a/ide/undo.ml +++ b/ide/undo.ml @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + open GText open Ideutils type action = diff --git a/ide/undo.mli b/ide/undo.mli index 0aae49e79..64812a53e 100644 --- a/ide/undo.mli +++ b/ide/undo.mli @@ -1,3 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + (* An undoable view class *) class undoable_view : Gtk.textview Gtk.obj -> diff --git a/ide/utils/configwin_ihm.ml b/ide/utils/configwin_ihm.ml index 04d7c05ed..d01b83003 100644 --- a/ide/utils/configwin_ihm.ml +++ b/ide/utils/configwin_ihm.ml @@ -1059,16 +1059,19 @@ let edit ?(with_apply=true) let hbox_buttons = GPack.hbox ~packing: (vbox#pack ~expand: false ~padding: 4) () in let bApply = GButton.button - ~label: Configwin_messages.mApply - () + ~stock:`APPLY + ~label: Configwin_messages.mApply + () in if with_apply then hbox_buttons#pack ~expand: true ~padding: 3 bApply#coerce; let bOk = GButton.button + ~stock:`OK ~label: Configwin_messages.mOk ~packing: (hbox_buttons#pack ~expand: true ~padding: 3) () in let bCancel = GButton.button + ~stock:`CANCEL ~label: Configwin_messages.mCancel ~packing: (hbox_buttons#pack ~expand: true ~padding: 3) () @@ -1091,6 +1094,9 @@ let edit ?(with_apply=true) let f_cancel () = window#destroy () in let _ = bCancel#connect#clicked f_cancel in + let _ = window#event#connect#key_press ~callback: + (fun k -> if GdkEvent.Key.keyval k = GdkKeysyms._Escape then f_cancel ();false) + in let _ = window#show () in GMain.Main.main () ; !return diff --git a/ide/utils/editable_cells.ml b/ide/utils/editable_cells.ml index 1fd15f77a..20111bf84 100644 --- a/ide/utils/editable_cells.ml +++ b/ide/utils/editable_cells.ml @@ -3,11 +3,17 @@ open Gobject let create l = let hbox = GPack.hbox () in + let scw = GBin.scrolled_window + ~hpolicy:`AUTOMATIC + ~vpolicy:`AUTOMATIC + ~packing:(hbox#pack ~expand:true) () in + let columns = new GTree.column_list in let command_col = columns#add Data.string in let coq_col = columns#add Data.string in let store = GTree.list_store columns in + (* populate the store *) let _ = List.iter (fun (x,y) -> let row = store#append () in @@ -15,25 +21,97 @@ let create l = store#set ~row ~column:coq_col y) l in - let view = GTree.view ~model:store ~packing:hbox#pack () in - - let renderer = GTree.cell_renderer_text () in - GtkText.Tag.set_property renderer (`EDITABLE true); + let view = GTree.view ~model:store ~packing:scw#add_with_viewport () in + + (* Alternate colors for the rows *) + view#set_rules_hint true; + + let renderer_comm = GTree.cell_renderer_text () in + ignore (GtkSignal.connect renderer_comm + ~sgn:GtkTree.CellRendererText.Signals.edited + ~callback:(fun (path:Gtk.tree_path) (s:string) -> + store#set + ~row:(store#get_iter path) + ~column:command_col s)); + GtkText.Tag.set_property renderer_comm (`EDITABLE true); let first = GTree.view_column ~title:"Coq Command to try" - ~renderer:(renderer,["text",command_col]) + ~renderer:(renderer_comm,["text",command_col]) () in ignore (view#append_column first); + + let renderer_coq = GTree.cell_renderer_text () in + ignore (GtkSignal.connect renderer_coq ~sgn:GtkTree.CellRendererText.Signals.edited + ~callback:(fun (path:Gtk.tree_path) (s:string) -> + store#set + ~row:(store#get_iter path) + ~column:coq_col s)); + GtkText.Tag.set_property renderer_coq (`EDITABLE true); let second = GTree.view_column ~title:"Coq Command to insert" - ~renderer:(renderer,["text",coq_col]) + ~renderer:(renderer_coq,["text",coq_col]) () in ignore (view#append_column second); - let vbox = GPack.button_box `VERTICAL ~packing:hbox#pack () in - let up = GButton.button ~label:"Up" ~packing:(vbox#pack ~expand:true ~fill:false) () in - let down = GButton.button ~label:"Down" ~packing:(vbox#pack ~expand:true ~fill:false) () in - let add = GButton.button ~label:"Add" ~packing:(vbox#pack ~expand:true ~fill:false) () in - let remove = GButton.button ~label:"Remove" ~packing:(vbox#pack ~expand:true ~fill:false) () in - hbox + let vbox = GPack.button_box `VERTICAL ~packing:hbox#pack ~layout:`SPREAD () + in + let up = GButton.button ~stock:`GO_UP ~label:"Up" ~packing:(vbox#pack ~expand:true ~fill:false) () in + let down = GButton.button + ~stock:`GO_DOWN + ~label:"Down" + ~packing:(vbox#pack ~expand:true ~fill:false) () + in + let add = GButton.button ~stock:`ADD + ~label:"Add" + ~packing:(vbox#pack ~expand:true ~fill:false) + () + in + let remove = GButton.button ~stock:`REMOVE + ~label:"Remove" + ~packing:(vbox#pack ~expand:true ~fill:false) () + in + + ignore (add#connect#clicked + ~callback:(fun b -> + let n = store#append () in + view#selection#select_iter n)); + ignore (remove#connect#clicked + ~callback:(fun b -> match view#selection#get_selected_rows with + | [] -> () + | path::_ -> + let iter = store#get_iter path in + ignore (store#remove iter); + )); + ignore (up#connect#clicked + ~callback:(fun b -> + match view#selection#get_selected_rows with + | [] -> () + | path::_ -> + let iter = store#get_iter path in + GtkTree.TreePath.prev path; + let upiter = store#get_iter path in + ignore (store#swap iter upiter); + )); + ignore (down#connect#clicked + ~callback:(fun b -> + match view#selection#get_selected_rows with + | [] -> () + | path::_ -> + let iter = store#get_iter path in + GtkTree.TreePath.next path; + try let upiter = store#get_iter path in + ignore (store#swap iter upiter) + with _ -> () + )); + let get_data () = + let start_path = GtkTree.TreePath.from_string "0" in + let start_iter = store#get_iter start_path in + let rec all acc = + let new_acc = (store#get ~row:start_iter ~column:command_col, + store#get ~row:start_iter ~column:coq_col)::acc + in + if store#iter_next start_iter then all new_acc else List.rev new_acc + in all [] + in + (hbox,get_data) |