1
2 /******************************************************************************
3 * MODULE : new_style.cpp
4 * DESCRIPTION: Style and DRD computation and caching
5 * COPYRIGHT : (C) 1999-2012 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #include "new_style.hpp"
13 #include "file.hpp"
14 #include "data_cache.hpp"
15 #include "convert.hpp"
16 #include "../../Typeset/env.hpp"
17
18 /******************************************************************************
19 * Global data
20 ******************************************************************************/
21
22 struct style_data_rep {
23 hashmap<tree,hashmap<string,tree> > style_cache;
24 hashmap<tree,tree> style_drd;
25 hashmap<string,bool> style_busy;
26 hashmap<string,tree> style_void;
27 drd_info drd_void;
28 hashmap<tree,hashmap<string,tree> > style_cached;
29 hashmap<tree,drd_info> drd_cached;
30
style_data_repstyle_data_rep31 style_data_rep ():
32 style_cache (hashmap<string,tree> (UNINIT)),
33 style_drd (tree (COLLECTION)),
34 style_busy (false),
35 style_void (UNINIT),
36 drd_void ("void"),
37 style_cached (style_void),
38 drd_cached (drd_void) {}
39 };
40
41 static style_data_rep* sd= NULL;
42
43 static void
init_style_data()44 init_style_data () {
45 if (sd == NULL) sd= tm_new<style_data_rep> ();
46 }
47
48 extern hashmap<string,tree> style_tree_cache;
49 hashmap<string,bool> hidden_packages (false);
50
51 /******************************************************************************
52 * Modify style so as to search in all ancestor directories
53 ******************************************************************************/
54
55 tree
preprocess_style(tree st,url name)56 preprocess_style (tree st, url name) {
57 if (is_rooted_tmfs (name)) return st;
58 if (is_atomic (st)) st= tree (TUPLE, st);
59 if (!is_tuple (st)) return st;
60 tree r (TUPLE, N(st));
61 for (int i=0; i<N(st); i++) {
62 r[i]= st[i];
63 if (!is_atomic (st[i])) continue;
64 string pack= st[i]->label * ".ts";
65 url stf= resolve (expand (head (name) * url_ancestor () * pack));
66 if (!is_none (stf)) r[i]= as_string (stf);
67 }
68 //if (r != st) cout << "old: " << st << "\nnew: " << r << "\n";
69 return r;
70 }
71
72 /******************************************************************************
73 * Caching style files on disk
74 ******************************************************************************/
75
76 static string
cache_file_name(tree t)77 cache_file_name (tree t) {
78 if (is_atomic (t)) return replace (t->label, "/", "%");
79 else {
80 string s;
81 int i, n= N(t);
82 for (i=0; i<n; i++)
83 s << "__" << cache_file_name (t[i]);
84 return s * "__";
85 }
86 }
87
88 void
style_invalidate_cache()89 style_invalidate_cache () {
90 style_tree_cache= hashmap<string,tree> ();
91 hidden_packages= hashmap<string,bool> (false);
92 if (sd != NULL) {
93 tm_delete<style_data_rep> (sd);
94 sd= NULL;
95 }
96 init_style_data ();
97 remove ("$TEXMACS_HOME_PATH/system/cache" * url_wildcard ("__*"));
98 }
99
100 void
style_set_cache(tree style,hashmap<string,tree> H,tree t)101 style_set_cache (tree style, hashmap<string,tree> H, tree t) {
102 init_style_data ();
103 // cout << "set cache " << style << LF;
104 sd->style_cache (copy (style))= H;
105 sd->style_drd (copy (style))= t;
106 url name ("$TEXMACS_HOME_PATH/system/cache", cache_file_name (style));
107 if (!exists (name)) {
108 save_string (name, tree_to_scheme (tuple ((tree) H, t)));
109 // cout << "saved " << name << LF;
110 }
111 }
112
113 void
style_get_cache(tree style,hashmap<string,tree> & H,tree & t,bool & f)114 style_get_cache (tree style, hashmap<string,tree>& H, tree& t, bool& f) {
115 init_style_data ();
116 //cout << "get cache " << style << LF;
117 if ((style == "") || (style == tree (TUPLE))) { f= false; return; }
118 f= sd->style_cache->contains (style);
119 if (f) {
120 H= sd->style_cache [style];
121 t= sd->style_drd [style];
122 }
123 else {
124 string s;
125 url name ("$TEXMACS_HOME_PATH/system/cache", cache_file_name (style));
126 if (exists (name) && (!load_string (name, s, false))) {
127 //cout << "loaded " << name << LF;
128 tree p= scheme_to_tree (s);
129 H= hashmap<string,tree> (UNINIT, p[0]);
130 t= p[1];
131 sd->style_cache (copy (style))= H;
132 sd->style_drd (copy (style))= t;
133 f= true;
134 }
135 }
136 }
137
138 /******************************************************************************
139 * Get environment and drd of style files
140 ******************************************************************************/
141
142 bool
compute_env_and_drd(tree style)143 compute_env_and_drd (tree style) {
144 init_style_data ();
145 ASSERT (is_tuple (style), "style tuple expected");
146 bool busy= false;
147 for (int i=0; i<N(style); i++)
148 busy= busy || sd->style_busy->contains (as_string (style[i]));
149 hashmap<string,bool> old_busy= copy (sd->style_busy);
150 for (int i=0; i<N(style); i++)
151 sd->style_busy (as_string (style[i]))= true;
152
153 //cout << "Get environment of " << style << INDENT << LF;
154 hashmap<string,tree> H;
155 drd_info drd ("none", std_drd);
156 url none= url ("$PWD/none");
157 hashmap<string,tree> lref;
158 hashmap<string,tree> gref;
159 hashmap<string,tree> laux;
160 hashmap<string,tree> gaux;
161 hashmap<string,tree> latt;
162 hashmap<string,tree> gatt;
163 edit_env env (drd, none, lref, gref, laux, gaux, latt, gatt);
164 if (!busy) {
165 tree t;
166 bool ok;
167 style_get_cache (style, H, t, ok);
168 if (ok) {
169 env->patch_env (H);
170 ok= drd->set_locals (t);
171 drd->set_environment (H);
172 }
173 if (!ok) {
174 env->exec (tree (USE_PACKAGE, A (style)));
175 env->read_env (H);
176 drd->heuristic_init (H);
177 }
178 sd->style_cached (style)= H;
179 sd->drd_cached (style)= drd;
180 }
181 //cout << UNINDENT << "Got environment of " << style << LF;
182
183 sd->style_busy= old_busy;
184 return !busy;
185 }
186
187 hashmap<string,tree>
get_style_env(tree style)188 get_style_env (tree style) {
189 //cout << "get_style_env " << style << "\n";
190 init_style_data ();
191 if (sd->style_cached->contains (style))
192 return sd->style_cached [style];
193 else if (compute_env_and_drd (style))
194 return sd->style_cached [style];
195 else {
196 //cout << "Busy style: " << style << "\n";
197 return hashmap<string,tree> ();
198 }
199 }
200
201 drd_info
get_style_drd(tree style)202 get_style_drd (tree style) {
203 //cout << "get_style_drd " << style << "\n";
204 init_style_data ();
205 init_std_drd ();
206 if (sd->drd_cached->contains (style))
207 return sd->drd_cached [style];
208 else if (compute_env_and_drd (style))
209 return sd->drd_cached [style];
210 else {
211 //cout << "Busy drd: " << style << "\n";
212 return std_drd;
213 }
214 }
215
216 tree
get_document_preamble(tree t)217 get_document_preamble (tree t) {
218 init_style_data ();
219 if (is_atomic (t)) return "";
220 else if (is_compound (t, "hide-preamble", 1)) return t[0];
221 else if (is_compound (t, "show-preamble", 1)) return t[0];
222 else {
223 int i, n= N(t);
224 for (i=0; i<n; i++) {
225 tree p= get_document_preamble (t[i]);
226 if (p != "") return p;
227 }
228 return "";
229 }
230 }
231
232 drd_info
get_document_drd(tree doc)233 get_document_drd (tree doc) {
234 init_style_data ();
235 tree style= extract (doc, "style");
236 if (extract (doc, "TeXmacs") == "") {
237 if (the_drd->get_syntax (make_tree_label ("theorem")) != tree (UNINIT))
238 return the_drd;
239 style= tree (TUPLE, "generic");
240 }
241 //cout << "style= " << style << "\n";
242 drd_info drd= get_style_drd (style);
243 tree p= get_document_preamble (doc);
244 if (p != "") {
245 drd= drd_info ("preamble", drd);
246 url none= url ("$PWD/none");
247 hashmap<string,tree> lref;
248 hashmap<string,tree> gref;
249 hashmap<string,tree> laux;
250 hashmap<string,tree> gaux;
251 hashmap<string,tree> latt;
252 hashmap<string,tree> gatt;
253 edit_env env (drd, none, lref, gref, laux, gaux, latt, gatt);
254 hashmap<string,tree> H;
255 env->exec (tree (USE_PACKAGE, A (style)));
256 env->exec (p);
257 env->read_env (H);
258 drd->heuristic_init (H);
259 }
260 return drd;
261 }
262
263 /******************************************************************************
264 * The style and package menus
265 ******************************************************************************/
266
267 static bool
ignore_dir(string dir)268 ignore_dir (string dir) {
269 return
270 (dir == "Beamer") ||
271 (dir == "Compute") ||
272 (dir == "Customize") ||
273 (dir == "Environment") ||
274 (dir == "Gui") ||
275 (dir == "Header") ||
276 (dir == "Latex") ||
277 (dir == "Miscellaneous") ||
278 (dir == "Obsolete") ||
279 (dir == "Section") ||
280 (dir == "Session") ||
281 (dir == "Standard") ||
282 (dir == "Test");
283 }
284
285 static bool
hidden_package(url u,string name,bool hidden)286 hidden_package (url u, string name, bool hidden) {
287 if (is_or (u))
288 return hidden_package (u[1], name, hidden) ||
289 hidden_package (u[2], name, hidden);
290 if (is_concat (u)) {
291 string dir= upcase_first (as_string (u[1]));
292 if (dir == "CVS" || dir == ".svn") return false;
293 return hidden_package (u[2], name, hidden || ignore_dir (dir));
294 }
295 if (hidden && is_atomic (u)) {
296 string l= as_string (u);
297 if (!ends (l, ".ts")) return false;
298 l= l(0, N(l)-3);
299 return name == l;
300 }
301 return false;
302 }
303
304 bool
hidden_package(string name)305 hidden_package (string name) {
306 if (!hidden_packages->contains (name)) {
307 url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
308 hidden_packages (name)= hidden_package (pck_u, name, false);
309 }
310 return hidden_packages [name];
311 }
312
313 static string
compute_style_menu(url u,int kind)314 compute_style_menu (url u, int kind) {
315 if (is_or (u)) {
316 string sep= "\n";
317 if (is_atomic (u[1]) &&
318 ((is_concat (u[2]) && (u[2][1] != "CVS") && (u[2][1] != ".svn")) ||
319 (is_or (u[2]) && is_concat (u[2][1]))))
320 sep= "\n---\n";
321 return
322 compute_style_menu (u[1], kind) * sep *
323 compute_style_menu (u[2], kind);
324 }
325 if (is_concat (u)) {
326 string dir= upcase_first (as_string (u[1]));
327 string sub= compute_style_menu (u[2], kind);
328 if (ignore_dir (dir) || dir == "CVS" || dir == ".svn") return "";
329 return "(-> \"" * dir * "\" " * sub * ")";
330 }
331 if (is_atomic (u)) {
332 string l = as_string (u);
333 if (!ends (l, ".ts")) return "";
334 l= l(0, N(l)-3);
335 string cmd ("set-main-style");
336 if (kind == 1) cmd= "add-style-package";
337 if (kind == 2) cmd= "remove-style-package";
338 if (kind == 3) cmd= "toggle-style-package";
339 return "((verbatim \"" * l * "\") (" * cmd * " \"" * l * "\"))";
340 }
341 return "";
342 }
343
344 object
get_style_menu()345 get_style_menu () {
346 url sty_u= descendance ("$TEXMACS_STYLE_ROOT");
347 string sty= compute_style_menu (sty_u, 0);
348 return eval ("(menu-dynamic " * sty * ")");
349 }
350
351 object
get_add_package_menu()352 get_add_package_menu () {
353 url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
354 string pck= compute_style_menu (pck_u, 1);
355 return eval ("(menu-dynamic " * pck * ")");
356 }
357
358 object
get_remove_package_menu()359 get_remove_package_menu () {
360 url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
361 string pck= compute_style_menu (pck_u, 2);
362 return eval ("(menu-dynamic " * pck * ")");
363 }
364
365 object
get_toggle_package_menu()366 get_toggle_package_menu () {
367 url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
368 string pck= compute_style_menu (pck_u, 3);
369 return eval ("(menu-dynamic " * pck * ")");
370 }
371