dorian 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/dorian/bin.rb +251 -2
  4. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 784498bc6998897d504352f4d0ddf7d5e447acb398928f629a1e8ece8a3588ac
4
- data.tar.gz: 5671d0b44c5021c61048ba7be6f95e9b16a822f0abd9f6a7d5e064f4cac77212
3
+ metadata.gz: a0a6f772eca1bab50085d4218db923c9cbb075d199f916b3466b3ef2b3ebcf73
4
+ data.tar.gz: cf651f86c12d4be9321eabd66ce6688c8e9080633c218e05b92ace51159a7002
5
5
  SHA512:
6
- metadata.gz: aa76e3f50983a9d002ec06a260e16b1bb135a4f9f09a4158e87af582fe13d1283870ac11d320d2c3287d6b0cf47ca157da28c31e55ef336dc3099ac31472d5b7
7
- data.tar.gz: 6521dd9fc06e9343ad01a4b4b686ffe260ff7c0f5028d41639035733935afa17dbfe2acd368db09e6afaf11a2a0491ba97c38a57b42c47dd7d7357f32207db7d
6
+ metadata.gz: ad150cb4d72cc18cc629bf5a4c4bf5348f89d057b2bdb50cb458bd85a53aadd5bbdfe6e8e3f5861fe754eb81a16d3753c81b6e622d5d63ef4034d25cd6004a76
7
+ data.tar.gz: 7a1d457ad1490a568bfd7627d7d6281057c00c2efc1720cdce96c41b0941290b50fd40ec2cc01c855e5003ab9d89dcf0640674d41c411aa8d049a8f03ac698e6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.4.0
data/lib/dorian/bin.rb CHANGED
@@ -87,7 +87,9 @@ class Dorian
87
87
  alias: :d
88
88
  },
89
89
  progress: :boolean,
90
- headers: { default: true },
90
+ headers: {
91
+ default: true
92
+ },
91
93
  progress_format: {
92
94
  alias: :pf,
93
95
  type: :string
@@ -96,6 +98,7 @@ class Dorian
96
98
  default: true
97
99
  },
98
100
  io: :string,
101
+ self: :boolean,
99
102
  version: {
100
103
  alias: :v
101
104
  },
@@ -179,6 +182,30 @@ class Dorian
179
182
  arguments.delete("commit")
180
183
  @command = :commit
181
184
  command_commit
185
+ when :compare
186
+ arguments.delete("compare")
187
+ @command = :compare
188
+ command_compare
189
+ when :dir
190
+ arguments.delete("dir")
191
+ @command = :dir
192
+ command_dir
193
+ when :submodules
194
+ arguments.delete("submodules")
195
+ @command = :submodules
196
+ command_submodules
197
+ when :dot
198
+ arguments.delete("dot")
199
+ @command = :dot
200
+ command_dot
201
+ when :eval
202
+ arguments.delete("eval")
203
+ @command = :eval
204
+ command_eval
205
+ when :ls
206
+ arguments.delete("ls")
207
+ @command = :ls
208
+ command_ls
182
209
  else
183
210
  arguments.delete("read")
184
211
  @command = :read
@@ -190,6 +217,10 @@ class Dorian
190
217
  parsed.files
191
218
  end
192
219
 
220
+ def command_eval
221
+ each(everything) { |thing| outputs(evaluates(ruby: thing).returned) }
222
+ end
223
+
193
224
  def command_chat
194
225
  puts completion(
195
226
  token: token(".chat"),
@@ -239,6 +270,100 @@ class Dorian
239
270
  read_stdin_files + stdin_arguments + read_files + arguments
240
271
  end
241
272
 
273
+ def command_dir
274
+ puts(
275
+ Git
276
+ .open(".")
277
+ .ls_files
278
+ .map(&:first)
279
+ .map { |path| path.split("/").first }
280
+ .select { |path| Dir.exist?(path) }
281
+ .reject { |path| path.start_with?(".") }
282
+ .sort
283
+ .uniq
284
+ )
285
+
286
+ puts "." if self?
287
+ end
288
+
289
+ def command_ls
290
+ puts(
291
+ Git
292
+ .open(".")
293
+ .ls_files
294
+ .map(&:first)
295
+ .map { |path| path.split("/").first }
296
+ .reject { |path| path.start_with?(".") }
297
+ .select { |path| match_filetypes?(path) }
298
+ .sort
299
+ .uniq
300
+ )
301
+
302
+ puts "." if self?
303
+ end
304
+
305
+ def command_submodules
306
+ puts(
307
+ File
308
+ .read(".gitmodules")
309
+ .lines
310
+ .grep(/path = /)
311
+ .map { |path| path.split("=").last.strip }
312
+ )
313
+
314
+ puts "." if self?
315
+ end
316
+
317
+ def command_dot
318
+ dir = files.first || arguments.first || "."
319
+
320
+ ignore_file = File.expand_path("#{dir.chomp("/")}/.dotignore")
321
+ ignore_content = File.exist?(ignore_file) ? File.read(ignore_file) : ""
322
+ ignore_patterns =
323
+ ignore_content
324
+ .lines
325
+ .map(&:strip)
326
+ .reject { |line| line.empty? || line.start_with?("#") }
327
+ .map { |pattern| Regexp.new("\\A#{pattern}\\z") }
328
+
329
+ Git
330
+ .open(dir)
331
+ .ls_files
332
+ .map(&:first)
333
+ .each do |file|
334
+ next if ignore_patterns.any? { |pattern| pattern.match?(file) }
335
+
336
+ homefile = "#{Dir.home}/#{file}"
337
+ dotfile = File.expand_path("#{dir.chomp("/")}/#{file}")
338
+ File.delete(homefile) if File.exist?(homefile) || File.symlink?(homefile)
339
+ FileUtils.mkdir_p(File.dirname(homefile))
340
+ FileUtils.ln_s(dotfile, homefile, verbose: true)
341
+ end
342
+ end
343
+
344
+ def self?
345
+ !!options.self
346
+ end
347
+
348
+ def command_compare
349
+ file_1, file_2 = files
350
+ key_1, key_2 = arguments
351
+ read_1, read_2 =
352
+ files.map.with_index do |file, index|
353
+ read = reads(File.read(file))
354
+
355
+ if arguments[index] && read.from_deep_struct.key?(arguments[index])
356
+ read[arguments[index]]
357
+ elsif arguments[index]
358
+ nil
359
+ else
360
+ read
361
+ end
362
+ end
363
+
364
+ compare(read_1, read_2, file_1:, file_2:)
365
+ end
366
+
242
367
  def command_each
243
368
  each(everything) do |input|
244
369
  each(lines(reads(input)), progress: true) { |line| evaluates(it: line) }
@@ -344,7 +469,7 @@ class Dorian
344
469
  def outputs(content, file: nil)
345
470
  if write? && file
346
471
  File.write(file, to_output(content))
347
- else
472
+ elsif !content.nil?
348
473
  puts to_output(content)
349
474
  end
350
475
  end
@@ -750,6 +875,57 @@ class Dorian
750
875
  http.request(request).body
751
876
  end
752
877
 
878
+ def compare(content_1, content_2, file_1:, file_2:, path: ".")
879
+ content_1 = content_1.from_deep_struct
880
+ content_2 = content_2.from_deep_struct
881
+
882
+ if content_1.is_a?(Hash) && content_2.is_a?(Hash)
883
+ (content_1.keys + content_2.keys).uniq.each do |key|
884
+ new_path = path == "." ? "#{path}#{key}" : "#{path}.#{key}"
885
+
886
+ if content_1[key] && !content_2[key]
887
+ warn "#{new_path} present in #{file_1} but not in #{file_2}"
888
+ next
889
+ elsif !content_1[key] && content_2[key]
890
+ warn "#{new_path} present in #{file_2} but not in #{file_1}"
891
+ next
892
+ end
893
+
894
+ compare(
895
+ content_1[key],
896
+ content_2[key],
897
+ path: new_path,
898
+ file_1:,
899
+ file_2:
900
+ )
901
+ end
902
+ elsif content_1.is_a?(Array) && content_2.is_a?(Array)
903
+ (0...([content_1.size, content_2.size].max)).each do |index|
904
+ new_path = "#{path}[#{index}]"
905
+ if content_1[index] && !content_2[index]
906
+ warn "#{new_path} present in #{file_1} but not in #{file_2}"
907
+ next
908
+ elsif !content_1[index] && content_2[index]
909
+ warn "#{new_path} present in #{file_2} but not in #{file_1}"
910
+ next
911
+ end
912
+
913
+ compare(
914
+ content_1[index],
915
+ content_2[index],
916
+ path: new_path,
917
+ file_1:,
918
+ file_2:
919
+ )
920
+ end
921
+ elsif content_1.class != content_2.class
922
+ warn(
923
+ "#{path} has #{content_1.class} for #{file_1} " \
924
+ "and #{content_2.class} for #{file_2}"
925
+ )
926
+ end
927
+ end
928
+
753
929
  def short(string)
754
930
  string[0..5000]
755
931
  end
@@ -758,6 +934,79 @@ class Dorian
758
934
  Tiktoken.encoding_for_model("gpt-4o")
759
935
  end
760
936
 
937
+ def match_filetypes?(path)
938
+ return true unless arguments.any?
939
+ return true unless arguments.intersect?(["rb", "ruby"])
940
+
941
+ ruby_extensions = %w[
942
+ .rb
943
+ .arb
944
+ .axlsx
945
+ .builder
946
+ .fcgi
947
+ .gemfile
948
+ .gemspec
949
+ .god
950
+ .jb
951
+ .jbuilder
952
+ .mspec
953
+ .opal
954
+ .pluginspec
955
+ .podspec
956
+ .rabl
957
+ .rake
958
+ .rbuild
959
+ .rbw
960
+ .rbx
961
+ .ru
962
+ .ruby
963
+ .schema
964
+ .spec
965
+ .thor
966
+ .watchr
967
+ ]
968
+
969
+ ruby_filenames = %w[
970
+ .irbrc
971
+ .pryrc
972
+ .simplecov
973
+ Appraisals
974
+ Berksfile
975
+ Brewfile
976
+ Buildfile
977
+ Capfile
978
+ Cheffile
979
+ Dangerfile
980
+ Deliverfile
981
+ Fastfile
982
+ Gemfile
983
+ Guardfile
984
+ Jarfile
985
+ Mavenfile
986
+ Podfile
987
+ Puppetfile
988
+ Rakefile
989
+ rakefile
990
+ Schemafile
991
+ Snapfile
992
+ Steepfile
993
+ Thorfile
994
+ Vagabondfile
995
+ Vagrantfile
996
+ buildfile
997
+ ]
998
+
999
+ return false if Dir.exist?(path)
1000
+ return true if ruby_filenames.include?(path)
1001
+ return true if ruby_extensions.include?(File.extname(path))
1002
+ return false unless File.exist?(path)
1003
+
1004
+ first_line =
1005
+ File.open(path, &:gets).to_s.encode("UTF-8", invalid: :replace)
1006
+
1007
+ /\A#!.*ruby\z/.match?(first_line)
1008
+ end
1009
+
761
1010
  def evaluates(
762
1011
  ruby: @ruby,
763
1012
  it: nil,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dorian
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-06 00:00:00.000000000 Z
11
+ date: 2024-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: csv
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: parallel
112
+ name: ostruct
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: yaml
126
+ name: parallel
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: ostruct
140
+ name: yaml
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="