benry-cmdopt 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +34 -1
- data/MIT-LICENSE +21 -0
- data/README.md +570 -62
- data/Rakefile.rb +6 -87
- data/benry-cmdopt.gemspec +23 -21
- data/doc/benry-cmdopt.html +650 -0
- data/doc/css/style.css +160 -0
- data/lib/benry/cmdopt.rb +568 -417
- data/task/common-task.rb +138 -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 +1372 -681
- metadata +22 -28
data/task/common-task.rb
ADDED
@@ -0,0 +1,138 @@
|
|
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
|
+
END
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
desc "create 'README.md' and 'doc/*.html'"
|
61
|
+
task :doc do
|
62
|
+
x = PROJECT
|
63
|
+
cd "doc" do
|
64
|
+
sh "../../docs/md2 --md #{x}.mdx > ../README.md"
|
65
|
+
sh "../../docs/md2 #{x}.mdx > #{x}.html"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "copy 'doc/*.html' to '../docs/'"
|
70
|
+
task 'doc:export' do
|
71
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
72
|
+
x = PROJECT
|
73
|
+
cp "doc/#{x}.html", "../docs/"
|
74
|
+
edit_file!("../docs/#{x}.html")
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
desc "edit metadata in files"
|
79
|
+
task :edit do
|
80
|
+
do_edit()
|
81
|
+
end
|
82
|
+
|
83
|
+
def do_edit()
|
84
|
+
target_files().each do |fname|
|
85
|
+
edit_file!(fname)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def target_files()
|
90
|
+
$_target_files ||= begin
|
91
|
+
spec_src = File.read("#{PROJECT}.gemspec", encoding: 'utf-8')
|
92
|
+
spec = eval spec_src
|
93
|
+
spec.name == PROJECT or
|
94
|
+
abort "** ERROR: '#{PROJECT}' != '#{spec.name}' (project name in gemspec file)"
|
95
|
+
spec.files + Dir.glob("doc/*.mdx")
|
96
|
+
end
|
97
|
+
return $_target_files
|
98
|
+
end
|
99
|
+
|
100
|
+
def edit_file!(filename, verbose: true)
|
101
|
+
changed = edit_file(filename) do |s|
|
102
|
+
s = s.gsub(/\$Release[:].*?\$/, "$"+"Release: #{RELEASE} $")
|
103
|
+
s = s.gsub(/\$Copyright[:].*?\$/, "$"+"Copyright: #{COPYRIGHT} $")
|
104
|
+
s = s.gsub(/\$License[:].*?\$/, "$"+"License: #{LICENSE} $")
|
105
|
+
s
|
106
|
+
end
|
107
|
+
if verbose
|
108
|
+
puts "[C] #{filename}" if changed
|
109
|
+
puts "[U] #{filename}" unless changed
|
110
|
+
end
|
111
|
+
return changed
|
112
|
+
end
|
113
|
+
|
114
|
+
def edit_file(filename)
|
115
|
+
File.open(filename, 'rb+') do |f|
|
116
|
+
s1 = f.read()
|
117
|
+
s2 = yield s1
|
118
|
+
if s1 != s2
|
119
|
+
f.rewind()
|
120
|
+
f.truncate(0)
|
121
|
+
f.write(s2)
|
122
|
+
true
|
123
|
+
else
|
124
|
+
false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
desc nil
|
131
|
+
task :'relink' do
|
132
|
+
Dir.glob("task/*.rb").each do |x|
|
133
|
+
src = "../" + x
|
134
|
+
next if File.identical?(src, x)
|
135
|
+
rm x
|
136
|
+
ln src, x
|
137
|
+
end
|
138
|
+
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
|