#
# NOTE: works on letters only
#
- # assert 'x'.rot(6) == 'd'
- # assert 'T'.rot(15) == 'I'
- # assert '1'.rot(10) == '1'
- # assert '$'.rot(10) == '$'
- # assert 'z'.rot(-2) == 'x'
+ # assert 'x'.rot(6) == 'd'
+ # assert 'T'.rot(15) == 'I'
+ # assert '1'.rot(10) == '1'
+ # assert '$'.rot(10) == '$'
+ # assert 'z'.rot(-2) == 'x'
fun rot(x: Int): Char do
if not is_letter then return self
x = x % 26
# We then replace every letter in our original string by
# their rotated representations, therefore yielding : "dbedewx"
#
- # assert "All your base are belong to us".rot(13) == "Nyy lbhe onfr ner orybat gb hf"
- # assert "This is no moon.".rot(4).rot(22) == "This is no moon."
+ # assert "All your base are belong to us".rot(13) == "Nyy lbhe onfr ner orybat gb hf"
+ # assert "This is no moon.".rot(4).rot(22) == "This is no moon."
#
# NOTE : Works on letters only
# NOTE : This cipher is symmetrically decrypted with an `x` of 26-`x`
#
# Therefore, yielding the ciphertext : "fgounbmtcieehkh"
#
- # assert "fuckingbehemoth".railfence(4) == "fgounbmtcieehkh"
+ # assert "fuckingbehemoth".railfence(4) == "fgounbmtcieehkh"
fun railfence(depth: Int): String do
var lines = new Array[FlatBuffer].with_capacity(depth)
var up = false
# Transforms a rail-fence-encrypted String to its original
#
- # assert "fgounbmtcieehkh".unrail(4) == "fuckingbehemoth"
+ # assert "fgounbmtcieehkh".unrail(4) == "fuckingbehemoth"
fun unrail(depth: Int): String do
var dots = "." * length
var arr = new FlatBuffer.from(dots)
#
# Write example:
#
-# var config = new ConfigTree("config.ini")
-# config["goo"] = "goo"
-# config["foo.bar"] = "foobar"
-# config["foo.baz"] = "foobaz"
-# config.save
-# assert config.to_map.length == 3
+# var config = new ConfigTree("config.ini")
+# config["goo"] = "goo"
+# config["foo.bar"] = "foobar"
+# config["foo.baz"] = "foobaz"
+# config.save
+# assert config.to_map.length == 3
#
# Read example:
#
-# config = new ConfigTree("config.ini")
-# assert config.has_key("foo.bar")
-# assert config["foo.bar"] == "foobar"
+# config = new ConfigTree("config.ini")
+# assert config.has_key("foo.bar")
+# assert config["foo.bar"] == "foobar"
class ConfigTree
super Writable
#
# REQUIRE: `has_key(key)`
#
- # var config = new ConfigTree("config.ini")
- # assert config["goo"] == "goo"
- # assert config["foo.bar"] == "foobar"
- # assert config["foo.baz"] == "foobaz"
+ # var config = new ConfigTree("config.ini")
+ # assert config["goo"] == "goo"
+ # assert config["foo.bar"] == "foobar"
+ # assert config["foo.baz"] == "foobaz"
fun [](key: String): String do
if not has_key(key) then
print "error: config key `{key}` not found"
#
# REQUIRE: `has_key(key)`
#
- # var config = new ConfigTree("config.ini")
- # var values = config.at("foo")
- # assert values.has_key("bar")
- # assert values.has_key("baz")
- # assert not values.has_key("goo")
+ # var config = new ConfigTree("config.ini")
+ # var values = config.at("foo")
+ # assert values.has_key("bar")
+ # assert values.has_key("baz")
+ # assert not values.has_key("goo")
fun at(key: String): Map[String, String] do
if not has_key(key) then
print "error: config key `{key}` not found"
# Set `value` at `key`
#
- # var config = new ConfigTree("config.ini")
- # assert config["foo.bar"] == "foobar"
- # config["foo.bar"] = "baz"
- # assert config["foo.bar"] == "baz"
+ # var config = new ConfigTree("config.ini")
+ # assert config["foo.bar"] == "foobar"
+ # config["foo.bar"] = "baz"
+ # assert config["foo.bar"] == "baz"
fun []=(key: String, value: nullable String) do
set_node(key, value)
end
# Is `key` in the config?
#
- # var config = new ConfigTree("config.ini")
- # assert config.has_key("goo")
- # assert config.has_key("foo.bar")
- # assert not config.has_key("zoo")
+ # var config = new ConfigTree("config.ini")
+ # assert config.has_key("goo")
+ # assert config.has_key("foo.bar")
+ # assert not config.has_key("zoo")
fun has_key(key: String): Bool do
var parts = key.split(".").reversed
var node = get_root(parts.pop)
# Get `self` as a Map of `key`, `value`
#
- # var config = new ConfigTree("config.ini")
- # var map = config.to_map
- # assert map.has_key("goo")
- # assert map.has_key("foo.bar")
- # assert map.has_key("foo.baz")
- # assert map.length == 3
+ # var config = new ConfigTree("config.ini")
+ # var map = config.to_map
+ # assert map.has_key("goo")
+ # assert map.has_key("foo.bar")
+ # assert map.has_key("foo.baz")
+ # assert map.length == 3
fun to_map: Map[String, String] do
var map = new HashMap[String, String]
for node in leaves do
# obj["baz"] = arr
# var res = obj.to_pretty_json
# var exp = """{
- # "foo": 1,
- # "bar": true,
- # "baz": [2, false, "baz"]
+ # \t"foo": 1,
+ # \t"bar": true,
+ # \t"baz": [2, false, "baz"]
# }\n"""
# assert res == exp
# ~~~
# store.load
# assert 1 == graph.edges.length
# for edge in graph.edges do
-# assert "BAZ" == edge.rel_type
-# assert a.labels == edge.from.labels
-# for k, v in a.properties do assert v == edge.from.properties[k]
-# assert b.labels == edge.to.labels
-# for k, v in b.properties do assert v == edge.to.properties[k]
+# assert "BAZ" == edge.rel_type
+# assert a.labels == edge.from.labels
+# for k, v in a.properties do assert v == edge.from.properties[k]
+# assert b.labels == edge.to.labels
+# for k, v in b.properties do assert v == edge.to.properties[k]
# end
# assert 2 == graph.nodes.length
# ~~~
# new SequentialNodeCollection("node_id"), graph.to_json)
# assert 1 == graph.edges.length
# for edge in graph.edges do
- # assert "BAZ" == edge.rel_type
- # assert a.labels == edge.from.labels
- # for k, v in a.properties do assert v == edge.from.properties[k]
- # assert b.labels == edge.to.labels
- # for k, v in b.properties do assert v == edge.to.properties[k]
+ # assert "BAZ" == edge.rel_type
+ # assert a.labels == edge.from.labels
+ # for k, v in a.properties do assert v == edge.from.properties[k]
+ # assert b.labels == edge.to.labels
+ # for k, v in b.properties do assert v == edge.to.properties[k]
# end
# assert 2 == graph.nodes.length
# ~~~
#
# In order to connect to Neo4j you need a connector:
#
-# # Create new Neo4j client
-# var client = new Neo4jClient("http://localhost:7474")
-# assert client.is_ok
+# # Create new Neo4j client
+# var client = new Neo4jClient("http://localhost:7474")
+# assert client.is_ok
#
# The fundamental units that form a graph are nodes and relationships.
#
# Nodes are used to represent entities stored in base:
#
-# # Create a disconnected node
-# var andres = new NeoNode
-# andres["name"] = "Andres"
-# # Connect the node to Neo4j
-# client.save_node(andres)
-# assert andres.is_linked
-# #
-# # Create a second node
-# var kate = new NeoNode
-# kate["name"] = "Kate"
-# client.save_node(kate)
-# assert kate.is_linked
+# # Create a disconnected node
+# var andres = new NeoNode
+# andres["name"] = "Andres"
+# # Connect the node to Neo4j
+# client.save_node(andres)
+# assert andres.is_linked
+#
+# # Create a second node
+# var kate = new NeoNode
+# kate["name"] = "Kate"
+# client.save_node(kate)
+# assert kate.is_linked
#
# Relationships between nodes are a key part of a graph database.
# They allow for finding related data. Just like nodes, relationships can have properties.
#
-# # Create a relationship
-# var loves = new NeoEdge(andres, "LOVES", kate)
-# client.save_edge(loves)
-# assert loves.is_linked
+# # Create a relationship
+# var loves = new NeoEdge(andres, "LOVES", kate)
+# client.save_edge(loves)
+# assert loves.is_linked
#
# Nodes can also be loaded fron Neo4j:
#
-# # Get a node from DB and explore edges
-# var url = andres.url.to_s
-# var from = client.load_node(url)
-# assert from["name"].to_s == "Andres"
-# var to = from.out_nodes("LOVES").first # follow the first LOVES relationship
-# assert to["name"].to_s == "Kate"
+# # Get a node from DB and explore edges
+# var url = andres.url.to_s
+# var from = client.load_node(url)
+# assert from["name"].to_s == "Andres"
+# var to = from.out_nodes("LOVES").first # follow the first LOVES relationship
+# assert to["name"].to_s == "Kate"
#
# For more details, see http://docs.neo4j.org/chunked/milestone/rest-api.html
module neo4j
# `Neo4jClient` is needed to communicate through the REST API
#
-# var client = new Neo4jClient("http://localhost:7474")
-# assert client.is_ok
+# var client = new Neo4jClient("http://localhost:7474")
+# assert client.is_ok
class Neo4jClient
# Neo4j REST services baseurl
#
# Example:
#
-# var client = new Neo4jClient("http://localhost:7474")
-# var query = new CypherQuery
-# query.nmatch("(n)-[r:LOVES]->(m)")
-# query.nwhere("n.name=\"Andres\"")
-# query.nreturn("m.name")
-# var res = client.cypher(query).as(JsonObject)
-# assert res["data"].as(JsonArray).first.as(JsonArray).first == "Kate"
+# var client = new Neo4jClient("http://localhost:7474")
+# var query = new CypherQuery
+# query.nmatch("(n)-[r:LOVES]->(m)")
+# query.nwhere("n.name=\"Andres\"")
+# query.nreturn("m.name")
+# var res = client.cypher(query).as(JsonObject)
+# assert res["data"].as(JsonArray).first.as(JsonArray).first == "Kate"
#
# For more details, see: http://docs.neo4j.org/chunked/milestone/rest-api-cypher.html
class CypherQuery
#
# If the entity is initialized unlinked from neo4j:
#
-# # Create a disconnected node
-# var andres = new NeoNode
-# andres["name"] = "Andres"
-# # At this point, the node is not linked
-# assert not andres.is_linked
+# # Create a disconnected node
+# var andres = new NeoNode
+# andres["name"] = "Andres"
+# # At this point, the node is not linked
+# assert not andres.is_linked
#
# Then we can link the entity to the base:
#
#
# Creating new nodes:
#
-# var client = new Neo4jClient("http://localhost:7474")
-# #
-# var andres = new NeoNode
-# andres.labels.add "Person"
-# andres["name"] = "Andres"
-# andres["age"] = 22
-# client.save_node(andres)
-# assert andres.is_linked
+# var client = new Neo4jClient("http://localhost:7474")
+#
+# var andres = new NeoNode
+# andres.labels.add "Person"
+# andres["name"] = "Andres"
+# andres["age"] = 22
+# client.save_node(andres)
+# assert andres.is_linked
#
# Get nodes from Neo4j:
#
-# var url = andres.url.to_s
-# var node = client.load_node(url)
-# assert node["name"] == "Andres"
-# assert node["age"].to_s.to_i == 22
+# var url = andres.url.to_s
+# var node = client.load_node(url)
+# assert node["name"] == "Andres"
+# assert node["age"].to_s.to_i == 22
class NeoNode
super NeoEntity
#
# Create a relationship:
#
-# var client = new Neo4jClient("http://localhost:7474")
-# # Create nodes
-# var andres = new NeoNode
-# andres["name"] = "Andres"
-# var kate = new NeoNode
-# kate["name"] = "Kate"
-# # Create a relationship of type `LOVES`
-# var loves = new NeoEdge(andres, "LOVES", kate)
-# client.save_edge(loves)
-# assert loves.is_linked
+# var client = new Neo4jClient("http://localhost:7474")
+# # Create nodes
+# var andres = new NeoNode
+# andres["name"] = "Andres"
+# var kate = new NeoNode
+# kate["name"] = "Kate"
+# # Create a relationship of type `LOVES`
+# var loves = new NeoEdge(andres, "LOVES", kate)
+# client.save_edge(loves)
+# assert loves.is_linked
#
# Get an edge from DB:
#
-# var url = loves.url.to_s
-# var edge = client.load_edge(url)
-# assert edge.from["name"].to_s == "Andres"
-# assert edge.to["name"].to_s == "Kate"
+# var url = loves.url.to_s
+# var edge = client.load_edge(url)
+# assert edge.from["name"].to_s == "Andres"
+# assert edge.to["name"].to_s == "Kate"
class NeoEdge
super NeoEntity
#
# Example:
#
-# var client = new Neo4jClient("http://localhost:7474")
-# #
-# var node1 = new NeoNode
-# var node2 = new NeoNode
-# var edge = new NeoEdge(node1, "TO", node2)
-# #
-# var batch = new NeoBatch(client)
-# batch.save_node(node1)
-# batch.save_node(node2)
-# batch.save_edge(edge)
-# batch.execute
-# #
-# assert node1.is_linked
-# assert node2.is_linked
-# assert edge.is_linked
+# var client = new Neo4jClient("http://localhost:7474")
+#
+# var node1 = new NeoNode
+# var node2 = new NeoNode
+# var edge = new NeoEdge(node1, "TO", node2)
+#
+# var batch = new NeoBatch(client)
+# batch.save_node(node1)
+# batch.save_node(node2)
+# batch.save_edge(edge)
+# batch.execute
+#
+# assert node1.is_linked
+# assert node2.is_linked
+# assert edge.is_linked
class NeoBatch
# Neo4j client connector
# Filter: sort with a given `comparator`.
# Important: require O(n) memory.
#
- # assert ["a", "c", "b"].iterator.sort_with(alpha_comparator).to_a == ["a", "b", "c"]
+ # assert ["a", "c", "b"].iterator.sort_with(alpha_comparator).to_a == ["a", "b", "c"]
fun sort_with(comparator: Comparator): Iterator[E]
do
var a = self.to_a
# Alternate each item with `e`.
#
- # assert [1,2,3].iterator.alternate(0).to_a == [1,0,2,0,3]
+ # assert [1,2,3].iterator.alternate(0).to_a == [1,0,2,0,3]
fun alternate(e: E): Iterator[E]
do
return new PipeAlternate[E](self, e)
# Filter: reject a given `item`.
#
- # assert [1,1,2,1,3].iterator.skip(1).to_a == [2,3]
+ # assert [1,1,2,1,3].iterator.skip(1).to_a == [2,3]
fun skip(item: E): Iterator[E]
do
return new PipeSkip[E](self, item)
#
# Return an error object in case of error.
#
- # assert "/fail/does not/exist".rmdir != null
+ # assert "/fail/does not/exist".rmdir != null
fun rmdir: nullable Error
do
var res = to_path.rmdir
# Is the string non-empty but only made of whitespaces?
#
- # assert " \n\t ".is_whitespace == true
- # assert " hello ".is_whitespace == false
- # assert "".is_whitespace == false
+ # assert " \n\t ".is_whitespace == true
+ # assert " hello ".is_whitespace == false
+ # assert "".is_whitespace == false
#
# `Char::is_whitespace` determines what is a whitespace.
fun is_whitespace: Bool
# Returns `self` removed from its last line terminator (if any).
#
- # assert "Hello\n".chomp == "Hello"
- # assert "Hello".chomp == "Hello"
+ # assert "Hello\n".chomp == "Hello"
+ # assert "Hello".chomp == "Hello"
#
- # assert "\n".chomp == ""
- # assert "".chomp == ""
+ # assert "\n".chomp == ""
+ # assert "".chomp == ""
#
# Line terminators are `"\n"`, `"\r\n"` and `"\r"`.
# A single line terminator, the last one, is removed.
#
- # assert "\r\n".chomp == ""
- # assert "\r\n\n".chomp == "\r\n"
- # assert "\r\n\r\n".chomp == "\r\n"
- # assert "\r\n\r".chomp == "\r\n"
+ # assert "\r\n".chomp == ""
+ # assert "\r\n\n".chomp == "\r\n"
+ # assert "\r\n\r\n".chomp == "\r\n"
+ # assert "\r\n\r".chomp == "\r\n"
#
# Note: unlike with most IO methods like `Reader::read_line`,
# a single `\r` is considered here to be a line terminator and will be removed.
# Gives the formatted string back as a Nit string with `args` in place
#
- # assert "This %1 is a %2.".format("String", "formatted String") == "This String is a formatted String."
- # assert "\\%1 This string".format("String") == "\\%1 This string"
+ # assert "This %1 is a %2.".format("String", "formatted String") == "This String is a formatted String."
+ # assert "\\%1 This string".format("String") == "\\%1 This string"
fun format(args: Object...): String do
var s = new Array[Text]
var curr_st = 0
# A macro is represented as a string identifier like `%MACRO%` in the template
# string. Using `TemplateString`, macros can be replaced by any `Writable` data:
#
-# var tpl = new TemplateString("Hello %NAME%!")
-# tpl.replace("NAME", "Dave")
-# assert tpl.write_to_string == "Hello Dave!"
+# var tpl = new TemplateString("Hello %NAME%!")
+# tpl.replace("NAME", "Dave")
+# assert tpl.write_to_string == "Hello Dave!"
#
# A macro identifier is valid if:
#
#
# Loading the template file using `TemplateString`:
#
-# var file = "example.tpl"
-# if file.file_exists then
-# tpl = new TemplateString.from_file("example.tpl")
-# tpl.replace("TITLE", "Home Page")
-# tpl.replace("ARTICLE", "Welcome on my site!")
-# end
+# var file = "example.tpl"
+# if file.file_exists then
+# tpl = new TemplateString.from_file("example.tpl")
+# tpl.replace("TITLE", "Home Page")
+# tpl.replace("ARTICLE", "Welcome on my site!")
+# end
#
# ## Outputting
#
# output like any other `Template` using methods like `write_to`, `write_to_string`
# or `write_to_file`.
#
-# tpl = new TemplateString("Hello %NAME%!")
-# tpl.replace("NAME", "Dave")
-# assert tpl.write_to_string == "Hello Dave!"
+# tpl = new TemplateString("Hello %NAME%!")
+# tpl.replace("NAME", "Dave")
+# assert tpl.write_to_string == "Hello Dave!"
#
# ## Template correctness
#
# `TemplateString` can be outputed even if all macros were not replaced.
# In this case, the name of the macro will be displayed wuthout any replacement.
#
-# tpl = new TemplateString("Hello %NAME%!")
-# assert tpl.write_to_string == "Hello %NAME%!"
+# tpl = new TemplateString("Hello %NAME%!")
+# assert tpl.write_to_string == "Hello %NAME%!"
#
# The `check` method can be used to ensure that all macros were replaced before
# performing the output. Warning messages will be stored in `warnings` and can
# be used to locate unreplaced macros.
#
-# tpl = new TemplateString("Hello %NAME%!")
-# if not tpl.check then
-# assert not tpl.warnings.is_empty
-# print "Cannot output unfinished template:"
-# print tpl.warnings.join("\n")
-# exit(0)
-# else
-# tpl.write_to sys.stdout
-# end
-# assert tpl.write_to_string == "Hello %NAME%!"
+# tpl = new TemplateString("Hello %NAME%!")
+# if not tpl.check then
+# assert not tpl.warnings.is_empty
+# print "Cannot output unfinished template:"
+# print tpl.warnings.join("\n")
+# exit(0)
+# else
+# tpl.write_to sys.stdout
+# end
+# assert tpl.write_to_string == "Hello %NAME%!"
class TemplateString
super Template
#
# To use a different delimiter you can subclasse `TemplateString` and defined the `marker`.
#
- # class DollarTemplate
- # super TemplateString
- # redef var marker = '$'
- # end
- # var tpl = new DollarTemplate("Hello $NAME$!")
- # tpl.replace("NAME", "Dave")
- # assert tpl.write_to_string == "Hello Dave!"
+ # class DollarTemplate
+ # super TemplateString
+ # redef var marker = '$'
+ # end
+ # var tpl = new DollarTemplate("Hello $NAME$!")
+ # tpl.replace("NAME", "Dave")
+ # assert tpl.write_to_string == "Hello Dave!"
protected var marker = '%'
# Creates a new template from a `text`.
#
- # var tpl = new TemplateString("Hello %NAME%!")
- # assert tpl.write_to_string == "Hello %NAME%!"
+ # var tpl = new TemplateString("Hello %NAME%!")
+ # assert tpl.write_to_string == "Hello %NAME%!"
init(text: String) do
self.tpl_text = text
parse
# Available macros in `self`.
#
- # var tpl = new TemplateString("Hello %NAME%!")
- # assert tpl.macro_names.first == "NAME"
+ # var tpl = new TemplateString("Hello %NAME%!")
+ # assert tpl.macro_names.first == "NAME"
fun macro_names: Collection[String] do return macros.keys
# Does `self` contain a macro with `name`.
#
- # var tpl = new TemplateString("Hello %NAME%")
- # assert tpl.has_macro("NAME")
+ # var tpl = new TemplateString("Hello %NAME%")
+ # assert tpl.has_macro("NAME")
fun has_macro(name: String): Bool do return macro_names.has(name)
# Replace a `macro` by a streamable `replacement`.
#
# REQUIRE `has_macro(name)`
#
- # var tpl = new TemplateString("Hello %NAME%!")
- # tpl.replace("NAME", "Dave")
- # assert tpl.write_to_string == "Hello Dave!"
+ # var tpl = new TemplateString("Hello %NAME%!")
+ # tpl.replace("NAME", "Dave")
+ # assert tpl.write_to_string == "Hello Dave!"
fun replace(name: String, replacement: Writable) do
assert has_macro(name)
for macro in macros[name] do
#
# Return false if a macro was not replaced and store message in `warnings`.
#
- # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
- # assert not tpl.check
- # tpl.replace("FIRSTNAME", "Corben")
- # tpl.replace("LASTNAME", "Dallas")
- # assert tpl.check
+ # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
+ # assert not tpl.check
+ # tpl.replace("FIRSTNAME", "Corben")
+ # tpl.replace("LASTNAME", "Dallas")
+ # assert tpl.check
fun check: Bool do
warnings.clear
var all_ok = true
# Last `check` warnings.
#
- # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
- # tpl.check
- # assert tpl.warnings.length == 2
- # assert tpl.warnings[0] == "No replacement for macro %FIRSTNAME% at (6:16)"
- # assert tpl.warnings[1] == "No replacement for macro %LASTNAME% at (19:28)"
- # tpl.replace("FIRSTNAME", "Corben")
- # tpl.replace("LASTNAME", "Dallas")
- # tpl.check
- # assert tpl.warnings.is_empty
+ # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
+ # tpl.check
+ # assert tpl.warnings.length == 2
+ # assert tpl.warnings[0] == "No replacement for macro %FIRSTNAME% at (6:16)"
+ # assert tpl.warnings[1] == "No replacement for macro %LASTNAME% at (19:28)"
+ # tpl.replace("FIRSTNAME", "Corben")
+ # tpl.replace("LASTNAME", "Dallas")
+ # tpl.check
+ # assert tpl.warnings.is_empty
var warnings = new Array[String]
# Returns a view on `self` macros on the form `macro.name`/`macro.replacement`.
# Given that all macros with the same name are all replaced with the same
# replacement, this view contains only one entry for each name.
#
- # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
- # for name, rep in tpl do assert rep == null
- # tpl.replace("FIRSTNAME", "Corben")
- # tpl.replace("LASTNAME", "Dallas")
- # for name, rep in tpl do assert rep != null
+ # var tpl = new TemplateString("Hello %FIRSTNAME%, %LASTNAME%!")
+ # for name, rep in tpl do assert rep == null
+ # tpl.replace("FIRSTNAME", "Corben")
+ # tpl.replace("LASTNAME", "Dallas")
+ # for name, rep in tpl do assert rep != null
fun iterator: MapIterator[String, nullable Writable] do
return new TemplateStringIterator(self)
end
# * starts with an uppercase letter
# * contains only numers, uppercase letters or '_'
#
- # # valid
- # assert "NAME".is_valid_macro_name
- # assert "FIRST_NAME".is_valid_macro_name
- # assert "BLOCK1".is_valid_macro_name
- # # invalid
- # assert not "1BLOCK".is_valid_macro_name
- # assert not "_BLOCK".is_valid_macro_name
- # assert not "FIRST NAME".is_valid_macro_name
- # assert not "name".is_valid_macro_name
+ # # valid
+ # assert "NAME".is_valid_macro_name
+ # assert "FIRST_NAME".is_valid_macro_name
+ # assert "BLOCK1".is_valid_macro_name
+ # # invalid
+ # assert not "1BLOCK".is_valid_macro_name
+ # assert not "_BLOCK".is_valid_macro_name
+ # assert not "FIRST NAME".is_valid_macro_name
+ # assert not "name".is_valid_macro_name
fun is_valid_macro_name: Bool do
if not first.is_upper then return false
for c in self do
# Append a bunch of elements at the end of the template with separations.
# see `add`.
#
- # var t = new Template
- # t.add_list(["1", "2", "3"], ", ", " and ")
- # assert t.write_to_string == "1, 2 and 3"
+ # var t = new Template
+ # t.add_list(["1", "2", "3"], ", ", " and ")
+ # assert t.write_to_string == "1, 2 and 3"
fun add_list(elements: Collection[Writable], sep, last_sep: Writable) do
var last = elements.length - 2
var i = 0