benry-cmdopt 1.1.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +35 -3
- data/MIT-LICENSE +21 -0
- data/README.md +447 -123
- data/Rakefile.rb +6 -87
- data/benry-cmdopt.gemspec +23 -21
- data/doc/benry-cmdopt.html +648 -0
- data/doc/css/style.css +168 -0
- data/lib/benry/cmdopt.rb +568 -439
- data/task/common-task.rb +139 -0
- data/task/package-task.rb +72 -0
- data/task/readme-task.rb +125 -0
- data/task/test-task.rb +81 -0
- data/test/cmdopt_test.rb +1361 -722
- metadata +22 -28
data/task/common-task.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
defined? PROJECT or abort "PROJECT required."
|
5
|
+
defined? RELEASE or abort "RELEASE required."
|
6
|
+
defined? COPYRIGHT or abort "COPYRIGHT required."
|
7
|
+
defined? LICENSE or abort "LICENSE required."
|
8
|
+
|
9
|
+
RELEASE =~ /\A\d+\.\d+\.\d+/ or abort "RELEASE=#{RELEASE}: invalid release number."
|
10
|
+
|
11
|
+
|
12
|
+
require 'rake/clean'
|
13
|
+
CLEAN << "build"
|
14
|
+
CLEAN.concat Dir.glob("#{PROJECT}-*.gem").collect {|x| x.sub(/\.gem$/, '') }
|
15
|
+
CLOBBER.concat Dir.glob("#{PROJECT}-*.gem")
|
16
|
+
|
17
|
+
|
18
|
+
task :default do
|
19
|
+
sh "rake -T", verbose: false
|
20
|
+
end unless Rake::Task.task_defined?(:default)
|
21
|
+
|
22
|
+
|
23
|
+
desc "show release guide"
|
24
|
+
task :guide do
|
25
|
+
do_guide()
|
26
|
+
end
|
27
|
+
|
28
|
+
def do_guide()
|
29
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
30
|
+
puts guide_message(PROJECT, RELEASE)
|
31
|
+
end
|
32
|
+
|
33
|
+
def guide_message(project, release)
|
34
|
+
target = "#{project}-#{release}"
|
35
|
+
tag = "#{project}-#{release}"
|
36
|
+
puts <<END
|
37
|
+
How to release:
|
38
|
+
|
39
|
+
$ git diff .
|
40
|
+
$ git status .
|
41
|
+
$ which ruby
|
42
|
+
$ rake test
|
43
|
+
$ rake test:all
|
44
|
+
$ rake readme:execute # optional
|
45
|
+
$ rake readme:toc # optional
|
46
|
+
$ rake package RELEASE=#{release}
|
47
|
+
$ rake package:extract # confirm files in gem file
|
48
|
+
$ (cd #{target}/data; find . -type f)
|
49
|
+
$ gem install #{target}.gem # confirm gem package
|
50
|
+
$ gem uninstall #{project}
|
51
|
+
$ gem push #{target}.gem # publish gem to rubygems.org
|
52
|
+
$ git tag #{tag} # or: git tag ruby-#{tag}
|
53
|
+
$ git push
|
54
|
+
$ git push --tags
|
55
|
+
$ rake clean
|
56
|
+
$ mv #{target}.gem archive/
|
57
|
+
END
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
desc "create 'README.md' and 'doc/*.html'"
|
62
|
+
task :doc do
|
63
|
+
x = PROJECT
|
64
|
+
cd "doc" do
|
65
|
+
sh "../../docs/md2 --md #{x}.mdx > ../README.md"
|
66
|
+
sh "../../docs/md2 #{x}.mdx > #{x}.html"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "copy 'doc/*.html' to '../docs/'"
|
71
|
+
task 'doc:export' do
|
72
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
73
|
+
x = PROJECT
|
74
|
+
cp "doc/#{x}.html", "../docs/"
|
75
|
+
edit_file!("../docs/#{x}.html")
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
desc "edit metadata in files"
|
80
|
+
task :edit do
|
81
|
+
do_edit()
|
82
|
+
end
|
83
|
+
|
84
|
+
def do_edit()
|
85
|
+
target_files().each do |fname|
|
86
|
+
edit_file!(fname)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def target_files()
|
91
|
+
$_target_files ||= begin
|
92
|
+
spec_src = File.read("#{PROJECT}.gemspec", encoding: 'utf-8')
|
93
|
+
spec = eval spec_src
|
94
|
+
spec.name == PROJECT or
|
95
|
+
abort "** ERROR: '#{PROJECT}' != '#{spec.name}' (project name in gemspec file)"
|
96
|
+
spec.files + Dir.glob("doc/*.mdx")
|
97
|
+
end
|
98
|
+
return $_target_files
|
99
|
+
end
|
100
|
+
|
101
|
+
def edit_file!(filename, verbose: true)
|
102
|
+
changed = edit_file(filename) do |s|
|
103
|
+
s = s.gsub(/\$Release[:].*?\$/, "$"+"Release: #{RELEASE} $")
|
104
|
+
s = s.gsub(/\$Copyright[:].*?\$/, "$"+"Copyright: #{COPYRIGHT} $")
|
105
|
+
s = s.gsub(/\$License[:].*?\$/, "$"+"License: #{LICENSE} $")
|
106
|
+
s
|
107
|
+
end
|
108
|
+
if verbose
|
109
|
+
puts "[C] #{filename}" if changed
|
110
|
+
puts "[U] #{filename}" unless changed
|
111
|
+
end
|
112
|
+
return changed
|
113
|
+
end
|
114
|
+
|
115
|
+
def edit_file(filename)
|
116
|
+
File.open(filename, 'rb+') do |f|
|
117
|
+
s1 = f.read()
|
118
|
+
s2 = yield s1
|
119
|
+
if s1 != s2
|
120
|
+
f.rewind()
|
121
|
+
f.truncate(0)
|
122
|
+
f.write(s2)
|
123
|
+
true
|
124
|
+
else
|
125
|
+
false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
desc nil
|
132
|
+
task :'relink' do
|
133
|
+
Dir.glob("task/*.rb").each do |x|
|
134
|
+
src = "../" + x
|
135
|
+
next if File.identical?(src, x)
|
136
|
+
rm x
|
137
|
+
ln src, x
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
desc "create package (*.gem)"
|
5
|
+
task :package do
|
6
|
+
do_package()
|
7
|
+
end
|
8
|
+
|
9
|
+
def do_package()
|
10
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
11
|
+
## copy
|
12
|
+
dir = "build"
|
13
|
+
rm_rf dir if File.exist?(dir)
|
14
|
+
mkdir dir
|
15
|
+
target_files().each do |file|
|
16
|
+
dest = File.join(dir, File.dirname(file))
|
17
|
+
mkdir_p dest, :verbose=>false unless File.exist?(dest)
|
18
|
+
cp file, "#{dir}/#{file}"
|
19
|
+
end
|
20
|
+
## edit
|
21
|
+
Dir.glob("#{dir}/**/*").each do |file|
|
22
|
+
next unless File.file?(file)
|
23
|
+
edit_file!(file, verbose: false)
|
24
|
+
end
|
25
|
+
## build
|
26
|
+
chdir dir do
|
27
|
+
sh "gem build #{PROJECT}.gemspec"
|
28
|
+
end
|
29
|
+
mv "#{dir}/#{PROJECT}-#{RELEASE}.gem", "."
|
30
|
+
rm_rf dir
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
desc "extract latest gem file"
|
35
|
+
task :'package:extract' do
|
36
|
+
do_package_extract()
|
37
|
+
end
|
38
|
+
|
39
|
+
def do_package_extract()
|
40
|
+
gemfile = Dir.glob("#{PROJECT}-*.gem").sort_by {|x| File.mtime(x) }.last
|
41
|
+
dir = gemfile.sub(/\.gem$/, '')
|
42
|
+
rm_rf dir if File.exist?(dir)
|
43
|
+
mkdir dir
|
44
|
+
mkdir "#{dir}/data"
|
45
|
+
cd dir do
|
46
|
+
sh "tar xvf ../#{gemfile}"
|
47
|
+
sh "gunzip *.gz"
|
48
|
+
cd "data" do
|
49
|
+
sh "tar xvf ../data.tar"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
desc "upload gem file to rubygems.org"
|
56
|
+
task :publish do
|
57
|
+
do_publish()
|
58
|
+
end
|
59
|
+
|
60
|
+
def do_publish()
|
61
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
62
|
+
gemfile = "#{PROJECT}-#{RELEASE}.gem"
|
63
|
+
print "** Are you sure to publish #{gemfile}? [y/N]: "
|
64
|
+
answer = $stdin.gets().strip()
|
65
|
+
if answer.downcase == "y"
|
66
|
+
sh "gem push #{gemfile}"
|
67
|
+
#sh "git tag ruby-#{PROJECT}-#{RELEASE}"
|
68
|
+
sh "git tag #{PROJECT}-#{RELEASE}"
|
69
|
+
sh "#git push"
|
70
|
+
sh "#git push --tags"
|
71
|
+
end
|
72
|
+
end
|
data/task/readme-task.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
README_FILE = "README.md" unless defined? README_FILE
|
4
|
+
README_EXTRACT = /^[Ff]ile: +(\S+)/ unless defined? README_EXTRACT
|
5
|
+
README_CODESTART = /^```\w+$/ unless defined? README_CODESTART
|
6
|
+
README_CODEEND = /^```$/ unless defined? README_CODEEND
|
7
|
+
README_DESTDIR = "tmp/readme" unless defined? README_DESTDIR
|
8
|
+
|
9
|
+
require 'rake/clean'
|
10
|
+
CLEAN << "README.html"
|
11
|
+
|
12
|
+
|
13
|
+
def readme_extract_callback(filename, str)
|
14
|
+
return str
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
namespace :readme do
|
19
|
+
|
20
|
+
|
21
|
+
desc "retrieve scripts from #{README_FILE}"
|
22
|
+
task :retrieve do
|
23
|
+
do_readme_retrieve()
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_readme_retrieve()
|
27
|
+
dir = README_DESTDIR
|
28
|
+
rm_rf dir if File.exist?(dir)
|
29
|
+
mkdir_p dir
|
30
|
+
s = File.read(README_FILE, encoding: 'utf-8')
|
31
|
+
filename = nil
|
32
|
+
buf = nil
|
33
|
+
s.each_line do |line|
|
34
|
+
case line
|
35
|
+
when README_EXTRACT
|
36
|
+
filename = $1
|
37
|
+
next
|
38
|
+
when README_CODESTART
|
39
|
+
if filename
|
40
|
+
buf = []
|
41
|
+
end
|
42
|
+
next
|
43
|
+
when README_CODEEND
|
44
|
+
if filename && buf
|
45
|
+
newfile = "#{dir}/#{filename}"
|
46
|
+
unless File.exist?(File.dirname(newfile))
|
47
|
+
mkdir_p File.dirname(newfile)
|
48
|
+
end
|
49
|
+
str = readme_extract_callback(filename, buf.join())
|
50
|
+
File.write(newfile, str, encoding: 'utf-8')
|
51
|
+
puts "[retrieve] #{newfile}"
|
52
|
+
end
|
53
|
+
filename = nil
|
54
|
+
buf = nil
|
55
|
+
next
|
56
|
+
end
|
57
|
+
#
|
58
|
+
if buf
|
59
|
+
buf << line
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
desc "execute code in readme file"
|
66
|
+
task :execute => :retrieve do
|
67
|
+
do_readme_execute()
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_readme_execute()
|
71
|
+
Dir.glob(README_DESTDIR+'/**/*.rb').sort.each do |fpath|
|
72
|
+
puts "========================================"
|
73
|
+
sh "ruby -I lib #{fpath}" do end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
desc "builds table of contents"
|
79
|
+
task :toc do
|
80
|
+
do_readme_toc()
|
81
|
+
end
|
82
|
+
|
83
|
+
def do_readme_toc()
|
84
|
+
url = ENV['README_URL'] or abort "$README_URL required."
|
85
|
+
mkdir "tmp" unless Dir.exist?("tmp")
|
86
|
+
htmlfile = "tmp/README.html"
|
87
|
+
sh "curl -s -o #{htmlfile} #{url}"
|
88
|
+
#rexp = /<h(\d) dir="auto"><a id="(.*?)" class="anchor".*><\/a>(.*)<\/h\1>/
|
89
|
+
rexp = /<h(\d) id="user-content-.*?" dir="auto"><a class="heading-link" href="#(.*?)">(.*)<svg/
|
90
|
+
html_str = File.read(htmlfile, encoding: 'utf-8')
|
91
|
+
buf = []
|
92
|
+
html_str.scan(rexp) do
|
93
|
+
level = $1.to_i
|
94
|
+
id = $2
|
95
|
+
title = $3
|
96
|
+
next if title =~ /Table of Contents/
|
97
|
+
title = title.gsub(/<\/?code>/, '`')
|
98
|
+
anchor = id.sub(/^user-content-/, '')
|
99
|
+
indent = " " * (level - 1)
|
100
|
+
buf << "#{indent}* <a href=\"##{anchor}\">#{title}</a>\n"
|
101
|
+
end
|
102
|
+
buf.shift() if buf[0] && buf[0] =~ /^\* /
|
103
|
+
toc_str = buf.join()
|
104
|
+
#
|
105
|
+
mdfile = README_FILE
|
106
|
+
changed = File.open(mdfile, "r+", encoding: 'utf-8') do |f|
|
107
|
+
s1 = f.read()
|
108
|
+
s2 = s1.sub(/(<!-- TOC -->\n).*(<!-- \/TOC -->\n)/m) {
|
109
|
+
[$1, toc_str, $2].join("\n")
|
110
|
+
}
|
111
|
+
if s1 != s2
|
112
|
+
f.rewind()
|
113
|
+
f.truncate(0)
|
114
|
+
f.write(s2)
|
115
|
+
true
|
116
|
+
else
|
117
|
+
false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
puts "[changed] #{mdfile}" if changed
|
121
|
+
puts "[not changed] #{mdfile}" unless changed
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
data/task/test-task.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
unless defined?(RUBY_VERSIONS)
|
5
|
+
RUBY_VERSIONS = (
|
6
|
+
if ENV['RUBY_VERSIONS']
|
7
|
+
ENV['RUBY_VERSIONS'].split()
|
8
|
+
else
|
9
|
+
["3.2", "3.1", "3.0", "2.7", "2.6", "2.5", "2.4", "2.3"]
|
10
|
+
end
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
desc "run test"
|
16
|
+
task :test do
|
17
|
+
do_test()
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_test()
|
21
|
+
run_test()
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_test(ruby=nil, &b)
|
25
|
+
run_oktest(ruby, &b)
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_minitest(ruby=nil, &b)
|
29
|
+
files = File.exist?("test/run_all.rb") \
|
30
|
+
? ["test/run_all.rb"] \
|
31
|
+
: Dir.glob("test/**/*_test.rb")
|
32
|
+
if ruby
|
33
|
+
sh(ruby, *files, &b)
|
34
|
+
else
|
35
|
+
ruby(*files, &b)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_oktest(ruby=nil, &b)
|
40
|
+
argstr = "-r oktest -e Oktest.main -- test -sp"
|
41
|
+
if ruby
|
42
|
+
sh("#{ruby} #{argstr}", &b)
|
43
|
+
else
|
44
|
+
ruby(argstr, &b)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
desc "run test in different ruby versions"
|
50
|
+
task :'test:all' do
|
51
|
+
do_test_all()
|
52
|
+
end
|
53
|
+
|
54
|
+
def do_test_all()
|
55
|
+
ENV['VS_HOME'] or
|
56
|
+
abort "[ERROR] rake test:all: '$VS_HOME' environment var required."
|
57
|
+
vs_home = ENV['VS_HOME'].split(/[:;]/).first
|
58
|
+
ruby_versions = RUBY_VERSIONS
|
59
|
+
test_all(vs_home, ruby_versions)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_all(vs_home, ruby_versions)
|
63
|
+
header = proc {|s| "\033[0;36m=============== #{s} ===============\033[0m" }
|
64
|
+
error = proc {|s| "\033[0;31m** #{s}\033[0m" }
|
65
|
+
comp = proc {|x, y| x.to_s.split('.').map(&:to_i) <=> y.to_s.split('.').map(&:to_i) }
|
66
|
+
ruby_versions.each do |ver|
|
67
|
+
dir = Dir.glob("#{vs_home}/ruby/#{ver}.*/").sort_by(&comp).last
|
68
|
+
puts ""
|
69
|
+
if dir
|
70
|
+
puts header.("#{ver} (#{dir})")
|
71
|
+
run_test("#{dir}/bin/ruby") do |ok, res|
|
72
|
+
$stderr.puts error.("test failed") unless ok
|
73
|
+
end
|
74
|
+
sleep 0.2
|
75
|
+
else
|
76
|
+
puts header.(ver)
|
77
|
+
$stderr.puts error.("ruby #{ver} not found")
|
78
|
+
sleep 1.0
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|