let item_to_string ?(tags=default_tags) () =
let module PQ = Biocaml_transform.Printer_queue in
let version =
List.find_map tags (function `version v -> Some v | _ -> None)
|! Option.value ~default:`three in
let printer =
PQ.make () ~to_string:(function
| `comment c -> sprintf "#%s\n" c
| `record t ->
let escape =
match version with | `three -> Url.escape | `two -> sprintf "%S" in
let optescape o = Option.value_map ~default:"." o ~f:escape in
String.concat ~sep:"\t" [
escape t.seqname;
optescape t.source;
optescape t.feature;
sprintf "%d" (fst t.pos);
sprintf "%d" (snd t.pos);
Option.value_map ~default:"." ~f:(sprintf "%g") t.score;
(match t.strand with`plus -> "+" | `minus -> "-"
| `not_applicable -> "." | `unknown -> "?");
Option.value_map ~default:"." ~f:(sprintf "%d") t.phase;
String.concat ~sep:";"
(List.map t.attributes (fun (k,v) ->
match version with
| `three ->
sprintf "%s=%s" (Url.escape k)
(List.map v Url.escape |! String.concat ~sep:",")
| `two ->
sprintf "%S %s" k
(List.map v escape |! String.concat ~sep:",")
));
] ^ "\n"
) in
Biocaml_transform.make ~name:"gff_printer" ()
~feed:(fun r -> PQ.feed printer r)
~next:(fun stopped ->
match (PQ.flush printer) with
| "" -> if stopped then `end_of_stream else `not_ready
| s -> `output s)