require 'dslkit/polite' require 'tins/xt/string' class Utils::Config::ConfigFile class << self attr_accessor :config_file_paths end self.config_file_paths = [ '/etc/utilsrc', '~/.utilsrc', './.utilsrc', ] include DSLKit::Interpreter class ConfigFileError < StandardError; end def initialize end def configure_from_paths(paths = self.class.config_file_paths) for config_file_path in paths parse_config_file config_file_path end end def parse_config_file(config_file_path) config_file_path = File.expand_path(config_file_path) File.open(config_file_path) do |cf| parse cf.read end self rescue SystemCallError => e $DEBUG and warn "Couldn't read config file "\ "#{config_file_path.inspect}: #{e.class} #{e}" return nil end def parse(source) interpret_with_binding source, binding self end class BlockConfig class << self def inherited(modul) modul.extend DSLKit::DSLAccessor super end def config(name, *r, &block) self.dsl_attributes ||= [] dsl_attributes << name.to_sym dsl_accessor name, *r, &block self end attr_accessor :dsl_attributes end def initialize(&block) block and instance_eval(&block) end def to_ruby result = '' result << "#{self.class.name[/::([^:]+)\z/, 1].underscore} do\n" for da in self.class.dsl_attributes result << " #{da} #{Array(__send__(da)).map(&:inspect) * ', '}\n" end result << "end\n" end end class Probe < BlockConfig config :test_framework, :'test-unit' config :include_dirs, %w[lib test tests ext spec] def include_dirs_argument Array(include_dirs) * ':' end def initialize(&block) super test_frameworks_allowed = [ :'test-unit', :rspec ] test_frameworks_allowed.include?(test_framework) or raise ConfigFileError, "test_framework has to be in #{test_frameworks_allowed.inspect}" end end def probe(&block) if block @probe = Probe.new(&block) end @probe ||= Probe.new end class FileFinder < BlockConfig def prune?(basename) Array(prune_dirs).any? { |pd| pd.match(basename.to_s) } end def skip?(basename) Array(skip_files).any? { |sf| sf.match(basename.to_s) } end end class Search < FileFinder config :prune_dirs, /\A(\.svn|\.git|CVS|tmp)\z/ config :skip_files, /(\A\.|\.sw[pon]\z|\.log\z|~\z)/ end def search(&block) if block @search = Search.new(&block) end @search ||= Search.new end class Discover < FileFinder config :prune_dirs, /\A(\.svn|\.git|CVS|tmp)\z/ config :skip_files, /(\A\.|\.sw[pon]\z|\.log\z|~\z)/ config :binary, false end def discover(&block) if block @discover = Discover.new(&block) end @discover ||= Discover.new end class StripSpaces < FileFinder config :prune_dirs, /\A(\..*|CVS)\z/ config :skip_files, /(\A\.|\.sw[pon]\z|\.log\z|~\z)/ end def strip_spaces(&block) if block @strip_spaces = StripSpaces.new(&block) end @strip_spaces ||= StripSpaces.new end class SshTunnel < BlockConfig config :terminal_multiplexer, 'sshscreen' def initialize super @multiplexer = terminal_multiplexer.to_s @multiplexer =~ /\A(sshscreen|tmux)\z/ or fail "invalid terminal_multiplexer #{terminal_multiplexer.inspect} was configured" end def multiplexer_list case @multiplexer when 'sshscreen' 'screen -ls' when 'tmux' 'tmux ls' end end def multiplexer_new(session) case @multiplexer when 'sshscreen' 'false' when 'tmux' 'tmux new -s "%s"' % session end end def multiplexer_attach(session) case @multiplexer when 'sshscreen' 'screen -DUR "%s"' % session when 'tmux' 'tmux attach -t "%s"' % session end end end def ssh_tunnel(&block) if block @ssh_tunnel = SshTunnel.new(&block) end @ssh_tunnel ||= SshTunnel.new end def to_ruby result = "# vim: set ft=ruby:\n" for bc in %w[search discover strip_spaces probe ssh_tunnel] result << "\n" << __send__(bc).to_ruby end result end end