]> git.donarmstrong.com Git - lilypond.git/blob - lily/program-option.cc
fd1327622f45b22e7e23c321d95c4b2209b5a05f
[lilypond.git] / lily / program-option.cc
1 /*
2   scm-option.cc -- implement option setting from Scheme
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2001--2007  Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "program-option.hh"
10 #include "profile.hh"
11
12 #include <cstdio>
13 #include <cstring>
14 using namespace std;
15
16 #include "international.hh"
17 #include "main.hh"
18 #include "parse-scm.hh"
19 #include "string-convert.hh"
20 #include "warn.hh"
21
22 /* Write midi as formatted ascii stream? */
23 bool do_midi_debugging_global;
24 bool use_object_keys;
25 bool debug_skylines;
26
27 /*
28   Backwards compatibility.
29 */
30 bool lily_1_8_relative = false;
31 bool lily_1_8_compatibility_used = false;
32 bool profile_property_accesses = false;
33 /*
34   crash if internally the wrong type is used for a grob property.
35 */
36 bool do_internal_type_checking_global;
37 bool strict_infinity_checking = false; 
38
39 static SCM option_hash;
40
41 void internal_set_option (SCM var, SCM val)
42 {
43   scm_hashq_set_x (option_hash, var, val);
44
45   if (0)
46     ;
47   else if (var == ly_symbol2scm ("profile-property-accesses"))
48     {
49       profile_property_accesses = to_boolean (val);
50       val = scm_from_bool (to_boolean (val));
51     }
52   else if (var == ly_symbol2scm ("debug-midi"))
53     {
54       do_midi_debugging_global = to_boolean (val);
55       val = scm_from_bool (to_boolean (val));
56     }
57   else if (var == ly_symbol2scm ("point-and-click"))
58     {
59       point_and_click_global = to_boolean (val);
60       val = scm_from_bool (to_boolean (val));
61     }
62   else if (var == ly_symbol2scm ("protected-scheme-parsing"))
63     {
64       parse_protect_global = to_boolean (val);
65       val = scm_from_bool (to_boolean (val));
66     }
67   else if (var == ly_symbol2scm ("check-internal-types"))
68     {
69       do_internal_type_checking_global = to_boolean (val);
70       val = scm_from_bool (to_boolean (val));
71     }
72   else if (var == ly_symbol2scm ("debug-gc-assert-parsed-dead"))
73     {
74       parsed_objects_should_be_dead = to_boolean (val);
75       val = scm_from_bool (parsed_objects_should_be_dead);
76     }
77   else if (var == ly_symbol2scm ("safe"))
78     {
79       be_safe_global = to_boolean (val);
80       val = scm_from_bool (be_safe_global);
81     }
82   else if (var == ly_symbol2scm ("old-relative"))
83     {
84       lily_1_8_relative = to_boolean (val);
85       /*  Needs to be reset for each file that uses this option.  */
86       lily_1_8_compatibility_used = to_boolean (val);
87       val = scm_from_bool (to_boolean (val));
88     }
89   else if (var == ly_symbol2scm ("object-keys"))
90     {
91       use_object_keys = to_boolean (val);
92       val = scm_from_bool (to_boolean (val));
93     }
94   else if (var == ly_symbol2scm ("strict-infinity-checking"))
95     {
96       strict_infinity_checking = to_boolean (val);
97       val = scm_from_bool (to_boolean (val));
98     }
99   else if (var == ly_symbol2scm ("debug-skylines"))
100     {
101       debug_skylines = to_boolean (val);
102       val = scm_from_bool (to_boolean (val));
103     }
104 }
105
106 ssize const HELP_INDENT = 30;
107 ssize const INDENT = 2;
108 ssize const SEPARATION = 5;
109
110 /*
111   Hmmm. should do in SCM / C++  ?
112 */
113 static string
114 get_help_string ()
115 {
116   SCM alist = ly_hash2alist (option_hash);
117   SCM convertor = ly_lily_module_constant ("scm->string");
118
119   vector<string> opts;
120
121   for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s))
122     {
123       SCM sym = scm_caar (s);
124       SCM val = scm_cdar (s);
125       string opt_spec
126         = String_convert::char_string (' ', INDENT)
127         + ly_symbol2string (sym)
128         + " ("
129         + ly_scm2string (scm_call_1 (convertor, val))
130         + ")";
131
132       if (opt_spec.length () + SEPARATION > HELP_INDENT)
133         {
134           opt_spec += "\n"
135             + String_convert::char_string (' ', HELP_INDENT);
136         }
137       else
138         opt_spec += String_convert::char_string (' ', HELP_INDENT - opt_spec.length ());
139
140       SCM opt_help_scm
141         = scm_object_property (sym, ly_symbol2scm ("program-option-documentation"));
142       string opt_help = ly_scm2string (opt_help_scm);
143       replace_all (opt_help,
144                    string ("\n"),
145                    string ("\n")
146                    + String_convert::char_string (' ', HELP_INDENT));
147
148       opts.push_back (opt_spec + opt_help + "\n");
149     }
150
151   string help ("Options supported by ly:set-option\n\n");
152   vector_sort (opts, less<string> ());
153   for (vsize i = 0; i < opts.size (); i++)
154     help += opts[i];
155
156   help += string ("\n");
157   return help;
158 }
159
160 LY_DEFINE (ly_option_usage, "ly:option-usage", 0, 0, 0, (),
161            "Print @code{ly:set-option} usage")
162 {
163   string help = get_help_string ();
164   progress_indication (help);
165
166   return SCM_UNSPECIFIED;
167 }
168
169 LY_DEFINE (ly_add_option, "ly:add-option", 3, 0, 0,
170            (SCM sym, SCM val, SCM description),
171            "Add a program option @var{sym} with default @var{val}.")
172 {
173   if (!option_hash)
174     {
175       option_hash = scm_permanent_object (scm_c_make_hash_table (11));
176     }
177   SCM_ASSERT_TYPE (scm_is_symbol (sym), sym, SCM_ARG1, __FUNCTION__, "symbol");
178   SCM_ASSERT_TYPE (scm_is_string (description), description,
179                    SCM_ARG3, __FUNCTION__, "string");
180
181   internal_set_option (sym, val);
182
183   scm_set_object_property_x (sym, ly_symbol2scm ("program-option-documentation"),
184                              description);
185
186   return SCM_UNSPECIFIED;
187 }
188
189 LY_DEFINE (ly_set_option, "ly:set-option", 1, 1, 0, (SCM var, SCM val),
190            "Set a program option. Try setting 'help for a help string.")
191 {
192   SCM_ASSERT_TYPE (scm_is_symbol (var), var, SCM_ARG1,
193                    __FUNCTION__, "symbol");
194
195   if (ly_symbol2scm ("help") == var)
196     {
197       ly_option_usage ();
198       exit (0);
199     }
200
201   if (val == SCM_UNDEFINED)
202     val = SCM_BOOL_T;
203
204   string varstr = ly_scm2string (scm_symbol_to_string (var));
205   if (varstr.substr (0, 3) == string ("no-"))
206     {
207       var = ly_symbol2scm (varstr.substr (3, varstr.length () -3).c_str ());
208       val = scm_from_bool (!to_boolean (val));
209     }
210
211   SCM handle = scm_hashq_get_handle (option_hash, var);
212   if (handle == SCM_BOOL_F)
213     warning (_f ("no such internal option: %s", varstr.c_str ()));
214
215   internal_set_option (var, val);
216   return SCM_UNSPECIFIED;
217 }
218
219 LY_DEFINE (ly_command_line_verbose_p, "ly:command-line-verbose?", 0, 0, 0, (),
220            "Was be_verbose_global set?")
221 {
222   return scm_from_bool (be_verbose_global);
223 }
224
225
226
227 LY_DEFINE (ly_all_option, "ly:all-options",
228            0, 0, 0, (),
229            "Get all option settings in an alist.")
230 {
231   return ly_hash2alist (option_hash);
232 }
233
234
235 LY_DEFINE (ly_get_option, "ly:get-option", 1, 0, 0, (SCM var),
236            "Get a global option setting.")
237 {
238   SCM_ASSERT_TYPE (scm_is_symbol (var), var,
239                    SCM_ARG1, __FUNCTION__, "symbol");
240   return scm_hashq_ref (option_hash, var, SCM_BOOL_F);
241 }
242
243
244
245 bool
246 get_program_option (const char *s)
247 {
248   SCM sym = ly_symbol2scm (s);
249
250   return to_boolean (ly_get_option (sym));
251 }