class Readme
Readme
is designed to parse a README file applying various hueristics in order to descern metadata about a project.
The heuristics are fairly simplistic at this point, but will improve with time and contribution.
Constants
- FILE_PATTERN
File glob for matching README file.
- VERSION
Attributes
file[R]
The ERADME file path, if provided.
text[R]
The README text.
Public Class Methods
cli(*argv)
click to toggle source
# File lib/readme/cli.rb, line 5 def self.cli(*argv) format = nil name = nil OptionParser.new do |opt| opt.banner = 'Usage: readme [option] [field]' opt.on('-y', '--yml', '--yaml', 'return in YAML format') do format = :yaml end opt.on('-j', '--json', 'return in JSON format') do format = :json end opt.on('-r', '--ruby', 'return in Ruby code format') do format = :ruby end opt.on_tail('-h', '--help', 'show this help message') do puts opt exit end end.parse!(argv) if argv.first name = argv.shift data = Readme.file[name] else if format data = Readme.file.to_h else data = Readme.file end end case format when :yaml require 'yaml' puts data.to_yaml when :json require 'json' puts data.to_json when :ruby data = {name => data} if name data.each do |k,v| case v when Hash puts "#{k} #{v.inspect[1...-1]}" else puts "#{k} #{v.inspect}" end end else puts data #Readme.file.to_s end end
file(path=Dir.pwd)
click to toggle source
# File lib/readme.rb, line 21 def self.file(path=Dir.pwd) if File.directory?(path) path = Dir.glob(File.join(path, FILE_PATTERN), File::FNM_CASEFOLD).first end if path new(File.read(path), path) else raise IOError, "no such README -- #{path}" end end
new(text, file=nil)
click to toggle source
# File lib/readme.rb, line 33 def initialize(text, file=nil) @text = text @file = file @data = {} parse end
Public Instance Methods
[](name)
click to toggle source
Access to underlying parse table.
# File lib/readme.rb, line 71 def [](name) @data[name.to_s] #return nil unless file #if respond_to?(name) # __send__(name) #else # nil #end end
copyright()
click to toggle source
# File lib/readme.rb, line 102 def copyright @data['copyright'] end
description()
click to toggle source
# File lib/readme.rb, line 92 def description @data['description'] end
extname()
click to toggle source
Return file extension of README. Even if the file has no extension, this method will look at the contents and try to determine it.
@todo Improve type heuristics.
@return [String] Extension type, e.g. ‘.md`.
# File lib/readme.rb, line 139 def extname ext = File.extname(file) if ext.empty? ext = '.rdoc' if /^\=/ =~ text ext = '.md' if /^\#/ =~ text end return ext end
homepage()
click to toggle source
# File lib/readme.rb, line 117 def homepage resources['home'] end
issues()
click to toggle source
# File lib/readme.rb, line 127 def issues resources['issues'] end
license()
click to toggle source
# File lib/readme.rb, line 97 def license @data['license'] end
name()
click to toggle source
# File lib/readme.rb, line 82 def name @data['name'] end
resources()
click to toggle source
# File lib/readme.rb, line 112 def resources @data['resources'] ||= {} end
root()
click to toggle source
title()
click to toggle source
# File lib/readme.rb, line 87 def title @data['title'] end
to_h()
click to toggle source
Access to a copy of the underlying parse table.
@return [Hash] Copy of the underlying table.
# File lib/readme.rb, line 153 def to_h @data.dup end
to_s()
click to toggle source
wiki()
click to toggle source
# File lib/readme.rb, line 122 def wiki resources['wiki'] end
Private Instance Methods
parse()
click to toggle source
# File lib/readme.rb, line 160 def parse parse_title parse_description parse_license parse_copyright parse_resources end
parse_copyright()
click to toggle source
# File lib/readme.rb, line 222 def parse_copyright md = /Copyright.*?\d+(.*?)$/.match(text) if md copyright = md[0] authors = md[1].split(/(and|\&|\,)/).map{|a|a.strip} authors = authors.map{ |a| a.sub(/all rights reserved\.?/i, '').strip.chomp('.') } @data['copyright'] = copyright @data['authors'] = authors end end
parse_description()
click to toggle source
# File lib/readme.rb, line 178 def parse_description if md = /[=#]+\s*(DESCRIPTION|ABSTRACT)[:]*(.*?)[=#]/mi.match(text) @data['description'] = md[2].strip #.sub("\n", ' ') # unfold instead of sub? else d = [] o = false text.split("\n").each do |line| if o if /^(\w|\s*$)/ !~ line break d else d << line end else if /^\w/ =~ line d << line o = true end end end @data['description'] = d.join(' ').strip end end
parse_license()
click to toggle source
# File lib/readme.rb, line 203 def parse_license if md = /[=]+\s*(LICENSE)/i.match(text) section = md.post_match @data['license'] = ( case section when /LGPL/ "LGPL" when /GPL/ "GPL" when /MIT/ "MIT" when /BSD/ "BSD" end ) end end
parse_resources()
click to toggle source
# File lib/readme.rb, line 236 def parse_resources @data['resources'] = {} scan_for_github scan_for_google_groups text.scan(/(\w+)\:\s*(http:.*?[\w\/])$/) do |m| @data['resources'][$1] = $2 end end
parse_title()
click to toggle source
# File lib/readme.rb, line 169 def parse_title if md = /^[=#]\s*(.*?)$/m.match(text) title = md[1].strip @data['title'] = title @data['name'] = title.downcase.gsub(/\s+/, '_') end end
scan_for_github()
click to toggle source
TODO: Improve on github matching.
# File lib/readme.rb, line 249 def scan_for_github text.scan(/http\:.*?github\.com.*?[">)\s]/) do |m| case m when /wiki/ @data['resources']['wiki'] = m[0...-1] when /issues/ @data['resources']['issues'] = m[0...-1] else if m[0] =~ /:\/\/github/ @data['resources']['code'] = m[0...-1] else @data['resources']['home'] = m[0...-1] end end end end
scan_for_google_groups()
click to toggle source
# File lib/readme.rb, line 267 def scan_for_google_groups if m = /http\:.*?groups\.google\.com.*?[">)\s]/.match(text) @data['resources']['mail'] = m[0][0...-1] end end