~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to ide/ideutils.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(* $Id: ideutils.ml 11749 2009-01-05 14:01:04Z notin $ *)
 
10
 
 
11
 
 
12
open Preferences
 
13
 
 
14
exception Forbidden
 
15
 
 
16
(* status bar and locations *)
 
17
 
 
18
let status = ref None
 
19
let push_info = ref (function s -> failwith "not ready")
 
20
let pop_info = ref (function s -> failwith "not ready")
 
21
let flash_info = ref  (fun ?delay s -> failwith "not ready")
 
22
 
 
23
let set_location = ref  (function s -> failwith "not ready")
 
24
 
 
25
let pulse = ref (function () -> failwith "not ready")
 
26
 
 
27
 
 
28
let debug = Flags.debug
 
29
 
 
30
let prerr_endline s =
 
31
  if !debug then (prerr_endline s;flush stderr)
 
32
let prerr_string s =
 
33
  if !debug then (prerr_string s;flush stderr)
 
34
 
 
35
let lib_ide_file f =
 
36
  let coqlib = Envars.coqlib () in
 
37
  Filename.concat (Filename.concat coqlib "ide") f
 
38
  
 
39
let get_insert input_buffer = input_buffer#get_iter_at_mark `INSERT
 
40
 
 
41
let is_char_start c = let code = Char.code c in code < 0x80 || code >= 0xc0
 
42
 
 
43
let byte_offset_to_char_offset s byte_offset = 
 
44
  if (byte_offset < String.length s) then begin
 
45
    let count_delta = ref 0 in
 
46
    for i = 0 to byte_offset do
 
47
      let code = Char.code s.[i] in
 
48
      if code >= 0x80 && code < 0xc0 then incr count_delta
 
49
    done;
 
50
    byte_offset - !count_delta
 
51
  end
 
52
  else begin
 
53
    let count_delta = ref 0 in
 
54
    for i = 0 to String.length s - 1 do
 
55
      let code = Char.code s.[i] in
 
56
      if code >= 0x80 && code < 0xc0 then incr count_delta
 
57
    done;
 
58
    byte_offset - !count_delta
 
59
  end
 
60
 
 
61
let print_id id =
 
62
  prerr_endline ("GOT sig id :"^(string_of_int (Obj.magic id)))
 
63
 
 
64
 
 
65
let do_convert s = 
 
66
  Utf8_convert.f
 
67
    (if Glib.Utf8.validate s then begin
 
68
       prerr_endline "Input is UTF-8";s
 
69
     end else
 
70
       let from_loc () = 
 
71
         let _,char_set = Glib.Convert.get_charset () in
 
72
         !flash_info
 
73
           ("Converting from locale ("^char_set^")");
 
74
         Glib.Convert.convert_with_fallback ~to_codeset:"UTF-8" ~from_codeset:char_set s
 
75
       in
 
76
       let from_manual () = 
 
77
         !flash_info 
 
78
           ("Converting from "^ !current.encoding_manual);
 
79
         Glib.Convert.convert s ~to_codeset:"UTF-8" ~from_codeset:!current.encoding_manual
 
80
       in
 
81
       if !current.encoding_use_utf8 || !current.encoding_use_locale then begin
 
82
         try
 
83
           from_loc ()
 
84
         with _ -> from_manual ()
 
85
       end else begin
 
86
         try
 
87
           from_manual () 
 
88
         with _ -> from_loc ()
 
89
       end)
 
90
 
 
91
let try_convert s = 
 
92
  try
 
93
    do_convert s
 
94
  with _ -> 
 
95
    "(* Fatal error: wrong encoding in input.
 
96
Please choose a correct encoding in the preference panel.*)";;
 
97
 
 
98
 
 
99
let try_export file_name s = 
 
100
  try let s = 
 
101
    try if !current.encoding_use_utf8 then begin
 
102
      (prerr_endline "UTF-8 is enforced" ;s)
 
103
    end else if !current.encoding_use_locale then begin
 
104
      let is_unicode,char_set = Glib.Convert.get_charset () in
 
105
      if is_unicode then 
 
106
        (prerr_endline "Locale is UTF-8" ;s)    
 
107
      else
 
108
        (prerr_endline ("Locale is "^char_set);
 
109
         Glib.Convert.convert_with_fallback ~from_codeset:"UTF-8" ~to_codeset:char_set s)
 
110
    end else    
 
111
      (prerr_endline ("Manual charset is "^ !current.encoding_manual);
 
112
       Glib.Convert.convert_with_fallback ~from_codeset:"UTF-8" ~to_codeset:!current.encoding_manual s)
 
113
    with e -> (prerr_endline ("Error ("^(Printexc.to_string e)^") in transcoding: falling back to UTF-8") ;s)
 
114
  in
 
115
  let oc = open_out file_name in
 
116
  output_string oc s;
 
117
  close_out oc;
 
118
  true
 
119
  with e -> prerr_endline (Printexc.to_string e);false
 
120
 
 
121
let my_stat f = try Some (Unix.stat f) with _ -> None
 
122
 
 
123
let revert_timer = ref None
 
124
let disconnect_revert_timer () = match !revert_timer with
 
125
  | None -> ()
 
126
  | Some id -> GMain.Timeout.remove id; revert_timer := None
 
127
 
 
128
let auto_save_timer = ref None
 
129
let disconnect_auto_save_timer () = match !auto_save_timer with
 
130
  | None -> ()
 
131
  | Some id -> GMain.Timeout.remove id; auto_save_timer := None
 
132
 
 
133
let highlight_timer = ref None
 
134
let set_highlight_timer f = 
 
135
  match !highlight_timer with 
 
136
    | None -> 
 
137
        revert_timer := 
 
138
      Some (GMain.Timeout.add ~ms:2000 
 
139
              ~callback:(fun () -> f (); highlight_timer := None; true))
 
140
    | Some id -> 
 
141
        GMain.Timeout.remove id;
 
142
        revert_timer := 
 
143
        Some (GMain.Timeout.add ~ms:2000 
 
144
                ~callback:(fun () -> f (); highlight_timer := None; true))
 
145
 
 
146
 
 
147
(* Get back the standard coq out channels *)
 
148
let init_stdout,read_stdout,clear_stdout =
 
149
  let out_buff = Buffer.create 100 in
 
150
  let out_ft = Format.formatter_of_buffer out_buff in
 
151
  let deep_out_ft = Format.formatter_of_buffer out_buff in
 
152
  let _ = Pp_control.set_gp deep_out_ft Pp_control.deep_gp in
 
153
  (fun () -> 
 
154
    Pp_control.std_ft := out_ft;
 
155
    Pp_control.err_ft := out_ft;
 
156
    Pp_control.deep_ft := deep_out_ft;
 
157
),
 
158
  (fun () -> Format.pp_print_flush out_ft (); 
 
159
     let r = Buffer.contents out_buff in
 
160
     prerr_endline "Output from Coq is: "; prerr_endline r;
 
161
     Buffer.clear out_buff; r),
 
162
  (fun () -> 
 
163
     Format.pp_print_flush out_ft (); Buffer.clear out_buff)
 
164
 
 
165
 
 
166
let last_dir = ref ""
 
167
 
 
168
let filter_all_files () = GFile.filter 
 
169
  ~name:"All" 
 
170
  ~patterns:["*"] () 
 
171
  
 
172
let filter_coq_files () =  GFile.filter 
 
173
  ~name:"Coq source code" 
 
174
  ~patterns:[ "*.v"] ()
 
175
 
 
176
let select_file_for_open ~title ?(dir = last_dir) ?(filename="") () =
 
177
  let file = ref None in 
 
178
  let file_chooser = GWindow.file_chooser_dialog ~action:`OPEN ~modal:true ~title () in
 
179
    file_chooser#add_button_stock `CANCEL `CANCEL ;
 
180
    file_chooser#add_select_button_stock `OPEN `OPEN ;
 
181
    file_chooser#add_filter (filter_coq_files ());
 
182
    file_chooser#add_filter (filter_all_files ());
 
183
    file_chooser#set_default_response `OPEN;
 
184
    ignore (file_chooser#set_current_folder !dir);
 
185
    begin match file_chooser#run () with
 
186
      | `OPEN -> 
 
187
          begin 
 
188
            file := file_chooser#filename;
 
189
            match !file with
 
190
                None -> ()
 
191
              | Some s -> dir := Filename.dirname s;
 
192
          end
 
193
      | `DELETE_EVENT | `CANCEL -> ()
 
194
    end ;
 
195
    file_chooser#destroy ();        
 
196
    !file
 
197
 
 
198
 
 
199
let select_file_for_save ~title ?(dir = last_dir) ?(filename="") () =
 
200
  let file = ref None in 
 
201
  let file_chooser = GWindow.file_chooser_dialog ~action:`SAVE ~modal:true ~title () in
 
202
    file_chooser#add_button_stock `CANCEL `CANCEL ;
 
203
    file_chooser#add_select_button_stock `SAVE `SAVE ;
 
204
    file_chooser#add_filter (filter_coq_files ());
 
205
    file_chooser#add_filter (filter_all_files ());
 
206
  (* this line will be used when a lablgtk >= 2.10.0 is the default on most distributions  
 
207
       file_chooser#set_do_overwrite_confirmation true;
 
208
     *)
 
209
    file_chooser#set_default_response `SAVE;
 
210
    ignore (file_chooser#set_current_folder !dir);
 
211
    ignore (file_chooser#set_current_name filename);
 
212
    
 
213
    begin match file_chooser#run () with
 
214
      | `SAVE -> 
 
215
          begin 
 
216
            file := file_chooser#filename;
 
217
            match !file with
 
218
                None -> ()
 
219
              | Some s -> dir := Filename.dirname s;
 
220
          end
 
221
      | `DELETE_EVENT | `CANCEL -> ()
 
222
    end ;
 
223
    file_chooser#destroy ();        
 
224
    !file
 
225
 
 
226
let find_tag_start (tag :GText.tag) (it:GText.iter) =
 
227
  let it = it#copy in
 
228
  let tag = Some tag in
 
229
  while not (it#begins_tag tag) && it#nocopy#backward_char do
 
230
    ()
 
231
  done;
 
232
  it
 
233
let find_tag_stop (tag :GText.tag) (it:GText.iter) =
 
234
  let it = it#copy in
 
235
  let tag = Some tag in
 
236
  while not (it#ends_tag tag) && it#nocopy#forward_char do
 
237
    ()
 
238
  done;
 
239
  it
 
240
let find_tag_limits (tag :GText.tag) (it:GText.iter) = 
 
241
 (find_tag_start tag it , find_tag_stop tag it)
 
242
 
 
243
(* explanations: Win32 threads won't work if events are produced
 
244
   in a thread different from the thread of the Gtk loop. In this
 
245
   case we must use GtkThread.async to push a callback in the
 
246
   main thread. Beware that the synchronus version may produce
 
247
   deadlocks. *)
 
248
let async = 
 
249
  if Sys.os_type = "Win32" then GtkThread.async else (fun x -> x)
 
250
let sync = 
 
251
  if Sys.os_type = "Win32" then GtkThread.sync else (fun x -> x)
 
252
 
 
253
let mutex text f =
 
254
  let m = Mutex.create() in
 
255
  fun x ->
 
256
    if Mutex.try_lock m
 
257
    then 
 
258
      (try
 
259
        prerr_endline ("Got lock on "^text);
 
260
        f x;
 
261
        Mutex.unlock m;
 
262
        prerr_endline ("Released lock on "^text)
 
263
      with e ->
 
264
        Mutex.unlock m;
 
265
        prerr_endline ("Released lock on "^text^" (on error)");
 
266
        raise e)
 
267
    else
 
268
      prerr_endline
 
269
        ("Discarded call for "^text^": computations ongoing")
 
270
 
 
271
 
 
272
let stock_to_widget ?(size=`DIALOG) s = 
 
273
  let img = GMisc.image () 
 
274
  in img#set_stock s;
 
275
  img#coerce
 
276
 
 
277
let rec print_list print fmt = function
 
278
  | [] -> ()
 
279
  | [x] -> print fmt x
 
280
  | x :: r -> print fmt x; print_list print fmt r
 
281
 
 
282
(* TODO: allow to report output as soon as it comes (user-fiendlier
 
283
   for long commands like make...) *)
 
284
let run_command f c =
 
285
  let result = Buffer.create 127 in
 
286
  let cin,cout,cerr = Unix.open_process_full c (Unix.environment ()) in
 
287
  let buff = String.make 127 ' ' in
 
288
  let buffe = String.make 127 ' ' in
 
289
  let n = ref 0 in
 
290
  let ne = ref 0 in
 
291
  while n:= input cin buff 0 127 ; ne := input cerr buffe 0 127 ; !n+ !ne <> 0
 
292
  do
 
293
    let r = try_convert (String.sub buff 0 !n) in 
 
294
    f r;
 
295
    Buffer.add_string result r;
 
296
    let r = try_convert (String.sub buffe 0 !ne) in 
 
297
    f r;
 
298
    Buffer.add_string result r 
 
299
  done;
 
300
  (Unix.close_process_full (cin,cout,cerr),  Buffer.contents result)
 
301
 
 
302
let browse f url =
 
303
  let com = Flags.subst_command_placeholder !current.cmd_browse url in
 
304
  let s = Sys.command com in
 
305
  if s = 127 then
 
306
    f ("Could not execute\n\""^com^
 
307
       "\"\ncheck your preferences for setting a valid browser command\n")
 
308
 
 
309
let url_for_keyword =
 
310
  let ht = Hashtbl.create 97 in
 
311
  begin try
 
312
    let cin = open_in (lib_ide_file "index_urls.txt") in
 
313
    try while true do
 
314
      let s = input_line cin in
 
315
      try 
 
316
        let i = String.index s ',' in
 
317
        let k = String.sub s 0 i in
 
318
        let u = String.sub s (i + 1) (String.length s - i - 1) in
 
319
        Hashtbl.add ht k u
 
320
      with _ ->
 
321
        ()
 
322
    done with End_of_file ->
 
323
      close_in cin
 
324
  with _ ->
 
325
    ()
 
326
  end;
 
327
  (Hashtbl.find ht : string -> string)
 
328
 
 
329
 
 
330
let browse_keyword f text = 
 
331
  try let u = url_for_keyword text in browse f (!current.doc_url ^ u) 
 
332
  with Not_found -> f ("No documentation found for "^text)
 
333
 
 
334
 
 
335
let underscore = Glib.Utf8.to_unichar "_" (ref 0)
 
336
 
 
337
let arobase = Glib.Utf8.to_unichar "@" (ref 0)
 
338
let prime = Glib.Utf8.to_unichar "'" (ref 0)
 
339
let bn = Glib.Utf8.to_unichar "\n" (ref 0)
 
340
let space = Glib.Utf8.to_unichar " " (ref 0)
 
341
let tab = Glib.Utf8.to_unichar "\t" (ref 0)
 
342
 
 
343
 
 
344
(*
 
345
  checks if two file names refer to the same (existing) file by
 
346
  comparing their device and inode. 
 
347
  It seems that under Windows, inode is always 0, so we cannot
 
348
  accurately check if 
 
349
 
 
350
*)
 
351
(* Optimised for partial application (in case many candidates must be
 
352
   compared to f1). *)
 
353
let same_file f1 =
 
354
  try
 
355
    let s1 = Unix.stat f1 in
 
356
    (fun f2 ->
 
357
      try
 
358
        let s2 = Unix.stat f2 in
 
359
        s1.Unix.st_dev = s2.Unix.st_dev &&
 
360
          if Sys.os_type = "Win32" then f1 = f2 
 
361
          else s1.Unix.st_ino = s2.Unix.st_ino
 
362
      with
 
363
          Unix.Unix_error _ -> false)
 
364
  with
 
365
      Unix.Unix_error _ -> (fun _ -> false)
 
366
 
 
367
let absolute_filename f =
 
368
  if Filename.is_relative f then 
 
369
    Filename.concat (Sys.getcwd ()) f
 
370
  else f
 
371