Getting started

Homotopy is a snippet language. It is designed with the focus on writing code and not caring about how it looks. That is handled automatically.

This document designed to get you up and running with using Homotopy. It uses C++ as a working language. To see snippets from standard library go to Snippet library.

Hello world

stdinc$stdio.h& &[[main]]>printf("Hello, world\!");& &return 0;
#include <stdio.h>

int main(int argc, char* argv[]){
    printf("Hello, world!");

    return 0;
}

That was a lot of code for one line. Following sections wil gradually introduce concepts used in the “Hello, World!” example.

Language

Snippet definitions

Snippet is defined as text with placeholders for parameter values.

{"name": "stdinc","language": "C++","snippet": "#include <$$$>"}

This is the definition for C++ snippet for including from standard library. $$$ is a placeholder for parameter $.

Example:

stdinc$stdio.h
#include <stdio.h>

Parameters

Parameters are used to bind values to a snippet definition. Parameters begin with on of the following characters.

NOTE: This is just a convention that standard library follows. It is not enforced by any part of the tool. Have that in mind if creating custom snippets.

Parameter name Description
! Class name
~ Implements
: Extends
^ Template
@ Method/function name
# Type
$ Value
% Other
func#void@foo
void foo(){

}

Parameters can be used more than once in the same snippet.

func#void@foo#int$i#int$j
void foo(int i, int j){

}

In the last example there are two adjacent int parameters of foo. Passing two value parameters first and then a single type parameter gives the same result.

func#void@foo$i$j#int
void foo(int i, int j){

}

Into

There is another, special, parameter, into >. It separates a parent and child snippets. Child snippet is substituted inside parent snippet at the placeholder >>> position.

if$i==4>printf("four");
if(i==4){
    printf("four");
}

In this way, several snippets can be combined to make up a larger construct.

Following control characters are used to combine snippets.

Parameter name Description
> Into
< Out
& And

Example with <:

if$i==4>printf("four");<printf("out of if");
if(i==4){
    printf("four");
}

printf("out of if");

Example with &:

printf("first line");&printf("second line");
printf("first line");

printf("second line");

Escape

Control character are picked so they don’t interfere with code too much. Yet sometimes code contains control characters. To make any character part of snippet and not treat it as a parameter just put backslash character '\' in front of that character.

Example:

if$a \> max>max = a
if(a > max){
    max = a
}

Shortcuts

There are common construction that are tedious to write. To help with that, Homotopy has a concept of shortcuts.

Anywhere in the snippet, place a definition inside double square brackets and it gets expanded before compilation.

Example:

[[main]]
int main(int argc, char* argv[]){

}

Hello world deep dive

Lets take a look at the hello world snippet once again and go through the process of compilation in detail. This is a fairly large example but includes most of the feathers of Homotopy.

stdinc$stdio.h& &[[main]]>printf("Hello, world\!");&return 0;

At the top level there are three snippets:

  1. stdinc$stdio.h and
  2. Space for an empty line.
  3. [[main]]>printf("Hello, world\!");&return 0;

They are implicitly inside an implicit block snippet. Block snippet just separate snippets by lines.

Definitions used to compile this snippet:

[
{"name": "stdinc","language": "C++","snippet": "#include <$$$>"},
{"name": "main","language": "C++","snippet": "func#int@main#int$argc#char*$argv[]"},
{"name": "func","language": "C++","snippet": "### @@@({{params}}){\n{{inside_wblock}}\n}"},
{"name": "params","language": "C++","snippet": "### $$${{opt_params}}"},
{"name": "opt_params","language": "C++","snippet": ", ### $$${{opt_params}}"},
{"name": "inside_wblock","language": "C++","snippet": "\t>>>{{opt_inside_block}}"},
{"name": "opt_inside_block","language": "C++","snippet": "\n\t>>>{{opt_inside_block}}"}
]

stdinc has the definition #include <$$$> and stdio.h just gets replaced in to get #include <stdio.h>

Lets now go through the third snippet step by step:

  1. [[main]] gets expanded into func#int@main#int$argc#char*$argv[].
  2. func get expanded into ### @@@({{params}}){\n{{inside_block}}\n}.
  3. ### gets replaced with int.
  4. @@@ gets replaced with main. Now, partial result is int main({{params}}){\n{{inside_block}}\n}.
  5. ### is not present in the current partial result so {{params}} gets expanded because it contains ###. New partial result is int main(### $$${{opt_params}}){\n{{inside_block}}\n}.
  6. ### gets replaced with int.
  7. $$$ gets replaced with argc.
  8. Similar to 5, {{opt_params}} gets replaced with , ### $$${{opt_params}}.
  9. ### gets replaced with char*.
  10. $$$ gets replaced with argv[].
  11. Similar to 5 and 8, {{inside_block}} gets replaced with \t>>>{{opt_inside_block}}.
  12. Compile snippet printf("Hello, world\!");. This is trivial in this case and the result printf("Hello, world!");. ! gets escaped and everything else stays the same.
  13. >>> gets replaced with printf("Hello, world!");.
  14. Similar to 5, 8 and 11, {{opt_inside_block}} gets replaced with \n\t>>>{{opt_inside_block}}.
  15. return 0; get trivially compiled to return 0;.
  16. >>> gets replaced with return 0;.
  17. Result gets cleaned from sub-snippets like {{opt_inside_block}} and {{opt_params}}.