module Forgitter ## # Strip unnecessary characters and downcase the given string. # # @param [String] any string # @return [String] the "parameterized" string # def self.parameterize(str) str.gsub(/[^a-z0-9+]+/i, '').downcase end ## # Filter ignorefiles by tags. # # If tags is empty, this will return all ignorefiles. # # @param [Hash] the hash of options containing tag strings # @return [Array] the array of filtered ignorefiles # def self.filter(options = {}) return ignorefiles if options[:tags].empty? ignorefiles.select do |ignorefile| selected = true options[:tags].uniq.each do |tag| selected &&= ignorefile[:tags].count(tag) >= options[:tags].count(tag) end selected end end ## # Fetch all available ignorefile paths, relative to the DATA_PATH. # # .gitignore files placed directly under DATA_PATH are ignored. # # @return [Array] the array of available ignorefile paths # def self.paths @@paths ||= Dir["#{DATA_PATH}/**/*.gitignore"].map do |path| path.sub("#{DATA_PATH}/", '') end.select do |path| path =~ /\// end end ## # Pull a parameterized ignorefile out of the given path. # # @param [String] the path to a .gitignore file # @return [String] the ignorefile # def self.ignorefile(path) parameterize(File.basename(path).sub('.gitignore', '')) end ## # Pull parameterized tags out of the given path. # # If path does not contain a /, this just returns the ignorefile name in an array. # # @param [String] the path to a .gitignore file # @return [Array] the tags # def self.tags(path) tags = [] if path =~ /\// tags = path.sub("/#{File.basename(path)}", '').split('/') tags.map! do |tag| parameterize(tag) end end tags << ignorefile(path) tags end ## # Fetch all available ignorefiles. # # @return [Array] the array of available ignorefiles # def self.ignorefiles unless defined?(@@ignorefiles) && !@@ignorefiles.empty? @@ignorefiles = [] paths.each do |path| @@ignorefiles << { :path => path, :name => ignorefile(path), :tags => tags(path) } end end @@ignorefiles end ## # Output a list of ignorefile tags along with the relative path to the gitignore, # formatted into columns. # # @param [Array] tags The list of tags to filter. # def self.list(tags = []) ignorefiles = filter({ :tags => tags }) if ignorefiles.empty? puts 'No ignorefiles found!' else lines = [] col1size = 0 ignorefiles.each do |ignorefile| id = ignorefile[:tags].join(' ') col1size = id.length if id.length > col1size lines << [id, ignorefile[:path]] end lines.sort_by { |line| line[0] }.each do |line| printf("%-#{col1size}s\t%s\n", line[0], line[1]) end end end end