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