pipetext 0.2.7 → 0.2.8

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.
@@ -1,1230 +1,12 @@
1
- # frozen_string_literal: true
2
-
3
- module PipeText
4
-
5
- public
6
-
7
- def pipetext_init(box_mode=true, ampersand_mode=false)
8
- attributes = {
9
- 'pipe' => false, # Pipe already been found?
10
- 'repeat_pattern' => false, # Used by |<#>~repeat pattern~
11
- 'pattern' => String.new, # Used by |<#>~repeat pattern~ to capture
12
- 'escape' => false, # Has an escape \ already been found in front of this character?
13
- 'ampersand' => false, # Has an ampersand already been found in front of this character?
14
- 'ampersand_mode' => ampersand_mode, # Do we even process ampersands for background colors?
15
- 'blink' => false, # Is blink turned on?
16
- 'bold' => false,
17
- 'crossed_out' => false,
18
- 'faint' => false,
19
- 'found' => false, # At the end -- did we find a match?
20
- 'italic' => false,
21
- 'inverse' => false,
22
- 'underline' => false,
23
- 'box' => -1, # Default to |O (no boxes)
24
- 'box_mode' => box_mode,
25
- 'num' => 0, # Number of times to repeat pattern
26
- 'end_capture' => false, # Used to capture the end column number
27
- 'end' => 0, # Number which current denotes the end of the column
28
- 'position' => 0, # Number which current position in the column
29
- 'center_capture' => false, # Used to capture text for centering
30
- 'center' => String.new, # Text to be centered
31
- 'variable_capture' => false, # Used to capture a variable for update or to display
32
- 'variable' => String.new, # Variable captured
33
- 'variables' => Hash.new, # Stores all captured variables
34
- 'emoji_capture' => false, # Used to capture emoji description or bell/move to position
35
- 'emoji' => String.new, # Used to capture emoji description or bell/move to position
36
- 'unicode_capture' => 0, # Used to capture Unicode using 6 character UTF-16 hex format
37
- 'unicode' => String.new,
38
- 'palette_capture' => 0, # Used to capture 8-bit color using 2 character hex format
39
- 'p' => String.new, # |p00 to |pFF
40
- 'color_capture' => 0, # Used to capture RGB color using #RRGGBB format
41
- 'r' => String.new,
42
- 'g' => String.new,
43
- 'b' => String.new,
44
- 'fg' => String.new, # Needed to restore after background change
45
- 'bg' => String.new, # Needed to restore after foreground change
46
- 'shell_prompt' => false # Used to add \[ and \] around non-printables for prompts
47
- }
48
- attributes['variables']['height'] = `tput lines`.chomp
49
- attributes['variables']['width'] = `tput cols`.chomp
50
- return attributes
51
- end
52
-
53
- def pipe(text, attributes)
54
- new_text = String.new
55
- text.chars.each do |character|
56
- process_character(character, new_text, attributes)
57
- if(new_text =~ /.*\n(.*)$/m)
58
- attributes['position'] = printable_length($1)
59
- else
60
- attributes['position'] += printable_length(new_text)
61
- end
62
- end
63
- # Clean up in case we've captured something we didn't process yet
64
- if(attributes['color_capture'] > 0)
65
- emit_color(new_text, attributes)
66
- elsif(attributes['palette_capture'] > 0)
67
- emit_palette_color(new_text, attributes)
68
- elsif(attributes['unicode_capture'] > 0)
69
- emit_unicode(new_text, attributes)
70
- elsif(attributes['emoji_capture'] == true)
71
- new_text << "|[" + attributes['emoji']
72
- elsif(attributes['center_capture'] == true)
73
- new_text << "|{" + attributes['center']
74
- elsif(attributes['variable_capture'] == true)
75
- new_text << "|(" + attributes['variable']
76
- end
77
- return new_text
78
- end
79
-
80
- def pipetext(text, box_mode=true, ampersand_mode=false)
81
- pipe(text, pipetext_init(box_mode, ampersand_mode))
82
- end
83
-
84
- # Immediate output to screen, no string buffer
85
- def fastpipe(text, attributes)
86
- new_text = String.new
87
- text.chars.each do |character|
88
- process_character(character, new_text, attributes)
89
- if(new_text != "")
90
- print(new_text)
91
- if(new_text =~ /\n(.*)$/)
92
- attributes['position'] = printable_length($1)
93
- else
94
- attributes['position'] += printable_length(new_text)
95
- end
96
- new_text = String.new
97
- end
98
- end
99
- # Clean up in case we've captured something we didn't process yet
100
- if(attributes['color_capture'] > 0)
101
- emit_color(new_text, attributes)
102
- elsif(attributes['palette_capture'] > 0)
103
- emit_palette_color(new_text, attributes)
104
- elsif(attributes['unicode_capture'] > 0)
105
- emit_unicode(new_text, attributes)
106
- elsif(attributes['emoji_capture'] == true)
107
- new_text << "|[" + attributes['emoji']
108
- elsif(attributes['center_capture'] == true)
109
- new_text << "|{" + attributes['center']
110
- elsif(attributes['variable_capture'] == true)
111
- new_text << "|(" + attributes['variable']
112
- end
113
- print(new_text)
114
- end
115
-
116
- def fastpipetext(text, box_mode=true, ampersand_mode=false)
117
- fastpipe(text, pipetext_init(box_mode, ampersand_mode))
118
- end
119
-
120
- def write(text, box_mode=true, ampersand_mode=false)
121
- fastpipetext(text, box_mode, ampersand_mode)
122
- end
123
-
124
- # Defaults to using & for background colors
125
- def paint(text, box_mode=true, ampersand_mode=true)
126
- fastpipetext(text, box_mode, ampersand_mode)
127
- end
128
-
129
- def ignored_character(character, ignored_characters)
130
- ignored_characters.chars.each do |ignored|
131
- if(character == ignored)
132
- return true
133
- end
134
- end
135
- return false
136
- end
137
-
138
- # Match abbreviated text descriptions for emojis by default ignore case and punctuation
139
- # Allows for 'space anchoring' so you can use |[smi f w he e] as an abbreviation for
140
- # |[smiling face with heart-eyes]
141
- def abbreviated_match(input, match, case_match=false, ignored_characters=",.':-")
142
- if(!input || !match)
143
- return 0
144
- end
145
- count = 0
146
- offset = 0
147
- input.chars.each_with_index do |character, index|
148
- while(ignored_character(match[index + offset], ignored_characters))
149
- offset += 1
150
- end
151
- if(character == match[index + offset].chr)
152
- count += 1
153
- elsif(case_match == false && character.downcase == match[index + offset].chr.downcase)
154
- count += 1
155
- elsif(character == ' ' && match[index + offset..-1] =~ / /)
156
- count += 1
157
- while(match[index + offset].chr != character)
158
- offset += 1
159
- end
160
- else
161
- count = 0
162
- offset = 0
163
- break
164
- end
165
- end
166
- return count + offset
167
- end
168
-
169
- # This is not entirely accurate because of emojis, which we assume are 2 characters
170
- def printable_length(string)
171
- if(string == "")
172
- return 0
173
- end
174
- length = 0
175
- escape = false
176
- wide = false
177
- wide_count = 0
178
- string.chars.each do |character|
179
- if(character[0].ord == 27)
180
- escape = true
181
- elsif(character[0].ord == 226 && wide == false)
182
- wide = true
183
- elsif(character[0].ord == 240 && wide == false)
184
- wide = true
185
- elsif(character[0].ord >= 32)
186
- if(escape == true && character[0].ord == 109)
187
- escape = false
188
- elsif(character[0].ord > 9600) # ~ Emoji / Unicode - double wide characters start
189
- length += 2
190
- elsif(escape == false && wide == false)
191
- length += 1
192
- elsif(wide == true)
193
- wide_count += 1
194
- end
195
- if(wide == true && wide_count >= 2)
196
- if(character[0].ord == 147)
197
- length += 1
198
- else
199
- length += 1
200
- wide = false
201
- wide_count = 0
202
- end
203
- end
204
- end
205
- end
206
- if(wide == true && wide_count > 0)
207
- length += 1
208
- end
209
- return length
210
- end
211
-
212
- private
213
-
214
- def process_character(character, new_text, attributes)
215
- if(attributes['repeat_pattern'] == false)
216
- # Will still need to process character, first process incorrect formats
217
- if(attributes['color_capture'] > 0 && character !~ /[0-9,A-F,a-f]/)
218
- emit_color(new_text, attributes)
219
- elsif(attributes['palette_capture'] > 0 && character !~ /[0-9,A-F,a-f]/)
220
- emit_palette_color(new_text, attributes)
221
- elsif(attributes['unicode_capture'] > 0 && character !~ /[0-9,A-F,a-f,+]/ ||
222
- (attributes['unicode_capture'] != 1 && character == '+'))
223
- emit_unicode(new_text, attributes)
224
- end
225
- end
226
- if(attributes['end_capture'] == true && character !~ /[0-9]/)
227
- attributes['end'] = attributes['num']
228
- attributes['num'] = 0
229
- attributes['end_capture'] = false
230
- end
231
- if(attributes['end_capture'] == true && character =~ /[0-9]/)
232
- if(character == '0') # |10+
233
- if(attributes['num'] > 0)
234
- attributes['num'] *= 10
235
- end
236
- elsif(character >= '1' && character <= '9') # |1+ through |9+
237
- if(attributes['num'] > 0)
238
- attributes['num'] *= 10
239
- end
240
- attributes['num'] += character.to_i
241
- end
242
- elsif(character == ')' && attributes['variable_capture'] == true && attributes['escape'] == false)
243
- if(attributes['variable'] =~ /=/ && attributes['variable'][0] != '#') # Update
244
- update_variable(attributes)
245
- else # Display
246
- emit_variable(new_text, attributes)
247
- end
248
- elsif(attributes['variable_capture'] == true)
249
- if(character == '\\')
250
- attributes['escape'] = true
251
- else
252
- if(attributes['escape'] == true)
253
- attributes['variable'] << "\\#{character}"
254
- attributes['escape'] = false
255
- else
256
- attributes['variable'] << character
257
- end
258
- end
259
- elsif(attributes['center_capture'] == true)
260
- if(character == '\\')
261
- attributes['escape'] = true
262
- else
263
- if(attributes['escape'] == true)
264
- attributes['center'] << "\\#{character}"
265
- attributes['escape'] = false
266
- elsif(character == '}')
267
- emit_center(new_text, attributes)
268
- else
269
- attributes['center'] << character
270
- end
271
- end
272
- elsif(attributes['emoji_capture'] == true)
273
- if(character == ']')
274
- if(attributes['emoji'] =~ /bell/)
275
- new_text << "\a"
276
- attributes['emoji'] = String.new
277
- attributes['emoji_capture'] = false
278
- elsif(attributes['emoji'] =~ /^([0-9]*)[,;]([0-9]*)$/)
279
- if(attributes['shell_prompt'] == true)
280
- new_text << "\\[\e[#{$1};#{$2}H\\]"
281
- else
282
- new_text << "\e[#{$1};#{$2}H"
283
- end
284
- attributes['emoji'] = String.new
285
- attributes['emoji_capture'] = false
286
- elsif(attributes['emoji'] =~ /^([0-9]*)s$/i) # Sleep in seconds
287
- attributes['emoji'] = String.new
288
- attributes['emoji_capture'] = false
289
- sleep($1.to_i)
290
- elsif(attributes['emoji'] =~ /^([0-9]*)ms$/i) # Sleep in milliseconds
291
- attributes['emoji'] = String.new
292
- attributes['emoji_capture'] = false
293
- sleep($1.to_i / 1000.0)
294
- else
295
- emit_emoji(new_text, attributes)
296
- end
297
- else
298
- attributes['emoji'] << character
299
- end
300
- elsif(character == '|' && attributes['repeat_pattern'] == false)
301
- process_pipe(character, new_text, attributes)
302
- elsif(character == '~' && attributes['pipe'] == true &&
303
- attributes['num'] > 0 && attributes['escape'] == false)
304
- process_repeat_pattern(character, new_text, attributes)
305
- elsif(attributes['repeat_pattern'] == true)
306
- capture_character_pattern(character, attributes)
307
- elsif(attributes['color_capture'] > 0 && character =~ /[0-9,A-F,a-f]/)
308
- capture_color(character, new_text, attributes)
309
- elsif(attributes['palette_capture'] > 0 && character =~ /[0-9,A-F,a-f]/)
310
- capture_palette_color(character, new_text, attributes)
311
- elsif(attributes['unicode_capture'] == 1 && character == '+') # Skip
312
- return
313
- elsif(attributes['unicode_capture'] > 0 && character =~ /[0-9,A-F,a-f]/)
314
- capture_unicode(character, new_text, attributes)
315
- elsif(attributes['pipe'] == true &&
316
- attributes['repeat_pattern'] == false &&
317
- attributes['escape'] == true)
318
- process_escaped_character(character, new_text, attributes)
319
- elsif(character == '&' && attributes['ampersand_mode'] == true &&
320
- attributes['pipe'] == false)
321
- process_ampersand(character, new_text, attributes)
322
- elsif(attributes['pipe'] == true)
323
- process_piped_character(character, new_text, attributes)
324
- elsif(attributes['ampersand'] == true)
325
- process_ampersanded_character(character, new_text, attributes)
326
- elsif(attributes['box'] == 0)
327
- new_text << process_box_zero_replace(character)
328
- elsif(attributes['box'] == 1)
329
- new_text << process_box_one_replace(character)
330
- elsif(attributes['box'] == 2)
331
- new_text << process_box_two_replace(character)
332
- else
333
- new_text << character
334
- end
335
- end
336
-
337
- def emit_color(new_text, attributes)
338
- r = attributes['r'].to_i(16).to_s
339
- g = attributes['g'].to_i(16).to_s
340
- b = attributes['b'].to_i(16).to_s
341
- if(attributes['ampersand'] == true) # Background Color
342
- if(attributes['shell_prompt'] == true)
343
- new_text << "\\[\e[48;2;#{r};#{g};#{b}m\\]"
344
- else
345
- new_text << "\e[48;2;#{r};#{g};#{b}m"
346
- end
347
- attributes['ampersand'] = false
348
- else # Foreground Color
349
- if(attributes['shell_prompt'] == true)
350
- new_text << "\\[\e[38;2;#{r};#{g};#{b}m\\]"
351
- else
352
- new_text << "\e[38;2;#{r};#{g};#{b}m"
353
- end
354
- end
355
- attributes['color_capture'] = 0
356
- attributes['r'] = String.new
357
- attributes['g'] = String.new
358
- attributes['b'] = String.new
359
- end
360
-
361
- def emit_palette_color(new_text, attributes)
362
- p = attributes['p'].to_i(16).to_s
363
- if(attributes['ampersand'] == true) # Background Color
364
- if(attributes['shell_prompt'] == true)
365
- new_text << "\\[\e[48;5;#{p}m\\]"
366
- else
367
- new_text << "\e[48;5;#{p}m"
368
- end
369
- attributes['ampersand'] = false
370
- else # Foreground Color
371
- if(attributes['shell_prompt'] == true)
372
- new_text << "\\[\e[38;5;#{p}m\\]"
373
- else
374
- new_text << "\e[38;5;#{p}m"
375
- end
376
- end
377
- attributes['palette_capture'] = 0
378
- attributes['p'] = String.new
379
- end
380
-
381
- def emit_unicode(new_text, attributes)
382
- new_text << [attributes['unicode'].to_i(16)].pack('U*')
383
- attributes['unicode_capture'] = 0
384
- attributes['unicode'] = String.new
385
- end
386
-
387
- def number?(text)
388
- text.chars.each do |character|
389
- if(character !~ /[0-9 ]/)
390
- return false
391
- end
392
- end
393
- return true
394
- end
395
-
396
- def update_variable(attributes)
397
- if(attributes['variable'] =~ /(.*)\-=(.*)/)
398
- if(!number?($2) || !number?(attributes['variables'][$1]))
399
- attributes['variables'][$1].slice!($2)
400
- elsif(attributes['variable'] =~ /(.*) \-= ?(.*)/ || attributes['variable'] =~ /(.*)\-= ?(.*)/)
401
- value = attributes['variables'][$1].to_i - $2.to_i
402
- attributes['variables'][$1] = value.to_s
403
- end
404
- elsif(attributes['variable'] =~ /(.*)\+=(.*)/)
405
- if(!number?($2) || !number?(attributes['variables'][$1]))
406
- attributes['variables'][$1] += $2
407
- elsif(attributes['variable'] =~ /(.*) \+= ?(.*)/ || attributes['variable'] =~ /(.*)\+= ?(.*)/)
408
- value = attributes['variables'][$1].to_i + $2.to_i
409
- attributes['variables'][$1] = value.to_s
410
- end
411
- elsif(attributes['variable'] =~ /(.*) \*= ?(.*)/ || attributes['variable'] =~ /(.*)\*= ?(.*)/)
412
- value = attributes['variables'][$1].to_i * $2.to_i
413
- attributes['variables'][$1] = value.to_s
414
- elsif(attributes['variable'] =~ /(.*) \/= ?(.*)/ || attributes['variable'] =~ /(.*)\/= ?(.*)/)
415
- value = attributes['variables'][$1].to_i / $2.to_i
416
- attributes['variables'][$1] = value.to_s
417
- elsif(attributes['variable'] =~ /(.*) = ?(.*)/ || attributes['variable'] =~ /(.*)= ?(.*)/)
418
- attributes['variables'][$1] = $2
419
- end
420
- attributes['variable_capture'] = false
421
- attributes['variable'] = String.new
422
- end
423
-
424
- def emit_variable(new_text, attributes)
425
- if(attributes['variable'][0] == '#') # We are manipulating attributes['num']
426
- if(attributes['variable'][1..-1] =~ /(.*) \-= ?(.*)/ ||
427
- attributes['variable'][1..-1] =~ /(.*)\-= ?(.*)/)
428
- attributes['num'] = pipetext(escape_fix(attributes['variables'][$1]), attributes['box_mode'],
429
- attributes['ampersand_mode']).to_i - $2.to_i
430
- elsif(attributes['variable'][1..-1] =~ /(.*) \+= ?(.*)/ ||
431
- attributes['variable'][1..-1] =~ /(.*)\+= ?(.*)/)
432
- attributes['num'] = pipetext(escape_fix(attributes['variables'][$1]), attributes['box_mode'],
433
- attributes['ampersand_mode']).to_i + $2.to_i
434
- elsif(attributes['variable'][1..-1] =~ /(.*) \*= ?(.*)/ ||
435
- attributes['variable'][1..-1] =~ /(.*)\*= ?(.*)/)
436
- attributes['num'] = pipetext(escape_fix(attributes['variables'][$1]), attributes['box_mode'],
437
- attributes['ampersand_mode']).to_i * $2.to_i
438
- elsif(attributes['variable'][1..-1] =~ /(.*) \/= ?(.*)/ ||
439
- attributes['variable'][1..-1] =~ /(.*)\/= ?(.*)/)
440
- attributes['num'] = pipetext(escape_fix(attributes['variables'][$1]), attributes['box_mode'],
441
- attributes['ampersand_mode']).to_i / $2.to_i
442
- else
443
- attributes['num'] = pipetext(escape_fix(attributes['variables'][attributes['variable'][1..-1]]),
444
- attributes['box_mode'], attributes['ampersand_mode']).to_i
445
- end
446
- attributes['pipe'] = true
447
- attributes['found'] = false
448
- elsif(attributes['variables'][attributes['variable']])
449
- new_text << pipetext(escape_fix(attributes['variables'][attributes['variable']]),
450
- attributes['box_mode'], attributes['ampersand_mode'])
451
- else
452
- new_text << "|(" + attributes['variable'] + ")"
453
- end
454
- attributes['variable_capture'] = false
455
- attributes['variable'] = String.new
456
- end
457
-
458
- def emit_center(new_text, attributes)
459
- spaces = attributes['end'] - attributes['position'] - printable_length(attributes['center'])
460
- if(printable_length(attributes['center']) % 2)
461
- spaces += 1
462
- end
463
- if(spaces > 0)
464
- spaces /= 2
465
- spaces.times do
466
- new_text << " "
467
- end
468
- end
469
- new_text << attributes['center']
470
- attributes['center_capture'] = false
471
- attributes['center'] = String.new
472
- end
473
-
474
- def emit_emoji(new_text, attributes)
475
- emoji = String.new
476
- match_length = 0
477
- value_length = 0
478
- $substitute_emoji_names.each do |key, value|
479
- if(attributes['emoji'] == key) # Use the most precise match first
480
- emoji = value
481
- break
482
- elsif(attributes['emoji'].length <= key.length) # Otherwise use shortest match
483
- match = abbreviated_match(attributes['emoji'], key)
484
- if(match == 0 && key =~ /-/)
485
- match = abbreviated_match(attributes['emoji'], key.sub(/-/, ' '))
486
- end
487
- if(match > 0 && (match <= match_length || match_length == 0) &&
488
- (value.length <= value_length || value_length == 0))
489
- emoji = value
490
- match_length = match
491
- value_length = value.length
492
- end
493
- end
494
- end
495
- if(emoji == String.new) # No match, put copy input
496
- new_text << "|[" + attributes['emoji'] + "]"
497
- else
498
- emoji.split(/\|U/).each do |e|
499
- if(e != "")
500
- attributes['unicode'] = e.sub(/^\+?/, '')
501
- emit_unicode(new_text, attributes)
502
- end
503
- end
504
- attributes['emoji'] = String.new
505
- end
506
- attributes['emoji_capture'] = false
507
- end
508
-
509
- def process_pipe(character, new_text, attributes)
510
- if(attributes['pipe'] == true && attributes['num'] == 0) # ||
511
- attributes['pipe'] = false
512
- new_text << character
513
- else
514
- attributes['pipe'] = true
515
- end
516
- end
517
-
518
- def process_repeat_pattern(character, new_text, attributes)
519
- if(attributes['repeat_pattern'] == true) # ~ at end of |5~Repeat 5 times~
520
- attributes['num'].times do
521
- new_text << pipetext(attributes['pattern'], attributes['box_mode'], attributes['ampersand_mode'])
522
- end
523
- attributes['num'] = 0
524
- attributes['pipe'] = false
525
- attributes['escape'] = false
526
- attributes['repeat_pattern'] = false
527
- attributes['pattern'] = String.new
528
- else # ~ after number in |5~Repeat 5 times~
529
- attributes['repeat_pattern'] = true
530
- end
531
- end
532
-
533
- def escape_fix(text) # Done this way for old Ruby versions
534
- text = text.gsub(/\\a/, "\a").gsub(/\\b/, "\b").gsub(/\\e/, "\e").gsub(/\\f/, "\f")
535
- text = text.gsub(/\\n/, "\n").gsub(/\\r/, "\r").gsub(/\\t/, "\t").gsub(/\\v/, "\v")
536
- text = text.gsub(/\\~/, '~').gsub(/\\\(/, '(').gsub(/\\\)/, ')')
537
- end
538
-
539
- def process_escaped_character(character, new_text, attributes)
540
- if(attributes['num'] > 0)
541
- attributes['num'].times do
542
- new_text << escape_fix("\\#{character}")
543
- end
544
- else
545
- new_text << escape_fix("\\#{character}")
546
- end
547
- attributes['num'] = 0
548
- attributes['pipe'] = false
549
- attributes['escape'] = false
550
- attributes['pattern'] = String.new
551
- attributes['repeat_pattern'] = false
552
- end
553
-
554
- def capture_color(character, new_text, attributes)
555
- if(character =~ /[0-9,A-F,a-f]/)
556
- if(attributes['color_capture'] <= 2)
557
- attributes['r'] << character
558
- elsif(attributes['color_capture'] <= 4)
559
- attributes['g'] << character
560
- elsif(attributes['color_capture'] <= 6)
561
- attributes['b'] << character
562
- end
563
- if(attributes['color_capture'] == 6)
564
- emit_color(new_text, attributes)
565
- else
566
- attributes['color_capture'] += 1
567
- end
568
- end
569
- end
570
-
571
- def capture_character_pattern(character, attributes)
572
- if(character == '\\')
573
- attributes['escape'] = true
574
- else
575
- if(attributes['escape'] == true)
576
- attributes['pattern'] << "\\#{character}"
577
- attributes['escape'] = false
578
- else
579
- attributes['pattern'] << character
580
- end
581
- end
582
- end
583
-
584
- def capture_palette_color(character, new_text, attributes)
585
- if(character =~ /[0-9,A-F,a-f]/)
586
- if(attributes['palette_capture'] <= 2)
587
- attributes['p'] << character
588
- end
589
- if(attributes['palette_capture'] == 2)
590
- emit_palette_color(new_text, attributes)
591
- else
592
- attributes['palette_capture'] += 1
593
- end
594
- end
595
- end
596
-
597
- def capture_unicode(character, new_text, attributes)
598
- if(character =~ /[0-9,A-F,a-f]/)
599
- if(attributes['unicode_capture'] <= 6)
600
- attributes['unicode'] << character
601
- end
602
- if(attributes['unicode_capture'] == 6)
603
- emit_unicode(new_text, attributes)
604
- else
605
- attributes['unicode_capture'] += 1
606
- end
607
- end
608
- end
609
-
610
- def process_ampersand(character, new_text, attributes)
611
- if(attributes['ampersand'] == true) # &&
612
- attributes['ampersand'] = false
613
- new_text << character
614
- else
615
- attributes['ampersand'] = true
616
- end
617
- end
618
-
619
- def update_attributes(new_text, attributes)
620
- if(attributes['shell_prompt'] == true)
621
- new_text << "\\["
622
- end
623
- if(attributes['bold'] == true)
624
- new_text << "\e[1m"
625
- end
626
- if(attributes['faint'] == true)
627
- new_text << "\e[2m"
628
- end
629
- if(attributes['italic'] == true)
630
- new_text << "\e[3m"
631
- end
632
- if(attributes['underline'] == true)
633
- new_text << "\e[4m"
634
- end
635
- if(attributes['blink'] == true)
636
- new_text << "\e[5m"
637
- end
638
- if(attributes['inverse'] == true)
639
- new_text << "\e[7m"
640
- end
641
- if(attributes['crossed_out'] == true)
642
- new_text << "\e[9m"
643
- end
644
- if(attributes['shell_prompt'] == true)
645
- new_text << "\\]"
646
- end
647
- end
648
-
649
- def process_piped_character(character, new_text, attributes)
650
- attributes['found'] = true # Assume we will find the next character
651
- if(attributes['num'] == 0) # We are not in repeat character mode
652
- case character
653
- when '&' # |& - Toggle & on/off for Background Colors
654
- if(attributes['ampersand_mode'] == true)
655
- attributes['ampersand_mode'] = false
656
- else
657
- attributes['ampersand_mode'] = true
658
- end
659
- attributes['pipe'] = false
660
- when '!' # |! - Clear screen
661
- if(attributes['shell_prompt'] == true)
662
- new_text << "\\[\e[H\e[J\\]"
663
- else
664
- new_text << "\e[H\e[J"
665
- end
666
- when '+' # |+ - Bold
667
- if(attributes['shell_prompt'] == true)
668
- new_text << "\\["
669
- end
670
- if(attributes['bold'] == false)
671
- new_text << "\e[1m"
672
- attributes['bold'] = true
673
- else
674
- new_text << "\e[22m"
675
- attributes['bold'] = false
676
- end
677
- if(attributes['shell_prompt'] == true)
678
- new_text << "\\]"
679
- end
680
- when '.' # |. - Faint / Dim
681
- if(attributes['shell_prompt'] == true)
682
- new_text << "\\["
683
- end
684
- if(attributes['faint'] == false)
685
- new_text << "\e[2m"
686
- attributes['faint'] = true
687
- else
688
- new_text << "\e[22m"
689
- attributes['faint'] = false
690
- end
691
- if(attributes['shell_prompt'] == true)
692
- new_text << "\\]"
693
- end
694
- when '~' # |~ - Italic
695
- if(attributes['shell_prompt'] == true)
696
- new_text << "\\["
697
- end
698
- if(attributes['italic'] == false)
699
- new_text << "\e[3m"
700
- attributes['italic'] = true
701
- else
702
- new_text << "\e[23m"
703
- attributes['italic'] = false
704
- end
705
- if(attributes['shell_prompt'] == true)
706
- new_text << "\\]"
707
- end
708
- when '_' # |_ - Underline
709
- if(attributes['shell_prompt'] == true)
710
- new_text << "\\["
711
- end
712
- if(attributes['underline'] == false)
713
- new_text << "\e[4m"
714
- attributes['underline'] = true
715
- else
716
- new_text << "\e[24m"
717
- attributes['underline'] = false
718
- end
719
- if(attributes['shell_prompt'] == true)
720
- new_text << "\\]"
721
- end
722
- when '@' # |@ - Blink
723
- if(attributes['shell_prompt'] == true)
724
- new_text << "\\["
725
- end
726
- if(attributes['blink'] == false)
727
- new_text << "\e[5m"
728
- attributes['blink'] = true
729
- else
730
- new_text << "\e[25m"
731
- attributes['blink'] = false
732
- end
733
- if(attributes['shell_prompt'] == true)
734
- new_text << "\\]"
735
- end
736
- when '^' # |^ - Move up 1 line
737
- new_text << "\e[A"
738
- when 'v', 'V' # |v - Move down 1 line
739
- new_text << "\e[B"
740
- when '>' # |> - Move forward 1 character
741
- new_text << "\e[C"
742
- when '<' # |< - Move back 1 character
743
- new_text << "\e[D"
744
- when 'h' # |h - Hide cursor
745
- if(attributes['shell_prompt'] == true)
746
- new_text << "\\[\e[?25l\\]"
747
- else
748
- new_text << "\e[?25l"
749
- end
750
- when 'H' # |H - Unhide cursor
751
- if(attributes['shell_prompt'] == true)
752
- new_text << "\\[\e[?25h\\]"
753
- else
754
- new_text << "\e[?25h"
755
- end
756
- when 'i', 'I' # |i - Inverse
757
- if(attributes['shell_prompt'] == true)
758
- new_text << "\\["
759
- end
760
- if(attributes['inverse'] == false)
761
- new_text << "\e[7m"
762
- attributes['inverse'] = true
763
- else
764
- new_text << "\e[27m"
765
- attributes['inverse'] = false
766
- end
767
- if(attributes['shell_prompt'] == true)
768
- new_text << "\\]"
769
- end
770
- when 'x', 'X' # |x - Crossed Out
771
- if(attributes['shell_prompt'] == true)
772
- new_text << "\\["
773
- end
774
- if(attributes['crossed_out'] == false)
775
- new_text << "\e[9m"
776
- attributes['crossed_out'] = true
777
- else
778
- new_text << "\e[29m"
779
- attributes['crossed_out'] = false
780
- end
781
- if(attributes['shell_prompt'] == true)
782
- new_text << "\\]"
783
- end
784
- when '#' # |#RRGGBB
785
- attributes['color_capture'] = 1
786
- when 'P', 'p' # |P or |p - 2 character hex format color (256 colors)
787
- attributes['palette_capture'] = 1
788
- when 'U', 'u' # |U or |u - Unicode 6 character hex format
789
- attributes['unicode_capture'] = 1
790
- when 'K', 'k' # |K or |k - Foreground text black
791
- attributes['fg'] = "\e[30m"
792
- if(attributes['shell_prompt'] == true)
793
- new_text << "\\[\e[0;30m\\]"
794
- else
795
- new_text << "\e[0;30m"
796
- end
797
- attributes['bold'] = false
798
- update_attributes(new_text, attributes)
799
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
800
- when 'S', 's' # |S or |s - Foreground text smoke
801
- attributes['fg'] = "\e[1;30m"
802
- if(attributes['shell_prompt'] == true)
803
- new_text << "\\[\e[1;30m\\]"
804
- else
805
- new_text << "\e[1;30m"
806
- end
807
- attributes['bold'] = false
808
- update_attributes(new_text, attributes)
809
- attributes['bold'] = true
810
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
811
- when 'r' # |r - Foreground text red
812
- attributes['fg'] = "\e[31m"
813
- if(attributes['shell_prompt'] == true)
814
- new_text << "\\[\e[0;31m\\]"
815
- else
816
- new_text << "\e[0;31m"
817
- end
818
- attributes['bold'] = false
819
- update_attributes(new_text, attributes)
820
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
821
- when 'R' # |R - Foreground text bright red
822
- attributes['fg'] = "\e[1;31m"
823
- if(attributes['shell_prompt'] == true)
824
- new_text << "\\[\e[1;31m\\]"
825
- else
826
- new_text << "\e[1;31m"
827
- end
828
- attributes['bold'] = false
829
- update_attributes(new_text, attributes)
830
- attributes['bold'] = true
831
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
832
- when 'g' # |g - Foreground text green
833
- attributes['fg'] = "\e[32m"
834
- if(attributes['shell_prompt'] == true)
835
- new_text << "\\[\e[0;32m\\]"
836
- else
837
- new_text << "\e[0;32m"
838
- end
839
- attributes['bold'] = false
840
- update_attributes(new_text, attributes)
841
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
842
- when 'G' # |G - Foreground text bright green
843
- attributes['fg'] = "\e[1;32m"
844
- if(attributes['shell_prompt'] == true)
845
- new_text << "\\[\e[1;32m\\]"
846
- else
847
- new_text << "\e[1;32m"
848
- end
849
- attributes['bold'] = false
850
- update_attributes(new_text, attributes)
851
- attributes['bold'] = true
852
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
853
- when 'y' # |y - Foreground text yellow (brown)
854
- attributes['fg'] = "\e[33m"
855
- if(attributes['shell_prompt'] == true)
856
- new_text << "\\[\e[0;33m\\]"
857
- else
858
- new_text << "\e[0;33m"
859
- end
860
- attributes['bold'] = false
861
- update_attributes(new_text, attributes)
862
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
863
- when 'Y' # |Y - Foreground text bright yellow
864
- attributes['fg'] = "\e[1;33m"
865
- if(attributes['shell_prompt'] == true)
866
- new_text << "\\[\e[1;33m\\]"
867
- else
868
- new_text << "\e[1;33m"
869
- end
870
- attributes['bold'] = false
871
- update_attributes(new_text, attributes)
872
- attributes['bold'] = true
873
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
874
- when 'b' # |b - Foreground text blue
875
- attributes['fg'] = "\e[34m"
876
- if(attributes['shell_prompt'] == true)
877
- new_text << "\\[\e[0;34m\\]"
878
- else
879
- new_text << "\e[0;34m"
880
- end
881
- attributes['bold'] = false
882
- update_attributes(new_text, attributes)
883
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
884
- when 'B' # |B - Foreground text bright blue
885
- attributes['fg'] = "\e[1;34m"
886
- if(attributes['shell_prompt'] == true)
887
- new_text << "\\[\e[1;34m\\]"
888
- else
889
- new_text << "\e[1;34m"
890
- end
891
- attributes['bold'] = false
892
- update_attributes(new_text, attributes)
893
- attributes['bold'] = true
894
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
895
- when 'm' # |m - Foreground text magenta
896
- attributes['fg'] = "\e[35m"
897
- if(attributes['shell_prompt'] == true)
898
- new_text << "\\[\e[0;35m\\]"
899
- else
900
- new_text << "\e[0;35m"
901
- end
902
- attributes['bold'] = false
903
- update_attributes(new_text, attributes)
904
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
905
- when 'M' # |M - Foreground text bright magenta
906
- attributes['fg'] = "\e[1;35m"
907
- if(attributes['shell_prompt'] == true)
908
- new_text << "\\[\e[1;35m\\]"
909
- else
910
- new_text << "\e[1;35m"
911
- end
912
- attributes['bold'] = false
913
- update_attributes(new_text, attributes)
914
- attributes['bold'] = true
915
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
916
- when 'c' # |c - Foreground text cyan
917
- attributes['fg'] = "\e[36m"
918
- if(attributes['shell_prompt'] == true)
919
- new_text << "\\[\e[0;36m\\]"
920
- else
921
- new_text << "\e[0;36m"
922
- end
923
- attributes['bold'] = false
924
- update_attributes(new_text, attributes)
925
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
926
- when 'C' # |C - Foreground text bright cyan
927
- attributes['fg'] = "\e[1;36m"
928
- if(attributes['shell_prompt'] == true)
929
- new_text << "\\[\e[1;36m\\]"
930
- else
931
- new_text << "\e[1;36m"
932
- end
933
- attributes['bold'] = false
934
- update_attributes(new_text, attributes)
935
- attributes['bold'] = true
936
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
937
- when 'W', 'w' # |W or |w - Foreground text white
938
- attributes['fg'] = "\e[1;37m"
939
- if(attributes['shell_prompt'] == true)
940
- new_text << "\\[\e[1;37m\\]"
941
- else
942
- new_text << "\e[1;37m"
943
- end
944
- attributes['bold'] = false
945
- update_attributes(new_text, attributes)
946
- attributes['bold'] = true
947
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
948
- when 'N', 'n' # |N or |n - Foreground text normal
949
- attributes['fg'] = ""
950
- if(attributes['shell_prompt'] == true)
951
- new_text << "\\[\e[0;37m\\]"
952
- else
953
- new_text << "\e[0;37m"
954
- end
955
- attributes['bold'] = false
956
- update_attributes(new_text, attributes)
957
- if(attributes['shell_prompt'] == true)
958
- new_text << attributes['bg'] == "\e[0m" ? "" : "\\[" + attributes['bg'] + "\\]"
959
- else
960
- new_text << attributes['bg'] == "\e[0m" ? "" : attributes['bg']
961
- end
962
- when 'O' # |O - Box mode off
963
- attributes['box'] = -1
964
- when 'o' # |o - Box mode 0
965
- attributes['box'] = 0
966
- when '-' # |- - Box mode 1
967
- if(attributes['box_mode'] == true)
968
- attributes['box'] = 1
969
- else # We didn't find the next character
970
- attributes['found'] = false
971
- end
972
- when '=' # |= - Box mode 2
973
- if(attributes['box_mode'] == true)
974
- attributes['box'] = 2
975
- else # We didn't find the next character
976
- attributes['found'] = false
977
- end
978
- when '{' # center
979
- attributes['center_capture'] = true
980
- when ';' # extend to end column with spaces
981
- spaces = attributes['end'] - attributes['position']
982
- spaces.times do
983
- new_text << " "
984
- end
985
- when ']' # |]0-9* - end column number
986
- attributes['end_capture'] = true
987
- when '[' # |[emoji]
988
- attributes['emoji_capture'] = true
989
- when '(' # |(variable) or |(variable=Some value)
990
- attributes['variable_capture'] = true
991
- when '\\' # |\ - Escape mode
992
- attributes['escape'] = true
993
- when '$' # |$ - Toggle shell prompt mode
994
- if(attributes['shell_prompt'] == true)
995
- attributes['shell_prompt'] = false
996
- else
997
- attributes['shell_prompt'] = true
998
- end
999
- else # We didn't find the next character
1000
- attributes['found'] = false
1001
- end
1002
- elsif(character == '\\')
1003
- attributes['escape'] = true
1004
- else # We didn't find the next character
1005
- attributes['found'] = false
1006
- end
1007
- if(attributes['found'] == false)
1008
- if(character == '0') # |10+
1009
- if(attributes['num'] > 0)
1010
- attributes['num'] *= 10
1011
- end
1012
- elsif(character >= '1' && character <= '9') # |1+ through |9+
1013
- if(attributes['num'] > 0)
1014
- attributes['num'] *= 10
1015
- end
1016
- attributes['num'] += character.to_i
1017
- else
1018
- if(attributes['num'] <= 0) # No replacement found
1019
- new_text << '|' + character
1020
- else # Repeat number replacement found
1021
- if(attributes['box'] == 1)
1022
- attributes['num'].times do
1023
- new_text << process_box_one_replace(character)
1024
- end
1025
- attributes['num'] = 0
1026
- elsif(attributes['box'] == 2)
1027
- attributes['num'].times do
1028
- new_text << process_box_two_replace(character)
1029
- end
1030
- attributes['num'] = 0
1031
- else
1032
- attributes['num'].times do
1033
- new_text << character
1034
- end
1035
- attributes['num'] = 0
1036
- end
1037
- end
1038
- attributes['pipe'] = false
1039
- end
1040
- elsif(attributes['escape'] == false)
1041
- attributes['pipe'] = false
1042
- end
1043
- end
1044
-
1045
- def process_ampersanded_character(character, new_text, attributes)
1046
- case character
1047
- when '#' # &#RRGGBB
1048
- attributes['color_capture'] = 1
1049
- return
1050
- when 'P', 'p' # |P or |p - 2 character hex format color (256 colors)
1051
- attributes['palette_capture'] = 1
1052
- return
1053
- when 'W', 'w' # &W or &w - Background white
1054
- if(attributes['shell_prompt'] == true)
1055
- new_text << "\\[\e[0;47m\\]"
1056
- else
1057
- new_text << "\e[0;47m"
1058
- end
1059
- attributes['bg'] = "\e[47m"
1060
- update_attributes(new_text, attributes)
1061
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1062
- when 'C', 'c' # &C or &c - Background cyan
1063
- if(attributes['shell_prompt'] == true)
1064
- new_text << "\\[\e[0;46m\\]"
1065
- else
1066
- new_text << "\e[0;46m"
1067
- end
1068
- attributes['bg'] = "\e[46m"
1069
- update_attributes(new_text, attributes)
1070
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1071
- when 'M', 'm' # &M or &m - Background magenta
1072
- if(attributes['shell_prompt'] == true)
1073
- new_text << "\\[\e[0;45m\\]"
1074
- else
1075
- new_text << "\e[0;45m"
1076
- end
1077
- attributes['bg'] = "\e[45m"
1078
- update_attributes(new_text, attributes)
1079
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1080
- when 'B', 'b' # &B or &b - Background blue
1081
- if(attributes['shell_prompt'] == true)
1082
- new_text << "\\[\e[0;44m\\]"
1083
- else
1084
- new_text << "\e[0;44m"
1085
- end
1086
- attributes['bg'] = "\e[44m"
1087
- update_attributes(new_text, attributes)
1088
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1089
- when 'Y', 'y' # &Y or &y - Background yellow (brown)
1090
- if(attributes['shell_prompt'] == true)
1091
- new_text << "\\[\e[0;43m\\]"
1092
- else
1093
- new_text << "\e[0;43m"
1094
- end
1095
- attributes['bg'] = "\e[43m"
1096
- update_attributes(new_text, attributes)
1097
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1098
- when 'G', 'g' # &G or &g - Background green
1099
- if(attributes['shell_prompt'] == true)
1100
- new_text << "\\[\e[0;42m\\]"
1101
- else
1102
- new_text << "\e[0;42m"
1103
- end
1104
- attributes['bg'] = "\e[42m"
1105
- update_attributes(new_text, attributes)
1106
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1107
- when 'R', 'r' # &R or &r - Background red
1108
- if(attributes['shell_prompt'] == true)
1109
- new_text << "\\[\e[0;41m\\]"
1110
- else
1111
- new_text << "\e[0;41m"
1112
- end
1113
- attributes['bg'] ="\e[41m"
1114
- update_attributes(new_text, attributes)
1115
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1116
- when 'S', 's', 'K', 'k' # &S, &s, &K, &k - Background black/smoke
1117
- if(attributes['shell_prompt'] == true)
1118
- new_text << "\\[\e[0;40m\\]"
1119
- else
1120
- new_text << "\e[0;40m"
1121
- end
1122
- attributes['bg'] = "\e[40m"
1123
- update_attributes(new_text, attributes)
1124
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1125
- when 'N', 'n' # &N or &n - Background normal
1126
- if(attributes['shell_prompt'] == true)
1127
- new_text << "\\[\e[0m\\]"
1128
- else
1129
- new_text << "\e[0m"
1130
- end
1131
- attributes['bg'] = ""
1132
- update_attributes(new_text, attributes)
1133
- if(attributes['shell_prompt'] == true)
1134
- new_text << attributes['fg'] == "\e[0m" ? "" : "\\[" + attributes['fg'] + "\\]"
1135
- else
1136
- new_text << attributes['fg'] == "\e[0m" ? "" : attributes['fg']
1137
- end
1138
- else
1139
- new_text << '&' + character
1140
- end
1141
- attributes['ampersand'] = false
1142
- end
1143
-
1144
- def process_box_zero_replace(character)
1145
- case character
1146
- when '['
1147
- '+'
1148
- when ']'
1149
- '+'
1150
- when '-'
1151
- '-'
1152
- when '!'
1153
- '|'
1154
- when '>'
1155
- '+'
1156
- when '<'
1157
- '+'
1158
- when '+'
1159
- '+'
1160
- when '{'
1161
- '+'
1162
- when '}'
1163
- '+'
1164
- when 'v'
1165
- '+'
1166
- when '^'
1167
- '+'
1168
- else
1169
- character
1170
- end
1171
- end
1172
-
1173
- def process_box_one_replace(character)
1174
- case character
1175
- when '['
1176
- '┌'
1177
- when ']'
1178
- '┐'
1179
- when '-'
1180
- '─'
1181
- when '!'
1182
- '│'
1183
- when '>'
1184
- '├'
1185
- when '<'
1186
- '┤'
1187
- when '+'
1188
- '┼'
1189
- when '{'
1190
- '└'
1191
- when '}'
1192
- '┘'
1193
- when 'v'
1194
- '┬'
1195
- when '^'
1196
- '┴'
1197
- else
1198
- character
1199
- end
1200
- end
1201
-
1202
- def process_box_two_replace(character)
1203
- case character
1204
- when '['
1205
- '╔'
1206
- when ']'
1207
- '╗'
1208
- when '-'
1209
- '═'
1210
- when '!'
1211
- '║'
1212
- when '>'
1213
- '╠'
1214
- when '<'
1215
- '╣'
1216
- when '+'
1217
- '╬'
1218
- when '{'
1219
- '╚'
1220
- when '}'
1221
- '╝'
1222
- when 'v'
1223
- '╦'
1224
- when '^'
1225
- '╩'
1226
- else
1227
- character
1
+ # Allow older versions of Ruby to respond to the require_relative method
2
+ if(!Kernel.respond_to?(:require_relative))
3
+ module Kernel
4
+ def require_relative(path)
5
+ require File.join(File.dirname(caller[0]), path.to_str)
1228
6
  end
1229
7
  end
1230
8
  end
9
+
10
+ require_relative File.join("pipetext", "version.rb")
11
+ require_relative File.join("pipetext", "pipetext.rb")
12
+ require_relative File.join("pipetext", "substitute_emoji_names.rb")