RubyMotion Preprocessor Code
This morning I had an interesting thought about how we could possible have C macro like functionality in RubyMotion, and I believe I've come up with a somewhat suitable solution, though it could definitely still use some work.
The basic idea is the anything between the comments #MBEGIN
and #MEND
will be executed before compilation is done. If a file that is in app.files
contains these comments, then the file in app.files
is replaced with a preprocessed version in the tmp
directory.
Lets look at an example to explain.
Setting up the preprocessor
To actually use the preprocessor, you need to do a few things.
First, copy and paste preprocessor.rb
into lib/preprocessor.rb
in your project from this gist: https://gist.github.com/FluffyJack/9678692
Then require the preprocessor in your Rakefile and call it in your setup block.
# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project/template/ios'
require './lib/preprocessor'
begin
require 'bundler'
Bundler.require
rescue LoadError
end
Motion::Project::App.setup do |app|
# Use `rake config' to see complete project settings.
app.name = 'Macros'
Preprocessor.process(app)
end
Using the preprocessor
Lastly, start using the syntax! Here is an example where we're adding a test
method to our AppDelegate
and calling it in the did finish launching method, but only if we do test=true rake
.
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
#MBEGIN
#if ENV['test']
# @contents << "self.test"
#end
#MEND
true
end
#MBEGIN
#if ENV['test']
#@contents << "def test"
#@contents << " puts 'test'"
#@contents << "end"
#end
#MEND
end
The code in the macro blocks is executed in the context of the processor, and so to add lines of code to the file, we just append it to the @contents
instance variable of the ProcessedFile
. It also means we have access to the ENV
hash.
I thought this was pretty awesome because it means we can run ruby code to preprocess our files. This could come in handy for debugging code, or platform specific code, because the result will never end up in the compiled files unless we tell it to.
The result
If you run just rake
, the preprocessed file that gets created will simply look like this.
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
true
end
end
But if you run test=true rake
then the extra code will be added.
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
self.test
true
end
def test
puts 'test'
end
end
It's actually horribly formatted, but I've cleaned it up here. Seeming it's just a temp file though, we'll never be working with these preprocessed files.
Would you use this?
Tell me on twitter if you would use this in your project, if enough people are interested I'll create a gem. https://twitter.com/RubyMotionTV