1

我正在编写一个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"
4

1 回答 1

1

正在评估的源文件的完整路径存储在__FILE__. 如果你只想要文件名,你会使用:

File.basename(__FILE__)

__FILE__常量对于 C、C++、Perl 和 Python 等是通用的。

如果您需要知道哪个文件调用了当前正在运行的例程,这可能会起作用:

caller(1)[0].split(':')[0]

这假定您的文件名中没有:,但在大多数情况下,这应该是一个相当安全的假设。您还需要在库的入口点调用它。如果它是堆栈中更深的方法,请测试caller(2)等等。

于 2013-04-24T15:50:05.583 回答