roxen.lists.roxen.general

Subject Author Date
[PATCH 15/17] New module: controlled variable expansion Stephen R. van den Berg <srb[at]cuci[dot]nl> 20-01-2009
---

 server/modules/tags/expandvariables.pike |  146 ++++++++++++++++++++++++++++++
 1 files changed, 146 insertions(+), 0 deletions(-)
 create mode 100644 server/modules/tags/expandvariables.pike

diff --git a/server/modules/tags/expandvariables.pike
b/server/modules/tags/expandvariables.pike
new file mode 100644
index 0000000..eaf5fe6
--- /dev/null
+++ b/server/modules/tags/expandvariables.pike
@@ -0,0 +1,146 @@
+// This is a roxen module which provides controlled variable expansion
+// capabilities.
+// Copyright (c) 2004-2009, Stephen R. van den Berg, The Netherlands.
+//                     <<srb[at]cuci.nl>>
+//
+// This module is open source software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation; either version 2, or (at your option) any
+// later version.
+//
+
+//<locale-token project="mod_expandvariables">_</locale-token>
+#define _(X,Y)  _DEF_LOCALE("mod_expandvariables",X,Y)
+
+constant thread_safe = 1;
+
+#include <module.h>
+
+inherit "module";
+
+// ---------------- Module registration stuff ----------------
+
+constant module_type = MODULE_TAG;
+LocaleString module_name = _(1,"Tags: Expand variables");
+LocaleString module_doc  = _(2,
+ "This module provides the expand-variables RXML tag.<br />"
+ "<p>Copyright &copy; 2004-2009, by "
+ "<a href='mailto:<srb[at]cuci.nl>'>Stephen R. van den Berg</a>, "
+ "The Netherlands.</p>"
+ "<p>This module is open source software; you can redistribute it and/or "
+ "modify it under the terms of the GNU General Public License as published "
+ "by the Free Software Foundation; either version 2, or (at your option) any "
+ "later version.</p>");
+
+void create()
+{
+  set_module_creator("Stephen R. van den Berg <<srb[at]cuci.nl>>");
+}
+
+static mapping(string:int) replacecounts=([]);
+
+string status() {
+  string s="<tr><td colspan=2>None yet</td></tr>";
+  if(sizeof(replacecounts))
+  { s="";
+    foreach(sort(indices(replacecounts)),string scope)
+      s+=sprintf("<tr><td>%s</td><td align=right>%d</td></tr>",
+       scope,replacecounts[scope]);
+  }
+  return _(5,"<table border=1><tr><th>Scope</th><th>Substitutions</th></tr>"+
+   s+"</table>");
+}
+
+#define IS(arg) ((arg) && sizeof(arg))
+
+// ------------------- Containers ----------------
+
+class TagExpandVariables
+{
+  inherit RXML.Tag;
+  constant name = "expand-variables";
+
+  mapping(string:RXML.Type) req_arg_types = ([
+  ]);
+  mapping(string:RXML.Type) opt_arg_types = ([
+   "scope":RXML.t_text(RXML.PEnt),
+   "from":RXML.t_text(RXML.PEnt),
+  ]);
+
+  class Frame
+  {
+    inherit RXML.Frame;
+
+    array do_return(RequestID id)
+    {
+      RXML.Context ctx = RXML_CONTEXT;
+      multiset scope;
+      result = IS(args->from)?ctx->user_get_var(args->from):content||"";
+
+      if(IS(args->scope))
+        scope = mkmultiset(args["scope"]/",");
+      Parser.HTML p = Parser.HTML();
+      //p->mixed_mode(1); DO NOT USE THIS, mayhem lies ahead
+      p->ignore_tags(1);
+      p->lazy_entity_end(1);
+      p->_set_entity_callback(lambda(Parser.HTML p,string ent)
+        { int i;
+          string s=p->tag_name();
+          if((i=search(s,"."))<1)
+            return 0;			     // exit early if no scope present
+          string cscope=s[..i-1];
+          s=s[i+1..];
+          if(scope)
+          { if(!scope[cscope])
+              return cscope[0]==':'
+	       && 2==sscanf(cscope,":%*[:]%[^:]",cscope)
+               && scope[cscope]?():0; // strip one colon per pass
+          }
+          else if(!ctx->get_scope(cscope))
+             return cscope[0]==':'?():0;
+          else if(2!=sscanf(s+";;","%*[-.:a-zA-Z0-9];%*c"))
+             return 0;
+          string encoding;
+          sscanf(s,"%[^:]:%s",s,encoding);
+          array splitted=ctx->parse_user_var(s,cscope);
+          s=ctx->get_var(splitted[1..],cscope)||"";
+          replacecounts[cscope]++;
+          return ();
+        });
+
+      if(!stringp(result))
+	if(!arrayp(result))
+	  result = "";
+      result=p->finish(result)->read();
+
+      return 0;
+    }
+  }
+}
+
+// --------------------- Documentation -----------------------
+
+TAGDOCUMENTATION;
+#ifdef manual
+constant tagdoc=([
+"expand-variables":#"<desc type='cont'><p><short hide='hide'>
+ Expand certain scopes only.</short>The &lt;expand-variables&gt;
+ tag allows one to specify which scopes to parse and expand, while
+ leaving all other entities and tags untouched.</p>
+<p>
+ The tag is intended for situations where external data needs to be parsed
+ for certain entities only, not affecting RXML code nor other
+ entities/variables.
+</p></desc>
+
+<attr name='scope' value='list'><p>
+ Comma-separated array of scopes to expand.  If omitted, all known scopes
+ are parsed and replaced.</p>
+</attr>
+
+<attr name='from'><p>
+ Variable to use as source instead of the content of the container.</p>
+</attr>
+",
+    ]);
+#endif