API Reference
The API Reference explains how to access various match and rewrite information in Comby if you want to integrate or build other tooling (like an editor plugin or grammar fuzzer).
There are three operations for information: match
, rewrite
, and
substitute
.
To perform these operations and access the results, there are three options:
- Use Python bindings for Comby.
- Invoke Comby directly on the command line.
- Use HTTP requests to a persistent server that you run on your machine.
Python Bindings
See the interface.py file that describes the operations and data types when using Python bindings.
Command Line
The command line is a bare-bones interface to perform operations, but useful for understanding the schema–consider using the Python bindings or a server to avoid command line awkwardness.
Match
Retrieve match information by using the -match-only
flag. For example:
echo 'printf("hello!");' | comby 'printf(:[arg])' '' .c -stdin -match-only
Note:
comby
currently expects a rewrite template in the second anonymous argument. When using-match-only
, simply use an empty string like above.
The -match-only
option will only print out the entire matched string on the
command line. Add the -json-lines
flag to get all information on matched
ranges and matched holes.
comby 'printf(:[arg])' '' .c -stdin -match-only -json-lines
This outputs JSON information, one line per match (in this case, the printf(...)
part). We can make the format more readable by piping the output to python -m json.tool
.
Schema example
{
"uri": null,
"matches": [
{
"range": {
"start": {
"offset": 0,
"line": 1,
"column": 1
},
"end": {
"offset": 16,
"line": 1,
"column": 17
}
},
"environment": [
{
"variable": "arg",
"value": "\"hello!\"",
"range": {
"start": {
"offset": 7,
"line": 1,
"column": 8
},
"end": {
"offset": 15,
"line": 1,
"column": 16
}
}
}
],
"matched": "printf(\"hello!\")"
}
]
}
uri
is the file path of the document containingmatches
(null
forstdin
)matches
is a list ofmatches
(likeprintf(...)
. Each item inmatches
contains:matched
, the string that was matched by the templaterange
, the range spanned bymatched
environment
, containing a list ofvariable
,value
, andrange
items where:variable
is the hole identifiervalue
is the string value bound tovariable
range
, the range spanned byvalue
range
contains offset
, line
, and column
where:
☞
offset
starts at zero☞
line
andcolumn
start at one
Rewrite
The rewrite operation is similar to match. Use the -json-lines
flag with a rewrite template as in:
echo 'printf("hello!");' | comby 'printf(:[arg])' 'printf("bye")' .c -stdin -json-lines
Schema summary
{
"uri": null,
"rewritten_source": "printf(\"bye\");\n",
"in_place_substitutions": [
{
"range": {
"start": {
"offset": 0,
"line": -1,
"column": -1
},
"end": {
"offset": 13,
"line": -1,
"column": -1
}
},
"replacement_content": "printf(\"bye\")",
"environment": []
}
],
"diff": "--- /dev/null\n+++ /dev/null\n@@ -1,1 +1,1 @@\n-printf(\"hello!\");\n+printf(\"bye\");"
}
uri
corresponds to the changed file (null
forstdin
)rewritten_source
is result of the entire rewritten file (or input forstdin
)diff
is a patch-compatiblediff
of the changein_place_substitions
is a list of substituted fragments where:replacement_content
is the fragment substituted in-place for matchesrange
, the range spanned byreplacement_content
environment
, a list ofvariable
andvalue
of holes used in this result, with the updatedrange
☞ Adding the
-json-only-diff
flag will output thediff
value of the change (useful if you only care about the resulting diff).
⚠ Current Limitations
Rewrite ranges currently do not report line and column values and are set to -1
If a hole with the same identifier is used multiple times in the rewrite template,
environment
will currently report only the first range
Substitute
Substitute an environment inside a rewrite template with the -substitute
flag. An example invocation is:
comby '' ':[1] :[2]' -substitute '[{"variable":"1","value":"hello"},{"variable":"2","value":"there"}]'
The output is only the rewritten output hello there
.
Note:
comby
currently expects a match template in the first anonymous argument. When using-substitute
, simply use an empty string like above.
Walked example
One way to effectively use -substitute
in scripting is by combining it with other operations. For example, Use jq
to extract environments from matches:
echo 'printf("hello", "there")' \
| comby 'printf(":[1]", ":[2]")' '' .c -stdin -json-lines -match-only \
| jq -c '.matches | map(.environment) | .[]'
The environment can be substituted by piping to xargs
and using -substitute
:
echo 'printf("hello", "there")' \
| comby 'printf(":[1]", ":[2]")' '' .c -stdin -json-lines -match-only \
| jq -c '.matches | map(.environment) | .[]' \
| xargs -0 comby '' ':[1] :[2]. General Kenobi!' -substitute
And we’ll see hello there. General Kenobi!
.
Comby server
To use the server, you’ll need to build from source. See the README instructions for comby-server.
The comby
server exposes the three HTTP POST endpoints below. These return the
same JSON values as the respective command line operations.
The endpoints accept options like rule
and language
corresponding to
command line flags.
/match
{"source": "hello there", "match": "hello :[1]", "rule": "where :[1] == \"there\"", "language": ".generic", "id": 0}
source
should be the entire source file to rewriteid
is an identifier for this request, which will be set in the corresponding response
/rewrite
{"source": "hello there", "match": "hello :[1]", "rule": "where :[1] == \"there\"", "rewrite": "kenobi", "language": ".generic", "substitution_kind": "in_place", "id": 0}
substitution_kind
can be one of in_place
or newline_separated
. When
newline_separated
is chosen, rewritten fragments are output one per line,
rather than replaced in-place in the original document.
/substitute
{"rewrite_template": "print(:[1])", "environment": "[{\"variable\":\"1\",\"value\":\"hello\"}]", "id": 0}
Set the DEBUG
environment variable to see verbose incoming and outgoing data.