pipetext 0.2.7 → 0.2.9

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.
@@ -0,0 +1,2343 @@
1
+ require "io/console"
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
+ "box_capture" => 0, # Used to capture boxes for update or to display
26
+ "boxes" => 0, # Total number of boxes used for nesting
27
+ "box_attributes" => Hash.new, # Box variables captured
28
+ "num" => 0, # Number of times to repeat pattern
29
+ "end_capture" => false, # Used to capture the end column number
30
+ "end" => 0, # Number which current denotes the end of the column
31
+ "position" => 0, # Number which current position in the column
32
+ "center_capture" => false, # Used to capture text for centering
33
+ "center" => String.new, # Text to be centered
34
+ "right_capture" => false, # Used to capture text for right justify
35
+ "right" => String.new, # Text to be justified to the right
36
+ "variable_capture" => false, # Used to capture a variable for update or to display
37
+ "variable" => String.new, # Variable captured
38
+ "variables" => Hash.new, # Stores all captured variables
39
+ "emoji_capture" => false, # Used to capture emoji description or bell/move to position
40
+ "emoji" => String.new, # Used to capture emoji description or bell/move to position
41
+ "unicode_capture" => 0, # Used to capture Unicode using 6 character UTF-16 hex format
42
+ "unicode" => String.new,
43
+ "palette_capture" => 0, # Used to capture 8-bit color using 2 character hex format
44
+ "p" => String.new, # |p00 to |pFF
45
+ "color_capture" => 0, # Used to capture RGB color using #RRGGBB format
46
+ "r" => String.new,
47
+ "g" => String.new,
48
+ "b" => String.new,
49
+ "fg" => String.new, # Needed to restore after background change
50
+ "bg" => String.new, # Needed to restore after foreground change
51
+ "remap" => Hash.new, # Used to remap pipetext codes
52
+ "shell_prompt" => false # Used to add \[ and \] around non-printables for prompts
53
+ }
54
+ attributes["variables"]["height"], attributes["variables"]["width"] = IO.console.winsize
55
+ return attributes
56
+ end
57
+
58
+ def pipe(text, attributes)
59
+ new_text = String.new
60
+ if(text != "")
61
+ if(attributes["remap"] != {})
62
+ attributes["remap"].each do |old, new|
63
+ text.gsub!(old, new)
64
+ end
65
+ end
66
+ attributes["remap"] = Hash.new
67
+ text.chars.each do |character|
68
+ process_character(character, new_text, attributes)
69
+ if(new_text =~ /.*\n(.*)$/m)
70
+ attributes["position"] = printable_length($1)
71
+ else
72
+ attributes["position"] = printable_length(new_text)
73
+ end
74
+ end
75
+ end
76
+ # Clean up in case we've captured something we didn't process yet
77
+ if(attributes["color_capture"] > 0)
78
+ emit_color(new_text, attributes)
79
+ elsif(attributes["palette_capture"] > 0)
80
+ emit_palette_color(new_text, attributes)
81
+ elsif(attributes["unicode_capture"] > 0)
82
+ emit_unicode(new_text, attributes)
83
+ elsif(attributes["emoji_capture"] == true)
84
+ new_text << "|[" + attributes["emoji"]
85
+ elsif(attributes["center_capture"] == true)
86
+ new_text << "|{" + attributes["center"]
87
+ elsif(attributes["right_capture"] == true)
88
+ emit_right(new_text, attributes)
89
+ elsif(attributes["variable_capture"] == true)
90
+ new_text << "|(" + attributes["variable"]
91
+ end
92
+ return new_text
93
+ end
94
+
95
+ def pipetext(text, box_mode=true, ampersand_mode=false)
96
+ pipe(text, pipetext_init(box_mode, ampersand_mode))
97
+ end
98
+
99
+ # Immediate output to screen, no string buffer
100
+ def fastpipe(text, attributes)
101
+ new_text = String.new
102
+ text.chars.each do |character|
103
+ process_character(character, new_text, attributes)
104
+ if(new_text != "")
105
+ print(new_text)
106
+ if(new_text =~ /.*\n(.*)$/m)
107
+ attributes["position"] = printable_length($1)
108
+ else
109
+ attributes["position"] += printable_length(new_text)
110
+ end
111
+ new_text = String.new
112
+ end
113
+ end
114
+ # Clean up in case we've captured something we didn't process yet
115
+ if(attributes["color_capture"] > 0)
116
+ emit_color(new_text, attributes)
117
+ elsif(attributes["palette_capture"] > 0)
118
+ emit_palette_color(new_text, attributes)
119
+ elsif(attributes["unicode_capture"] > 0)
120
+ emit_unicode(new_text, attributes)
121
+ elsif(attributes["emoji_capture"] == true)
122
+ new_text << "|[" + attributes["emoji"]
123
+ elsif(attributes["center_capture"] == true)
124
+ new_text << "|{" + attributes["center"]
125
+ elsif(attributes["right_capture"] == true)
126
+ emit_right(new_text, attributes)
127
+ elsif(attributes["variable_capture"] == true)
128
+ new_text << "|(" + attributes["variable"]
129
+ end
130
+ print(new_text)
131
+ end
132
+
133
+ def fastpipetext(text, box_mode=true, ampersand_mode=false)
134
+ fastpipe(text, pipetext_init(box_mode, ampersand_mode))
135
+ end
136
+
137
+ def write(text, box_mode=true, ampersand_mode=false)
138
+ fastpipetext(text, box_mode, ampersand_mode)
139
+ end
140
+
141
+ # Defaults to using & for background colors
142
+ def paint(text, box_mode=true, ampersand_mode=true)
143
+ fastpipetext(text, box_mode, ampersand_mode)
144
+ end
145
+
146
+ def ignored_character(character, ignored_characters)
147
+ ignored_characters.chars.each do |ignored|
148
+ if(character == ignored)
149
+ return true
150
+ end
151
+ end
152
+ return false
153
+ end
154
+
155
+ # Match abbreviated text descriptions for emojis by default ignore case and punctuation
156
+ # Allows for "space anchoring" so you can use |[smi f w he e] as an abbreviation for
157
+ # |[smiling face with heart-eyes]
158
+ def abbreviated_match(input, match, case_match=false, ignored_characters=",.,:-")
159
+ if(!input || !match)
160
+ return 0
161
+ end
162
+ count = 0
163
+ offset = 0
164
+ input.chars.each_with_index do |character, index|
165
+ while(ignored_character(match[index + offset], ignored_characters))
166
+ offset += 1
167
+ end
168
+ if(character == match[index + offset].chr)
169
+ count += 1
170
+ elsif(case_match == false && character.downcase == match[index + offset].chr.downcase)
171
+ count += 1
172
+ elsif(character == " " && match[index + offset..-1] =~ / /)
173
+ count += 1
174
+ while(match[index + offset].chr != character)
175
+ offset += 1
176
+ end
177
+ else
178
+ count = 0
179
+ offset = 0
180
+ break
181
+ end
182
+ end
183
+ return count + offset
184
+ end
185
+
186
+ # Just yikes!
187
+ def double_wide_character(character)
188
+ if(character == nil || character == "")
189
+ return false
190
+ end
191
+ ord = character.ord
192
+ if((ord >= 4352 && ord <= 4447) ||
193
+ (ord >= 4520 && ord <= 4607) ||
194
+ ord == 8986 || ord == 8987 ||
195
+ ord == 9193 || ord == 9194 ||
196
+ ord == 9195 || ord == 9196 ||
197
+ ord == 9200 ||
198
+ ord == 9203 ||
199
+ ord == 9654 ||
200
+ ord == 9664 ||
201
+ ord == 9726 ||
202
+ ord == 9729 || ord == 9730 ||
203
+ ord == 9731 || ord == 9732 ||
204
+ ord == 9742 ||
205
+ ord == 9748 || ord == 9749 ||
206
+ ord == 9752 ||
207
+ ord == 9757 ||
208
+ ord == 9760 ||
209
+ ord == 9762 || ord == 9763 ||
210
+ ord == 9770 ||
211
+ ord == 9774 || ord == 9775 ||
212
+ ord == 9784 ||
213
+ (ord >= 9800 && ord <= 9811) ||
214
+ ord == 9823 ||
215
+ ord == 9832 ||
216
+ ord == 9851 ||
217
+ ord == 9855 ||
218
+ ord == 9874 ||
219
+ ord == 9875 || ord == 9876 ||
220
+ ord == 9877 ||
221
+ ord == 9878 || ord == 9879 ||
222
+ ord == 9884 ||
223
+ ord == 9888 || ord == 9889 ||
224
+ ord == 9895 ||
225
+ ord == 9904 || ord == 9905 ||
226
+ ord == 9917 || ord == 9918 ||
227
+ ord == 9924 || ord == 9925 ||
228
+ ord == 9928 ||
229
+ ord == 9934 || ord == 9935 ||
230
+ ord == 9937 ||
231
+ ord == 9939 || ord == 9940 ||
232
+ ord == 9961 || ord == 9962 ||
233
+ ord == 9968 || ord == 9969 ||
234
+ ord == 9970 || ord == 9971 ||
235
+ ord == 9972 || ord == 9973 ||
236
+ ord == 9975 || ord == 9976 ||
237
+ ord == 9977 || ord == 9978 ||
238
+ ord == 9981 ||
239
+ ord == 9989 ||
240
+ ord == 9993 || ord == 9994 ||
241
+ ord == 9995 || ord == 9996 ||
242
+ ord == 9997 ||
243
+ ord == 9999 ||
244
+ ord == 10002 ||
245
+ ord == 10024 ||
246
+ ord == 10060 ||
247
+ ord == 10062 ||
248
+ ord == 10067 || ord == 10068 ||
249
+ ord == 10069 ||
250
+ ord == 10071 ||
251
+ ord == 10083 ||
252
+ ord == 10133 || ord == 10134 ||
253
+ ord == 10135 ||
254
+ ord == 10160 ||
255
+ ord == 10175 ||
256
+ ord == 10548 ||
257
+ ord == 10549 ||
258
+ ord == 11035 ||
259
+ ord == 11036 ||
260
+ ord == 11088 ||
261
+ ord == 11093 ||
262
+ (ord >= 11904 && ord <= 12245) ||
263
+ (ord >= 12272 && ord <= 12283) ||
264
+ (ord >= 12288 && ord <= 12351) ||
265
+ (ord >= 12352 && ord <= 12735) ||
266
+ (ord >= 12736 && ord <= 12771) ||
267
+ (ord >= 12784 && ord <= 12831) ||
268
+ (ord >= 12832 && ord <= 12879) ||
269
+ (ord >= 12880 && ord <= 13055) ||
270
+ (ord >= 13056 && ord <= 13311) ||
271
+ (ord >= 13312 && ord <= 19903) ||
272
+ (ord >= 19968 && ord <= 40959) ||
273
+ (ord >= 44032 && ord <= 55203) ||
274
+ (ord >= 63744 && ord <= 64255) ||
275
+ (ord >= 65072 && ord <= 65103) ||
276
+ (ord >= 65104 && ord <= 65135) ||
277
+ (ord >= 65184 && ord <= 65279) ||
278
+ (ord >= 65280 && ord <= 65376) ||
279
+ (ord >= 65382 && ord <= 65439) ||
280
+ (ord >= 65440 && ord <= 65500) ||
281
+ (ord >= 65504 && ord <= 65510) ||
282
+ (ord >= 65512 && ord <= 65518) ||
283
+ (ord >= 110592 && ord <= 110593) ||
284
+ (ord >= 110594 && ord <= 110847) ||
285
+ ord == 126980 ||
286
+ ord == 127183 ||
287
+ ord == 127374 ||
288
+ ord == 127377 || ord == 127378 ||
289
+ ord == 127379 ||
290
+ ord == 127381 || ord == 127382 ||
291
+ ord == 127383 ||
292
+ (ord >= 127462 && ord <= 127487) ||
293
+ (ord >= 127744 && ord <= 129791) ||
294
+ (ord >= 131072 && ord <= 173791) ||
295
+ (ord >= 173824 && ord <= 177983) ||
296
+ (ord >= 177984 && ord <= 178207) ||
297
+ (ord >= 178208 && ord <= 183983) ||
298
+ (ord >= 183984 && ord <= 191455) ||
299
+ (ord >= 191456 && ord <= 196607) ||
300
+ (ord >= 196608 && ord <= 201546) ||
301
+ (ord >= 201552 && ord <= 262143))
302
+ return true
303
+ end
304
+ return false
305
+ end
306
+
307
+ # This is not entirely accurate because of emojis - double yikes!
308
+ def printable_length(string)
309
+ if(string == "")
310
+ return 0
311
+ end
312
+ length = 0
313
+ escape = false
314
+ wide = false
315
+ wide_count = 0
316
+ zero_width_join = false
317
+ last_was_wide = false
318
+ country_code = false
319
+ string.chars.each do |character|
320
+ if(character[0].ord == 27)
321
+ escape = true
322
+ elsif(character[0].ord == 226 && wide == false)
323
+ wide = true
324
+ elsif(character[0].ord == 240 && wide == false)
325
+ wide = true
326
+ elsif(character[0].ord >= 32)
327
+ if(escape == true && character[0].ord == 109)
328
+ escape = false
329
+ elsif(zero_width_join == true)
330
+ zero_width_join = false
331
+ elsif(character[0].ord == 8205)
332
+ zero_width_join = true
333
+ elsif(character[0].ord == 65039)
334
+ if(last_was_wide == false)
335
+ length += 1
336
+ end
337
+ elsif(character[0].ord == 8419)
338
+ next
339
+ elsif(character[0].ord >= 127462 && character[0].ord <= 127487 && country_code == true)
340
+ country_code = false
341
+ next
342
+ elsif(character[0].ord >= 127995 && character[0].ord <= 127999)
343
+ next
344
+ elsif(character[0].ord >= 917602 && character[0].ord <= 917631)
345
+ next
346
+ elsif(double_wide_character(character))
347
+ if(character[0].ord >= 127462 && character[0].ord <= 127487)
348
+ country_code = true
349
+ end
350
+ length += 2
351
+ last_was_wide = true
352
+ elsif(escape == false && wide == false)
353
+ length += 1
354
+ last_was_wide = false
355
+ country_code = false
356
+ elsif(wide == true)
357
+ wide_count += 1
358
+ end
359
+ if(wide == true && wide_count >= 2)
360
+ if(character[0].ord == 147)
361
+ length += 1
362
+ else
363
+ length += 1
364
+ wide = false
365
+ wide_count = 0
366
+ end
367
+ end
368
+ end
369
+ end
370
+ if(wide == true && wide_count > 0)
371
+ length += 1
372
+ end
373
+ return length
374
+ end
375
+
376
+ def with_spinner(spinner="⠇⠏⠋⠙⠹⠸⣰⣠⣄⣆", colors=["|n"])
377
+ spinner_thread = Thread.new do
378
+ count = 0
379
+ if(colors == nil)
380
+ fastpipetext("|h#{spinner[0]}")
381
+ else
382
+ fastpipetext("|h#{colors[0]}#{spinner[0]}")
383
+ end
384
+ while(true)
385
+ ord = spinner[count % spinner.length].ord
386
+ if(double_wide_character(spinner[count % spinner.length]))
387
+ print "\b"
388
+ end
389
+ count += 1
390
+ sleep 0.05
391
+ if(colors == nil)
392
+ fastpipetext("\b#{spinner[count % spinner.length]}")
393
+ else
394
+ fastpipetext("\b#{colors[count % colors.length]}#{spinner[count % spinner.length]}")
395
+ end
396
+ end
397
+ end
398
+ begin
399
+ yield
400
+ ensure
401
+ spinner_thread.kill
402
+ fastpipetext("|H\b|n")
403
+ end
404
+ end
405
+
406
+ def with_spinner_mode(mode=0, &block)
407
+ if(mode == 0)
408
+ with_spinner(&block)
409
+ elsif(mode == 1)
410
+ with_spinner(["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘",
411
+ "🌑", "🌘", "🌗", "🌖", "🌕", "🌔", "🌓", "🌒"], &block)
412
+ elsif(mode == 2)
413
+ with_spinner(["🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛"], &block)
414
+ elsif(mode == 3)
415
+ with_spinner(["◐", "◓", "◑", "◒"], &block)
416
+ elsif(mode == 4)
417
+ with_spinner(["◜", "◠", "◝", "◞", "◡", "◟"], &block)
418
+ elsif(mode == 5)
419
+ with_spinner(["⠁", "⠂", "⠄", "⠂"], &block)
420
+ elsif(mode == 6)
421
+ with_spinner([" ", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃"], &block)
422
+ elsif(mode == 7)
423
+ with_spinner(["◰", "◳", "◲", "◱"], &block)
424
+ elsif(mode == 8)
425
+ with_spinner(["🔴", "🟠", "🟡", "🟢", "🔵", "🟣"], &block)
426
+ end
427
+ end
428
+
429
+ private
430
+
431
+ def process_character(character, new_text, attributes)
432
+ if(attributes["repeat_pattern"] == false)
433
+ # Will still need to process character, first process incorrect formats
434
+ if(attributes["color_capture"] > 0 && character !~ /[0-9,A-F,a-f]/)
435
+ emit_color(new_text, attributes)
436
+ elsif(attributes["palette_capture"] > 0 && character !~ /[0-9,A-F,a-f]/)
437
+ emit_palette_color(new_text, attributes)
438
+ elsif(attributes["unicode_capture"] > 0 && (character !~ /[0-9,A-F,a-f,+]/ ||
439
+ (attributes["unicode_capture"] != 1 && character == "+")))
440
+ emit_unicode(new_text, attributes)
441
+ end
442
+ end
443
+ if(attributes["end_capture"] == true && character !~ /[0-9]/)
444
+ attributes["end"] = attributes["num"]
445
+ attributes["num"] = 0
446
+ attributes["end_capture"] = false
447
+ end
448
+ if(attributes["end_capture"] == true && character =~ /[0-9]/)
449
+ if(character == "0") # |10+
450
+ if(attributes["num"] > 0)
451
+ attributes["num"] *= 10
452
+ end
453
+ elsif(character >= "1" && character <= "9") # |1+ through |9+
454
+ if(attributes["num"] > 0)
455
+ attributes["num"] *= 10
456
+ end
457
+ attributes["num"] += character.to_i
458
+ end
459
+ elsif(character == ")" && attributes["variable_capture"] == true && attributes["escape"] == false)
460
+ if(attributes["variable"] =~ /=/ && attributes["variable"][0] != "#") # Update
461
+ update_variable(attributes)
462
+ else # Display
463
+ emit_variable(new_text, attributes)
464
+ end
465
+ elsif(attributes["variable_capture"] == true)
466
+ if(character == "\\")
467
+ attributes["escape"] = true
468
+ else
469
+ if(attributes["escape"] == true)
470
+ attributes["variable"] << "\\#{character}"
471
+ attributes["escape"] = false
472
+ else
473
+ attributes["variable"] << character
474
+ end
475
+ end
476
+ elsif(attributes["center_capture"] == true)
477
+ if(character == "\\")
478
+ attributes["escape"] = true
479
+ else
480
+ if(attributes["escape"] == true)
481
+ attributes["center"] << "\\#{character}"
482
+ attributes["escape"] = false
483
+ elsif(character == "}")
484
+ emit_center(new_text, attributes)
485
+ else
486
+ attributes["center"] << character
487
+ end
488
+ end
489
+ elsif(attributes["right_capture"] == true)
490
+ if(character == "\\")
491
+ attributes["escape"] = true
492
+ else
493
+ if(attributes["escape"] == true)
494
+ attributes["right"] << "\\#{character}"
495
+ attributes["escape"] = false
496
+ if(character == "n")
497
+ emit_right(new_text, attributes)
498
+ end
499
+ elsif(character == "\n")
500
+ emit_right(new_text, attributes)
501
+ else
502
+ attributes["right"] << character
503
+ end
504
+ end
505
+ elsif(attributes["box_capture"] > 0)
506
+ if(attributes["box_attributes"][attributes["box_capture"]]["capture_attributes"] == true)
507
+ if(character == "]" && !open_expression(attributes["box_attributes"][attributes["box_capture"]]["attributes"]))
508
+ attributes["box_attributes"][attributes["box_capture"]]["capture_attributes"] = false
509
+ else
510
+ attributes["box_attributes"][attributes["box_capture"]]["attributes"] << character
511
+ end
512
+ elsif(character == "]" && (attributes["box_attributes"][attributes["box_capture"]]["capture"] =~ /\|\[\/box$/i ||
513
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] =~ /\|\[box end$/i))
514
+ attributes["box_attributes"][attributes["box_capture"]]["capture"].sub!(/\|\[box end$/i, "")
515
+ attributes["box_attributes"][attributes["box_capture"]]["capture"].sub!(/\|\[\/box$/i, "")
516
+ if(attributes["box_attributes"][attributes["box_capture"]]["parent"] == 0)
517
+ emit_box(new_text, attributes)
518
+ else
519
+ attributes["box_capture"] = attributes["box_attributes"][attributes["box_capture"]]["parent"]
520
+ end
521
+ # Start another box
522
+ elsif(character == "]" && attributes["box_attributes"][attributes["box_capture"]]["capture"] !~ /\|\[boxi/i &&
523
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] =~ /\|\[box(.*)?/mi)
524
+ capture_attributes = $1
525
+ parent = attributes["box_capture"]
526
+ attributes["box_attributes"][parent]["capture"].sub!(/\|\[box#{Regexp.escape(capture_attributes)}$/i, "")
527
+ attributes["boxes"] += 1
528
+ attributes["box_capture"] = attributes["boxes"]
529
+ attributes["box_attributes"][attributes["box_capture"]] = Hash.new
530
+ attributes["box_attributes"][attributes["box_capture"]]["parent"] = parent
531
+ attributes["box_attributes"][attributes["box_capture"]]["capture_attributes"] = false
532
+ attributes["box_attributes"][attributes["box_capture"]]["attributes"] = capture_attributes.lstrip
533
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] = String.new
534
+ else
535
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] << character
536
+ end
537
+ elsif(attributes["emoji_capture"] == true)
538
+ if(character == "]")
539
+ if(attributes["emoji"] =~ /^b$/)
540
+ new_text << "\a"
541
+ attributes["emoji"] = String.new
542
+ attributes["emoji_capture"] = false
543
+ elsif(attributes["emoji"] =~ /^([0-9]+)[,;]([0-9]+)$/)
544
+ if(attributes["shell_prompt"] == true)
545
+ new_text << "\\[\e[#{$1};#{$2}H\\]"
546
+ else
547
+ new_text << "\e[#{$1};#{$2}H"
548
+ end
549
+ attributes["emoji"] = String.new
550
+ attributes["emoji_capture"] = false
551
+ elsif(attributes["emoji"] =~ /^([0-9]+)s$/i) # Sleep in seconds
552
+ attributes["emoji"] = String.new
553
+ attributes["emoji_capture"] = false
554
+ sleep($1.to_i)
555
+ elsif(attributes["emoji"] =~ /^([0-9]+)ms$/i) # Sleep in milliseconds
556
+ attributes["emoji"] = String.new
557
+ attributes["emoji_capture"] = false
558
+ sleep($1.to_i / 1000.0)
559
+ elsif(attributes["emoji"] + character =~ /^box\]/i) # Box start
560
+ attributes["emoji"] = String.new
561
+ attributes["emoji_capture"] = false
562
+ attributes["box_capture"] = 1
563
+ attributes["boxes"] = 1
564
+ attributes["box_attributes"][attributes["box_capture"]] = Hash.new
565
+ attributes["box_attributes"][attributes["box_capture"]]["parent"] = 0
566
+ attributes["box_attributes"][attributes["box_capture"]]["capture_attributes"] = false
567
+ attributes["box_attributes"][attributes["box_capture"]]["attributes"] = String.new
568
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] = String.new
569
+ else
570
+ emit_emoji(new_text, attributes)
571
+ end
572
+ elsif(attributes["emoji"] + character =~ /^box /i) # Box start with attributes
573
+ attributes["emoji"] = String.new
574
+ attributes["emoji_capture"] = false
575
+ attributes["box_capture"] += 1
576
+ attributes["boxes"] += 1
577
+ attributes["box_attributes"][attributes["box_capture"]] = Hash.new
578
+ attributes["box_attributes"][attributes["box_capture"]]["parent"] = 0
579
+ attributes["box_attributes"][attributes["box_capture"]]["capture_attributes"] = true
580
+ attributes["box_attributes"][attributes["box_capture"]]["attributes"] = String.new
581
+ attributes["box_attributes"][attributes["box_capture"]]["capture"] = String.new
582
+ else
583
+ attributes["emoji"] << character
584
+ end
585
+ elsif(character == "|" && attributes["repeat_pattern"] == false)
586
+ process_pipe(character, new_text, attributes)
587
+ elsif(character == "~" && attributes["pipe"] == true &&
588
+ attributes["num"] > 0 && attributes["escape"] == false)
589
+ process_repeat_pattern(character, new_text, attributes)
590
+ elsif(attributes["repeat_pattern"] == true)
591
+ capture_character_pattern(character, attributes)
592
+ elsif(attributes["color_capture"] > 0 && character =~ /[0-9,A-F,a-f]/)
593
+ capture_color(character, new_text, attributes)
594
+ elsif(attributes["palette_capture"] > 0 && character =~ /[0-9,A-F,a-f]/)
595
+ capture_palette_color(character, new_text, attributes)
596
+ elsif(attributes["unicode_capture"] == 1 && character == "+") # Skip
597
+ return
598
+ elsif(attributes["unicode_capture"] > 0 && character =~ /[0-9,A-F,a-f]/)
599
+ capture_unicode(character, new_text, attributes)
600
+ elsif(attributes["pipe"] == true &&
601
+ attributes["repeat_pattern"] == false &&
602
+ attributes["escape"] == true)
603
+ process_escaped_character(character, new_text, attributes)
604
+ elsif(character == "&" && attributes["ampersand_mode"] == true &&
605
+ attributes["pipe"] == false)
606
+ process_ampersand(character, new_text, attributes)
607
+ elsif(attributes["pipe"] == true)
608
+ process_piped_character(character, new_text, attributes)
609
+ elsif(attributes["ampersand"] == true)
610
+ process_ampersanded_character(character, new_text, attributes)
611
+ elsif(attributes["box"] == 0)
612
+ new_text << process_box_zero_replace(character)
613
+ elsif(attributes["box"] == 1)
614
+ new_text << process_box_one_replace(character)
615
+ elsif(attributes["box"] == 2)
616
+ new_text << process_box_two_replace(character)
617
+ else
618
+ new_text << character
619
+ end
620
+ end
621
+
622
+ def emit_color(new_text, attributes)
623
+ r = attributes["r"].to_i(16).to_s
624
+ g = attributes["g"].to_i(16).to_s
625
+ b = attributes["b"].to_i(16).to_s
626
+ if(attributes["ampersand"] == true) # Background Color
627
+ if(attributes["shell_prompt"] == true)
628
+ new_text << "\\[\e[48;2;#{r};#{g};#{b}m\\]"
629
+ else
630
+ new_text << "\e[48;2;#{r};#{g};#{b}m"
631
+ end
632
+ attributes["bg"] = "\e[48;2;#{r};#{g};#{b}m"
633
+ new_text << attributes["fg"] == "\e[0m" ? "" : attributes["fg"]
634
+ attributes["ampersand"] = false
635
+ else # Foreground Color
636
+ if(attributes["shell_prompt"] == true)
637
+ new_text << "\\[\e[38;2;#{r};#{g};#{b}m\\]"
638
+ else
639
+ new_text << "\e[38;2;#{r};#{g};#{b}m"
640
+ end
641
+ attributes["fg"] = "\e[38;2;#{r};#{g};#{b}m"
642
+ new_text << attributes["bg"] == "\e[0m" ? "" : attributes["bg"]
643
+ end
644
+ attributes["color_capture"] = 0
645
+ attributes["r"] = String.new
646
+ attributes["g"] = String.new
647
+ attributes["b"] = String.new
648
+ end
649
+
650
+ def emit_palette_color(new_text, attributes)
651
+ p = attributes["p"].to_i(16).to_s
652
+ if(attributes["ampersand"] == true) # Background Color
653
+ if(attributes["shell_prompt"] == true)
654
+ new_text << "\\[\e[48;5;#{p}m\\]"
655
+ else
656
+ new_text << "\e[48;5;#{p}m"
657
+ end
658
+ attributes["ampersand"] = false
659
+ else # Foreground Color
660
+ if(attributes["shell_prompt"] == true)
661
+ new_text << "\\[\e[38;5;#{p}m\\]"
662
+ else
663
+ new_text << "\e[38;5;#{p}m"
664
+ end
665
+ end
666
+ attributes["palette_capture"] = 0
667
+ attributes["p"] = String.new
668
+ end
669
+
670
+ def emit_unicode(new_text, attributes)
671
+ new_text << [attributes["unicode"].to_i(16)].pack("U*")
672
+ attributes["unicode_capture"] = 0
673
+ attributes["unicode"] = String.new
674
+ end
675
+
676
+ def open_expression(text)
677
+ if(text.count("\"") % 2 == 1)
678
+ return true
679
+ elsif(text.count("'") % 2 == 1)
680
+ return true
681
+ elsif(text.count("[") > text.count("]") + 1)
682
+ return true
683
+ end
684
+ return false
685
+ end
686
+
687
+ def number?(text)
688
+ text.chars.each do |character|
689
+ if(character !~ /[0-9 ]/)
690
+ return false
691
+ end
692
+ end
693
+ return true
694
+ end
695
+
696
+ def update_variable(attributes)
697
+ if(attributes["variable"] =~ /(.*)\-=(.*)/)
698
+ if(!number?($2) || !number?(attributes["variables"][$1]))
699
+ attributes["variables"][$1].slice!($2)
700
+ elsif(attributes["variable"] =~ /(.*) \-= ?(.*)/ || attributes["variable"] =~ /(.*)\-= ?(.*)/)
701
+ value = attributes["variables"][$1].to_i - $2.to_i
702
+ attributes["variables"][$1] = value.to_s
703
+ end
704
+ elsif(attributes["variable"] =~ /(.*)\+=(.*)/)
705
+ if(!number?($2) || !number?(attributes["variables"][$1]))
706
+ attributes["variables"][$1] += $2
707
+ elsif(attributes["variable"] =~ /(.*) \+= ?(.*)/ || attributes["variable"] =~ /(.*)\+= ?(.*)/)
708
+ value = attributes["variables"][$1].to_i + $2.to_i
709
+ attributes["variables"][$1] = value.to_s
710
+ end
711
+ elsif(attributes["variable"] =~ /(.*) \*= ?(.*)/ || attributes["variable"] =~ /(.*)\*= ?(.*)/)
712
+ value = attributes["variables"][$1].to_i * $2.to_i
713
+ attributes["variables"][$1] = value.to_s
714
+ elsif(attributes["variable"] =~ /(.*) \/= ?(.*)/ || attributes["variable"] =~ /(.*)\/= ?(.*)/)
715
+ value = attributes["variables"][$1].to_i / $2.to_i
716
+ attributes["variables"][$1] = value.to_s
717
+ elsif(attributes["variable"] =~ /(.*) = ?(.*)/ || attributes["variable"] =~ /(.*)= ?(.*)/)
718
+ attributes["variables"][$1] = $2
719
+ end
720
+ attributes["variable_capture"] = false
721
+ attributes["variable"] = String.new
722
+ end
723
+
724
+ def emit_variable(new_text, attributes)
725
+ if(attributes["variable"][0] == "#") # We are manipulating attributes["num"]
726
+ if(attributes["variable"][1..-1] =~ /(.*) \-= ?(.*)/ ||
727
+ attributes["variable"][1..-1] =~ /(.*)\-= ?(.*)/)
728
+ attributes["num"] = pipetext(escape_fix(attributes["variables"][$1]), attributes["box_mode"],
729
+ attributes["ampersand_mode"]).to_i - $2.to_i
730
+ elsif(attributes["variable"][1..-1] =~ /(.*) \+= ?(.*)/ ||
731
+ attributes["variable"][1..-1] =~ /(.*)\+= ?(.*)/)
732
+ attributes["num"] = pipetext(escape_fix(attributes["variables"][$1]), attributes["box_mode"],
733
+ attributes["ampersand_mode"]).to_i + $2.to_i
734
+ elsif(attributes["variable"][1..-1] =~ /(.*) \*= ?(.*)/ ||
735
+ attributes["variable"][1..-1] =~ /(.*)\*= ?(.*)/)
736
+ attributes["num"] = pipetext(escape_fix(attributes["variables"][$1]), attributes["box_mode"],
737
+ attributes["ampersand_mode"]).to_i * $2.to_i
738
+ elsif(attributes["variable"][1..-1] =~ /(.*) \/= ?(.*)/ ||
739
+ attributes["variable"][1..-1] =~ /(.*)\/= ?(.*)/)
740
+ attributes["num"] = pipetext(escape_fix(attributes["variables"][$1]), attributes["box_mode"],
741
+ attributes["ampersand_mode"]).to_i / $2.to_i
742
+ else
743
+ attributes["num"] = pipetext(escape_fix(attributes["variables"][attributes["variable"][1..-1]]),
744
+ attributes["box_mode"], attributes["ampersand_mode"]).to_i
745
+ end
746
+ attributes["pipe"] = true
747
+ attributes["found"] = false
748
+ elsif(attributes["variables"][attributes["variable"]])
749
+ new_text << pipetext(escape_fix(attributes["variables"][attributes["variable"]]),
750
+ attributes["box_mode"], attributes["ampersand_mode"])
751
+ else
752
+ new_text << "|(" + attributes["variable"] + ")"
753
+ end
754
+ attributes["variable_capture"] = false
755
+ attributes["variable"] = String.new
756
+ end
757
+
758
+ def emit_center(new_text, attributes)
759
+ text = pipetext(attributes["center"], attributes["box_mode"], attributes["ampersand_mode"])
760
+ length = printable_length(text)
761
+ spaces = attributes["end"] - attributes["position"] - length
762
+ if(length % 2)
763
+ spaces += 1
764
+ end
765
+ if(spaces > 0)
766
+ spaces /= 2
767
+ spaces.times do
768
+ new_text << " "
769
+ end
770
+ end
771
+ new_text << text
772
+ attributes["center_capture"] = false
773
+ attributes["center"] = String.new
774
+ end
775
+
776
+ def emit_right(new_text, attributes)
777
+ text = pipetext(attributes["right"], attributes["box_mode"], attributes["ampersand_mode"])
778
+ length = printable_length(text)
779
+ spaces = attributes["end"] - attributes["position"] - length
780
+ if(spaces > 0)
781
+ spaces.times do
782
+ new_text << " "
783
+ end
784
+ end
785
+ new_text << text
786
+ attributes["right_capture"] = false
787
+ attributes["right"] = String.new
788
+ end
789
+
790
+ def set_box_symbols(box_symbol, border_mode)
791
+ if(border_mode == 1)
792
+ box_symbol[:horizontal] = "─"
793
+ box_symbol[:vertical] = "│"
794
+ box_symbol[:top_left] = "╭"
795
+ box_symbol[:top_right] = "╮"
796
+ box_symbol[:bottom_left] = "╰"
797
+ box_symbol[:bottom_right] = "╯"
798
+ box_symbol[:t_top] = "┬"
799
+ box_symbol[:t_bottom] = "┴"
800
+ box_symbol[:t_left] = "├"
801
+ box_symbol[:t_right] = "┤"
802
+ box_symbol[:cross] = "┼"
803
+ elsif(border_mode == 2)
804
+ box_symbol[:horizontal] = "═"
805
+ box_symbol[:vertical] = "║"
806
+ box_symbol[:top_left] = "╔"
807
+ box_symbol[:top_right] = "╗"
808
+ box_symbol[:bottom_left] = "╚"
809
+ box_symbol[:bottom_right] = "╝"
810
+ box_symbol[:t_top] = "╦"
811
+ box_symbol[:t_bottom] = "╩"
812
+ box_symbol[:t_left] = "╠"
813
+ box_symbol[:t_right] = "╣"
814
+ box_symbol[:cross] = "╬"
815
+ elsif(border_mode == 3)
816
+ box_symbol[:horizontal] = "─"
817
+ box_symbol[:vertical] = "│"
818
+ box_symbol[:top_left] = "┌"
819
+ box_symbol[:top_right] = "┐"
820
+ box_symbol[:bottom_left] = "└"
821
+ box_symbol[:bottom_right] = "┘"
822
+ box_symbol[:t_top] = "┬"
823
+ box_symbol[:t_bottom] = "┴"
824
+ box_symbol[:t_left] = "├"
825
+ box_symbol[:t_right] = "┤"
826
+ box_symbol[:cross] = "┼"
827
+ elsif(border_mode == 4)
828
+ box_symbol[:horizontal] = "━"
829
+ box_symbol[:vertical] = "┃"
830
+ box_symbol[:top_left] = "┏"
831
+ box_symbol[:top_right] = "┓"
832
+ box_symbol[:bottom_left] = "┗"
833
+ box_symbol[:bottom_right] = "┛"
834
+ box_symbol[:t_top] = "┳"
835
+ box_symbol[:t_bottom] = "┻"
836
+ box_symbol[:t_left] = "┣"
837
+ box_symbol[:t_right] = "┫"
838
+ box_symbol[:cross] = "╋"
839
+ elsif(border_mode == 5)
840
+ box_symbol[:horizontal] = "─"
841
+ box_symbol[:vertical] = "┃"
842
+ box_symbol[:top_left] = "┍"
843
+ box_symbol[:top_right] = "┑"
844
+ box_symbol[:bottom_left] = "└"
845
+ box_symbol[:bottom_right] = "┘"
846
+ box_symbol[:t_top] = "┯"
847
+ box_symbol[:t_bottom] = "┷"
848
+ box_symbol[:t_left] = "┝"
849
+ box_symbol[:t_right] = "┥"
850
+ box_symbol[:cross] = "┿"
851
+ elsif(border_mode == 6)
852
+ box_symbol[:horizontal] = "━"
853
+ box_symbol[:vertical] = "│"
854
+ box_symbol[:top_left] = "┎"
855
+ box_symbol[:top_right] = "┒"
856
+ box_symbol[:bottom_left] = "┖"
857
+ box_symbol[:bottom_right] = "┚"
858
+ box_symbol[:t_top] = "┰"
859
+ box_symbol[:t_bottom] = "┸"
860
+ box_symbol[:t_left] = "┠"
861
+ box_symbol[:t_right] = "┨"
862
+ box_symbol[:cross] = "╂"
863
+ elsif(border_mode == 7)
864
+ box_symbol[:horizontal] = "═"
865
+ box_symbol[:vertical] = "│"
866
+ box_symbol[:top_left] = "╒"
867
+ box_symbol[:top_right] = "╕"
868
+ box_symbol[:bottom_left] = "╘"
869
+ box_symbol[:bottom_right] = "╛"
870
+ box_symbol[:t_top] = "╤"
871
+ box_symbol[:t_bottom] = "╧"
872
+ box_symbol[:t_left] = "╞"
873
+ box_symbol[:t_right] = "╡"
874
+ box_symbol[:cross] = "╪"
875
+ elsif(border_mode == 8)
876
+ box_symbol[:horizontal] = "─"
877
+ box_symbol[:vertical] = "║"
878
+ box_symbol[:top_left] = "╓"
879
+ box_symbol[:top_right] = "╖"
880
+ box_symbol[:bottom_left] = "╙"
881
+ box_symbol[:bottom_right] = "╜"
882
+ box_symbol[:t_top] = "╥"
883
+ box_symbol[:t_bottom] = "╨"
884
+ box_symbol[:t_left] = "╟"
885
+ box_symbol[:t_right] = "╢"
886
+ box_symbol[:cross] = "╫"
887
+ elsif(border_mode == 9)
888
+ box_symbol[:horizontal] = "┄"
889
+ box_symbol[:vertical] = "┆"
890
+ box_symbol[:top_left] = "○"
891
+ box_symbol[:top_right] = "○"
892
+ box_symbol[:bottom_left] = "○"
893
+ box_symbol[:bottom_right] = "○"
894
+ box_symbol[:t_top] = "⊹"
895
+ box_symbol[:t_bottom] = "⊹"
896
+ box_symbol[:t_left] = "⊹"
897
+ box_symbol[:t_right] = "⊹"
898
+ box_symbol[:cross] = "⊹"
899
+ elsif(border_mode == 10)
900
+ box_symbol[:horizontal] = "✨"
901
+ box_symbol[:vertical] = "✨"
902
+ box_symbol[:top_left] = "🌸"
903
+ box_symbol[:top_right] = "🌸"
904
+ box_symbol[:bottom_left] = "🌸"
905
+ box_symbol[:bottom_right] = "🌸"
906
+ box_symbol[:t_top] = "⭐"
907
+ box_symbol[:t_bottom] = "⭐"
908
+ box_symbol[:t_left] = "⭐"
909
+ box_symbol[:t_right] = "⭐"
910
+ box_symbol[:cross] = "🌟"
911
+ elsif(border_mode == 11)
912
+ box_symbol[:horizontal] = "░"
913
+ box_symbol[:vertical] = "▒"
914
+ box_symbol[:top_left] = "▓"
915
+ box_symbol[:top_right] = "▓"
916
+ box_symbol[:bottom_left] = "▓"
917
+ box_symbol[:bottom_right] = "▓"
918
+ box_symbol[:t_top] = "▒"
919
+ box_symbol[:t_bottom] = "▒"
920
+ box_symbol[:t_left] = "▒"
921
+ box_symbol[:t_right] = "▒"
922
+ box_symbol[:cross] = "▓"
923
+ elsif(border_mode == 12)
924
+ box_symbol[:horizontal] = "⚜️"
925
+ box_symbol[:vertical] = "⚜️"
926
+ box_symbol[:top_left] = "💎"
927
+ box_symbol[:top_right] = "💎"
928
+ box_symbol[:bottom_left] = "💎"
929
+ box_symbol[:bottom_right] = "💎"
930
+ box_symbol[:t_top] = "👑"
931
+ box_symbol[:t_bottom] = "👑"
932
+ box_symbol[:t_left] = "👑"
933
+ box_symbol[:t_right] = "👑"
934
+ box_symbol[:cross] = "⚜️"
935
+ elsif(border_mode == 13)
936
+ box_symbol[:horizontal] = "🌿"
937
+ box_symbol[:vertical] = "🌿"
938
+ box_symbol[:top_left] = "🍃"
939
+ box_symbol[:top_right] = "🍃"
940
+ box_symbol[:bottom_left] = "🍂"
941
+ box_symbol[:bottom_right] = "🍂"
942
+ box_symbol[:t_top] = "🌻"
943
+ box_symbol[:t_bottom] = "🌻"
944
+ box_symbol[:t_left] = "🌻"
945
+ box_symbol[:t_right] = "🌻"
946
+ box_symbol[:cross] = "🌳"
947
+ elsif(border_mode == 14)
948
+ box_symbol[:horizontal] = "⚠️"
949
+ box_symbol[:vertical] = "⚠️"
950
+ box_symbol[:top_left] = "🚨"
951
+ box_symbol[:top_right] = "🚨"
952
+ box_symbol[:bottom_left] = "🚨"
953
+ box_symbol[:bottom_right] = "🚨"
954
+ box_symbol[:t_top] = "⛔"
955
+ box_symbol[:t_bottom] = "⛔"
956
+ box_symbol[:t_left] = "⛔"
957
+ box_symbol[:t_right] = "⛔"
958
+ box_symbol[:cross] = "🧨"
959
+ elsif(border_mode == 15)
960
+ box_symbol[:horizontal] = "✨"
961
+ box_symbol[:vertical] = "✨"
962
+ box_symbol[:top_left] = "☄️"
963
+ box_symbol[:top_right] = "☄️"
964
+ box_symbol[:bottom_left] = "☄️"
965
+ box_symbol[:bottom_right] = "☄️"
966
+ box_symbol[:t_top] = "🌙"
967
+ box_symbol[:t_bottom] = "🌙"
968
+ box_symbol[:t_left] = "🌙"
969
+ box_symbol[:t_right] = "🌙"
970
+ box_symbol[:cross] = "☀️"
971
+ elsif(border_mode == 16)
972
+ box_symbol[:horizontal] = "†"
973
+ box_symbol[:vertical] = "‡"
974
+ box_symbol[:top_left] = "⛧"
975
+ box_symbol[:top_right] = "⛧"
976
+ box_symbol[:bottom_left] = "⛧"
977
+ box_symbol[:bottom_right] = "⛧"
978
+ box_symbol[:t_top] = "♱"
979
+ box_symbol[:t_bottom] = "♱"
980
+ box_symbol[:t_left] = "♱"
981
+ box_symbol[:t_right] = "♱"
982
+ box_symbol[:cross] = "☨"
983
+ elsif(border_mode == 17)
984
+ box_symbol[:horizontal] = "🔥"
985
+ box_symbol[:vertical] = "🔥"
986
+ box_symbol[:top_left] = "💥"
987
+ box_symbol[:top_right] = "💥"
988
+ box_symbol[:bottom_left] = "💥"
989
+ box_symbol[:bottom_right] = "💥"
990
+ box_symbol[:t_top] = "☀️"
991
+ box_symbol[:t_bottom] = "☀️"
992
+ box_symbol[:t_left] = "☀️"
993
+ box_symbol[:t_right] = "☀️"
994
+ box_symbol[:cross] = "🌋"
995
+ elsif(border_mode == 18)
996
+ box_symbol[:horizontal] = "〓"
997
+ box_symbol[:vertical] = "〓"
998
+ box_symbol[:top_left] = "⬜"
999
+ box_symbol[:top_right] = "⬜"
1000
+ box_symbol[:bottom_left] = "⬜"
1001
+ box_symbol[:bottom_right] = "⬜"
1002
+ box_symbol[:t_top] = "◽"
1003
+ box_symbol[:t_bottom] = "◽"
1004
+ box_symbol[:t_left] = "◽"
1005
+ box_symbol[:t_right] = "◽"
1006
+ box_symbol[:cross] = "◻️"
1007
+ elsif(border_mode == 19)
1008
+ box_symbol[:horizontal] = "〰️"
1009
+ box_symbol[:vertical] = "⌇"
1010
+ box_symbol[:top_left] = "📜"
1011
+ box_symbol[:top_right] = "📜"
1012
+ box_symbol[:bottom_left] = "📜"
1013
+ box_symbol[:bottom_right] = "📜"
1014
+ box_symbol[:t_top] = "🏺"
1015
+ box_symbol[:t_bottom] = "🏺"
1016
+ box_symbol[:t_left] = "🏺"
1017
+ box_symbol[:t_right] = "🏺"
1018
+ box_symbol[:cross] = "🗝️"
1019
+ elsif(border_mode == 20)
1020
+ box_symbol[:horizontal] = "≈"
1021
+ box_symbol[:vertical] = "≋"
1022
+ box_symbol[:top_left] = "🐚"
1023
+ box_symbol[:top_right] = "🐚"
1024
+ box_symbol[:bottom_left] = "🐚"
1025
+ box_symbol[:bottom_right] = "🐚"
1026
+ box_symbol[:t_top] = "🌊"
1027
+ box_symbol[:t_bottom] = "🌊"
1028
+ box_symbol[:t_left] = "🌊"
1029
+ box_symbol[:t_right] = "🌊"
1030
+ box_symbol[:cross] = "⚓"
1031
+ elsif(border_mode == 21)
1032
+ box_symbol[:horizontal] = "💕"
1033
+ box_symbol[:vertical] = "💕"
1034
+ box_symbol[:top_left] = "💖"
1035
+ box_symbol[:top_right] = "💖"
1036
+ box_symbol[:bottom_left] = "💖"
1037
+ box_symbol[:bottom_right] = "💖"
1038
+ box_symbol[:t_top] = "💗"
1039
+ box_symbol[:t_bottom] = "💗"
1040
+ box_symbol[:t_left] = "💗"
1041
+ box_symbol[:t_right] = "💗"
1042
+ box_symbol[:cross] = "❤️"
1043
+ else
1044
+ box_symbol[:horizontal] = "-"
1045
+ box_symbol[:vertical] = "|"
1046
+ box_symbol[:top_left] = "["
1047
+ box_symbol[:top_right] = "]"
1048
+ box_symbol[:bottom_left] = "["
1049
+ box_symbol[:bottom_right] = "]"
1050
+ box_symbol[:t_top] = "+"
1051
+ box_symbol[:t_bottom] = "+"
1052
+ box_symbol[:t_left] = "+"
1053
+ box_symbol[:t_right] = "+"
1054
+ box_symbol[:cross] = "+"
1055
+ end
1056
+ end
1057
+
1058
+ def wide_border_mode(border_mode)
1059
+ scratch = Hash.new
1060
+ set_box_symbols(scratch, border_mode)
1061
+ if(double_wide_character(scratch[:horizontal]))
1062
+ return true
1063
+ end
1064
+ return false
1065
+ end
1066
+
1067
+ def max_line_length(line, max)
1068
+ if(line =~ /^(.*)\|\\n(.*)$/m || line =~ /^([^\n]*)\n(.*)$/m)
1069
+ if($1 != nil)
1070
+ length = printable_length($1)
1071
+ if(length > max)
1072
+ max = length
1073
+ end
1074
+ end
1075
+ return max_line_length($2, max)
1076
+ elsif(line != nil)
1077
+ length = printable_length(line)
1078
+ if(length > max)
1079
+ max = length
1080
+ end
1081
+ end
1082
+ return max
1083
+ end
1084
+
1085
+ def max_line_count(line, count)
1086
+ if(line =~ /^(.*)\|\\n(.*)$/)
1087
+ if($1 =~ /\n/)
1088
+ count += $1.count("\n")
1089
+ else
1090
+ count += 1
1091
+ end
1092
+ return max_line_count($2, count)
1093
+ elsif(line != nil)
1094
+ if(line =~ /\n/)
1095
+ count += line.count("\n")
1096
+ else
1097
+ count += 1
1098
+ end
1099
+ else
1100
+ count += 1
1101
+ end
1102
+ return count
1103
+ end
1104
+
1105
+ def update_box_attributes(attributes)
1106
+ min_height = 0
1107
+ min_width = 0
1108
+ 1.upto(attributes["boxes"]) do |box_num|
1109
+ box = attributes["box_attributes"][box_num]
1110
+ if(box["attributes"] =~ /grow/i)
1111
+ box["grow"] = true
1112
+ else
1113
+ box["grow"] = false
1114
+ end
1115
+ if(box["attributes"] =~ /(?<!inside|outside )border background color *[=:]? ([^ ,;\]]*)/i ||
1116
+ box["attributes"] =~ /(?<!inside|outside )border bg color *[=:]? ([^ ,;\]]*)/i ||
1117
+ box["attributes"] =~ /(?<!inside|outside )border bg *[=:]? ([^ ,;\]]*)/i)
1118
+ box["border_background_color"] = pipetext($1, true, true)
1119
+ else
1120
+ box["border_background_color"] = pipetext("&n", true, true)
1121
+ end
1122
+ if(box["attributes"] =~ /inside border background color *[=:]? ([^ ,;\]]*)/i ||
1123
+ box["attributes"] =~ /inside border bg color *[=:]? ([^ ,;\]]*)/i ||
1124
+ box["attributes"] =~ /inside border bg *[=:]? ([^ ,;\]]*)/i ||
1125
+ box["attributes"] =~ /padding bg color *[=:]? ([^ ,;\]]*)/i ||
1126
+ box["attributes"] =~ /padding color *[=:]? ([^ ,;\]]*)/i ||
1127
+ box["attributes"] =~ /padding bg *[=:]? ([^ ,;\]]*)/i)
1128
+ box["inside_border_background_color"] = pipetext($1, true, true)
1129
+ else
1130
+ box["inside_border_background_color"] = box["border_background_color"]
1131
+ end
1132
+ if(box["attributes"] =~ /outside (?:border )background color *[=:]? ([^ ,;\]]*)/i ||
1133
+ box["attributes"] =~ /outside (?:border )bg color *[=:]? ([^ ,;\]]*)/i ||
1134
+ box["attributes"] =~ /outside (?:border )bg *[=:]? ([^ ,;\]]*)/i ||
1135
+ box["attributes"] =~ /margin bg color *[=:]? ([^ ,;\]]*)/i ||
1136
+ box["attributes"] =~ /margin color *[=:]? ([^ ,;\]]*)/i ||
1137
+ box["attributes"] =~ /margin bg *[=:]? ([^ ,;\]]*)/i)
1138
+ box["outside_border_background_color"] = pipetext($1, true, true)
1139
+ else
1140
+ box["outside_border_background_color"] = box["border_background_color"]
1141
+ end
1142
+ if(box["attributes"] =~ /(?<!border )background color *[=:]? ([^ ,;\]]*)/i ||
1143
+ box["attributes"] =~ /(?<!border )bg color *[=:]? ([^ ,;\]]*)/i ||
1144
+ box["attributes"] =~ /(?<!border )bg *[=:]? ([^ ,;\]]*)/i)
1145
+ box["bg_pipe_color"] = $1
1146
+ else
1147
+ box["bg_pipe_color"] = "&n"
1148
+ end
1149
+ box["background_color"] = pipetext(box["bg_pipe_color"], true, true)
1150
+ if(box["attributes"] =~ /border foreground color *[=:]? ([^ ,;\]]*)/i ||
1151
+ box["attributes"] =~ /border fg color *[=:]? ([^ ,;\]]*)/i ||
1152
+ box["attributes"] =~ /border fg *[=:]? ([^ ,;\]]*)/i)
1153
+ box["border_foreground_color"] = pipetext($1, true, true)
1154
+ else
1155
+ box["border_foreground_color"] = pipetext("|n", true, true)
1156
+ end
1157
+ if(box["attributes"] =~ /(?<!border )foreground color *[=:]? ([^ ,;\]]*)/i ||
1158
+ box["attributes"] =~ /(?<!border )fg color *[=:]? ([^ ,;\]]*)/i ||
1159
+ box["attributes"] =~ /(?<!border )fg *[=:]? ([^ ,;\]]*)/i)
1160
+ box["fg_pipe_color"] = $1
1161
+ else
1162
+ box["fg_pipe_color"] = "|n"
1163
+ end
1164
+ box["foreground_color"] = pipetext(box["fg_pipe_color"], true, true)
1165
+ if(box["attributes"] =~ /inside (?:border )*[=:]? *([0-9]+)/i ||
1166
+ box["attributes"] =~ /padding *[=:]? *([0-9]+)/i)
1167
+ box["inside_border"] = $1.to_i
1168
+ else
1169
+ box["inside_border"] = 0
1170
+ end
1171
+ if(box["attributes"] =~ /outside (?:border )*[=:]? *([0-9]+)/i ||
1172
+ box["attributes"] =~ /margin *[=:]? *([0-9]+)/i)
1173
+ box["outside_border"] = $1.to_i
1174
+ else
1175
+ box["outside_border"] = 0
1176
+ end
1177
+ if(box["attributes"] =~ /(?<!side )border mode *[=:]? *([\-0-9]+)/i ||
1178
+ box["attributes"] =~ /(?<!side )border *[=:]? *([\-0-9]+)/i ||
1179
+ box["attributes"] =~ /mode *[=:]? *([\-0-9]+)/i)
1180
+ box["border_mode"] = $1.to_i
1181
+ elsif(box["attributes"] =~ /mode *[=:]? *off/i)
1182
+ box["border_mode"] = -1
1183
+ else
1184
+ box["border_mode"] = 1
1185
+ end
1186
+ if(box["attributes"] =~ /title *[=:]? \"(.*)\"/i)
1187
+ box["title"] = $1
1188
+ elsif(box["attributes"] =~ /title *[=:]? '(.*)'/i)
1189
+ box["title"] = $1
1190
+ else
1191
+ box["title"] = String.new
1192
+ end
1193
+ if(box["attributes"] =~ /height *[=:]? *max/i)
1194
+ box["height"], _ = IO.console.winsize
1195
+ elsif(box["attributes"] =~ /height *[=:]? *([0-9]+)/i)
1196
+ box["height"] = $1.to_i
1197
+ if(box["grow"] == true && box["parent"] == 0)
1198
+ box["height"], _ = IO.console.winsize
1199
+ end
1200
+ else
1201
+ box["height"] = 0
1202
+ if(box["capture"] != "")
1203
+ box["capture"].lines.each do |line|
1204
+ box["height"] = max_line_count(pipetext(line, attributes["box_mode"],
1205
+ attributes["ampersand_mode"]), box["height"])
1206
+ end
1207
+ end
1208
+ if(box["title"] != "")
1209
+ box["height"] = max_line_count(pipetext(box["title"], attributes["box_mode"],
1210
+ attributes["ampersand_mode"]), box["height"])
1211
+ box["height"] += 1
1212
+ end
1213
+ if(box["border_mode"] > 0)
1214
+ box["height"] += 2
1215
+ end
1216
+ if(box["inside_border"] > 0)
1217
+ box["height"] += (box["inside_border"] * 2)
1218
+ end
1219
+ if(box["outside_border"] > 0)
1220
+ box["height"] += (box["outside_border"] * 2)
1221
+ end
1222
+ end
1223
+ if(box["height"] < 2)
1224
+ box["height"] = 2
1225
+ end
1226
+ if(box["attributes"] =~ /width *[=:]? *max/i)
1227
+ _, box["width"] = IO.console.winsize
1228
+ elsif(box["attributes"] =~ /width *[=:]? *([0-9]+)/i)
1229
+ box["width"] = $1.to_i
1230
+ if(box["grow"] == true && box["parent"] == 0)
1231
+ _, box["width"] = IO.console.winsize
1232
+ end
1233
+ else
1234
+ box["width"] = 0
1235
+ if(box["capture"] != "")
1236
+ width = 0
1237
+ box_num = attributes["box_capture"]
1238
+ attributes["box_capture"] = 0
1239
+ box["capture"].lines.each do |line|
1240
+ box["width"] = max_line_length(pipe(line, attributes), box["width"])
1241
+ end
1242
+ attributes["box_capture"] = box_num
1243
+ end
1244
+ if(box["title"] != "")
1245
+ box_num = attributes["box_capture"]
1246
+ attributes["box_capture"] = 0
1247
+ box["width"] = max_line_length(pipe(box["title"], attributes), box["width"])
1248
+ attributes["box_capture"] = box_num
1249
+ end
1250
+ if(box["border_mode"] > 0)
1251
+ box["width"] += 2
1252
+ if(wide_border_mode(box["border_mode"]) == true)
1253
+ box["width"] += 2
1254
+ end
1255
+ end
1256
+ if(box["inside_border"] > 0)
1257
+ box["width"] += (box["inside_border"] * 2)
1258
+ end
1259
+ if(box["outside_border"] > 0)
1260
+ box["width"] += (box["outside_border"] * 2)
1261
+ end
1262
+ end
1263
+ if(box["width"] < 4 && wide_border_mode(box["border_mode"]) == true)
1264
+ box["width"] = 4
1265
+ elsif(box["width"] < 2)
1266
+ box["width"] = 2
1267
+ end
1268
+ if(box["attributes"] =~ /layout *[=:]? *horizontal/i)
1269
+ box["layout"] = "horizontal"
1270
+ else
1271
+ box["layout"] = "vertical"
1272
+ end
1273
+ if(box["attributes"] =~ /clip/i)
1274
+ box["clip_children"] = true
1275
+ else
1276
+ box["clip_children"] = false
1277
+ end
1278
+ end
1279
+ end
1280
+
1281
+ def box_set(x, y, symbol, background=nil, foreground=nil)
1282
+ @drawing[[x, y]] = { "symbol" => symbol, "bg" => background, "fg" => foreground }
1283
+ @bounds["min_x"] = [@bounds["min_x"], x].min
1284
+ @bounds["max_x"] = [@bounds["max_x"], x].max
1285
+ @bounds["min_y"] = [@bounds["min_y"], y].min
1286
+ @bounds["max_y"] = [@bounds["max_y"], y].max
1287
+ end
1288
+
1289
+ def process_box_line(text_x, text_y, bg_color, fg_color, line)
1290
+ escape = false
1291
+ bracket = false
1292
+ join = false
1293
+ collect = String.new
1294
+ line.each_char do |character|
1295
+ if(character == "\e")
1296
+ escape = true
1297
+ collect << "\e"
1298
+ elsif(escape == true && bracket == false && character == "[")
1299
+ bracket = true
1300
+ collect << "["
1301
+ elsif(escape == true)
1302
+ collect << character
1303
+ if(character >= "@" && character <= "~")
1304
+ escape = false
1305
+ bracket = false
1306
+ end
1307
+ elsif(character[0].ord == 8205)
1308
+ join = true
1309
+ @drawing[[text_x - 1, text_y]]["symbol"] << character
1310
+ elsif(character[0].ord == 65039)
1311
+ @drawing[[text_x - 1, text_y]]["symbol"] << character
1312
+ if(@drawing[[text_x, text_y]]["symbol"] == " ")
1313
+ @drawing[[text_x, text_y]]["symbol"] = ""
1314
+ end
1315
+ elsif(character[0].ord >= 917602 && character[0].ord <= 917631)
1316
+ @drawing[[text_x - 1, text_y]]["symbol"] << character
1317
+ elsif(character[0].ord >= 127462 && character[0].ord <= 127487 &&
1318
+ @drawing[[text_x - 1, text_y]]["symbol"][-1].ord >= 127462 &&
1319
+ @drawing[[text_x - 1, text_y]]["symbol"][-1].ord <= 127487 &&
1320
+ (@drawing[[text_x - 1, text_y]]["symbol"][-2] == nil ||
1321
+ @drawing[[text_x - 1, text_y]]["symbol"][-2].ord < 127462 ||
1322
+ @drawing[[text_x - 1, text_y]]["symbol"][-2].ord > 127487))
1323
+ @drawing[[text_x - 1, text_y]]["symbol"] << character
1324
+ elsif(join == true)
1325
+ @drawing[[text_x - 1, text_y]]["symbol"] << character
1326
+ join = false
1327
+ else
1328
+ box_set(text_x, text_y, collect + character, bg_color, fg_color)
1329
+ collect = String.new
1330
+ text_x += 1
1331
+ end
1332
+ end
1333
+ end
1334
+
1335
+ def set_box_lines(text_x, text_y, bg_color, fg_color, line, max_height)
1336
+ if(text_y > max_height)
1337
+ return max_height
1338
+ end
1339
+ if(line == nil)
1340
+ return text_y
1341
+ elsif(line =~ /^(.*)|\\n(.*)$/)
1342
+ line1 = $1
1343
+ line2 = $2
1344
+ if(line1 != nil)
1345
+ process_box_line(text_x, text_y, bg_color, fg_color, line1)
1346
+ text_y += 1
1347
+ end
1348
+ if(line2 == nil)
1349
+ return text_y
1350
+ end
1351
+ return set_box_lines(text_x, text_y, bg_color, fg_color, line2, max_height)
1352
+ else
1353
+ if(line != nil)
1354
+ process_box_line(text_x, text_y, bg_color, fg_color, line)
1355
+ text_y += 1
1356
+ end
1357
+ end
1358
+ return text_y
1359
+ end
1360
+
1361
+ def draw_box_outside_border(attributes, box, x, y, width, height)
1362
+ border_size = box["outside_border"]
1363
+ if(border_size > 0)
1364
+ horizontal_range = (x...x + width)
1365
+ vertical_range = (y...y + height)
1366
+ vertical_range.each do |row|
1367
+ horizontal_range.each do |column|
1368
+ if(column >= attributes["box_attributes"][1]["width"] - 1 ||
1369
+ (row >= attributes["box_attributes"][1]["height"] - 1 && column == x + width - 1))
1370
+ box_set(column + 1, row, " ", "\e[49m", "\e[39m")
1371
+ end
1372
+ location = @drawing[[x - 1, row]]
1373
+ if(location != nil && double_wide_character(location["symbol"]))
1374
+ location["symbol"] = " "
1375
+ end
1376
+ if(row <= y + border_size || row >= y + height - border_size - 1 ||
1377
+ column <= x + border_size || column >= x + width - border_size - 1)
1378
+ box_set(column, row, " ", box["outside_border_background_color"], box["foreground_color"])
1379
+ end
1380
+ end
1381
+ end
1382
+ end
1383
+ end
1384
+
1385
+ def draw_box_frame(box, x, y, width, height)
1386
+ title_height = 0
1387
+ box_symbol = Hash.new
1388
+ wide_border = false
1389
+
1390
+ y_offset = x_offset = 0
1391
+ if(box["border_mode"] > 0)
1392
+ set_box_symbols(box_symbol, box["border_mode"])
1393
+ if(double_wide_character(box_symbol[:horizontal]))
1394
+ wide_border = true
1395
+ end
1396
+ end
1397
+ x_offset += box["outside_border"]
1398
+ y_offset += box["outside_border"]
1399
+ if(box["title"] != "")
1400
+ text_y = y + y_offset + 1
1401
+ text_x = x + x_offset + 1
1402
+ if(wide_border == true)
1403
+ text_x += 1
1404
+ end
1405
+ new_attributes = pipetext_init
1406
+ new_attributes["remap"] = { "|n" => box["fg_pipe_color"], "&n" => box["bg_pipe_color"] }
1407
+ new_attributes["ampersand_mode"] = true
1408
+ new_attributes["end"] = width
1409
+ if(box["border_mode"] > 0)
1410
+ if(wide_border == true)
1411
+ new_attributes["end"] -= 4
1412
+ else
1413
+ new_attributes["end"] -= 2
1414
+ end
1415
+ end
1416
+ new_attributes["end"] -= (2 * x_offset)
1417
+ if(new_attributes["end"] > 0)
1418
+ new_attributes["position"] = 0
1419
+ box["title"] = pipe(box["title"], new_attributes)
1420
+ if(text_y < y + height && box["title"] != "")
1421
+ box["title"].lines.each do |line|
1422
+ if(text_y < y + height)
1423
+ text_y = set_box_lines(text_x, text_y, box["background_color"], box["foreground_color"], line, y + height)
1424
+ title_height = text_y - (y + y_offset + 1)
1425
+ end
1426
+ end
1427
+ end
1428
+ end
1429
+ end
1430
+
1431
+ toggle = false
1432
+ horizontal_range = (x + x_offset + 1...x + width - x_offset - 1)
1433
+ horizontal_range.each do |column|
1434
+ if(wide_border == false || (wide_border == true && toggle == true && column < horizontal_range.last))
1435
+ if(wide_border == false)
1436
+ box_set(column, y + y_offset, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1437
+ box_set(column, y + height - y_offset - 1, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1438
+ if(box["title"] != "")
1439
+ box_set(column, title_height + y_offset + 1, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1440
+ end
1441
+ else
1442
+ box_set(column, y + y_offset, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1443
+ box_set(column, y + height - y_offset - 1, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1444
+ if(box["title"] != "")
1445
+ box_set(column, title_height + y_offset + 1, box_symbol[:horizontal], box["border_background_color"], box["border_foreground_color"])
1446
+ end
1447
+ end
1448
+ toggle = false
1449
+ else
1450
+ toggle = true
1451
+ end
1452
+ end
1453
+
1454
+ toggle = true
1455
+ vertical_range = (y + y_offset + 1...y + height - y_offset - 1)
1456
+ vertical_range.each do |row|
1457
+ if(wide_border == false || (wide_border == true && toggle == true && row < vertical_range.last))
1458
+ location = @drawing[[x + x_offset - 1, row]]
1459
+ if(location != nil && double_wide_character(location["symbol"]))
1460
+ location["symbol"] = " "
1461
+ end
1462
+ if(wide_border == false)
1463
+ box_set(x + x_offset, row, box_symbol[:vertical], box["border_background_color"], box["border_foreground_color"])
1464
+ box_set(x + width - x_offset - 1, row, box_symbol[:vertical], box["border_background_color"], box["border_foreground_color"])
1465
+ else
1466
+ box_set(x + x_offset, row, box_symbol[:vertical], box["border_background_color"], box["border_foreground_color"])
1467
+ box_set(x + width - x_offset - 2, row, box_symbol[:vertical], box["border_background_color"], box["border_foreground_color"])
1468
+ end
1469
+ else
1470
+ toggle = true
1471
+ end
1472
+ end
1473
+ location = @drawing[[x + x_offset - 1, y + y_offset]]
1474
+ if(location != nil && double_wide_character(location["symbol"]))
1475
+ location["symbol"] = " "
1476
+ end
1477
+ location = @drawing[[x + x_offset - 1, y + height - y_offset]]
1478
+ if(location != nil && double_wide_character(location["symbol"]))
1479
+ location["symbol"] = " "
1480
+ end
1481
+ if(wide_border == false)
1482
+ box_set(x + x_offset, y + y_offset, box_symbol[:top_left], box["border_background_color"], box["border_foreground_color"])
1483
+ box_set(x + width - x_offset - 1, y + y_offset, box_symbol[:top_right], box["border_background_color"], box["border_foreground_color"])
1484
+ box_set(x + x_offset, y + height - y_offset - 1, box_symbol[:bottom_left], box["border_background_color"], box["border_foreground_color"])
1485
+ box_set(x + width - x_offset - 1, y + height - y_offset - 1, box_symbol[:bottom_right], box["border_background_color"], box["border_foreground_color"])
1486
+ if(box["title"] != "")
1487
+ box_set(x + x_offset, y + y_offset + title_height + 1, box_symbol[:t_left], box["border_background_color"], box["border_foreground_color"])
1488
+ box_set(x + width - x_offset - 1, y + y_offset + title_height + 1, box_symbol[:t_right], box["border_background_color"], box["border_foreground_color"])
1489
+ end
1490
+ else
1491
+ box_set(x + x_offset, y + y_offset, box_symbol[:top_left], box["border_background_color"], box["border_foreground_color"])
1492
+ box_set(x + width - x_offset - 2, y + y_offset, box_symbol[:top_right], box["border_background_color"], box["border_foreground_color"])
1493
+ box_set(x + x_offset, y + height - y_offset - 1, box_symbol[:bottom_left], box["border_background_color"], box["border_foreground_color"])
1494
+ box_set(x + width - x_offset - 2, y + height - y_offset - 1, box_symbol[:bottom_right], box["border_background_color"], box["border_foreground_color"])
1495
+ end
1496
+ if(wide_border == true)
1497
+ x_offset += 2
1498
+ else
1499
+ x_offset += 1
1500
+ end
1501
+ y_offset += title_height
1502
+ y += title_height + 1
1503
+ return y, wide_border, x_offset, y_offset
1504
+ end
1505
+
1506
+ def draw_box_inside_border(box, x, y, width, height, x_offset, y_offset, wide_frame_border)
1507
+ border_size = box["inside_border"]
1508
+ if(border_size > 0)
1509
+ # if(wide_frame_border == true)
1510
+ # horizontal_range = (x + x_offset + 1...x + width - x_offset - 1)
1511
+ # else
1512
+ # horizontal_range = (x + x_offset - 1...x + width - x_offset + 1)
1513
+ # end
1514
+ horizontal_range = (x + x_offset...x + width - x_offset)
1515
+ vertical_range = (y + y_offset...y + height - y_offset - 2)
1516
+ vertical_range.each do |row|
1517
+ horizontal_range.each do |column|
1518
+ location = @drawing[[x - 1, row]]
1519
+ if(location != nil && double_wide_character(location["symbol"]))
1520
+ location["symbol"] = " "
1521
+ end
1522
+ # if(wide_frame_border == true)
1523
+ # if(row < y + y_offset + border_size || row >= y + height - y_offset - border_size - 2 ||
1524
+ # column <= x + x_offset + border_size || column >= x + width - x_offset - border_size - 1)
1525
+ # box_set(column, row, " ", box["inside_border_background_color"], box["foreground_color"])
1526
+ # end
1527
+ # else
1528
+ # if(row < y + y_offset + border_size || row >= y + height - y_offset - border_size - 2 ||
1529
+ # column < x + x_offset + border_size - 1 || column > x + width - x_offset - border_size)
1530
+ # box_set(column, row, " ", box["inside_border_background_color"], box["foreground_color"])
1531
+ # end
1532
+ # end
1533
+ if(row < y + y_offset + border_size || row >= y + height - y_offset - border_size - 2 ||
1534
+ column < x + x_offset + border_size || column > x + width - x_offset - border_size - 1)
1535
+ box_set(column, row, " ", box["inside_border_background_color"], box["foreground_color"])
1536
+ end
1537
+ end
1538
+ end
1539
+ end
1540
+ end
1541
+
1542
+ def draw_box_background(box, x, y, height, width)
1543
+ horizontal_range = (x + 1...x + width - 1)
1544
+ vertical_range = (y + 1...y + height - 1)
1545
+ vertical_range.each do |row|
1546
+ horizontal_range.each do |column|
1547
+ box_set(column, row, " ", box["background_color"], box["foreground_color"])
1548
+ end
1549
+ end
1550
+ end
1551
+
1552
+ def draw_box_text(box, x, y, width, height, x_offset, y_offset)
1553
+ text_x = x + x_offset
1554
+ text_y = y + y_offset
1555
+ new_attributes = pipetext_init
1556
+ new_attributes["remap"] = { "|n" => box["fg_pipe_color"], "&n" => box["bg_pipe_color"] }
1557
+ new_attributes["ampersand_mode"] = true
1558
+ new_attributes["end"] = width
1559
+ new_attributes["position"] = 0
1560
+ box["capture"] = pipe(box["capture"], new_attributes)
1561
+ if(text_y < y + height && box["capture"] != "")
1562
+ box["capture"].lines.each do |line|
1563
+ if(text_y < y + height)
1564
+ text_y = set_box_lines(text_x, text_y, box["background_color"], box["foreground_color"], line, y + height)
1565
+ end
1566
+ end
1567
+ end
1568
+ return text_y - y_offset
1569
+ end
1570
+
1571
+ def draw_box_children(attributes, box_index, x, y, width, height, x_offset, y_offset)
1572
+ box = attributes["box_attributes"][box_index]
1573
+ inside_x = x + x_offset
1574
+ inside_y = y + y_offset
1575
+ inside_width = width - (x_offset * 2)
1576
+ inside_height = height - (y_offset * 2)
1577
+ current_x = inside_x
1578
+ current_y = inside_y
1579
+ attributes["box_attributes"].each do |index, inside_box|
1580
+ if(inside_box["parent"] == box_index)
1581
+ inside_width = inside_box["width"]
1582
+ inside_height = inside_box["height"]
1583
+ if(box["layout"] == "horizontal")
1584
+ available_width = width - x_offset - current_x
1585
+ available_height = height - current_y - 1
1586
+ if(inside_box["grow"] == true)
1587
+ inside_width = available_width
1588
+ inside_height = available_height
1589
+ end
1590
+ if(box["clip_children"] == true)
1591
+ inside_width = [inside_width, available_width].min
1592
+ inside_height = [inside_height, available_height].min
1593
+ end
1594
+ if(inside_width > 2 && inside_height > 2)
1595
+ box_draw(attributes, index, current_x, current_y, inside_width, inside_height)
1596
+ current_x += inside_width
1597
+ end
1598
+ else
1599
+ available_width = (x + width - x_offset) - current_x
1600
+ available_height = (y + height - (2 * y_offset)) - current_y - 1
1601
+ if(inside_box["grow"] == true)
1602
+ inside_width = available_width
1603
+ inside_height = available_height
1604
+ end
1605
+ if(box["clip_children"] == true)
1606
+ inside_width = [inside_width, available_width].min
1607
+ inside_height = [inside_height, available_height].min
1608
+ end
1609
+ if(inside_width > 2 && inside_height > 2)
1610
+ box_draw(attributes, index, current_x, current_y, inside_width, inside_height)
1611
+ current_y += inside_height
1612
+ end
1613
+ end
1614
+ end
1615
+ end
1616
+ end
1617
+
1618
+ def box_draw(attributes, box_index, x, y, override_width=nil, override_height=nil)
1619
+ x_offset = 0
1620
+ y_offset = 0
1621
+ box = attributes["box_attributes"][box_index]
1622
+ if(override_width)
1623
+ width = override_width
1624
+ else
1625
+ width = box["width"]
1626
+ end
1627
+ if(override_height)
1628
+ height = override_height
1629
+ else
1630
+ height = box["height"]
1631
+ end
1632
+ if(box["outside_border"] > 0)
1633
+ draw_box_outside_border(attributes, box, x, y, width, height)
1634
+ end
1635
+ draw_box_background(box, x, y, height, width)
1636
+ if(box["border_mode"] >= 0)
1637
+ y, wide_frame_border, x_offset, y_offset = draw_box_frame(box, x, y, width, height)
1638
+ end
1639
+ draw_box_inside_border(box, x, y, width, height, x_offset, y_offset, wide_frame_border)
1640
+ x_offset += box["inside_border"]
1641
+ y_offset += box["inside_border"]
1642
+ text_width = width - (2 * box["outside_border"])
1643
+ text_height = height - (2 * box["outside_border"])
1644
+ if(box["border_mode"] >= 0)
1645
+ text_width -= 2
1646
+ text_height -= 2
1647
+ if(wide_frame_border == true)
1648
+ text_width -= 2
1649
+ end
1650
+ end
1651
+ text_width -= (2 * box["inside_border"])
1652
+ text_height -= (2 * box["inside_border"])
1653
+ y = draw_box_text(box, x, y, text_width, text_height, x_offset, y_offset)
1654
+ draw_box_children(attributes, box_index, x, y, width, height, x_offset, y_offset)
1655
+ end
1656
+
1657
+ def box_render
1658
+ result = String.new
1659
+ rendered_box = Array.new
1660
+ y_render_range = (@bounds["min_y"]..@bounds["max_y"])
1661
+ y_render_range.each do |y|
1662
+ row = Array.new
1663
+ x_render_range = (@bounds["min_x"]..@bounds["max_x"])
1664
+ previous_bg = String.new
1665
+ previous_fg = String.new
1666
+ offset = 0
1667
+ wide = 0
1668
+ x_render_range.each do |x|
1669
+ location = @drawing[[x + offset, y]]
1670
+ if(!location)
1671
+ if(wide > 0)
1672
+ wide -= 1
1673
+ else
1674
+ row << " "
1675
+ end
1676
+ elsif(wide > 0 && location["symbol"] == " ")
1677
+ wide -= 1
1678
+ else
1679
+ if(double_wide_character(location["symbol"]))
1680
+ wide += 1
1681
+ end
1682
+ bg = String.new
1683
+ if(location["bg"])
1684
+ bg = location["bg"]
1685
+ end
1686
+ fg = String.new
1687
+ if(location["fg"])
1688
+ fg = location["fg"]
1689
+ end
1690
+ if(previous_bg == bg && previous_fg == fg)
1691
+ row << location["symbol"]
1692
+ elsif(previous_bg != bg && previous_fg == fg)
1693
+ row << bg + location["symbol"]
1694
+ elsif(previous_bg == bg && previous_fg != fg)
1695
+ row << fg + location["symbol"]
1696
+ else
1697
+ row << bg + fg + location["symbol"]
1698
+ end
1699
+ previous_fg = fg
1700
+ previous_bg = bg
1701
+ end
1702
+ end
1703
+ rendered_box << row.join
1704
+ end
1705
+ rendered_box.each do |line|
1706
+ result << line + "\e[49m\e[39m\n"
1707
+ end
1708
+ return result
1709
+ end
1710
+
1711
+ def emit_box(new_text, attributes)
1712
+ @drawing = Hash.new
1713
+ @bounds = { "min_x" => Float::INFINITY, "max_x" => -Float::INFINITY,
1714
+ "min_y" => Float::INFINITY, "max_y" => -Float::INFINITY }
1715
+ update_box_attributes(attributes)
1716
+ box_draw(attributes, 1, 0, 0)
1717
+ new_text << box_render
1718
+ attributes["box_capture"] = 0
1719
+ attributes["boxes"] = 0
1720
+ attributes["box_attributes"] = Hash.new
1721
+ end
1722
+
1723
+ def emit_emoji(new_text, attributes)
1724
+ emoji = String.new
1725
+ match_length = 0
1726
+ value_length = 0
1727
+ $substitute_emoji_names.each do |key, value|
1728
+ if(attributes["emoji"] == key) # Use the most precise match first
1729
+ emoji = value
1730
+ break
1731
+ elsif(attributes["emoji"].length <= key.length) # Otherwise use shortest match
1732
+ match = abbreviated_match(attributes["emoji"], key)
1733
+ if(match == 0 && key =~ /-/)
1734
+ match = abbreviated_match(attributes["emoji"], key.sub(/-/, " "))
1735
+ end
1736
+ if(match > 0 && (match <= match_length || match_length == 0) &&
1737
+ (value.length <= value_length || value_length == 0))
1738
+ emoji = value
1739
+ match_length = match
1740
+ value_length = value.length
1741
+ end
1742
+ end
1743
+ end
1744
+ if(emoji == String.new) # No match, put copy input
1745
+ new_text << "|[" + attributes["emoji"] + "]"
1746
+ else
1747
+ emoji.split(/\|U/).each do |e|
1748
+ if(e != "")
1749
+ attributes["unicode"] = e.sub(/^\+?/, "")
1750
+ emit_unicode(new_text, attributes)
1751
+ end
1752
+ end
1753
+ attributes["emoji"] = String.new
1754
+ end
1755
+ attributes["emoji_capture"] = false
1756
+ end
1757
+
1758
+ def process_pipe(character, new_text, attributes)
1759
+ if(attributes["pipe"] == true && attributes["num"] == 0) # ||
1760
+ attributes["pipe"] = false
1761
+ new_text << character
1762
+ else
1763
+ attributes["pipe"] = true
1764
+ end
1765
+ end
1766
+
1767
+ def process_repeat_pattern(character, new_text, attributes)
1768
+ if(attributes["repeat_pattern"] == true) # ~ at end of |5~Repeat 5 times~
1769
+ attributes["num"].times do
1770
+ new_text << pipetext(attributes["pattern"], attributes["box_mode"], attributes["ampersand_mode"])
1771
+ end
1772
+ attributes["num"] = 0
1773
+ attributes["pipe"] = false
1774
+ attributes["escape"] = false
1775
+ attributes["repeat_pattern"] = false
1776
+ attributes["pattern"] = String.new
1777
+ else # ~ after number in |5~Repeat 5 times~
1778
+ attributes["repeat_pattern"] = true
1779
+ end
1780
+ end
1781
+
1782
+ def escape_fix(text) # Done this way for old Ruby versions
1783
+ text = text.gsub(/\\a/, "\a").gsub(/\\b/, "\b").gsub(/\\e/, "\e").gsub(/\\f/, "\f")
1784
+ text = text.gsub(/\\n/, "\n").gsub(/\\r/, "\r").gsub(/\\t/, "\t").gsub(/\\v/, "\v")
1785
+ text = text.gsub(/\\~/, "~").gsub(/\\\(/, "(").gsub(/\\\)/, ")")
1786
+ end
1787
+
1788
+ def process_escaped_character(character, new_text, attributes)
1789
+ if(attributes["num"] > 0)
1790
+ attributes["num"].times do
1791
+ new_text << escape_fix("\\#{character}")
1792
+ end
1793
+ else
1794
+ new_text << escape_fix("\\#{character}")
1795
+ end
1796
+ attributes["num"] = 0
1797
+ attributes["pipe"] = false
1798
+ attributes["escape"] = false
1799
+ attributes["pattern"] = String.new
1800
+ attributes["repeat_pattern"] = false
1801
+ end
1802
+
1803
+ def capture_color(character, new_text, attributes)
1804
+ if(character =~ /[0-9,A-F,a-f]/)
1805
+ if(attributes["color_capture"] <= 2)
1806
+ attributes["r"] << character
1807
+ elsif(attributes["color_capture"] <= 4)
1808
+ attributes["g"] << character
1809
+ elsif(attributes["color_capture"] <= 6)
1810
+ attributes["b"] << character
1811
+ end
1812
+ if(attributes["color_capture"] == 6)
1813
+ emit_color(new_text, attributes)
1814
+ else
1815
+ attributes["color_capture"] += 1
1816
+ end
1817
+ end
1818
+ end
1819
+
1820
+ def capture_character_pattern(character, attributes)
1821
+ if(character == "\\")
1822
+ attributes["escape"] = true
1823
+ else
1824
+ if(attributes["escape"] == true)
1825
+ attributes["pattern"] << "\\#{character}"
1826
+ attributes["escape"] = false
1827
+ else
1828
+ attributes["pattern"] << character
1829
+ end
1830
+ end
1831
+ end
1832
+
1833
+ def capture_palette_color(character, new_text, attributes)
1834
+ if(character =~ /[0-9,A-F,a-f]/)
1835
+ if(attributes["palette_capture"] <= 2)
1836
+ attributes["p"] << character
1837
+ end
1838
+ if(attributes["palette_capture"] == 2)
1839
+ emit_palette_color(new_text, attributes)
1840
+ else
1841
+ attributes["palette_capture"] += 1
1842
+ end
1843
+ end
1844
+ end
1845
+
1846
+ def capture_unicode(character, new_text, attributes)
1847
+ if(character =~ /[0-9,A-F,a-f]/)
1848
+ if(attributes["unicode_capture"] <= 6)
1849
+ attributes["unicode"] << character
1850
+ end
1851
+ if(attributes["unicode_capture"] == 6)
1852
+ emit_unicode(new_text, attributes)
1853
+ else
1854
+ attributes["unicode_capture"] += 1
1855
+ end
1856
+ end
1857
+ end
1858
+
1859
+ def process_ampersand(character, new_text, attributes)
1860
+ if(attributes["ampersand"] == true) # &&
1861
+ attributes["ampersand"] = false
1862
+ new_text << character
1863
+ else
1864
+ attributes["ampersand"] = true
1865
+ end
1866
+ end
1867
+
1868
+ def test_shell_add(attributes, text)
1869
+ if(attributes["shell_prompt"] == true)
1870
+ return "\\[#{text}\\]"
1871
+ else
1872
+ return text
1873
+ end
1874
+ end
1875
+
1876
+ def process_piped_character(character, new_text, attributes)
1877
+ attributes["found"] = true # Assume we will find the next character
1878
+ if(attributes["num"] == 0) # We are not in repeat character mode
1879
+ case character
1880
+ when "&" # |& - Toggle & on/off for Background Colors
1881
+ if(attributes["ampersand_mode"] == true)
1882
+ attributes["ampersand_mode"] = false
1883
+ else
1884
+ attributes["ampersand_mode"] = true
1885
+ end
1886
+ attributes["pipe"] = false
1887
+ when "!" # |! - Clear screen
1888
+ new_text << test_shell_add(attributes, "\e[H\e[J")
1889
+ when "+" # |+ - Bold
1890
+ if(attributes["bold"] == false)
1891
+ new_text << test_shell_add(attributes, "\e[1m")
1892
+ attributes["bold"] = true
1893
+ else
1894
+ new_text << test_shell_add(attributes, "\e[22m")
1895
+ attributes["bold"] = false
1896
+ end
1897
+ when "." # |. - Faint / Dim
1898
+ if(attributes["faint"] == false)
1899
+ new_text << test_shell_add(attributes, "\e[2m")
1900
+ attributes["faint"] = true
1901
+ else
1902
+ new_text << test_shell_add(attributes, "\e[22m")
1903
+ attributes["faint"] = false
1904
+ end
1905
+ when "~" # |~ - Italic
1906
+ if(attributes["italic"] == false)
1907
+ new_text << test_shell_add(attributes, "\e[3m")
1908
+ attributes["italic"] = true
1909
+ else
1910
+ new_text << test_shell_add(attributes, "\e[23m")
1911
+ attributes["italic"] = false
1912
+ end
1913
+ when "_" # |_ - Underline
1914
+ if(attributes["underline"] == false)
1915
+ new_text << test_shell_add(attributes, "\e[4m")
1916
+ attributes["underline"] = true
1917
+ else
1918
+ new_text << test_shell_add(attributes, "\e[24m")
1919
+ attributes["underline"] = false
1920
+ end
1921
+ when "@" # |@ - Blink
1922
+ if(attributes["blink"] == false)
1923
+ new_text << test_shell_add(attributes, "\e[5m")
1924
+ attributes["blink"] = true
1925
+ else
1926
+ new_text << test_shell_add(attributes, "\e[25m")
1927
+ attributes["blink"] = false
1928
+ end
1929
+ when "^" # |^ - Move up 1 line
1930
+ new_text << "\e[A"
1931
+ when "v", "V" # |v - Move down 1 line
1932
+ new_text << "\e[B"
1933
+ when ">" # |> - Move forward 1 character
1934
+ new_text << "\e[C"
1935
+ when "<" # |< - Move back 1 character
1936
+ new_text << "\e[D"
1937
+ when "h" # |h - Hide cursor
1938
+ new_text << test_shell_add(attributes, "\e[?25l")
1939
+ when "H" # |H - Unhide cursor
1940
+ new_text << test_shell_add(attributes, "\e[?25h")
1941
+ when "i", "I" # |i - Inverse
1942
+ if(attributes["inverse"] == false)
1943
+ new_text << test_shell_add(attributes, "\e[7m")
1944
+ attributes["inverse"] = true
1945
+ else
1946
+ new_text << test_shell_add(attributes, "\e[27m")
1947
+ attributes["inverse"] = false
1948
+ end
1949
+ when "x", "X" # |x - Crossed Out
1950
+ if(attributes["crossed_out"] == false)
1951
+ new_text << test_shell_add(attributes, "\e[9m")
1952
+ attributes["crossed_out"] = true
1953
+ else
1954
+ new_text << test_shell_add(attributes, "\e[29m")
1955
+ attributes["crossed_out"] = false
1956
+ end
1957
+ when "#" # |#RRGGBB
1958
+ attributes["color_capture"] = 1
1959
+ when "P", "p" # |P or |p - 2 character hex format color (256 colors)
1960
+ attributes["palette_capture"] = 1
1961
+ when "U", "u" # |U or |u - Unicode 6 character hex format
1962
+ attributes["unicode_capture"] = 1
1963
+ when "k" # |k - Foreground text black
1964
+ if(attributes["fg"] != "\e[30m")
1965
+ attributes["fg"] = "\e[30m"
1966
+ new_text << test_shell_add(attributes, attributes["fg"])
1967
+ end
1968
+ when "K" # |K - Foreground text bright black
1969
+ if(attributes["fg"] != "\e[90m")
1970
+ attributes["fg"] = "\e[90m"
1971
+ new_text << test_shell_add(attributes, attributes["fg"])
1972
+ end
1973
+ when "r" # |r - Foreground text red
1974
+ if(attributes["fg"] != "\e[31m")
1975
+ attributes["fg"] = "\e[31m"
1976
+ new_text << test_shell_add(attributes, attributes["fg"])
1977
+ end
1978
+ when "R" # |R - Foreground text bright red
1979
+ if(attributes["fg"] != "\e[91m")
1980
+ attributes["fg"] = "\e[91m"
1981
+ new_text << test_shell_add(attributes, attributes["fg"])
1982
+ end
1983
+ when "g" # |g - Foreground text green
1984
+ if(attributes["fg"] != "\e[32m")
1985
+ attributes["fg"] = "\e[32m"
1986
+ new_text << test_shell_add(attributes, attributes["fg"])
1987
+ end
1988
+ when "G" # |G - Foreground text bright green
1989
+ if(attributes["fg"] != "\e[92m")
1990
+ attributes["fg"] = "\e[92m"
1991
+ new_text << test_shell_add(attributes, attributes["fg"])
1992
+ end
1993
+ when "y" # |y - Foreground text yellow (brown)
1994
+ if(attributes["fg"] != "\e[33m")
1995
+ attributes["fg"] = "\e[33m"
1996
+ new_text << test_shell_add(attributes, attributes["fg"])
1997
+ end
1998
+ when "Y" # |Y - Foreground text bright yellow
1999
+ if(attributes["fg"] != "\e[93m")
2000
+ attributes["fg"] = "\e[93m"
2001
+ new_text << test_shell_add(attributes, attributes["fg"])
2002
+ end
2003
+ when "b" # |b - Foreground text blue
2004
+ if(attributes["fg"] != "\e[34m")
2005
+ attributes["fg"] = "\e[34m"
2006
+ new_text << test_shell_add(attributes, attributes["fg"])
2007
+ end
2008
+ when "B" # |B - Foreground text bright blue
2009
+ if(attributes["fg"] != "\e[94m")
2010
+ attributes["fg"] = "\e[94m"
2011
+ new_text << test_shell_add(attributes, attributes["fg"])
2012
+ end
2013
+ when "m" # |m - Foreground text magenta
2014
+ if(attributes["fg"] != "\e[35m")
2015
+ attributes["fg"] = "\e[35m"
2016
+ new_text << test_shell_add(attributes, attributes["fg"])
2017
+ end
2018
+ when "M" # |M - Foreground text bright magenta
2019
+ if(attributes["fg"] != "\e[95m")
2020
+ attributes["fg"] = "\e[95m"
2021
+ new_text << test_shell_add(attributes, attributes["fg"])
2022
+ end
2023
+ when "c" # |c - Foreground text cyan
2024
+ if(attributes["fg"] != "\e[36m")
2025
+ attributes["fg"] = "\e[36m"
2026
+ new_text << test_shell_add(attributes, attributes["fg"])
2027
+ end
2028
+ when "C" # |C - Foreground text bright cyan
2029
+ if(attributes["fg"] != "\e[96m")
2030
+ attributes["fg"] = "\e[96m"
2031
+ new_text << test_shell_add(attributes, attributes["fg"])
2032
+ end
2033
+ when "w" # |w - Foreground text white
2034
+ if(attributes["fg"] != "\e[37m")
2035
+ attributes["fg"] = "\e[37m"
2036
+ new_text << test_shell_add(attributes, attributes["fg"])
2037
+ end
2038
+ when "W" # |W - Foreground text white
2039
+ if(attributes["fg"] != "\e[97m")
2040
+ attributes["fg"] = "\e[97m"
2041
+ new_text << test_shell_add(attributes, attributes["fg"])
2042
+ end
2043
+ when "n", "N" # |n or |N - Foreground text normal
2044
+ attributes["fg"] = "\e[39m"
2045
+ new_text << test_shell_add(attributes, attributes["fg"])
2046
+ when "O" # |O - Box mode off
2047
+ attributes["box"] = -1
2048
+ when "o" # |o - Box mode 0
2049
+ attributes["box"] = 0
2050
+ when "-" # |- - Box mode 1
2051
+ if(attributes["box_mode"] == true)
2052
+ attributes["box"] = 1
2053
+ else # We didn"t find the next character
2054
+ attributes["found"] = false
2055
+ end
2056
+ when "=" # |= - Box mode 2
2057
+ if(attributes["box_mode"] == true)
2058
+ attributes["box"] = 2
2059
+ else # We didn"t find the next character
2060
+ attributes["found"] = false
2061
+ end
2062
+ when "{" # center
2063
+ attributes["center_capture"] = true
2064
+ when ";" # extend to end column with spaces
2065
+ spaces = attributes["end"] - attributes["position"]
2066
+ spaces.times do
2067
+ new_text << " "
2068
+ end
2069
+ when "]" # |]0-9* - end column number
2070
+ attributes["end_capture"] = true
2071
+ when "[" # |[emoji]
2072
+ attributes["emoji_capture"] = true
2073
+ when "(" # |(variable) or |(variable=Some value)
2074
+ attributes["variable_capture"] = true
2075
+ when ")" # |)Right Aligned
2076
+ attributes["right_capture"] = true
2077
+ when "\\" # |\ - Escape mode
2078
+ attributes["escape"] = true
2079
+ when "$" # |$ - Toggle shell prompt mode
2080
+ if(attributes["shell_prompt"] == true)
2081
+ attributes["shell_prompt"] = false
2082
+ else
2083
+ attributes["shell_prompt"] = true
2084
+ end
2085
+ else # We didn"t find the next character
2086
+ attributes["found"] = false
2087
+ end
2088
+ elsif(character == "\\")
2089
+ attributes["escape"] = true
2090
+ else # We didn"t find the next character
2091
+ attributes["found"] = false
2092
+ end
2093
+ if(attributes["found"] == false)
2094
+ if(character == "0") # |10+
2095
+ if(attributes["num"] > 0)
2096
+ attributes["num"] *= 10
2097
+ end
2098
+ elsif(character >= "1" && character <= "9") # |1+ through |9+
2099
+ if(attributes["num"] > 0)
2100
+ attributes["num"] *= 10
2101
+ end
2102
+ attributes["num"] += character.to_i
2103
+ else
2104
+ if(attributes["num"] <= 0) # No replacement found
2105
+ new_text << "|" + character
2106
+ else # Repeat number replacement found
2107
+ if(attributes["box"] == 1)
2108
+ attributes["num"].times do
2109
+ new_text << process_box_one_replace(character)
2110
+ end
2111
+ attributes["num"] = 0
2112
+ elsif(attributes["box"] == 2)
2113
+ attributes["num"].times do
2114
+ new_text << process_box_two_replace(character)
2115
+ end
2116
+ attributes["num"] = 0
2117
+ else
2118
+ attributes["num"].times do
2119
+ new_text << character
2120
+ end
2121
+ attributes["num"] = 0
2122
+ end
2123
+ end
2124
+ attributes["pipe"] = false
2125
+ end
2126
+ elsif(attributes["escape"] == false)
2127
+ attributes["pipe"] = false
2128
+ end
2129
+ end
2130
+
2131
+ def process_ampersanded_character(character, new_text, attributes)
2132
+ case character
2133
+ when "#" # &#RRGGBB
2134
+ attributes["color_capture"] = 1
2135
+ return
2136
+ when "P", "p" # |P or |p - 2 character hex format color (256 colors)
2137
+ attributes["palette_capture"] = 1
2138
+ return
2139
+ when "w" # &w - Background white
2140
+ if(attributes["bg"] != "\e[47m")
2141
+ attributes["bg"] = "\e[47m"
2142
+ new_text << test_shell_add(attributes, attributes["bg"])
2143
+ end
2144
+ when "W" # &W - Background white
2145
+ if(attributes["bg"] != "\e[107m")
2146
+ attributes["bg"] = "\e[107m"
2147
+ new_text << test_shell_add(attributes, attributes["bg"])
2148
+ end
2149
+ when "c" # &c - Background cyan
2150
+ if(attributes["bg"] != "\e[46m")
2151
+ attributes["bg"] = "\e[46m"
2152
+ new_text << test_shell_add(attributes, attributes["bg"])
2153
+ end
2154
+ when "C" # &C - Background cyan
2155
+ if(attributes["bg"] != "\e[106m")
2156
+ attributes["bg"] = "\e[106m"
2157
+ new_text << test_shell_add(attributes, attributes["bg"])
2158
+ end
2159
+ when "m" # &m - Background magenta
2160
+ if(attributes["bg"] != "\e[45m")
2161
+ attributes["bg"] = "\e[45m"
2162
+ new_text << test_shell_add(attributes, attributes["bg"])
2163
+ end
2164
+ when "M" # &M - Background magenta
2165
+ if(attributes["bg"] != "\e[105m")
2166
+ attributes["bg"] = "\e[105m"
2167
+ new_text << test_shell_add(attributes, attributes["bg"])
2168
+ end
2169
+ when "b" # &b - Background blue
2170
+ if(attributes["bg"] != "\e[44m")
2171
+ attributes["bg"] = "\e[44m"
2172
+ new_text << test_shell_add(attributes, attributes["bg"])
2173
+ end
2174
+ when "B" # &B - Background blue
2175
+ if(attributes["bg"] != "\e[104m")
2176
+ attributes["bg"] = "\e[104m"
2177
+ new_text << test_shell_add(attributes, attributes["bg"])
2178
+ end
2179
+ when "y" # &y - Background yellow (brown)
2180
+ if(attributes["bg"] != "\e[43m")
2181
+ attributes["bg"] = "\e[43m"
2182
+ new_text << test_shell_add(attributes, attributes["bg"])
2183
+ end
2184
+ when "Y" # &Y - Background yellow (brown)
2185
+ if(attributes["bg"] != "\e[103m")
2186
+ attributes["bg"] = "\e[103m"
2187
+ new_text << test_shell_add(attributes, attributes["bg"])
2188
+ end
2189
+ when "g" # &g - Background green
2190
+ if(attributes["bg"] != "\e[42m")
2191
+ attributes["bg"] = "\e[42m"
2192
+ new_text << test_shell_add(attributes, attributes["bg"])
2193
+ end
2194
+ when "G" # &G - Background green
2195
+ if(attributes["bg"] != "\e[102m")
2196
+ attributes["bg"] = "\e[102m"
2197
+ new_text << test_shell_add(attributes, attributes["bg"])
2198
+ end
2199
+ when "r" # &r - Background red
2200
+ if(attributes["bg"] != "\e[41m")
2201
+ attributes["bg"] ="\e[41m"
2202
+ new_text << test_shell_add(attributes, attributes["bg"])
2203
+ end
2204
+ when "R" # &R - Background red
2205
+ if(attributes["bg"] != "\e[101m")
2206
+ attributes["bg"] ="\e[101m"
2207
+ new_text << test_shell_add(attributes, attributes["bg"])
2208
+ end
2209
+ when "k" # &k - Background black
2210
+ if(attributes["bg"] != "\e[40m")
2211
+ attributes["bg"] = "\e[40m"
2212
+ new_text << test_shell_add(attributes, attributes["bg"])
2213
+ end
2214
+ when "K" # &K - Background black
2215
+ if(attributes["bg"] != "\e[100m")
2216
+ attributes["bg"] = "\e[100m"
2217
+ new_text << test_shell_add(attributes, attributes["bg"])
2218
+ end
2219
+ when "n", "N" # &n or &N - Background normal
2220
+ attributes["bg"] = "\e[49m"
2221
+ new_text << test_shell_add(attributes, attributes["bg"])
2222
+ else
2223
+ new_text << "&" + character
2224
+ end
2225
+ attributes["ampersand"] = false
2226
+ end
2227
+
2228
+ def process_box_zero_replace(character)
2229
+ case character
2230
+ when "["
2231
+ "+"
2232
+ when "]"
2233
+ "+"
2234
+ when "-"
2235
+ "-"
2236
+ when "!"
2237
+ "|"
2238
+ when ">"
2239
+ "+"
2240
+ when "<"
2241
+ "+"
2242
+ when "+"
2243
+ "+"
2244
+ when "{"
2245
+ "+"
2246
+ when "}"
2247
+ "+"
2248
+ when "v"
2249
+ "+"
2250
+ when "^"
2251
+ "+"
2252
+ else
2253
+ character
2254
+ end
2255
+ end
2256
+
2257
+ def process_box_one_replace(character)
2258
+ case character
2259
+ when "["
2260
+ "╭"
2261
+ when "]"
2262
+ "╮"
2263
+ when "-"
2264
+ "─"
2265
+ when "!"
2266
+ "│"
2267
+ when ">"
2268
+ "├"
2269
+ when "<"
2270
+ "┤"
2271
+ when "+"
2272
+ "┼"
2273
+ when "{"
2274
+ "╰"
2275
+ when "}"
2276
+ "╯"
2277
+ when "v"
2278
+ "┬"
2279
+ when "^"
2280
+ "┴"
2281
+ else
2282
+ character
2283
+ end
2284
+ end
2285
+
2286
+ def process_box_two_replace(character)
2287
+ case character
2288
+ when "["
2289
+ "╔"
2290
+ when "]"
2291
+ "╗"
2292
+ when "-"
2293
+ "═"
2294
+ when "!"
2295
+ "║"
2296
+ when ">"
2297
+ "╠"
2298
+ when "<"
2299
+ "╣"
2300
+ when "+"
2301
+ "╬"
2302
+ when "{"
2303
+ "╚"
2304
+ when "}"
2305
+ "╝"
2306
+ when "v"
2307
+ "╦"
2308
+ when "^"
2309
+ "╩"
2310
+ else
2311
+ character
2312
+ end
2313
+ end
2314
+
2315
+ def process_box_three_replace(character) # currently unused
2316
+ case character
2317
+ when "["
2318
+ "┌"
2319
+ when "]"
2320
+ "┐"
2321
+ when "-"
2322
+ "─"
2323
+ when "!"
2324
+ "│"
2325
+ when ">"
2326
+ "├"
2327
+ when "<"
2328
+ "┤"
2329
+ when "+"
2330
+ "┼"
2331
+ when "{"
2332
+ "└"
2333
+ when "}"
2334
+ "┘"
2335
+ when "v"
2336
+ "┬"
2337
+ when "^"
2338
+ "┴"
2339
+ else
2340
+ character
2341
+ end
2342
+ end
2343
+ end