reenrb 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5350da1a685dccdcd5298a94beed380476f381a8e75ebb8a02b655bca0185bd7
4
+ data.tar.gz: d9fac2a8bbce0dc7ff8c6d71a1e100ac2decdee5bc0036878ff74056653af7a3
5
+ SHA512:
6
+ metadata.gz: 5f5b124d9f7552d06380ed3f1c8eea08e1c707a9f8d5ef1feb80373ce5c24ec71ee2b2b4f661a7f4a2cb22fc780270a2163e9fb523b334b1bab30dfa518fc4c6
7
+ data.tar.gz: e3508d642009b303cd23692403d41ab8de61f0e8a805aeeade650dcb3954cdbd851c74a41b0c008dca3a40e3b31419308cda371e99f9d3fc433650813292a0a0
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+ NewCops: enable
4
+
5
+ Style/StringLiterals:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Style/StringLiteralsInInterpolation:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Layout/LineLength:
14
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-11-05
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in reenrb.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ reenrb (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ ffi (1.15.5)
11
+ json (2.6.2)
12
+ listen (3.7.1)
13
+ rb-fsevent (~> 0.10, >= 0.10.3)
14
+ rb-inotify (~> 0.9, >= 0.9.10)
15
+ minitest (5.16.3)
16
+ minitest-rg (5.2.0)
17
+ minitest (~> 5.0)
18
+ parallel (1.22.1)
19
+ parser (3.1.2.1)
20
+ ast (~> 2.4.1)
21
+ rainbow (3.1.1)
22
+ rake (13.0.6)
23
+ rb-fsevent (0.11.2)
24
+ rb-inotify (0.10.1)
25
+ ffi (~> 1.0)
26
+ regexp_parser (2.6.0)
27
+ rerun (0.13.1)
28
+ listen (~> 3.0)
29
+ rexml (3.2.5)
30
+ rubocop (1.38.0)
31
+ json (~> 2.3)
32
+ parallel (~> 1.10)
33
+ parser (>= 3.1.2.1)
34
+ rainbow (>= 2.2.2, < 4.0)
35
+ regexp_parser (>= 1.8, < 3.0)
36
+ rexml (>= 3.2.5, < 4.0)
37
+ rubocop-ast (>= 1.23.0, < 2.0)
38
+ ruby-progressbar (~> 1.7)
39
+ unicode-display_width (>= 1.4.0, < 3.0)
40
+ rubocop-ast (1.23.0)
41
+ parser (>= 3.1.1.0)
42
+ ruby-progressbar (1.11.0)
43
+ rubyzip (2.3.2)
44
+ unicode-display_width (2.3.0)
45
+
46
+ PLATFORMS
47
+ arm64-darwin-21
48
+
49
+ DEPENDENCIES
50
+ minitest (~> 5.0)
51
+ minitest-rg (~> 5.0)
52
+ rake (~> 13.0)
53
+ reenrb!
54
+ rerun (~> 0.13)
55
+ rubocop (~> 1.21)
56
+ rubyzip (~> 2.3)
57
+
58
+ BUNDLED WITH
59
+ 2.3.8
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Soumya Ray
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Reenrb
2
+
3
+ Reen-rb is a utility written in Ruby (requires Ruby installed on your machine) that mass renames/deletes files by allowing the user to modify a list. It includes a command line executable called `reen` that opens the user's default editor to permit interactive changes, or can be used programatically by modifying the list of file names using a code block.
4
+
5
+ ## Installation
6
+
7
+ To install the command line utility, use:
8
+
9
+ $ gem install reenrb
10
+
11
+ Or add this line to your Ruby application's Gemfile for programmatic use:
12
+
13
+ ```ruby
14
+ gem 'reenrb'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle install
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install reenrb
24
+
25
+ ## Usage
26
+
27
+ ### Command line
28
+
29
+ From command line, run `reen` with file list:
30
+
31
+ reen [file ...]
32
+
33
+ Examples:
34
+
35
+ reen *
36
+ reen myfolder/**/*.mov
37
+
38
+ ### Ruby application
39
+
40
+ Use programmatically using the `reenrb` gem. In the example below, we specify that we do not want to use an actual editor to modify the list, but rather alter the list file using a block.
41
+
42
+ ```ruby
43
+ require 'reenrb'
44
+
45
+ glob = Dir.glob("*")
46
+ reen = Reenrb::Reen.new(options: { mock_editor: true })
47
+
48
+ reen.execute(glob) do |tmpfile_path|
49
+ lines = File.read(tmpfile_path).split("\n")
50
+
51
+ # Rename LICENSE.txt -> LICENSE.md
52
+ index = lines.index { |l| l.include? "LICENSE.txt" }
53
+ lines[index] = lines[index].gsub("txt", "md")
54
+ File.write(tmpfile_path, lines.join("\n"))
55
+ end
56
+ ```
57
+
58
+ ## Development
59
+
60
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
61
+
62
+ ## Contributing
63
+
64
+ Bug reports and pull requests are welcome on GitHub at https://github.com/soumyaray/reenrb.
65
+
66
+ ## License
67
+
68
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:spec) do |t|
7
+ t.libs << "tspecest"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["spec/**/spec_*.rb"]
10
+ end
11
+
12
+ task :respec do
13
+ sh "rerun -c --ignore 'spec/fixtures/*' rake spec"
14
+ end
15
+
16
+ namespace :example do
17
+ task :config do
18
+ require_relative "spec/fixture_helper"
19
+ end
20
+
21
+ desc "Recreates the example fixture folder"
22
+ task :recreate => :config do
23
+ FixtureHelper.recreate_example_dir
24
+ puts "Example fixture recreated"
25
+ end
26
+
27
+ desc "Deletes the example fixture folder"
28
+ task :remove => :config do
29
+ FixtureHelper.remove_example_dirs
30
+ puts "Example fixture removed"
31
+ end
32
+ end
33
+
34
+ require "rubocop/rake_task"
35
+
36
+ RuboCop::RakeTask.new
37
+
38
+ task default: %i[spec rubocop]
data/bin/reen ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ EDITOR_MSG = "Editor not set in $EDITOR or $VISUAL -- please set one of those environment variables"
5
+
6
+ def exit_with_error(err)
7
+ puts err
8
+ exit(false)
9
+ end
10
+
11
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
12
+ require "reenrb"
13
+
14
+ file_list = ARGV || Dir.glob("*")
15
+ editor = ENV["VISUAL"] || ENV["EDITOR"]
16
+ exit_with_error(EDITOR_MSG) if editor.empty?
17
+
18
+ results = Reenrb::Reen.new(editor: editor).execute(file_list)
19
+
20
+ changes = Reenrb::Changes.new(results).change_requested
21
+
22
+ puts changes.summarize
data/lib/change.rb ADDED
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reenrb
4
+ # Change to an orignal file
5
+ class Change
6
+ attr_reader :original, :requested, :change, :status
7
+
8
+ module STATUS
9
+ ACCEPTED = :accepted
10
+ REJECTED = :rejected
11
+ EXECUTED = :executed
12
+ end
13
+
14
+ module CHANGE
15
+ NONE = :none
16
+ DELETE = :delete
17
+ RENAME = :rename
18
+ end
19
+
20
+ CHANGES_DESC = {
21
+ none: "Nothing",
22
+ delete: "Deleting",
23
+ rename: "Renaming"
24
+ }.freeze
25
+
26
+ def initialize(original, requested)
27
+ @original = original
28
+ @requested = requested
29
+ @change = compare
30
+ consider
31
+ end
32
+
33
+ def compare
34
+ if original == requested
35
+ :none
36
+ elsif requested.start_with? "-"
37
+ :delete
38
+ else
39
+ :rename
40
+ end
41
+ end
42
+
43
+ def request_directory?
44
+ Dir.exist? @original
45
+ end
46
+
47
+ def request_delete?
48
+ @change == CHANGE::DELETE
49
+ end
50
+
51
+ def request_empty_directory?
52
+ Dir.empty? @original
53
+ end
54
+
55
+ def request_full_directory?
56
+ request_directory? && !request_empty_directory?
57
+ end
58
+
59
+ def consider
60
+ if request_full_directory? && request_delete?
61
+ @status = STATUS::REJECTED
62
+ @reason = "Directories with files cannot be changed"
63
+ else
64
+ @status = STATUS::ACCEPTED
65
+ end
66
+ end
67
+
68
+ def executed_or_rejected
69
+ %i[executed rejected].include? @status
70
+ end
71
+
72
+ def execute
73
+ return(self) if executed_or_rejected
74
+
75
+ case @change
76
+ when :rename
77
+ File.rename(@original, @requested)
78
+ when :delete
79
+ File.delete(@original)
80
+ end
81
+
82
+ @status = STATUS::EXECUTED
83
+ self
84
+ end
85
+
86
+ def to_s
87
+ file_desc =
88
+ case @change
89
+ when :rename
90
+ "#{@original} -> #{@requested}"
91
+ else
92
+ @original
93
+ end
94
+
95
+ reason_desc = @status == STATUS::REJECTED ? " (failed: #{@reason})" : ""
96
+
97
+ "#{CHANGES_DESC[@change]}: #{file_desc}#{reason_desc}"
98
+ end
99
+ end
100
+ end
data/lib/changes.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reenrb
4
+ # Change to an orignal file
5
+ class Changes
6
+ attr_reader :list
7
+
8
+ def initialize(changes_list)
9
+ @list = changes_list
10
+ end
11
+
12
+ def none
13
+ Changes.new(@list.select { |c| c.change == :none })
14
+ end
15
+
16
+ def rename_requested
17
+ Changes.new(@list.select { |c| c.change == :rename })
18
+ end
19
+
20
+ def delete_requested
21
+ Changes.new(@list.select { |c| c.change == :delete })
22
+ end
23
+
24
+ def change_requested
25
+ Changes.new(@list.reject { |c| c.change == :none })
26
+ end
27
+
28
+ def rejected
29
+ Changes.new(@list.select { |c| c.status == :rejected })
30
+ end
31
+
32
+ def accepted
33
+ Changes.new(@list.select { |c| c.status == :accepted })
34
+ end
35
+
36
+ def executed
37
+ Changes.new(@list.select { |c| c.status == :executed })
38
+ end
39
+
40
+ def summarize
41
+ return "Nothing changed" if @list.empty?
42
+
43
+ @list.map(&:to_s).join("\n")
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module Reenrb
6
+ # Manages a temporary file with requested changes
7
+ class ChangesFile
8
+ def initialize(requested_list)
9
+ @list_file = Tempfile.new("reenrb-")
10
+ @list_file.write(requested_list.join("\n"))
11
+ @list_file.close
12
+ end
13
+
14
+ def path
15
+ @list_file.path
16
+ end
17
+
18
+ def allow_changes(&block)
19
+ block.call(self)
20
+ File.read(path).split("\n")
21
+ end
22
+
23
+ def blocking_edit(editor)
24
+ `#{editor} #{@list_file.path}`
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reenrb
4
+ VERSION = "0.1.0"
5
+ end
data/lib/reenrb.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "reenrb/version"
4
+ require_relative "changes_file"
5
+ require_relative "change"
6
+ require_relative "changes"
7
+
8
+ module Reenrb
9
+ class Error < StandardError; end
10
+
11
+ # Renames pattern of files with given editor
12
+ # Example:
13
+ # Reenrb::Reen.new(editor: "code -w").call("spec/fixtures/example/*")
14
+ class Reen
15
+ DEL_ERROR = "Do not delete any file/folder names"
16
+
17
+ attr_reader :changes
18
+
19
+ def initialize(editor: "emacs", options: {})
20
+ @editor = editor
21
+ @options = options
22
+ end
23
+
24
+ def request(original_list, &block)
25
+ # original_list = Dir.glob(pattern)
26
+ changed_list = ChangesFile.new(original_list).allow_changes do |file|
27
+ @options[:mock_editor] ? yield(file.path) : file.blocking_edit(@editor)
28
+ end
29
+
30
+ raise(Error, DEL_ERROR) if changed_list.size != original_list.size
31
+
32
+ @changes = compare_lists(original_list, changed_list)
33
+ end
34
+
35
+ def execute(original_list, &block)
36
+ @changes ||= request(original_list, &block)
37
+ @changes = @changes.map(&:execute)
38
+ end
39
+
40
+ private
41
+
42
+ def compare_lists(original_list, changed_list)
43
+ original_list.zip(changed_list).map do |original, revised|
44
+ Change.new(original, revised)
45
+ end
46
+ end
47
+ end
48
+ end
data/reenrb.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/reenrb/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "reenrb"
7
+ spec.version = Reenrb::VERSION
8
+ spec.authors = ["Soumya Ray"]
9
+ spec.email = ["soumya.ray@gmail.com"]
10
+
11
+ spec.summary = "Renames or deletes a pattern of files using your favorite editor"
12
+ spec.description = "Renames or deletes a pattern of files using your favorite editor"
13
+ spec.homepage = "https://github.com/soumyaray/reenrb"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.7"
16
+
17
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = spec.homepage
21
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
28
+ end
29
+ end
30
+ spec.bindir = "bin"
31
+ spec.executables << "reen"
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_development_dependency "rake", "~> 13.0"
35
+ spec.add_development_dependency "rubyzip", "~> 2.3"
36
+ spec.add_development_dependency "minitest", "~> 5.0"
37
+ spec.add_development_dependency "minitest-rg", "~> 5.0"
38
+ spec.add_development_dependency "rerun", "~> 0.13"
39
+ spec.add_development_dependency "rubocop", "~> 1.21"
40
+
41
+ # For more information and examples about making a new gem, check out our
42
+ # guide at: https://bundler.io/guides/creating_gem.html
43
+ end
data/sig/reenrb.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Reenrb
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reenrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Soumya Ray
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-11-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-rg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rerun
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.13'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.21'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.21'
97
+ description: Renames or deletes a pattern of files using your favorite editor
98
+ email:
99
+ - soumya.ray@gmail.com
100
+ executables:
101
+ - reen
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".rubocop.yml"
106
+ - CHANGELOG.md
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - bin/reen
113
+ - lib/change.rb
114
+ - lib/changes.rb
115
+ - lib/changes_file.rb
116
+ - lib/reenrb.rb
117
+ - lib/reenrb/version.rb
118
+ - reenrb.gemspec
119
+ - sig/reenrb.rbs
120
+ homepage: https://github.com/soumyaray/reenrb
121
+ licenses:
122
+ - MIT
123
+ metadata:
124
+ homepage_uri: https://github.com/soumyaray/reenrb
125
+ source_code_uri: https://github.com/soumyaray/reenrb
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '2.7'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubygems_version: 3.3.7
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Renames or deletes a pattern of files using your favorite editor
145
+ test_files: []