package talaria-bibtex

  1. Overview
  2. Docs

Source file fields.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
include Field_types


exception Unknown_attribute of string*string

module Record = Orec.Namespace.Make()
include(Record)

type 'a named_field =
  { name : string; f : 'a Record.field ; conv: ('a,string) Record.bijection }
let str named_field = Record.( named_field.f @: named_field.conv )
let named_field ~name conv = {name; f=Record.new_field (); conv }
let str_field = let id x = x in named_field Record.{ to_ = id ; from = id }
let int_field = named_field Record.{to_ = string_of_int; from = int_of_string }

module StrSet = Set.Make(String)
module RawMap = Map.Make(String)

let strset_field = named_field Record.{
    to_ =  ( fun x -> x |> StrSet.elements |> String.concat "," ) ;
    from = ( fun x -> x |> Lexing.from_string |>
                      Field_parsers.tags Field_lexers.tags |> StrSet.of_list )
  }

let uid = str_field  ~name:"uid"
let raw : string RawMap.t Record.field = Record.new_field ()

let kind = named_field ~name:"kind" Record.{
             to_ = (function
                | Article -> "article"
                | Inproceedings -> "inproceedings"
                | Talk -> "talk"
                | Book -> "book"
                | Poster -> "poster"
                   );
             from= ( function
                | "article" -> Article
                | "inproceedings" -> Inproceedings
                | "talk" -> Talk
                | "book" -> Book
                | "poster" -> Poster
                | s  -> raise @@ Unknown_attribute ("kind",s)  )
           }

let title = str_field ~name:"title"

let authors =
   named_field ~name:"author"
    Record.{
      to_ =( fun p -> String.concat " and " @@
             List.map (fun {firstname; lastname} ->
                 String.concat ", " [lastname;firstname]
               ) p );
      from = (fun s -> s |> Lexing.from_string |> Field_parsers.names Field_lexers.names )
    }

let year = int_field ~name:"year"
let journal = str_field ~name:"journal"
let booktitle=str_field ~name:"booktitle"

let volume = int_field ~name:"volume"
let number = int_field ~name:"number"
let pages =
  named_field ~name:"pages" Record.{
      to_ = (function Loc n -> string_of_int n | Interv (k,l) ->
          Printf.sprintf "%d-%d" k l);
      from = ( fun s -> s |> Lexing.from_string |>  Field_parsers.pages Field_lexers.pages )
    }

let doi =
  named_field ~name:"doi" Record.{
      to_ = String.concat "/" ;
      from = (fun s ->  s |> Lexing.from_string |> Field_parsers.path Field_lexers.path)
    }

let arxiv = str_field ~name:"arxiv"

let tags = strset_field ~name:"tags"
let src = strset_field ~name:"src"

let state= named_field ~name:"state" Record.{
    to_ = (  function Published -> "published"
                    | Accepted -> "accepted"
                    | Submitted -> "submitted"
                    | WIP -> "wip" );
             from = ( function
                | "published" -> Published
                | "accepted" -> Accepted
                | "submitted"  -> Submitted
                | "wip" -> WIP
                | s -> raise @@ Unknown_attribute ("state",s) )
           }

let abstract = str_field ~name:"abstract"
let location = str_field  ~name:"location"
let conference = str_field  ~name:"conference"

let get_uid entry = match entry.%{uid.f} with None -> assert false | Some x -> x
let get_kind entry = match entry.%{kind.f} with
  | None -> assert false
  | Some x -> x
let get_state entry = match entry.%{state.f} with None -> WIP | Some x -> x

type entry = Record.t
module Database=Map.Make(String)
type data = entry Database.t

type raw_entry = { uid:string; kind:string; raw: string Database.t  }
let default_keys =
  let ( |>> ) database named_field =
    Database.add named_field.name (str named_field) database
  in
  Database.empty
  |>> title
  |>> authors
  |>> journal
  |>> year
  |>> volume
  |>> number
  |>> pages
  |>> doi
  |>> arxiv
  |>> abstract
  |>> state
  |>> tags
  |>> src
  |>> booktitle
  |>> location
  |>> conference

let check_entry keydtb raw_entry =
  let add key value e =
    match Database.find key keydtb with
    | exception Not_found ->  e.%{ raw |= fun m -> Database.add key value m }
    | key -> e.%{ key ^= value }
  in
  let init = create [ str uid ^= raw_entry.uid; str kind ^= raw_entry.kind; raw ^= Database.empty ] in
  Database.fold add raw_entry.raw init

let check ?(with_keys=default_keys) raw =
  Database.map (check_entry with_keys) raw