(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
let lang_manager = GSourceView3.source_language_manager ~default:true let () = lang_manager#set_search_path
((Minilib.rocqide_data_dirs ())@lang_manager#search_path) let style_manager = GSourceView3.source_style_scheme_manager ~default:true let () = style_manager#set_search_path
((Minilib.rocqide_data_dirs ())@style_manager#search_path)
type obj = { set : stringlist -> unit;
get : unit -> stringlist;
}
let preferences : obj Util.String.Map.t ref = ref Util.String.Map.empty let unknown_preferences : stringlist Util.String.Map.t ref = ref Util.String.Map.empty
class virtual ['a] repr =
object(self)
method raw_into v = Option.get (self#into [v])
method raw_from s = List.hd (self#from s)
method virtual into : stringlist -> 'a option
method virtual from : 'a -> string list end
class ['a] preference_signals ~(changed : 'a GUtil.signal) =
object
inherit GUtil.ml_signals [changed#disconnect]
method changed = changed#connect ~after end
class ['a] preference ~(name : string list) ~(init : 'a) ~(repr : 'a repr) =
object (self)
initializer letset v = match repr#into v with None -> () | Some s -> self#set s in let get () = repr#from self#get in let obj = { set; get } in let name = String.concat "." name in if Util.String.Map.mem name !preferences then
invalid_arg ("Preference " ^ name ^ " already exists") else
preferences := Util.String.Map.add name obj !preferences
val default = init val mutable data = init val changed : 'a GUtil.signal = new GUtil.signal () val name : stringlist = name
method connect = new preference_signals ~changed
method get = data
method set (n : 'a) = data <- n; changed#call n
method reset () = self#set default
method default = default
method repr = repr end
let stick (pref : 'a preference) (obj : < connect : #GObj.widget_signals ; .. >)
(cb : 'a -> unit) = let _ = cb pref#get in let p_id = pref#connect#changed ~callback:(fun v -> cb v) in let _ = obj#connect#destroy ~callback:(fun () -> pref#connect#disconnect p_id) in
()
let mod_list_to_str l = List.fold_left (fun s m -> (mod_to_str m)^s) "" l
let str_to_mod_list s = snd (GtkData.AccelGroup.parse s)
type project_behavior = Ignore_args | Append_args | Subst_args
let string_of_project_behavior = function
| Ignore_args -> "ignored"
| Append_args -> "appended to arguments"
| Subst_args -> "taken instead of arguments"
let project_behavior_of_string = function
| "taken instead of arguments" -> Subst_args
| "appended to arguments" -> Append_args
| _ -> Ignore_args
type inputenc = Elocale | Eutf8 | Emanual ofstring
let string_of_inputenc = function
| Elocale -> "LOCALE"
| Eutf8 -> "UTF-8"
| Emanual s -> s
let inputenc_of_string = function
| "UTF-8" -> Eutf8
| "LOCALE" -> Elocale
| s -> Emanual s
type line_ending = [ `DEFAULT | `WINDOWS | `UNIX ]
let line_end_of_string = function
| "unix" -> `UNIX
| "windows" -> `WINDOWS
| _ -> `DEFAULT
let line_end_to_string = function
| `UNIX -> "unix"
| `WINDOWS -> "windows"
| `DEFAULT -> "default"
let use_default_doc_url = "(automatic)"
module Repr = struct
letstring : string repr =
object
inherit [string] repr
method from s = [s]
method into = function [s] -> Some s | _ -> None end
let string_pair : (string * string) repr =
object
inherit [string * string] repr
method from (s1, s2) = [s1; s2]
method into = function [s1; s2] -> Some (s1, s2) | _ -> None end
let string_list : stringlist repr =
object
inherit [stringlist] repr
method from s = s
method into s = Some s end
let string_pair_list (sep : char) : (string * string) list repr =
object
inherit [(string * string) list] repr val sep' = String.make 1 sep
method from = CList.map (fun (s1, s2) -> CString.concat sep' [s1; s2])
method into l = try
Some (CList.map (fun s -> let split = String.split_on_char sep s in
CList.nth split 0, CList.nth split 1) l) with Failure _ -> None end
letbool : bool repr =
object
inherit [bool] repr
method from s = [string_of_bool s]
method into = function
| ["true"] -> Some true
| ["false"] -> Some false
| _ -> None end
let int : int repr =
object
inherit [int] repr
method from s = [string_of_int s]
method into = function
| [i] -> (try Some (int_of_string i) with _ -> None)
| _ -> None end
letoption (r : 'a repr) : 'a option repr =
object
inherit ['a option] repr
method from = function None -> [] | Some v -> "" :: r#from v
method into = function
| [] -> Some None
| "" :: s -> Some (r#into s)
| _ -> None end
let custom (from : 'a -> string) (into : string -> 'a) : 'a repr =
object
inherit ['a] repr
method! raw_from = from
method! raw_into = into
method from x = try [from x] with _ -> []
method into = function
| [s] -> (try Some (into s) with _ -> None)
| _ -> None end
let tag : tag repr = let _to s = if s = ""then None else Some s in let _of = function None -> "" | Some s -> s in
object
inherit [tag] repr
method from tag = [
_of tag.tag_fg_color;
_of tag.tag_bg_color;
string_of_bool tag.tag_bold;
string_of_bool tag.tag_italic;
string_of_bool tag.tag_underline;
string_of_bool tag.tag_strikethrough;
]
method into = function
| [fg; bg; bd; it; ul; st] ->
(try Some {
tag_fg_color = _to fg;
tag_bg_color = _to bg;
tag_bold = bool_of_string bd;
tag_italic = bool_of_string it;
tag_underline = bool_of_string ul;
tag_strikethrough = bool_of_string st;
} with _ -> None)
| _ -> None end
end
let get_config_file dirs name = let find_config dir = Sys.file_exists (Filename.concat dir name) in let config_dir = List.find find_config dirs in
Filename.concat config_dir name
let get_unicode_bindings_local_file () = try Some (get_config_file [Minilib.rocqide_config_home ()] "coqide.bindings") with Not_found -> None
let get_unicode_bindings_default_file () = let name = "default.bindings"in let chk d = Sys.file_exists (Filename.concat d name) in try let dir = List.find chk (Minilib.rocqide_data_dirs ()) in
Some (Filename.concat dir name) with Not_found -> None
(** Hooks *)
let cmd_rocqtop =
new preference ~name:["cmd_coqtop"] ~init:None ~repr:Repr.(optionstring)
let cmd_rocqc =
new preference ~name:["cmd_coqc"] ~init:"coqc" ~repr:Repr.(string)
let cmd_make =
new preference ~name:["cmd_make"] ~init:"make" ~repr:Repr.(string)
let cmd_rocqmakefile =
new preference ~name:["cmd_coqmakefile"] ~init:"coq_makefile -o makefile *.v" ~repr:Repr.(string)
let cmd_rocqdoc =
new preference ~name:["cmd_coqdoc"] ~init:"coqdoc -q -g" ~repr:Repr.(string)
let source_language =
new preference ~name:["source_language"] ~init:"coq" ~repr:Repr.(string)
let source_style =
new preference ~name:["source_style"] ~init:"coq_style" ~repr:Repr.(string)
let global_auto_reload =
new preference ~name:["global_auto_reload"] ~init:false ~repr:Repr.(bool)
let global_auto_reload_delay =
new preference ~name:["global_auto_reload_delay"] ~init:10000 ~repr:Repr.(int)
let auto_save =
new preference ~name:["auto_save"] ~init:true ~repr:Repr.(bool)
let auto_save_delay =
new preference ~name:["auto_save_delay"] ~init:10000 ~repr:Repr.(int)
let auto_save_name =
new preference ~name:["auto_save_name"] ~init:("#","#") ~repr:Repr.(string_pair)
let read_project = let repr = Repr.custom string_of_project_behavior project_behavior_of_string in
new preference ~name:["read_project"] ~init:Append_args ~repr
let project_file_name =
new preference ~name:["project_file_name"] ~init:"_CoqProject" ~repr:Repr.(string)
let project_path =
new preference ~name:["project_path"] ~init:None ~repr:Repr.(optionstring)
let encoding = let repr = Repr.custom string_of_inputenc inputenc_of_string in let init = Eutf8 in
new preference ~name:["encoding"] ~init ~repr
let automatic_tactics = let init = ["trivial"; "tauto"; "auto"; "auto with *"; "intuition" ] in
new preference ~name:["automatic_tactics"] ~init ~repr:Repr.(string_list)
let cmd_print =
new preference ~name:["cmd_print"] ~init:"lpr" ~repr:Repr.(string)
let attach_modifiers (pref : string preference) ?(filter = Fun.consttrue) prefix = let cb mds = let mds = str_to_mod_list mds in let change ~path ~key ~modi ~changed = if CString.is_prefix prefix path && filter path then
ignore (GtkData.AccelMap.change_entry ~key ~modi:mds ~replace:true path) in
GtkData.AccelMap.foreach change in
pref#connect#changed ~callback:cb
let select_arch m m_mac = (* Gtk's <Primary> maps to <Meta> (i.e. "Command") on Darwin (i.e. Mac),
<Control> on other architectures; but sometimes, we want more distinction *) if Coq_config.arch = "Darwin"then m_mac else m
let modifier_for_navigation =
new preference ~name:["modifier_for_navigation"]
~init:(select_arch "<Alt>""<Control><Primary>") ~repr:Repr.(string)
let modifier_for_templates =
new preference ~name:["modifier_for_templates"] ~init:"<Control><Shift>" ~repr:Repr.(string)
let modifier_for_display =
new preference ~name:["modifier_for_display"]
~init:(select_arch "<Alt><Shift>""<Primary><Shift>")~repr:Repr.(string)
let modifier_for_queries =
new preference ~name:["modifier_for_queries"] ~init:"<Control><Shift>" ~repr:Repr.(string)
let printopts_item_names = ref []
let attach_modifiers_callback () = (* Tell to propagate changes done in preference menu to accel map *) (* To be done after the preferences are loaded *) let printopts_filter path = let after_last_slash_pos = (String.rindex path '/') + 1 in let item_name = String.sub path after_last_slash_pos (String.length path - after_last_slash_pos) in List.mem item_name !printopts_item_names in let _ = attach_modifiers modifier_for_display "<Actions>/View/" ~filter:printopts_filter in let _ = attach_modifiers modifier_for_navigation "<Actions>/Navigation/"in let _ = attach_modifiers modifier_for_templates "<Actions>/Templates/"in let _ = attach_modifiers modifier_for_queries "<Actions>/Queries/"in
()
let modifiers_valid =
new preference ~name:["modifiers_valid"] (* Note: <Primary> is providing <Meta> (i.e. "Command") for Darwin, i.e. MacOS X *)
~init:"<Alt><Control><Shift><Primary>" ~repr:Repr.(string)
let browser_cmd_fmt = Option.default Coq_config.browser (Boot.Util.getenv_rocq "REMOTEBROWSER")
let cmd_browse =
new preference ~name:["cmd_browse"] ~init:browser_cmd_fmt ~repr:Repr.(string)
let cmd_editor = let init = if Sys.os_type = "Win32"then"NOTEPAD %s"else"emacs %s"in
new preference ~name:["cmd_editor"] ~init ~repr:Repr.(string)
let text_font = let init = match Config.gtk_platform with
| `QUARTZ -> "Arial Unicode MS 11"
| _ -> "Monospace 10" in
new preference ~name:["text_font"] ~init ~repr:Repr.(string)
let show_toolbar =
new preference ~name:["show_toolbar"] ~init:true ~repr:Repr.(bool)
let window_width =
new preference ~name:["window_width"] ~init:800 ~repr:Repr.(int)
let window_height =
new preference ~name:["window_height"] ~init:600 ~repr:Repr.(int)
let unicode_binding =
new preference ~name:["unicode_binding"] ~init:true ~repr:Repr.(bool)
let auto_complete =
new preference ~name:["auto_complete"] ~init:false ~repr:Repr.(bool)
let auto_complete_delay =
new preference ~name:["auto_complete_delay"] ~init:250 ~repr:Repr.(int)
let stop_before =
new preference ~name:["stop_before"] ~init:true ~repr:Repr.(bool)
let reset_on_tab_switch =
new preference ~name:["reset_on_tab_switch"] ~init:false ~repr:Repr.(bool)
let line_ending = let repr = Repr.custom line_end_to_string line_end_of_string in
new preference ~name:["line_ending"] ~init:`DEFAULT ~repr
let document_tabs_pos =
new preference ~name:["document_tabs_pos"] ~init:"top" ~repr:Repr.(string)
let message_tab_capped =
new preference ~name:["message_tab_capped"] ~init:true ~repr:Repr.(bool)
let message_tab_length =
new preference ~name:["message_tab_length"] ~init:1000 ~repr:Repr.(int)
(* let background_color = *) (* new preference ~name:["background_color"] ~init:"cornsilk" ~repr:Repr.(string) *)
let attach_tag (pref : string preference) (tag : GText.tag) f =
tag#set_property (f pref#get);
pref#connect#changed ~callback:(fun c -> tag#set_property (f c))
let attach_bg (pref : string preference) (tag : GText.tag) =
attach_tag pref tag (fun c -> `BACKGROUND c)
let attach_fg (pref : string preference) (tag : GText.tag) =
attach_tag pref tag (fun c -> `FOREGROUND c)
let processed_color =
new preference ~name:["processed_color"] ~init:"light green" ~repr:Repr.(string)
let _ = attach_bg processed_color Tags.Script.processed let _ = attach_bg processed_color Tags.Proof.highlight
let processing_color =
new preference ~name:["processing_color"] ~init:"light blue" ~repr:Repr.(string)
let incompletely_processed_color =
new preference ~name:["incompletely_processed_color"] ~init:"light sky blue" ~repr:Repr.(string)
let unjustified_conclusion_color =
new preference ~name:["unjustified_conclusion_color"] ~init:"gold" ~repr:Repr.(string)
let _ = attach_bg processing_color Tags.Script.to_process let _ = attach_bg incompletely_processed_color Tags.Script.incomplete let _ = attach_bg unjustified_conclusion_color Tags.Script.unjustified
let breakpoint_color =
new preference ~name:["breakpoint_color"] ~init:"#db5860" ~repr:Repr.(string) let white = (* worth showing on preferences menu?? *)
new preference ~name:["white"] ~init:"white" ~repr:Repr.(string)
let _ = attach_bg breakpoint_color Tags.Script.breakpoint let _ = attach_fg white Tags.Script.breakpoint
let db_stopping_point_color =
new preference ~name:["db_stopping_point_color"] ~init:"#2154a6" ~repr:Repr.(string)
let _ = attach_bg db_stopping_point_color Tags.Script.debugging let _ = attach_fg white Tags.Script.debugging
let error_color =
new preference ~name:["error_color"] ~init:"#FFCCCC" ~repr:Repr.(string)
let _ = attach_bg error_color Tags.Script.error_bg
let error_fg_color =
new preference ~name:["error_fg_color"] ~init:"red" ~repr:Repr.(string)
let _ = attach_fg error_fg_color Tags.Script.error
let dynamic_word_wrap =
new preference ~name:["dynamic_word_wrap"] ~init:false ~repr:Repr.(bool)
let show_line_number =
new preference ~name:["show_line_number"] ~init:false ~repr:Repr.(bool)
let auto_indent =
new preference ~name:["auto_indent"] ~init:true ~repr:Repr.(bool)
let show_spaces =
new preference ~name:["show_spaces"] ~init:true ~repr:Repr.(bool)
let show_right_margin =
new preference ~name:["show_right_margin"] ~init:false ~repr:Repr.(bool)
let show_progress_bar =
new preference ~name:["show_progress_bar"] ~init:true ~repr:Repr.(bool)
let spaces_instead_of_tabs =
new preference ~name:["spaces_instead_of_tabs"] ~init:true ~repr:Repr.(bool)
let tab_length =
new preference ~name:["tab_length"] ~init:2 ~repr:Repr.(int)
let highlight_current_line =
new preference ~name:["highlight_current_line"] ~init:true ~repr:Repr.(bool)
let microPG = (* Legacy name in preference is "nanoPG" *)
new preference ~name:["nanoPG"] ~init:false ~repr:Repr.(bool)
let user_queries =
new preference ~name:["user_queries"] ~init:[] ~repr:Repr.(string_pair_list '$')
let diffs =
new preference ~name:["diffs"] ~init:"off" ~repr:Repr.(string)
(** Loading/saving preferences *)
let pref_file = Filename.concat (Minilib.rocqide_config_home ()) "coqiderc" let accel_file = Filename.concat (Minilib.rocqide_config_home ()) "coqide.keys"
let accel_regex = Str.regexp {|\(; \|\)(gtk_accel_path "\([^""]*\)"|}
exception UnknownFormat
(* Attention: this only works with absolute normalized paths -
which can be assumed here since the path comes from Glib.get_user_config_dir *) let rec mkdir_p path perms = ifnot (Sys.file_exists path) then let parent = Filename.dirname path in ifnot (Sys.file_exists parent) && parent<>path then mkdir_p parent perms else Unix.mkdir path perms else ()
let save_accel_pref () =
mkdir_p (Minilib.rocqide_config_home ()) 0o700; let tmp_file, fd = Filename.open_temp_file ?perms:(Some 0o644)
?temp_dir:(Some (Filename.dirname accel_file)) "coqide.keys_"""in
close_out fd;
GtkData.AccelMap.save tmp_file; (* AccelMap.save writes entries in random order, so sort them: *) let fd = open_in tmp_file in letmap = ref CString.Map.empty in let top_lines = ref [] in begin try whiletruedo let line = input_line fd in if Str.string_match accel_regex line 0 then let key = Str.matched_group 2 line in map := CString.Map.add key line !map elsebegin ifnot (CString.Map.is_empty !map) thenbegin
Minilib.log ("Unknown format for coqide.keys; sorting skipped"); raise UnknownFormat end;
top_lines := line :: !top_lines end
done with
| UnknownFormat -> close_in fd
| End_of_file ->
close_in fd; let fd = open_out tmp_file in List.iter (fun l -> Printf.fprintf fd "%s\n" l) (List.rev !top_lines);
CString.Map.iter (fun k l -> Printf.fprintf fd "%s\n" l) !map;
close_out fd end;
Sys.rename tmp_file accel_file
let save_rc_pref () =
mkdir_p (Minilib.rocqide_config_home ()) 0o700; let add = Util.String.Map.add in let fold key obj accu = add key (obj.get ()) accu in let prefs = Util.String.Map.fold fold !preferences Util.String.Map.empty in let prefs = Util.String.Map.fold Util.String.Map.add !unknown_preferences prefs in
Config_lexer.print_file pref_file prefs
let save_pref () =
save_accel_pref ();
save_rc_pref ()
let try_load_pref_file loader warn file = try
loader file with
e -> warn ~delay:5000 ("Could not load " ^ file ^ " ("^Printexc.to_string e^")")
let load_pref_file loader warn name = try let user_file = get_config_file [Minilib.rocqide_config_home ()] name in
warn ~delay:2000 ("Loading " ^ user_file);
try_load_pref_file loader warn user_file with Not_found -> try let system_wide_file = get_config_file (Minilib.rocqide_system_config_dirs ()) name in
warn ~delay:5000 ("No user " ^ name ^ ", using system wide configuration");
try_load_pref_file loader warn system_wide_file with Not_found -> (* Compatibility with oldest versions of RocqIDE (<= 8.4) *) try let old_user_file = get_config_file [Option.default "" (Glib.get_home_dir ())] ("."^name) in
warn ~delay:5000 ("No " ^ name ^ ", trying to recover from an older version of RocqIDE");
try_load_pref_file loader warn old_user_file with Not_found -> (* Built-in configuration *)
warn ~delay:5000 ("No " ^ name ^ ", using default internal configuration")
let load_accel_pref ~warn =
load_pref_file GtkData.AccelMap.load warn "coqide.keys"
let load_rc_pref ~warn = let loader file = let m = Config_lexer.load_file file in let iter name v = if Util.String.Map.mem name !preferences then try (Util.String.Map.find name !preferences).set v with _ -> () else unknown_preferences := Util.String.Map.add name v !unknown_preferences in
Util.String.Map.iter iter m in
load_pref_file loader warn "coqiderc";
attach_modifiers_callback ()
let load_pref ~warn =
load_rc_pref ~warn;
load_accel_pref ~warn
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.