All Projects → ainslec → picocog

ainslec / picocog

Licence: Apache-2.0 license
A tiny code generation library (< 8 KB) written in Java, useful for any purpose, but ideal for JSR-269

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to picocog

CodegenCS
C# Toolkit for Code Generation (T4 alternative!)
Stars: ✭ 119 (+45.12%)
Mutual labels:  template-engine, codegeneration
Sodajs
Light weight but powerful template engine for JavaScript
Stars: ✭ 240 (+192.68%)
Mutual labels:  template-engine
Express Es6 Template Engine
Rendering engine for Express that uses ES6 javascript string templates as syntax.
Stars: ✭ 175 (+113.41%)
Mutual labels:  template-engine
Fatfree
A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!
Stars: ✭ 2,504 (+2953.66%)
Mutual labels:  template-engine
Gotemplatebenchmark
comparing the performance of different template engines
Stars: ✭ 180 (+119.51%)
Mutual labels:  template-engine
Jte
jte is a secure and lightweight template engine for Java.
Stars: ✭ 228 (+178.05%)
Mutual labels:  template-engine
Diamond
Diamond is a full-stack web-framework written in The D Programming Language using vibe.d
Stars: ✭ 173 (+110.98%)
Mutual labels:  template-engine
sempare-delphi-template-engine
Sempare Template Engine for Delphi allows for flexible dynamic text generation. It can be used for generating email, html, source code, xml, configuration, etc.
Stars: ✭ 79 (-3.66%)
Mutual labels:  template-engine
Eta
Embedded JS template engine for Node, Deno, and the browser. Lighweight, fast, and pluggable. Written in TypeScript
Stars: ✭ 233 (+184.15%)
Mutual labels:  template-engine
Ructe
Rust Compiled Templates with static-file handling
Stars: ✭ 206 (+151.22%)
Mutual labels:  template-engine
React Ssr
React SSR as a view template engine
Stars: ✭ 200 (+143.9%)
Mutual labels:  template-engine
Thymeleaf
Thymeleaf is a modern server-side Java template engine for both web and standalone environments.
Stars: ✭ 2,251 (+2645.12%)
Mutual labels:  template-engine
Pupa
Simple micro templating
Stars: ✭ 231 (+181.71%)
Mutual labels:  template-engine
Microconfig
Modern tool for microservice configuration management
Stars: ✭ 180 (+119.51%)
Mutual labels:  template-engine
Sailfish
Simple, small, and extremely fast template engine for Rust
Stars: ✭ 242 (+195.12%)
Mutual labels:  template-engine
Quicktemplate
Fast, powerful, yet easy to use template engine for Go. Optimized for speed, zero memory allocations in hot paths. Up to 20x faster than html/template
Stars: ✭ 2,287 (+2689.02%)
Mutual labels:  template-engine
Yarte
Yarte stands for Yet Another Rust Template Engine
Stars: ✭ 189 (+130.49%)
Mutual labels:  template-engine
Flexml
🚀基于Litho的Android高性能动态业务容器。
Stars: ✭ 225 (+174.39%)
Mutual labels:  template-engine
abell-renderer
A template engine that lets you write variables, loops, and conditions in HTML using JavaScript Syntax.
Stars: ✭ 42 (-48.78%)
Mutual labels:  template-engine
Jade
Jade.go - pug template engine for Go (golang)
Stars: ✭ 251 (+206.1%)
Mutual labels:  template-engine

Picocog

1. Intro

Picocog is a tiny library for use in formatting text programatically (indents and placeholders) for the purposes of source code generation.

Picocog’s only purpose is to output indented text, don’t expect anything fancier than that. Picocog supports deferred writing, indentation and not much more.

The initial release is just 6K. Size doesn’t matter.

2. Maven dependency

(see GWT section for additional GWT dependency)

   <dependency>
      <groupId>org.ainslec</groupId>
      <artifactId>picocog</artifactId>
      <version>1.0.7</version>
   </dependency>

3. Sample Usage

3.1. Basic

The basic example simply demonstrates indentation.

Generator Source
PicoWriter w = new PicoWriter();

w.writeln("int foo = calcFoo();");
w.writeln("");
w.writeln("// We shall dance here");
w.writeln_r("if (foo == 0) {");
w.writeln("sayHello();");
w.writeln_lr("} else if (foo < 100) {");
w.writeln("sayGoodbye();");
w.writeln_lr("} else {");
w.writeln("sayAnything();");
w.writeln_l("}");

System.out.println(w.toString());
Generated Source
int foo = calcFoo();

// We shall dance here
if (foo == 0) {
   sayHello();
} else if (foo < 100) {
   sayGoodbye();
} else {
   sayAnything();
}
Note
Adding in comments, even silly ones, is extremely important when generating sourcecode. They act as markers so that it is easy to locate the corresponding code generator code.

3.2. Advanced

This example demonstrates out of sequence writing (deferrals).

A deferral can be placed within the write stream, and then can be used to insert code at the reservation point. The point at which the call to createDeferredWriter() is called is significant. Indentation levels are inherited.

This is useful where there are blocks of code in different parts of the source that need to be updated at the same time.

Although not demonstrated here, it is possible to create deferrals within deferrals using the same API.

Generator Source
  // This is our top level source formatter
  PicoWriter topWriter = new PicoWriter();

  String myPackageName = "com.samplepackage";
  String myClassName   = "MyClass";

  topWriter.writeln ("package " + myPackageName + ";");
  topWriter.writeln ("");
  topWriter.writeln_r ("public class "+myClassName+" {");

  PicoWriter memvarWriter    = topWriter.createDeferredWriter();
  topWriter.writeln_r ("{");
  PicoWriter indentedSection = topWriter.createDeferredWriter();
  topWriter.writeln_l ("}");
  topWriter.writeln("");

  // Reserve a place at the current row
  PicoWriter methodSection = topWriter.createDeferredWriter();

  memvarWriter.writeln("String myString = null;" );
  indentedSection.writeln("// Contents of the indented section (1)");
  memvarWriter.writeln("String myString2 = null;" );
  indentedSection.writeln("// Contents of the indented section (2)");

  // Reserve a place at the current row
  PicoWriter mainMethod = methodSection.createDeferredWriter();

  mainMethod.writeln_r("public static void main(String[] args) {");
  mainMethod.writeln_r("if (args.length == 0) {");
  mainMethod.writeln("System.out.println(\"Require more than one argument\");");
  mainMethod.writeln_lr("} else if (args.length == 1) {");
  mainMethod.writeln("doSomething();");
  mainMethod.writeln_lr("} else {");
  mainMethod.writeln("System.out.println(\"Too many arguments\");");
  mainMethod.writeln_l("}");
  mainMethod.writeln_l("}");
  mainMethod.writeln("");
  topWriter.writeln_l ("}");

  // To extract the source code, call .toString()
  System.out.println(topWriter.toString());
Generated Source
package com.samplepackage;

public class MyClass {
   String myString = null;
   String myString2 = null;
   {
      // Contents of the indented section (1)
      // Contents of the indented section (2)
   }

   public static void main(String[] args) {
      if (args.length == 0) {
         System.out.println("Require more than one argument");
      } else if (args.length == 1) {
         doSomething();
      } else {
         System.out.println("Too many arguments");
      }
   }

}

4. FAQ

4.1. Why not use a templating library?

It’s highly subjective but generating sourcecode using Java code is much easier to debug imho. There is almost no learning curve, and anyone can debug.

Templates can be easier to read, but they can also be very complex, and involve reflection, something which makes debugging difficult.

With Java based code generation, you control everything, and you understand everything.

A Template (Velocity) is generally better for shallow complexity, programatic code generation (Picocog, Java Poet) is better for deep complexity.

4.2. How do I escape JSON/XML/YAML/Java text?

It’s a slippery slope, so Picoclogs ships with no text escaping utility methods.

If you want to escape common text formats, the following library is useful:

4.3. Alternatives

Some alternative technologies.

Warning
Some of these products are over 16 Kilobytes in size.

4.3.1. Java Code Based

4.3.2. Template Based

4.3.3. Articles

4.4. JSR 269

Picocog can come in useful for iterating over annotations on source code, and from those annotations, generating new source code.

Of course, you can do this without Picocog too, but Picocog is tailor-made for this kind of use-case.

See :

4.5. GWT

Picocog is compatible with client-side GWT.

To use Picocog in your client side code:

1a - For non maven projects, make sure picocog source code is on your classpath.
1b - For maven projects, add the following dependency to your GWT Client POM (GWT requires source code + module gwt.xml):

   <dependency>
      <groupId>org.ainslec</groupId>
      <artifactId>picocog</artifactId>
      <version>1.0.7</version>
      <classifier>sources</classifier>
   </dependency>

2 - Add the following line to your client project .gwt.xml file:

<inherits name='org.ainslec.picocog.Picocog'/>

5. Tips / Tricks

  • It helps to create a bunch of deferrals straight away.

  • Always match indents at point of writing. Never wait to match an indent.

  • Always generate distinctive comments in your generated source - these act as anchors for debugging your source code generator.

  • Always use the writeln_lr for '} else if (…​) {' lines.

  • Be aware of the escaping requirements of the language for which you are generating sourcecode.

  • Store commonly use strings in member variables and/or constants.

  • If you have access to the API at code generation time for which you are generating source for, make use of the YourApiClass.class.getName() method call. This will make sure that your code generator will automatically cope with class name refactoring.

  • If you are nice to other people, they tend to act nicer towards you.

6. Contact

Email : [email protected]
Follow me : @ainslec

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].