<commit_before>module Traverse
	attr_accessor :parent

	# Creates a Rind::Nodes list of all ancestors. If an Xpath
	# is provided it will only return the nodes that match.
	def ancestors(path = nil)
		node = self
		ancestors = Rind::Nodes.new()
		while not node.parent.nil?
			node = node.parent
			ancestors.push(node)
		end

		(path.nil? or ancestors.empty?) ? ancestors : ancestors.filter(path)
	end

	# Creates a Rind::Nodes list of all descendants. If an Xpath
	# is provided it will only return the nodes that match.
	def descendants(path = nil)
		descendants = Rind::Nodes.new()
		if self.respond_to? :children and not self.children.empty?
			descendants.push(*self.children)

			self.children.each do |child|
				child_descendants = child.descendants
				descendants.push(*child_descendants) if not child_descendants.nil?
			end
		end
		(path.nil? or descendants.empty?) ? descendants : descendants.filter(path)
	end

	# Returns the first descendant node. If an Xpath is provided
	# it will return the first one that matches.
	def down(path = nil)
		if self.respond_to? :children and not self.children.empty?
			# if there's not path then send back the first child
			if path.nil?
				self.children.first
			else
				nodes = self.children.filter(path)
				if nodes.empty?
					self.children.each do |child|
						node = child.down(path)
						return node if not node.nil?
					end
					nil
				else
					nodes.first
				end
			end
		end
	end

	# Returns the first sibling that follows the current node in
	# the list of siblings. If an Xpath is provided it will return
	# the first one that matches.
	def next(path = nil)
		children = self.parent.children
		self_index = children.index(self)
		if path.nil?
			children[self_index + 1]
		else
			(self_index + 1).upto(children.length) do |i|
				return children[i] if not Rind::Nodes.new([children[i]]).filter(path).empty?
			end
		end
	end

	# Creates a Rind::Nodes list of all siblings that follow the
	# current node in the list of siblings. If an Xpath is provided
	# it will only return the nodes that match.
	def next_siblings(path = nil)
		children = self.parent.children
		siblings = Rind::Nodes.new(children[children.index(self)+1..children.length-1])
		path.nil? ? siblings : siblings.filter(path)
	end

	# Returns the first sibling that proceeds the current node in
	# the list of siblings. If an Xpath is provided it will return
	# the first one that matches.
	def prev(path = nil)
		children = self.parent.children
		self_index = children.index(self)
		if self_index == 0
			nil
		elsif path.nil?
			children[self_index - 1]
		else
			0.upto(self_index - 1) do |i|
				return children[i] if not Rind::Nodes.new([children[i]]).filter(path).empty?
			end
		end
	end

	# Creates a Rind::Nodes list of all siblings that proceed the
	# current node in the list of siblings. If an Xpath is provided
	# it will only return the nodes that match.
	def prev_siblings(path = nil)
		children = self.parent.children
		siblings = Rind::Nodes.new(children[0...children.index(self)])
		path.nil? ? siblings : siblings.filter(path)
	end

	# Creates a Rind::Nodes list of all siblings. If an Xpath is
	# provided it will only return the nodes that match.
	def siblings(path = nil)
		siblings = Rind::Nodes.new(self.parent.children.find_all{|child| not child.equal? self})
		path.nil? ? siblings : siblings.filter(path)
	end

	# Returns the first ancestor node. If an Xpath is provided
	# it will return the first one that matches.
	def up(path = nil)
		ancestors = self.ancestors(path)
		ancestors.first
	end
end<commit_msg>reworked up to improve performance<commit_after>module Traverse
	attr_accessor :parent

	# Creates a Rind::Nodes list of all ancestors. If an Xpath
	# is provided it will only return the nodes that match.
	def ancestors(path = nil)
		node = self
		ancestors = Rind::Nodes.new()
		while not node.parent.nil?
			node = node.parent
			ancestors.push(node)
		end

		(path.nil? or ancestors.empty?) ? ancestors : ancestors.filter(path)
	end

	# Creates a Rind::Nodes list of all descendants. If an Xpath
	# is provided it will only return the nodes that match.
	def descendants(path = nil)
		descendants = Rind::Nodes.new()
		if self.respond_to? :children and not self.children.empty?
			descendants.push(*self.children)

			self.children.each do |child|
				child_descendants = child.descendants
				descendants.push(*child_descendants) if not child_descendants.nil?
			end
		end
		(path.nil? or descendants.empty?) ? descendants : descendants.filter(path)
	end

	# Returns the first descendant node. If an Xpath is provided
	# it will return the first one that matches.
	def down(path = nil)
		if self.respond_to? :children and not self.children.empty?
			# if there's not path then send back the first child
			if path.nil?
				self.children.first
			else
				nodes = self.children.filter(path)
				if nodes.empty?
					self.children.each do |child|
						node = child.down(path)
						return node if not node.nil?
					end
					nil
				else
					nodes.first
				end
			end
		end
	end

	# Returns the first sibling that follows the current node in
	# the list of siblings. If an Xpath is provided it will return
	# the first one that matches.
	def next(path = nil)
		children = self.parent.children
		self_index = children.index(self)
		if path.nil?
			children[self_index + 1]
		else
			(self_index + 1).upto(children.length) do |i|
				return children[i] if not Rind::Nodes.new([children[i]]).filter(path).empty?
			end
		end
	end

	# Creates a Rind::Nodes list of all siblings that follow the
	# current node in the list of siblings. If an Xpath is provided
	# it will only return the nodes that match.
	def next_siblings(path = nil)
		children = self.parent.children
		siblings = Rind::Nodes.new(children[children.index(self)+1..children.length-1])
		path.nil? ? siblings : siblings.filter(path)
	end

	# Returns the first sibling that proceeds the current node in
	# the list of siblings. If an Xpath is provided it will return
	# the first one that matches.
	def prev(path = nil)
		children = self.parent.children
		self_index = children.index(self)
		if self_index == 0
			nil
		elsif path.nil?
			children[self_index - 1]
		else
			0.upto(self_index - 1) do |i|
				return children[i] if not Rind::Nodes.new([children[i]]).filter(path).empty?
			end
		end
	end

	# Creates a Rind::Nodes list of all siblings that proceed the
	# current node in the list of siblings. If an Xpath is provided
	# it will only return the nodes that match.
	def prev_siblings(path = nil)
		children = self.parent.children
		siblings = Rind::Nodes.new(children[0...children.index(self)])
		path.nil? ? siblings : siblings.filter(path)
	end

	# Creates a Rind::Nodes list of all siblings. If an Xpath is
	# provided it will only return the nodes that match.
	def siblings(path = nil)
		siblings = Rind::Nodes.new(self.parent.children.find_all{|child| not child.equal? self})
		path.nil? ? siblings : siblings.filter(path)
	end

	# Returns the first ancestor node. If an Xpath is provided
	# it will return the first one that matches.
	def up(path = nil)
		if path.nil?
			self.parent
		else
			node = self
			while not node.parent.nil?
				node = node.parent
				return node if not Rind::Nodes.new([node]).filter(path).empty?
			end
			nil
		end
	end
end
{'fraction_non_alphanumeric': 0.09163019693654267, 'fraction_numerical': 0.002461706783369803, 'mean_word_length': 3.434808975136446, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2807776', 'n_tokens_mistral': 2624, 'n_tokens_neox': 2303, 'n_words': 823}