cloudhead-mutter 0.1.2 → 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.
- data/README.md +10 -4
- data/VERSION +1 -1
- data/lib/ext.rb +36 -0
- data/lib/mutter/indenter.rb +11 -0
- data/lib/mutter/mutterer.rb +157 -0
- data/lib/{defaults.yml → mutter/styles.yml} +0 -0
- data/lib/mutter.rb +27 -89
- data/mutter.gemspec +6 -3
- data/spec/mutter_spec.rb +5 -0
- data/spec/style.yml +7 -1
- metadata +6 -3
data/README.md
CHANGED
@@ -6,8 +6,7 @@ mutter
|
|
6
6
|
style
|
7
7
|
|
8
8
|
> mutter is the tiny CLI library, with a focus on style.
|
9
|
-
|
10
|
-
use it in your apps to have _gorgeous_ command-line output!
|
9
|
+
> use it in your apps to have _gorgeous_ command-line output!
|
11
10
|
|
12
11
|
usage (command-line output)
|
13
12
|
---------------------------
|
@@ -19,6 +18,7 @@ usage (command-line output)
|
|
19
18
|
mut.say "hello world", :bold # bolds the whole string
|
20
19
|
mut.say "hello [world]", :cyan # inverts 'world', and colors the string cyan
|
21
20
|
mut.print "bonjour!" # alias of `say`
|
21
|
+
mut["hola"] # yet another way to print
|
22
22
|
|
23
23
|
styles
|
24
24
|
------
|
@@ -45,8 +45,9 @@ customization
|
|
45
45
|
}
|
46
46
|
|
47
47
|
mut = Mutter.new(styles)
|
48
|
-
mut.say
|
49
|
-
mut.
|
48
|
+
mut.say "warning, warning!", :warning
|
49
|
+
mut.warning "warning, warning!"
|
50
|
+
mut.say "gosh, we have an !!error!!"
|
50
51
|
|
51
52
|
### quick styles
|
52
53
|
|
@@ -70,3 +71,8 @@ That's it!
|
|
70
71
|
----------
|
71
72
|
|
72
73
|
_have fun_
|
74
|
+
|
75
|
+
Footnote
|
76
|
+
--------
|
77
|
+
|
78
|
+
This code is _highly experimental_, don't try this at home!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
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,157 @@
|
|
1
|
+
module Mutter
|
2
|
+
class Mutterer
|
3
|
+
@stream = STDOUT
|
4
|
+
|
5
|
+
# Initialize the styles, and load the defaults from +defaults.yml+
|
6
|
+
#
|
7
|
+
# @active: currently active styles, which apply to the whole string
|
8
|
+
# @styles: contains all the user + default styles
|
9
|
+
#
|
10
|
+
def initialize obj = {}
|
11
|
+
@active, @styles = [], {}
|
12
|
+
load File.dirname(__FILE__) + "/styles"
|
13
|
+
|
14
|
+
case obj
|
15
|
+
when Hash # A style definition: expand quick-styles and merge with @styles
|
16
|
+
obj = obj.inject({}) do |h, (k, v)|
|
17
|
+
h.merge k =>
|
18
|
+
(v.is_a?(Hash) ? v : { :match => v, :style => [k].flatten })
|
19
|
+
end
|
20
|
+
@styles.merge! obj
|
21
|
+
when Array # An array of styles to be activated
|
22
|
+
@active = obj
|
23
|
+
when Symbol # A single style to be activated
|
24
|
+
self.<< obj
|
25
|
+
when String # The path of a yaml style-sheet
|
26
|
+
load obj
|
27
|
+
else raise ArgumentError
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Create an instance method for each style
|
32
|
+
#
|
33
|
+
@styles.keys.each do |style|
|
34
|
+
(class << self; self end).class_eval do
|
35
|
+
define_method style do |msg|
|
36
|
+
say msg, style
|
37
|
+
end
|
38
|
+
end if style.is_a? Symbol
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Loads styles from a YAML style-sheet,
|
44
|
+
# and converts the keys to symbols
|
45
|
+
#
|
46
|
+
def load styles
|
47
|
+
styles += '.yml' unless styles =~ /\.ya?ml/
|
48
|
+
@defaults = YAML.load_file(styles).inject({}) do |h, (key, value)|
|
49
|
+
value = { :match => value['match'], :style => value['style'] }
|
50
|
+
h.merge key.to_sym => value
|
51
|
+
end
|
52
|
+
@styles.merge! @defaults
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Output to the command-line
|
57
|
+
# we parse the string, but also apply a style on the whole string,
|
58
|
+
#
|
59
|
+
def say obj, *styles
|
60
|
+
stylize(parse(obj), @active + styles).tap do |out|
|
61
|
+
self.write out.gsub(/\e(\d+)\e/, "\e[\\1m") + "\n"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
alias :print say
|
66
|
+
alias :[] say
|
67
|
+
|
68
|
+
#
|
69
|
+
# Write to the out stream, and flush it
|
70
|
+
#
|
71
|
+
def write str
|
72
|
+
self.class.stream.tap do |stream|
|
73
|
+
stream.write str
|
74
|
+
stream.flush
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Utility function, to make a block interruptible
|
80
|
+
#
|
81
|
+
def watch
|
82
|
+
begin
|
83
|
+
yield
|
84
|
+
rescue Interrupt
|
85
|
+
puts
|
86
|
+
exit 0
|
87
|
+
end
|
88
|
+
end
|
89
|
+
alias :oo watch
|
90
|
+
|
91
|
+
#
|
92
|
+
# Add a style to the active styles
|
93
|
+
#
|
94
|
+
def << style
|
95
|
+
@active << style
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# Parse a string to ANSI codes
|
100
|
+
#
|
101
|
+
# if the glyph is a pair, we match [0] as the start
|
102
|
+
# and [1] as the end marker.
|
103
|
+
# the matches are sent to +stylize+
|
104
|
+
#
|
105
|
+
def parse string
|
106
|
+
@styles.inject(string) do |str, (name, options)|
|
107
|
+
glyph, styles = options[:match], options[:style]
|
108
|
+
if glyph.is_a? Array
|
109
|
+
str.gsub(/#{Regexp.escape(glyph.first)}(.+?)
|
110
|
+
#{Regexp.escape(glyph.last)}/x) { stylize $1, styles }
|
111
|
+
else
|
112
|
+
str.gsub(/(#{Regexp.escape(glyph)}+)(.+?)\1/) { stylize $2, styles }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Apply styles to a string
|
119
|
+
#
|
120
|
+
# if the style is a default ANSI style, we add the start
|
121
|
+
# and end sequence to the string.
|
122
|
+
#
|
123
|
+
# if the style is a custom style, we recurse, sending
|
124
|
+
# the list of ANSI styles contained in the custom style.
|
125
|
+
#
|
126
|
+
def stylize string, styles = []
|
127
|
+
[styles].flatten.inject(string) do |str, style|
|
128
|
+
style = style.to_sym
|
129
|
+
if ANSI.include? style
|
130
|
+
open, close = ANSI[style]
|
131
|
+
"#{esc(open)}#{str}#{esc(close || 0)}"
|
132
|
+
else
|
133
|
+
stylize(str, @styles[style][:style])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Escape a string, for later replacement
|
140
|
+
#
|
141
|
+
def esc style
|
142
|
+
"\e#{style}\e"
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Output stream (defaults to STDOUT)
|
147
|
+
# mostly for test purposes
|
148
|
+
#
|
149
|
+
def self.stream
|
150
|
+
@stream
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.stream= io
|
154
|
+
@stream = io
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
File without changes
|
data/lib/mutter.rb
CHANGED
@@ -1,6 +1,26 @@
|
|
1
|
-
|
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 'ext'
|
2
12
|
|
3
13
|
module Mutter
|
14
|
+
#
|
15
|
+
# ANSI color & style codes
|
16
|
+
#
|
17
|
+
# if the value's an array, it
|
18
|
+
# represents [0] is the start code
|
19
|
+
# and [1] is the end code.
|
20
|
+
#
|
21
|
+
# if the value is an int, it represents
|
22
|
+
# the start code, and the end code will be 0
|
23
|
+
#
|
4
24
|
ANSI = {
|
5
25
|
:bold => [1, 22],
|
6
26
|
:underline => [4, 24],
|
@@ -12,100 +32,18 @@ module Mutter
|
|
12
32
|
:cyan => 36, :white => 37
|
13
33
|
}
|
14
34
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def initialize obj = {}
|
19
|
-
@active, @styles = [], {}
|
20
|
-
load File.dirname(__FILE__) + "/defaults"
|
21
|
-
|
22
|
-
case obj
|
23
|
-
when Hash
|
24
|
-
obj = obj.inject({}) do |h, (k, v)|
|
25
|
-
h.merge k =>
|
26
|
-
(v.is_a?(Hash) ? v : { :match => v, :style => [k].flatten })
|
27
|
-
end
|
28
|
-
@styles.merge! obj
|
29
|
-
when Array
|
30
|
-
@active = obj
|
31
|
-
when Symbol
|
32
|
-
self.<< obj
|
33
|
-
when String
|
34
|
-
load obj
|
35
|
-
else raise ArgumentError
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def load styles
|
40
|
-
styles += '.yml' unless styles =~ /\.ya?ml/
|
41
|
-
styles = YAML.load_file(styles).inject({}) do |h, (key, value)|
|
42
|
-
value = { :match => value['match'], :style => value['style'] }
|
43
|
-
h.merge key.to_sym => value
|
44
|
-
end
|
45
|
-
@styles.merge! styles
|
46
|
-
end
|
47
|
-
|
48
|
-
def say str, *styles
|
49
|
-
out = stylize(parse(str), @active + styles)
|
50
|
-
self.class.stream.write out.gsub(/\e(\d+)\e/, "\e[\\1m") + "\n"
|
51
|
-
self.class.stream.flush
|
52
|
-
end
|
53
|
-
alias :print say
|
54
|
-
|
55
|
-
def watch
|
56
|
-
begin
|
57
|
-
yield
|
58
|
-
rescue Interrupt
|
59
|
-
puts
|
60
|
-
exit 0
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def << style
|
65
|
-
@active << style
|
66
|
-
end
|
67
|
-
|
68
|
-
def parse string
|
69
|
-
@styles.inject(string) do |str, (name, options)|
|
70
|
-
glyph, styles = options[:match], options[:style]
|
71
|
-
if glyph.is_a? Array
|
72
|
-
str.gsub(/#{Regexp.escape(glyph.first)}(.+?)
|
73
|
-
#{Regexp.escape(glyph.last)}/x) { stylize $1, styles }
|
74
|
-
else
|
75
|
-
str.gsub(/(#{Regexp.escape(glyph)}+)(.+?)\1/) { stylize $2, styles }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def stylize string, styles = []
|
81
|
-
[styles].flatten.inject(string) do |str, style|
|
82
|
-
style = style.to_sym
|
83
|
-
if ANSI.include? style
|
84
|
-
open, close = ANSI[style]
|
85
|
-
"#{esc(open)}#{str}#{esc(close || 0)}"
|
86
|
-
else
|
87
|
-
stylize(str, @styles[style][:style])
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def esc style
|
93
|
-
"\e#{style}\e"
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.stream
|
97
|
-
@stream
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.stream= io
|
101
|
-
@stream = io
|
102
|
-
end
|
35
|
+
def self.indenter tab
|
36
|
+
Indenter.new tab
|
103
37
|
end
|
104
38
|
|
105
39
|
def self.say *args
|
106
40
|
new.say *args
|
107
41
|
end
|
108
42
|
|
43
|
+
def self.stylize *args
|
44
|
+
new.stylize *args
|
45
|
+
end
|
46
|
+
|
109
47
|
def self.new *args
|
110
48
|
Mutterer.new(*args)
|
111
49
|
end
|
data/mutter.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{mutter}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["cloudhead"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-31}
|
10
10
|
s.email = %q{self@cloudhead.net}
|
11
11
|
s.extra_rdoc_files = [
|
12
12
|
"LICENSE",
|
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
"README.md",
|
20
20
|
"Rakefile",
|
21
21
|
"VERSION",
|
22
|
-
"lib/
|
22
|
+
"lib/ext.rb",
|
23
23
|
"lib/mutter.rb",
|
24
|
+
"lib/mutter/indenter.rb",
|
25
|
+
"lib/mutter/mutterer.rb",
|
26
|
+
"lib/mutter/styles.yml",
|
24
27
|
"mutter.gemspec",
|
25
28
|
"spec/mutter_spec.rb",
|
26
29
|
"spec/spec_helper.rb",
|
data/spec/mutter_spec.rb
CHANGED
@@ -94,6 +94,11 @@ describe Mutter do
|
|
94
94
|
Mutter.new("spec/style").say "{important message!}"
|
95
95
|
out.should == "\e[33m\e[4m\e[1mimportant message!\e[22m\e[24m\e[0m\n"
|
96
96
|
end
|
97
|
+
|
98
|
+
it "should be able to call styles as methods" do
|
99
|
+
Mutter.new("spec/style").important "important message!"
|
100
|
+
out.should == "\e[33m\e[4m\e[1mimportant message!\e[22m\e[24m\e[0m\n"
|
101
|
+
end
|
97
102
|
end
|
98
103
|
|
99
104
|
it "should parse a complex string" do
|
data/spec/style.yml
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudhead-mutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cloudhead
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-31 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -29,8 +29,11 @@ files:
|
|
29
29
|
- README.md
|
30
30
|
- Rakefile
|
31
31
|
- VERSION
|
32
|
-
- lib/
|
32
|
+
- lib/ext.rb
|
33
33
|
- lib/mutter.rb
|
34
|
+
- lib/mutter/indenter.rb
|
35
|
+
- lib/mutter/mutterer.rb
|
36
|
+
- lib/mutter/styles.yml
|
34
37
|
- mutter.gemspec
|
35
38
|
- spec/mutter_spec.rb
|
36
39
|
- spec/spec_helper.rb
|