# The class can be used as it to work with generic tree.
# The class can also be specialized to provide more specific behavior.
class OrderedTree[E: Object]
+ super Streamable
+
# Sequence
var roots = new Array[E]
var sub = new HashMap[E, Array[E]]
# print the full tree on `o`
# Write a ASCII-style tree and use the `display` method to label elements
- fun pretty(o: OStream)
+ redef fun write_to(stream: OStream)
do
var last = roots.last
for r in roots do
- o.write display(r)
- o.write "\n"
- sub_pretty(o, r, "")
+ stream.write display(r)
+ stream.write "\n"
+ sub_write_to(stream, r, "")
end
end
- private fun sub_pretty(o: OStream, e: E, prefix: String)
+ private fun sub_write_to(o: OStream, e: E, prefix: String)
do
if not sub.has_key(e) then return
var subs = sub[e]
for e2 in subs do
if e2 != last then
o.write "{prefix}|--{display(e2)}\n"
- sub_pretty(o, e2, prefix+"| ")
+ sub_write_to(o, e2, prefix+"| ")
else
o.write "{prefix}`--{display(e2)}\n"
- sub_pretty(o, e2, prefix+" ")
+ sub_write_to(o, e2, prefix+" ")
end
end
end
# Sort roots and other elements using a comparator method
# This method basically sorts roots then each group of children
- fun sort_with(comparator: AbstractSorter[E])
+ fun sort_with(comparator: Comparator[E])
do
comparator.sort(roots)
for a in sub.values do
###############################################################################
+ redef class Streamable
+ # Like `write_to` but take care of creating the file
+ fun write_to_file(filepath: String)
+ do
+ var stream = new OFStream.open(filepath)
+ write_to(stream)
+ stream.close
+ end
+ end
+
redef class String
# return true if a file with this names exists
fun file_exists: Bool do return to_cstring.file_exists
end
# Extract the basename of a path and remove the extension
+ #
+ # assert "/path/to/a_file.ext".basename(".ext") == "a_file"
+ # assert "path/to/a_file.ext".basename(".ext") == "a_file"
+ # assert "path/to".basename(".ext") == "to"
+ # assert "path/to/".basename(".ext") == "to"
+ # assert "path".basename("") == "path"
+ # assert "/path".basename("") == "path"
+ # assert "/".basename("") == "/"
+ # assert "".basename("") == ""
fun basename(ext: String): String
do
- var pos = last_index_of_from('/', _length - 1)
+ var l = _length - 1 # Index of the last char
+ while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
+ if l == 0 then return "/"
+ var pos = last_index_of_from('/', l)
var n = self
if pos >= 0 then
- n = substring_from(pos+1)
+ n = substring(pos+1, l-pos)
end
return n.strip_extension(ext)
end
fun dirname: String
do
var l = _length - 1 # Index of the last char
- if l > 0 and self.chars[l] == '/' then l -= 1 # remove trailing `/`
+ while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
var pos = last_index_of_from('/', l)
if pos > 0 then
return substring(0, pos)
# Compare modules and groups using the
# FIXME do not use Object, but a better common interface of MModule and MGroup
private class LinexComparator
- super AbstractSorter[Object]
+ super Comparator[Object]
var mins = new HashMap [MGroup, nullable MModule]
var maxs = new HashMap [MGroup, nullable MModule]
fun min(o: Object): nullable MModule do
# Interessing elements must be selected. See `mmodules`, ``
# Display configuration can be set. See `cluster_group`, `project_group`
class MProjectDot
+ super Streamable
+
# The model where to look for information
var model: Model
end
end
- # Generate the dot-file named `filepath` with the current configuration
- fun render(filepath: String)
+ # Generate the dot content with the current configuration
+ redef fun write_to(stream)
do
# Collect interessing nodes
for m in model.mmodules do
end
end
- print "generating {filepath}"
- var dot = new OFStream.open(filepath)
- dot.write("digraph g \{\n")
- dot.write("rankdir=BT;node[shape=box];\n")
+ stream.write("digraph g \{\n")
+ stream.write("rankdir=BT;node[shape=box];\n")
# Generate the nodes
for p in model.mprojects do
- dot_cluster(dot, p.root.as(not null))
+ dot_cluster(stream, p.root.as(not null))
end
# Generate the edges
for m in mmodules do
var nm = node_for(m)
var nsm = node_for(sm)
if m.in_importation.direct_greaters.has(sm) then
- dot.write("\t{nm} -> {nsm}[style=bold]\n")
+ stream.write("\t{nm} -> {nsm}[style=bold]\n")
else
- dot.write("\t{nm} -> {nsm}[style=solid]\n")
+ stream.write("\t{nm} -> {nsm}[style=solid]\n")
end
end
end
- dot.write("\}\n")
- dot.close
- # sys.system("xdot -f dot {filepath}")
+ stream.write("\}\n")
end
end