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 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