arTTY 0.9.48

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df17d6bc87a48aafd84c5371ff5bad973bc9c5e6
4
+ data.tar.gz: abcb987b6e79acfe71b1da42b520bba0d11ee556
5
+ SHA512:
6
+ metadata.gz: 866089b6a04d29a56c1a42fbbd303615eed3b3d72257dae6103f05c7f75c406bfdba251017ff4f194964298d7876e55fa1ea1e8ceaed0ccf6cc99d36386639de
7
+ data.tar.gz: 88e6e76cc7678f2c52fef9bbb67b63ee4ea0bfd31ad384df5dc6c801cdede9f1692f14de2ed23fb9c47757a9e69968bb34798746df77bc79d038ae0f72388954
@@ -0,0 +1,486 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "arTTY"
4
+ require "hilighter"
5
+ require "io/wait"
6
+ require "jsoncfg"
7
+ require "optparse"
8
+ require "scoobydoo"
9
+ require "typhoeus"
10
+
11
+ class ArTTYConfig < JSONConfig
12
+ extend JSONConfig::Keys
13
+
14
+ add_key("art")
15
+ add_bool_key("clear_screen")
16
+ add_bool_key("devexcuse")
17
+ add_key("exclude")
18
+ add_key("fields")
19
+ add_bool_key("fit")
20
+ add_bool_key("fortune")
21
+ add_key("match")
22
+ add_bool_key("random")
23
+ add_bool_key("sysinfo")
24
+
25
+ def initialize(file = nil)
26
+ file ||= "~/.config/arTTY/rc"
27
+ @defaults = {
28
+ "art" => "",
29
+ "clear_screen" => true,
30
+ "devexcuse" => false,
31
+ "exclude" => "",
32
+ "fields" => Array.new,
33
+ "fit" => true,
34
+ "fortune" => false,
35
+ "match" => "",
36
+ "random" => true,
37
+ "sysinfo" => true
38
+ }
39
+ super(file, false)
40
+ end
41
+ end
42
+
43
+ class ArTTYExit
44
+ GOOD = 0
45
+ INVALID_OPTION = 1
46
+ INVALID_ARGUMENT = 2
47
+ MISSING_ARGUMENT = 3
48
+ EXTRA_ARGUMENTS = 4
49
+ EXCEPTION = 5
50
+ AMBIGUOUS_ARGUMENT = 6
51
+ UNSUPPORTED_ART = 7
52
+ end
53
+
54
+ def get_devexcuse
55
+ begin
56
+ Typhoeus::Request.get(
57
+ "http://developerexcuses.com"
58
+ ).body.match(/<a href.+>(.+)<\/a>/) do |m|
59
+ return m[1]
60
+ end
61
+ rescue
62
+ return nil
63
+ end
64
+ end
65
+
66
+ def parse(args)
67
+ options = Hash.new
68
+ options["action"] = "draw"
69
+ options["all"] = false
70
+ options["art"] = ""
71
+ options["clear"] = false
72
+ options["conf"] = ArTTYConfig.new
73
+ options["devexcuse"] = false
74
+ options["exclude"] = ""
75
+ options["fields"] = Array.new
76
+ options["fit"] = false
77
+ options["fortune"] = false
78
+ options["generate"] = nil
79
+ options["match"] = ""
80
+ options["plain"] = false
81
+ options["random"] = false
82
+ options["sysinfo"] = false
83
+ options["verbose"] = false
84
+
85
+ info = "Art for your TTY."
86
+
87
+ parser = OptionParser.new do |opts|
88
+ opts.summary_width = 25
89
+
90
+ opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [art]"
91
+
92
+ opts.on("", "DESCRIPTION")
93
+
94
+ info.scan(/\S.{0,76}\S(?=\s|$)|\S+/).each do |line|
95
+ opts.on(" #{line}")
96
+ end
97
+
98
+ opts.on("", "OPTIONS")
99
+
100
+ opts.on("-a", "--all", "Ignore previous filtering") do
101
+ options["all"] = true
102
+ end
103
+
104
+ opts.on("--cache", "Refresh the cache") do
105
+ case options["action"]
106
+ when "draw"
107
+ options["action"] = "cache"
108
+ else
109
+ puts(opts)
110
+ exit ArTTYExit::INVALID_OPTION
111
+ end
112
+ end
113
+
114
+ opts.on("-c", "--clear", "Clear screen first") do
115
+ options["clear"] = true
116
+ end
117
+
118
+ opts.on("--demo", "Demo art matching filters") do
119
+ case options["action"]
120
+ when "draw"
121
+ options["action"] = "demo"
122
+ else
123
+ puts(opts)
124
+ exit ArTTYExit::INVALID_OPTION
125
+ end
126
+ end
127
+
128
+ opts.on("-d", "--devexcuse", "Display a developer excuse") do
129
+ options["devexcuse"] = true
130
+ end
131
+
132
+ opts.on(
133
+ "-e",
134
+ "--exclude=PATTERN",
135
+ "Exclude art matching pattern"
136
+ ) do |pattern|
137
+ options["exclude"] = pattern
138
+ end
139
+
140
+ opts.on(
141
+ "--fields=FIELDS",
142
+ "Specify order of sysinfo (comma-separated, see",
143
+ "FIELDS)"
144
+ ) do |fields|
145
+ options["fields"] = fields.split(",")
146
+ options["sysinfo"] = true
147
+ end
148
+
149
+ opts.on(
150
+ "--fit",
151
+ "Only use art that fits in the current window"
152
+ ) do |f|
153
+ options["fit"] = true
154
+ end
155
+
156
+ opts.on(
157
+ "-f",
158
+ "--fortune",
159
+ "Display a fortune (if installed)"
160
+ ) do
161
+ options["fortune"] = true
162
+ end
163
+
164
+ opts.on("-h", "--help", "Display this help message") do
165
+ puts(opts)
166
+ exit ArTTYExit::GOOD
167
+ end
168
+
169
+ opts.on(
170
+ "-g",
171
+ "--generate=IMAGE",
172
+ "Generate ArTTY art from image (NAME_WxH.png)"
173
+ ) do |image|
174
+ case options["action"]
175
+ when "draw"
176
+ options["action"] = "generate"
177
+ else
178
+ puts(opts)
179
+ exit ArTTYExit::INVALID_OPTION
180
+ end
181
+ options["generate"] = image
182
+ end
183
+
184
+ opts.on("--ls", "List art matching filters") do
185
+ case options["action"]
186
+ when "draw"
187
+ options["action"] = "list"
188
+ else
189
+ puts(opts)
190
+ exit ArTTYExit::INVALID_OPTION
191
+ end
192
+ end
193
+
194
+ opts.on(
195
+ "-m",
196
+ "--match=PATTERN",
197
+ "Only use art matching pattern"
198
+ ) do |pattern|
199
+ options["match"] = pattern
200
+ end
201
+
202
+ opts.on("--[no-]color", "Disable colorized output") do |c|
203
+ Hilighter.disable if (!c)
204
+ end
205
+
206
+ opts.on(
207
+ "-p",
208
+ "--plain",
209
+ "Ignore previous flags and filtering (useful for",
210
+ "tab-completion with --ls)"
211
+ ) do
212
+ options["plain"] = true
213
+ end
214
+
215
+ opts.on(
216
+ "-r",
217
+ "--random",
218
+ "Display random art matching filters"
219
+ ) do
220
+ options["random"] = true
221
+ end
222
+
223
+ opts.on("--save", "Save specified options as default") do
224
+ case options["action"]
225
+ when "draw"
226
+ options["action"] = "save"
227
+ else
228
+ puts(opts)
229
+ exit ArTTYExit::INVALID_OPTION
230
+ end
231
+ end
232
+
233
+ opts.on(
234
+ "--show-config",
235
+ "Show the current config with any other options applied",
236
+ ) do
237
+ case options["action"]
238
+ when "draw"
239
+ options["action"] = "show"
240
+ else
241
+ puts(opts)
242
+ exit ArTTYExit::INVALID_OPTION
243
+ end
244
+ end
245
+
246
+ opts.on("-s", "--sysinfo", "Display system info") do
247
+ options["sysinfo"] = true
248
+ end
249
+
250
+ opts.on(
251
+ "-u",
252
+ "--update",
253
+ "Download new art and refresh the cache"
254
+ ) do
255
+ case options["action"]
256
+ when "draw"
257
+ options["action"] = "update"
258
+ else
259
+ puts(opts)
260
+ exit ArTTYExit::INVALID_OPTION
261
+ end
262
+ end
263
+
264
+ opts.on(
265
+ "-v",
266
+ "--verbose",
267
+ "Show backtrace when error occurs"
268
+ ) do
269
+ options["verbose"] = true
270
+ end
271
+
272
+ opts.on("-V", "--version", "Show version") do
273
+ __FILE__.match(/arTTY-(\d+\.\d+\.\d+)/) do |m|
274
+ puts("arTTY version #{m[1]}")
275
+ end
276
+ exit ArTTYExit::GOOD
277
+ end
278
+
279
+ opts.on(
280
+ "",
281
+ "FIELDS",
282
+ " colors Show terminal colors",
283
+ " cpu Show cpu info",
284
+ " fs Show filesystem usage",
285
+ " host, hostname Show hostname",
286
+ " ip Show IPv4 and IPv6 addresses",
287
+ " ipv4 Show only IPv4 addresses",
288
+ " ipv6 Show only IPv6 addresses",
289
+ " kernel Show kernel info",
290
+ " os Show operating system info",
291
+ " ram Show RAM usage",
292
+ " shell Show current shell",
293
+ " tty Show TTY info",
294
+ " uptime Show uptime"
295
+ )
296
+ end
297
+
298
+ begin
299
+ parser.parse!
300
+ rescue OptionParser::InvalidOption => e
301
+ puts(e.message)
302
+ puts(parser)
303
+ exit ArTTYExit::INVALID_OPTION
304
+ rescue OptionParser::InvalidArgument => e
305
+ puts(e.message)
306
+ puts(parser)
307
+ exit ArTTYExit::INVALID_ARGUMENT
308
+ rescue OptionParser::MissingArgument => e
309
+ puts(e.message)
310
+ puts(parser)
311
+ exit ArTTYExit::MISSING_ARGUMENT
312
+ rescue OptionParser::AmbiguousOption => e
313
+ puts(e.message)
314
+ puts(parser)
315
+ exit ArTTYExit::AMBIGUOUS_ARGUMENT
316
+ end
317
+
318
+ if (args.length == 1)
319
+ options["random"] = false
320
+ options["art"] = args[0]
321
+ elsif (args.length > 1)
322
+ puts(parser)
323
+ exit ArTTYExit::EXTRA_ARGUMENTS
324
+ end
325
+
326
+ return options
327
+ end
328
+
329
+ def validate(cfg, opts)
330
+ if opts["all"]
331
+ cfg.no_fit
332
+ cfg.set_exclude("")
333
+ cfg.set_match("")
334
+ elsif opts["plain"]
335
+ cfg.default
336
+ cfg.no_clear_screen
337
+ cfg.no_fit
338
+ cfg.no_random
339
+ cfg.no_sysinfo
340
+ end
341
+
342
+ cfg.set_art(opts["art"])
343
+ cfg.clear_screen if (opts["clear"])
344
+ cfg.devexcuse if (opts["devexcuse"])
345
+ cfg.set_exclude(opts["exclude"]) if (!opts["exclude"].empty?)
346
+ cfg.set_fields(opts["fields"]) if (!opts["fields"].empty?)
347
+ cfg.fit if (opts["fit"])
348
+ cfg.fortune if (opts["fortune"])
349
+ cfg.set_match(opts["match"]) if (!opts["match"].empty?)
350
+ cfg.random if (opts["random"])
351
+ cfg.sysinfo if (opts["sysinfo"])
352
+ end
353
+
354
+ begin
355
+ options = parse(ARGV)
356
+ rescue Interrupt
357
+ # Exit gracefully on ^C
358
+ exit ArTTYExit::GOOD
359
+ end
360
+
361
+ begin
362
+ config = options["conf"]
363
+ validate(config, options)
364
+
365
+ arTTY = ArTTY.new
366
+ arTTY.exclude(config.get_exclude) if (config.exclude?)
367
+ arTTY.match(config.get_match) if (config.match?)
368
+
369
+ devexcuse = nil
370
+ if (config.devexcuse?)
371
+ devexcuse = get_devexcuse
372
+ end
373
+
374
+ fortune = nil
375
+ if (config.fortune? && ScoobyDoo.where_are_you("fortune"))
376
+ fortune = %x(fortune -s)
377
+ end
378
+
379
+ info = nil
380
+ if (config.sysinfo?)
381
+ info = ArTTY::SystemInfo.new(config.get_fields)
382
+ end
383
+
384
+ # Remove all that do not fit
385
+ if (config.fit?)
386
+ height = %x(tput lines).to_i - 4 # Leave some space for prompt
387
+ width = %x(tput cols).to_i - 1
388
+ if (config.sysinfo?)
389
+ width -= (info.width + 2)
390
+ info = nil if ((height <= info.height) || (width <= 0))
391
+ end
392
+ if (devexcuse)
393
+ eheight = devexcuse.split("\n").length
394
+ ewidth = devexcuse.split("\n").map(&:length).max
395
+ devexcuse = nil if (height <= eheight || ewidth > width)
396
+ height -= eheight if (devexcuse)
397
+ end
398
+ if (fortune)
399
+ fheight = fortune.split("\n").length
400
+ fwidth = fortune.split("\n").map(&:length).max
401
+ fortune = nil if (height <= fheight || fwidth > width)
402
+ height -= fheight if (fortune)
403
+ end
404
+ arTTY.fits(width, height)
405
+ end
406
+
407
+ case options["action"]
408
+ when "cache"
409
+ arTTY.cache
410
+ when "demo"
411
+ arTTY.art.each do |name|
412
+ puts("### #{name} ###".white)
413
+ art = arTTY.get(name, info).draw
414
+ puts("\n#{art}\n") if (!art.empty?)
415
+ end
416
+ when "draw"
417
+ # Randomize
418
+ if (!config.art? && config.random?)
419
+ config.set_art(arTTY.random)
420
+ end
421
+
422
+ # Ensure art is not nil
423
+ config.set_art("none") if (!config.art?)
424
+
425
+ # Clear screen if requested
426
+ system("clear") if (config.clear_screen?)
427
+
428
+ art = arTTY.get(config.get_art, info).draw
429
+ puts("\n#{art}\n") if (!art.empty?)
430
+ puts(devexcuse) if (devexcuse)
431
+ puts(fortune) if (fortune)
432
+ when "generate"
433
+ puts(
434
+ ArTTY::Generator.new.generate(
435
+ options["generate"],
436
+ options["conf"].getdiff("art")
437
+ )
438
+ )
439
+ when "list"
440
+ puts(arTTY.art)
441
+ when "save"
442
+ config.save
443
+ when "show"
444
+ puts(config)
445
+ when "update"
446
+ arTTY.cache(true)
447
+ end
448
+ rescue ArTTY::Error => e
449
+ $stderr.puts(e.message.white.on_red)
450
+ if (options["verbose"])
451
+ e.backtrace.each do |line|
452
+ $stderr.puts(line.yellow)
453
+ end
454
+ end
455
+ exit ArTTYExit::EXCEPTION
456
+ rescue Interrupt
457
+ # Exit gracefully on ^C
458
+ rescue Errno::EPIPE
459
+ # Do nothing. This can happen if piping to another program such as
460
+ # less. Usually if less is closed before we're done with STDOUT.
461
+ rescue Exception => e
462
+ $stderr.puts(
463
+ [
464
+ "Oops! Looks like an error has occured! If the error",
465
+ "persists, file a bug at:"
466
+ ].join(" ").wrap
467
+ )
468
+ $stderr.puts
469
+ $stderr.puts(" https://gitlab.com/mjwhitta/arTTY/issues")
470
+ $stderr.puts
471
+ $stderr.puts(
472
+ [
473
+ "Maybe the message below will help. If not, you can use",
474
+ "the --verbose flag to get a backtrace."
475
+ ].join(" ").wrap
476
+ )
477
+
478
+ $stderr.puts(e.message.white.on_red)
479
+ if (options["verbose"])
480
+ e.backtrace.each do |line|
481
+ $stderr.puts(line.light_yellow)
482
+ end
483
+ end
484
+ exit ArTTYExit::EXCEPTION
485
+ end
486
+ exit ArTTYExit::GOOD