dorian 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +15 -0
- data/.github/workflows/ci.yml +38 -0
- data/.gitignore +30 -0
- data/.node-version +1 -0
- data/.prettierignore +2 -0
- data/.rubocop.yml +129 -0
- data/.ruby-version +1 -0
- data/.tool-versions +3 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +186 -0
- data/LICENSE +19 -0
- data/README.md +24 -0
- data/VERSION +1 -1
- data/bin/bundle +123 -0
- data/bin/bundle-audit +31 -0
- data/bin/bundler-audit +31 -0
- data/bin/rspec +31 -0
- data/bin/rubocop +31 -0
- data/dorian.gemspec +35 -0
- data/lib/dorian/bin.rb +921 -14
- data/package-lock.json +39 -0
- data/package.json +11 -0
- data/samples/books.json +33 -0
- data/samples/books.jsonl +3 -0
- data/samples/config.yml +27 -0
- data/samples/config_2.yml +22 -0
- data/samples/maths.js +1 -0
- data/samples/numbers.raw +10 -0
- data/samples/people.csv +6 -0
- data/samples/people.yml +28 -0
- data/samples/query.sql +7 -0
- data/samples/user.json +31 -0
- data/spec/dorian_spec.rb +276 -0
- data/spec/spec_helper.rb +3 -0
- data/vendor/groovy-beautify/LICENSE.MD +21 -0
- data/vendor/groovy-beautify/README.md +65 -0
- data/vendor/groovy-beautify/dist/__tests__/index.test.d.ts +1 -0
- data/vendor/groovy-beautify/dist/cjs/index.js +573 -0
- data/vendor/groovy-beautify/dist/cjs/package.json +3 -0
- data/vendor/groovy-beautify/dist/es/index.js +682 -0
- data/vendor/groovy-beautify/dist/es/package.json +3 -0
- data/vendor/groovy-beautify/dist/formatter/FormatRule.d.ts +14 -0
- data/vendor/groovy-beautify/dist/formatter/Formatter.d.ts +11 -0
- data/vendor/groovy-beautify/dist/formatter/GroovyFormatRules.d.ts +3 -0
- data/vendor/groovy-beautify/dist/formatter/__tests__/formatter.test.d.ts +1 -0
- data/vendor/groovy-beautify/dist/index.d.ts +5 -0
- data/vendor/groovy-beautify/dist/parser/GroovyParseRules.d.ts +3 -0
- data/vendor/groovy-beautify/dist/parser/ParseRule.d.ts +23 -0
- data/vendor/groovy-beautify/dist/parser/Parser.d.ts +29 -0
- data/vendor/groovy-beautify/dist/parser/__tests__/parser.test.d.ts +1 -0
- data/vendor/groovy-beautify/dist/parser/types.d.ts +6 -0
- data/vendor/groovy-beautify/dist/utils/text.d.ts +4 -0
- data/vendor/groovy-beautify/package.json +55 -0
- data/vendor/prettier/LICENSE +4379 -0
- data/vendor/prettier/README.md +109 -0
- data/vendor/prettier/bin/prettier.cjs +71 -0
- data/vendor/prettier/doc.d.ts +243 -0
- data/vendor/prettier/doc.js +1545 -0
- data/vendor/prettier/doc.mjs +1503 -0
- data/vendor/prettier/index.cjs +825 -0
- data/vendor/prettier/index.d.ts +941 -0
- data/vendor/prettier/index.mjs +25899 -0
- data/vendor/prettier/internal/cli.mjs +4366 -0
- data/vendor/prettier/package.json +198 -0
- data/vendor/prettier/plugins/acorn.d.ts +6 -0
- data/vendor/prettier/plugins/acorn.js +6618 -0
- data/vendor/prettier/plugins/acorn.mjs +6456 -0
- data/vendor/prettier/plugins/angular.d.ts +8 -0
- data/vendor/prettier/plugins/angular.js +2435 -0
- data/vendor/prettier/plugins/angular.mjs +2375 -0
- data/vendor/prettier/plugins/babel.d.ts +18 -0
- data/vendor/prettier/plugins/babel.js +14271 -0
- data/vendor/prettier/plugins/babel.mjs +13986 -0
- data/vendor/prettier/plugins/estree.d.ts +1 -0
- data/vendor/prettier/plugins/estree.js +9487 -0
- data/vendor/prettier/plugins/estree.mjs +9279 -0
- data/vendor/prettier/plugins/flow.d.ts +5 -0
- data/vendor/prettier/plugins/flow.js +51477 -0
- data/vendor/prettier/plugins/flow.mjs +51219 -0
- data/vendor/prettier/plugins/glimmer.d.ts +5 -0
- data/vendor/prettier/plugins/glimmer.js +8534 -0
- data/vendor/prettier/plugins/glimmer.mjs +8421 -0
- data/vendor/prettier/plugins/graphql.d.ts +5 -0
- data/vendor/prettier/plugins/graphql.js +2421 -0
- data/vendor/prettier/plugins/graphql.mjs +2347 -0
- data/vendor/prettier/plugins/html.d.ts +8 -0
- data/vendor/prettier/plugins/html.js +8182 -0
- data/vendor/prettier/plugins/html.mjs +8077 -0
- data/vendor/prettier/plugins/markdown.d.ts +7 -0
- data/vendor/prettier/plugins/markdown.js +9068 -0
- data/vendor/prettier/plugins/markdown.mjs +8977 -0
- data/vendor/prettier/plugins/meriyah.d.ts +5 -0
- data/vendor/prettier/plugins/meriyah.js +5953 -0
- data/vendor/prettier/plugins/meriyah.mjs +5800 -0
- data/vendor/prettier/plugins/postcss.d.ts +7 -0
- data/vendor/prettier/plugins/postcss.js +9244 -0
- data/vendor/prettier/plugins/postcss.mjs +9046 -0
- data/vendor/prettier/plugins/typescript.d.ts +5 -0
- data/vendor/prettier/plugins/typescript.js +38058 -0
- data/vendor/prettier/plugins/typescript.mjs +37732 -0
- data/vendor/prettier/plugins/yaml.d.ts +5 -0
- data/vendor/prettier/plugins/yaml.js +7425 -0
- data/vendor/prettier/plugins/yaml.mjs +7329 -0
- data/vendor/prettier/standalone.d.ts +33 -0
- data/vendor/prettier/standalone.js +3984 -0
- data/vendor/prettier/standalone.mjs +3938 -0
- data/vendor/sql-formatter.js +18762 -0
- metadata +207 -4
data/lib/dorian/bin.rb
CHANGED
|
@@ -6,14 +6,82 @@ require "dorian/eval"
|
|
|
6
6
|
require "dorian/progress"
|
|
7
7
|
require "dorian/to_struct"
|
|
8
8
|
require "git"
|
|
9
|
+
require "hexapdf"
|
|
9
10
|
require "json"
|
|
11
|
+
require "mini_racer"
|
|
10
12
|
require "net/http"
|
|
11
13
|
require "parallel"
|
|
14
|
+
require "shellwords"
|
|
15
|
+
require "syntax_tree"
|
|
16
|
+
require "syntax_tree/erb"
|
|
17
|
+
require "syntax_tree/haml"
|
|
18
|
+
require "syntax_tree/xml"
|
|
19
|
+
require "syntax_tree/json"
|
|
20
|
+
require "tempfile"
|
|
21
|
+
require "terminal-table"
|
|
12
22
|
require "uri"
|
|
13
23
|
require "yaml"
|
|
14
24
|
|
|
15
25
|
class Dorian
|
|
16
26
|
class Bin
|
|
27
|
+
RUBY_EXTENSIONS = %w[
|
|
28
|
+
.rb
|
|
29
|
+
.arb
|
|
30
|
+
.axlsx
|
|
31
|
+
.builder
|
|
32
|
+
.fcgi
|
|
33
|
+
.gemfile
|
|
34
|
+
.gemspec
|
|
35
|
+
.god
|
|
36
|
+
.jb
|
|
37
|
+
.jbuilder
|
|
38
|
+
.mspec
|
|
39
|
+
.opal
|
|
40
|
+
.pluginspec
|
|
41
|
+
.podspec
|
|
42
|
+
.rabl
|
|
43
|
+
.rake
|
|
44
|
+
.rbuild
|
|
45
|
+
.rbw
|
|
46
|
+
.rbx
|
|
47
|
+
.ru
|
|
48
|
+
.ruby
|
|
49
|
+
.schema
|
|
50
|
+
.spec
|
|
51
|
+
.thor
|
|
52
|
+
.watchr
|
|
53
|
+
].freeze
|
|
54
|
+
|
|
55
|
+
RUBY_FILENAMES = %w[
|
|
56
|
+
.irbrc
|
|
57
|
+
.pryrc
|
|
58
|
+
.simplecov
|
|
59
|
+
Appraisals
|
|
60
|
+
Berksfile
|
|
61
|
+
Brewfile
|
|
62
|
+
Buildfile
|
|
63
|
+
Capfile
|
|
64
|
+
Cheffile
|
|
65
|
+
Dangerfile
|
|
66
|
+
Deliverfile
|
|
67
|
+
Fastfile
|
|
68
|
+
Gemfile
|
|
69
|
+
Guardfile
|
|
70
|
+
Jarfile
|
|
71
|
+
Mavenfile
|
|
72
|
+
Podfile
|
|
73
|
+
Puppetfile
|
|
74
|
+
Rakefile
|
|
75
|
+
rakefile
|
|
76
|
+
Schemafile
|
|
77
|
+
Snapfile
|
|
78
|
+
Steepfile
|
|
79
|
+
Thorfile
|
|
80
|
+
Vagabondfile
|
|
81
|
+
Vagrantfile
|
|
82
|
+
buildfile
|
|
83
|
+
].freeze
|
|
84
|
+
|
|
17
85
|
VERSION = File.read(File.expand_path("../../VERSION", __dir__))
|
|
18
86
|
|
|
19
87
|
DEFAULT_IO = :raw
|
|
@@ -51,8 +119,7 @@ class Dorian
|
|
|
51
119
|
alias: :o
|
|
52
120
|
},
|
|
53
121
|
parallel: {
|
|
54
|
-
alias: :p
|
|
55
|
-
default: true
|
|
122
|
+
alias: :p
|
|
56
123
|
},
|
|
57
124
|
parallel_type: {
|
|
58
125
|
alias: :pt,
|
|
@@ -87,7 +154,9 @@ class Dorian
|
|
|
87
154
|
alias: :d
|
|
88
155
|
},
|
|
89
156
|
progress: :boolean,
|
|
90
|
-
headers: {
|
|
157
|
+
headers: {
|
|
158
|
+
default: true
|
|
159
|
+
},
|
|
91
160
|
progress_format: {
|
|
92
161
|
alias: :pf,
|
|
93
162
|
type: :string
|
|
@@ -96,6 +165,7 @@ class Dorian
|
|
|
96
165
|
default: true
|
|
97
166
|
},
|
|
98
167
|
io: :string,
|
|
168
|
+
self: :boolean,
|
|
99
169
|
version: {
|
|
100
170
|
alias: :v
|
|
101
171
|
},
|
|
@@ -179,6 +249,107 @@ class Dorian
|
|
|
179
249
|
arguments.delete("commit")
|
|
180
250
|
@command = :commit
|
|
181
251
|
command_commit
|
|
252
|
+
when :compare
|
|
253
|
+
arguments.delete("compare")
|
|
254
|
+
@command = :compare
|
|
255
|
+
command_compare
|
|
256
|
+
when :dir
|
|
257
|
+
arguments.delete("dir")
|
|
258
|
+
@command = :dir
|
|
259
|
+
command_dir
|
|
260
|
+
when :submodules
|
|
261
|
+
arguments.delete("submodules")
|
|
262
|
+
@command = :submodules
|
|
263
|
+
command_submodules
|
|
264
|
+
when :dot
|
|
265
|
+
arguments.delete("dot")
|
|
266
|
+
@command = :dot
|
|
267
|
+
command_dot
|
|
268
|
+
when :eval
|
|
269
|
+
arguments.delete("eval")
|
|
270
|
+
@command = :eval
|
|
271
|
+
command_eval
|
|
272
|
+
when :ls
|
|
273
|
+
arguments.delete("ls")
|
|
274
|
+
@command = :ls
|
|
275
|
+
command_ls
|
|
276
|
+
when :strip
|
|
277
|
+
arguments.delete("strip")
|
|
278
|
+
@command = :strip
|
|
279
|
+
command_strip
|
|
280
|
+
when :rstrip
|
|
281
|
+
arguments.delete("rstrip")
|
|
282
|
+
@command = :rstrip
|
|
283
|
+
command_rstrip
|
|
284
|
+
when :lstrip
|
|
285
|
+
arguments.delete("lstrip")
|
|
286
|
+
@command = :lstrip
|
|
287
|
+
command_lstrip
|
|
288
|
+
when :merge
|
|
289
|
+
arguments.delete("merge")
|
|
290
|
+
@command = :merge
|
|
291
|
+
command_merge
|
|
292
|
+
when :pluck
|
|
293
|
+
arguments.delete("pluck")
|
|
294
|
+
@command = :pluck
|
|
295
|
+
command_pluck
|
|
296
|
+
when :shuffle
|
|
297
|
+
arguments.delete("shuffle")
|
|
298
|
+
@command = :shuffle
|
|
299
|
+
command_shuffle
|
|
300
|
+
when :rename
|
|
301
|
+
arguments.delete("rename")
|
|
302
|
+
@command = :rename
|
|
303
|
+
command_rename
|
|
304
|
+
when :replace
|
|
305
|
+
arguments.delete("replace")
|
|
306
|
+
@command = :replace
|
|
307
|
+
command_replace
|
|
308
|
+
when :sort
|
|
309
|
+
arguments.delete("sort")
|
|
310
|
+
@command = :sort
|
|
311
|
+
command_sort
|
|
312
|
+
when :table
|
|
313
|
+
arguments.delete("table")
|
|
314
|
+
@command = :table
|
|
315
|
+
command_table
|
|
316
|
+
when :then
|
|
317
|
+
arguments.delete("then")
|
|
318
|
+
@command = :then
|
|
319
|
+
@ruby = arguments.delete_at(0)
|
|
320
|
+
command_then
|
|
321
|
+
when :times
|
|
322
|
+
arguments.delete("times")
|
|
323
|
+
@command = :times
|
|
324
|
+
command_times
|
|
325
|
+
when :uniq
|
|
326
|
+
arguments.delete("uniq")
|
|
327
|
+
@command = :uniq
|
|
328
|
+
command_uniq
|
|
329
|
+
when :write
|
|
330
|
+
arguments.delete("write")
|
|
331
|
+
@command = :write
|
|
332
|
+
command_write
|
|
333
|
+
when :release
|
|
334
|
+
arguments.delete("release")
|
|
335
|
+
@command = :release
|
|
336
|
+
command_release
|
|
337
|
+
when :top
|
|
338
|
+
arguments.delete("top")
|
|
339
|
+
@command = :top
|
|
340
|
+
command_top
|
|
341
|
+
when :tree
|
|
342
|
+
arguments.delete("tree")
|
|
343
|
+
@command = :tree
|
|
344
|
+
command_tree
|
|
345
|
+
when :format
|
|
346
|
+
arguments.delete("format")
|
|
347
|
+
@command = :format
|
|
348
|
+
command_format
|
|
349
|
+
when :pretty
|
|
350
|
+
arguments.delete("pretty")
|
|
351
|
+
@command = :pretty
|
|
352
|
+
command_pretty
|
|
182
353
|
else
|
|
183
354
|
arguments.delete("read")
|
|
184
355
|
@command = :read
|
|
@@ -186,10 +357,219 @@ class Dorian
|
|
|
186
357
|
end
|
|
187
358
|
end
|
|
188
359
|
|
|
360
|
+
def command_pretty
|
|
361
|
+
command_format
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def command_format
|
|
365
|
+
context = MiniRacer::Context.new
|
|
366
|
+
context.attach("puts", proc { |string| puts(string) })
|
|
367
|
+
context.attach("warn", proc { |string| warn(string) })
|
|
368
|
+
context.attach("read", proc { |path| File.read(path) })
|
|
369
|
+
context.attach(
|
|
370
|
+
"write",
|
|
371
|
+
proc { |path, content| File.write(path, content) }
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
root = File.expand_path("../../", __dir__)
|
|
375
|
+
|
|
376
|
+
prettier_path = File.join(root, "vendor/prettier/standalone.js")
|
|
377
|
+
prettier_js = File.read(prettier_path)
|
|
378
|
+
context.eval(prettier_js)
|
|
379
|
+
|
|
380
|
+
sql_path = File.join(root, "vendor/sql-formatter.js")
|
|
381
|
+
sql_js = File.read(sql_path)
|
|
382
|
+
context.eval("self = {};")
|
|
383
|
+
context.eval(sql_js)
|
|
384
|
+
context.eval("sqlFormatter = self.sqlFormatter;")
|
|
385
|
+
|
|
386
|
+
groovy_path = File.join(root, "vendor/groovy-beautify/dist/cjs/index.js")
|
|
387
|
+
groovy_js = File.read(groovy_path)
|
|
388
|
+
context.eval("module = { exports: {} };")
|
|
389
|
+
context.eval("exports = module.exports;")
|
|
390
|
+
context.eval(groovy_js)
|
|
391
|
+
context.eval("groovyBeautify = module.exports;")
|
|
392
|
+
|
|
393
|
+
plugins = %w[babel estree typescript html postcss markdown]
|
|
394
|
+
|
|
395
|
+
plugins.each do |plugin|
|
|
396
|
+
path = File.join(root, "vendor/prettier/plugins/#{plugin}.js")
|
|
397
|
+
js = File.read(path)
|
|
398
|
+
context.eval("module = { exports: {} };")
|
|
399
|
+
context.eval("exports = module.exports;")
|
|
400
|
+
context.eval(js)
|
|
401
|
+
context.eval("#{plugin} = module.exports;")
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
context.eval("plugins = [#{plugins.join(", ")}];")
|
|
405
|
+
|
|
406
|
+
context.eval(<<~JS)
|
|
407
|
+
format = async (path, parser) => {
|
|
408
|
+
try {
|
|
409
|
+
const before = read(path);
|
|
410
|
+
let after;
|
|
411
|
+
|
|
412
|
+
if (parser === "sql") {
|
|
413
|
+
after = sqlFormatter.format(before);
|
|
414
|
+
} else if (parser === "groovy") {
|
|
415
|
+
after = groovyBeautify(before);
|
|
416
|
+
} else {
|
|
417
|
+
after = await prettier.format(before, { parser, plugins });
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (before != after) {
|
|
421
|
+
puts(path);
|
|
422
|
+
write(path, after);
|
|
423
|
+
}
|
|
424
|
+
} catch (e) {
|
|
425
|
+
warn(`failed to parse ${path}: ${e.message.split("\\n")[0]}`);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
JS
|
|
429
|
+
|
|
430
|
+
if files.any?
|
|
431
|
+
each(files) { |file| format(file, context:) }
|
|
432
|
+
else
|
|
433
|
+
each(
|
|
434
|
+
Git.open(".").ls_files.map(&:first)
|
|
435
|
+
) { |file| format(file, context:) }
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def command_release
|
|
440
|
+
File.delete(*Dir["*.gem"])
|
|
441
|
+
system("gem build")
|
|
442
|
+
system("gem push *.gem")
|
|
443
|
+
File.delete(*Dir["*.gem"])
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def command_top
|
|
447
|
+
shell = arguments[0] || File.basename(ENV.fetch("SHELL", nil)) || "bash"
|
|
448
|
+
limit = arguments[1] || 10
|
|
449
|
+
|
|
450
|
+
history =
|
|
451
|
+
case shell.to_s.downcase
|
|
452
|
+
when "fish"
|
|
453
|
+
File
|
|
454
|
+
.read("#{Dir.home}/.local/share/fish/fish_history")
|
|
455
|
+
.lines
|
|
456
|
+
.grep(/^- cmd: /)
|
|
457
|
+
.map { |line| line.split("- cmd: ", 2).last.strip }
|
|
458
|
+
when "bash"
|
|
459
|
+
File.read("#{Dir.home}/.bash_history").lines.map(&:strip)
|
|
460
|
+
when "zsh"
|
|
461
|
+
File.read("#{Dir.home}/.zsh_history").lines.map(&:strip)
|
|
462
|
+
else
|
|
463
|
+
raise NotImplementedError, shell
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
table(
|
|
467
|
+
history
|
|
468
|
+
.map { |line| line.split.first }
|
|
469
|
+
.tally
|
|
470
|
+
.to_a
|
|
471
|
+
.sort_by(&:last)
|
|
472
|
+
.reverse
|
|
473
|
+
.map
|
|
474
|
+
.with_index do |(command, command_count), index|
|
|
475
|
+
{
|
|
476
|
+
"#" => index + 1,
|
|
477
|
+
:count => command_count,
|
|
478
|
+
:percent =>
|
|
479
|
+
"#{(command_count * 100 / history.size.to_f).round(3)}%",
|
|
480
|
+
:command => command
|
|
481
|
+
}
|
|
482
|
+
end
|
|
483
|
+
.first(limit)
|
|
484
|
+
)
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def command_tree
|
|
488
|
+
space = " "
|
|
489
|
+
right = "└── "
|
|
490
|
+
down = "│ "
|
|
491
|
+
down_and_right = "├── "
|
|
492
|
+
|
|
493
|
+
git_ls_files = ->(path) { Git.open(".").ls_files(path).map(&:first) }
|
|
494
|
+
|
|
495
|
+
group =
|
|
496
|
+
lambda do |files|
|
|
497
|
+
files
|
|
498
|
+
.group_by { |file| file.split("/").first }
|
|
499
|
+
.transform_values do |values|
|
|
500
|
+
group.call(
|
|
501
|
+
values
|
|
502
|
+
.map { |value| value.split("/")[1..].join("/") }
|
|
503
|
+
.reject(&:empty?)
|
|
504
|
+
)
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
print =
|
|
509
|
+
lambda do |key:, values:, index: 0, size: 1, prefix: ""|
|
|
510
|
+
key = "#{key}/" if values.any?
|
|
511
|
+
last = index + 1 == size
|
|
512
|
+
right_prefix = last ? right : down_and_right
|
|
513
|
+
puts prefix + right_prefix + key
|
|
514
|
+
values.each.with_index do |(value_key, value_values), value_index|
|
|
515
|
+
print.call(
|
|
516
|
+
key: value_key,
|
|
517
|
+
values: value_values,
|
|
518
|
+
index: value_index,
|
|
519
|
+
size: values.size,
|
|
520
|
+
prefix: prefix + (last ? space : down)
|
|
521
|
+
)
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
keys = (arguments + files)
|
|
526
|
+
keys = ["."] unless keys.any?
|
|
527
|
+
|
|
528
|
+
keys.each do |key|
|
|
529
|
+
files =
|
|
530
|
+
git_ls_files
|
|
531
|
+
.call(key)
|
|
532
|
+
.map { |file| parsed.arguments.any? ? file.sub(key, "") : file }
|
|
533
|
+
values = group.call(files)
|
|
534
|
+
key = "#{key}/" if values.any? && key != "." && key[-1] != "/"
|
|
535
|
+
puts key
|
|
536
|
+
values.each.with_index do |(value_key, value_values), value_index|
|
|
537
|
+
print.call(
|
|
538
|
+
key: value_key,
|
|
539
|
+
values: value_values,
|
|
540
|
+
index: value_index,
|
|
541
|
+
size: values.size
|
|
542
|
+
)
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
189
547
|
def files
|
|
190
548
|
parsed.files
|
|
191
549
|
end
|
|
192
550
|
|
|
551
|
+
def command_times
|
|
552
|
+
map(everything, &:to_i).sum.times { |index| puts index + 1 }
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def command_eval
|
|
556
|
+
each(everything) { |thing| outputs(evaluates(ruby: thing)) }
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def command_then
|
|
560
|
+
each(stdin_files + files) do |input|
|
|
561
|
+
outputs(evaluates(it: reads(File.read(input))), file: input)
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
each(stdin_arguments + arguments) do |input|
|
|
565
|
+
outputs(evaluates(it: reads(input)))
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def command_table
|
|
570
|
+
table(map(everything) { |thing| lines(reads(thing)) }.inject(&:+))
|
|
571
|
+
end
|
|
572
|
+
|
|
193
573
|
def command_chat
|
|
194
574
|
puts completion(
|
|
195
575
|
token: token(".chat"),
|
|
@@ -227,6 +607,39 @@ class Dorian
|
|
|
227
607
|
puts message
|
|
228
608
|
end
|
|
229
609
|
|
|
610
|
+
def command_replace
|
|
611
|
+
from, to = arguments
|
|
612
|
+
|
|
613
|
+
each(stdin_files + stdin_arguments + files) do |file|
|
|
614
|
+
next if File.directory?(file)
|
|
615
|
+
|
|
616
|
+
File.write(file, File.read(file).gsub(from, to))
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def command_rename
|
|
621
|
+
from, to = arguments
|
|
622
|
+
files = stdin_files + stdin_arguments + self.files
|
|
623
|
+
(files - directories).each { |file| rename(file, file.gsub(from, to)) }
|
|
624
|
+
directories.each { |dir| rename(dir, dir.gsub(from, to)) }
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def directories
|
|
628
|
+
(stdin_files + files).select { |file| File.directory?(file) }
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
def rename(old, new)
|
|
632
|
+
return if old == new
|
|
633
|
+
|
|
634
|
+
puts "#{old} -> #{new}"
|
|
635
|
+
File.rename(old, new)
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
def command_write
|
|
639
|
+
content = read_stdin.join
|
|
640
|
+
each(files + arguments) { |file| File.write(file, content) }
|
|
641
|
+
end
|
|
642
|
+
|
|
230
643
|
def command_read
|
|
231
644
|
each(stdin_files + files) do |input|
|
|
232
645
|
outputs(reads(File.read(input)), file: input)
|
|
@@ -235,16 +648,179 @@ class Dorian
|
|
|
235
648
|
each(stdin_arguments + arguments) { |input| outputs(reads(input)) }
|
|
236
649
|
end
|
|
237
650
|
|
|
651
|
+
def command_strip
|
|
652
|
+
each(stdin_files + files) do |input|
|
|
653
|
+
outputs(lines(reads(File.read(input)), strip: :strip), file: input)
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
each(stdin_arguments + arguments) do |input|
|
|
657
|
+
outputs(lines(reads(input), strip: :strip))
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
def command_rstrip
|
|
662
|
+
each(stdin_files + files) do |input|
|
|
663
|
+
outputs(lines(reads(File.read(input)), strip: :rstrip), file: input)
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
each(stdin_arguments + arguments) do |input|
|
|
667
|
+
outputs(lines(reads(input), strip: :rstrip))
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def command_lstrip
|
|
672
|
+
each(stdin_files + files) do |input|
|
|
673
|
+
outputs(lines(reads(File.read(input)), strip: :lstrip), file: input)
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
each(stdin_arguments + arguments) do |input|
|
|
677
|
+
outputs(lines(reads(input), strip: :lstrip))
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
238
681
|
def everything
|
|
239
682
|
read_stdin_files + stdin_arguments + read_files + arguments
|
|
240
683
|
end
|
|
241
684
|
|
|
685
|
+
def command_dir
|
|
686
|
+
puts(
|
|
687
|
+
Git
|
|
688
|
+
.open(".")
|
|
689
|
+
.ls_files
|
|
690
|
+
.map(&:first)
|
|
691
|
+
.map { |path| path.split("/").first }
|
|
692
|
+
.select { |path| Dir.exist?(path) }
|
|
693
|
+
.reject { |path| path.start_with?(".") }
|
|
694
|
+
.sort
|
|
695
|
+
.uniq
|
|
696
|
+
)
|
|
697
|
+
|
|
698
|
+
puts "." if self?
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def command_ls
|
|
702
|
+
puts(
|
|
703
|
+
Git
|
|
704
|
+
.open(".")
|
|
705
|
+
.ls_files
|
|
706
|
+
.map(&:first)
|
|
707
|
+
.map { |path| path.split("/").first }
|
|
708
|
+
.reject { |path| path.start_with?(".") }
|
|
709
|
+
.select { |path| match_filetypes?(path) }
|
|
710
|
+
.sort
|
|
711
|
+
.uniq
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
puts "." if self?
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
def command_submodules
|
|
718
|
+
puts(
|
|
719
|
+
File
|
|
720
|
+
.read(".gitmodules")
|
|
721
|
+
.lines
|
|
722
|
+
.grep(/path = /)
|
|
723
|
+
.map { |path| path.split("=").last.strip }
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
puts "." if self?
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
def command_dot
|
|
730
|
+
dir = files.first || arguments.first || "."
|
|
731
|
+
|
|
732
|
+
ignore_file = File.expand_path("#{dir.chomp("/")}/.dotignore")
|
|
733
|
+
ignore_content = File.exist?(ignore_file) ? File.read(ignore_file) : ""
|
|
734
|
+
ignore_patterns =
|
|
735
|
+
ignore_content
|
|
736
|
+
.lines
|
|
737
|
+
.map(&:strip)
|
|
738
|
+
.reject { |line| line.empty? || line.start_with?("#") }
|
|
739
|
+
.map { |pattern| Regexp.new("\\A#{pattern}\\z") }
|
|
740
|
+
|
|
741
|
+
Git
|
|
742
|
+
.open(dir)
|
|
743
|
+
.ls_files
|
|
744
|
+
.map(&:first)
|
|
745
|
+
.each do |file|
|
|
746
|
+
next if ignore_patterns.any? { |pattern| pattern.match?(file) }
|
|
747
|
+
|
|
748
|
+
homefile = "#{Dir.home}/#{file}"
|
|
749
|
+
dotfile = File.expand_path("#{dir.chomp("/")}/#{file}")
|
|
750
|
+
if File.exist?(homefile) || File.symlink?(homefile)
|
|
751
|
+
File.delete(homefile)
|
|
752
|
+
end
|
|
753
|
+
FileUtils.mkdir_p(File.dirname(homefile))
|
|
754
|
+
FileUtils.ln_s(dotfile, homefile, verbose: true)
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
def self?
|
|
759
|
+
!!options.self
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
def command_compare
|
|
763
|
+
file_1, file_2 = files
|
|
764
|
+
key_1, key_2 = arguments
|
|
765
|
+
read_1, read_2 =
|
|
766
|
+
files.map.with_index do |file, index|
|
|
767
|
+
read = reads(File.read(file))
|
|
768
|
+
|
|
769
|
+
if arguments[index] && read.from_deep_struct.key?(arguments[index])
|
|
770
|
+
read[arguments[index]]
|
|
771
|
+
elsif arguments[index]
|
|
772
|
+
nil
|
|
773
|
+
else
|
|
774
|
+
read
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
compare(read_1, read_2, file_1:, file_2:)
|
|
779
|
+
end
|
|
780
|
+
|
|
242
781
|
def command_each
|
|
243
782
|
each(everything) do |input|
|
|
244
783
|
each(lines(reads(input)), progress: true) { |line| evaluates(it: line) }
|
|
245
784
|
end
|
|
246
785
|
end
|
|
247
786
|
|
|
787
|
+
def command_merge
|
|
788
|
+
outputs(map(everything) { |thing| lines(reads(thing)) }.inject(&:+))
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
def command_sort
|
|
792
|
+
outputs(
|
|
793
|
+
map(everything) { |thing| lines(reads(thing)) }
|
|
794
|
+
.inject(&:+)
|
|
795
|
+
.sort_by do |line|
|
|
796
|
+
result = pluck(line).from_deep_struct
|
|
797
|
+
result.is_a?(Hash) ? result.values : result
|
|
798
|
+
end
|
|
799
|
+
)
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
def command_uniq
|
|
803
|
+
outputs(
|
|
804
|
+
map(everything) { |thing| lines(reads(thing)) }
|
|
805
|
+
.inject(&:+)
|
|
806
|
+
.uniq { |line| pluck(line) }
|
|
807
|
+
)
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
def command_pluck
|
|
811
|
+
outputs(
|
|
812
|
+
map(everything) do |thing|
|
|
813
|
+
map(lines(reads(thing))) { |line| pluck(line) }
|
|
814
|
+
end.inject(&:+)
|
|
815
|
+
)
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
def command_shuffle
|
|
819
|
+
outputs(
|
|
820
|
+
map(everything) { |thing| lines(reads(thing)) }.inject(&:+).shuffle
|
|
821
|
+
)
|
|
822
|
+
end
|
|
823
|
+
|
|
248
824
|
def command_tally
|
|
249
825
|
each(everything) do |input|
|
|
250
826
|
outputs(
|
|
@@ -253,7 +829,7 @@ class Dorian
|
|
|
253
829
|
if ruby.to_s.empty?
|
|
254
830
|
element
|
|
255
831
|
else
|
|
256
|
-
evaluates(it: element, returns: true, stdout: false)
|
|
832
|
+
evaluates(it: element, returns: true, stdout: false)
|
|
257
833
|
end
|
|
258
834
|
end.tally
|
|
259
835
|
)
|
|
@@ -268,11 +844,13 @@ class Dorian
|
|
|
268
844
|
end
|
|
269
845
|
|
|
270
846
|
def command_append
|
|
271
|
-
outputs(everything
|
|
847
|
+
outputs(map(everything) { |input| lines(reads(input)) }.inject(&:+))
|
|
272
848
|
end
|
|
273
849
|
|
|
274
850
|
def command_prepend
|
|
275
|
-
outputs(
|
|
851
|
+
outputs(
|
|
852
|
+
map(everything.reverse) { |input| lines(reads(input)) }.inject(&:+)
|
|
853
|
+
)
|
|
276
854
|
end
|
|
277
855
|
|
|
278
856
|
def command_select
|
|
@@ -344,7 +922,7 @@ class Dorian
|
|
|
344
922
|
def outputs(content, file: nil)
|
|
345
923
|
if write? && file
|
|
346
924
|
File.write(file, to_output(content))
|
|
347
|
-
|
|
925
|
+
elsif !content.nil?
|
|
348
926
|
puts to_output(content)
|
|
349
927
|
end
|
|
350
928
|
end
|
|
@@ -362,12 +940,14 @@ class Dorian
|
|
|
362
940
|
end.join
|
|
363
941
|
when :json
|
|
364
942
|
pretty? ? JSON.pretty_generate(content) : content.to_json
|
|
365
|
-
when :jsonl
|
|
366
|
-
map(content, &:to_json).join("\n")
|
|
943
|
+
when :jsonl
|
|
944
|
+
"#{map(content, &:to_json).join("\n")}\n"
|
|
367
945
|
when :raw
|
|
368
946
|
content
|
|
369
947
|
when :yaml
|
|
370
948
|
content.to_yaml
|
|
949
|
+
when :yamll
|
|
950
|
+
"#{map(map(content, &:to_yaml), &:to_json).join("\n")}\n"
|
|
371
951
|
else
|
|
372
952
|
abort "#{output.inspect} not supported"
|
|
373
953
|
end
|
|
@@ -383,12 +963,16 @@ class Dorian
|
|
|
383
963
|
end
|
|
384
964
|
when :json
|
|
385
965
|
JSON.parse(content).to_deep_struct
|
|
386
|
-
when :jsonl
|
|
966
|
+
when :jsonl
|
|
387
967
|
map(content.lines) { |line| JSON.parse(line) }.to_deep_struct
|
|
388
968
|
when :raw
|
|
389
969
|
content
|
|
390
970
|
when :yaml
|
|
391
971
|
YAML.safe_load(content).to_deep_struct
|
|
972
|
+
when :yamll
|
|
973
|
+
map(content.lines) do |line|
|
|
974
|
+
YAML.safe_load(JSON.parse(line))
|
|
975
|
+
end.to_deep_struct
|
|
392
976
|
else
|
|
393
977
|
abort "#{input.inspect} not supported"
|
|
394
978
|
end
|
|
@@ -597,9 +1181,9 @@ class Dorian
|
|
|
597
1181
|
end
|
|
598
1182
|
end
|
|
599
1183
|
|
|
600
|
-
def lines(input)
|
|
1184
|
+
def lines(input, strip: :rstrip)
|
|
601
1185
|
if input.is_a?(String)
|
|
602
|
-
input.lines.map(
|
|
1186
|
+
input.lines.map(&strip)
|
|
603
1187
|
elsif deep?
|
|
604
1188
|
deep_lines(input)
|
|
605
1189
|
else
|
|
@@ -702,7 +1286,7 @@ class Dorian
|
|
|
702
1286
|
end
|
|
703
1287
|
|
|
704
1288
|
def match?(element, ruby: @ruby)
|
|
705
|
-
!!evaluates(ruby:, it: element, stdout: false, returns: true)
|
|
1289
|
+
!!evaluates(ruby:, it: element, stdout: false, returns: true)
|
|
706
1290
|
end
|
|
707
1291
|
|
|
708
1292
|
def token(file)
|
|
@@ -750,6 +1334,57 @@ class Dorian
|
|
|
750
1334
|
http.request(request).body
|
|
751
1335
|
end
|
|
752
1336
|
|
|
1337
|
+
def compare(content_1, content_2, file_1:, file_2:, path: ".")
|
|
1338
|
+
content_1 = content_1.from_deep_struct
|
|
1339
|
+
content_2 = content_2.from_deep_struct
|
|
1340
|
+
|
|
1341
|
+
if content_1.is_a?(Hash) && content_2.is_a?(Hash)
|
|
1342
|
+
(content_1.keys + content_2.keys).uniq.each do |key|
|
|
1343
|
+
new_path = path == "." ? "#{path}#{key}" : "#{path}.#{key}"
|
|
1344
|
+
|
|
1345
|
+
if content_1[key] && !content_2[key]
|
|
1346
|
+
warn "#{new_path} present in #{file_1} but not in #{file_2}"
|
|
1347
|
+
next
|
|
1348
|
+
elsif !content_1[key] && content_2[key]
|
|
1349
|
+
warn "#{new_path} present in #{file_2} but not in #{file_1}"
|
|
1350
|
+
next
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
compare(
|
|
1354
|
+
content_1[key],
|
|
1355
|
+
content_2[key],
|
|
1356
|
+
path: new_path,
|
|
1357
|
+
file_1:,
|
|
1358
|
+
file_2:
|
|
1359
|
+
)
|
|
1360
|
+
end
|
|
1361
|
+
elsif content_1.is_a?(Array) && content_2.is_a?(Array)
|
|
1362
|
+
(0...([content_1.size, content_2.size].max)).each do |index|
|
|
1363
|
+
new_path = "#{path}[#{index}]"
|
|
1364
|
+
if content_1[index] && !content_2[index]
|
|
1365
|
+
warn "#{new_path} present in #{file_1} but not in #{file_2}"
|
|
1366
|
+
next
|
|
1367
|
+
elsif !content_1[index] && content_2[index]
|
|
1368
|
+
warn "#{new_path} present in #{file_2} but not in #{file_1}"
|
|
1369
|
+
next
|
|
1370
|
+
end
|
|
1371
|
+
|
|
1372
|
+
compare(
|
|
1373
|
+
content_1[index],
|
|
1374
|
+
content_2[index],
|
|
1375
|
+
path: new_path,
|
|
1376
|
+
file_1:,
|
|
1377
|
+
file_2:
|
|
1378
|
+
)
|
|
1379
|
+
end
|
|
1380
|
+
elsif content_1.class != content_2.class
|
|
1381
|
+
warn(
|
|
1382
|
+
"#{path} has #{content_1.class} for #{file_1} " \
|
|
1383
|
+
"and #{content_2.class} for #{file_2}"
|
|
1384
|
+
)
|
|
1385
|
+
end
|
|
1386
|
+
end
|
|
1387
|
+
|
|
753
1388
|
def short(string)
|
|
754
1389
|
string[0..5000]
|
|
755
1390
|
end
|
|
@@ -758,6 +1393,67 @@ class Dorian
|
|
|
758
1393
|
Tiktoken.encoding_for_model("gpt-4o")
|
|
759
1394
|
end
|
|
760
1395
|
|
|
1396
|
+
def match_filetypes?(path, filetypes: arguments)
|
|
1397
|
+
return true if filetypes.none?
|
|
1398
|
+
return true unless filetypes.intersect?(%w[rb ruby])
|
|
1399
|
+
return false if Dir.exist?(path)
|
|
1400
|
+
return true if RUBY_FILENAMES.include?(path)
|
|
1401
|
+
return true if RUBY_EXTENSIONS.include?(File.extname(path))
|
|
1402
|
+
return false unless File.exist?(path)
|
|
1403
|
+
|
|
1404
|
+
first_line = File.open(path, &:gets).to_s
|
|
1405
|
+
first_line = first_line.encode("UTF-8", invalid: :replace)
|
|
1406
|
+
|
|
1407
|
+
return true if /\A#!.*ruby\z/.match?(first_line)
|
|
1408
|
+
|
|
1409
|
+
false
|
|
1410
|
+
end
|
|
1411
|
+
|
|
1412
|
+
def pluck(element)
|
|
1413
|
+
element = element.from_deep_struct
|
|
1414
|
+
|
|
1415
|
+
keys =
|
|
1416
|
+
if arguments.any?
|
|
1417
|
+
arguments
|
|
1418
|
+
elsif element.is_a?(Hash)
|
|
1419
|
+
element.keys
|
|
1420
|
+
elsif element.is_a?(Array)
|
|
1421
|
+
(0...(element.size)).map(&:to_s)
|
|
1422
|
+
else
|
|
1423
|
+
"it"
|
|
1424
|
+
end
|
|
1425
|
+
|
|
1426
|
+
results =
|
|
1427
|
+
keys.map do |argument|
|
|
1428
|
+
if element.is_a?(Array) && argument.to_i.to_s == argument
|
|
1429
|
+
element[argument.to_i]
|
|
1430
|
+
elsif element.is_a?(Hash) && element.key?(argument)
|
|
1431
|
+
{ argument => element[argument] }
|
|
1432
|
+
else
|
|
1433
|
+
evaluates(ruby: argument, it: element.to_deep_struct)
|
|
1434
|
+
end
|
|
1435
|
+
end
|
|
1436
|
+
|
|
1437
|
+
if results.all?(Hash)
|
|
1438
|
+
results.inject(&:merge).to_deep_struct
|
|
1439
|
+
else
|
|
1440
|
+
results
|
|
1441
|
+
.map { |result| result.is_a?(Hash) ? result.values.first : result }
|
|
1442
|
+
.to_deep_struct
|
|
1443
|
+
end
|
|
1444
|
+
end
|
|
1445
|
+
|
|
1446
|
+
def table(data)
|
|
1447
|
+
is_hashes = data.first.from_deep_struct.is_a?(Hash)
|
|
1448
|
+
headings = is_hashes ? data.first.to_h.keys : nil
|
|
1449
|
+
rows = is_hashes ? data.map(&:values) : data.map { |row| wrap(row) }
|
|
1450
|
+
if headings
|
|
1451
|
+
puts Terminal::Table.new(headings:, rows:)
|
|
1452
|
+
else
|
|
1453
|
+
puts Terminal::Table.new(rows:)
|
|
1454
|
+
end
|
|
1455
|
+
end
|
|
1456
|
+
|
|
761
1457
|
def evaluates(
|
|
762
1458
|
ruby: @ruby,
|
|
763
1459
|
it: nil,
|
|
@@ -779,7 +1475,218 @@ class Dorian
|
|
|
779
1475
|
rails:,
|
|
780
1476
|
fast:,
|
|
781
1477
|
returns:
|
|
782
|
-
)
|
|
1478
|
+
).returned
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
def sort(object)
|
|
1482
|
+
object = object.from_deep_struct
|
|
1483
|
+
|
|
1484
|
+
if object.is_a?(Hash)
|
|
1485
|
+
object
|
|
1486
|
+
.to_a
|
|
1487
|
+
.sort_by(&:first)
|
|
1488
|
+
.to_h
|
|
1489
|
+
.transform_values { |value| sort(value) }
|
|
1490
|
+
elsif object.is_a?(Array)
|
|
1491
|
+
object.map { |element| sort(element) }
|
|
1492
|
+
else
|
|
1493
|
+
object
|
|
1494
|
+
end
|
|
1495
|
+
end
|
|
1496
|
+
|
|
1497
|
+
def filetype(path)
|
|
1498
|
+
ext = File.extname(path).to_s.downcase
|
|
1499
|
+
return :directory if Dir.exist?(path)
|
|
1500
|
+
return :symlink if File.symlink?(path)
|
|
1501
|
+
return :ruby if RUBY_FILENAMES.include?(File.basename(path))
|
|
1502
|
+
return :ruby if RUBY_EXTENSIONS.include?(ext)
|
|
1503
|
+
return :json if ext == ".json"
|
|
1504
|
+
return :jsonl if ext == ".jsonl"
|
|
1505
|
+
return :yaml if ext == ".yaml"
|
|
1506
|
+
return :yaml if ext == ".yml"
|
|
1507
|
+
return :yamll if ext == ".yamll"
|
|
1508
|
+
return :yamll if ext == ".ymll"
|
|
1509
|
+
return :csv if ext == ".csv"
|
|
1510
|
+
return :js if ext == ".js"
|
|
1511
|
+
return :js if ext == ".mjs"
|
|
1512
|
+
return :js if ext == ".cjs"
|
|
1513
|
+
return :ts if ext == ".ts"
|
|
1514
|
+
return :css if ext == ".css"
|
|
1515
|
+
return :html if ext == ".html"
|
|
1516
|
+
return :html if ext == ".htm"
|
|
1517
|
+
return :haml if ext == ".haml"
|
|
1518
|
+
return :slim if ext == ".slim"
|
|
1519
|
+
return :erb if ext == ".erb"
|
|
1520
|
+
return :fish if ext == ".fish"
|
|
1521
|
+
return :sql if ext == ".sql"
|
|
1522
|
+
return :tex if ext == ".tex"
|
|
1523
|
+
return :md if ext == ".md"
|
|
1524
|
+
return :md if ext == ".markdown"
|
|
1525
|
+
return :png if ext == ".png"
|
|
1526
|
+
return :jpeg if ext == ".jpg"
|
|
1527
|
+
return :jpeg if ext == ".jpeg"
|
|
1528
|
+
return :ico if ext == ".ico"
|
|
1529
|
+
return :webp if ext == ".webp"
|
|
1530
|
+
return :heic if ext == ".heic"
|
|
1531
|
+
return :pdf if ext == ".pdf"
|
|
1532
|
+
return :raw if ext == ".raw"
|
|
1533
|
+
return :env if path == ".env"
|
|
1534
|
+
return :env if path.start_with?(".env.")
|
|
1535
|
+
return :sh if path == "Dockerfile"
|
|
1536
|
+
return :sh if ext == ".sh"
|
|
1537
|
+
return :enc if ext == ".enc"
|
|
1538
|
+
return :enc if ext == ".keystore"
|
|
1539
|
+
return :pro if ext == ".pro"
|
|
1540
|
+
return :txt if ext == ".txt"
|
|
1541
|
+
return :bat if ext == ".bat"
|
|
1542
|
+
return :xcconfig if ext == ".xcconfig"
|
|
1543
|
+
return :pbxproj if ext == ".pbxproj"
|
|
1544
|
+
return :xml if ext == ".xml"
|
|
1545
|
+
return :xml if ext == ".plist"
|
|
1546
|
+
return :xml if ext == ".storyboard"
|
|
1547
|
+
return :xml if ext == ".xcscheme"
|
|
1548
|
+
return :xml if ext == ".xcworkspacedata"
|
|
1549
|
+
return :xml if ext == ".xcprivacy"
|
|
1550
|
+
return :xml if ext == ".entitlements"
|
|
1551
|
+
return :kotlin if ext == ".kt"
|
|
1552
|
+
return :groovy if ext == ".gradle"
|
|
1553
|
+
return :groovy if ext == ".properties"
|
|
1554
|
+
return :binary if ext == ".jar"
|
|
1555
|
+
return :objectivec if ext == ".h"
|
|
1556
|
+
return :objectivec if ext == ".mm"
|
|
1557
|
+
return :objectivec if ext == ".m"
|
|
1558
|
+
return unless File.exist?(path)
|
|
1559
|
+
|
|
1560
|
+
first_line = File.open(path, &:gets).to_s
|
|
1561
|
+
first_line = first_line.encode("UTF-8", invalid: :replace).strip
|
|
1562
|
+
return :ruby if first_line == "#!/usr/bin/env ruby"
|
|
1563
|
+
return :sh if first_line == "#!/bin/bash"
|
|
1564
|
+
return :sh if first_line == "#!/bin/sh"
|
|
1565
|
+
return :sh if first_line == "#!/bin/bash -e"
|
|
1566
|
+
return :sh if first_line == "#!/usr/bin/env sh"
|
|
1567
|
+
|
|
1568
|
+
nil
|
|
1569
|
+
end
|
|
1570
|
+
|
|
1571
|
+
def format(path, context:)
|
|
1572
|
+
return if File.symlink?(path)
|
|
1573
|
+
return if File.directory?(path)
|
|
1574
|
+
return unless File.exist?(path)
|
|
1575
|
+
|
|
1576
|
+
before = File.read(path)
|
|
1577
|
+
|
|
1578
|
+
case filetype(path)
|
|
1579
|
+
when :directory
|
|
1580
|
+
when :ruby
|
|
1581
|
+
after = SyntaxTree.format(before)
|
|
1582
|
+
when :haml
|
|
1583
|
+
after = SyntaxTree::Haml.format(before)
|
|
1584
|
+
when :erb
|
|
1585
|
+
after = SyntaxTree::ERB.format(before)
|
|
1586
|
+
when :xml
|
|
1587
|
+
after = SyntaxTree::XML.format(before)
|
|
1588
|
+
when :json
|
|
1589
|
+
after = JSON.pretty_generate(JSON.parse(before))
|
|
1590
|
+
when :jsonl
|
|
1591
|
+
after = before.lines.map { |line| JSON.parse(line).to_json }.join("\n")
|
|
1592
|
+
when :csv
|
|
1593
|
+
after =
|
|
1594
|
+
CSV.generate { |csv| CSV.parse(before).each { |row| csv << row } }
|
|
1595
|
+
when :yaml
|
|
1596
|
+
after = sort(YAML.safe_load(before)).to_yaml
|
|
1597
|
+
when :yamll
|
|
1598
|
+
after =
|
|
1599
|
+
before
|
|
1600
|
+
.lines
|
|
1601
|
+
.map do |line|
|
|
1602
|
+
sort(YAML.safe_load(JSON.parse(line))).to_yaml.to_json
|
|
1603
|
+
end
|
|
1604
|
+
.join("\n") + "\n"
|
|
1605
|
+
when :js
|
|
1606
|
+
context.eval("format(#{path.to_json}, 'babel')")
|
|
1607
|
+
when :ts
|
|
1608
|
+
context.eval("format(#{path.to_json}, 'typescript')")
|
|
1609
|
+
when :html
|
|
1610
|
+
context.eval("format(#{path.to_json}, 'html')")
|
|
1611
|
+
when :md
|
|
1612
|
+
context.eval("format(#{path.to_json}, 'markdown')")
|
|
1613
|
+
when :sql
|
|
1614
|
+
context.eval("format(#{path.to_json}, 'sql')")
|
|
1615
|
+
when :groovy
|
|
1616
|
+
context.eval("format(#{path.to_json}, 'groovy')")
|
|
1617
|
+
when :css
|
|
1618
|
+
context.eval("format(#{path.to_json}, 'css')")
|
|
1619
|
+
when :sh
|
|
1620
|
+
if system("command -v shfmt > /dev/null 2>&1")
|
|
1621
|
+
command = ["shfmt", "--indent", "4", path].shelljoin
|
|
1622
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
1623
|
+
raise stderr unless stderr.empty? && status.success?
|
|
1624
|
+
|
|
1625
|
+
after = stdout
|
|
1626
|
+
else
|
|
1627
|
+
warn "run: `brew install shfmt` for #{path}"
|
|
1628
|
+
end
|
|
1629
|
+
when :pdf
|
|
1630
|
+
doc = HexaPDF::Document.open(path)
|
|
1631
|
+
doc.trailer.info.each_key { |key| doc.trailer.info.delete(key) }
|
|
1632
|
+
doc.write(path, update_fields: false)
|
|
1633
|
+
after = File.read(path)
|
|
1634
|
+
when :tex
|
|
1635
|
+
if system("command -v latexindent > /dev/null 2>&1")
|
|
1636
|
+
command = ["latexindent", path, "--logfile", "/dev/null"].shelljoin
|
|
1637
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
1638
|
+
raise stderr unless stderr.empty? && status.success?
|
|
1639
|
+
|
|
1640
|
+
after = stdout.gsub("\t", " ")
|
|
1641
|
+
else
|
|
1642
|
+
warn "run: `brew install latexindent` for #{path}"
|
|
1643
|
+
end
|
|
1644
|
+
when :objectivec
|
|
1645
|
+
if system("command -v clang-format > /dev/null 2>&1")
|
|
1646
|
+
command = ["clang-format", path].shelljoin
|
|
1647
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
1648
|
+
raise stderr unless stderr.empty? && status.success?
|
|
1649
|
+
|
|
1650
|
+
after = stdout.gsub("\t", " ")
|
|
1651
|
+
else
|
|
1652
|
+
warn "run: `brew install clang-format` for #{path}"
|
|
1653
|
+
end
|
|
1654
|
+
when :kotlin
|
|
1655
|
+
if system("command -v ktlint > /dev/null 2>&1")
|
|
1656
|
+
command = ["ktlint", "-F", path].shelljoin
|
|
1657
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
1658
|
+
raise stderr unless stderr.empty? && status.success?
|
|
1659
|
+
|
|
1660
|
+
after = File.read(path)
|
|
1661
|
+
else
|
|
1662
|
+
warn "run: `brew install ktlint` for #{path}"
|
|
1663
|
+
end
|
|
1664
|
+
when :raw, :directory, :symlink, :env, :enc, :txt, :pro, :binary, :slim,
|
|
1665
|
+
:fish, :bat, :xcconfig, :pbxproj, :jpeg, :png, :webp, :heic, :ico
|
|
1666
|
+
# nothing to do
|
|
1667
|
+
else
|
|
1668
|
+
case File.basename(path)
|
|
1669
|
+
when ".gitignore", ".node-version", ".prettierignore", ".ruby-version",
|
|
1670
|
+
".tool-versions", "Gemfile.lock", "LICENSE", "VERSION", ".rspec",
|
|
1671
|
+
"Procfile", "Procfile.dev", "Podfile.lock", ".xcode.env", "CNAME",
|
|
1672
|
+
"TODO", ".gitmodules", ".asdfrc", "config", ".dotignore", ".gemrc",
|
|
1673
|
+
".gitconfig", ".gitmessage", ".hushlogin", ".psqlrc", ".vimrc",
|
|
1674
|
+
"DIRECTORIES"
|
|
1675
|
+
# nothing to do
|
|
1676
|
+
when ".keep"
|
|
1677
|
+
File.write(path, "")
|
|
1678
|
+
else
|
|
1679
|
+
puts "unhandled: #{path}"
|
|
1680
|
+
end
|
|
1681
|
+
end
|
|
1682
|
+
|
|
1683
|
+
if after && before != after
|
|
1684
|
+
puts path
|
|
1685
|
+
File.write(path, after)
|
|
1686
|
+
end
|
|
1687
|
+
rescue StandardError => e
|
|
1688
|
+
warn "failed to parse #{path}: #{e.message}"
|
|
1689
|
+
binding.irb
|
|
783
1690
|
end
|
|
784
1691
|
end
|
|
785
1692
|
end
|