Module: I18n::Processes::Data::Tree::Traversal
Overview
Any Enumerable that yields nodes can mix in this module
Instance Method Summary collapse
- #breadth_first(&visitor) ⇒ Object
- #depth_first(&visitor) ⇒ Object
- #get_nodes_by_key_filter(root: false, &block) ⇒ Set<I18n::Processes::Data::Tree::Node>
- #grep_keys(match, opts = {}) ⇒ Object
- #intersect_keys(other_tree, key_opts = {}, &block) ⇒ Siblings
- #key_names(opts = {}) ⇒ Object
- #key_values(opts = {}) ⇒ Object
- #keys(root: false, &visitor) ⇒ Object
- #leaves(&visitor) ⇒ Object
- #levels(&block) ⇒ Object
-
#nodes(&block) ⇒ Object
rubocop:disable Metrics/ModuleLength.
- #root_key_value_data(sort = false) ⇒ Object
- #root_key_values(sort = false) ⇒ Object
- #select_keys(root: false, &block) ⇒ Siblings
- #select_keys!(root: false, &block) ⇒ Siblings
-
#select_nodes(&block) ⇒ Siblings
Select the nodes for which the block returns true.
-
#select_nodes!(&block) ⇒ Siblings
Select the nodes for which the block returns true.
- #set_each_value!(val_pattern, key_pattern = nil, &value_proc) ⇒ Object
Instance Method Details
#breadth_first(&visitor) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 36 def breadth_first(&visitor) return to_enum(:breadth_first) unless visitor levels do |nodes| nodes.each { |node| visitor.yield(node) } end self end |
#depth_first(&visitor) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 44 def depth_first(&visitor) return to_enum(:depth_first) unless visitor each do |node| visitor.yield node next unless node.children? node.children.each do |child| child.depth_first(&visitor) end end self end |
#get_nodes_by_key_filter(root: false, &block) ⇒ Set<I18n::Processes::Data::Tree::Node>
134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 134 def get_nodes_by_key_filter(root: false, &block) matches = Set.new keys(root: root) do |full_key, node| if block.yield(full_key, node) node.walk_to_root do |p| break unless matches.add?(p) end end end matches end |
#grep_keys(match, opts = {}) ⇒ Object
158 159 160 161 162 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 158 def grep_keys(match, opts = {}) select_keys(opts) do |full_key, _node| match === full_key # rubocop:disable Style/CaseEquality end end |
#intersect_keys(other_tree, key_opts = {}, &block) ⇒ Siblings
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 147 def intersect_keys(other_tree, key_opts = {}, &block) if block select_keys(key_opts) do |key, node| other_node = other_tree[key] other_node && yield(key, node, other_node) end else select_keys(key_opts) { |key, _node| other_tree[key] } end end |
#key_names(opts = {}) ⇒ Object
63 64 65 66 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 63 def key_names(opts = {}) opts[:root] = false unless opts.key?(:root) keys(opts).map { |key, _node| key } end |
#key_values(opts = {}) ⇒ Object
68 69 70 71 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 68 def key_values(opts = {}) opts[:root] = false unless opts.key?(:root) keys(opts).map { |key, node| [key, node.value] } end |
#keys(root: false, &visitor) ⇒ Object
57 58 59 60 61 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 57 def keys(root: false, &visitor) return to_enum(:keys, root: root) unless visitor leaves { |node| visitor.yield(node.full_key(root: root), node) } self end |
#leaves(&visitor) ⇒ Object
13 14 15 16 17 18 19 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 13 def leaves(&visitor) return to_enum(:leaves) unless visitor nodes do |node| visitor.yield(node) if node.leaf? end self end |
#levels(&block) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 21 def levels(&block) return to_enum(:levels) unless block nodes = to_nodes unless nodes.empty? block.yield nodes if nodes.size == 1 node = first node.children.levels(&block) if node.children? else I18n::Processes::Data::Tree::Nodes.new(nodes: nodes.children).levels(&block) end end self end |
#nodes(&block) ⇒ Object
rubocop:disable Metrics/ModuleLength
9 10 11 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 9 def nodes(&block) depth_first(&block) end |
#root_key_value_data(sort = false) ⇒ Object
79 80 81 82 83 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 79 def root_key_value_data(sort = false) result = keys(root: false).map { |key, node| [node.root.key, key, node.value, node.data] } result.sort! { |a, b| a[0] != b[0] ? a[0] <=> b[0] : a[1] <=> b[1] } if sort result end |
#root_key_values(sort = false) ⇒ Object
73 74 75 76 77 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 73 def root_key_values(sort = false) result = keys(root: false).map { |key, node| [node.root.key, key, node.value] } result.sort! { |a, b| a[0] != b[0] ? a[0] <=> b[0] : a[1] <=> b[1] } if sort result end |
#select_keys(root: false, &block) ⇒ Siblings
118 119 120 121 122 123 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 118 def select_keys(root: false, &block) matches = get_nodes_by_key_filter(root: root, &block) select_nodes do |node| matches.include?(node) end end |
#select_keys!(root: false, &block) ⇒ Siblings
126 127 128 129 130 131 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 126 def select_keys!(root: false, &block) matches = get_nodes_by_key_filter(root: root, &block) select_nodes! do |node| matches.include?(node) end end |
#select_nodes(&block) ⇒ Siblings
Select the nodes for which the block returns true. Pre-order traversal.
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 89 def select_nodes(&block) tree = Siblings.new each do |node| next unless block.yield(node) tree.append! node.derive( parent: tree.parent, children: (node.children.select_nodes(&block).to_a if node.children) ) end tree end |
#select_nodes!(&block) ⇒ Siblings
Select the nodes for which the block returns true. Pre-order traversal.
103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 103 def select_nodes!(&block) to_remove = [] each do |node| if block.yield(node) node.children.select_nodes!(&block) if node.children else # removing during each is unsafe to_remove << node end end to_remove.each { |node| remove! node } self end |
#set_each_value!(val_pattern, key_pattern = nil, &value_proc) ⇒ Object
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/i18n/processes/data/tree/traversal.rb', line 164 def set_each_value!(val_pattern, key_pattern = nil, &value_proc) value_proc ||= proc do |node| node_value = node.value next node_value if node.reference? human_key = ActiveSupport::Inflector.humanize(node.key.to_s) full_key = node.full_key default = (node.data[:occurrences] || []).detect { |o| o.default_arg.presence }.try(:default_arg) StringInterpolation.interpolate_soft( val_pattern, value: node_value, human_key: human_key, key: full_key, default: default, value_or_human_key: node_value.presence || human_key, value_or_default_or_human_key: node_value.presence || default || human_key ) end pattern_re = I18n::Processes::KeyPatternMatching.compile_key_pattern(key_pattern) if key_pattern.present? keys.each do |key, node| next if pattern_re && key !~ pattern_re node.value = value_proc.call(node) end self end |