<commit_before>#class Word < Struct.new(:pronunciations, :gloss)
#  def with_changed_pronunciations(word, pronunciations)
#    Word.new(pronunciations, word.gloss)
#  end
#
#  def each_pronunciation
#    if block_given?
#      pronunciations.each do |p|
#        yield p
#      end
#    else
#      pronunciations.each
#    end
#  end
#
#  def == other_word
#    other_word.gloss == gloss
#    other_word.each_pronunciation.all? do |p|
#      pronunciations.include? p
#    end
#  end
#end
#
#class Change
#  def apply_to word
#    word
#  end
#end
#
#class Checkpoint
#  def golden_wordlist= wordlist
#    @wordlist = wordlist
#  end
#
#  def ok? word
#    golden_word = wordlist.find_by_gloss word.gloss
#    word == golden_word
#  end
#end

class Change < Struct.new(:find, :replacement, :context_before, :context_after)
  def apply_to word
    Application.new(word, self).result
    #parts = word.partition(find)
    #return word if parts[0] == word
    #
    #replaced = context_before =~ parts[0] && context_after =~ parts[2] ? replace : parts[1]
    #
    #parts[0] + replaced + apply_to(parts[2])
  end

  def replace(part)
    if Proc === replacement
      replacement.call(part)
    else
      replacement
    end
  end

  def self.build(find, transformation, context)
    context_before, _, context_after = context.partition('_')
    context_before = Regexp.new(context_before + '$')
    context_after = Regexp.new('^' + context_after)

    new(Regexp.new(find), transformation, context_before, context_after)
  end

  class Application < Struct.new(:word, :change)
    def result
      # TODO: passing in the suffix might not be enough; what if the beginning of the word has necessary context?
      return word if element_to_change_not_found?
      prefix + changed_part + result_of_changing_suffix
    end

    private

    def element_to_change_not_found?
      prefix == word
    end

    def changed_part
      change_applies? ? change.replace(part_to_change) : part_to_change
    end

    def result_of_changing_suffix
      Application.new(suffix, change).result
    end

    def prefix
      parts[0]
    end

    def part_to_change
      parts[1]
    end

    def suffix
      parts[2]
    end

    def parts
      @parts ||= word.partition(change.find)
    end

    def change_applies?
      change.context_before =~ prefix && change.context_after =~ suffix
    end
  end
end

words = [
  'folon',
  'bad',
  'bat',
  'bazork',
  'batzog'
]

lengthen = ->(v) {
  v + v
}

changes = [
  Change.new(/o/, 'oo', /[flo]$/, /^[l]/),
  Change.build('[aeiou]', lengthen, '_[dbgz]'),<commit_msg>changes respect context<commit_after>class Change < Struct.new(:find, :replacement, :context_before, :context_after)
  def apply_to word, prefix=''
    parts = word.partition(find)
    if parts[0] == word
      return prefix + word
    end

    prefix = prefix + parts[0]

    replaced = context_before =~ prefix && context_after =~ parts[2] ? replace(parts[1]) : parts[1]

    apply_to(parts[2], prefix + replaced)
  end

  def replace(part)
    if Proc === replacement
      replacement.call(part)
    else
      replacement
    end
  end

  def self.build(find, transformation, context)
    context_before, _, context_after = context.partition('_')
    context_before = Regexp.new(context_before + '$')
    context_after = Regexp.new('^' + context_after)

    new(Regexp.new(find), transformation, context_before, context_after)
  end
end

words = [
  'folon',
  #'bad',
  #'bat',
  #'bazork',
  #'batzog',
  #'dazod',
  'baiiiar'
]

lengthen = ->(v) {
  v + v
}

changes = [
  Change.new(/o/, 'oo', /[flo]$/, /^[l]/),
  Change.build('[aeiou]', lengthen, '_[dbgz]'),
{'fraction_non_alphanumeric': 0.12673375033995105, 'fraction_numerical': 0.004079412564590699, 'mean_word_length': 3.0821309655937847, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3450606', 'n_tokens_mistral': 1308, 'n_tokens_neox': 1274, 'n_words': 294}