wad 0.2.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 +7 -0
- data/Gemfile +3 -0
- data/LICENSE +23 -0
- data/README +71 -0
- data/bin/wad +22 -0
- data/lib/wad/bundle.rb +52 -0
- data/lib/wad/compiler.rb +93 -0
- data/lib/wad/file.rb +34 -0
- data/lib/wad/gem.rb +49 -0
- data/lib/wad/reporter.rb +85 -0
- data/lib/wad/target.rb +52 -0
- data/lib/wad/vendor/highlight.rb +298 -0
- data/wad.gemspec +47 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a1b10e3871e52d7c16f10d19fe4309ad1b139e2a
|
4
|
+
data.tar.gz: 87f4f52ba33d1ed5591252d00b234861073bb005
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d4e44bbb4bebad9f1e31b3d12c32f670a10f8c176cda11d5d018cb57f8b4722cb1256ca63ff66f5da685ca838cf56cf867206793e00132d6db4b12b647c33e12
|
7
|
+
data.tar.gz: 5cd247d3a93716847cd5758ce1de8dec73c8946de11563fc06b1847645a59070c1c41ce813b6d6765cc53701d30deceb63abe15329e3c7ecb35bdff9f1838d4c
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2015 Kaspar Schiess
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person
|
5
|
+
obtaining a copy of this software and associated documentation
|
6
|
+
files (the "Software"), to deal in the Software without
|
7
|
+
restriction, including without limitation the rights to use,
|
8
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the
|
10
|
+
Software is furnished to do so, subject to the following
|
11
|
+
conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
NAME
|
3
|
+
|
4
|
+
wad - rolls all your libraries in a big wad, ghetto style
|
5
|
+
|
6
|
+
After rubygems and bundler, let us take you full circle and go back to a
|
7
|
+
lib directory that contains all your libraries. Except now, it's per project.
|
8
|
+
|
9
|
+
SYNOPSIS
|
10
|
+
|
11
|
+
$ wad roll # installs all your libs into 'vendor/lib', by default.
|
12
|
+
|
13
|
+
DESCRIPTION
|
14
|
+
|
15
|
+
Since we're all following very strict standards with regards to how our gems
|
16
|
+
are constructed, we might as well pack all those gems back into a directory
|
17
|
+
and use that directory in our load path.
|
18
|
+
|
19
|
+
Once you do that, you'll discover that loading from all these paths and doing
|
20
|
+
dependency resolution cost on every ruby invocation. On our machines, using
|
21
|
+
wad saves us >500ms every time, on every call.
|
22
|
+
|
23
|
+
Wad helps you with getting there: It vendors your Gemfile below `vendor/bundle`,
|
24
|
+
then copies relevant source code to `vendor/lib`. All in one simple call.
|
25
|
+
|
26
|
+
After that, the standard code for augmenting the load path in your binaries
|
27
|
+
becomes:
|
28
|
+
|
29
|
+
require 'pathname'
|
30
|
+
root = Pathname.new(__FILE__).dirname.join('..').expand_path
|
31
|
+
%w(vendor/lib lib).each { |p| $:.unshift(root.join(p)) }
|
32
|
+
|
33
|
+
require 'mylib' # And it's simple requires from then on.
|
34
|
+
|
35
|
+
It might be useful to extend your (bash) .profile with something like this:
|
36
|
+
|
37
|
+
function be() {
|
38
|
+
if [[ -d vendor/lib ]]; then
|
39
|
+
RUBYOPT="-I vendor/lib" command $*
|
40
|
+
else
|
41
|
+
if [[ -a Gemfile ]]; then
|
42
|
+
bundle exec $*
|
43
|
+
else
|
44
|
+
command $*
|
45
|
+
fi
|
46
|
+
fi
|
47
|
+
}
|
48
|
+
alias ruby="be ruby"
|
49
|
+
alias rake="be rake"
|
50
|
+
alias rspec="be rspec"
|
51
|
+
alias irb="be irb"
|
52
|
+
|
53
|
+
This way, you don't notice wad. Except that it boots real quick.
|
54
|
+
|
55
|
+
INSTALL
|
56
|
+
|
57
|
+
$ gem install wad
|
58
|
+
|
59
|
+
BUGS
|
60
|
+
|
61
|
+
This is new and will get you into all sorts of trouble, unless you know what
|
62
|
+
you're doing. But if you don't, you're in trouble anyway. In short: if any
|
63
|
+
milk gets spilt, don't expect us to lick it.
|
64
|
+
|
65
|
+
COPYRIGHT
|
66
|
+
|
67
|
+
MIT. See LICENSE file.
|
68
|
+
|
69
|
+
AUTHORS
|
70
|
+
|
71
|
+
Resident Astronauts: Kaspar Schiess (Technology Astronauts dot ch) & Florian Hanke (Technology Astronauts dot ch)
|
data/bin/wad
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'clamp'
|
5
|
+
|
6
|
+
$:.unshift Pathname.new(__FILE__).dirname.join('../lib')
|
7
|
+
require 'wad/compiler'
|
8
|
+
|
9
|
+
class CompileCommand < Clamp::Command
|
10
|
+
option '--root', "PROJECT_ROOT", 'root of the project to compile'
|
11
|
+
|
12
|
+
def execute
|
13
|
+
compiler = Wad::Compiler.new(root || Pathname.new(Dir.pwd))
|
14
|
+
compiler.compile
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class WadApp < Clamp::Command
|
19
|
+
subcommand 'roll', 'rolls your library in a big wad in vendor/lib', CompileCommand
|
20
|
+
end
|
21
|
+
|
22
|
+
WadApp.run
|
data/lib/wad/bundle.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'mixlib/shellout'
|
3
|
+
|
4
|
+
module Wad
|
5
|
+
# Interaction with bundler THROUGH THE COMMAND LINE SINCE THE CODE IS REALLY
|
6
|
+
# COMPLICATED.
|
7
|
+
#
|
8
|
+
class Bundle
|
9
|
+
class LiveDelegator
|
10
|
+
def initialize &block
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def << buffer
|
15
|
+
buffer.lines.each do |line|
|
16
|
+
@block.call(line.chomp)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def install &block
|
22
|
+
status = bundle(:install, live_stream: LiveDelegator.new(&block))
|
23
|
+
! status.error?
|
24
|
+
end
|
25
|
+
|
26
|
+
def list *a
|
27
|
+
cmd = bundle(:list, *a, raise_on_error: true)
|
28
|
+
cmd.stdout
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def bundle *a, **opts
|
33
|
+
raise_on_error = opts.delete(:raise_on_error)
|
34
|
+
|
35
|
+
timeout = 60*60 # seconds
|
36
|
+
a = a.map { |e| e.to_s }
|
37
|
+
a.unshift 'bundle'
|
38
|
+
|
39
|
+
runner = Mixlib::ShellOut.new(
|
40
|
+
*a,
|
41
|
+
opts.merge(timeout: timeout))
|
42
|
+
|
43
|
+
runner.run_command
|
44
|
+
|
45
|
+
if raise_on_error
|
46
|
+
runner.error!
|
47
|
+
end
|
48
|
+
|
49
|
+
runner
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/wad/compiler.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'rubygems/specification'
|
6
|
+
|
7
|
+
require 'wad/gem'
|
8
|
+
require 'wad/target'
|
9
|
+
require 'wad/reporter'
|
10
|
+
require 'wad/bundle'
|
11
|
+
|
12
|
+
module Wad
|
13
|
+
class Compiler
|
14
|
+
|
15
|
+
attr_reader :root
|
16
|
+
attr_reader :reporter
|
17
|
+
attr_reader :bundle
|
18
|
+
|
19
|
+
# Constructs a new compiler which will do its work in root/vendor, copying
|
20
|
+
# vendor/bundle to vendor/lib.
|
21
|
+
#
|
22
|
+
# @param root [Pathname] root of the project
|
23
|
+
#
|
24
|
+
def initialize root
|
25
|
+
@root = root
|
26
|
+
@reporter = Reporter.new
|
27
|
+
@bundle = Bundle.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def compile
|
31
|
+
target = Target.new(root, 'vendor/lib', reporter)
|
32
|
+
|
33
|
+
empty(target)
|
34
|
+
bundle_install or raise "Please fix bundler failures first."
|
35
|
+
copy_files(target)
|
36
|
+
end
|
37
|
+
|
38
|
+
def empty target
|
39
|
+
reporter.report_emptying(target)
|
40
|
+
# Danger.
|
41
|
+
FileUtils.rm_rf(target.path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def bundle_install
|
45
|
+
status = false # declare local var
|
46
|
+
|
47
|
+
reporter.report_bundle_install do
|
48
|
+
status = bundle.install do |line|
|
49
|
+
reporter.report_bundle_install_line(line)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
status
|
54
|
+
end
|
55
|
+
|
56
|
+
def copy_files target
|
57
|
+
reporter.report_copy_phase(target)
|
58
|
+
|
59
|
+
# my editor messes up highlighting upon encountering 'gem'... so ghem it is.
|
60
|
+
each_gem do |ghem|
|
61
|
+
reporter.report_copy_for(ghem) do
|
62
|
+
ghem.each_lib_file do |file|
|
63
|
+
# We can't 'copy' directories
|
64
|
+
next if file.directory?
|
65
|
+
|
66
|
+
file.copy(target)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def each_gem
|
75
|
+
bundle_list do |path, spec|
|
76
|
+
yield Gem.new(path, spec)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# @yield path_to_gem, gem_spec
|
81
|
+
#
|
82
|
+
def bundle_list
|
83
|
+
bundle.list('--paths').lines.each do |line|
|
84
|
+
path = Pathname.new(line.chomp)
|
85
|
+
|
86
|
+
gemspec_file = Pathname.glob(path.join('*.gemspec')).first
|
87
|
+
spec = ::Gem::Specification.load(gemspec_file.to_s)
|
88
|
+
|
89
|
+
yield path, spec
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/wad/file.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module Wad
|
3
|
+
|
4
|
+
# A file that is part of a gem.
|
5
|
+
#
|
6
|
+
class File
|
7
|
+
# Full file path
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
# Relative path this file should have after the copy
|
11
|
+
attr_reader :to
|
12
|
+
|
13
|
+
# Gem this belongs to
|
14
|
+
attr_reader :ghem
|
15
|
+
|
16
|
+
def initialize ghem, path, to
|
17
|
+
@ghem = ghem
|
18
|
+
@path = path
|
19
|
+
@to = to
|
20
|
+
end
|
21
|
+
|
22
|
+
def copy target
|
23
|
+
target.copy(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def gem_name
|
27
|
+
ghem.name
|
28
|
+
end
|
29
|
+
|
30
|
+
def directory?
|
31
|
+
path.directory?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/wad/gem.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
require 'wad/file'
|
3
|
+
|
4
|
+
module Wad
|
5
|
+
|
6
|
+
# Our internal representation of a gem that we copy files from.
|
7
|
+
#
|
8
|
+
class Gem
|
9
|
+
# Base directory of the gem version
|
10
|
+
attr_reader :base
|
11
|
+
# Name of the gem, currently including the version
|
12
|
+
attr_reader :name
|
13
|
+
# @return [Gem::Specification] loaded gemspec
|
14
|
+
attr_reader :spec
|
15
|
+
|
16
|
+
def initialize path, spec
|
17
|
+
@base = path
|
18
|
+
@spec = spec
|
19
|
+
@name = path.split.last.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def each_lib_file
|
23
|
+
each_require_path do |subdir|
|
24
|
+
subdir_path = base.join(subdir)
|
25
|
+
|
26
|
+
wildcard = base.join("#{subdir}/**/*")
|
27
|
+
Pathname.glob(wildcard).each do |path|
|
28
|
+
yield File.new(self, path, path.relative_path_from(subdir_path))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def each_require_path &block
|
34
|
+
if spec
|
35
|
+
# Filter the require paths to not include:
|
36
|
+
# a) '.', because that would mess up the toplevel dir in vendor/lib
|
37
|
+
# b) '../...', because those paths mostly point to bundles,
|
38
|
+
# which also exist in lib!
|
39
|
+
allowed_require_paths = Array(spec.require_paths)
|
40
|
+
.reject { |rqp| rqp.start_with?('.') }
|
41
|
+
|
42
|
+
allowed_require_paths.each(&block)
|
43
|
+
else
|
44
|
+
# If gemspec wasn't in the gem directory, let's just cheat.
|
45
|
+
yield 'lib'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/wad/reporter.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
require 'wad/vendor/highlight'
|
3
|
+
|
4
|
+
String.highlighter = Text::ANSIHighlighter.new
|
5
|
+
|
6
|
+
module Wad
|
7
|
+
|
8
|
+
class Gig
|
9
|
+
def initialize text
|
10
|
+
@n = 0
|
11
|
+
@text = text
|
12
|
+
|
13
|
+
put
|
14
|
+
end
|
15
|
+
|
16
|
+
def put
|
17
|
+
a = %w(| / - \\)
|
18
|
+
|
19
|
+
ab(@text, a[@n % a.size])
|
20
|
+
|
21
|
+
inc
|
22
|
+
end
|
23
|
+
|
24
|
+
def done status
|
25
|
+
ab(@text, status)
|
26
|
+
puts
|
27
|
+
end
|
28
|
+
|
29
|
+
def ab a, b
|
30
|
+
printf("\r%s [%s]", a, b)
|
31
|
+
end
|
32
|
+
|
33
|
+
def inc
|
34
|
+
@n += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Reports on progress.
|
39
|
+
#
|
40
|
+
class Reporter
|
41
|
+
attr_reader :gig
|
42
|
+
|
43
|
+
def report_emptying target
|
44
|
+
puts "Cleaning #{target}."
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param target [Target] copy target
|
48
|
+
#
|
49
|
+
def report_copy_phase target
|
50
|
+
# printf "-> %s\n", target.to_s.green
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param ghem [Gem] gem that copy phase is executed for
|
54
|
+
# @yield
|
55
|
+
#
|
56
|
+
def report_copy_for ghem
|
57
|
+
@gig = Gig.new(ghem.name.yellow)
|
58
|
+
@count = 0
|
59
|
+
|
60
|
+
yield
|
61
|
+
|
62
|
+
@gig.done 'done'.green + " (#{@count} files copied)"
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param gem_file [File] gem file that is being copied
|
66
|
+
# @param path [Pathname] target path
|
67
|
+
#
|
68
|
+
def report_copy_file gem_file, path
|
69
|
+
@count += 1
|
70
|
+
@gig.put
|
71
|
+
end
|
72
|
+
|
73
|
+
# @yield
|
74
|
+
#
|
75
|
+
def report_bundle_install
|
76
|
+
printf("Performing a `%s`...\n", "bundle install".yellow)
|
77
|
+
yield
|
78
|
+
printf(" > %s\n", '...looks good!'.green)
|
79
|
+
end
|
80
|
+
|
81
|
+
def report_bundle_install_line line
|
82
|
+
puts " > #{line}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/wad/target.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
module Wad
|
3
|
+
|
4
|
+
# A target directory that will gem files through #copy. Also keeps track of
|
5
|
+
# what files have already been written.
|
6
|
+
#
|
7
|
+
class Target
|
8
|
+
attr_reader :path
|
9
|
+
attr_reader :postfix
|
10
|
+
|
11
|
+
attr_reader :existing
|
12
|
+
attr_reader :old_source
|
13
|
+
|
14
|
+
attr_reader :reporter
|
15
|
+
|
16
|
+
def initialize path, postfix, reporter
|
17
|
+
@postfix = postfix
|
18
|
+
@path = path.join(postfix)
|
19
|
+
@existing = {}
|
20
|
+
@old_source = {}
|
21
|
+
@reporter = reporter
|
22
|
+
|
23
|
+
FileUtils.mkdir_p(path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
postfix
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy gem_file
|
31
|
+
key = gem_file.to.to_s
|
32
|
+
gem_name = gem_file.gem_name
|
33
|
+
|
34
|
+
# Try to detect multiple copies of one and the same gem file.
|
35
|
+
if existing.has_key?(key) && existing[key] != gem_name
|
36
|
+
name = existing[key]
|
37
|
+
old_path = old_source[key]
|
38
|
+
|
39
|
+
raise "Cannot copy #{gem_file.path} from #{gem_name}, already exists from #{name} (@#{old_path.to_s})."
|
40
|
+
else
|
41
|
+
existing[key] = gem_name
|
42
|
+
old_source[key] = gem_file.path
|
43
|
+
|
44
|
+
reporter.report_copy_file(gem_file, path)
|
45
|
+
|
46
|
+
dest = path.join(gem_file.to)
|
47
|
+
FileUtils.mkdir_p(dest.dirname)
|
48
|
+
FileUtils.cp(gem_file.path, dest) unless dest.file?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
# Our vendored copy of text-highlight (https://rubygems.org/gems/text-highlight)
|
4
|
+
# version 1.0.2 by Jeff Pace.
|
5
|
+
|
6
|
+
module Text
|
7
|
+
|
8
|
+
# Highlights text using either ANSI terminal codes, or HTML.
|
9
|
+
|
10
|
+
class Highlighter
|
11
|
+
|
12
|
+
VERSION = "1.0.2"
|
13
|
+
|
14
|
+
ATTRIBUTES = %w{
|
15
|
+
none
|
16
|
+
reset
|
17
|
+
bold
|
18
|
+
underscore
|
19
|
+
underline
|
20
|
+
blink
|
21
|
+
reverse
|
22
|
+
concealed
|
23
|
+
black
|
24
|
+
red
|
25
|
+
green
|
26
|
+
yellow
|
27
|
+
blue
|
28
|
+
magenta
|
29
|
+
cyan
|
30
|
+
white
|
31
|
+
on_black
|
32
|
+
on_red
|
33
|
+
on_green
|
34
|
+
on_yellow
|
35
|
+
on_blue
|
36
|
+
on_magenta
|
37
|
+
on_cyan
|
38
|
+
on_white
|
39
|
+
}
|
40
|
+
|
41
|
+
NONE = Object.new
|
42
|
+
HTML = Object.new
|
43
|
+
ANSI = Object.new
|
44
|
+
|
45
|
+
# Colorizes the given object. If a block is passed, its return value is used
|
46
|
+
# and the stream is reset. If a String is provided as the object, it is
|
47
|
+
# colorized and the stream is reset. Otherwise, only the code for the given
|
48
|
+
# color name is returned.
|
49
|
+
|
50
|
+
def color(colorname, obj = self, &blk)
|
51
|
+
# ^^^^ this is the Module self
|
52
|
+
result = name_to_code(colorname)
|
53
|
+
if blk
|
54
|
+
result << blk.call
|
55
|
+
result << name_to_code("reset")
|
56
|
+
elsif obj.kind_of?(String)
|
57
|
+
result << obj
|
58
|
+
result << name_to_code("reset")
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
ATTRIBUTES.each do |attr|
|
64
|
+
code = <<-EODEF
|
65
|
+
def #{attr}(&blk)
|
66
|
+
color("#{attr}", &blk)
|
67
|
+
end
|
68
|
+
|
69
|
+
EODEF
|
70
|
+
|
71
|
+
eval code
|
72
|
+
end
|
73
|
+
|
74
|
+
# returns the code for the given color string, which is in the format:
|
75
|
+
# foreground* [on background]?
|
76
|
+
#
|
77
|
+
# Note that the foreground and background sections can have modifiers
|
78
|
+
# (attributes).
|
79
|
+
#
|
80
|
+
# Examples:
|
81
|
+
# black
|
82
|
+
# blue on white
|
83
|
+
# bold green on yellow
|
84
|
+
# underscore bold magenta on cyan
|
85
|
+
# underscore red on cyan
|
86
|
+
|
87
|
+
def code(str)
|
88
|
+
fg, bg = str.split(/\s*\bon_?\s*/)
|
89
|
+
(fg ? foreground(fg) : "") + (bg ? background(bg) : "")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the code for the given background color(s).
|
93
|
+
def background(bgcolor)
|
94
|
+
name_to_code("on_" + bgcolor)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the code for the given foreground color(s).
|
98
|
+
def foreground(fgcolor)
|
99
|
+
fgcolor.split(/\s+/).collect { |fg| name_to_code(fg) }.join("")
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Highlights using HTML. Fonts are highlighted using <span> tags, not <font>.
|
106
|
+
# Also note that reverse is translated to white on black.
|
107
|
+
# According to http://www.w3.org/TR/REC-CSS2/syndata.html#value-def-color,
|
108
|
+
# valid color keywords are: aqua, black, blue, fuchsia, gray, green, lime,
|
109
|
+
# maroon, navy, olive, purple, red, silver, teal, white, and yellow.
|
110
|
+
# Thus, no magenta or cyan.
|
111
|
+
|
112
|
+
class HTMLHighlighter < Highlighter
|
113
|
+
|
114
|
+
def initialize
|
115
|
+
# we need to know what we're resetting from (bold, font, underlined ...)
|
116
|
+
@stack = []
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the start tag for the given name.
|
120
|
+
|
121
|
+
def start_style(name)
|
122
|
+
case name
|
123
|
+
when "reverse"
|
124
|
+
"<span style=\"color: white; background-color: black\">"
|
125
|
+
when /on_(\w+)/
|
126
|
+
"<span style=\"background-color: #{$1}\">"
|
127
|
+
else
|
128
|
+
"<span style=\"color: #{name}\">"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the end tag ("</span>").
|
133
|
+
|
134
|
+
def end_style
|
135
|
+
"</span>"
|
136
|
+
end
|
137
|
+
|
138
|
+
def color_value(cname)
|
139
|
+
case cname
|
140
|
+
when "cyan"
|
141
|
+
"#00FFFF"
|
142
|
+
when "magenta"
|
143
|
+
"#FF00FF"
|
144
|
+
else
|
145
|
+
cname
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns the code for the given name.
|
150
|
+
|
151
|
+
def name_to_code(name)
|
152
|
+
@stack << name
|
153
|
+
|
154
|
+
case name
|
155
|
+
when "none", "reset"
|
156
|
+
@stack.pop
|
157
|
+
str = ""
|
158
|
+
if @stack.length > 0
|
159
|
+
begin
|
160
|
+
prev = @stack.pop
|
161
|
+
case prev
|
162
|
+
when "bold"
|
163
|
+
str << "</b>"
|
164
|
+
when "underscore", "underline"
|
165
|
+
str << "</u>"
|
166
|
+
when "blink"
|
167
|
+
str << "</blink>"
|
168
|
+
when "concealed"
|
169
|
+
str << " -->"
|
170
|
+
else
|
171
|
+
str << end_style
|
172
|
+
end
|
173
|
+
end while @stack.length > 0
|
174
|
+
end
|
175
|
+
str
|
176
|
+
when "bold"
|
177
|
+
"<b>"
|
178
|
+
when "underscore", "underline"
|
179
|
+
"<u>"
|
180
|
+
when "blink"
|
181
|
+
"<blink>"
|
182
|
+
when "concealed"
|
183
|
+
"<!-- "
|
184
|
+
else
|
185
|
+
start_style(name)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
# Highlights using ANSI escape sequences.
|
193
|
+
|
194
|
+
class ANSIHighlighter < Highlighter
|
195
|
+
|
196
|
+
@@ATTRIBUTES = Hash[
|
197
|
+
'none' => '0',
|
198
|
+
'reset' => '0',
|
199
|
+
'bold' => '1',
|
200
|
+
'underscore' => '4',
|
201
|
+
'underline' => '4',
|
202
|
+
'blink' => '5',
|
203
|
+
'reverse' => '7',
|
204
|
+
'concealed' => '8',
|
205
|
+
'black' => '30',
|
206
|
+
'red' => '31',
|
207
|
+
'green' => '32',
|
208
|
+
'yellow' => '33',
|
209
|
+
'blue' => '34',
|
210
|
+
'magenta' => '35',
|
211
|
+
'cyan' => '36',
|
212
|
+
'white' => '37',
|
213
|
+
'on_black' => '40',
|
214
|
+
'on_red' => '41',
|
215
|
+
'on_green' => '42',
|
216
|
+
'on_yellow' => '43',
|
217
|
+
'on_blue' => '44',
|
218
|
+
'on_magenta' => '45',
|
219
|
+
'on_cyan' => '46',
|
220
|
+
'on_white' => '47',
|
221
|
+
]
|
222
|
+
|
223
|
+
# Returns the escape sequence for the given name.
|
224
|
+
|
225
|
+
def name_to_code(nm)
|
226
|
+
"\e[#{@@ATTRIBUTES[nm]}m"
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
# Does no highlighting.
|
233
|
+
|
234
|
+
class NonHighlighter < Highlighter
|
235
|
+
|
236
|
+
# Since the NonHighlighter does no highlighting, and thus its name, this
|
237
|
+
# returns an empty string.
|
238
|
+
|
239
|
+
def name_to_code(colorname)
|
240
|
+
""
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
# An object that can be highlighted. This is used by the String class.
|
247
|
+
|
248
|
+
module Highlightable
|
249
|
+
|
250
|
+
# The highlighter for the class in which this module is included.
|
251
|
+
|
252
|
+
@@highlighter = NonHighlighter.new
|
253
|
+
|
254
|
+
Text::Highlighter::ATTRIBUTES.each do |attr|
|
255
|
+
code = <<-EODEF
|
256
|
+
def #{attr}(&blk)
|
257
|
+
@@highlighter.color("#{attr}", self, &blk)
|
258
|
+
end
|
259
|
+
|
260
|
+
EODEF
|
261
|
+
|
262
|
+
eval code
|
263
|
+
end
|
264
|
+
|
265
|
+
alias negative reverse
|
266
|
+
|
267
|
+
# Sets the highlighter for this class. This can be either by type or by
|
268
|
+
# String.
|
269
|
+
|
270
|
+
def highlighter=(hl)
|
271
|
+
$VERBOSE = false
|
272
|
+
@@highlighter = case hl
|
273
|
+
when Text::Highlighter
|
274
|
+
hl
|
275
|
+
when Text::Highlighter::NONE, "NONE", nil
|
276
|
+
Text::NonHighlighter.new unless @@highlighter.kind_of?(Text::NonHighlighter)
|
277
|
+
when Text::Highlighter::HTML, "HTML"
|
278
|
+
Text::HTMLHighlighter.new unless @@highlighter.kind_of?(Text::HTMLHighlighter)
|
279
|
+
when Text::Highlighter::ANSI, "ANSI"
|
280
|
+
Text::ANSIHighlighter.new unless @@highlighter.kind_of?(Text::ANSIHighlighter)
|
281
|
+
else
|
282
|
+
Text::NonHighlighter.new
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
$HAVE_TEXT_HIGHLIGHT = true
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
# String is extended to support highlighting.
|
294
|
+
|
295
|
+
class String
|
296
|
+
include Text::Highlightable
|
297
|
+
extend Text::Highlightable
|
298
|
+
end
|
data/wad.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
# Yes, we don't use generators and hoes for this. This is simple enough.
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'wad'
|
7
|
+
s.version = '0.2.0'
|
8
|
+
|
9
|
+
s.authors = ['Kaspar Schiess', 'Florian Hanke']
|
10
|
+
s.email = [
|
11
|
+
'kaspar.schiess@technologyastronauts.ch',
|
12
|
+
'florian.hanke@technologyastronauts.ch']
|
13
|
+
s.extra_rdoc_files = ['README']
|
14
|
+
|
15
|
+
# Generate this manifest using 'git ls-tree -r --name-only master'
|
16
|
+
s.files = File.readlines('manifest.txt')
|
17
|
+
.map { |l| l.chomp } -
|
18
|
+
%w(.gitignore manifest.txt)
|
19
|
+
s.homepage = 'https://bitbucket.org/technologyastronauts/wad'
|
20
|
+
s.rdoc_options = ['--main', 'README']
|
21
|
+
s.require_paths = ['lib']
|
22
|
+
|
23
|
+
s.license = 'MIT'
|
24
|
+
|
25
|
+
s.summary =
|
26
|
+
'After rubygems and bundler, let us take you full circle and go back to a
|
27
|
+
lib directory that contains all your libraries. Except now, it\'s per project. '
|
28
|
+
|
29
|
+
s.description = <<-EOD
|
30
|
+
Since we're all following very strict standards with regards to how our gems
|
31
|
+
are constructed, we might as well pack all those gems back into a directory
|
32
|
+
and use that directory in our load path.
|
33
|
+
|
34
|
+
Once you do that, you'll discover that loading from all these paths and doing
|
35
|
+
dependency resolution cost on every ruby invocation. On our machines, using
|
36
|
+
wad saves us >500ms every time, on every call.
|
37
|
+
|
38
|
+
Wad helps you with getting there: It vendors your Gemfile below `vendor/bundle`,
|
39
|
+
then copies relevant source code to `vendor/lib`. All in one simple call.
|
40
|
+
EOD
|
41
|
+
|
42
|
+
s.executables << 'wad'
|
43
|
+
|
44
|
+
s.add_runtime_dependency 'clamp', '~> 0.6'
|
45
|
+
s.add_runtime_dependency 'bundler', '> 0'
|
46
|
+
s.add_runtime_dependency 'mixlib-shellout', '~> 2.0'
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kaspar Schiess
|
8
|
+
- Florian Hanke
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-05-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: clamp
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.6'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.6'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mixlib-shellout
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.0'
|
56
|
+
description: " Since we're all following very strict standards with regards to
|
57
|
+
how our gems \n are constructed, we might as well pack all those gems back into
|
58
|
+
a directory \n and use that directory in our load path. \n\n Once you do that,
|
59
|
+
you'll discover that loading from all these paths and doing \n dependency resolution
|
60
|
+
cost on every ruby invocation. On our machines, using \n wad saves us >500ms
|
61
|
+
every time, on every call. \n\n Wad helps you with getting there: It vendors
|
62
|
+
your Gemfile below `vendor/bundle`, \n then copies relevant source code to `vendor/lib`.
|
63
|
+
All in one simple call. \n"
|
64
|
+
email:
|
65
|
+
- kaspar.schiess@technologyastronauts.ch
|
66
|
+
- florian.hanke@technologyastronauts.ch
|
67
|
+
executables:
|
68
|
+
- wad
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files:
|
71
|
+
- README
|
72
|
+
files:
|
73
|
+
- Gemfile
|
74
|
+
- LICENSE
|
75
|
+
- README
|
76
|
+
- bin/wad
|
77
|
+
- lib/wad/bundle.rb
|
78
|
+
- lib/wad/compiler.rb
|
79
|
+
- lib/wad/file.rb
|
80
|
+
- lib/wad/gem.rb
|
81
|
+
- lib/wad/reporter.rb
|
82
|
+
- lib/wad/target.rb
|
83
|
+
- lib/wad/vendor/highlight.rb
|
84
|
+
- wad.gemspec
|
85
|
+
homepage: https://bitbucket.org/technologyastronauts/wad
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options:
|
91
|
+
- "--main"
|
92
|
+
- README
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.2.2
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: After rubygems and bundler, let us take you full circle and go back to a lib
|
111
|
+
directory that contains all your libraries. Except now, it's per project.
|
112
|
+
test_files: []
|
113
|
+
has_rdoc:
|