TeaCode Language

In short: TeaCode allows to create your own expanders which is its superpower. You can do it using a simple language made for that purpose. This boring article describes that language, so you should read it anyway.

TeaCode has its own, very simple language designed to create expanders. It is based on variables, filters and optional expressions. Each expander consists of pattern and template.

A pattern is an expression built from text and (optionally) some variables which values are passed to the template.

A pattern variable looks like ${name:type}, where name is a variable name and type is one of the supported variable types.

A template is the text that will be produced when user enters the pattern and presses the expand shortcut (++e by default.) The template consists of text and values that can be also filtered by built-in filters.

A template variable usually looks like ${name} where name is the name of a variable from the pattern. However variable values can be filtered. Such variables look like ${name.capitalize} or ${name.remove_spaces.capitalize}.

As an example, let's take a look at an expander that creates a ViewController class in Swift.

For pattern vc ${name:word}, the template is:

class ${name.capitalize}ViewController: NSViewController {

	#
}
It means that if user types vc main, the output code will be:
class MainViewController: NSViewController {

    |
}

Variable Types

  • text
    matches text values
  • text?
    matches text values using lazy pattern (.+?.) The shortest possible text is matched.
  • word
    matches a single word that consists of letters and/or numbers.
  • identifier
    matches identifiers (e.g. variable names, types, class names, etc). It matches letters, numbers and special characters: $, !, ?, [, ], <, >, @, :, -, _.
  • number
    matches numeric values.
  • switch(key1:value1,...)
    matches keys and replaces them with the given values.
    There's a special key *. It works like default in switch statement known from other programming languages. So if they key is *, then every word not defined as a key (even empty string) is replaced by the value.

    As an example let's take a look at simplified scope expander. The pattern: ${scope:switch(+:public,-:private,*:internal)} generates:

    ${scope}

    + is replaced by public and - is replaced by private. Any other word (or empty text) is replaced by internal.

  • enum(value1,...)
    matches one of its values and returns the same value in template. It's useful for making expanders that need particular words.
    A good example is simple HTML tag expander with pattern: ${tag:enum(div,p,a)} that generates:
    <${tag}>#</${tag}>
    ${tag} requires its value to be one of the following word: div, p or a.
  • exp(...)
    embeds another expander in the current one.

    A good example is a simplified HTML tag expander: ${tag:exp(tag)}.${class:word} that generates:

    <${tag} class="${class}">#</${tag}>

    In this case tag is an identifier of the expander that was the example for enum variable.

Filters

  • md5
    converts text into MD5 hash value
  • uppercase
    makes all the letters UPPERCASE
  • capitalize
    Converts First Letter Of Each Word To Uppercase
  • camelcase
    converts text to camelCase
  • snakecase
    converts text to snake_case
  • dashcase
    converts text to dash-case
  • lowercase
    makes all the letters lowercase
  • sha1
    converts text into SHA1 hash value
  • pascalcase
    converts text to PascalCase
  • remove_spaces
    removesallthespaces
  • lcfirst
    makes the first letter lowercase
  • ucfirst
    makes the last letter uppercase

Hash character

# is a special character that tells the TeaCode where the cursor should be in generated code.

Optional Expressions

TeaCode provides optional expressions that are bounded within | operator. The operator needs to be both in the pattern and in the template.

As an example let's take a look at pattern ${tag:enum(div,p,a)}|.${class:word}| that generates:

<${tag}| class="${class}"|>#</${tag}>

The expander works both for div and div.className expressions. In the second case it adds class attribute (with appropriate name) to the tag.