Showing posts with label Groovy. Show all posts
Showing posts with label Groovy. Show all posts

Saturday, October 29, 2016

oh Google, O Alphabets !

This is my untagged Facebook post today:

Yes, some followers do not know what Microsoft calls "Azure" or that an Amazon makes profits on Web Services for cloud storage or that Google is owned by Alphabet.
Bill Gates owns the art.
Google does NOT own the alphabet as THAT is in Unicode Version 9 which is NOT Plan 9 which is another obscure reference only to amuse someone who does not follow me anyway.

Thursday, October 15, 2009

curlgen with Groovy BuilderSupport: CurlBuilder for Curl web content markup

Because the Groovy MarkupBuilder has a private method which hardcodes the markup delimiters, a CurlBuilder must extend BuilderSupport just as does MarkupBuilder itself.

What follows looks to be roughly a builder candidate for Curl web content markup using "{" and "}" as the delimiters.  As with XHTML, the Curl content may require a 'prolog' and a few non-hierarchical items comparable to the !DOCTYPE of XML.  Web markup is often more than simply a hierarchy of nested nodes.
/**
* A helper class for creating Curl markup
* borrowed from http://docs.codehaus.org/display/GROOVY/Make+a+builder
* original MarkupBuilder by James Strathan
* mods by RS
*/
public class CurlBuilder extends BuilderSupport {

private IndentPrinter out;
private boolean nospace;
private int state;
private boolean nodeIsEmpty = true;

public CurlBuilder() {
  this(new IndentPrinter());
}

public CurlBuilder(PrintWriter writer) {
  this(new IndentPrinter(writer));
}

public CurlBuilder(Writer writer) {
  this(new IndentPrinter(new PrintWriter(writer)));
}

public CurlBuilder(IndentPrinter out) {
  this.out = out;
}

protected void setParent(Object parent, Object child) {
}

protected Object createNode(Object name) {
  toState(1, name);
  return name;
}

protected Object createNode(Object name, Object value) {
  toState(2, name);
// out.print(">");
  out.print(value.toString());
  return name;
}

protected Object createNode(Object name, Map attributes, Object value) {
  toState(1, name);
  for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
    Map.Entry entry = (Map.Entry) iter.next();
    out.print(" ");
    print(transformName(entry.getKey().toString()));
    out.print("='");
    print(transformValue(entry.getValue().toString()));
    out.print("'");
  }
  if (value != null)
  {
    nodeIsEmpty = false;
    out.print(" " + value + "}");
  }
  return name;
}

protected Object createNode(Object name, Map attributes) {
  return createNode(name, attributes, null);
}

protected void nodeCompleted(Object parent, Object node) {
  toState(3, node);
  out.flush();
}

protected void print(Object node) {
  out.print(node == null ? "null" : node.toString());
}

protected Object getName(String methodName) {
  return super.getName(transformName(methodName));
}

protected String transformName(String name) {
  if (name.startsWith("_")) name = name.substring(1);
    return name.replace('_', '-');
}

protected String transformValue(String value) {
  return value.replaceAll("\\'", """); }

protected void toState(int next, Object name) {
  switch (state) {
    case 0:
      switch (next) {
        case 1:
        case 2:
          out.print("{");
          print(name);
          break;
        case 3:
         throw new Error();
      }
      break;
    case 1:
      switch (next) {
        case 1:
        case 2:
          out.print(" ");
          if (nospace) {
            nospace = false;
          } else {
            out.println();
            out.incrementIndent();
            out.printIndent();
          }
          out.print("{");
          print(name);
          break;
        case 3:
          if (nodeIsEmpty) {
            out.print(" }");
          }
          break;
        }
        break;
      case 2:
        switch (next) {
          case 1:
          case 2:
            throw new Error();
          case 3:
            out.print(" }");
            break;
        }
        break;
      case 3:
        switch (next) {
          case 1:
          case 2:
            if (nospace) {
              nospace = false;
            } else {
              out.println();
              out.printIndent();
            }
            out.print("{");
            print(name);
            break;
          case 3:
            if (nospace) {
              nospace = false;
            } else {
              out.println();
              out.decrementIndent();
              out.printIndent();
            }
            out.print(" }");
            break;
        }
        break;
     }
     state = next;
   }
}
That could have been so elegant if the MarkupBuilder class had understood markup itself as a pattern rather than hard-coding the SGML-style tag delimiters and assuming the tagging style (close before content, reopen after content.)

The ability to inject a markup builder for non-SGML markup for an entire site is lost: we still have to look into such things as 404 and 500 errors because we have only covered where we explicitly instantiate a builder.  DI should have solved that web container-wide.

As I never tire of saying, when we get beyond HTML5 and the mere browser, this SGML-bias will look like an unquestioned assumption as curious as any other in the history of data format oddities and over-sights.

To get from   <br/>  to {br} should not be a coding intervention task of this magnitude or this nature.

Thursday, September 13, 2007

Cool Curl 'live' code widget

Over at eclectic-pencil I have a post on a very cool Curl widget that rivals almost anything I have ever seen expand and collapse on a web page.

What I neglect to mention is that in the example, the only code to create the XMl tree is this:
   let xmldoc:XDMDocument =
{build-xml preserve-whitespace? = false, loc}
|| ...
{XDMTreeControl open? = true, xmldoc.root}

Which you would be hard-pressed to beat in Seaside for Smalltalk or in Groovy. Concise.

TiScript also has an alternative DOM and some nice features as a JavaScript alternative, but Curl 5.0 is a mature, full RIA product with 'live' code for inspection and a focus on the client-side. It is almost Smalltalk but it was also built for the web (in fairness, Curl goes about as far back as Smalltalk VisualWave.)

The only cool but alive technologies as neglected as Curl 5.0 must be Gemstone/S and Rebol 2.6.3 ... and the latter is soon to be 2.7.x with 3.0 in the wings ...

Watch for a Seaside for Gemstone/S beta in the news soon ...

PS For people living on AIR and FLASH, Rebol/FLASH went 2.0 today ...

Friday, August 24, 2007

Rebol dialects and Groovy builders

I am working on a blog post over at eclectic-pencil on DSL (domain-specific languages) in Rebol and Groovy. It is an area that the folks at PDC Prolog got into a few years back and that I first explored using Java + Amzi! Prolog with DCG's in Eclipse. I hope to get a piece up on Groovy and categories as mix-ins in comparison to exploring categories and protocols in Logtalk. In the meantime there is a great deal of activity on the SWI-Prolog mailing list often relating to their Java programming interface. And Plone has a new release just as I wait for Rebol3. And I have a new version of the Curl 5.0 Web SDK to check out. And the MindTouch Deki-Wiki up on VMWare as I watch for the Gemstone/S + Seaside beta. Too much!
My opinion of the out-of-print 'Official Guide' to Rebol 2.3 keeps improving: I wish I could say the same of Manning's 'Groovy In Action' or the APress 'Grails' book. Neither of my favorite bookstores had 'Programming Groovy' on the shelves, which might have been a better choice than the former. Of course there is no book on Logtalk to recommend ... yet.

Tuesday, August 7, 2007

GRAILS and Groovy tip

If you try out groovy Grails on Windows as an open-source web application framework, I suggest you install it as a sub-directory of your Groovy directory.
You will want to knwo that your groovy is running fine: in my case I added
set CLASSPATH=I:\groovy-1.0\groovy-1.0.jar;%CLASSPATH%
to my groovy-1.0\bin\groovyConsole.bat I also have three ENV variables defined: GROOVY_HOME, GROOVY_JAR and GRAILS_HOME and both HOME var's are in my path with \bin appended to them.

With that done, you can go into the Grails bin and edit the
grails.bat
I think that there is no point avoiding at least this much:
set CLASSPATH=
because even with my own classpath tool it is just too much grief. Grails does not need your classpath but having one is a problem. The top of my grails.bat now reads
REM set groovy_home=I:\groovy-1.0
REM set GRAILS_HOME=%GROOVY_HOME%\grails-0.5.6
REM set path=%groovy_home%\bin;%grails_home%\bin;%PATH%
REM set GROOVY_JAR=groovy-1.0.jar
set classpath=
To test that things are running start in the grails\bin with
grails help
which should run error-free and list the grails commands. From there you should be OK following the Grails Quick Start steps. Until help comes up error-free, you have an issue.

One last tip: Grails will create your web app root directory in the directory you are in at the time you execute
grails create-app
which in my case is running
I:\groovy-1.0\grails-0.5.6\scripts\CreateApp.groovy
so you do not want to be in .\grails\bin on your command line. If you have not installed the Microsoft Power Toy Open Command Window which launches CMD.exe from any folder in the file explorer, you will want to do so ... whether you are using Grails or Rails without an IDE.