我正在编写一个ruby DSL,它将用于代码生成许多Objective-C++函数。我希望每个函数的名称都源自其ruby DSL 源文件的名称。
例如,给定这个源文件clusterOptions.rb
:
require './vMATCodeMonkey'
VMATCodeMonkey.new(:print).options_processor <<EOS
-cutoff: flag: set('useCutoff', true), arg: vector('double')
-depth: flag: set('useInconsistent', true), arg: scalar('double', default: 2.0)
-maxclust: flag: set('useCutoff', false), arg: vector('index')
EOS
当VMATCodeMonkey.new(:print)
表达式被评估时,理想情况下,我希望新对象以某种方式捕获clusterOptions.rb
源文件名。那可能吗?
如果(我怀疑)它不是,在ruby 中是否有一个很好的习惯用法来完成此功能[例如,使源文件名有效地成为 DSL 捕获的规范的一部分] ?
[虽然我怀疑不可能完全按照我所描述的那样做,但我还是问了,因为我不止一次对ruby 的晦涩功能感到惊讶。]
编辑:我知道__FILE__
;我正在寻找的是一些以 DSL 为中心的方式来捕获 DSL 源文件的名称,而无需__FILE__
在 DSL 源中明确提及。嗯,现在我正在尝试解释它,也许是从类initialize
方法中爬取堆栈跟踪?
解决方案
感谢 tadman,这是我的VMATCodeMonkey#initialize
方法:
def initialize(out_opt = :print)
@caller_file = caller(1)[0].split(':')[0]
case out_opt
when :pbcopy
@out = IO.popen('pbcopy', 'w')
when :print
@out = $stdout
else
raise ArgumentError, "#{out_opt} is not an option!"
end
@out.puts "// vMATCodeMonkey's work; do not edit by hand!\n\n"
initialize_options_processor
end
这就是它捕获的内容:
@caller_file = "/Users/Shared/Source/vMAT/ruby/clusterOptions.rb"