Tags
Bluehawk tags come in two forms: single-line and block. Single-line tags
operate upon the current line, while block tags operate upon the span of lines between
the start of the tag and the end of the tag. Since tags aren't valid syntax in
most languages, you should place them in comments -- Bluehawk will still process them.
To avoid name clashes with various languages and markup frameworks, all Bluehawk tags
begin and end with colons (:
).
The following examples demonstrate the remove tag in single-line and block forms:
Single-line tags use :<tag>:
to mark up a single line:
public class Main {
public static void main(String[] args){
int a = 2;
int b = 3;
int c = a * b;
assert(c == 6); // :remove:
System.out.println("Hello world!");
}
}
Block tags use :<tag>-start:
and :<tag>-end:
to mark the beginning and end
of a spanned range of lines:
public class Main {
public static void main(String[] args){
int a = 2;
int b = 3;
int c = a * b;
// :remove-start:
assert(c == 6);
// :remove-end:
System.out.println("Hello world!");
}
}
Some tags, like remove
in the examples above, don't require any arguments at all.
Other tags, such as snippet
, require a unique (to that file) identifier. Yet other
tags, such as replace
, require an attribute list of JSON objects. Pass arguments to
tags by listing them after the tag itself:
public class Main {
public static void main(String[] args){
// :snippet-start: multiply-abc
int a = 2;
int b = 3;
int c = a * b;
// :remove-start:
assert(c == 6);
// :remove-end:
System.out.println("Hello world!");
// :snippet-end:
}
}
💡 For a summary of all of the tags available in your local installation of Bluehawk, run
bluehawk list tags
.
Attribute Lists​
Attribute lists are JSON objects that contain additional information about a tag. They must use double quotes for fields, and the opening line of an attribute list must appear on the same line as the tag itself.
// :some-tag-start: {
// "field": "value"
// }
// :some-tag-end:
Snippet​
info
Prior to version 1.0, bluehawk accepted code-block
as an alias for snippet
.
Version 1.0 removed the code-block
alias.
The snippet
tag marks a range of content in a file as a snippet.
You can use the snip CLI command to generate snippet files from these snippets.
Because snippet
operates on ranges of content, it is only available as
a block tag. You must pass snippet
an identifier.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
// :snippet-start: test-block
System.out.println("Hello world!");
// :snippet-end:
}
}
Running the following command:
bluehawk snip Main.java -o .
Produces the following output:
Main.snippet.test-block.java
:
System.out.println("Hello world!");
State​
The state
tag marks a range of content in a file as part of a particular state.
You can use the snip or copy CLI commands with the state
flag to generate output files that contain only content from a specific named state.
When you use the --state
flag to specify a state, all state blocks other than the
specified state are removed from the output. If a file has state blocks
but you do not specify a --state
flag in the CLI, no content from the state blocks
is included in the generated output. All content not in a state block is
unaffected and outputs normally.
state
can be helpful for managing tutorial code
with multiple steps, such as a "start" state that only contains // TODO
and a
"final" state that contains completed implementation code.
Because state
operates on ranges of content, it is only available as
a block tag. You must pass state
at least one identifier, which determines
the name of the state or states that the block belongs to. You can pass
in a list of identifiers either through a space-separated list directly after
the tag itself, or through the id
field of an attribute list.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
// :snippet-start: example
int example = 1;
// :state-start: hello-world
System.out.println("Hello world!");
// :state-end:
// :state-start: hello-user
System.out.println("Hello user!");
// :state-end:
example++;
// :snippet-end:
}
}
Running the following command:
bluehawk snip Main.java -o . --state hello-user
Produces the following output:
Main.snippet.example.java
:
int example = 1;
System.out.println("Hello user!");
example++;
Alternatively, running the following command:
bluehawk snip Main.java -o . --state hello-world
Produces the following output:
Main.snippet.example.java
:
int example = 1;
System.out.println("Hello world!");
example++;
State-Uncomment​
The state-uncomment
tag combines the state and uncomment
tags. In terms of syntax, state-uncomment
works exactly the same as state
,
except one layer of commenting is removed from the entire state in produced output.
Use state-uncomment
to prevent executable code in a state from actually executing
in the source code you use to produce output.
Because state-uncomment
operates on ranges of content, it is only available as
a block tag.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
// :snippet-start: add-or-subtract
int example = 1;
// :state-start: add-one
example++;
// :state-end:
// :state-uncomment-start: subtract-one
//example--;
// :state--uncomment-end:
System.out.println("Example: " + example);
// :snippet-end:
}
}
Running the following command:
bluehawk snip Main.java -o . --state subtract-one
Produces the following output:
Main.snippet.add-or-subtract.java
:
int example = 1;
example--;
System.out.println("Example: " + example);
💡 Note that Bluehawk has trimmed one layer of comments from the
hello-user
state in the produced code block.
With state-uncomment
, you can create multiple valid end states but only run
one of those states when executing your source code.
State Remove​
The state-remove
tag removes the spanned range from
Bluehawk output for specified states.
Use the state-remove
when you want to include
enclosed text in everything except the states you
specify to the tag.
The state-remove
tag is a block tag.
Uncomment​
The uncomment
tag removes a single comment from the beginning of
each line of the spanned range in all output.
Because uncomment
operates on ranges of content, it is only available as
a block tag.
💡 Comments are only specified in certain language types. For example, plaintext does not have a comment syntax, so this tag does nothing in plaintext.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
int example = 1;
// :uncomment-start:
//example--;
// :uncomment-end:
example++;
System.out.println("Example: " + example);
}
}
Running the following command:
bluehawk copy Main.java -o .
Produces the following output:
Main.java
:
public class Main {
public static void main(String[] args){
int example = 1;
example--;
example++;
System.out.println("Example: " + example);
}
}
Replace​
The replace
tag accepts a JSON dictionary called "terms" as input via an
attribute list, and replaces occurrences string keys in the map within the
spanned range with their map values in all output. You can use replace
to
remove implementation details like complicated class names or API endpoint URLs
in generated output.
Because replace
operates on ranges of content, it is only available
as a block tag. You must pass an attribute list containing "terms",
a dictionary of strings to strings.
Consider the following file:
Main.java
:
// :replace-start: {
// "terms": {
// "MyMainExample": "Main",
// "www.example.com/rest/v1": "YOUR_REST_ENDPOINT_HERE"
// }
// }
/*
* MyMainExample -- a class that contains only a hello world main method
* that defines a rest endpoint.
*/
public class MyMainExample {
String rest_endpoint;
public static void main(String[] args){
System.out.println("Hello world!");
rest_endpoint = "www.example.com/rest/v1"
}
}
// :replace-end:
Running the following command:
bluehawk copy Main.java -o .
Produces the following output:
Main.java
:
/*
* Main -- a class that contains only a hello world main method
* that defines a rest endpoint.
*/
public class Main {
String rest_endpoint;
public static void main(String[] args){
System.out.println("Hello world!");
rest_endpoint = "YOUR_REST_ENDPOINT_HERE"
}
}
Emphasize​
The emphasize
tag highlights marked lines in formatted output.
emphasize
makes it easier to keep the correct lines highlighted
when you update code samples, because it calculates the highlighted
line numbers for you.
You can use emphasize
as either a block tag or a line tag.
note
The emphasize tag only applies to certain formatted outputs.
Use the --format
flag with Bluehawk CLI to get formatted output.
For more information on support for emphasize
,
refer to the formatted output documentation.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
// :snippet-start: modulo
int dividend = 11;
int divisor = 3;
int modulus = dividend % divisor; // :emphasize:
System.out.println(dividend + " % " + divisor + " = " + modulus);
// :snippet-end:
}
}
Running the following command:
bluehawk snip Main.java -o . --format=rst
Produces the following output:
Main.snippet.modulo.java.rst
:
.. code-block:: java
:emphasize-lines: 3
int dividend = 11;
int divisor = 3;
int modulus = dividend % divisor;
System.out.println(dividend + " % " + divisor + " = " + modulus);
Remove​
The remove
tag removes the spanned range from Bluehawk output. remove
can be
helpful for hiding assertions and state setup from user-facing code samples.
You can use remove
as either a block tag or a
line tag.
Consider the following file:
Main.java
:
public class Main {
public static void main(String[] args){
// :snippet-start: division
int dividend = 11;
int divisor = 3;
int quotient = dividend / divisor;
assert(quotient == 3) // :remove:
System.out.println(dividend + " / " + divisor + " = " + quotient);
// :snippet-end:
}
}
Running the following command:
bluehawk snip Main.java -o .
Produces the following output:
Main.snippet.division.java
:
int dividend = 11;
int divisor = 3;
int quotient = dividend / divisor;
System.out.println(dividend + " / " + divisor + " = " + quotient);