mutter 0.3.2
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.
- data/.document +5 -0
- data/.gitignore +6 -0
- data/LICENSE +20 -0
- data/README.md +98 -0
- data/Rakefile +100 -0
- data/VERSION +1 -0
- data/lib/ext.rb +36 -0
- data/lib/mutter/indenter.rb +11 -0
- data/lib/mutter/mutterer.rb +179 -0
- data/lib/mutter/styles.yml +14 -0
- data/lib/mutter.rb +57 -0
- data/mutter.gemspec +52 -0
- data/spec/mutter_spec.rb +129 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/style.yml +14 -0
- metadata +71 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 cloudhead
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
mutter
|
2
|
+
======
|
3
|
+
|
4
|
+
$ my words come out,
|
5
|
+
in color and
|
6
|
+
style
|
7
|
+
|
8
|
+
> mutter takes the concepts of **separation of style & content** to the command-line!
|
9
|
+
|
10
|
+
synopsis
|
11
|
+
--------
|
12
|
+
|
13
|
+
require 'mutter'
|
14
|
+
|
15
|
+
mut = Mutter.new # creates a new 'Mutterer', who talks in command-line language
|
16
|
+
mut.say "hello _world_" # underlines 'world'
|
17
|
+
mut.say "hello world", :bold # bolds the whole string
|
18
|
+
mut.say "hello [world]", :cyan # inverts 'world', and colors the string cyan
|
19
|
+
mut.print "bonjour!" # alias of `say`
|
20
|
+
mut["_hola_"] # return the stylized string without printing
|
21
|
+
|
22
|
+
styles
|
23
|
+
------
|
24
|
+
mutter supports these styles:
|
25
|
+
|
26
|
+
:bold, :underline, :inverse, :blink
|
27
|
+
|
28
|
+
and these colors:
|
29
|
+
|
30
|
+
:red, :green, :blue, :yellow, :cyan, :purple, :white, :black
|
31
|
+
|
32
|
+
customization
|
33
|
+
-------------
|
34
|
+
|
35
|
+
styles = {
|
36
|
+
:warning => { # an alias you can use anywhere in mutter
|
37
|
+
:match => ['*!', '!*'], # will match *!mutter!*
|
38
|
+
:style => ['yellow', 'bold'] # these styles will be applied to the match
|
39
|
+
},
|
40
|
+
:error => {
|
41
|
+
:match => '!!', # will match !!mutter!!
|
42
|
+
:style => ['red', 'underline']
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
mut = Mutter.new(styles)
|
47
|
+
mut.say "warning, the dogs have escaped!", :warning # These two are
|
48
|
+
mut.warning "warning, the dogs have escaped!" # equivalent
|
49
|
+
mut.say "gosh, we have an !!error!!"
|
50
|
+
|
51
|
+
### YAML
|
52
|
+
|
53
|
+
The previous example could have (and should really have) been written in a separate .yml file, like so:
|
54
|
+
|
55
|
+
warning:
|
56
|
+
match:
|
57
|
+
- '*!'
|
58
|
+
- '!*
|
59
|
+
style:
|
60
|
+
- yellow
|
61
|
+
- bold
|
62
|
+
|
63
|
+
error:
|
64
|
+
match: '!!'
|
65
|
+
style:
|
66
|
+
- red
|
67
|
+
- underline
|
68
|
+
|
69
|
+
and then loaded like this:
|
70
|
+
|
71
|
+
Mutter.new("styles.yml")
|
72
|
+
|
73
|
+
### quick styles
|
74
|
+
|
75
|
+
mut = Mutter.new :yellow => '~'
|
76
|
+
mut.say "~[black on yellow!]~"
|
77
|
+
|
78
|
+
### add/remove styles from an instance
|
79
|
+
|
80
|
+
mut = Mutter.new(:blink)
|
81
|
+
mut >> :blink # remove :blink
|
82
|
+
mut << :bold << :underline # add :bold and :underline
|
83
|
+
mut.say "hello mutter." # bold and underlined
|
84
|
+
|
85
|
+
installation
|
86
|
+
------------
|
87
|
+
|
88
|
+
$ sudo gem install cloudhead-mutter
|
89
|
+
|
90
|
+
That's it!
|
91
|
+
----------
|
92
|
+
|
93
|
+
_have fun_
|
94
|
+
|
95
|
+
Footnote
|
96
|
+
--------
|
97
|
+
|
98
|
+
This code is _highly experimental_, don't try this at home!
|
data/Rakefile
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "mutter"
|
8
|
+
gem.summary = %Q{the tiny CLI library}
|
9
|
+
gem.email = "self@cloudhead.net"
|
10
|
+
gem.homepage = "http://github.com/cloudhead/mutter"
|
11
|
+
gem.rubyforge_project = 'mutter'
|
12
|
+
gem.authors = ["cloudhead"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
# rubyforge
|
21
|
+
begin
|
22
|
+
require 'rake/contrib/sshpublisher'
|
23
|
+
namespace :rubyforge do
|
24
|
+
desc "Release gem and RDoc documentation to RubyForge"
|
25
|
+
task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
|
26
|
+
|
27
|
+
namespace :release do
|
28
|
+
desc "Publish RDoc to RubyForge."
|
29
|
+
task :docs => [:rdoc] do
|
30
|
+
config = YAML.load(
|
31
|
+
File.read(File.expand_path('~/.rubyforge/user-config.yml'))
|
32
|
+
)
|
33
|
+
options << '--line-numbers' << '--inline-source'
|
34
|
+
host = "#{config['username']}@rubyforge.org"
|
35
|
+
remote_dir = "/var/www/gforge-projects/the-perfect-gem/"
|
36
|
+
local_dir = 'rdoc'
|
37
|
+
|
38
|
+
Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'rake/testtask'
|
47
|
+
Rake::TestTask.new(:test) do |test|
|
48
|
+
test.libs << 'lib' << 'test'
|
49
|
+
test.pattern = 'test/**/*_test.rb'
|
50
|
+
test.verbose = true
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
require 'rcov/rcovtask'
|
55
|
+
Rcov::RcovTask.new do |test|
|
56
|
+
test.libs << 'test'
|
57
|
+
test.pattern = 'test/**/*_test.rb'
|
58
|
+
test.verbose = true
|
59
|
+
end
|
60
|
+
rescue LoadError
|
61
|
+
task :rcov do
|
62
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
task :default => :test
|
68
|
+
|
69
|
+
require 'rake/rdoctask'
|
70
|
+
Rake::RDocTask.new do |rdoc|
|
71
|
+
if File.exist?('VERSION.yml')
|
72
|
+
config = YAML.load(File.read('VERSION.yml'))
|
73
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
74
|
+
else
|
75
|
+
version = ""
|
76
|
+
end
|
77
|
+
|
78
|
+
rdoc.rdoc_dir = 'rdoc'
|
79
|
+
rdoc.title = "mutter #{version}"
|
80
|
+
rdoc.rdoc_files.include('README*')
|
81
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
82
|
+
end
|
83
|
+
|
84
|
+
require 'spec/rake/spectask'
|
85
|
+
|
86
|
+
Spec::Rake::SpecTask.new("spec") do |t|
|
87
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
88
|
+
t.spec_opts = ['--color', '--format=specdoc']
|
89
|
+
end
|
90
|
+
|
91
|
+
task :test do
|
92
|
+
Rake::Task['spec'].invoke
|
93
|
+
end
|
94
|
+
|
95
|
+
Spec::Rake::SpecTask.new("rcov_spec") do |t|
|
96
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
97
|
+
t.spec_opts = ['--color']
|
98
|
+
t.rcov = true
|
99
|
+
t.rcov_opts = ['--exclude', '^spec,/gems/']
|
100
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.2
|
data/lib/ext.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'mutter'
|
2
|
+
|
3
|
+
class String
|
4
|
+
def examine depth = 0
|
5
|
+
inspect
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Array
|
10
|
+
def examine depth = 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Hash
|
15
|
+
def examine depth = 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Symbol
|
20
|
+
def examine depth = 0
|
21
|
+
Mutter.stylize inspect, :purple
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Numeric
|
26
|
+
def examine depth = 0
|
27
|
+
Mutter.stylize inspect, :cyan
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Object
|
32
|
+
def tap
|
33
|
+
yield self
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module Mutter
|
2
|
+
class Mutterer
|
3
|
+
attr_accessor :styles
|
4
|
+
|
5
|
+
@stream = STDOUT
|
6
|
+
|
7
|
+
# Initialize the styles, and load the defaults from +styles.yml+
|
8
|
+
#
|
9
|
+
# @active: currently active styles, which apply to the whole string
|
10
|
+
# @styles: contains all the user + default styles
|
11
|
+
#
|
12
|
+
def initialize obj = {}
|
13
|
+
@active, @styles = [], {}
|
14
|
+
load File.dirname(__FILE__) + "/styles"
|
15
|
+
|
16
|
+
case obj
|
17
|
+
when Hash # A style definition: expand quick-styles and merge with @styles
|
18
|
+
obj = obj.inject({}) do |h, (k, v)|
|
19
|
+
h.merge k =>
|
20
|
+
(v.is_a?(Hash) ? v : { :match => v, :style => [k].flatten })
|
21
|
+
end
|
22
|
+
@styles.merge! obj
|
23
|
+
when Array # An array of styles to be activated
|
24
|
+
@active = obj
|
25
|
+
when Symbol # A single style to be activated
|
26
|
+
self.<< obj
|
27
|
+
when String # The path of a yaml style-sheet
|
28
|
+
load obj
|
29
|
+
else raise ArgumentError
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Create an instance method for each style
|
34
|
+
#
|
35
|
+
@styles.keys.each do |style|
|
36
|
+
(class << self; self end).class_eval do
|
37
|
+
define_method style do |msg|
|
38
|
+
say msg, style
|
39
|
+
end
|
40
|
+
end if style.is_a? Symbol
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Loads styles from a YAML style-sheet,
|
46
|
+
# and converts the keys to symbols
|
47
|
+
#
|
48
|
+
def load styles
|
49
|
+
styles += '.yml' unless styles =~ /\.ya?ml/
|
50
|
+
@defaults = YAML.load_file(styles).inject({}) do |h, (key, value)|
|
51
|
+
value = { :match => value['match'], :style => value['style'] }
|
52
|
+
h.merge key.to_sym => value
|
53
|
+
end
|
54
|
+
@styles.merge! @defaults
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Output to @stream
|
59
|
+
#
|
60
|
+
def say msg, *styles
|
61
|
+
self.write (ENV['TERM'].include?('color') ? process(msg, *styles) : msg) + "\n"
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
|
65
|
+
alias :print say
|
66
|
+
|
67
|
+
#
|
68
|
+
# Parse the message, but also apply a style on the whole thing
|
69
|
+
#
|
70
|
+
def process msg, *styles
|
71
|
+
stylize(parse(msg), @active + styles).gsub(/\e(\d+)\e/, "\e[\\1m")
|
72
|
+
end
|
73
|
+
alias :[] process
|
74
|
+
|
75
|
+
#
|
76
|
+
# Write to the out stream, and flush it
|
77
|
+
#
|
78
|
+
def write str
|
79
|
+
self.class.stream.tap do |stream|
|
80
|
+
stream.write str
|
81
|
+
stream.flush
|
82
|
+
end; nil
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Utility function, to make a block interruptible
|
87
|
+
#
|
88
|
+
def watch
|
89
|
+
begin
|
90
|
+
yield
|
91
|
+
rescue Interrupt
|
92
|
+
puts
|
93
|
+
exit 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
alias :oo watch
|
97
|
+
|
98
|
+
#
|
99
|
+
# Add and remove styles from the active styles
|
100
|
+
#
|
101
|
+
def << style
|
102
|
+
@active << style
|
103
|
+
end
|
104
|
+
|
105
|
+
def >> style
|
106
|
+
@active.delete style
|
107
|
+
end
|
108
|
+
|
109
|
+
def + style
|
110
|
+
dup.tap {|m| m << style }
|
111
|
+
end
|
112
|
+
|
113
|
+
def - style
|
114
|
+
dup.tap {|m| m >> style }
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Parse a string to ANSI codes
|
119
|
+
#
|
120
|
+
# if the glyph is a pair, we match [0] as the start
|
121
|
+
# and [1] as the end marker.
|
122
|
+
# the matches are sent to +stylize+
|
123
|
+
#
|
124
|
+
def parse string
|
125
|
+
@styles.inject(string) do |str, (name, options)|
|
126
|
+
glyph, styles = options[:match], options[:style]
|
127
|
+
if glyph.is_a? Array
|
128
|
+
str.gsub(/#{Regexp.escape(glyph.first)}(.+?)
|
129
|
+
#{Regexp.escape(glyph.last)}/x) { stylize $1, styles }
|
130
|
+
else
|
131
|
+
str.gsub(/(#{Regexp.escape(glyph)}+)(.+?)\1/) { stylize $2, styles }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
#
|
137
|
+
# Apply styles to a string
|
138
|
+
#
|
139
|
+
# if the style is a default ANSI style, we add the start
|
140
|
+
# and end sequence to the string.
|
141
|
+
#
|
142
|
+
# if the style is a custom style, we recurse, sending
|
143
|
+
# the list of ANSI styles contained in the custom style.
|
144
|
+
#
|
145
|
+
# TODO: use ';' delimited codes instead of multiple \e sequences
|
146
|
+
#
|
147
|
+
def stylize string, styles = []
|
148
|
+
[styles].flatten.inject(string) do |str, style|
|
149
|
+
style = style.to_sym
|
150
|
+
if ANSI[:transforms].include? style
|
151
|
+
esc str, *ANSI[:transforms][style]
|
152
|
+
elsif ANSI[:colors].include? style
|
153
|
+
esc str, ANSI[:colors][style], ANSI[:colors][:reset]
|
154
|
+
else
|
155
|
+
stylize(str, @styles[style][:style])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Escape a string, for later replacement
|
162
|
+
#
|
163
|
+
def esc str, open, close
|
164
|
+
"\e#{open}\e" + str + "\e#{close}\e"
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# Output stream (defaults to STDOUT)
|
169
|
+
# mostly for test purposes
|
170
|
+
#
|
171
|
+
def self.stream
|
172
|
+
@stream
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.stream= io
|
176
|
+
@stream = io
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
data/lib/mutter.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#
|
2
|
+
# Mutter — the tiny command-line interface library with lots of style~
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
$:.unshift File.dirname(__FILE__) + '/mutter'
|
8
|
+
|
9
|
+
require 'mutterer'
|
10
|
+
require 'indenter'
|
11
|
+
require 'io'
|
12
|
+
require 'ext'
|
13
|
+
|
14
|
+
module Mutter
|
15
|
+
#
|
16
|
+
# ANSI color & transform codes
|
17
|
+
#
|
18
|
+
# If the value's an array,
|
19
|
+
# [0] is the start code
|
20
|
+
# and [1] is the end code.
|
21
|
+
#
|
22
|
+
# Colors all have the same
|
23
|
+
# reset code (39).
|
24
|
+
#
|
25
|
+
ANSI = {
|
26
|
+
:reset => 0,
|
27
|
+
:transforms => {
|
28
|
+
:bold => [1, 22],
|
29
|
+
:underline => [4, 24],
|
30
|
+
:blink => [5, 25],
|
31
|
+
:inverse => [7, 27]
|
32
|
+
},
|
33
|
+
:colors => {
|
34
|
+
:black => 30, :red => 31,
|
35
|
+
:green => 32, :yellow => 33,
|
36
|
+
:blue => 34, :purple => 35,
|
37
|
+
:cyan => 36, :white => 37,
|
38
|
+
:reset => 39
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
def self.indenter tab
|
43
|
+
Indenter.new tab
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.say *args
|
47
|
+
new.say *args
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.stylize *args
|
51
|
+
new.stylize *args
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.new *args
|
55
|
+
Mutterer.new(*args)
|
56
|
+
end
|
57
|
+
end
|
data/mutter.gemspec
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{mutter}
|
5
|
+
s.version = "0.3.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["cloudhead"]
|
9
|
+
s.date = %q{2009-09-02}
|
10
|
+
s.email = %q{self@cloudhead.net}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.md"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".document",
|
17
|
+
".gitignore",
|
18
|
+
"LICENSE",
|
19
|
+
"README.md",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"lib/ext.rb",
|
23
|
+
"lib/mutter.rb",
|
24
|
+
"lib/mutter/indenter.rb",
|
25
|
+
"lib/mutter/mutterer.rb",
|
26
|
+
"lib/mutter/styles.yml",
|
27
|
+
"mutter.gemspec",
|
28
|
+
"spec/mutter_spec.rb",
|
29
|
+
"spec/spec_helper.rb",
|
30
|
+
"spec/style.yml"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/cloudhead/mutter}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubyforge_project = %q{mutter}
|
36
|
+
s.rubygems_version = %q{1.3.5}
|
37
|
+
s.summary = %q{the tiny CLI library}
|
38
|
+
s.test_files = [
|
39
|
+
"spec/mutter_spec.rb",
|
40
|
+
"spec/spec_helper.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
else
|
49
|
+
end
|
50
|
+
else
|
51
|
+
end
|
52
|
+
end
|
data/spec/mutter_spec.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Mutter do
|
4
|
+
def out
|
5
|
+
File.read("spec/out.txt")
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
Mutter::Mutterer.stream = File.new("spec/out.txt", 'w')
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:all) do
|
13
|
+
File.delete("spec/out.txt")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should output strings" do
|
17
|
+
Mutter.say "hello mutter!"
|
18
|
+
out.should == "hello mutter!\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should underline" do
|
22
|
+
Mutter.say "_hello mutter!_"
|
23
|
+
out.should == "\e[4mhello mutter!\e[24m\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should bold" do
|
27
|
+
Mutter.say "*hello mutter!*"
|
28
|
+
out.should == "\e[1mhello mutter!\e[22m\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should inverse" do
|
32
|
+
Mutter.say "[hello mutter!]"
|
33
|
+
out.should == "\e[7mhello mutter!\e[27m\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should blink" do
|
37
|
+
Mutter.say "hello mutter!", :blink
|
38
|
+
out.should == "\e[5mhello mutter!\e[25m\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should escape glyphs" do
|
42
|
+
Mutter.say "**hello * world**"
|
43
|
+
out.should == "\e[1mhello * world\e[22m\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set defaults at the instance level" do
|
47
|
+
Mutter.new([:bold, :underline]).say "hello mutter!"
|
48
|
+
out.should == "\e[4m\e[1mhello mutter!\e[22m\e[24m\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set defaults at the method level" do
|
52
|
+
Mutter.say "hello mutter!", :bold, :underline
|
53
|
+
out.should == "\e[4m\e[1mhello mutter!\e[22m\e[24m\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should set defaults at both levels" do
|
57
|
+
Mutter.new(:bold).say "hello mutter!", :underline, :yellow
|
58
|
+
out.should == "\e[33m\e[4m\e[1mhello mutter!\e[22m\e[24m\e[39m\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "with custom styles" do
|
62
|
+
it "should work with custom styles" do
|
63
|
+
style = {
|
64
|
+
:alert => {
|
65
|
+
:match => '!!',
|
66
|
+
:style => ['bold', 'red']
|
67
|
+
}
|
68
|
+
}
|
69
|
+
Mutter.new(style).say "alert!", :alert
|
70
|
+
out.should == "\e[31m\e[1malert!\e[22m\e[39m\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should work with shorthand custom styles" do
|
74
|
+
Mutter.new({:bold => '~'}).say "~hello mutter!~"
|
75
|
+
out.should == "\e[1mhello mutter!\e[22m\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should color" do
|
79
|
+
Mutter.new({:cyan => ['<', '>']}).say "<hello mutter!>"
|
80
|
+
out.should == "\e[36mhello mutter!\e[39m\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should mix styles" do
|
84
|
+
Mutter.new({:cyan => '~'}).say "_*hello* ~world~_"
|
85
|
+
out.should == "\e[4m\e[1mhello\e[22m \e[36mworld\e[39m\e[24m\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should color backgrounds" do
|
89
|
+
Mutter.new({:cyan => '~'}).say "~[hello mutter!]~"
|
90
|
+
out.should == "\e[36m\e[7mhello mutter!\e[27m\e[39m\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should work with multiple shorthand styles" do
|
94
|
+
Mutter.new({[:cyan, :underline] => '~'}).say "~hello mutter!~"
|
95
|
+
out.should == "\e[4m\e[36mhello mutter!\e[39m\e[24m\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should load styles from a yaml" do
|
99
|
+
Mutter.new("spec/style").say "{important message!}"
|
100
|
+
out.should == "\e[33m\e[4m\e[1mimportant message!\e[22m\e[24m\e[39m\n"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should be able to call styles as methods" do
|
104
|
+
Mutter.new("spec/style").important "important message!"
|
105
|
+
out.should == "\e[33m\e[4m\e[1mimportant message!\e[22m\e[24m\e[39m\n"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should add and remove active styles" do
|
109
|
+
mut = Mutter.new
|
110
|
+
mut << :bold << :underline << :inverse
|
111
|
+
mut >> :inverse
|
112
|
+
mut.say "hello mutter!"
|
113
|
+
out.should == "\e[4m\e[1mhello mutter!\e[22m\e[24m\n"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should return instances of itself, +- active styles" do
|
117
|
+
mut = Mutter.new
|
118
|
+
mut << :bold << :underline
|
119
|
+
(mut - :bold).say "hello mutter!"
|
120
|
+
out.should == "\e[4mhello mutter!\e[24m\n"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should parse a complex string" do
|
125
|
+
m = Mutter.new({:cyan => ['<','>']})
|
126
|
+
m.say "hello *mutter*, would you _<please be quiet>_ for this <[test]>?"
|
127
|
+
out.should == "hello \e[1mmutter\e[22m, would you \e[4m\e[36mplease be quiet\e[39m\e[24m for this \e[36m\e[7mtest\e[27m\e[39m?\n"
|
128
|
+
end
|
129
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/style.yml
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mutter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- cloudhead
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-02 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: self@cloudhead.net
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- LICENSE
|
29
|
+
- README.md
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- lib/ext.rb
|
33
|
+
- lib/mutter.rb
|
34
|
+
- lib/mutter/indenter.rb
|
35
|
+
- lib/mutter/mutterer.rb
|
36
|
+
- lib/mutter/styles.yml
|
37
|
+
- mutter.gemspec
|
38
|
+
- spec/mutter_spec.rb
|
39
|
+
- spec/spec_helper.rb
|
40
|
+
- spec/style.yml
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/cloudhead/mutter
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --charset=UTF-8
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: mutter
|
65
|
+
rubygems_version: 1.3.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: the tiny CLI library
|
69
|
+
test_files:
|
70
|
+
- spec/mutter_spec.rb
|
71
|
+
- spec/spec_helper.rb
|