dorian 2.3.0 → 2.4.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.
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
  - - ">="