indented-list 0.0.1
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 +7 -0
- data/lib/indented-list/indented-list-parser.rb +52 -0
- data/lib/indented-list.rb +88 -0
- data/test/indented_list_test.rb +7479 -0
- metadata +47 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 2b0048ef91a5c25c0f8cfb7f98a434f2315a71a3
         | 
| 4 | 
            +
              data.tar.gz: 7914d6c64b58c1dbe7c167586b6480649facc52c
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: a5c541dfd88b371a0e954e4f8f3a7911ab0cc2cd5946e4d55e861d449c01d2e44e73a66b2fb03ed695112d1fa883357364b7a8b3ac8dfd4471a7f274e4dd27d6
         | 
| 7 | 
            +
              data.tar.gz: 929d141bbd25b1aca52a221df9de9e876e144426e0126215af50f3d5e082d86cf09b80284cf196569bf51545af4544c09b7f2f4e877cebb9bdd86b41e3cb5e94
         | 
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            class IndentedListParser
         | 
| 2 | 
            +
              attr_reader :list, :raw
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # Parses a whitespace indented nested list and returns its content as an object of nested Hashes and Arrays. 
         | 
| 6 | 
            +
              #
         | 
| 7 | 
            +
              def initialize( list )
         | 
| 8 | 
            +
                case list
         | 
| 9 | 
            +
                  when String
         | 
| 10 | 
            +
                    source = list && File.exist?( list ) ? File.readlines( list ) : list.lines
         | 
| 11 | 
            +
                  when Array 
         | 
| 12 | 
            +
                    source = list
         | 
| 13 | 
            +
                  else
         | 
| 14 | 
            +
                    abort "List can be given as a file name, String or Array. The class of the currently used list '#{list}' is: #{list.class}."
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
                raw = source.map(&:chomp).select { |line|  line if !line.match(/^\s*$/) }
         | 
| 17 | 
            +
                @list = step raw
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             
         | 
| 20 | 
            +
              private
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def get_indentation_map( arr )
         | 
| 23 | 
            +
                arr.map { |line| line[/^ */].size }
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def slice_before_smallest_indent( arr )
         | 
| 27 | 
            +
                indentation_map = get_indentation_map( arr ).uniq.sort
         | 
| 28 | 
            +
                smallest_indent = indentation_map[0]
         | 
| 29 | 
            +
                arr.slice_before { |line| line[/^ */].size == smallest_indent  }.to_a
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def turn_nested_arr_into_hash( nested_arr )
         | 
| 33 | 
            +
                nested_arr.inject({}) { |hash, arr| hash = hash.merge( arr[0].strip => arr[1..-1] ) }
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def step( arr )
         | 
| 37 | 
            +
                if arr.is_a?( Array ) && !arr.empty? && arr[0].is_a?( String )     
         | 
| 38 | 
            +
                  if get_indentation_map( arr ).uniq.sort.count > 1 
         | 
| 39 | 
            +
                    arr = slice_before_smallest_indent arr
         | 
| 40 | 
            +
                    arr = turn_nested_arr_into_hash arr
         | 
| 41 | 
            +
                    arr = arr.inject({}) do |hash, (key, value)|
         | 
| 42 | 
            +
                      hash = hash.merge( key => step( value ) )
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                  else
         | 
| 45 | 
            +
                    arr = arr.map(&:strip)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                else
         | 
| 48 | 
            +
                  arr
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
                
         | 
| 52 | 
            +
            end
         | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            require 'indented-list/indented-list-parser'
         | 
| 2 | 
            +
            require 'pp'
         | 
| 3 | 
            +
             
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # Parses whitespace indented nested list.
         | 
| 6 | 
            +
              # The parsing result is an object of Hashes of Array, hence the list can easily be converted to JSON or YAML.
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              #
         | 
| 9 | 
            +
              # == Getting started 
         | 
| 10 | 
            +
              #      require 'indented-list'
         | 
| 11 | 
            +
              #      list = IndentedList.new( 'list.txt' )  # load list from a text file
         | 
| 12 | 
            +
              #      list = IndentedList.new( my-list )     # list can be passed as Array or String
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              #
         | 
| 15 | 
            +
              # == Usage
         | 
| 16 | 
            +
              #
         | 
| 17 | 
            +
              # Full text search 
         | 
| 18 | 
            +
              # Returns full branch of the root Hash in which match has occured.
         | 
| 19 | 
            +
              #       pp list.find( /my-regex/ )  
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              #
         | 
| 22 | 
            +
              # == Extensibility
         | 
| 23 | 
            +
              #
         | 
| 24 | 
            +
              # This gem suggests the hook method 'get' which can be implemented as needed for any specific list. 
         | 
| 25 | 
            +
              # Any other list-specific method can be easily implemented. 
         | 
| 26 | 
            +
              #   class MyList < IndentedList
         | 
| 27 | 
            +
              #     def get( *params )
         | 
| 28 | 
            +
              #       get_tags_with_indicators
         | 
| 29 | 
            +
              #     end
         | 
| 30 | 
            +
              #
         | 
| 31 | 
            +
              #     def get_tags_with_indicators
         | 
| 32 | 
            +
              #       # ...
         | 
| 33 | 
            +
              #     end
         | 
| 34 | 
            +
              #   end
         | 
| 35 | 
            +
              #
         | 
| 36 | 
            +
              #
         | 
| 37 | 
            +
              # == CLI Usage
         | 
| 38 | 
            +
              #
         | 
| 39 | 
            +
              # For use with IRB suppress return output:
         | 
| 40 | 
            +
              #       irb(main):001:0> irb --simple-prompt --noecho
         | 
| 41 | 
            +
              #
         | 
| 42 | 
            +
              # You can also suppress return output in irb on a by-line basis:
         | 
| 43 | 
            +
              #       irb(main):001:0> marc = MARC21Format.new;0    # => 0
         | 
| 44 | 
            +
              #
         | 
| 45 | 
            +
              # Commands can then be used as described above.
         | 
| 46 | 
            +
              #
         | 
| 47 | 
            +
              # ---
         | 
| 48 | 
            +
              #
         | 
| 49 | 
            +
              # Copyright (c) 2017 Maike Kittelmann
         | 
| 50 | 
            +
              #
         | 
| 51 | 
            +
              # Indented-List is freely distributable under the terms of MIT license.
         | 
| 52 | 
            +
              # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
         | 
| 53 | 
            +
              #
         | 
| 54 | 
            +
              # Disclaimer: The software comes without any warranty.
         | 
| 55 | 
            +
              
         | 
| 56 | 
            +
              
         | 
| 57 | 
            +
            class IndentedList
         | 
| 58 | 
            +
              attr_reader :list
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def initialize( list )
         | 
| 61 | 
            +
                parser = IndentedListParser.new( list )
         | 
| 62 | 
            +
                @list = parser.list
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
              
         | 
| 65 | 
            +
              def each( &block )
         | 
| 66 | 
            +
                list.each( &block )
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
              
         | 
| 69 | 
            +
              def method_missing( method, *args, &block )
         | 
| 70 | 
            +
                list.respond_to?( method, *args, &block ) ? list.send( method, *args, &block ) : super
         | 
| 71 | 
            +
              end  
         | 
| 72 | 
            +
              
         | 
| 73 | 
            +
              #
         | 
| 74 | 
            +
              # Full text search. Takes a regular expression as an argument. 
         | 
| 75 | 
            +
              # Returns full branch of the root Hash in which match has occured.
         | 
| 76 | 
            +
              #  
         | 
| 77 | 
            +
              def find( regex )
         | 
| 78 | 
            +
                list.select { |k,v| { k => v } if ( k.match( regex ) || v.to_s.match( regex ) ) } 
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
              
         | 
| 81 | 
            +
              #
         | 
| 82 | 
            +
              # Hook
         | 
| 83 | 
            +
              #
         | 
| 84 | 
            +
              def get( *params )
         | 
| 85 | 
            +
                puts 'Implement specific searches for your list. See documentation for how to do this.'
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
              
         | 
| 88 | 
            +
            end
         |