Custom Postfix Templates is an Intellij IDEA plugin that allows you to define your own custom postfix completion templates. At the moment it supports the following programming languages with : Java, Scala, SQL, PHP, Go, Groovy, Python, LaTeX, Kotlin (untyped templates), Dart (untyped templates), JavaScript (untyped templates), and Rust (untyped templates).
Since IDEA 2018 you are now able to define your own postfix templates in the settings UI (Editor → General → Postfix Templates). However, this is a pretty new feature and it's less functional than this plugin. Here are some of the advantages of this plugin:
$varName$
) which are filled by the user while applying the template.$var:suggestVariableName()$
) as well as you can define default values."test".val
to val s = "test"
if Lombok is available).array.toList
can be expanded to asList(array)
instead of Arrays.asList(array)
if you add [USE_STATIC_IMPORTS]
to the rule).string.toInt
→ Integer.parse(string)
array.toList
→ Arrays.asList(array)
file.lines
→ Files.readAllLines(file.toPath(), Charset.forName("UTF-8"))
file.getName().val
→ final String name = file.getName();
You can download the plugin Custom Postfix Templates via Settings → Plugins → Browse Repositories.
The plugin comes with a predefined set of templates for Java and Scala (see below) which can be immediatly applied in Java/Scala files. For instance, write
"1".toInt
in a Java file. If the completion popup does not automatically show up, press Ctrl+SPACE.
Select the .toInt
template and see how it is expanded.
And if you want to see the template definition, just press Alt+ENTER in the completiion popup and select Edit '.toInt' template.
There are three different types of template files:
Template rules are applied in a first-come-first-serve manner, i.e., more specific rules/files should be placed above more general rules/files. Reorder files in the tree by selecting them and by using the up/down buttons.
The plugin comes with a set of so-called "web template files" which provide in total more than 200 useful templates. While web template files are read-only and shall not be edited by the user because of automatic updates, you can still edit or deactivate templates of these files.
To change or deactivate a predefined template you just have to start the template name completion with Ctrl+Space and then press ALT+Enter and select the third item (Edit .TEMPLATE_NAME template). The corresponding web template file is opened and you see the definition of the template rule. Since you cannot this template file directly you have to override the template rule by pressing Alt+Enter and selecting Override template rule. This overriding works in a way that your template rule needs to be loaded before the predefined template gets loaded. This is done by adding your rule to a user template file which is placed above the predefined web template file in the plugin settings. In case that you don't have a user template file which is loaded before, you are offered to create one. After you selected an existing user template or created a new one the template rule to override is automatically added to this file and you can start adapting it. To deactivate a template rule, replace the rigth side of the rule with [SKIP].
Press Shift+Alt+P (or go to menu Tools → Custom Postfix Templates → Edit Templates of Current Language) to open the custom postfix templates for the programming language in your current editor. Here you can easily change, remove, or add new templates matching your needs. Note that you have to save the template file explicitly (via Ctrl+S) in order to update the postfix templates in the IDE.
The file may contain multiple template definitions of the form:
.TEMPLATE_NAME : TEMPLATE_DESCRIPTION
TEMPLATE_RULE1
TEMPLATE_RULE2
...
Each template definition consists of a template name, a template description and an arbitrary number of template rules. The template name is used as key in the code completion and the template description is shown as hint in the code completion popup. The template rules define on which types the template can be applied and how the application is performed.
A simple template rule has the form
MATCHING_TYPE → TEMPLATE_CODE
whereas
MATCHING_TYPE
defines the type the template can be applied to, andTEMPLATE_CODE
defines how the template is applied (how the expression is replaced).The options for MATCHING_TYPE may differ from programming language to programming language:
ANY
- any expressionVOID
- any void expressionNON_VOID
- any non-void expressionARRAY
- any Java arrayBOOLEAN
- boxed or unboxed boolean expressionsITERABLE_OR_ARRAY
- any iterable or arrayNOT_PRIMITIVE
- any non-primitive valueNUMBER
- any boxed or unboxed numberBYTE
- a boxed or unboxed byte valueSHORT
- a boxed or unboxed short valueCHAR
- a boxed or unboxed char valueINT
- a boxed or unboxed int valueLONG
- a boxed or unboxed long valueFLOAT
- a boxed or unboxed float valueDOUBLE
- a boxed or unboxed double valueNUMBER_LITERAL
- any number literalBYTE_LITERAL
- a byte literalSHORT_LITERAL
- a short literalCHAR_LITERAL
- a char literalINT_LITERAL
- an int literalLONG_LITERAL
- a long literalFLOAT_LITERAL
- a float literalDOUBLE_LITERAL
- a double literalSTRING_LITERAL
- a String literalCLASS
- any class referenceANY
- any expressionVOID
- any void (Unit) expressionNON_VOID
- any non-void (non-Unit) expressionBOOLEAN
- scala.Boolean or java.lang.BooleanNUMBER
- any Scala or Java number valueBYTE
- scala.Byte or java.lang.ByteSHORT
- scala.Short or java.lang.ShortCHAR
- scala.Char or java.lang.CharINT
- scala.Int or java.lang.IntegerLONG
- scala.Long or java.lang.LongFLOAT
- scala.Float or java.lang.FloatDOUBLE
- scala.Double or java.lang.DoubleANY
- any expressionUNKNOWN
- unknown expressionDEFAULT
- ?INTEGER
- integer expressionREAL
- real expressionSTRING
- string expressionBOOLEAN
- boolean expressionDATE_TIME
- date-time expressionDATE
- date expressionTIME
- time expressionTIMESTAMP
- timestamp expressionINTERVAL
- interval expressionBYTES
- bytes expressionREFERENCE
- ?ARRAY
- array expressionCOLLECTION
- collection expressionTABLE
- table referenceRECORD
- ?SETO
- ?ANY
- any expressionempty
null
string
boolean
int
float
object
callable
resource
array
iterable
number
void
unset
static
\Closure
\Exception
\Throwable
ANY
- any expressionARRAY
- any arrayBOOLEAN
- any boolean expressionSTRING
- any string expressionINT
- any integer expressionINT64
- any 64 bit integer expressionUINT
- any unsigned integer expressionFLOAT
- any floating point expressionFLOAT32
- any 32 bit floating point expressionFLOAT64
- any 64 bit floating point expressionBYTESLICE
- any byte slice expressionERROR
- any error expressionCOMPLEX
- ???NIL
- any expression of type NilANY
- any expressionARRAY
- any Java arrayBOOLEAN
- boxed or unboxed boolean expressionsITERABLE_OR_ARRAY
- any iterable or arrayNUMBER
- any boxed or unboxed numberBYTE
- a boxed or unboxed byte valueSHORT
- a boxed or unboxed short valueCHAR
- a boxed or unboxed char valueINT
- a boxed or unboxed int valueLONG
- a boxed or unboxed long valueFLOAT
- a boxed or unboxed float valueDOUBLE
- a boxed or unboxed double valueCLASS
- any class referenceANY
- any expressionobject
list
dict
set
tuple
int
float
complex
str
unicode
bytes
bool
classmethod
staticmethod
type
ANY
.ANY
.ANY
.ANY
ANY
- any expression in any contextTEXT
- any expression that is not within a math environmentMATH
- any expression that is within a math environmentThe TEMPLATE_CODE can be any text which may also contain template variables used as placeholder.
$NAME$
.$expr$
- the expression the template shall be applied to$END$
- the final cursor position after the template application$NAME#NO:EXPRESSION:DEFAULT_VALUE$
*
at the end of the name to skip user interactionsuggestVariableName()
)\
) at the end of a line to indicate that the template code continues at the next line..test : test
NON_VOID → "$user*#1:user()$: $second#3:className()$ + $first#2::"1st"$ + $first$" + $expr$
.logd : log a variable
NON_VOID → Log.d("$user*:user():"MyTag"$", "$className*:className()$ :: $methodName*:methodName()$): $expr$="+$expr$);
.for : iterate over ...
ITERABLE_OR_ARRAY → for ($ELEMENT_TYPE:iterableComponentType(expr):"java.lang.Object"$ $VAR:suggestVariableName()$ : $expr$) {\
$END$\
}
While writing the templates you can use the code completion for completing class names, variable names, template macros and arrows (→).
In the chapter above some options have been omitted for simplicity. If you need more functionality here is the full format of template rules including two optional parameters:
MATCHING_TYPE [REQUIRED_CLASS] → TEMPLATE_CODE [FLAG]
SKIP
- skips the ruleUSE_STATIC_IMPORTS
- adds static method imports automatically if possible (Java only)IMPORT
... - adds an import to the file header (Scala only)Sometimes you may want to write library specific template rules, i.e. rules that shall be only applied when a certain library is included in the project. For instance, take a look at the .val
template provided with this plugin:
.val : extract as value
NON_VOID [lombok.val] → val $var:suggestVariableName()$ = $expr$;
NON_VOID → final $type*:expressionType(expr))$ $var:suggestVariableName()$ = $expr$;
It can be applied to any non-void expression and expands either to
val myVar = myExpression;
if lombok is available, or to
final MyType myVar = myExpression;
if you're using Java without lombok.
In this exmaple template the [lombok.val]
part after the matching type is used to restrict the rule appliction to those cases where the class lombok.val
is available in the class path.
In general you can use any class name between the square brackets you want to define a restriction on.
You can use the [SKIP]
flag for deactivating the template rule for a given matching type.
Example:
.sort : sort naturally
de.endrullis.lazyseq.LazySeq → [SKIP]
java.util.List → java.util.Collections.sort($expr$)
In this example a postfix template .sort
is defined.
The first rule tells the plugin that there shall be no completition for expressions of type LazySeq
.
The second rule defines how List
expressions shall be completed.
If you tag a template rule for Java with [USE_STATIC_IMPORTS]
all static methods that are used will be automatically imported and your code gets more compact. For instance, lets take the following template rule:
.toList : convert to List
ARRAY → java.util.Arrays.asList($expr$) [USE_STATIC_IMPORTS]
Since the rule is tagged with [USE_STATIC_IMPORTS]
expanding of array.toList
does not lead to Arrays.asList(array)
but to asList(array)
and the following line is added to your import statements:
import static java.util.Arrays.asList;
If you tag a template rule for Scala with [IMPORT FULLY_QUALIFIED_CLASSNAME]
the given class (or method) import is automatically added to the file header when the template gets applied:
.printStream : get PrintStream
java.io.File → new PrintStream($expr$) [IMPORT java.io.PrintStream]
Note that you can use the IMPORT
flag multiple times.
Go to Settings → Editor → Custom Postfix Templates or Tools → Custom Postfix Templates → Open Settings / Upgrade Templates. There you can chose between two different lambda styles and check/uncheck the template files you want to enable/disable.
Any contributions are welcome. Just fork the project, make your changes and create a pull request.
Here are some guides: