wad 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|