Commit 46222e8b authored by bguillaum's avatar bguillaum

version 2.19: adapt to lib version 2.22 and better handling of input files

git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/semagramme/dep2pict/trunk@8766 7838e531-6607-4d57-9587-6c381814729c
parent 7e498f16
......@@ -20,15 +20,6 @@ conf : config/configure.ac
cd config && autoconf -o ../configure configure.ac
rm -rf config.status config.log autom4te.cache config/autom4te.cache
LAUNCHER=/usr/share/applications/dep2pict.desktop
REP=/usr/share/desktop-directories/calligramme.directory
DESKTOP=[Desktop Entry]\nName=Dep2pict\nName[fr]=Dep2pict\nComment=Draw dependencies\nComment[fr]=Graphes de dépendences\nExec=dep2pict\nIcon=$(DATA_DIR)dep2pict.png\nTerminal=false\nType=Application\nCategories=Calligramme;
FOLDER=[Desktop Entry]\nEncoding=UTF-8\nName=Calligramme\nComment=Calligramme App\nIcon=$(DATA_DIR)/calligramme.png\nType=Directory
install : opt
cp bin/dep2pict.opt $(INSTALL_DIR)/dep2pict
ifeq (@BUILD_GUI@,yes)
......@@ -38,22 +29,6 @@ ifeq (@BUILD_GUI@,yes)
endif
install_linux:
echo "installation in linux desktop -- need to be root"
ifeq (@BUILD_GUI@,yes)
ifeq (@SYSTEM@,Linux)
touch $(REP)
echo "$(FOLDER)" > $(REP)
if test -e $(LAUNCHER); then : rm -rf $(LAUNCHER) ; fi
touch $(LAUNCHER)
echo "$(DESKTOP)" > $(LAUNCHER)
xdg-desktop-menu install --novendor $(REP) $(LAUNCHER)
xdg-desktop-menu forceupdate --mode user
xdg-desktop-menu forceupdate --mode system
endif
endif
clean :
@make cleanup
@make -C config cleanup
......@@ -73,21 +48,3 @@ ifeq (@BUILD_GUI@,yes)
cp src/dep2pict.glade $(DESTDIR)$(DATA_DIR)
cp img/* $(DESTDIR)$(DATA_DIR)
endif
targz: clean conf
rm -rf dep2pict-$(VERSION)
mkdir -p dep2pict-$(VERSION)
cp -r src/ dep2pict-$(VERSION)/
cp -r config/ dep2pict-$(VERSION)/
cp -r img/ dep2pict-$(VERSION)/
cp configure dep2pict-$(VERSION)/
cp Makefile.in dep2pict-$(VERSION)/
tar -czvf packaging/dep2pict-$(VERSION).tar.gz dep2pict-$(VERSION)
rm -rf dep2pict-$(VERSION)
portfile: targz
cd packaging && sh create_portfile.sh $(VERSION)
pack_deb: targz
sh packaging/make_deb.sh $(VERSION) $(INSTALL_DIR) $(DATA_DIR) $(DOC_DIR)
VERSION = 2.18
VERSION = 2.19
INSTALL_DIR = @prefix@@bindir@
DATA_DIR = @prefix@@datarootdir@/dep2pict/
......
open Printf
open Log
open Dep2pict
type format = Dep | Conll | Xml | Png | Svg | Pdf
exception Found of format
let get_format file =
try
List.iter
(fun (ext, fmt) ->
if Filename.check_suffix file ext
then raise (Found fmt)
) [ ("dep", Dep); ("conll",Conll); ("xml",Xml); ("png",Png); ("svg",Svg); ("pdf",Pdf) ];
Log.fcritical "Unkwnow file extension for file \"%s\"" file
with Found fmt -> fmt
let string_of_format = function
| Dep -> "dep"
| Conll -> "conll"
| Xml -> "xml"
| Png -> "png"
| Svg -> "svg"
| Pdf -> "pdf"
module File = struct
let read file =
let in_ch = open_in file in
(* if the input file contains an UTF-8 byte order mark (EF BB BF), skip 3 bytes, else get back to 0 *)
(match input_byte in_ch with 0xEF -> seek_in in_ch 3 | _ -> seek_in in_ch 0);
let buff = Buffer.create 32 in
try
while true do
bprintf buff "%s\n" (input_line in_ch)
done; assert false
with End_of_file ->
close_in in_ch;
Buffer.contents buff
(* -------------------------------------------------------------------------------- *)
let write file string =
let out_ch = open_out file in
fprintf out_ch "%s\n" string;
close_out out_ch
let (input_file : string option ref) = ref None
let (output_file : string option ref) = ref None
end (* module File *)
let batch = ref false
let critical msg = ksprintf
(fun m -> match !batch with
| true -> printf "%s\n" m; exit 1
| false -> Log.fcritical "%s" m
) msg
let logo = String.concat "\n" [
"[GRAPH] { word_spacing=0; opacity=50; scale=300 }";
"[WORDS] {";
" A { word=\"Dep\"; forecolor=purple; }";
" B { word=\"2\"; forecolor=orange; }";
" C { word=\"pict\"; forecolor=pink; }";
"}";
"[EDGES] {";
" A -> B { color=red; }";
" C -> B { color=blue;}";
" B -> A { bottom; color=yellow; }";
" B -> C { bottom; color=green; }";
"}";
]
exception Found of int
let get_suffix file_name =
let len = String.length file_name in
try
for i = len-1 downto 0 do
if file_name.[i] = '.'
then raise (Found i)
done;
None
with
| Found i -> Some (String.sub file_name i (len-i))
module Format = struct
type format = Dep | Conll | Png | Svg | Pdf | No_suff | Unk of string
let current_infos = ref ["pos"]
let get file =
match get_suffix file with
| None -> Log.fwarning "Cannot guess format (no suffix) for file \"%s\"" file; No_suff
| Some suff ->
try List.assoc suff [ (".dep",Dep); (".conll",Conll); (".png",Png); (".svg",Svg); (".pdf",Pdf)]
with Not_found -> Log.fwarning "Unkwnow file extension \"%s\" for file \"%s\"" suff file; Unk suff
(* elements of [current array] are pairs (sentid, code) *)
let (current_array : (string * string) array ref) = ref [||]
let (current_position : int option ref) = ref None (* position of the current_focus in the current_array *)
let to_string = function
| Dep -> "dep"
| Conll -> "conll"
| Png -> "png"
| Svg -> "svg"
| Pdf -> "pdf"
| No_suff -> "no_suff"
| Unk suff -> sprintf "unkown suffix '%s'" suff
end
let current_source = ref ""
type input_data =
| No_data
| Dep of Dep2pict.t * string
| Conll of (string * string) array
let (input_file : string option ref) = ref None
let (output_file : string option ref) = ref None
let current_data = ref No_data
let (current_position : int ref) = ref 0 (* position of the current_focus in the current_array *)
let current_source = ref logo (* by default use the logo code *)
let modified = ref false
let debug = ref false
let get_pos () = match !current_position with
| None -> 0
| Some v -> v
let get_id () = fst (!current_array.(get_pos ()))
let get_id () =
match !current_data with
| Conll arr -> fst (arr.(!current_position))
| _ -> Log.critical "[get_id] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let array_assoc key array =
......@@ -57,65 +120,67 @@ let array_assoc key array =
(* -------------------------------------------------------------------------------- *)
let search_sentid sentid =
let (new_pos,_) = array_assoc sentid !current_array in
current_position := Some new_pos
match !current_data with
| Conll arr ->
let (new_pos,_) = array_assoc sentid arr in current_position := new_pos
| _ -> Log.critical "[search_sentid] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let update_source () =
match !current_position with
| None -> ()
| Some p -> current_source := (snd !current_array.(p))
match (!current_data, !current_position) with
| (Conll arr, p) -> current_source := (snd arr.(p))
| (Dep (graph,text), _) -> current_source := text
| (No_data, _) -> current_source := logo
(* -------------------------------------------------------------------------------- *)
let first () =
current_position := Some 0;
update_source ()
match !current_data with
| Conll arr -> current_position := 0; update_source ()
| _ -> Log.critical "[first] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let last () =
current_position := Some ((Array.length !current_array) - 1);
update_source ()
match !current_data with
| Conll arr -> current_position :=((Array.length arr) - 1); update_source ()
| _ -> Log.critical "[last] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let next () =
match !current_position with
| Some p when p < (Array.length !current_array)-1 ->
current_position := Some (p+1);
update_source ()
| x -> ()
match (!current_data, !current_position) with
| (Conll arr, p) when p < (Array.length arr) - 1 ->
current_position := p+1; update_source ()
| _ -> Log.critical "[next] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let has_next () =
match !current_position with
| Some p when p < (Array.length !current_array)-1 -> true
let has_next () =
match (!current_data, !current_position) with
| (Conll arr, p) -> p < (Array.length arr)-1
| _ -> false
(* -------------------------------------------------------------------------------- *)
let prev () =
match !current_position with
| Some p when p > 0 ->
current_position := Some (p-1);
update_source ()
| x -> ()
match (!current_data, !current_position) with
| (Conll _, p) when p > 0 ->
current_position := p-1; update_source ()
| _ -> Log.critical "[prev] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let has_prev () =
match !current_position with
| Some p when p > 0 -> true
match (!current_data, !current_position) with
| (Conll _, p) -> p > 0
| _ -> false
(* -------------------------------------------------------------------------------- *)
let view_label () =
match (!current_array, !current_position) with
| ([||], None) -> "No dep"
| ([|(id,_)|], Some 0) when id="00001" -> "no_id"
| ([|(id,_)|], Some 0) -> sprintf "[%s]" id
| (a, Some p) ->
match (!current_data, !current_position) with
| (Conll [|(id,_)|], 0) when id="00001" -> "no_id"
| (Conll [|(id,_)|], 0) -> sprintf "[%s]" id
| (Conll a, p) ->
let (id, _) = a.(p) in
if id = sprintf "%05d" p
then sprintf "(%d/%d) [no_id]" (p+1) (Array.length a)
else sprintf "(%d/%d) [%s]" (p+1) (Array.length a) id
| _ -> Log.critical "Inconsistent state"
| _ -> "no_id"
(* -------------------------------------------------------------------------------- *)
let file_label () =
......@@ -123,24 +188,20 @@ let file_label () =
| None -> "No file loaded"
| Some in_file -> in_file
(* -------------------------------------------------------------------------------- *)
let write file string =
let out_ch = open_out file in
fprintf out_ch "%s\n" string;
close_out out_ch
(* -------------------------------------------------------------------------------- *)
let save file =
match !current_position with
| None -> Log.critical "[Global.save] No position defined!"
| Some index -> !current_array.(index) <- (fst (!current_array.(index)), !current_source);
let out_ch = open_out file in
Array.iter (fun (_,src) -> fprintf out_ch "%s\n" src) !current_array;
close_out out_ch;
modified := false
match (!current_data, !current_position) with
| (Conll arr, index) ->
arr.(index) <- (fst (arr.(index)), !current_source);
let out_ch = open_out file in
Array.iter (fun (_,src) -> fprintf out_ch "%s\n" src) arr;
close_out out_ch;
modified := false
| _ -> Log.critical "[Global.save] can be use only with CONLL data"
(* -------------------------------------------------------------------------------- *)
let load file =
let conll_array file =
let in_ch = open_in file in
let buff = Buffer.create 32 in
let cpt = ref 0 in
......@@ -172,10 +233,27 @@ let load file =
| _ -> sprintf "%05d.conll" !cpt in
sentid := Some new_sentid;
Printf.bprintf buff "%s\n" line
done
done; assert false
with End_of_file ->
(match !sentid with
| Some si -> current_list := (si, Buffer.contents buff) :: !current_list
| None -> ());
current_array := Array.of_list (List.rev !current_list)
Array.of_list (List.rev !current_list)
(* -------------------------------------------------------------------------------- *)
let load file =
try
match Format.get file with
| Format.Dep -> let dep = File.read file in current_data := Dep (Dep2pict.from_dep dep, dep)
| Format.Conll -> current_data := Conll (conll_array file)
| _ ->
Log.fwarning "No valid input format detected for file \"%s\", try to guess...\n%!" file;
let text = File.read file in
if String.length text > 0 && text.[0] = '1'
then current_data := Conll (conll_array file)
else current_data := Dep (Dep2pict.from_dep text, text)
with
| Dep2pict.Parse_error msgs -> List.iter (fun (l,m) -> printf "Line %d: %s\n" l m) msgs; critical "Parse error !!"
| Dep2pict.Id_already_in_use_ id -> critical "Id already in use : %s" id
| Dep2pict.Unknown_index id -> critical "Can't find index: %s" id
| Dep2pict.Loop_in_dep msg -> critical "Loop in dependency : %s" msg
......@@ -45,6 +45,7 @@ let check_modified continuation () =
(* -------------------------------------------------------------------------------- *)
let main () =
let _ = GMain.Main.init () in
(* Build the main windows *)
......@@ -58,14 +59,17 @@ let main () =
(* -------------------------------------------------------------------------------- *)
let refresh_view () =
try
let svg =
let graph =
if !current_source <> "" && !current_source.[0] = '1'
then Dep2pict.fromConllStringToSvgString ~infos:(!current_infos) !current_source
else Dep2pict.fromDepStringToSvgString !current_source in
then Dep2pict.from_conll !current_source
else Dep2pict.from_dep !current_source in
let svg = try Dep2pict.to_svg graph with _ -> failwith "FFF" in
webkit#load_html_string svg "";
webkit#set_zoom_level (!current_zoom /. 100.);
ui#error_view#buffer#set_text "";
let _ = ui#prev_button#misc#set_sensitive (has_prev ()) in
let _ = ui#next_button#misc#set_sensitive (has_next ()) in
let _ = ui#first_button#misc#set_sensitive (has_prev ()) in
......@@ -161,30 +165,31 @@ let main () =
let format =
match (ui#svg_radio#active, ui#png_radio#active, ui#pdf_radio#active) with
| (true,false,false) -> Svg
| (false,true,false) -> Png
| (false,false,true) -> Pdf
| (true,false,false) -> Format.Svg
| (false,true,false) -> Format.Png
| (false,false,true) -> Format.Pdf
| _ -> Log.critical "Inconsistent format radiobuttons" in
let title = sprintf "Convert file to %s" (string_of_format format) in
let title = sprintf "Convert file to %s" (Format.to_string format) in
let file_window = GWindow.file_selection ~title ~show:true() in
let _ = file_window#ok_button#connect#clicked
~callback:(fun () ->
begin
let dep_code =
let graph =
if String.length !current_source > 0 && !current_source.[0] = '1'
then Dep2pict.fromConllStringToDepString !current_source
else !current_source in
then Dep2pict.from_conll !current_source
else Dep2pict.from_dep !current_source in
match format with
| Svg -> write file_window#filename (Dep2pict.fromDepStringToSvgString dep_code)
| Png -> ignore (Dep2pict.fromDepStringToPng dep_code file_window#filename)
| Pdf -> ignore (Dep2pict.fromDepStringToPdf dep_code file_window#filename)
| _ -> Log.fcritical "Unsupported output format: %s" (string_of_format format)
| Format.Svg -> Dep2pict.save_svg ~filename:file_window#filename graph
| Format.Png -> Dep2pict.save_png ~filename:file_window#filename graph
| Format.Pdf -> Dep2pict.save_pdf ~filename:file_window#filename graph
| _ -> Log.fcritical "Unsupported output format: %s" (Format.to_string format)
end;
file_window#destroy ()
) in
let _ = file_window#cancel_button#connect#clicked ~callback:(file_window#destroy) in
let _ = file_window#complete ~filter:("*."^(string_of_format format)) in
let _ = file_window#complete ~filter:("*."^(Format.to_string format)) in
() in
......
......@@ -40,46 +40,28 @@ let usage = String.concat "\n" [
" * accepted output formats are: png, svg, pdf, dep";
"";
"Options:";
" -i | --infos <string> select infos to display for conll input:";
" <string> is a '|' separated list of atoms from: \"lemma\", \"pos\", \"lpos\", \"all\",";
" (default=\"pos\")";
" -s | --sentid <string> identifier of the sentence to display (incompatible with -p | --position)";
" -p | --position <int> number of the dep structure to display when input file contains sequence (incompatible with -s | --sentid)";
" -d | --debug add on_mouse_over tips in svg output and set verbose mode for font utilities";
" -b | --batch Unformated error message that can be used in a pipeline or a web app";
" --special_chars <file> give a set of chars (one char by line) that are considered as 1.5 width of 'X' (for korean chars for instance)";
"================================================================================";
]
let logo = String.concat "\n" [
"[GRAPH] { word_spacing=0; opacity=50; scale=300 }";
"[WORDS] {";
" A { word=\"Dep\"; forecolor=purple; }";
" B { word=\"2\"; forecolor=orange; }";
" C { word=\"pict\"; forecolor=pink; }";
"}";
"[EDGES] {";
" A -> B { color=red; }";
" C -> B { color=blue;}";
" B -> A { bottom; color=yellow; }";
" B -> C { bottom; color=green; }";
"}";
]
let requested_sentid = ref None
(* the name of the file containing special chars (like korean chars) *)
let special_chars = ref None
let rec parse_arg = function
| [] -> ()
| "-v"::_ | "--version"::_ -> printf "%s\n%!" version; exit 0
| "-h"::_ | "--help"::_ -> printf "%s\n%!" usage; exit 0
| "-i"::i::tail
| "--infos"::i::tail -> current_infos := Str.split (Str.regexp " *| *") i; parse_arg tail
| "-p"::i::tail
| "--position"::i::tail -> current_position := Some (int_of_string i); parse_arg tail
| "--position"::i::tail -> current_position := ((int_of_string i)-1); parse_arg tail
| "-s"::s::tail
| "--sentid"::s::tail -> requested_sentid := Some s; parse_arg tail
......@@ -88,21 +70,22 @@ let rec parse_arg = function
| "-d"::tail | "--debug"::tail -> debug := true; parse_arg tail
| "-b"::tail | "--batch"::tail -> batch := true; parse_arg tail
| s::_ when s.[0] = '-' -> Log.fcritical "Unknwon option \"%s\"" s
| anon :: tail ->
begin
match !input_file with
| None -> input_file := Some anon
| Some _ ->
match !output_file with
| None -> output_file := Some anon
| Some _ -> Log.fcritical "At most two anonymous arguments are allowed, don't know what to do with \"%s\"" anon
| None -> input_file := Some anon
| Some _ ->
match !output_file with
| None -> output_file := Some anon
| Some _ -> Log.fcritical "At most two anonymous arguments are allowed, don't know what to do with \"%s\"" anon
end;
parse_arg tail
(* -------------------------------------------------------------------------------- *)
let _ =
let () = parse_arg (List.tl (Array.to_list Sys.argv)) in
......@@ -114,62 +97,56 @@ let _ =
| Some filename -> Dep2pict.load_special_chars filename
end;
(* check for input_file *)
match !input_file with
| None -> current_source := logo; gui ()
(* check for input_file and load file if any *)
begin
match !input_file with
| None -> ()
| Some in_file when not (Sys.file_exists in_file) -> Log.fcritical "The input file %s doesn't exist." in_file
| Some in_file -> load in_file;
(* check for focus *)
begin
match (!current_position, !requested_sentid) with
| (None, None) when Array.length !current_array = 0 -> ()
| (None, None) -> current_position := Some 0
| (Some p, None) when p < 0 || p >= (Array.length !current_array) ->
Log.fwarning "position %d is out of bounds, set position to 0" p;
current_position := Some 0
| (Some p, None) -> current_position := Some p
| (None, Some sentid) -> (
try search_sentid sentid
with Not_found -> Log.fwarning "sentid %s cannot be found, set position to 0" sentid;
)
| (Some _, Some _) -> Log.fcritical "Options --position and --sentid are incompatible"
end;
update_source ();
match !output_file with
| None -> gui ()
| Some out_file ->
begin
try
match (get_format in_file, get_format out_file) with
| (Xml, Png) -> ignore (Dep2pict.fromXmlFileToPng in_file out_file (get_pos ()))
| (Dep, Png) -> ignore (Dep2pict.fromDepFileToPng in_file out_file)
| (Conll, Png) -> ignore (Dep2pict.fromConllStringToPng ~infos:!current_infos !current_source out_file)
| (Xml, Svg) -> ignore (Dep2pict.fromXmlFileToSvgFile ~debug:(!debug) in_file out_file (get_pos ()))
| (Dep, Svg) -> ignore (Dep2pict.fromDepFileToSvgFile ~debug:(!debug) in_file out_file)
| (Conll, Svg) -> ignore (Dep2pict.fromConllStringToSvgFile ~infos:!current_infos !current_source out_file)
| (Xml, Pdf) -> ignore (Dep2pict.fromXmlFileToPdf in_file out_file (get_pos ()))
| (Dep, Pdf) -> ignore (Dep2pict.fromDepFileToPdf in_file out_file)
| (Conll, Pdf) -> ignore (Dep2pict.fromConllStringToPdf ~infos:!current_infos !current_source out_file)
| (Conll, Dep) -> Dep2pict.fromConllStringToDep ~infos:!current_infos !current_source out_file
| (Dep, Dep)
| (Xml, Dep) -> Log.fcritical "Conversion from Xml or Dep into Dep is not implemented. Please contact developers if your really need it!"
| (_, Xml) -> Log.fcritical "Conversion to Xml is not implemented. Please contact developers if your really need it!"
| (Pdf, _) -> Log.fcritical "pdf in not a valid input format"
| (Svg, _) -> Log.fcritical "svg in not a valid input format"
| (Png, _) -> Log.fcritical "png in not a valid input format"
| (_, Conll) -> Log.fcritical "conll in not a valid output format"
with
| Dep2pict.Parse_error msgs -> List.iter (fun (l,m) -> printf "Line %d: %s\n" l m) msgs; Log.fcritical "Parse error !!"
| Dep2pict.Id_already_in_use_ id -> Log.fcritical "Id already in use : %s" id
| Dep2pict.Unknown_index id -> Log.fcritical "Can't find index: %s" id
| Dep2pict.Loop_in_dep msg -> Log.fcritical "Loop in dependency : %s" msg
end;
Log.finfo "File %s generated." out_file
| Some in_file -> load in_file
end;
(* check for focus *)
begin
match (!current_data, !current_position, !requested_sentid) with
| (Conll _, _, Some sentid) -> (
try search_sentid sentid
with Not_found ->
Log.fwarning "sentid %s cannot be found, set position to 0" sentid;
current_position := 0; update_source ()
)
| (Conll arr, p, None) when p < 0 || p >= (Array.length arr) ->
Log.fwarning "position %d is out of bounds, set position to 0" p;
current_position := 0; update_source ()
| (Conll _, p, None) -> current_position := p; update_source ()
| (_, _, Some _) -> Log.fcritical "Options --sentid can be used only with CONLL input"
| (_, _, None) -> ()
end;
match !output_file with
| None -> gui ()
| Some out_file ->
try
let graph = match !current_data with
| No_data -> critical "No input data loaded"
| Dep (g,_) -> g
| Conll _ -> Dep2pict.from_conll ~conll:(!current_source) in
begin
match Format.get out_file with
| Format.Svg -> Dep2pict.save_svg ~filename:out_file graph
| Format.Pdf -> Dep2pict.save_pdf ~filename:out_file graph
| Format.Png -> Dep2pict.save_png ~filename:out_file graph
| Format.Dep -> (
match (!current_data, !current_position) with
| (Conll arr, p) -> File.write out_file (Dep2pict.conll_to_dep ~conll:(snd arr.(p)))
| _ -> critical "<dep> output format is available only for <conll> inputs"
)
| f -> critical "<%s> is not a valid output format" (Format.to_string f)
end;
Log.finfo "File %s generated." out_file
with
| Dep2pict.Parse_error msgs -> List.iter (fun (l,m) -> printf "Line %d: %s\n" l m) msgs; critical "Parse error !!"
| Dep2pict.Id_already_in_use_ id -> critical "Id already used: %s" id