lipsttyck 0.1.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/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: []
|