twiddler-utils 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/twid-utils +52 -0
- data/doc/README +2 -0
- data/doc/Specifications +15 -0
- data/doc/coverage/index.html +170 -0
- data/doc/coverage/jquery-1.3.2.min.js +19 -0
- data/doc/coverage/jquery.tablesorter.min.js +15 -0
- data/doc/coverage/lib-twiddler-config_rb.html +2547 -0
- data/doc/coverage/lib-twiddler-lint_rb.html +417 -0
- data/doc/coverage/lib-twiddler-parser_rb.html +645 -0
- data/doc/coverage/lib-twiddler-rendering_rb.html +201 -0
- data/doc/coverage/lib-twiddler-target_builder_rb.html +783 -0
- data/doc/coverage/print.css +12 -0
- data/doc/coverage/rcov.js +42 -0
- data/doc/coverage/screen.css +270 -0
- data/lib/twiddler/config.rb +414 -0
- data/lib/twiddler/lint.rb +59 -0
- data/lib/twiddler/parser.rb +97 -0
- data/lib/twiddler/rendering.rb +23 -0
- data/lib/twiddler/target_builder.rb +120 -0
- data/spec_help/file-sandbox.rb +164 -0
- data/spec_help/fixtures/TWIDDLER.CFG +0 -0
- data/spec_help/gem_test_suite.rb +17 -0
- data/spec_help/spec_helper.rb +4 -0
- data/spec_help/ungemmer.rb +36 -0
- data/templates/cheatsheet.erb +38 -0
- data/templates/lua.erb +51 -0
- metadata +201 -0
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require 'twiddler/config'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Twiddler
         | 
| 4 | 
            +
              module Lint
         | 
| 5 | 
            +
                def self.check(config)
         | 
| 6 | 
            +
                  report = []
         | 
| 7 | 
            +
                  Rule::registered.each do |rule|
         | 
| 8 | 
            +
                    report << rule.new(config).check
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  report
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class Rule
         | 
| 14 | 
            +
                  class << self
         | 
| 15 | 
            +
                    def register
         | 
| 16 | 
            +
                      @@registered ||= []
         | 
| 17 | 
            +
                      @@registered << self
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def registered
         | 
| 21 | 
            +
                      @@registered || []
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def initialize(config)
         | 
| 26 | 
            +
                    @config = config
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def check()
         | 
| 30 | 
            +
                    return ""
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                class MissingStrokes < Rule
         | 
| 35 | 
            +
                  register
         | 
| 36 | 
            +
                  def check()
         | 
| 37 | 
            +
                    all_strokes = []
         | 
| 38 | 
            +
                    @config.keytable.each do |key|
         | 
| 39 | 
            +
                      all_strokes << [key.code, ""]
         | 
| 40 | 
            +
                      all_strokes << [key.code, "shift"] if key.has_mod?("shift")
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    @config.keyboard.each do |chord|
         | 
| 44 | 
            +
                      next unless chord.single?
         | 
| 45 | 
            +
                      all_strokes.delete(@config.keytable.normalized(chord[0]))
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    if all_strokes.empty?
         | 
| 49 | 
            +
                      return "Missing: all normal keystrokes accounted for"
         | 
| 50 | 
            +
                    else
         | 
| 51 | 
            +
                      return "Config lacks strokes: #{all_strokes.map{|str| @config.keytable[*str]}.inspect}"
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                  
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| @@ -0,0 +1,97 @@ | |
| 1 | 
            +
            require 'twiddler/config'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Twiddler
         | 
| 4 | 
            +
              class Parser
         | 
| 5 | 
            +
                def self.parse(data)
         | 
| 6 | 
            +
                  version = *data.unpack("c")
         | 
| 7 | 
            +
                  case version
         | 
| 8 | 
            +
                  when 4
         | 
| 9 | 
            +
                    V4Parser.new(data, 1).go.parsed
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                class V4Parser
         | 
| 14 | 
            +
                  def initialize(raw, skipped = 0)
         | 
| 15 | 
            +
                    @data = raw
         | 
| 16 | 
            +
                    @refs = Hash.new{|h,k| h[k] = [:missing_ref]}
         | 
| 17 | 
            +
                    bytes_hex
         | 
| 18 | 
            +
                    @index = 0
         | 
| 19 | 
            +
                    consume("x" * skipped)
         | 
| 20 | 
            +
                    bytes_hex
         | 
| 21 | 
            +
                    @config = Config.new()
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def parsed
         | 
| 25 | 
            +
                    return @config
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def consume(template)
         | 
| 29 | 
            +
                    old_len = @data.length
         | 
| 30 | 
            +
                    values = @data.unpack(template + "a*")
         | 
| 31 | 
            +
                    @data = values.pop
         | 
| 32 | 
            +
                    @index += old_len - @data.length
         | 
| 33 | 
            +
                    return values
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def bytes_hex(count = 8)
         | 
| 37 | 
            +
                    "0x%04x:#{' %02x'*count}" % ([@index] + @data.unpack("c" * count))
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def go()
         | 
| 41 | 
            +
                    total_size = @data.length + 1
         | 
| 42 | 
            +
                    @keyboard_chord_table, @mouse_chord_table, @multichar_table = *consume("vvv")
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    @config.configs[:raw] = *consume("a#{@keyboard_chord_table - @index}")
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    until @index >= @mouse_chord_table
         | 
| 47 | 
            +
                      key1234, mod_or_ff, keyindex = consume("B16B8c")
         | 
| 48 | 
            +
                      exit if @index > 685 
         | 
| 49 | 
            +
                      if keyindex == 0 and 
         | 
| 50 | 
            +
                        key1234 == "0000000000000000" and 
         | 
| 51 | 
            +
                        mod_or_ff == "00000000"
         | 
| 52 | 
            +
                        next
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      chord = Config::KeyChord.new
         | 
| 56 | 
            +
                      chord.keydata = key1234
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                      if(mod_or_ff == "11111111")
         | 
| 59 | 
            +
                        @refs[keyindex] = chord
         | 
| 60 | 
            +
                      else
         | 
| 61 | 
            +
                        chord.add_keystroke(mod_or_ff, keyindex)
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                      @config.keyboard << chord
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    while @index < @multichar_table
         | 
| 68 | 
            +
                      key1234, data = consume("B16B8")
         | 
| 69 | 
            +
                      if key1234 == "0000000000000000" and 
         | 
| 70 | 
            +
                        data == "00000000"
         | 
| 71 | 
            +
                        next
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                      chord_record = Config::MouseChord.new
         | 
| 75 | 
            +
                      chord_record.keydata = key1234
         | 
| 76 | 
            +
                      chord_record.data = data
         | 
| 77 | 
            +
                      @config.mouse << chord_record
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    data_idx = 0
         | 
| 81 | 
            +
                    until @data.size == 0 do
         | 
| 82 | 
            +
                      data_size = *consume("v")
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                      chord_data = []
         | 
| 85 | 
            +
                      ((data_size-1)/2).times do 
         | 
| 86 | 
            +
                        mod, idx = *consume("B8c")
         | 
| 87 | 
            +
                        next if idx == 0 #Not sure this is sufficient
         | 
| 88 | 
            +
                        @refs[data_idx].add_keystroke(mod, idx)
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
                      data_idx += 1
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    return self
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'erb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Twiddler
         | 
| 4 | 
            +
              class Rendering
         | 
| 5 | 
            +
                def initialize(config)
         | 
| 6 | 
            +
                  @config = config
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def embed(name)
         | 
| 10 | 
            +
                  path = template_path(name)
         | 
| 11 | 
            +
                  template = File::read(path)
         | 
| 12 | 
            +
                  erb = ERB.new(template, nil, "%>")
         | 
| 13 | 
            +
                  erb.filename = path
         | 
| 14 | 
            +
                  mod = erb.def_module("render")
         | 
| 15 | 
            +
                  @config.extend(mod)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def template_path(name)
         | 
| 19 | 
            +
                  path = File::expand_path("../../templates/#{name}.erb", 
         | 
| 20 | 
            +
                                           File::dirname(__FILE__))
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,120 @@ | |
| 1 | 
            +
            require 'fileutils'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Twiddler
         | 
| 4 | 
            +
              module TargetBuilder
         | 
| 5 | 
            +
                def self.build(output_dir, dictionary, config)
         | 
| 6 | 
            +
                  FileUtils::mkdir_p(output_dir)
         | 
| 7 | 
            +
                  File::open(dictionary, "r") do |dict|
         | 
| 8 | 
            +
                    Builder::registered.each do |klass|
         | 
| 9 | 
            +
                      dict.rewind
         | 
| 10 | 
            +
                      klass.new(output_dir, dict, config).go
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                class Builder
         | 
| 16 | 
            +
                  class << self
         | 
| 17 | 
            +
                    def register
         | 
| 18 | 
            +
                      @@registered ||= []
         | 
| 19 | 
            +
                      @@registered << self
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def registered
         | 
| 23 | 
            +
                      @@registered || []
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def initialize(dir, dict, config)
         | 
| 28 | 
            +
                    @dir = dir
         | 
| 29 | 
            +
                    @dict = dict
         | 
| 30 | 
            +
                    @config = config
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def output_to(name)
         | 
| 34 | 
            +
                    File::open(File::expand_path("#{name}.list", @dir), "w") do |file|
         | 
| 35 | 
            +
                      yield(file)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def go
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                class RegexpBuilder < Builder
         | 
| 44 | 
            +
                  def match_any_of(list)
         | 
| 45 | 
            +
                    return "(?:#{list.map{|it| Regexp::escape(it)}.join(")|(?:")})"
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  def go
         | 
| 48 | 
            +
                    output_to(filename) do |file|
         | 
| 49 | 
            +
                      @dict.grep(regexp) do |word|
         | 
| 50 | 
            +
                        file.puts(word)
         | 
| 51 | 
            +
                      end
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                class ShortWords < RegexpBuilder
         | 
| 57 | 
            +
                  register
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def filename
         | 
| 60 | 
            +
                    "Short Words"
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def regexp
         | 
| 64 | 
            +
                    /^.{1,5}$/
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                class Macros < RegexpBuilder
         | 
| 69 | 
            +
                  register
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def filename
         | 
| 72 | 
            +
                    "Macros"
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def regexp
         | 
| 76 | 
            +
                    macros = @config.keyboard.find_all do |chord|
         | 
| 77 | 
            +
                      chord.keystrokes.length > 1 and chord.keystrokes.all? do |stroke|
         | 
| 78 | 
            +
                        stroke[1].empty?
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                    return %r{^.{0,1}(?:#{match_any_of(macros.map{|chord| chord.render_action})}).{0,1}$}
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                class Flow < RegexpBuilder
         | 
| 86 | 
            +
                  register
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  def filename
         | 
| 89 | 
            +
                    "Flow"
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  def regexp
         | 
| 93 | 
            +
                    flow = []
         | 
| 94 | 
            +
                    chords = @config.keyboard.find_all do |chord|
         | 
| 95 | 
            +
                      chord.single? and chord.keystrokes[0][1].empty? and Config.keytable.is_tagged?(chord.keystrokes[0][0], :letters)
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    chords.each do |first|
         | 
| 99 | 
            +
                      chords.each do |second|
         | 
| 100 | 
            +
                        next if first == second
         | 
| 101 | 
            +
                        pairs = first.rows.zip(second.rows).find_all{|one,two| one != two}
         | 
| 102 | 
            +
                        case pairs.length 
         | 
| 103 | 
            +
                        when 1
         | 
| 104 | 
            +
                          flow << first.render_action + second.render_action
         | 
| 105 | 
            +
                          next
         | 
| 106 | 
            +
                        when 2
         | 
| 107 | 
            +
                          next if pairs.find{|pair| !pair.include?(:open)}
         | 
| 108 | 
            +
                          if pairs[0][0] == pairs[1][1] and pairs[0][1] == pairs[1][0]
         | 
| 109 | 
            +
                            flow << first.render_action + second.render_action
         | 
| 110 | 
            +
                            next
         | 
| 111 | 
            +
                          end
         | 
| 112 | 
            +
                        end
         | 
| 113 | 
            +
                      end
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    return %r{^.{0,1}(?:#{match_any_of(flow)}).{0,1}$}
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
              end
         | 
| 120 | 
            +
            end
         | 
| @@ -0,0 +1,164 @@ | |
| 1 | 
            +
            require 'ftools'
         | 
| 2 | 
            +
            require 'fileutils'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module FileSandbox
         | 
| 5 | 
            +
              def self.included(spec)
         | 
| 6 | 
            +
                return unless spec.respond_to? :before
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                spec.before do
         | 
| 9 | 
            +
                  setup_sandbox
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                spec.after do
         | 
| 13 | 
            +
                  teardown_sandbox
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              class HaveContents
         | 
| 18 | 
            +
                def initialize(contents)
         | 
| 19 | 
            +
                  @contents = contents
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def matches?(target)
         | 
| 23 | 
            +
                  case @contents
         | 
| 24 | 
            +
                  when Regexp
         | 
| 25 | 
            +
            	@contents =~ target.contents
         | 
| 26 | 
            +
                  when String
         | 
| 27 | 
            +
            	@contents == target.contents
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def have_contents(expected)
         | 
| 33 | 
            +
                HaveContents.new(expected)
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              attr_reader :sandbox
         | 
| 37 | 
            +
              
         | 
| 38 | 
            +
              def in_sandbox(&block)
         | 
| 39 | 
            +
                raise "I expected to create a sandbox as you passed in a block to me" if !block_given?
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                setup_sandbox
         | 
| 42 | 
            +
                original_error = nil
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                begin
         | 
| 45 | 
            +
                  yield @sandbox
         | 
| 46 | 
            +
                rescue => e
         | 
| 47 | 
            +
                  original_error = e
         | 
| 48 | 
            +
                  raise
         | 
| 49 | 
            +
                ensure
         | 
| 50 | 
            +
                  begin
         | 
| 51 | 
            +
                    teardown_sandbox
         | 
| 52 | 
            +
                  rescue
         | 
| 53 | 
            +
                    if original_error
         | 
| 54 | 
            +
                      STDERR.puts "ALERT: a test raised an error and failed to release some lock(s) in the sandbox directory"
         | 
| 55 | 
            +
                      raise(original_error)
         | 
| 56 | 
            +
                    else
         | 
| 57 | 
            +
                      raise
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def setup_sandbox(path = '__sandbox')
         | 
| 64 | 
            +
                unless @sandbox
         | 
| 65 | 
            +
                  @sandbox = Sandbox.new(path)
         | 
| 66 | 
            +
                  @__old_path_for_sandbox = Dir.pwd
         | 
| 67 | 
            +
                  Dir.chdir(@sandbox.root)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def teardown_sandbox
         | 
| 72 | 
            +
                if @sandbox
         | 
| 73 | 
            +
                  Dir.chdir(@__old_path_for_sandbox)
         | 
| 74 | 
            +
                  @sandbox.clean_up
         | 
| 75 | 
            +
                  @sandbox = nil
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              class Sandbox
         | 
| 80 | 
            +
                attr_reader :root
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                def initialize(path = '__sandbox')
         | 
| 83 | 
            +
                  @root = File.expand_path(path)
         | 
| 84 | 
            +
                  clean_up
         | 
| 85 | 
            +
                  FileUtils.mkdir_p @root
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
                
         | 
| 88 | 
            +
                def [](name)
         | 
| 89 | 
            +
                  SandboxFile.new(File.join(@root, name), name)
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                # usage new :file=>'my file.rb', :with_contents=>'some stuff'
         | 
| 93 | 
            +
                def new(options)
         | 
| 94 | 
            +
                  if options.has_key? :directory
         | 
| 95 | 
            +
                    dir = self[options.delete(:directory)]
         | 
| 96 | 
            +
                    FileUtils.mkdir_p dir.path
         | 
| 97 | 
            +
                  else
         | 
| 98 | 
            +
                    file = self[options.delete(:file)]
         | 
| 99 | 
            +
                    if (binary_content = options.delete(:with_binary_content) || options.delete(:with_binary_contents))
         | 
| 100 | 
            +
                      file.binary_content = binary_content
         | 
| 101 | 
            +
                    else
         | 
| 102 | 
            +
                      file.content = (options.delete(:with_content) || options.delete(:with_contents) || '')
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
                  
         | 
| 106 | 
            +
                  raise "unexpected keys '#{options.keys.join(', ')}'" unless options.empty?
         | 
| 107 | 
            +
                  
         | 
| 108 | 
            +
                  dir || file
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
                
         | 
| 111 | 
            +
                def remove(options)
         | 
| 112 | 
            +
                  name = File.join(@root, options[:file])
         | 
| 113 | 
            +
                  FileUtils.remove_file name
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
                
         | 
| 116 | 
            +
                def clean_up
         | 
| 117 | 
            +
                  FileUtils.rm_rf @root
         | 
| 118 | 
            +
                  if File.exists? @root
         | 
| 119 | 
            +
                    raise "Could not remove directory #{@root.inspect}, something is probably still holding a lock on it"
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
             | 
| 125 | 
            +
              class SandboxFile
         | 
| 126 | 
            +
                attr_reader :path
         | 
| 127 | 
            +
                
         | 
| 128 | 
            +
                def initialize(path, sandbox_path)
         | 
| 129 | 
            +
                  @path = path
         | 
| 130 | 
            +
                  @sandbox_path = sandbox_path
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                def inspect
         | 
| 134 | 
            +
                  "SandboxFile: #@sandbox_path"
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                def exist?
         | 
| 138 | 
            +
                  File.exist? path
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                def content
         | 
| 142 | 
            +
                  File.read path
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
                
         | 
| 145 | 
            +
                def content=(content)
         | 
| 146 | 
            +
                  FileUtils.mkdir_p File.dirname(@path)
         | 
| 147 | 
            +
                  File.open(@path, "w") {|f| f << content}
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
                
         | 
| 150 | 
            +
                def binary_content=(content)
         | 
| 151 | 
            +
                  FileUtils.mkdir_p File.dirname(@path)
         | 
| 152 | 
            +
                  File.open(@path, "wb") {|f| f << content}
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                def create
         | 
| 156 | 
            +
                  self.content = ''
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                alias exists? exist?
         | 
| 160 | 
            +
                alias contents content
         | 
| 161 | 
            +
                alias contents= content=
         | 
| 162 | 
            +
                alias binary_contents= binary_content=    
         | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
            end
         |