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:
stdinc$stdio.h
and- Space for an empty line.
[[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:
[[main]]
gets expanded intofunc#int@main#int$argc#char*$argv[]
.func
get expanded into### @@@({{params}}){\n{{inside_block}}\n}
.###
gets replaced withint
.@@@
gets replaced withmain
. Now, partial result isint main({{params}}){\n{{inside_block}}\n}
.###
is not present in the current partial result so{{params}}
gets expanded because it contains###
. New partial result isint main(### $$${{opt_params}}){\n{{inside_block}}\n}
.###
gets replaced withint
.$$$
gets replaced withargc
.- Similar to 5,
{{opt_params}}
gets replaced with, ### $$${{opt_params}}
. ###
gets replaced withchar*
.$$$
gets replaced withargv[]
.- Similar to 5 and 8,
{{inside_block}}
gets replaced with\t>>>{{opt_inside_block}}
. - Compile snippet
printf("Hello, world\!");
. This is trivial in this case and the resultprintf("Hello, world!");
.!
gets escaped and everything else stays the same. >>>
gets replaced withprintf("Hello, world!");
.- Similar to 5, 8 and 11,
{{opt_inside_block}}
gets replaced with\n\t>>>{{opt_inside_block}}
. return 0;
get trivially compiled toreturn 0;
.>>>
gets replaced withreturn 0;
.- Result gets cleaned from sub-snippets like
{{opt_inside_block}}
and{{opt_params}}
.