[/] [trunk/] [src/] [settingsrwfn.sml] - Blame information for rev 45

Line No. Rev Author Line
1 13 tbourke
(* $Id: settings-rw.sml 328 2007-10-31 06:05:10Z tbourke $ *)
2
 
3
functor SettingsRWFn (val checkFile : string -> bool) :> SETTINGS_RW =
4
struct
5
  val version                    = concat [Version.version, " (",
6
                                           Version.svnversion, ")"]
7
  val progName                   = "urpal"
8
 
9
  datatype debug_priority = All | VeryDetailed | Detailed | Outline | NoDebug
10
  fun debugToInt All          = 0
11
    | debugToInt VeryDetailed = 1
12
    | debugToInt Detailed     = 2
13
    | debugToInt Outline      = 3
14
    | debugToInt NoDebug      = 4
15
 
16
  fun intToDebug 0 = SOME All
17
    | intToDebug 1 = SOME VeryDetailed
18
    | intToDebug 2 = SOME Detailed
19
    | intToDebug 3 = SOME Outline
20
    | intToDebug 4 = SOME NoDebug
21
    | intToDebug _ = NONE
22
 
23
  fun setXOff (_, NONE)                            = ()
24
    | setXOff (r as ref NONE, SOME v)              = (r := SOME {xoff=v, yoff=0})
25
    | setXOff (r as ref (SOME {yoff,...}), SOME v) = (r := SOME {xoff=v, yoff=yoff})
26
 
27
  fun setYOff (_, NONE)                            = ()
28
    | setYOff (r as ref NONE, SOME v)              = (r := SOME {xoff=0,    yoff=v})
29
    | setYOff (r as ref (SOME {xoff,...}), SOME v) = (r := SOME {xoff=xoff, yoff=v})
30
 
31
  local
32
    val ref_dtdPath                = ref (NONE : string option)
33
    val ref_prefix                 = ref (SOME "/usr/local")
34
    val ref_graphvizPath           = ref (NONE : string option)
35 21 tbourke
    val ref_graphvizEngine         = ref "fdp"
36 13 tbourke
    val ref_maxLabelWidth          = ref 72
37
    val ref_maxDeclarationWidth    = ref 72
38
    val ref_newColor               = ref (SOME "#f0e68c")
39
    val ref_errorColor             = ref (SOME "#f0e68c")
40
    val ref_urgChanLocColor        = ref (SOME "#7fffd4")
41
 
42
    val ref_splitShiftOld          = ref (NONE : {xoff:int, yoff:int} option)
43
    val ref_splitShiftNew          = ref (NONE : {xoff:int, yoff:int} option)
44
    val ref_tabulateShift          = ref (NONE : {xoff:int, yoff:int} option)
45
 
46
    val ref_tabulateLabels         = ref false
47
 
48
    val ref_priority = ref NoDebug
49
  in
50
 
51
  fun dtdPath ()                 = !ref_dtdPath
52
  fun set_dtdPath nv             = (ref_dtdPath := nv)
53
 
54
  fun prefix ()                  = !ref_prefix
55
 
56
  fun graphvizPath ()            = (case (!ref_graphvizPath, !ref_prefix) of
57
                                      (NONE, NONE)   => ""
58
                                    | (NONE, SOME p) => p
59 21 tbourke
                                    | (SOME g,NONE)  => g
60
                                    | (SOME g,SOME p)=> if OS.Path.isRelative g
61
                                                        then OS.Path.concat(p,g)
62
                                                        else g)
63 13 tbourke
 
64 21 tbourke
  fun set_graphvizPath nv        = (ref_graphvizPath := nv)
65 13 tbourke
 
66
  fun set_prefix nv              = (ref_prefix := nv;
67
                                    case !ref_graphvizPath of
68
                                      NONE => set_graphvizPath nv
69
                                    | _    => ())
70
 
71
  fun graphvizEngine ()          = !ref_graphvizEngine
72
  fun set_graphvizEngine nv      = (ref_graphvizEngine := nv)
73
 
74
  fun maxLabelWidth ()           = !ref_maxLabelWidth
75
  fun set_maxLabelWidth nv       = (ref_maxLabelWidth := nv)
76
 
77
  fun maxDeclarationWidth ()     = !ref_maxDeclarationWidth
78
  fun set_maxDeclarationWidth nv = (ref_maxDeclarationWidth := nv)
79
 
80
  fun newColor ()                = !ref_newColor
81
  fun set_newColor nv            = (ref_newColor := nv)
82
 
83
  fun errorColor ()              = !ref_errorColor
84
  fun set_errorColor nv          = (ref_errorColor := nv)
85
 
86
  fun urgChanLocColor ()         = !ref_urgChanLocColor
87
  fun set_urgChanLocColor nv     = (ref_urgChanLocColor := nv)
88
 
89
  fun splitShiftOld ()           = !ref_splitShiftOld
90
  fun set_splitShiftOld v        = (ref_splitShiftOld := v)
91
  fun splitShiftNew ()           = !ref_splitShiftNew
92
  fun set_splitShiftNew v        = (ref_splitShiftNew := v)
93
 
94
  fun set_splitShiftOldX v       = setXOff (ref_splitShiftOld, v)
95
  fun set_splitShiftOldY v       = setYOff (ref_splitShiftOld, v)
96
  fun set_splitShiftNewX v       = setXOff (ref_splitShiftNew, v)
97
  fun set_splitShiftNewY v       = setYOff (ref_splitShiftNew, v)
98
 
99
  fun set_tabulateShiftX v       = setXOff (ref_tabulateShift, v)
100
  fun set_tabulateShiftY v       = setYOff (ref_tabulateShift, v)
101
 
102
  fun tabulateShift ()           = case !ref_tabulateShift of
103
                                     NONE   => {xoff=10, yoff=10}
104
                                   | SOME p => p
105
  fun set_tabulateShift v        = (ref_tabulateShift := v)
106
 
107
  fun tabulateLabels ()          = !ref_tabulateLabels
108
  fun set_tabulateLabels v       = (ref_tabulateLabels := v)
109
 
110
  fun set_priority d = ignore(Option.map(fn v=>ref_priority:=v) (intToDebug d))
111
  fun showDebug (d1) = debugToInt d1 >= debugToInt (!ref_priority)
112
  fun priority () = !ref_priority
113
 
114
  end (* local *)
115
 
116
  fun warn msg = (TextIO.output (TextIO.stdErr,
117
                                 String.concat (progName::":"::msg));
118
                  TextIO.output (TextIO.stdErr, "\n"))
119
 
120
  fun validate () = let
121
 
122
      fun check test (name, path) = let
123
          val r = test path handle SysErr => false
124
          val _ = if r then ()
125
                  else warn ["setting ", name, " (", path ,") is invalid."]
126
        in r end
127
 
128
      fun checkoFile (_, NONE)   = true
129
        | checkoFile (s, SOME p) = check checkFile (s, p)
130
 
131
      fun addFile (f, d) = OS.Path.joinDirFile {dir=d, file=f}
132
 
133
      val results = [ checkoFile ("dtd_path", dtdPath ()),
134
                      check checkFile ("graphviz/path",
135
                                      foldl addFile (graphvizPath ())
136
                                            ["bin", "dot"])
137
                    ]
138
    in List.all (fn x=>x) results end
139
 
140
 
141
  local
142
    structure CT = ConfigTree
143
 
144
    val <*< = Option.compose; infixr <*<
145
    val <**< = Option.composePartial; infixr <**<
146
 
147
    fun some x = SOME (SOME x)
148
  in
149
  fun loadConfigFile rdr strm = let
150
      val cfgFile = CT.parse rdr strm
151
                    handle CT.ParseError l => [] before
152
                      warn ["error at line ", Int.toString l,
153
                            "of config file (all contents ignored)."]
154
      fun updateOption (path, changeSetting, f) = ignore (Option.map
155
                                        changeSetting (f (map Atom.atom path)))
156
 
157
      fun % f = fn v=> f (cfgFile, v)
158
    in
159
      List.app updateOption
160
      [(["dtd_path"],set_dtdPath, some <**< %CT.getString),
161
       (["prefix"],  set_prefix,  some <**< %CT.getString)];
162
 
163
      List.app updateOption
164
      [(["max_label_width"],       set_maxLabelWidth,       %CT.getInt),
165
       (["max_declaration_width"], set_maxDeclarationWidth, %CT.getInt)];
166
 
167 21 tbourke
      updateOption (["graphviz", "engine"], set_graphvizEngine, %CT.getString);
168 13 tbourke
      updateOption (["graphviz", "path"], set_graphvizPath,
169
                                                    some <**< %CT.getString);
170
 
171
      updateOption (["split_shift_old", "x"],       set_splitShiftOldX,
172
                                                    some <**<    %CT.getInt);
173
      updateOption (["split_shift_old", "y"],       set_splitShiftOldY,
174
                                                    some <**<    %CT.getInt);
175
      updateOption (["split_shift_new", "x"],       set_splitShiftNewX,
176
                                                    some <**<    %CT.getInt);
177
      updateOption (["split_shift_new", "y"],       set_splitShiftNewY,
178
                                                    some <**<    %CT.getInt);
179
      updateOption (["tabulate_shift", "x"],        set_tabulateShiftX,
180
                                                    some <**<    %CT.getInt);
181
      updateOption (["tabulate_shift", "y"],        set_tabulateShiftY,
182
                                                    some <**<    %CT.getInt);
183
 
184
      List.app updateOption
185
      [(["new_color"],           set_newColor,       some <**< %CT.getString),
186
       (["error_color"],         set_errorColor,     some <**< %CT.getString),
187
       (["urgent_chanloc_color"],set_urgChanLocColor,some <**< %CT.getString)];
188
 
189
      updateOption (["debug"],   set_priority,                 %CT.getInt)
190
    end
191
 
192
  fun saveConfigFile outs = let
193
 
194
      val % = Atom.atom
195
      fun id x = x
196
 
197
      fun optEntry (n, w, v) = Option.map (fn v=>CT.Entry (n, w v)) v
198
      fun defEntry (n, w, v) = SOME (CT.Entry (n, w v))
199
 
200
      fun optOffset (n, NONE) = NONE
201
        | optOffset (n, SOME {xoff, yoff}) = SOME (CT.Section (n,
202
            [CT.Entry (%"x", CT.Int xoff), CT.Entry (%"y", CT.Int yoff)]))
203
 
204
      val cfg = List.mapPartial id [
205
          optEntry (%"dtd_path",            CT.String,dtdPath()),
206
 
207
          defEntry (%"max_label_width",      CT.Int, maxLabelWidth()),
208
          defEntry (%"max_declaration_width",CT.Int, maxDeclarationWidth()),
209
 
210
          optEntry (%"new_color",           CT.Color, newColor()),
211
          optEntry (%"error_color",         CT.Color, errorColor()),
212
          optEntry (%"urgent_chanloc_color",CT.Color, urgChanLocColor()),
213
 
214
          optOffset (%"split_shift_old",    splitShiftOld ()),
215
          optOffset (%"split_shift_new",      splitShiftNew      ()),
216
          optOffset (%"tabulate_shift",       SOME (tabulateShift ())),
217
 
218
          SOME (CT.Section (%"graphviz", [
219 21 tbourke
            CT.Entry (%"path",   CT.String (graphvizPath ())),
220
            CT.Entry (%"engine", CT.String (graphvizEngine ()))])),
221 13 tbourke
 
222
          defEntry (%"debug",             CT.Int, debugToInt (priority ()))
223
        ]
224
    in CT.output (outs, cfg) end
225
 
226
  end (* local *)
227
 
228
end
229