Skip to content

Instantly share code, notes, and snippets.

@rosenfeld
Created April 3, 2014 16:53
Show Gist options
  • Save rosenfeld/9958332 to your computer and use it in GitHub Desktop.
Save rosenfeld/9958332 to your computer and use it in GitHub Desktop.
Demonstrates how to generate refined version for Facets gem
Simple script that should work if you follow the convention of declaring a single outer class per file with simple class names and structure.
Some files may not be compatible with refinements and should have some comment like "#skip-refinement-conversion" in the file header (first 10_000 chars of the file). The "class" line should also be in the header section of the file.
Files skipped will be copied "as is" to the new directory.
require 'fileutils'
class Converter
DEST = 'lib-refined'
def self.convert
new.convert
end
def convert
FileUtils.mkdir_p DEST
Dir['lib/**/*.rb'].each do |fn|
newfn = fn.sub 'lib', DEST
dir = File.dirname(newfn)
basename = File.basename fn
FileUtils.mkdir_p dir
File.write newfn, processed_file(fn)
end
end
def processed_file(fn)
content = file_content fn
header = content[0..10_000] # adjust for your needs or use full content
return content if header =~ /\#skip-refinement-conversion/
return content unless match = header.match(/.*?^(\s*class\s.*?$)/m)
first_class_line = match[1]
match = first_class_line.match /\s*class\s*([A-Z]\w*)\s*$/
return content unless match # skip complex cases
refinement_replacement = "module Facets\nrefine #{match[1]} do"
# assume a single "class XXX\n...\nend" block per file
content.sub(first_class_line, refinement_replacement) + "\nend"
end
def file_content(fn)
File.read fn
end
end
Converter.convert
# ruby -I lib-refined/core test.rb
require 'facets/array/before'
using Facets
puts [1, 2].before 2 # 1 is printed
@trans
Copy link

trans commented Apr 4, 2014

You gave me an idea.

require 'finder'

def refinement(feature)
  file = Find.feature(feature, :absolute=>true).first

  raise LoadError unless file

  text = File.read(file)

  text = text.gsub(/^\s*class\s*([A-Z]\w*)\s*$/, 'module Refinements; refine \1 do')

  text = text + "\nend"

  eval text, TOPLEVEL_BINDING

  return Refinements
end

Usage:

using refinement('facets/string/indent')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment