String.sub s 0 nl_pos
with Not_found -> s
-type guistuff = {
- mathviewer:MatitaTypes.mathViewer;
- urichooser: UriManager.uri list -> UriManager.uri list;
- ask_confirmation: title:string -> message:string -> [`YES | `NO | `CANCEL];
-}
-
-let eval_with_engine include_paths guistuff grafite_status user_goal
- skipped_txt nonskipped_txt st
+let eval_with_engine include_paths status skipped_txt nonskipped_txt st
=
let parsed_text_length =
String.length skipped_txt + String.length nonskipped_txt
let text = skipped_txt ^ nonskipped_txt in
let prefix_len = MatitaGtkMisc.utf8_string_length skipped_txt in
let enriched_history_fragment =
- MatitaEngine.eval_ast ~do_heavy_checks:(Helm_registry.get_bool
+ MatitaEngine.eval_ast ~include_paths ~do_heavy_checks:(Helm_registry.get_bool
"matita.do_heavy_checks")
- grafite_status (text,prefix_len,st)
+ status (text,prefix_len,st)
in
let enriched_history_fragment = List.rev enriched_history_fragment in
(* really fragile *)
match alias with
| None -> (status,to_prepend ^ nonskipped_txt)::acc,""
| Some (k,value) ->
- let newtxt = LexiconAstPp.pp_alias value in
+ let newtxt = GrafiteAstPp.pp_alias value in
(status,to_prepend ^ newtxt ^ "\n")::acc, "")
([],skipped_txt) enriched_history_fragment
in
res,"",parsed_text_length
;;
-(* this function calls the parser in a way that it does not perform inclusions,
- * so that we can ensure the inclusion is performed after the included file
- * is compiled (if needed). matitac does not need that, since it compiles files
- * in the good order, here files may be compiled on demand. *)
-let wrap_with_make include_paths (f : #LexiconEngine.status GrafiteParser.statement) x =
- try
- f ~never_include:true ~include_paths x
- with
- | GrafiteParser.NoInclusionPerformed mafilename ->
- let root, buri, _, tgt =
- try Librarian.baseuri_of_script ~include_paths mafilename
- with Librarian.NoRootFor _ ->
- HLog.error ("The included file '"^mafilename^"' has no root file,");
- HLog.error "please create it.";
- raise (Failure ("No root file for "^mafilename))
- in
- let b = MatitacLib.Make.make root [tgt] in
- if b then
- try f ~include_paths x with LexiconEngine.IncludedFileNotCompiled _ ->
- raise
- (Failure ("Including: "^tgt^
- "\nNothing to do... did you run matitadep?"))
- else raise (Failure ("Compiling: " ^ tgt))
-;;
-
-let pp_eager_statement_ast =
- GrafiteAstPp.pp_statement ~term_pp:CicNotationPp.pp_term
- ~lazy_term_pp:(fun _ -> assert false) ~obj_pp:(fun _ -> assert false)
+let pp_eager_statement_ast = GrafiteAstPp.pp_statement
-let eval_nmacro include_paths (buffer : GText.buffer) guistuff grafite_status user_goal unparsed_text parsed_text script mac =
+let eval_nmacro include_paths (buffer : GText.buffer) status unparsed_text parsed_text script mac =
let parsed_text_length = String.length parsed_text in
match mac with
| TA.Screenshot (_,name) ->
- let status = script#grafite_status in
+ let status = script#status in
let _,_,menv,subst,_ = status#obj in
let name = Filename.dirname (script#filename) ^ "/" ^ name in
let sequents =
let selected = Continuationals.Stack.head_goals status#stack in
List.filter (fun x,_ -> List.mem x selected) menv
in
- guistuff.mathviewer#screenshot status sequents menv subst name;
+ CicMathView.screenshot status sequents menv subst name;
[status, parsed_text], "", parsed_text_length
| TA.NCheck (_,t) ->
- let status = script#grafite_status in
+ let status = script#status in
let _,_,menv,subst,_ = status#obj in
let ctx =
- try let _,(_,ctx,_) = List.hd menv in ctx
- with Failure "hd" -> []
- in
+ match Continuationals.Stack.head_goals status#stack with
+ [] -> []
+ | g::tl ->
+ if tl <> [] then
+ HLog.warn
+ "Many goals focused. Using the context of the first one\n";
+ let _, ctx, _ = NCicUtils.lookup_meta g menv in
+ ctx in
let m, s, status, t =
GrafiteDisambiguate.disambiguate_nterm
- None status ctx menv subst (parsed_text,parsed_text_length,
- CicNotationPt.Cast (t,CicNotationPt.Implicit `JustOne))
+ status None ctx menv subst (parsed_text,parsed_text_length,
+ NotationPt.Cast (t,NotationPt.Implicit `JustOne))
(* XXX use the metasenv, if possible *)
in
- guistuff.mathviewer#show_entry (`NCic (t,ctx,m,s));
+ MatitaMathView.cicBrowser (Some (`NCic (t,ctx,m,s)));
[status, parsed_text], "", parsed_text_length
| TA.NIntroGuess _loc ->
let names_ref = ref [] in
- let s =
- NTactics.intros_tac ~names_ref [] script#grafite_status
- in
+ let s = NTactics.intros_tac ~names_ref [] script#status in
let rex = Pcre.regexp ~flags:[`MULTILINE] "\\A([\\n\\t\\r ]*).*\\Z" in
let nl = Pcre.replace ~rex ~templ:"$1" parsed_text in
- [s, nl ^ "#" ^ String.concat " " !names_ref ^ ";"], "", parsed_text_length
+ [s, nl ^ "#" ^ String.concat " #" !names_ref], "", parsed_text_length
| TA.NAutoInteractive (_loc, (None,a)) ->
let trace_ref = ref [] in
- let s =
- NnAuto.auto_tac
- ~params:(None,a) ~trace_ref script#grafite_status
- in
+ let s = NnAuto.auto_tac ~params:(None,a) ~trace_ref script#status in
let depth =
try List.assoc "depth" a
with Not_found -> ""
in
- let trace = "/"^(if int_of_string depth > 1 then depth else "")^"/ by " in
+ let trace = "/"^(if int_of_string depth > 1 then depth else "")^" by " in
let thms =
match !trace_ref with
- | [] -> "{}"
+ | [] -> ""
| thms ->
String.concat ", "
(HExtlib.filter_map (function
- | CicNotationPt.NRef r -> Some (NCicPp.r2s true r)
+ | NotationPt.NRef r -> Some (NCicPp.r2s status true r)
| _ -> None)
thms)
in
let rex = Pcre.regexp ~flags:[`MULTILINE] "\\A([\\n\\t\\r ]*).*\\Z" in
let nl = Pcre.replace ~rex ~templ:"$1" parsed_text in
- [s, nl ^ trace ^ thms ^ ";"], "", parsed_text_length
+ [s, nl ^ trace ^ thms ^ "/"], "", parsed_text_length
| TA.NAutoInteractive (_, (Some _,_)) -> assert false
-let rec eval_macro include_paths (buffer : GText.buffer) guistuff grafite_status user_goal unparsed_text parsed_text script mac =
- let module CTC = CicTypeChecker in
- (* no idea why ocaml wants this *)
- let parsed_text_length = String.length parsed_text in
- let dbd = LibraryDb.instance () in
- match mac with
- (* REAL macro *)
- | TA.Hint (loc, rewrite) -> (* MATITA 1.0 *) assert false
- | TA.Eval (_, kind, term) -> assert false (* MATITA 1.0
- let metasenv = GrafiteTypes.get_proof_metasenv grafite_status in
- let context =
- match user_goal with
- None -> []
- | Some n -> GrafiteTypes.get_proof_context grafite_status n in
- let ty,_ = CTC.type_of_aux' metasenv context term CicUniv.empty_ugraph in
- let term =
- match kind with
- | `Normalize ->
- CicReduction.normalize ~delta:true ~subst:[] context term
- | `Simpl ->
- ProofEngineReduction.simpl context term
- | `Unfold None ->
- ProofEngineReduction.unfold ?what:None context term
- | `Unfold (Some lazy_term) ->
- let what, _, _ =
- lazy_term context metasenv CicUniv.empty_ugraph in
- ProofEngineReduction.unfold ~what context term
- | `Whd ->
- CicReduction.whd ~delta:true ~subst:[] context term
- in
- let t_and_ty = Cic.Cast (term,ty) in
- guistuff.mathviewer#show_entry (`Cic (t_and_ty,metasenv));
- [(grafite_status#set_proof_status No_proof), parsed_text ],"",
- parsed_text_length *)
- | TA.Inline (_, suri, params) ->
- let str = "\n\n" ^
- ApplyTransformation.txt_of_inline_macro
- ~map_unicode_to_tex:(Helm_registry.get_bool
- "matita.paste_unicode_as_tex")
- params suri
- in
- [], str, String.length parsed_text
-
-and eval_executable include_paths (buffer : GText.buffer) guistuff
-grafite_status user_goal unparsed_text skipped_txt nonskipped_txt
-script ex loc
+let rec eval_executable include_paths (buffer : GText.buffer)
+status unparsed_text skipped_txt nonskipped_txt script ex loc
=
try
ignore (buffer#move_mark (`NAME "beginning_of_statement")
~where:((buffer#get_iter_at_mark (`NAME "locked"))#forward_chars
(Glib.Utf8.length skipped_txt))) ;
- eval_with_engine include_paths
- guistuff grafite_status user_goal skipped_txt nonskipped_txt
- (TA.Executable (loc, ex))
+ eval_with_engine include_paths status skipped_txt nonskipped_txt
+ (TA.Executable (loc, ex))
with
MatitaTypes.Cancel -> [], "", 0
- | GrafiteEngine.Macro (_loc,lazy_macro) ->
- let context = [] in
- let grafite_status,macro = lazy_macro context in
- eval_macro include_paths buffer guistuff grafite_status
- user_goal unparsed_text (skipped_txt ^ nonskipped_txt) script macro
| GrafiteEngine.NMacro (_loc,macro) ->
- eval_nmacro include_paths buffer guistuff grafite_status
- user_goal unparsed_text (skipped_txt ^ nonskipped_txt) script macro
+ eval_nmacro include_paths buffer status
+ unparsed_text (skipped_txt ^ nonskipped_txt) script macro
-and eval_statement include_paths (buffer : GText.buffer) guistuff
- grafite_status user_goal script statement
+and eval_statement include_paths (buffer : GText.buffer) status script
+ statement
=
- let (grafite_status,st), unparsed_text =
+ let st,unparsed_text =
match statement with
| `Raw text ->
if Pcre.pmatch ~rex:only_dust_RE text then raise Margin;
- let ast =
- wrap_with_make include_paths
- (GrafiteParser.parse_statement (Ulexing.from_utf8_string text))
- grafite_status
- in
- ast, text
- | `Ast (st, text) -> (grafite_status, st), text
+ let strm =
+ GrafiteParser.parsable_statement status
+ (Ulexing.from_utf8_string text) in
+ let ast = MatitaEngine.get_ast status include_paths strm in
+ ast, text
+ | `Ast (st, text) -> st, text
in
let text_of_loc floc =
let nonskipped_txt,_ = MatitaGtkMisc.utf8_parsed_text unparsed_text floc in
txt,nonskipped_txt,skipped_txt,len
in
match st with
- | GrafiteParser.LNone loc ->
- let parsed_text, _, _, parsed_text_length = text_of_loc loc in
- [grafite_status,parsed_text],"",
- parsed_text_length
- | GrafiteParser.LSome (GrafiteAst.Executable (loc, ex)) ->
+ | GrafiteAst.Executable (loc, ex) ->
let _, nonskipped, skipped, parsed_text_length = text_of_loc loc in
- eval_executable include_paths buffer guistuff
- grafite_status user_goal unparsed_text skipped nonskipped script ex loc
- | GrafiteParser.LSome (GrafiteAst.Comment (loc, GrafiteAst.Code (_, ex)))
+ eval_executable include_paths buffer status unparsed_text
+ skipped nonskipped script ex loc
+ | GrafiteAst.Comment (loc, GrafiteAst.Code (_, ex))
when Helm_registry.get_bool "matita.execcomments" ->
let _, nonskipped, skipped, parsed_text_length = text_of_loc loc in
- eval_executable include_paths buffer guistuff
- grafite_status user_goal unparsed_text skipped nonskipped script ex loc
- | GrafiteParser.LSome (GrafiteAst.Comment (loc, _)) ->
+ eval_executable include_paths buffer status unparsed_text
+ skipped nonskipped script ex loc
+ | GrafiteAst.Comment (loc, _) ->
let parsed_text, _, _, parsed_text_length = text_of_loc loc in
let remain_len = String.length unparsed_text - parsed_text_length in
let s = String.sub unparsed_text parsed_text_length remain_len in
let s,text,len =
try
- eval_statement include_paths buffer guistuff
- grafite_status user_goal script (`Raw s)
+ eval_statement include_paths buffer status script (`Raw s)
with
HExtlib.Localized (floc, exn) ->
HExtlib.raise_localized_exception
let i = ref 0 in
fun () -> incr i; !i
-class script ~(source_view: GSourceView2.source_view)
- ~(mathviewer: MatitaTypes.mathViewer)
- ~set_star
- ~ask_confirmation
- ~urichooser
- () =
+(** Selection handling
+ * Two clipboards are used: "clipboard" and "primary".
+ * "primary" is used by X, when you hit the middle button mouse is content is
+ * pasted between applications. In Matita this selection always contain the
+ * textual version of the selected term.
+ * "clipboard" is used inside Matita only and support ATM two different targets:
+ * "TERM" and "PATTERN", in the future other targets like "MATHMLCONTENT" may
+ * be added
+ *)
+class script ~(parent:GBin.scrolled_window) ~tab_label () =
+let source_view =
+ GSourceView2.source_view
+ ~auto_indent:true
+ ~insert_spaces_instead_of_tabs:true ~tab_width:2
+ ~right_margin_position:80 ~show_right_margin:true
+ ~smart_home_end:`AFTER
+ ~packing:parent#add
+ () in
let buffer = source_view#buffer in
let source_buffer = source_view#source_buffer in
+let similarsymbols_tag_name = "similarsymbolos" in
+let similarsymbols_tag = `NAME similarsymbols_tag_name in
let initial_statuses current baseuri =
- let empty_lstatus = new LexiconEngine.status in
+ let status = new MatitaEngine.status baseuri in
(match current with
- Some current ->
- LexiconSync.time_travel ~present:current ~past:empty_lstatus;
- GrafiteSync.time_travel ~present:current ();
- (* CSC: there is a known bug in invalidation; temporary fix here *)
- NCicEnvironment.invalidate ()
+ Some current -> NCicLibrary.time_travel status;
+(*
+ (* MATITA 1.0: there is a known bug in invalidation; temporary fix here *)
+ NCicEnvironment.invalidate () *)
| None -> ());
- let lexicon_status =
- CicNotation2.load_notation ~include_paths:[] empty_lstatus
- BuildTimeConf.core_notation_script
- in
- let grafite_status = GrafiteSync.init lexicon_status baseuri in
- grafite_status
-in
-let read_include_paths file =
- try
- let root, _buri, _fname, _tgt =
- Librarian.baseuri_of_script ~include_paths:[] file
- in
- let rc =
- Str.split (Str.regexp " ")
- (List.assoc "include_paths" (Librarian.load_root_file (root^"/root")))
- in
- List.iter (HLog.debug) rc; rc
- with Librarian.NoRootFor _ | Not_found -> []
+ status
in
let default_buri = "cic:/matita/tests" in
let default_fname = ".unnamed.ma" in
object (self)
val mutable include_paths_ = []
+ val clipboard = GData.clipboard Gdk.Atom.clipboard
+ (*val primary = GData.clipboard Gdk.Atom.primary*)
+ val mutable similarsymbols = []
+ val mutable similarsymbols_orig = []
+ val similar_memory = Hashtbl.create 97
+ val mutable old_used_memory = false
val scriptId = fresh_script_id ()
- val guistuff = {
- mathviewer = mathviewer;
- urichooser = urichooser;
- ask_confirmation = ask_confirmation;
- }
-
val mutable filename_ = (None : string option)
method has_name = filename_ <> None
+
+ method source_view = source_view
method include_paths =
include_paths_ @
method private curdir =
try
let root, _buri, _fname, _tgt =
- Librarian.baseuri_of_script ~include_paths:self#include_paths
+ Librarian.baseuri_of_script ~include_paths:self#include_paths
self#filename
in
root
Librarian.baseuri_of_script ~include_paths:self#include_paths f
in
buri
- with Librarian.NoRootFor _ -> default_buri
+ with Librarian.NoRootFor _ | Librarian.FileNotFound _ -> default_buri
method filename = match filename_ with None -> default_fname | Some f -> f
initializer
+ ignore
+ (source_view#source_buffer#begin_not_undoable_action ();
+ self#reset ();
+ self#template ();
+ source_view#source_buffer#end_not_undoable_action ());
+ MatitaMisc.observe_font_size (fun font_size ->
+ source_view#misc#modify_font_by_name
+ (sprintf "%s %d" BuildTimeConf.script_font font_size));
+ source_view#misc#grab_focus ();
+ ignore(source_view#source_buffer#set_language
+ (Some MatitaGtkMisc.matita_lang));
+ ignore(source_view#source_buffer#set_highlight_syntax true);
+ ignore(source_view#connect#after#paste_clipboard
+ ~callback:(fun () -> self#clean_dirty_lock));
ignore (GMain.Timeout.add ~ms:300000
~callback:(fun _ -> self#_saveToBackupFile ();true));
ignore (buffer#connect#modified_changed
- (fun _ -> set_star buffer#modified))
+ (fun _ -> self#set_star buffer#modified));
+ (* clean_locked is set to true only "during" a PRIMARY paste
+ operation (i.e. by clicking with the second mouse button) *)
+ let clean_locked = ref false in
+ ignore(source_view#event#connect#button_press
+ ~callback:
+ (fun button ->
+ if GdkEvent.Button.button button = 2 then
+ clean_locked := true;
+ false
+ ));
+ ignore(source_view#event#connect#button_release
+ ~callback:(fun button -> clean_locked := false; false));
+ ignore(source_view#buffer#connect#after#apply_tag
+ ~callback:(
+ fun tag ~start:_ ~stop:_ ->
+ if !clean_locked &&
+ tag#get_oid = self#locked_tag#get_oid
+ then
+ begin
+ clean_locked := false;
+ self#clean_dirty_lock;
+ clean_locked := true
+ end));
+ ignore(source_view#source_buffer#connect#after#insert_text
+ ~callback:(fun iter str ->
+ if (MatitaMisc.get_gui ())#main#menuitemAutoAltL#active && (str = " " || str = "\n") then
+ ignore(self#expand_virtual_if_any iter str)));
+ ignore(source_view#connect#after#populate_popup
+ ~callback:(fun pre_menu ->
+ let menu = new GMenu.menu pre_menu in
+ let menuItems = menu#children in
+ let undoMenuItem, redoMenuItem =
+ match menuItems with
+ [undo;redo;sep1;cut;copy;paste;delete;sep2;
+ selectall;sep3;inputmethod;insertunicodecharacter] ->
+ List.iter menu#remove [ copy; cut; delete; paste ];
+ undo,redo
+ | _ -> assert false in
+ let add_menu_item =
+ let i = ref 2 in (* last occupied position *)
+ fun ?label ?stock () ->
+ incr i;
+ GMenu.image_menu_item ?label ?stock ~packing:(menu#insert ~pos:!i)
+ ()
+ in
+ let copy = add_menu_item ~stock:`COPY () in
+ let cut = add_menu_item ~stock:`CUT () in
+ let delete = add_menu_item ~stock:`DELETE () in
+ let paste = add_menu_item ~stock:`PASTE () in
+ let paste_pattern = add_menu_item ~label:"Paste as pattern" () in
+ copy#misc#set_sensitive self#canCopy;
+ cut#misc#set_sensitive self#canCut;
+ delete#misc#set_sensitive self#canDelete;
+ paste#misc#set_sensitive self#canPaste;
+ paste_pattern#misc#set_sensitive self#canPastePattern;
+ MatitaGtkMisc.connect_menu_item copy self#copy;
+ MatitaGtkMisc.connect_menu_item cut self#cut;
+ MatitaGtkMisc.connect_menu_item delete self#delete;
+ MatitaGtkMisc.connect_menu_item paste self#paste;
+ MatitaGtkMisc.connect_menu_item paste_pattern self#pastePattern;
+ let new_undoMenuItem =
+ GMenu.image_menu_item
+ ~image:(GMisc.image ~stock:`UNDO ())
+ ~use_mnemonic:true
+ ~label:"_Undo"
+ ~packing:(menu#insert ~pos:0) () in
+ new_undoMenuItem#misc#set_sensitive
+ (undoMenuItem#misc#get_flag `SENSITIVE);
+ menu#remove (undoMenuItem :> GMenu.menu_item);
+ MatitaGtkMisc.connect_menu_item new_undoMenuItem
+ (fun () -> self#safe_undo);
+ let new_redoMenuItem =
+ GMenu.image_menu_item
+ ~image:(GMisc.image ~stock:`REDO ())
+ ~use_mnemonic:true
+ ~label:"_Redo"
+ ~packing:(menu#insert ~pos:1) () in
+ new_redoMenuItem#misc#set_sensitive
+ (redoMenuItem#misc#get_flag `SENSITIVE);
+ menu#remove (redoMenuItem :> GMenu.menu_item);
+ MatitaGtkMisc.connect_menu_item new_redoMenuItem
+ (fun () -> self#safe_redo)));
val mutable statements = [] (** executed statements *)
* the script.
* Invariant: this list length is 1 + length of statements *)
- (** goal as seen by the user (i.e. metano corresponding to current tab) *)
- val mutable userGoal = (None : int option)
-
(** text mark and tag representing locked part of a script *)
val locked_mark =
buffer#create_mark ~name:"locked" ~left_gravity:true buffer#start_iter
val locked_tag = buffer#create_tag [`BACKGROUND "lightblue"; `EDITABLE false]
val error_tag = buffer#create_tag [`UNDERLINE `SINGLE; `FOREGROUND "red"]
+ (** unicode handling *)
+ method nextSimilarSymbol =
+ let write_similarsymbol s =
+ let s = Glib.Utf8.from_unichar s in
+ let iter = source_view#source_buffer#get_iter_at_mark `INSERT in
+ assert(Glib.Utf8.validate s);
+ source_view#source_buffer#delete ~start:iter ~stop:(iter#copy#backward_chars 1);
+ source_view#source_buffer#insert ~iter:(source_view#source_buffer#get_iter_at_mark `INSERT) s;
+ (try source_view#source_buffer#delete_mark similarsymbols_tag
+ with GText.No_such_mark _ -> ());
+ ignore(source_view#source_buffer#create_mark ~name:similarsymbols_tag_name
+ (source_view#source_buffer#get_iter_at_mark `INSERT));
+ in
+ let new_similarsymbol =
+ try
+ let iter_ins = source_view#source_buffer#get_iter_at_mark `INSERT in
+ let iter_lig = source_view#source_buffer#get_iter_at_mark similarsymbols_tag in
+ not (iter_ins#equal iter_lig)
+ with GText.No_such_mark _ -> true
+ in
+ if new_similarsymbol then
+ (if not(self#expand_virtual_if_any (source_view#source_buffer#get_iter_at_mark `INSERT) "")then
+ let last_symbol =
+ let i = source_view#source_buffer#get_iter_at_mark `INSERT in
+ Glib.Utf8.first_char (i#get_slice ~stop:(i#copy#backward_chars 1))
+ in
+ (match Virtuals.similar_symbols last_symbol with
+ | [] -> ()
+ | eqclass ->
+ similarsymbols_orig <- eqclass;
+ let is_used =
+ try Hashtbl.find similar_memory similarsymbols_orig
+ with Not_found ->
+ let is_used = List.map (fun x -> x,false) eqclass in
+ Hashtbl.add similar_memory eqclass is_used;
+ is_used
+ in
+ let hd, next, tl =
+ let used, unused =
+ List.partition (fun s -> List.assoc s is_used) eqclass
+ in
+ match used @ unused with a::b::c -> a,b,c | _ -> assert false
+ in
+ let hd, tl =
+ if hd = last_symbol then next, tl @ [hd] else hd, (next::tl)
+ in
+ old_used_memory <- List.assoc hd is_used;
+ let is_used =
+ (hd,true) :: List.filter (fun (x,_) -> x <> hd) is_used
+ in
+ Hashtbl.replace similar_memory similarsymbols_orig is_used;
+ write_similarsymbol hd;
+ similarsymbols <- tl @ [ hd ]))
+ else
+ match similarsymbols with
+ | [] -> ()
+ | hd :: tl ->
+ let is_used = Hashtbl.find similar_memory similarsymbols_orig in
+ let last = HExtlib.list_last tl in
+ let old_used_for_last = old_used_memory in
+ old_used_memory <- List.assoc hd is_used;
+ let is_used =
+ (hd, true) :: (last,old_used_for_last) ::
+ List.filter (fun (x,_) -> x <> last && x <> hd) is_used
+ in
+ Hashtbl.replace similar_memory similarsymbols_orig is_used;
+ similarsymbols <- tl @ [ hd ];
+ write_similarsymbol hd
+
+ method private reset_similarsymbols =
+ similarsymbols <- [];
+ similarsymbols_orig <- [];
+ try source_view#source_buffer#delete_mark similarsymbols_tag
+ with GText.No_such_mark _ -> ()
+
+ method private expand_virtual_if_any iter tok =
+ try
+ let len = MatitaGtkMisc.utf8_string_length tok in
+ let last_word =
+ let prev = iter#copy#backward_chars len in
+ prev#get_slice ~stop:(prev#copy#backward_find_char
+ (fun x -> Glib.Unichar.isspace x || x = Glib.Utf8.first_char "\\"))
+ in
+ let inplaceof, symb = Virtuals.symbol_of_virtual last_word in
+ self#reset_similarsymbols;
+ let s = Glib.Utf8.from_unichar symb in
+ assert(Glib.Utf8.validate s);
+ source_view#source_buffer#delete ~start:iter
+ ~stop:(iter#copy#backward_chars
+ (MatitaGtkMisc.utf8_string_length inplaceof + len));
+ source_view#source_buffer#insert ~iter
+ (if inplaceof.[0] = '\\' then s else (s ^ tok));
+ true
+ with Virtuals.Not_a_virtual -> false
+
+ (** selections / clipboards handling *)
+
+ method markupSelected = MatitaMathView.has_selection ()
+ method private textSelected =
+ (source_view#source_buffer#get_iter_at_mark `INSERT)#compare
+ (source_view#source_buffer#get_iter_at_mark `SEL_BOUND) <> 0
+ method private markupStored = MatitaMathView.has_clipboard ()
+ method private textStored = clipboard#text <> None
+ method canCopy = self#textSelected
+ method canCut = self#textSelected
+ method canDelete = self#textSelected
+ (*CSC: WRONG CODE: we should look in the clipboard instead! *)
+ method canPaste = self#markupStored || self#textStored
+ method canPastePattern = self#markupStored
+
+ method safe_undo =
+ (* phase 1: we save the actual status of the marks and we undo *)
+ let locked_mark = `MARK (self#locked_mark) in
+ let locked_iter = source_view#buffer#get_iter_at_mark locked_mark in
+ let locked_iter_offset = locked_iter#offset in
+ let mark2 =
+ `MARK
+ (source_view#buffer#create_mark ~name:"lock_point"
+ ~left_gravity:true locked_iter) in
+ source_view#source_buffer#undo ();
+ (* phase 2: we save the cursor position and we redo, restoring
+ the previous status of all the marks *)
+ let cursor_iter = source_view#buffer#get_iter_at_mark `INSERT in
+ let mark =
+ `MARK
+ (source_view#buffer#create_mark ~name:"undo_point"
+ ~left_gravity:true cursor_iter)
+ in
+ source_view#source_buffer#redo ();
+ let mark_iter = source_view#buffer#get_iter_at_mark mark in
+ let mark2_iter = source_view#buffer#get_iter_at_mark mark2 in
+ let mark2_iter = mark2_iter#set_offset locked_iter_offset in
+ source_view#buffer#move_mark locked_mark ~where:mark2_iter;
+ source_view#buffer#delete_mark mark;
+ source_view#buffer#delete_mark mark2;
+ (* phase 3: if after the undo the cursor was in the locked area,
+ then we move it there again and we perform a goto *)
+ if mark_iter#offset < locked_iter_offset then
+ begin
+ source_view#buffer#move_mark `INSERT ~where:mark_iter;
+ self#goto `Cursor ();
+ end;
+ (* phase 4: we perform again the undo. This time we are sure that
+ the text to undo is not locked *)
+ source_view#source_buffer#undo ();
+ source_view#misc#grab_focus ()
+
+ method safe_redo =
+ (* phase 1: we save the actual status of the marks, we redo and
+ we undo *)
+ let locked_mark = `MARK (self#locked_mark) in
+ let locked_iter = source_view#buffer#get_iter_at_mark locked_mark in
+ let locked_iter_offset = locked_iter#offset in
+ let mark2 =
+ `MARK
+ (source_view#buffer#create_mark ~name:"lock_point"
+ ~left_gravity:true locked_iter) in
+ source_view#source_buffer#redo ();
+ source_view#source_buffer#undo ();
+ (* phase 2: we save the cursor position and we restore
+ the previous status of all the marks *)
+ let cursor_iter = source_view#buffer#get_iter_at_mark `INSERT in
+ let mark =
+ `MARK
+ (source_view#buffer#create_mark ~name:"undo_point"
+ ~left_gravity:true cursor_iter)
+ in
+ let mark_iter = source_view#buffer#get_iter_at_mark mark in
+ let mark2_iter = source_view#buffer#get_iter_at_mark mark2 in
+ let mark2_iter = mark2_iter#set_offset locked_iter_offset in
+ source_view#buffer#move_mark locked_mark ~where:mark2_iter;
+ source_view#buffer#delete_mark mark;
+ source_view#buffer#delete_mark mark2;
+ (* phase 3: if after the undo the cursor is in the locked area,
+ then we move it there again and we perform a goto *)
+ if mark_iter#offset < locked_iter_offset then
+ begin
+ source_view#buffer#move_mark `INSERT ~where:mark_iter;
+ self#goto `Cursor ();
+ end;
+ (* phase 4: we perform again the redo. This time we are sure that
+ the text to redo is not locked *)
+ source_view#source_buffer#redo ();
+ source_view#misc#grab_focus ()
+
+
+ method copy () =
+ if self#textSelected
+ then begin
+ MatitaMathView.empty_clipboard ();
+ source_view#buffer#copy_clipboard clipboard;
+ end else
+ MatitaMathView.copy_selection ()
+
+ method cut () =
+ source_view#buffer#cut_clipboard clipboard;
+ MatitaMathView.empty_clipboard ()
+
+ method delete () =
+ ignore (source_view#buffer#delete_selection ())
+
+ method paste () =
+ if MatitaMathView.has_clipboard ()
+ then source_view#buffer#insert (MatitaMathView.paste_clipboard `Term)
+ else source_view#buffer#paste_clipboard clipboard;
+ self#clean_dirty_lock
+
+ method pastePattern () =
+ source_view#buffer#insert (MatitaMathView.paste_clipboard `Pattern)
+
method locked_mark = locked_mark
method locked_tag = locked_tag
method error_tag = error_tag
(* history can't be empty, the invariant above grant that it contains at
* least the init grafite_status *)
- method grafite_status = match history with s::_ -> s | _ -> assert false
+ method status = match history with s::_ -> s | _ -> assert false
method private _advance ?statement () =
let s = match statement with Some s -> s | None -> self#getFuture in
let time1 = Unix.gettimeofday () in
let entries, newtext, parsed_len =
try
- eval_statement self#include_paths buffer guistuff
- self#grafite_status userGoal self (`Raw s)
+ eval_statement self#include_paths buffer self#status self (`Raw s)
with End_of_file -> raise Margin
in
let time2 = Unix.gettimeofday () in
end;
end;
self#moveMark (Glib.Utf8.length new_text);
- buffer#insert ~iter:(buffer#get_iter_at_mark (`MARK locked_mark)) newtext;
- (* here we need to set the Goal in case we are going to cursor (or to
- bottom) and we will face a macro *)
- userGoal <- None
-
- method private _retract offset grafite_status new_statements
- new_history
- =
- let cur_grafite_status =
- match history with s::_ -> s | [] -> assert false
- in
- LexiconSync.time_travel ~present:cur_grafite_status ~past:grafite_status;
- GrafiteSync.time_travel ~present:cur_grafite_status ~past:grafite_status ();
+ buffer#insert ~iter:(buffer#get_iter_at_mark (`MARK locked_mark)) newtext
+
+ method private _retract offset status new_statements new_history =
+ NCicLibrary.time_travel status;
statements <- new_statements;
history <- new_history;
self#moveMark (- offset)
method retract () =
try
- let cmp,new_statements,new_history,grafite_status =
+ let cmp,new_statements,new_history,status =
match statements,history with
stat::statements, _::(status::_ as history) ->
assert (Glib.Utf8.validate stat);
| [],[_] -> raise Margin
| _,_ -> assert false
in
- self#_retract cmp grafite_status new_statements
- new_history;
+ self#_retract cmp status new_statements new_history;
self#notify
with
| Margin -> self#notify
observers <- o :: observers
method private notify =
- let grafite_status = self#grafite_status in
- List.iter (fun o -> o grafite_status) observers
+ let status = self#status in
+ List.iter (fun o -> o status) observers
- method loadFromString s =
- buffer#set_text s;
- self#reset_buffer;
- buffer#set_modified true
+ method activate =
+ NCicLibrary.replace self#status;
+ self#notify
method loadFromFile f =
buffer#set_text (HExtlib.input_file f);
buffer#set_modified false
method assignFileName file =
- let file =
- match file with
- | Some f -> Some (Librarian.absolutize f)
- | None -> None
- in
- filename_ <- file;
- include_paths_ <-
- (match file with Some file -> read_include_paths file | None -> []);
- self#reset_buffer;
- Sys.chdir self#curdir;
- HLog.debug ("Moving to " ^ Sys.getcwd ())
+ match file with
+ None ->
+ tab_label#set_text default_fname;
+ filename_ <- None;
+ include_paths_ <- [];
+ self#reset_buffer
+ | Some file ->
+ let f = Librarian.absolutize file in
+ tab_label#set_text (Filename.basename f);
+ filename_ <- Some f;
+ include_paths_ <- MatitaEngine.read_include_paths ~include_paths:[] f;
+ self#reset_buffer
+
+ method set_star b =
+ tab_label#set_text ((if b then "*" else "")^Filename.basename self#filename);
+ tab_label#misc#set_tooltip_text
+ ("URI: " ^ self#buri_of_current_file ^ "\nPATH: " ^ self#filename);
method saveToFile () =
if self#has_name then
output_string oc (buffer#get_text ~start:buffer#start_iter
~stop:buffer#end_iter ());
close_out oc;
- set_star false;
+ self#set_star false;
buffer#set_modified false
else
HLog.error "Can't save, no filename selected"
method private _saveToBackupFile () =
if buffer#modified then
begin
- let f = self#filename in
+ let f = self#filename ^ "~" in
let oc = open_out f in
output_string oc (buffer#get_text ~start:buffer#start_iter
~stop:buffer#end_iter ());
close_out oc;
- HLog.debug ("backup " ^ f ^ " saved")
+ HLog.debug ("backup " ^ f ^ " saved")
end
method private reset_buffer =
statements <- [];
- history <- [ initial_statuses (Some self#grafite_status) self#buri_of_current_file ];
- userGoal <- None;
+ history <- [ initial_statuses (Some self#status) self#buri_of_current_file ];
self#notify;
buffer#remove_tag locked_tag ~start:buffer#start_iter ~stop:buffer#end_iter;
buffer#move_mark (`MARK locked_mark) ~where:buffer#start_iter
let template = HExtlib.input_file BuildTimeConf.script_template in
buffer#insert ~iter:(buffer#get_iter `START) template;
buffer#set_modified false;
- set_star false
+ self#set_star false;
method goto (pos: [`Top | `Bottom | `Cursor]) () =
try
in
let rec back_until_cursor len = (* go backward until locked < cursor *)
function
- statements, ((grafite_status)::_ as history)
+ statements, ((status)::_ as history)
when len <= 0 ->
- self#_retract (icmp - len) grafite_status statements
+ self#_retract (icmp - len) status statements
history
| statement::tl1, _::tl2 ->
back_until_cursor (len - MatitaGtkMisc.utf8_string_length statement) (tl1,tl2)
with Invalid_argument "Array.make" ->
HLog.error "The script is too big!\n"
- method stack = (assert false : Continuationals.Stack.t) (* MATITA 1.0 GrafiteTypes.get_stack
- self#grafite_status *)
- method setGoal n = userGoal <- n
- method goal = userGoal
-
method bos =
match history with
| _::[] -> true
| _ -> false
method eos =
- let rec is_there_only_comments lexicon_status s =
+ let rec is_there_only_comments status s =
if Pcre.pmatch ~rex:only_dust_RE s then raise Margin;
- let lexicon_status,st =
- GrafiteParser.parse_statement (Ulexing.from_utf8_string s)
- ~include_paths:self#include_paths lexicon_status
- in
- match st with
- | GrafiteParser.LSome (GrafiteAst.Comment (loc,_)) ->
+ let strm =
+ GrafiteParser.parsable_statement status
+ (Ulexing.from_utf8_string s)in
+ match GrafiteParser.parse_statement status strm with
+ | GrafiteAst.Comment (loc,_) ->
let _,parsed_text_length = MatitaGtkMisc.utf8_parsed_text s loc in
(* CSC: why +1 in the following lines ???? *)
let parsed_text_length = parsed_text_length + 1 in
let remain_len = String.length s - parsed_text_length in
let next = String.sub s parsed_text_length remain_len in
- is_there_only_comments lexicon_status next
- | GrafiteParser.LNone _
- | GrafiteParser.LSome (GrafiteAst.Executable _) -> false
+ is_there_only_comments status next
+ | GrafiteAst.Executable _ -> false
in
- try is_there_only_comments self#grafite_status self#getFuture
+ try is_there_only_comments self#status self#getFuture
with
- | LexiconEngine.IncludedFileNotCompiled _
+ | NCicLibrary.IncludedFileNotCompiled _
| HExtlib.Localized _
| CicNotationParser.Parse_error _ -> false
| Margin | End_of_file -> true
HLog.debug (sprintf "%d statements:" (List.length statements));
List.iter HLog.debug statements;
HLog.debug ("Current file name: " ^ self#filename);
+
+ method has_parent (p : GObj.widget) = parent#coerce#misc#get_oid = p#misc#get_oid
end
-let _script = ref None
+let _script = ref []
-let script ~source_view ~mathviewer ~urichooser ~ask_confirmation ~set_star ()
+let script ~parent ~tab_label ()
=
- let s = new script
- ~source_view ~mathviewer ~ask_confirmation ~urichooser ~set_star ()
- in
- _script := Some s;
+ let s = new script ~parent ~tab_label () in
+ _script := s::!_script;
s
-let current () = match !_script with None -> assert false | Some s -> s
+let at_page page =
+ let notebook = (MatitaMisc.get_gui ())#main#scriptNotebook in
+ let parent = notebook#get_nth_page page in
+ try
+ List.find (fun s -> s#has_parent parent) !_script
+ with
+ Not_found -> assert false
+;;
+
+let current () =
+ at_page ((MatitaMisc.get_gui ())#main#scriptNotebook#current_page)
+
+let destroy page =
+ let s = at_page page in
+ _script := List.filter ((<>) s) !_script
+;;
+
+let iter_scripts f = List.iter f !_script;;
+let _ =
+ CicMathView.register_matita_script_current (current :> unit -> < advance: ?statement:string -> unit -> unit; status: GrafiteTypes.status >)
+;;