Last active
December 11, 2018 13:09
-
-
Save timgentry/c6f1e10f74538d179e36c6e1b314dfc1 to your computer and use it in GitHub Desktop.
Rake example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Parses Graphviz .dot files | |
class DotFileParser | |
EDGE_PATTERN = /"([^"]*)" -> "([^"]*)"/ | |
NODE_PATTERN = /\A\t"([^"]*)" \[/ | |
def initialize(filename) | |
@filename = filename | |
end | |
def each_edge | |
readlines.each do |line| | |
matchdata = line.match(EDGE_PATTERN) | |
next if matchdata.nil? | |
yield(matchdata[1], matchdata[2]) | |
end | |
end | |
def each_node | |
readlines.each do |line| | |
matchdata = line.match(NODE_PATTERN) | |
next if matchdata.nil? | |
yield(matchdata[1]) | |
end | |
end | |
def all_nodes | |
return @all_nodes if @all_nodes | |
@all_nodes = Set.new | |
each_node do |node| | |
@all_nodes.add(node) | |
end | |
@all_nodes | |
end | |
def connections(node) | |
nodes = Set.new | |
each_edge do |from, to| | |
next unless from == node || to == node | |
nodes.add(from) if to == node | |
nodes.add(to) if from == node | |
end | |
nodes | |
end | |
def clusters | |
return @clusters if @clusters | |
remaining_nodes = all_nodes | |
@clusters = [] | |
one_node_clusters = Set.new | |
until remaining_nodes.empty? | |
cluster_nodes = Set.new | |
current_nodes = Set[remaining_nodes.first] | |
current_connections = Set.new | |
until current_nodes.empty? | |
cluster_nodes += current_nodes | |
remaining_nodes -= current_nodes | |
current_connections = Set.new | |
current_nodes.each do |node| | |
current_connections += connections(node) & remaining_nodes | |
end | |
current_nodes = current_connections | |
end | |
if cluster_nodes.size == 1 | |
one_node_clusters << cluster_nodes.first | |
else | |
@clusters << cluster_nodes | |
end | |
end | |
@clusters << one_node_clusters unless one_node_clusters.empty? | |
@clusters | |
end | |
def filtered_lines(nodes) | |
readlines.each.with_index do |line, i| | |
yield(line) if i < 3 || i > readlines.length - 2 | |
yield(line) if line =~ NODE_PATTERN && nodes.include?(line.match(NODE_PATTERN)[1]) | |
yield(line) if line =~ EDGE_PATTERN && nodes.include?(line.match(EDGE_PATTERN)[1]) && | |
nodes.include?(line.match(EDGE_PATTERN)[2]) | |
end | |
end | |
private | |
def readlines | |
@readlines ||= File.readlines(@filename) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rake/clean' | |
require_relative 'dot_file_parser' | |
namespace :railroady_demo do | |
desc 'set up railroady demo prerequisites' | |
task :setup do | |
# Usage: bin/rake railroady_demo:setup | |
system 'brew install graphviz librsvg' | |
end | |
end | |
MODEL_PATTERN = %r{\Adoc/models_(brief|complete)\.dot\z} | |
rule MODEL_PATTERN => 'railroady_demo:setup' do |t| | |
# Usage: bin/rake doc/models_{brief,complete}.dot | |
require 'open3' | |
command = ['railroady', '-o', t.name, '-lamM'] | |
command << '-b' if 'brief' == t.name.match(MODEL_PATTERN)[1] | |
stdin, stdout, stderr = Open3.popen3(*command) | |
stdin.close | |
puts stderr.read + stdout.read | |
end | |
CLEAN << FileList['doc/*.dot'] | |
desc 'clusters' | |
task clusters: 'doc/models_brief.dot' do |t| | |
dot_parser = DotFileParser.new(t.source) | |
source_parts = t.source.split('.') | |
dot_parser.clusters.each.with_index do |cluster_nodes, i| | |
output_file = [source_parts[0..-2], "cluster#{i}", source_parts[-1]].join('.') | |
File.open(output_file, 'w') do |output| | |
dot_parser.filtered_lines(cluster_nodes) do |line| | |
output << line | |
end | |
end | |
end | |
end | |
rule %r{\Adoc/.*\.svg\z} => '.dot' do |t| | |
# Usage: bin/rake doc/<anything>.svg | |
require 'shellwords' | |
system "dot -Tsvg #{Shellwords.escape(t.source)} > " \ | |
"#{Shellwords.escape(t.name)}" | |
end | |
CLEAN << FileList['doc/*.svg'] | |
rule %r{\Adoc/.*\.pdf\z} => '.svg' do |t| | |
# Usage: bin/rake doc/<anything>.pdf | |
require 'shellwords' | |
system "rsvg-convert -f pdf -o #{Shellwords.escape(t.name)} " \ | |
"#{Shellwords.escape(t.source)}" | |
end | |
CLOBBER << FileList['doc/*.pdf'] | |
desc 'Generate cluster PDFs' | |
task generate_pdfs: FileList['doc/*.cluster*.dot'].ext('.pdf') | |
# Usage: bin/rake clusters generate_pdfs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment