Project

slither

0.09
Low commit activity in last 3 years
A long-lived project that still receives updates
A simple, clean DSL for describing, writing, and parsing fixed-width text files.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Slither

by Ryan Wood http://ryanwood.com

Documentation: https://www.rubydoc.info/gems/slither

Description:

A simple, clean DSL for describing, writing, and parsing fixed-width text files.

Features:

  • Easy DSL syntax
  • Can parse and format fixed width files
  • Templated sections for reuse
  • Helpful error messages for invalid data

Synopsis:

Create a Slither::Defintion to describe a file format

  Slither.define :simple, :by_bytes => false do |d|

    # This is a template section that can be reused in other sections
    d.template :boundary do |t|
      t.column :record_type, 4
      t.column :company_id, 12
    end

    # Create a header section
    #   alternatively, you can define the section on the fly by using metaprogramming
    #   ex: d.header(:align => :left) { |header| ... }
    d.section(:header, :align => :left) do |header|
      # The trap tells Slither which lines should fall into this section
      header.trap { |line| line[0,4] == 'HEAD' }
      # Use the boundary template for the columns
      header.template :boundary
    end

    d.section(:body) do |body|
      body.trap { |line| line[0,4] =~ /[^(HEAD|FOOT)]/ }
      body.column :id, 10, :type => :integer
      body.column :name, 10, :align => :left
      body.spacer 3
      body.column :state, 2
    end

    d.section(:footer) do |footer|
      footer.trap { |line| line[0,4] == 'FOOT' }
      footer.template :boundary
      footer.column :record_count, 10
    end
  end

Supported types are: string, integer, date, float, money, and money_with_implied_decimal.

Use :by_bytes => true (default) to allow newlines within rows and specify length in bytes. Use :by_bytes => false to support sections of different lengths and length specification in number of characters.

Then either feed it a nested struct with data values to create the file in the defined format:

  test_data = {
    :body => [
      { :id => 12, :name => "Ryan", :state => 'SC' },
      { :id => 23, :name => "Joe", :state => 'VA' },
      { :id => 42, :name => "Tommy", :state => 'FL' },
    ],
    :header => { :record_type => 'HEAD', :company_id => 'ABC'  },
    :footer => { :record_type => 'FOOT', :company_id => 'ABC'  }
  }

  # Generates the file as a string
  puts Slither.generate(:simple, test_data)
  # =>
  #   HEAD         ABC
  #         12Ryan         SC
  #         23Joe          VA
  #         42Tommy        FL
  # FOOT         ABC

  # Writes the file
  Slither.write(output_filename, :simple, test_data)

or parse files already in that format into a nested hash:

   parsed_data = Slither.parse(input_filename, :simple)
   parsed_data = Slither.parseIo(io_object, :simple)

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Slither project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.