ramekin 0.2.1 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +32 -1
- data/lib/ramekin/bends.rb +10 -17
- data/lib/ramekin/cli.rb +25 -10
- data/lib/ramekin/meta.rb +5 -6
- data/lib/ramekin/sample_pack.rb +59 -12
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4d868f9a713e079e67a612eb195411f981e08762404d04d864e3c49ebb436264
         | 
| 4 | 
            +
              data.tar.gz: 1147c0e541694973b8c5e50c953822cce616abdcffba5a00e9a379e21bc65920
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b5f887113d039e9f9e496062b96c2905a1b877dd9199daf2db87a8e5b2072b3db74736ab496fbc92680f40bb8567ba875a6b0fb4e8934d9e674bc3734dc35f10
         | 
| 7 | 
            +
              data.tar.gz: 76a5c121c7e2755fa09ef578fe8d9a002b3357c0fcdb3af5cf7241fbad7d59b153b6a111201caa4467c4a18e83d87c3c273d1a41467d219eec7a030ce0dc370b
         | 
    
        data/README.md
    CHANGED
    
    | @@ -10,6 +10,8 @@ Ramekin is a pre-processor for AddMusicK syntax that is in very early developmen | |
| 10 10 |  | 
| 11 11 | 
             
            Please keep in mind that as alpha software, **I may make breaking changes at any time.** After initial testing is done, I will release 1.0.0, at which point I will make a reasonable commitment to back-compatibility. That time is not yet.
         | 
| 12 12 |  | 
| 13 | 
            +
            For a preview of what full Ramekin tracks look like, feel free to check out [the examples repo](https://codeberg.org/jneen/ramekin-examples).
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
            # Installation
         | 
| 14 16 |  | 
| 15 17 | 
             
            First, [Install Ruby](https://ruby-lang.org). Windows users can use [RubyInstaller](https://rubyinstaller.org/).
         | 
| @@ -40,10 +42,19 @@ ramekin setup | |
| 40 42 | 
             
            # Usage
         | 
| 41 43 |  | 
| 42 44 | 
             
            ```
         | 
| 43 | 
            -
            usage: ramekin [command] [flags]
         | 
| 45 | 
            +
            usage: ramekin [--pack NAME=PATH] [command] [flags]
         | 
| 44 46 | 
             
                (default command: compile)
         | 
| 45 47 |  | 
| 48 | 
            +
            ramekin --pack my_cool_pack=/path/to/my_cool_pack [...]
         | 
| 49 | 
            +
                Specifies an additional custom sample location.
         | 
| 50 | 
            +
                Files compiled this way should use #pack "my_cool_pack",
         | 
| 51 | 
            +
                and sample paths relative to the deepest common path that
         | 
| 52 | 
            +
                contains .brr files. Use with `package --list my_cool_pack` to
         | 
| 53 | 
            +
                see details.
         | 
| 54 | 
            +
             | 
| 46 55 | 
             
            ramekin compile -i filename.rmk [flags]
         | 
| 56 | 
            +
            ramekin compile filename.rmk [flags]
         | 
| 57 | 
            +
            ramekin filename.rmk [flags]
         | 
| 47 58 | 
             
                flags:
         | 
| 48 59 | 
             
                    -h --help
         | 
| 49 60 | 
             
                        display this message
         | 
| @@ -397,6 +408,26 @@ Or drum instrument helpers: | |
| 397 408 |  | 
| 398 409 | 
             
            Or anything else you might find helpful.
         | 
| 399 410 |  | 
| 411 | 
            +
            ## Custom Samples
         | 
| 412 | 
            +
             | 
| 413 | 
            +
            If you have your own BRR-format samples that you'd like to use, Ramekin supports loading these through *custom packs*, specified on the CLI. First, organize your samples into a directory, with an optional `!patterns.txt` or `tunings.txt` file, much as may be found on [SMW Central's BRR repository](https://www.smwcentral.net/?p=section&s=brrsamples). In the simplest case, this is just a directory with .brr files in it.
         | 
| 414 | 
            +
             | 
| 415 | 
            +
            Then, when running ramekin, use:
         | 
| 416 | 
            +
             | 
| 417 | 
            +
            ```console
         | 
| 418 | 
            +
            $ ramekin --pack 'my cool pack=/path/to/my_cool_pack' [the rest of the ramekin command]
         | 
| 419 | 
            +
            ```
         | 
| 420 | 
            +
             | 
| 421 | 
            +
            where `/path/to/my_cool_pack` is replaced with a relative path to your BRR files directory. Your ramekin files can then freely use `#pack "my cool pack"`, and conjure up instruments from the pack. If no tuning file is specified, you may need to use `#tuning:XXXX` to specify a tuning, as the default tuning of `0000` is unlikely to be audible.
         | 
| 422 | 
            +
             | 
| 423 | 
            +
            If Ramekin is having trouble finding your BRR files, try:
         | 
| 424 | 
            +
             | 
| 425 | 
            +
            ```console
         | 
| 426 | 
            +
            $ ramekin --pack 'my cool pack=/path/to/my_cool_pack' package --list 'my cool pack'
         | 
| 427 | 
            +
            ```
         | 
| 428 | 
            +
             | 
| 429 | 
            +
            which will display the paths it expects you to use for each BRR sample it found.
         | 
| 430 | 
            +
             | 
| 400 431 | 
             
            # Thank you for trying out Ramekin!
         | 
| 401 432 |  | 
| 402 433 | 
             
            If you find any bugs, please report them in the issue tracker here on Codeberg. If you have questions, design ideas, or complaints, or just want to chat, please feel free to ask anything in [my discord](https://jneen.ca/discord). Cheers!
         | 
    
        data/lib/ramekin/bends.rb
    CHANGED
    
    | @@ -56,6 +56,8 @@ module Ramekin | |
| 56 56 |  | 
| 57 57 | 
             
                  leftover = total_duration - bend_duration
         | 
| 58 58 |  | 
| 59 | 
            +
                  return '' unless check_duration!(from, div)
         | 
| 60 | 
            +
             | 
| 59 61 | 
             
                  # ensure there is some leftover so we can toggle legato
         | 
| 60 62 | 
             
                  # before the end
         | 
| 61 63 | 
             
                  if leftover < 2
         | 
| @@ -67,8 +69,6 @@ module Ramekin | |
| 67 69 | 
             
                    end
         | 
| 68 70 | 
             
                  end
         | 
| 69 71 |  | 
| 70 | 
            -
                  return '' unless check_duration!(from)
         | 
| 71 | 
            -
             | 
| 72 72 | 
             
                  out = StringIO.new
         | 
| 73 73 |  | 
| 74 74 | 
             
                  out << from.octave_amk(oct)
         | 
| @@ -94,8 +94,8 @@ module Ramekin | |
| 94 94 | 
             
                  true
         | 
| 95 95 | 
             
                end
         | 
| 96 96 |  | 
| 97 | 
            -
                def check_duration!(note)
         | 
| 98 | 
            -
                  ticks = note.ticks
         | 
| 97 | 
            +
                def check_duration!(note, divisor)
         | 
| 98 | 
            +
                  ticks = note.ticks / divisor
         | 
| 99 99 | 
             
                  return true if ticks > 0 && ticks <= 96
         | 
| 100 100 |  | 
| 101 101 | 
             
                  error! 'bend length too short (must be at least one tick)', el: note if ticks <= 0
         | 
| @@ -115,32 +115,25 @@ module Ramekin | |
| 115 115 | 
             
                    note = @notes[i]
         | 
| 116 116 | 
             
                    to_note = @notes[i+1]
         | 
| 117 117 |  | 
| 118 | 
            +
                    next unless check_duration!(note, divisor)
         | 
| 119 | 
            +
             | 
| 118 120 | 
             
                    if i == 0
         | 
| 119 | 
            -
                      ticks = note.ticks + to_note.ticks
         | 
| 120 121 | 
             
                      out << note.octave_amk(octave)
         | 
| 121 122 | 
             
                      out << note.note_name
         | 
| 122 123 | 
             
                    else
         | 
| 123 | 
            -
                      ticks = to_note.ticks
         | 
| 124 124 | 
             
                      out << '^'
         | 
| 125 125 | 
             
                    end
         | 
| 126 126 |  | 
| 127 | 
            -
                    ticks  | 
| 128 | 
            -
                    next unless check_duration!(note)
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                    # $dd doesn't work properly if the note
         | 
| 131 | 
            -
                    # beforehand is more than a half note, so we have to
         | 
| 132 | 
            -
                    # split it up
         | 
| 133 | 
            -
                    clamped_ticks = [0x60, ticks].min
         | 
| 134 | 
            -
                    leftover_ticks = [0, ticks-0x60].max
         | 
| 127 | 
            +
                    ticks = note.ticks / divisor
         | 
| 135 128 |  | 
| 136 129 | 
             
                    # always use tick count notation here because
         | 
| 137 130 | 
             
                    # amk can insert ties in some cases which will break $dd
         | 
| 138 | 
            -
                    out << "=#{ | 
| 139 | 
            -
                    out << dd( | 
| 131 | 
            +
                    out << "=#{ticks}"
         | 
| 132 | 
            +
                    out << dd(ticks, to_note)
         | 
| 140 133 | 
             
                    out << '$f4$01' if @end_legato && i == 0
         | 
| 141 | 
            -
                    out << "^=#{leftover_ticks}" if leftover_ticks > 0
         | 
| 142 134 | 
             
                  end
         | 
| 143 135 |  | 
| 136 | 
            +
                  out << "^#{@notes.last.length_amk(divisor)}" if @notes.last.ticks > 0
         | 
| 144 137 | 
             
                  out.string
         | 
| 145 138 | 
             
                end
         | 
| 146 139 |  | 
    
        data/lib/ramekin/cli.rb
    CHANGED
    
    | @@ -19,10 +19,19 @@ module Ramekin | |
| 19 19 | 
             
                def usage
         | 
| 20 20 | 
             
                  $stderr.puts "Ramekin version #{RAMEKIN_VERSION}"
         | 
| 21 21 | 
             
                  $stderr.puts ""
         | 
| 22 | 
            -
                  $stderr.puts "usage: ramekin [command] [flags]"
         | 
| 22 | 
            +
                  $stderr.puts "usage: ramekin [--pack NAME=PATH] [command] [flags]"
         | 
| 23 23 | 
             
                  $stderr.puts "    (default command: compile)"
         | 
| 24 24 | 
             
                  $stderr.puts ""
         | 
| 25 | 
            +
                  $stderr.puts "ramekin --pack my_cool_pack=/path/to/my_cool_pack [...]"
         | 
| 26 | 
            +
                  $stderr.puts "    Specifies an additional custom sample location."
         | 
| 27 | 
            +
                  $stderr.puts "    Files compiled this way should use #pack \"my_cool_pack\","
         | 
| 28 | 
            +
                  $stderr.puts "    and sample paths relative to the deepest common path that"
         | 
| 29 | 
            +
                  $stderr.puts "    contains .brr files. Use with `package --list my_cool_pack` to"
         | 
| 30 | 
            +
                  $stderr.puts "    see details."
         | 
| 31 | 
            +
                  $stderr.puts ""
         | 
| 25 32 | 
             
                  $stderr.puts "ramekin compile -i filename.rmk [flags]"
         | 
| 33 | 
            +
                  $stderr.puts "ramekin compile filename.rmk [flags]"
         | 
| 34 | 
            +
                  $stderr.puts "ramekin filename.rmk [flags]"
         | 
| 26 35 | 
             
                  $stderr.puts "    flags:"
         | 
| 27 36 | 
             
                  $stderr.puts "        -h --help"
         | 
| 28 37 | 
             
                  $stderr.puts "            display this message"
         | 
| @@ -388,15 +397,21 @@ module Ramekin | |
| 388 397 | 
             
                    return 0
         | 
| 389 398 | 
             
                  end
         | 
| 390 399 |  | 
| 391 | 
            -
                   | 
| 392 | 
            -
             | 
| 393 | 
            -
                     | 
| 394 | 
            -
             | 
| 395 | 
            -
             | 
| 396 | 
            -
             | 
| 397 | 
            -
                     | 
| 398 | 
            -
             | 
| 399 | 
            -
                     | 
| 400 | 
            +
                  while argv.any?
         | 
| 401 | 
            +
                    case (arg = argv.shift)
         | 
| 402 | 
            +
                    when '--pack'
         | 
| 403 | 
            +
                      pack = argv.shift or fail! '--pack missing a pack definition NAME=PATH'
         | 
| 404 | 
            +
                      pack =~ /\A(.*?)=(.*)\z/ or fail! 'invalid --pack, must be of the form NAME=PATH'
         | 
| 405 | 
            +
                      SamplePack.add_custom($1, File.expand_path($2))
         | 
| 406 | 
            +
                    when 'compile'
         | 
| 407 | 
            +
                      return compile(*argv)
         | 
| 408 | 
            +
                    when 'package', 'pack'
         | 
| 409 | 
            +
                      return package(*argv)
         | 
| 410 | 
            +
                    when 'setup'
         | 
| 411 | 
            +
                      return setup(*argv)
         | 
| 412 | 
            +
                    else
         | 
| 413 | 
            +
                      return compile(arg, *argv)
         | 
| 414 | 
            +
                    end
         | 
| 400 415 | 
             
                  end
         | 
| 401 416 | 
             
                end
         | 
| 402 417 | 
             
              end
         | 
    
        data/lib/ramekin/meta.rb
    CHANGED
    
    | @@ -284,17 +284,16 @@ module Ramekin | |
| 284 284 | 
             
                end
         | 
| 285 285 |  | 
| 286 286 | 
             
                def adsr
         | 
| 287 | 
            -
                  @adsr ||= ext_adsr || pack_adsr  | 
| 288 | 
            -
                    or error! "no adsr configured for #{name.value}", el: name
         | 
| 287 | 
            +
                  @adsr ||= ext_adsr || pack_adsr || [0, 7, 7, 0x1f]
         | 
| 289 288 | 
             
                end
         | 
| 290 289 |  | 
| 291 290 | 
             
                def tuning
         | 
| 292 | 
            -
                  @tuning ||= ext_tuning || pack_tuning  | 
| 293 | 
            -
                    or error! "no tuning configured for #{name.value}", el: name
         | 
| 291 | 
            +
                  @tuning ||= ext_tuning || pack_tuning || [0, 0]
         | 
| 294 292 | 
             
                end
         | 
| 295 293 |  | 
| 296 294 | 
             
                def pack_tuning
         | 
| 297 295 | 
             
                  _, _, _, d, e = pack_hexes
         | 
| 296 | 
            +
                  return nil unless d && e
         | 
| 298 297 | 
             
                  [d, e]
         | 
| 299 298 | 
             
                end
         | 
| 300 299 |  | 
| @@ -319,7 +318,7 @@ module Ramekin | |
| 319 318 | 
             
                end
         | 
| 320 319 |  | 
| 321 320 | 
             
                def gain
         | 
| 322 | 
            -
                  @gain ||= ext_gain || pack_gain ||  | 
| 321 | 
            +
                  @gain ||= ext_gain || pack_gain || 0x8F
         | 
| 323 322 | 
             
                end
         | 
| 324 323 |  | 
| 325 324 | 
             
                def hexes
         | 
| @@ -332,7 +331,7 @@ module Ramekin | |
| 332 331 | 
             
                  adsr1 = ((7 - d)*16 | 0x80) + (15 - a)
         | 
| 333 332 | 
             
                  adsr2 = (s*32 + (31-r))
         | 
| 334 333 |  | 
| 335 | 
            -
                  [ | 
| 334 | 
            +
                  [adsr1, adsr2, g, t1, t2].map(&method(:to_hex))
         | 
| 336 335 | 
             
                end
         | 
| 337 336 |  | 
| 338 337 | 
             
                def to_hex(x)
         | 
    
        data/lib/ramekin/sample_pack.rb
    CHANGED
    
    | @@ -70,6 +70,12 @@ module Ramekin | |
| 70 70 | 
             
                def self.each(&b)
         | 
| 71 71 | 
             
                  return enum_for(:each) unless block_given?
         | 
| 72 72 |  | 
| 73 | 
            +
                  custom_packs.each do |name, path|
         | 
| 74 | 
            +
                    Dir.chdir(path) do
         | 
| 75 | 
            +
                      yield CustomSamplePack.new(name, path)
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 73 79 | 
             
                  Dir.chdir Ramekin.config.packages_dir do
         | 
| 74 80 | 
             
                    Dir.entries('.').sort.each do |subd|
         | 
| 75 81 | 
             
                      next unless /\A\d+\z/ =~ subd
         | 
| @@ -80,6 +86,14 @@ module Ramekin | |
| 80 86 | 
             
                  end
         | 
| 81 87 | 
             
                end
         | 
| 82 88 |  | 
| 89 | 
            +
                def self.custom_packs
         | 
| 90 | 
            +
                  @custom_packs ||= {}
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def self.add_custom(name, path)
         | 
| 94 | 
            +
                  custom_packs[name] = path
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 83 97 | 
             
                def initialize(data)
         | 
| 84 98 | 
             
                  @meta = data
         | 
| 85 99 | 
             
                end
         | 
| @@ -143,7 +157,7 @@ module Ramekin | |
| 143 157 |  | 
| 144 158 | 
             
                def find_tunings(name_re)
         | 
| 145 159 | 
             
                  raw = []
         | 
| 146 | 
            -
                  Dir.glob('**/*.txt').sort.each do |entry|
         | 
| 160 | 
            +
                  Dir.glob('**/*.txt', File::FNM_CASEFOLD).sort.each do |entry|
         | 
| 147 161 | 
             
                    next unless File.basename(entry).downcase =~ name_re
         | 
| 148 162 |  | 
| 149 163 | 
             
                    contents = File.read(entry, encoding: 'binary')
         | 
| @@ -169,7 +183,19 @@ module Ramekin | |
| 169 183 | 
             
                  out
         | 
| 170 184 | 
             
                end
         | 
| 171 185 |  | 
| 172 | 
            -
                def  | 
| 186 | 
            +
                def index_and_save!
         | 
| 187 | 
            +
                  index!
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                  File.write('.index.json', JSON.dump(
         | 
| 190 | 
            +
                    prefix: @prefix,
         | 
| 191 | 
            +
                    brrs: @brrs,
         | 
| 192 | 
            +
                    tunings: @tunings,
         | 
| 193 | 
            +
                  ))
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                  @cached_index = nil
         | 
| 196 | 
            +
                end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                def index!
         | 
| 173 199 | 
             
                  paths = []
         | 
| 174 200 | 
             
                  raw_tunings = []
         | 
| 175 201 |  | 
| @@ -177,7 +203,7 @@ module Ramekin | |
| 177 203 | 
             
                  other_tunings = find_tunings(/\Atuning/)
         | 
| 178 204 | 
             
                  misc_tunings = find_tunings(//)
         | 
| 179 205 |  | 
| 180 | 
            -
                  @brrs = Dir.glob('**/*.brr')
         | 
| 206 | 
            +
                  @brrs = Dir.glob('**/*.brr', File::FNM_CASEFOLD)
         | 
| 181 207 | 
             
                  @brrs.sort!
         | 
| 182 208 | 
             
                  @brrs.uniq!
         | 
| 183 209 | 
             
                  @prefix = shortest_prefix(@brrs.map(&File.method(:dirname)))
         | 
| @@ -200,14 +226,6 @@ module Ramekin | |
| 200 226 |  | 
| 201 227 | 
             
                    @tunings[brr] = candidates.map { |p, _, h| [p, h] }
         | 
| 202 228 | 
             
                  end
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                  File.write('.index.json', JSON.dump(
         | 
| 205 | 
            -
                    prefix: @prefix,
         | 
| 206 | 
            -
                    brrs: @brrs,
         | 
| 207 | 
            -
                    tunings: @tunings,
         | 
| 208 | 
            -
                  ))
         | 
| 209 | 
            -
             | 
| 210 | 
            -
                  @cached_index = nil
         | 
| 211 229 | 
             
                end
         | 
| 212 230 |  | 
| 213 231 | 
             
                def cached_index
         | 
| @@ -235,12 +253,13 @@ module Ramekin | |
| 235 253 | 
             
                end
         | 
| 236 254 |  | 
| 237 255 | 
             
                def prefix_dir
         | 
| 256 | 
            +
                  return dir if prefix == '.'
         | 
| 238 257 | 
             
                  File.join(dir, prefix)
         | 
| 239 258 | 
             
                end
         | 
| 240 259 |  | 
| 241 260 | 
             
                def self.download_all!
         | 
| 242 261 | 
             
                  smwc_each(&:download)
         | 
| 243 | 
            -
                  each(&: | 
| 262 | 
            +
                  each(&:index_and_save!)
         | 
| 244 263 | 
             
                end
         | 
| 245 264 |  | 
| 246 265 | 
             
                def needs_download?
         | 
| @@ -298,4 +317,32 @@ module Ramekin | |
| 298 317 | 
             
                  File.write(meta_file, JSON.dump(@meta))
         | 
| 299 318 | 
             
                end
         | 
| 300 319 | 
             
              end
         | 
| 320 | 
            +
             | 
| 321 | 
            +
              class CustomSamplePack < SamplePack
         | 
| 322 | 
            +
                attr_reader :dir, :name
         | 
| 323 | 
            +
                def initialize(name, dir)
         | 
| 324 | 
            +
                  @name = name
         | 
| 325 | 
            +
                  @dir = dir
         | 
| 326 | 
            +
                end
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                def cached_index
         | 
| 329 | 
            +
                  @cached_index ||= begin
         | 
| 330 | 
            +
                    Dir.chdir(dir) { index! }
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                    {
         | 
| 333 | 
            +
                      'prefix' => @prefix,
         | 
| 334 | 
            +
                      'brrs' => @brrs,
         | 
| 335 | 
            +
                      'tunings' => @tunings,
         | 
| 336 | 
            +
                    }
         | 
| 337 | 
            +
                  end
         | 
| 338 | 
            +
                end
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                def needs_download?
         | 
| 341 | 
            +
                  false
         | 
| 342 | 
            +
                end
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                def download
         | 
| 345 | 
            +
                  # pass
         | 
| 346 | 
            +
                end
         | 
| 347 | 
            +
              end
         | 
| 301 348 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ramekin
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.2. | 
| 4 | 
            +
              version: 0.2.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - jneen
         | 
| 8 8 | 
             
            bindir: gembin
         | 
| 9 9 | 
             
            cert_chain: []
         | 
| 10 | 
            -
            date: 2025-03- | 
| 10 | 
            +
            date: 2025-03-08 00:00:00.000000000 Z
         | 
| 11 11 | 
             
            dependencies:
         | 
| 12 12 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 13 13 | 
             
              name: strscan
         |