Back to index

texmacs  1.0.7.15
new_style.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : new_style.cpp
00004 * DESCRIPTION: Style and DRD computation and caching
00005 * COPYRIGHT  : (C) 1999-2012  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "new_style.hpp"
00013 #include "file.hpp"
00014 #include "convert.hpp"
00015 #include "../../Typeset/env.hpp"
00016 
00017 /******************************************************************************
00018 * Global data
00019 ******************************************************************************/
00020 
00021 struct style_data_rep {
00022   hashmap<tree,hashmap<string,tree> > style_cache;
00023   hashmap<tree,tree> style_drd;
00024   hashmap<string,bool> style_busy;
00025   hashmap<string,tree> style_void;
00026   drd_info drd_void;
00027   hashmap<tree,hashmap<string,tree> > style_cached;
00028   hashmap<tree,drd_info> drd_cached;
00029 
00030   style_data_rep ():
00031     style_cache (hashmap<string,tree> (UNINIT)),
00032     style_drd (tree (COLLECTION)),
00033     style_busy (false),
00034     style_void (UNINIT),
00035     drd_void ("void"),
00036     style_cached (style_void),
00037     drd_cached (drd_void) {}
00038 };
00039 
00040 static style_data_rep* sd= NULL;
00041 
00042 static void
00043 init_style_data () {
00044   if (sd == NULL) sd= tm_new<style_data_rep> ();
00045 }
00046 
00047 /******************************************************************************
00048 * Caching style files
00049 ******************************************************************************/
00050 
00051 static string
00052 cache_file_name (tree t) {
00053   if (is_atomic (t)) return t->label;
00054   else {
00055     string s;
00056     int i, n= N(t);
00057     for (i=0; i<n; i++)
00058       s << "__" << cache_file_name (t[i]);
00059     return s * "__";
00060   }
00061 }
00062 
00063 void
00064 style_invalidate_cache () {
00065   init_style_data ();
00066   sd->style_cache=
00067     hashmap<tree,hashmap<string,tree> > (hashmap<string,tree> (UNINIT));
00068   remove ("$TEXMACS_HOME_PATH/system/cache" * url_wildcard ("__*"));
00069 }
00070 
00071 void
00072 style_set_cache (tree style, hashmap<string,tree> H, tree t) {
00073   init_style_data ();
00074   // cout << "set cache " << style << LF;
00075   sd->style_cache (copy (style))= H;
00076   sd->style_drd   (copy (style))= t;
00077   url name ("$TEXMACS_HOME_PATH/system/cache", cache_file_name (style));
00078   if (!exists (name)) {
00079     save_string (name, tree_to_scheme (tuple ((tree) H, t)));
00080     // cout << "saved " << name << LF;
00081   }
00082 }
00083 
00084 void
00085 style_get_cache (tree style, hashmap<string,tree>& H, tree& t, bool& f) {
00086   init_style_data ();
00087   //cout << "get cache " << style << LF;
00088   if ((style == "") || (style == tree (TUPLE))) { f= false; return; }
00089   f= sd->style_cache->contains (style);
00090   if (f) {
00091     H= sd->style_cache [style];
00092     t= sd->style_drd   [style];
00093   }
00094   else {
00095     string s;
00096     url name ("$TEXMACS_HOME_PATH/system/cache", cache_file_name (style));
00097     if (exists (name) && (!load_string (name, s, false))) {
00098       //cout << "loaded " << name << LF;
00099       tree p= scheme_to_tree (s);
00100       H= hashmap<string,tree> (UNINIT, p[0]);
00101       t= p[1];
00102       sd->style_cache (copy (style))= H;
00103       sd->style_drd   (copy (style))= t;
00104       f= true;
00105     }
00106   }
00107 }
00108 
00109 /******************************************************************************
00110 * Get environment and drd of style files
00111 ******************************************************************************/
00112 
00113 bool
00114 compute_env_and_drd (tree style) {
00115   init_style_data ();
00116   ASSERT (is_tuple (style), "style tuple expected");
00117   bool busy= false;
00118   for (int i=0; i<N(style); i++)
00119     busy= busy || sd->style_busy->contains (as_string (style[i]));
00120   hashmap<string,bool> old_busy= copy (sd->style_busy);
00121   for (int i=0; i<N(style); i++)
00122     sd->style_busy (as_string (style[i]))= true;
00123 
00124   //cout << "Get environment of " << style << INDENT << LF;
00125   hashmap<string,tree> H;
00126   drd_info drd ("none", std_drd);
00127   url none= url ("$PWD/none");
00128   hashmap<string,tree> lref;
00129   hashmap<string,tree> gref;
00130   hashmap<string,tree> laux;
00131   hashmap<string,tree> gaux;
00132   edit_env env (drd, none, lref, gref, laux, gaux);
00133   if (!busy) {
00134     tree t;
00135     bool ok;
00136     style_get_cache (style, H, t, ok);
00137     if (ok) {
00138       env->patch_env (H);
00139       ok= drd->set_locals (t);
00140       drd->set_environment (H);
00141     }
00142     if (!ok) {
00143       env->exec (tree (USE_PACKAGE, A (style)));
00144       env->read_env (H);
00145       drd->heuristic_init (H);
00146     }
00147     sd->style_cached (style)= H;
00148     sd->drd_cached (style)= drd;
00149   }
00150   //cout << UNINDENT << "Got environment of " << style << LF;
00151 
00152   sd->style_busy= old_busy;
00153   return !busy;
00154 }
00155 
00156 hashmap<string,tree>
00157 get_style_env (tree style) {
00158   init_style_data ();
00159   if (sd->style_cached->contains (style))
00160     return sd->style_cached [style];
00161   else if (compute_env_and_drd (style))
00162     return sd->style_cached [style];
00163   else {
00164     //cout << "Busy style: " << style << "\n";
00165     return hashmap<string,tree> ();
00166   }
00167 }
00168 
00169 drd_info
00170 get_style_drd (tree style) {
00171   init_style_data ();
00172   init_std_drd ();
00173   if (sd->drd_cached->contains (style))
00174     return sd->drd_cached [style];
00175   else if (compute_env_and_drd (style))
00176     return sd->drd_cached [style];
00177   else {
00178     //cout << "Busy drd: " << style << "\n";
00179     return std_drd;
00180   }
00181 }
00182 
00183 tree
00184 get_document_preamble (tree t) {
00185   init_style_data ();
00186   if (is_atomic (t)) return "";
00187   else if (is_compound (t, "hide-preamble", 1)) return t[0];
00188   else if (is_compound (t, "show-preamble", 1)) return t[0];
00189   else {
00190     int i, n= N(t);
00191     for (i=0; i<n; i++) {
00192       tree p= get_document_preamble (t[i]);
00193       if (p != "") return p;
00194     }
00195     return "";
00196   }
00197 }
00198 
00199 drd_info
00200 get_document_drd (tree doc) {
00201   init_style_data ();
00202   tree style= extract (doc, "style");
00203   if (extract (doc, "TeXmacs") == "") {
00204     if (the_drd->get_syntax (make_tree_label ("theorem")) != tree (UNINIT))
00205       return the_drd;
00206     style= tree (TUPLE, "generic");
00207   }
00208   //cout << "style= " << style << "\n";
00209   drd_info drd= get_style_drd (style);
00210   tree p= get_document_preamble (doc);
00211   if (p != "") {
00212     drd= drd_info ("preamble", drd);
00213     url none= url ("$PWD/none");
00214     hashmap<string,tree> lref;
00215     hashmap<string,tree> gref;
00216     hashmap<string,tree> laux;
00217     hashmap<string,tree> gaux;
00218     edit_env env (drd, none, lref, gref, laux, gaux);
00219     hashmap<string,tree> H;
00220     env->exec (tree (USE_PACKAGE, A (style)));
00221     env->exec (p);
00222     env->read_env (H);
00223     drd->heuristic_init (H);
00224   }
00225   return drd;
00226 }
00227 
00228 /******************************************************************************
00229 * The style and package menus
00230 ******************************************************************************/
00231 
00232 static string
00233 compute_style_menu (url u, int kind) {
00234   if (is_or (u)) {
00235     string sep= "\n";
00236     if (is_atomic (u[1]) &&
00237        ((is_concat (u[2]) && (u[2][1] != "CVS") && (u[2][1] != ".svn")) ||
00238         (is_or (u[2]) && is_concat (u[2][1]))))
00239       sep= "\n---\n";
00240     return
00241       compute_style_menu (u[1], kind) * sep *
00242       compute_style_menu (u[2], kind);
00243   }
00244   if (is_concat (u)) {
00245     string dir= upcase_first (as_string (u[1]));
00246     string sub= compute_style_menu (u[2], kind);
00247     if ((dir == "Test") || (dir == "Obsolete") ||
00248        (dir == "CVS") || (dir == ".svn")) return "";
00249     return "(-> \"" * dir * "\" " * sub * ")";
00250   }
00251   if (is_atomic (u)) {
00252     string l  = as_string (u);
00253     if (!ends (l, ".ts")) return "";
00254     l= l(0, N(l)-3);
00255     string cmd ("init-style");
00256     if (kind == 1) cmd= "init-add-package";
00257     if (kind == 2) cmd= "init-remove-package";
00258     return "((verbatim \"" * l * "\") (" * cmd * " \"" * l * "\"))";
00259   }
00260   return "";
00261 }
00262 
00263 object
00264 get_style_menu () {
00265   url sty_u= descendance ("$TEXMACS_STYLE_ROOT");
00266   string sty= compute_style_menu (sty_u, 0);
00267   return eval ("(menu-dynamic " * sty * ")");
00268 }
00269 
00270 object
00271 get_add_package_menu () {
00272   url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
00273   string pck= compute_style_menu (pck_u, 1);
00274   return eval ("(menu-dynamic " * pck * ")");
00275 }
00276 
00277 object
00278 get_remove_package_menu () {
00279   url pck_u= descendance ("$TEXMACS_PACKAGE_ROOT");
00280   string pck= compute_style_menu (pck_u, 2);
00281   return eval ("(menu-dynamic " * pck * ")");
00282 }