Skip to content

Instantly share code, notes, and snippets.

@louisgillies
Created March 28, 2010 10:16
Show Gist options
  • Save louisgillies/346689 to your computer and use it in GitHub Desktop.
Save louisgillies/346689 to your computer and use it in GitHub Desktop.
Allows easy patching and editing of files with strings
# Allows easy patching and editing of files with strings
#
# Extracted from methods seen in adva cms setup.rb
# See http://github.com/svenfuchs/adva_cms
# Thought it would be useful to extend the String and File classes to include this functionality.
# I find it useful when running install hooks for plugins.
module Patch
module InstanceMethods
module StringMethods
def patch(insert, mode = :insert_after)
case mode
when :change
"#{insert}"
when :insert_after
"#{self}\n#{insert}"
when :insert_before
"#{insert}\n#{self}"
else
self.patch(insert, :insert_after)
end
end
end
end
module ClassMethods
module FileMethods
# == Parameters
# *path* - the path to the file to patch
# *current* - the string to look for in the file.
# *insert* - the string to patch into the file.
# *options* - only options is :patch_mode which determines the way to patch the file.
#
# Valid patch modes:
#
# :insert_after - this will add the insert text into the file on the line after current.
#
# :insert_before - This will add the insert text into the file on the line before current.
#
# :change - This will replace the current text with insert text
#
# == Examples
# * The following will find the line "{ config: { a: 1, b: 2 } }" in the the file public/javascripts/file_to_patch.js and change it to "{ config: { a: 3, b: 4} }"
# the_file = File.join("public", "javascripts", "file_to_patch.js")
# File.patch(the_file, "{ config: { a: 1, b: 2 } }", "{ config: { a: 3, b: 4} }", :patch_mode => :change)
def patch(path, current, insert, options = {})
options = {
:patch_mode => :insert_after
}.merge(options)
old_text = current
new_text = current.patch(insert, options[:patch_mode])
content = self.open(path) { |f| f.read }
content.gsub!(old_text, new_text) unless content =~ /#{Regexp.escape(insert)}/mi
self.open(path, 'w') { |f| f.write(content) }
end
end
end
end
String.send(:include, Patch::InstanceMethods::StringMethods)
File.send(:extend, Patch::ClassMethods::FileMethods)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment