lipsttyck 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/lipsttyck.rb +488 -0
- metadata +44 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 355f25e88c6e6339f99cd72b9e8e0f92daba450c
|
4
|
+
data.tar.gz: 327f0af5863376af7712c857bc22be09f46b6361
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d55db29fab201556d7239d5497cdfb6de72a915b97cb0268e9c8d0eaaabfe10be24c681afbc4ea72d2ff1ea177b8f161c918903d8f6600fca87bdcfc872e6988
|
7
|
+
data.tar.gz: 0c2ee3928f776d146e61a5b5cb31384734b306902c13f274b2e42832836873f4b16a1f12e3212b7047abeb2e2ce9afe28665b5f6038d1067b3c7fa54265a057c
|
data/lib/lipsttyck.rb
ADDED
@@ -0,0 +1,488 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "pty"
|
3
|
+
|
4
|
+
##
|
5
|
+
# LipsTTYck provides a collection of utilities for formatting shell output. It
|
6
|
+
# parses a simple markup syntax for adding color formatting, right-justification
|
7
|
+
# of text, headers, and horizontal dividers.
|
8
|
+
#
|
9
|
+
# @author Nick Williams
|
10
|
+
# @version 0.1.0
|
11
|
+
#
|
12
|
+
class LipsTTYck
|
13
|
+
# Logging/Output Levels
|
14
|
+
LOG_LEVEL_NEVER = 0
|
15
|
+
LOG_LEVEL_FAILURE = 1
|
16
|
+
LOG_LEVEL_ALWAYS = 2
|
17
|
+
|
18
|
+
# Templates
|
19
|
+
@@templatePad = "\n\n"
|
20
|
+
@@templatePrefix = ""
|
21
|
+
@@templatePadding = " "
|
22
|
+
@@templateIndentOn = "#@@templatePrefix#@@templatePadding"
|
23
|
+
@@templateIndentOff = ""
|
24
|
+
@@templateH1 = "#@@templatePrefix@gray(================================================================================)"
|
25
|
+
@@templateH2 = "#@@templatePrefix@gray(--------------------------------------------------------------------------------)"
|
26
|
+
@@templateDiv = "#@@templateH2"
|
27
|
+
@@templateBlockquote = "| "
|
28
|
+
@@templateEnd = "#@@templateH2"
|
29
|
+
@@templateSuccess = "[ @green(OK) ]" # "@green(✓)", "@green(✔)"︎
|
30
|
+
@@templateFailure = "[ @red(FAIL) ]" # "@red(✗)", "@red(✘)"
|
31
|
+
@@templateSkip = "[ @blue(SKIP) ]" # "@blue(~)", "@blue(⋯)"
|
32
|
+
@@templateColorPrompt = "@blue"
|
33
|
+
@@templateColorStdOut = "@gray"
|
34
|
+
@@templateColorStdErr = "@red"
|
35
|
+
|
36
|
+
##
|
37
|
+
# Initializes a new LipsTTYck instance.
|
38
|
+
#
|
39
|
+
# @param [Hash] config optional configuration settings with which to initialize (overriding any defaults)
|
40
|
+
#
|
41
|
+
# @return [LipsTTYck]
|
42
|
+
#
|
43
|
+
def initialize(config = {})
|
44
|
+
# Config
|
45
|
+
@config = {
|
46
|
+
"margin" => 80,
|
47
|
+
"marginTemplateOverrides" => true,
|
48
|
+
"showStdOut" => LOG_LEVEL_NEVER,
|
49
|
+
"showStdErr" => LOG_LEVEL_FAILURE
|
50
|
+
}
|
51
|
+
|
52
|
+
@config.merge!(config)
|
53
|
+
|
54
|
+
# Flags
|
55
|
+
@entryQueued = false
|
56
|
+
|
57
|
+
# Caches
|
58
|
+
@cacheLast = ""
|
59
|
+
@cacheLine = ""
|
60
|
+
|
61
|
+
# Margin-Sensitive Template Overrides
|
62
|
+
if(@config['marginTemplateOverrides'])
|
63
|
+
# H1 Override
|
64
|
+
@@templateH1 = "#@@templatePrefix@gray("
|
65
|
+
|
66
|
+
@config['margin'].times do
|
67
|
+
@@templateH1 += "="
|
68
|
+
end
|
69
|
+
|
70
|
+
@@templateH1 += ")"
|
71
|
+
|
72
|
+
# H2 Override
|
73
|
+
@@templateH2 = "#@@templatePrefix@gray("
|
74
|
+
|
75
|
+
@config['margin'].times do
|
76
|
+
@@templateH2 += "-"
|
77
|
+
end
|
78
|
+
|
79
|
+
@@templateH2 += ")"
|
80
|
+
|
81
|
+
# DIV Override
|
82
|
+
@@templateDiv = "#@@templateH2"
|
83
|
+
|
84
|
+
# END Override
|
85
|
+
@@templateEnd = "#@@templateH2"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Outputs the specified text, processing any detected markup.
|
91
|
+
#
|
92
|
+
# @param [String] text the text to be displayed
|
93
|
+
# @param [Boolean] trailingNewline whether or not to automatically append a trailing newline character
|
94
|
+
# @param [Boolean] autoIndent whether or not to automatically apply indentation
|
95
|
+
# @param [Boolean] rightJustified whether or not to right-align the text according to the configured margin width
|
96
|
+
#
|
97
|
+
# @return void
|
98
|
+
#
|
99
|
+
def out(text, trailingNewline = true, autoIndent = true, rightJustified = false)
|
100
|
+
formatted = "#{text}"
|
101
|
+
unformatted = "#{text}"
|
102
|
+
templateIndent = autoIndent ? @@templateIndentOn : @@templateIndentOff
|
103
|
+
line = "#@cacheLine"
|
104
|
+
|
105
|
+
# Apply Indentation
|
106
|
+
formatted.gsub!(/\n/m, "\n#{templateIndent}")
|
107
|
+
|
108
|
+
# Apply Markup Formatting
|
109
|
+
case formatted
|
110
|
+
when /@H1(?: (.*))?/im
|
111
|
+
formatted = "#@@templateH1\n#{templateIndent}@green(#$1)\n#@@templateH1"
|
112
|
+
|
113
|
+
# Handle Queued Entry
|
114
|
+
if @entryQueued
|
115
|
+
formatted = "#@@templatePad#{formatted}"
|
116
|
+
@entryQueued = false
|
117
|
+
end
|
118
|
+
|
119
|
+
when /@H2(?: (.*))?/im
|
120
|
+
stripped = $1
|
121
|
+
|
122
|
+
if @cacheLast =~ /^@H[12](.*)/i
|
123
|
+
formatted="#{templateIndent}@yellow(#{stripped})\n#@@templateH2"
|
124
|
+
else
|
125
|
+
formatted="#@@templateH2\n#{templateIndent}@yellow(#{stripped})\n#@@templateH2"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Handle Queued Entry
|
129
|
+
if @entryQueued
|
130
|
+
formatted = "#@@templatePad#{formatted}"
|
131
|
+
@entryQueued = false
|
132
|
+
end
|
133
|
+
|
134
|
+
when /@DIV(?: (.*))?/im
|
135
|
+
if $1
|
136
|
+
formatted = "#@@templateDiv\n#$1"
|
137
|
+
else
|
138
|
+
formatted = "#@@templateDiv"
|
139
|
+
end
|
140
|
+
|
141
|
+
when /@BLOCKQUOTE\((.*)(?<!\\)\)/im
|
142
|
+
formatted = "#$1".gsub(/\n/m, "\n#@@templateBlockquote")
|
143
|
+
|
144
|
+
when /@SUCCESS(?: (.*))?/im
|
145
|
+
formatted = "#@@templateSuccess#@@templatePadding"
|
146
|
+
|
147
|
+
when /@FAILURE(?: (.*))?/im
|
148
|
+
formatted = "#@@templateFailure#@@templatePadding"
|
149
|
+
|
150
|
+
when /@SKIP(?: (.*))?/im
|
151
|
+
formatted = "#@@templateSkip#@@templatePadding"
|
152
|
+
|
153
|
+
when /@ENTRY(?: (.*))?/im
|
154
|
+
@entryQueued = true
|
155
|
+
return
|
156
|
+
|
157
|
+
when /@EXIT(?: (.*))?/im
|
158
|
+
# Handle Queued Entry
|
159
|
+
if @entryQueued
|
160
|
+
@entryQueued = false
|
161
|
+
else
|
162
|
+
# Handle Exit w/ Heading
|
163
|
+
if @cacheLast =~ /^@H[12].*/im
|
164
|
+
# Handle Double Newline (After Heading)
|
165
|
+
if @@templatePad[0,2] == "\n"
|
166
|
+
formatted = @@templatePad[2,-1]
|
167
|
+
else
|
168
|
+
formatted = "#@@templatePad"
|
169
|
+
end
|
170
|
+
else
|
171
|
+
# Handle Exit w/ Text
|
172
|
+
if formatted.length > 5
|
173
|
+
formatted = "#{templateIndent}" << formatted[6..-1] << "\n#@@templateEnd#@@templatePad"
|
174
|
+
else
|
175
|
+
formatted = "#@@templateEnd#@@templatePad"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
@entryQueued = false
|
180
|
+
end
|
181
|
+
else
|
182
|
+
formatted = "#{templateIndent}" + formatted.gsub(/\\@/, "@")
|
183
|
+
|
184
|
+
# Handle Queued Entry
|
185
|
+
if @entryQueued
|
186
|
+
formatted = "#@@templatePad#@@templateDiv\n#{formatted}"
|
187
|
+
@entryQueued = false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
stripped = "#{formatted}"
|
192
|
+
|
193
|
+
# Apply Color Formatting
|
194
|
+
if formatted.include? "@"
|
195
|
+
stripped = formatted.gsub(/(?<!\\)@[A-Za-z0-9\-_]*\((.*?)(?<!\\)\)/, '\1')
|
196
|
+
|
197
|
+
formatted = formatted.gsub(/(?<!\\)@none\((.*?)\)/im, "\033[0m" << '\1' << "\033[0m")
|
198
|
+
.gsub(/(?<!\\)@black\((.*?)(?<!\\)\)/im, "\033[0;30m" << '\1' << "\033[0m")
|
199
|
+
.gsub(/(?<!\\)@white\((.*?)(?<!\\)\)/im, "\033[1;37m" << '\1' << "\033[0m")
|
200
|
+
.gsub(/(?<!\\)@blue\((.*?)(?<!\\)\)/im, "\033[0;34m" << '\1' << "\033[0m")
|
201
|
+
.gsub(/(?<!\\)@blue_lt\((.*?)(?<!\\)\)/im, "\033[1;34m" << '\1' << "\033[0m")
|
202
|
+
.gsub(/(?<!\\)@green\((.*?)(?<!\\)\)/im, "\033[0;32m" << '\1' << "\033[0m")
|
203
|
+
.gsub(/(?<!\\)@green_lt\((.*?)(?<!\\)\)/im, "\033[1;32m" << '\1' << "\033[0m")
|
204
|
+
.gsub(/(?<!\\)@cyan\((.*?)(?<!\\)\)/im, "\033[0;36m" << '\1' << "\033[0m")
|
205
|
+
.gsub(/(?<!\\)@cyan_lt\((.*?)(?<!\\)\)/im, "\033[1;36m" << '\1' << "\033[0m")
|
206
|
+
.gsub(/(?<!\\)@red\((.*?)(?<!\\)\)/im, "\033[0;31m" << '\1' << "\033[0m")
|
207
|
+
.gsub(/(?<!\\)@red_lt\((.*?)(?<!\\)\)/im, "\033[1;31m" << '\1' << "\033[0m")
|
208
|
+
.gsub(/(?<!\\)@purple\((.*?)(?<!\\)\)/im, "\033[0;35m" << '\1' << "\033[0m")
|
209
|
+
.gsub(/(?<!\\)@purple_lt\((.*?)(?<!\\)\)/im, "\033[1;35m" << '\1' << "\033[0m")
|
210
|
+
.gsub(/(?<!\\)@yellow\((.*?)(?<!\\)\)/im, "\033[0;33m" << '\1' << "\033[0m")
|
211
|
+
.gsub(/(?<!\\)@yellow_lt\((.*?)(?<!\\)\)/im, "\033[1;33m" << '\1' << "\033[0m")
|
212
|
+
.gsub(/(?<!\\)@gray\((.*?)(?<!\\)\)/im, "\033[1;30m" << '\1' << "\033[0m")
|
213
|
+
.gsub(/(?<!\\)@gray_lt\((.*?)(?<!\\)\)/im, "\033[0;37m" << '\1' << "\033[0m")
|
214
|
+
end
|
215
|
+
|
216
|
+
# Strip Escaping Slashes
|
217
|
+
escapedPattern = /\\([@\(\)])/im
|
218
|
+
|
219
|
+
stripped.gsub!(escapedPattern, "\\1")
|
220
|
+
formatted.gsub!(escapedPattern, "\\1")
|
221
|
+
|
222
|
+
# Apply Right-Justification
|
223
|
+
if rightJustified
|
224
|
+
paddingSize = (@config['margin'] - line.length) - stripped.length
|
225
|
+
padding = "%#{paddingSize}s" % ""
|
226
|
+
|
227
|
+
formatted = "#{padding}#{formatted}"
|
228
|
+
end
|
229
|
+
|
230
|
+
# Apply Trailing Newline
|
231
|
+
if trailingNewline
|
232
|
+
formatted = "#{formatted}\n"
|
233
|
+
end
|
234
|
+
|
235
|
+
# Output Formatted String
|
236
|
+
print "#{formatted}"
|
237
|
+
|
238
|
+
# Cache Unformatted Version
|
239
|
+
@cacheLast = unformatted
|
240
|
+
|
241
|
+
# Cache Current Line
|
242
|
+
if !trailingNewline
|
243
|
+
@cacheLine = @cacheLine << stripped
|
244
|
+
else
|
245
|
+
@cacheLine = ""
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
##
|
250
|
+
# Prompts for input, first outputting the specified text.
|
251
|
+
#
|
252
|
+
# @param [String] label the label to be used when prompting
|
253
|
+
# @param [mixed] value the existing value if available
|
254
|
+
# @param [mixed] default a default fallback value if the response is blank
|
255
|
+
# @param [Boolean] verbose whether or not to always prompt, regardless of a passed value
|
256
|
+
#
|
257
|
+
# @return [mixed] the result of the prompt
|
258
|
+
#
|
259
|
+
def in(label, value = nil, default = nil, verbose = false)
|
260
|
+
# Don't continue if verbosity is off and value is already set.
|
261
|
+
if !verbose && !self.class.unassigned(value)
|
262
|
+
return
|
263
|
+
end
|
264
|
+
|
265
|
+
# Default value, falls back to existing value if possible.
|
266
|
+
if default.nil? && !self.class.unassigned(value)
|
267
|
+
default = value
|
268
|
+
end
|
269
|
+
|
270
|
+
# Prompt for input.
|
271
|
+
prompt = "#{label}"
|
272
|
+
|
273
|
+
if default.nil?
|
274
|
+
prompt += ": "
|
275
|
+
else
|
276
|
+
prompt += " \\\(#{default}\\\): "
|
277
|
+
end
|
278
|
+
|
279
|
+
out("#@@templateColorPrompt(#{prompt})", false)
|
280
|
+
|
281
|
+
value = $stdin.gets.chomp
|
282
|
+
|
283
|
+
# Fall back default value if input is empty.
|
284
|
+
if self.class.unassigned(value)
|
285
|
+
value = default
|
286
|
+
end
|
287
|
+
|
288
|
+
return value
|
289
|
+
end
|
290
|
+
|
291
|
+
##
|
292
|
+
# Prompts for a boolean response (y/n).
|
293
|
+
#
|
294
|
+
# @param [String] label the label to be used when prompting
|
295
|
+
# @param [Boolean] value the existing value if available
|
296
|
+
# @param [Boolean] default a default fallback value if the response is blank
|
297
|
+
# @param [Boolean] verbose whether or not to always prompt, regardless of a passed value
|
298
|
+
#
|
299
|
+
# @return [Boolean] the result of the confirmation prompt
|
300
|
+
#
|
301
|
+
def confirm(label, value = nil, default = true, verbose = false)
|
302
|
+
# Don't continue if verbosity is off and value is already set.
|
303
|
+
if !verbose && !self.class.unassigned(value)
|
304
|
+
return
|
305
|
+
end
|
306
|
+
|
307
|
+
# Default value, falls back to existing value if possible.
|
308
|
+
if default.nil? && !self.class.unassigned(value)
|
309
|
+
default = value
|
310
|
+
end
|
311
|
+
|
312
|
+
# Prompt for input.
|
313
|
+
prompt = "#{label}"
|
314
|
+
|
315
|
+
if default
|
316
|
+
prompt += " \\\(Y/n\\\): "
|
317
|
+
else
|
318
|
+
prompt += " \\\(y/N\\\): "
|
319
|
+
end
|
320
|
+
|
321
|
+
out("#@@templateColorPrompt(#{prompt})", false)
|
322
|
+
|
323
|
+
response = $stdin.gets.chomp
|
324
|
+
|
325
|
+
# Fall back default value if input is empty.
|
326
|
+
if self.class.unassigned(response)
|
327
|
+
value = default
|
328
|
+
else
|
329
|
+
if response.casecmp("y") == 0
|
330
|
+
value = true
|
331
|
+
elsif response.casecmp("n") == 0
|
332
|
+
value = false
|
333
|
+
else
|
334
|
+
out "Invalid response \"#{response}\""
|
335
|
+
value = confirm(label, value, default, verbose)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
return value
|
340
|
+
end
|
341
|
+
|
342
|
+
##
|
343
|
+
# Attempts to execute the specified shell command(s), capturing STDIN and
|
344
|
+
# STDOUT for optional output to the user.
|
345
|
+
#
|
346
|
+
# @param [String] label a label to use when prompting for input
|
347
|
+
# @param [Array] commands one or more commands to be executed
|
348
|
+
#
|
349
|
+
# @return [Boolean] whetehr or not all commands were executed successfully
|
350
|
+
#
|
351
|
+
def attempt(label, commands)
|
352
|
+
# Setup
|
353
|
+
commandOutputLogs = [];
|
354
|
+
failed = false
|
355
|
+
|
356
|
+
# Convert single command to an array.
|
357
|
+
if !commands.kind_of?(Array)
|
358
|
+
commands = [commands]
|
359
|
+
end
|
360
|
+
|
361
|
+
# Output label.
|
362
|
+
self.out(label, false)
|
363
|
+
|
364
|
+
# Execute each command.
|
365
|
+
commands.each do|command|
|
366
|
+
# Output progress indicator for current command.
|
367
|
+
self.out(".", false, false)
|
368
|
+
|
369
|
+
Open3.popen3(command) do |stdin, stdout, stderr, waitThread|
|
370
|
+
commandOutputLogs << {
|
371
|
+
:stdout => stdout.eof? ? nil : stdout.read,
|
372
|
+
:stderr => stderr.eof? ? nil : stderr.read
|
373
|
+
}
|
374
|
+
|
375
|
+
if waitThread.value.to_i > 0
|
376
|
+
failed = true
|
377
|
+
break
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
# Display the result of the attempted commands.
|
383
|
+
if failed
|
384
|
+
self.out("@FAILURE", true, false, true)
|
385
|
+
else
|
386
|
+
self.out("@SUCCESS", true, false, true)
|
387
|
+
end
|
388
|
+
|
389
|
+
# Output I/O streams according to config.
|
390
|
+
if @config['showStdOut'] == LOG_LEVEL_ALWAYS || failed && @config['showStdOut'] == LOG_LEVEL_FAILURE || @config['showStdErr'] == LOG_LEVEL_ALWAYS || failed && @config['showStdErr'] == LOG_LEVEL_FAILURE
|
391
|
+
lastIndex = commandOutputLogs.length - 1
|
392
|
+
|
393
|
+
self.out("")
|
394
|
+
|
395
|
+
commandOutputLogs.each_index do |i|
|
396
|
+
# STDOUT
|
397
|
+
if (@config['showStdOut'] == LOG_LEVEL_ALWAYS) || (failed && @config['showStdOut'] == LOG_LEVEL_FAILURE && i == lastIndex)
|
398
|
+
blockquote(commandOutputLogs[i][:stdout], @@templateColorStdOut)
|
399
|
+
end
|
400
|
+
|
401
|
+
# STDERR
|
402
|
+
if (@config['showStdErr']) == LOG_LEVEL_ALWAYS || (failed && @config['showStdErr'] == LOG_LEVEL_FAILURE && i == lastIndex)
|
403
|
+
blockquote(commandOutputLogs[i][:stderr], @@templateColorStdErr)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
return !failed
|
409
|
+
end
|
410
|
+
|
411
|
+
##
|
412
|
+
# Executes the specified command, passing any output to the respective
|
413
|
+
# output streams.
|
414
|
+
#
|
415
|
+
# @param [Array] commands one or more commands to be executed
|
416
|
+
#
|
417
|
+
# @return void
|
418
|
+
#
|
419
|
+
def passthru(commands, colorStdOut = "@gray", colorStdErr = "@red", colorStdIn = "@blue")
|
420
|
+
# Convert single command to an array.
|
421
|
+
if !commands.kind_of?(Array)
|
422
|
+
commands = [commands]
|
423
|
+
end
|
424
|
+
|
425
|
+
commands.each do |command|
|
426
|
+
PTY.spawn(command) do |stdout, stdin, pid|
|
427
|
+
# self.out("#{colorStdIn}(> " + self.class.escape(command) + ")", true, false)
|
428
|
+
stdout.each_line { |line| self.out("#{colorStdOut}(| " + self.class.escape(line.gsub!(/\n/m, "")) + ")") }
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
##
|
434
|
+
# Outputs an indented block of text.
|
435
|
+
#
|
436
|
+
# @param [String] lines the text to be displayed
|
437
|
+
# @param [String] prefix optional string to prepend to each line
|
438
|
+
# @param [String] postfix optional string to append to each line
|
439
|
+
#
|
440
|
+
# @return void
|
441
|
+
#
|
442
|
+
def blockquote(lines, color = "@gray")
|
443
|
+
if lines
|
444
|
+
# Escape special characters.
|
445
|
+
lines = self.class.escape(lines)
|
446
|
+
|
447
|
+
lines.each_line do |line|
|
448
|
+
self.out("#{color}(| " + line.gsub!(/(\n)$/, "") + ")")
|
449
|
+
end
|
450
|
+
|
451
|
+
self.out("")
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
private
|
456
|
+
|
457
|
+
##
|
458
|
+
# Checks if the specified variable is empty or nil.
|
459
|
+
#
|
460
|
+
# @param [mixed] the value to be checked
|
461
|
+
#
|
462
|
+
# @return [Boolean] whether or not the value should be considered unassigned
|
463
|
+
#
|
464
|
+
def self.unassigned(var)
|
465
|
+
result = false
|
466
|
+
|
467
|
+
result |= ((var.respond_to? :empty?) && var.empty?)
|
468
|
+
result |= ((var.respond_to? :nil?) && var.nil?)
|
469
|
+
|
470
|
+
return result
|
471
|
+
end
|
472
|
+
|
473
|
+
##
|
474
|
+
# Escapes all special characters otherwise interpreted as formatting markup.
|
475
|
+
#
|
476
|
+
# @param [String] text the text to be escaped
|
477
|
+
#
|
478
|
+
# @return [String] the escaped text
|
479
|
+
#
|
480
|
+
def self.escape(text)
|
481
|
+
# Escape special characters.
|
482
|
+
text.gsub!(/@/, "\\@")
|
483
|
+
text.gsub!(/\(/, "\\(")
|
484
|
+
text.gsub!(/\)/, "\\)")
|
485
|
+
|
486
|
+
return text
|
487
|
+
end
|
488
|
+
end
|
metadata
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lipsttyck
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A library for formatting terminal output using a simplified markup.
|
14
|
+
email: projects.lipsttyck@nickawilliams.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/lipsttyck.rb
|
20
|
+
homepage: https://github.com/RogWilco/lipsttyck
|
21
|
+
licenses:
|
22
|
+
- BSD-3-Clause
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubyforge_project:
|
40
|
+
rubygems_version: 2.0.6
|
41
|
+
signing_key:
|
42
|
+
specification_version: 4
|
43
|
+
summary: A library for formatting terminal output.
|
44
|
+
test_files: []
|