https://github.com/kh-bd/interp4j
String interpolation library for Java
https://github.com/kh-bd/interp4j
java library
Last synced: about 1 year ago
JSON representation
String interpolation library for Java
- Host: GitHub
- URL: https://github.com/kh-bd/interp4j
- Owner: kh-bd
- Created: 2021-08-31T17:27:49.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2024-05-27T08:26:17.000Z (about 2 years ago)
- Last Synced: 2025-04-10T00:41:53.544Z (about 1 year ago)
- Topics: java, library
- Language: Java
- Size: 358 KB
- Stars: 10
- Watchers: 3
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Interp4j is a string interpolation library for Java
[](https://github.com/kh-bd/interp4j/actions/workflows/main-tests.yml)
## Why do we need it?
To understand why we need string interpolation and how to use it, consider following example:
We have to implement a function, which can build a short person descriptor.
StringBuilder implementation:
```java
class Greeter {
public String describe(Person person) {
StringBuilder builder = new StringBuilder();
builder.append("Hello! My name is ");
builder.append(person.getName());
builder.append(". I'm ");
builder.append(person.getAge());
return builder.toString();
}
}
```
A lot of code to implement such simple thing. May be `String.format` can help us.
```java
class Greeter {
public String describe(Person person) {
String template = "Hello! My name is %s. I'm %d";
return String.format(template, person.getName(), person.getAge());
}
}
```
Better, but we can do even better. String interpolation can help us to write such code in a nicer and shorter way.
```java
class Greeter {
public String describe(Person person) {
return s("Hello! My name is ${person.getName()}. I'm ${person.getAge()}");
}
}
```
## How to use it?
First, you need to add `interp4j-core` dependency to your project. For example, if you use maven, add the following
configuration to your `pom.xml` file:
```xml
dev.khbd.interp4j
interp4j-core
compile
LATEST
```
Now, you can use function from `Interpolations` class in your code. These function are entry point to interpolations.
Second, you need to configure your build tool to run interpolation process before source files compilation.
### `s` interpolator
`s` interpolator is simple. Write down a text and inject any java expression into in `${...}`. If an expression is
a java identifier curly braces can be omitted. For example, `s("Hello, ${person.name}")` or `s("Hello, $name")`.
### `fmt` interpolator
`fmt` interpolator is a replacement for `String.format`. The usage is quite the same as `s` interpolator, but
before each expression valid specifier must be provided. For example, `fmt("Hello, %20.4s${person.name}")`.
All features of `String.format` are supported, but there are several syntactic rules:
- before each expression part a valid specifier must be present
- numeric or implicit indexing are not supported. So `fmt("%1$s${person.name}")` or `fmt("%1$s${person.name}, % version | Latest release |
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `1.8` | [](https://mvnrepository.com/artifact/dev.khbd.interp4j/interp4j/2.0.0_jre1.8) |
| `11` | [](https://mvnrepository.com/artifact/dev.khbd.interp4j/interp4j/2.0.0_jre11) |
| `17` | [](https://mvnrepository.com/artifact/dev.khbd.interp4j/interp4j/2.0.0_jre17) |
| `21` | [](https://mvnrepository.com/artifact/dev.khbd.interp4j/interp4j/2.0.0_jre21) |
## Maven support
To interpolate strings in maven-based projects you have to configure compiler to enable interp4j compiler plugin during
compilation. Add the following configuration to your `pom.xml` file and that's it.
```xml
org.apache.maven.plugins
maven-compiler-plugin
-Xplugin:interp4j
dev.khbd.interp4j
interp4j-processor
LATEST
```
Compiler plugin uses internal jdk api to interpolate string literals and
this api is [strongly encapsulated by default](https://openjdk.org/jeps/403) in jdk 17.
To relax it at compile time configuration should be changed accordingly.
```xml
org.apache.maven.plugins
maven-compiler-plugin
true
-Xplugin:interp4j
-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
dev.khbd.interp4j
interp4j-processor
LATEST
```
Additional exports are needed only for compiling process, resulted code will not be dependent on internal jdk api.
## Gradle support
To interpolate strings in gradle-based projects you have to configure compiler to enable interp4j compiler plugin during
compilation. Add the following configuration to your `build.gradle` file and that's it.
```groovy
dependencies {
compileOnly group: 'dev.khbd.interp4j', name: 'interp4j-core', version: interp4j_version
annotationProcessor group: 'dev.khbd.interp4j', name: 'interp4j-processor', version: interp4j_version
}
task.withType(JavaCompile) {
options.fork = true
options.compilerArgs.add('-Xplugin:interp4j')
}
```
If you use jdk 17 or higher additional options are required to allow compiler plugin
to use internal jdk api.
```groovy
dependencies {
compileOnly group: 'dev.khbd.interp4j', name: 'interp4j-core', version: interp4j_version
annotationProcessor group: 'dev.khbd.interp4j', name: 'interp4j-processor', version: interp4j_version
}
task.withType(JavaCompile) {
options.fork = true
options.compilerArgs.add('-Xplugin:interp4j')
options.forkOptions.jvmArgs.addAll([
'--add-exports', 'jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
'--add-exports', 'jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
'--add-exports', 'jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
'--add-exports', 'jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED'
])
}
```
Additional exports are needed only for compiling process, resulted code will not be dependent on internal jdk api.
## Intellij support
To support `interp4j` by intellij, install
[interp4j-intellij-plugin](https://github.com/kh-bd/interp4j-intellij-plugin).
## How to look at modified source code?
To look at modified source code after interpolation, set flag `prettyPrint.after.interpolation` to `true`. For example,
for maven-based projects it can look like that:
```xml
maven-compiler-plugin
-Xplugin:interp4j prettyPrint.after.interpolation=true
...
```
By default, this feature is disabled.
## Benchmarks
All benchmarks were run on:
- Machine: MacBook Pro 2023
- Processor: Apple M2 Max
- Memory: 32 GB LPDDR5
See latest benchmark
result [here](https://jmh.morethan.io/?source=https://raw.githubusercontent.com/kh-bd/interp4j/main/readme/beanchmark/jmh_v1.1.0_j21.json)
.
As you can see, compile time interpolation is about 10 times faster then `String.format`
and at the same time as fast as manual string concatenation. Benchmarks source code can
be found in `interp4j-benchmark` module.
### Run benchmarks on your own machine
To run benchmarks do several steps:
- pull project to your machine
- run from root directory `mvn package -Pbenchmark`
- go to `interp4j-benchmark/target` directory. `interp4j-benchmark-${version}-jar-with-dependencies.jar` should be
generated
- run
command `java -cp ./interp4j-benchmark-${version}-jar-with-dependencies.jar dev.khbd.interp4j.benchmark.BenchmarkRunner -rf json`
- `jmh-result.json` report should be generated
- view it through [jmh visualizer](https://jmh.morethan.io/)