{"id":40594925,"url":"https://github.com/ainslec/picocog","last_synced_at":"2026-01-21T03:36:33.082Z","repository":{"id":46153463,"uuid":"88739742","full_name":"ainslec/picocog","owner":"ainslec","description":"A tiny code generation library (\u003c 8 KB) written in Java, useful for any purpose, but ideal for JSR-269","archived":false,"fork":false,"pushed_at":"2021-11-10T20:33:25.000Z","size":52,"stargazers_count":87,"open_issues_count":3,"forks_count":19,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-20T12:25:18.520Z","etag":null,"topics":["codegeneration","gwt","java","jsr269","template-engine"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ainslec.png","metadata":{"files":{"readme":"README.asc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-19T12:00:31.000Z","updated_at":"2024-01-13T23:56:38.000Z","dependencies_parsed_at":"2022-08-25T01:31:06.876Z","dependency_job_id":null,"html_url":"https://github.com/ainslec/picocog","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ainslec/picocog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainslec%2Fpicocog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainslec%2Fpicocog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainslec%2Fpicocog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainslec%2Fpicocog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ainslec","download_url":"https://codeload.github.com/ainslec/picocog/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainslec%2Fpicocog/sbom","scorecard":{"id":173169,"data":{"date":"2025-08-11","repo":{"name":"github.com/ainslec/picocog","commit":"d88e9f19c2e4d337f6ad7af875c35c225c4525a8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 1/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T17:05:52.262Z","repository_id":46153463,"created_at":"2025-08-16T17:05:52.262Z","updated_at":"2025-08-16T17:05:52.262Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28624563,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T02:47:06.670Z","status":"ssl_error","status_checked_at":"2026-01-21T02:45:44.886Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codegeneration","gwt","java","jsr269","template-engine"],"created_at":"2026-01-21T03:36:32.175Z","updated_at":"2026-01-21T03:36:33.077Z","avatar_url":"https://github.com/ainslec.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Picocog\nChris Ainsley\n:doctype: book\n:encoding: utf-8\n:lang: en\n:toc: left\n:toclevels: 3\n:numbered:\n:hardbreaks:\n:tabledef-default.subs: normal,callouts \n\n== Intro\n\nPicocog is a tiny library for use in formatting text programatically (indents and placeholders) for the purposes of source code generation.\n\nPicocog's only purpose is to output indented text, don't expect anything fancier than that. Picocog supports deferred writing, indentation and not much more.\n\nThe initial release is just 6K. Size doesn't matter.\n\n== Maven dependency\n\n(see GWT section for additional GWT dependency)\n\n[source,xml]\n-----\n   \u003cdependency\u003e\n      \u003cgroupId\u003eorg.ainslec\u003c/groupId\u003e\n      \u003cartifactId\u003epicocog\u003c/artifactId\u003e\n      \u003cversion\u003e1.0.7\u003c/version\u003e\n   \u003c/dependency\u003e\n-----\n\nJar download available here : https://repo1.maven.org/maven2/org/ainslec/picocog/1.0.7/picocog-1.0.7.jar\n\n== Sample Usage\n\n=== Basic\n\nThe basic example simply demonstrates indentation.\n\n.Generator Source\n[source,java]\n-----\nPicoWriter w = new PicoWriter();\n\nw.writeln(\"int foo = calcFoo();\");\nw.writeln(\"\");\nw.writeln(\"// We shall dance here\");\nw.writeln_r(\"if (foo == 0) {\");\nw.writeln(\"sayHello();\");\nw.writeln_lr(\"} else if (foo \u003c 100) {\");\nw.writeln(\"sayGoodbye();\");\nw.writeln_lr(\"} else {\");\nw.writeln(\"sayAnything();\");\nw.writeln_l(\"}\");\n\nSystem.out.println(w.toString());\n-----\n\n\n.Generated Source\n[source,java]\n-----\nint foo = calcFoo();\n\n// We shall dance here\nif (foo == 0) {\n   sayHello();\n} else if (foo \u003c 100) {\n   sayGoodbye();\n} else {\n   sayAnything();\n}\n-----\n\nNOTE: 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.\n\n=== Advanced\n\nThis example demonstrates out of sequence writing (deferrals).\n\nA 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.\n\nThis is useful where there are blocks of code in different parts of the source that need to be updated at the same time.\n\nAlthough not demonstrated here, it is possible to create deferrals within deferrals using the same API.\n\n.Generator Source\n[source,java]\n-----\n  // This is our top level source formatter\n  PicoWriter topWriter = new PicoWriter();\n  \n  String myPackageName = \"com.samplepackage\";\n  String myClassName   = \"MyClass\";\n  \n  topWriter.writeln (\"package \" + myPackageName + \";\");\n  topWriter.writeln (\"\");\n  topWriter.writeln_r (\"public class \"+myClassName+\" {\");\n  \n  PicoWriter memvarWriter    = topWriter.createDeferredWriter();\n  topWriter.writeln_r (\"{\");\n  PicoWriter indentedSection = topWriter.createDeferredWriter();\n  topWriter.writeln_l (\"}\");\n  topWriter.writeln(\"\");\n  \n  // Reserve a place at the current row\n  PicoWriter methodSection = topWriter.createDeferredWriter();\n  \n  memvarWriter.writeln(\"String myString = null;\" );\n  indentedSection.writeln(\"// Contents of the indented section (1)\");\n  memvarWriter.writeln(\"String myString2 = null;\" );\n  indentedSection.writeln(\"// Contents of the indented section (2)\");\n  \n  // Reserve a place at the current row\n  PicoWriter mainMethod = methodSection.createDeferredWriter();\n  \n  mainMethod.writeln_r(\"public static void main(String[] args) {\");\n  mainMethod.writeln_r(\"if (args.length == 0) {\");\n  mainMethod.writeln(\"System.out.println(\\\"Require more than one argument\\\");\");\n  mainMethod.writeln_lr(\"} else if (args.length == 1) {\");\n  mainMethod.writeln(\"doSomething();\");\n  mainMethod.writeln_lr(\"} else {\");\n  mainMethod.writeln(\"System.out.println(\\\"Too many arguments\\\");\");\n  mainMethod.writeln_l(\"}\");\n  mainMethod.writeln_l(\"}\");\n  mainMethod.writeln(\"\");\n  topWriter.writeln_l (\"}\");\n  \n  // To extract the source code, call .toString()\n  System.out.println(topWriter.toString());\n-----\n\n.Generated Source\n[source,java]\n-----\npackage com.samplepackage;\n\npublic class MyClass {\n   String myString = null;\n   String myString2 = null;\n   {\n      // Contents of the indented section (1)\n      // Contents of the indented section (2)\n   }\n   \n   public static void main(String[] args) {\n      if (args.length == 0) {\n         System.out.println(\"Require more than one argument\");\n      } else if (args.length == 1) {\n         doSomething();\n      } else {\n         System.out.println(\"Too many arguments\");\n      }\n   }\n   \n}\n-----\n\n== FAQ\n\n=== Why not use a templating library?\n\nIt'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.\n\nTemplates can be easier to read, but they can also be very complex, and involve reflection, something which makes debugging difficult.\n\nWith Java based code generation, you control everything, and you understand everything.\n\nA Template (Velocity) is generally better for shallow complexity, programatic code generation (Picocog, Java Poet) is better for deep complexity.\n\n=== How do I escape JSON/XML/YAML/Java text?\n\nIt's a slippery slope, so Picoclogs ships with no text escaping utility methods.\n\nIf you want to escape common text formats, the following library is useful:\n\nhttps://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html[Commons Escape Utils]\n\n=== Alternatives\n\nSome alternative technologies.\n\nWARNING: Some of these products are over 16 Kilobytes in size.\n\n==== Java Code Based\n\n* https://github.com/square/javapoet[Java Poet]\n\n==== Template Based\n* http://freemarker.org/[FreeMarker]\n* http://velocity.apache.org/[Apache Velocity]\n\n==== Articles\n* https://medium.com/@model_train/introducing-picocog-68de4978eaf4[Introducing Picocog]\n\n=== JSR 269\n\nPicocog can come in useful for iterating over annotations on source code, and from those annotations, generating new source code.\n\nOf course, you can do this without Picocog too, but Picocog is tailor-made for this kind of use-case.\n\nSee : \n\n* https://jcp.org/aboutJava/communityprocess/final/jsr269/index.html[JSR 269 Spec]\n* https://www.youtube.com/watch?v=ggxy1vS79CE[Pluggable Annotation Processing API and GWT]\n\n=== GWT\n\nPicocog is compatible with client-side https://http://www.gwtproject.org[GWT].\n\nTo use Picocog in your client side code:\n\n1a - For non maven projects, make sure picocog source code is on your classpath.\n1b - For maven projects, add the following dependency to your GWT Client POM (GWT requires source code + module gwt.xml):\n\n[source,xml]\n-----\n   \u003cdependency\u003e\n      \u003cgroupId\u003eorg.ainslec\u003c/groupId\u003e\n      \u003cartifactId\u003epicocog\u003c/artifactId\u003e\n      \u003cversion\u003e1.0.7\u003c/version\u003e\n      \u003cclassifier\u003esources\u003c/classifier\u003e\n   \u003c/dependency\u003e\n-----\n\n2 - Add the following line to your client project .gwt.xml file:\n\n[source,xml]\n-----\n\u003cinherits name='org.ainslec.picocog.Picocog'/\u003e\n-----\n\n== Tips / Tricks\n\n* It helps to create a bunch of deferrals straight away.\n* Always match indents at point of writing. Never wait to match an indent.\n* Always generate distinctive comments in your generated source - these act as anchors for debugging your source code generator.\n* Always use the writeln_lr for '} else if (...) {' lines.\n* Be aware of the escaping requirements of the language for which you are generating sourcecode.\n* Store commonly use strings in member variables and/or constants.\n* 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.\n* If you are nice to other people, they tend to act nicer towards you.\n\n== Contact\n\nEmail   : c.b.ainsley@gmail.com\nFollow me : https://twitter.com/ainslec[@ainslec]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fainslec%2Fpicocog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fainslec%2Fpicocog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fainslec%2Fpicocog/lists"}