lib/utils/config_file.rb
require 'tins'
require 'tins/xt/string'
class Utils::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.config_settings ||= []
config_settings << name.to_sym
dsl_accessor name, *r, &block
self
end
attr_accessor :config_settings
end
def initialize(&block)
block and instance_eval(&block)
end
def to_ruby(depth = 0)
result = ''
result << ' ' * 2 * depth <<
"#{self.class.name[/::([^:]+)\z/, 1].underscore} do\n"
for name in self.class.config_settings
value = __send__(name)
if value.respond_to?(:to_ruby)
result << ' ' * 2 * (depth + 1) << value.to_ruby(depth + 1)
else
result << ' ' * 2 * (depth + 1) <<
"#{name} #{Array(value).map(&:inspect) * ', '}\n"
end
end
result << ' ' * 2 * depth << "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
config :max_matches, 10
config :index_expire_after
end
def discover(&block)
if block
@discover = Discover.new(&block)
end
@discover ||= Discover.new
end
class Scope < 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 scope(&block)
if block
@scope = Scope.new(&block)
end
@scope ||= Scope.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, 'tmux'
config :env, {}
config :login_session do
ENV.fetch('HOME', 'session')
end
def initialize
super
self.terminal_multiplexer = terminal_multiplexer
end
def terminal_multiplexer=(terminal_multiplexer)
@multiplexer = terminal_multiplexer.to_s
@multiplexer =~ /\A(screen|tmux)\z/ or
fail "invalid terminal_multiplexer #{terminal_multiplexer.inspect} was configured"
end
def multiplexer_list
case @multiplexer
when 'screen'
'screen -ls'
when 'tmux'
'tmux ls'
end
end
def multiplexer_new(session)
case @multiplexer
when 'screen'
'false'
when 'tmux'
'tmux -u new -s "%s"' % session
end
end
def multiplexer_attach(session)
case @multiplexer
when 'screen'
'screen -DUR "%s"' % session
when 'tmux'
'tmux -u attach -d -t "%s"' % session
end
end
class CopyPaste < BlockConfig
config :bind_address, 'localhost'
config :port, 6166
config :host, 'localhost'
config :host_port, 6166
def to_s
[ bind_address, port, host, host_port ] * ':'
end
end
def copy_paste(enable = false, &block)
if @copy_paste
@copy_paste
else
if block
@copy_paste = CopyPaste.new(&block)
elsif enable
@copy_paste = CopyPaste.new {}
end
end
end
self.config_settings << :copy_paste
end
def ssh_tunnel(&block)
if block
@ssh_tunnel = SshTunnel.new(&block)
end
@ssh_tunnel ||= SshTunnel.new
end
class Edit < BlockConfig
config :vim_path do `which vim`.chomp end
config :vim_default_args, nil
end
def edit(&block)
if block
@edit = Edit.new(&block)
end
@edit ||= Edit.new
end
class Classify < BlockConfig
config :shift_path_by_default, 0
config :shift_path_for_prefix, []
end
def classify(&block)
if block
@classify = Classify.new(&block)
end
@classify ||= Classify.new
end
class SyncDir < BlockConfig
config :skip_path, %r((\A|/)\.\w)
def skip?(path)
path =~ skip_path
end
end
def sync_dir(&block)
if block
@sync_dir = SyncDir.new(&block)
end
@sync_dir ||= SyncDir.new
end
def to_ruby
result = "# vim: set ft=ruby:\n"
for bc in %w[search discover strip_spaces probe ssh_tunnel edit classify]
result << "\n" << __send__(bc).to_ruby
end
result
end
end