]> git.donarmstrong.com Git - lilypond.git/blob - lily/program-option.cc
use a single function for asking profile info.
[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--2006  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 ly:set-option usage")
162 {
163   string help = get_help_string ();
164   fputs (help.c_str (), stdout);
165
166   exit (0);
167   return SCM_UNSPECIFIED;
168 }
169
170 LY_DEFINE (ly_add_option, "ly:add-option", 3, 0, 0,
171            (SCM sym, SCM val, SCM description),
172            "Add a program option @var{sym} with default @var{val}.")
173 {
174   if (!option_hash)
175     {
176       option_hash = scm_permanent_object (scm_c_make_hash_table (11));
177     }
178   SCM_ASSERT_TYPE (scm_is_symbol (sym), sym, SCM_ARG1, __FUNCTION__, "symbol");
179   SCM_ASSERT_TYPE (scm_is_string (description), description,
180                    SCM_ARG3, __FUNCTION__, "string");
181
182   internal_set_option (sym, val);
183
184   scm_set_object_property_x (sym, ly_symbol2scm ("program-option-documentation"),
185                              description);
186
187   return SCM_UNSPECIFIED;
188 }
189
190 LY_DEFINE (ly_set_option, "ly:set-option", 1, 1, 0, (SCM var, SCM val),
191            "Set a program option. Try setting 'help for a help string.")
192 {
193   SCM_ASSERT_TYPE (scm_is_symbol (var), var, SCM_ARG1,
194                    __FUNCTION__, "symbol");
195
196   if (ly_symbol2scm ("help") == var)
197     ly_option_usage ();
198
199   if (val == SCM_UNDEFINED)
200     val = SCM_BOOL_T;
201
202   string varstr = ly_scm2string (scm_symbol_to_string (var));
203   if (varstr.substr (0, 3) == string ("no-"))
204     {
205       var = ly_symbol2scm (varstr.substr (3, varstr.length () -3).c_str ());
206       val = scm_from_bool (!to_boolean (val));
207     }
208
209   SCM handle = scm_hashq_get_handle (option_hash, var);
210   if (handle == SCM_BOOL_F)
211     warning (_f ("no such internal option: %s", varstr.c_str ()));
212
213   internal_set_option (var, val);
214   return SCM_UNSPECIFIED;
215 }
216
217 LY_DEFINE (ly_command_line_verbose_p, "ly:command-line-verbose?", 0, 0, 0, (),
218            "Was be_verbose_global set?")
219 {
220   return scm_from_bool (be_verbose_global);
221 }
222
223
224
225 LY_DEFINE (ly_all_option, "ly:all-options",
226            0, 0, 0, (),
227            "Get all option settings in an alist.")
228 {
229   return ly_hash2alist (option_hash);
230 }
231
232
233 LY_DEFINE (ly_get_option, "ly:get-option", 1, 0, 0, (SCM var),
234            "Get a global option setting.")
235 {
236   SCM_ASSERT_TYPE (scm_is_symbol (var), var,
237                    SCM_ARG1, __FUNCTION__, "symbol");
238   return scm_hashq_ref (option_hash, var, SCM_BOOL_F);
239 }
240
241
242
243 bool
244 get_program_option (const char *s)
245 {
246   SCM sym = ly_symbol2scm (s);
247
248   return to_boolean (ly_get_option (sym));
249 }