Closed edusantana closed 4 years ago
And here's my Rakefile for this small project:
require 'rake'
desc 'gera os testes'
task :test
rule '.pdf' => '.tex' do |t|
sh "latexmk -pdflatex=lualatex -f -pdf #{t.name.ext('.tex')}"
end
FileList['test/**/*.tex'].each do |f|
task :test => f.ext('.pdf')
file f.ext('.pdf') => f
end
desc 'Update Guardfile from Rakefile tasks'
task :upguard do
# https://ruby.github.io/rake/Rake/Task.html#method-c-tasks
Rake::Task.tasks.each do |t|
# ignore tasks that aren't files names
next unless t.name.include? "/"
# guard 'rake', :task => 'doit' do
# watch(%r{^some_files/.+$})
# end
puts "guard 'rake', :task => '#{t.name}' do"
t.prerequisites.each do |p|
puts " watch(%r{^#{p}$})"
end
puts "end"
end
end
I finally got a solution
The solution would be get all task that has file dependencies and create a watch and a action (rake task).
Let's keep a simple example, with this Rakefile:
files = Rake::FileList.new('*.md')
desc "Create a book"
task 'book' => files do
sh "cat #{files.join(" ")} > book.txt"
end
Here we can see it's tasks dependencies:
$ rake -P
rake book
CHANGELOG.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
ISSUE_TEMPLATE.md
README.md
These file are dynamically listed from the FileList.
This Guardfile would solve my problem:
guard :shell do
watch(%r{^(CHANGELOG.md|CODE_OF_CONDUCT.md|CONTRIBUTING.md|ISSUE_TEMPLATE.md|README.md)$}) do |m|
system("rake book")
end
end
To make solution easy, lets create a file called rakelib/guard.rake with this content:
ERB_TEMPLATE = <<~HEREDOC
guard :shell do
<% all_tasks.each do |t, files| %>
watch(%r{^(<%= files.join('|') %>)$}) do |m|
system("rake <%= t %>")
end
<% end %>
end
HEREDOC
desc "Generates a Guardfile from Rake tasks"
task :guard do
all_tasks = {}
current_task = nil
`rake -P`.each_line do |line|
if line.start_with? "rake" then
current_task = line[5..-2]
else
#its a dependency
filename = line.strip
if File.file?(filename) then
all_tasks[current_task] = [] unless all_tasks[current_task]
all_tasks[current_task] << filename
end
end
end
template = ERB.new(ERB_TEMPLATE)
File.write('Guardfile', template.result(binding))
end
Now we can see it:
$ rake -T
rake book # Create a book
rake guard # Generates a Guardfile from Rake tasks
If you call rake guard
it will generate Guardfile with the expected content.
NOTE: If someone find a better solution, please let me know.
I have updated the rakelib/guard.rake
file:
ERB_TEMPLATE = <<~HEREDOC
guard :shell do
<% all_tasks.each do |t, files| %>
watch(%r{^(<%= files.join('|') %>)$}) do |m|
system("rake <%= t %>")
end
<% end %>
end
HEREDOC
desc "Generates a Guardfile from Rake tasks"
task :guard do
app = Rake::application
app.init
app.load_rakefile
all_tasks = {}
app.tasks.each do |t|
t.sources.each do |src|
if File.file?(src) then
all_tasks[t.name] = [] unless all_tasks[t.name]
all_tasks[t.name] << src
end
end
end
template = ERB.new(ERB_TEMPLATE)
File.write('Guardfile', template.result(binding))
end
We could make this inside this lib, so one could require it inside the Rakefile.
It should read tasks from Rake tasks variable and watch which file changed and call the task that has it as a dependency.
When I run
rake -P
I get tasks and dependencies:We can then create a Guardfile with this content:
I have created a simple task file to generate this code:
Here's this
upguard
task execution:I would like this
guard-rake
plugin to do it on the fly. When Rakefile changes it should load new watches.