can_cli 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6bf02108fde1cf47368121daf62f72d4ddaf6467345d4c18e61860695385f23
4
- data.tar.gz: 2a4dc6a1a67d0ea2a784cc0798a0b79625be2f5123096c8d2375e7c934a73684
3
+ metadata.gz: 30f07d677961d3cacd7883588248a12abc8cc704e43e404dca8f8e57b5732cd6
4
+ data.tar.gz: bcc9de955586c990221b7d1c1bd271740552ae28f50bf8bf0bccf0ed39194641
5
5
  SHA512:
6
- metadata.gz: a2ad87540fa21fc74daef3bd50dac07fa43c9fdb03b0388885a310ab558358e2be1ba13679c0a3dda568fa255727068bd878672bd1c13cc88e52fec983c71da3
7
- data.tar.gz: c22db9cf85967ecf266f52156c6941a3bd1de43f73d3cf403b51701bad63d34e774157e623bb2cab043436de2953e85a15f21586aa34093abd5f6898678eded6
6
+ metadata.gz: 2e43c013bef3784c96fb479fc79277edbe75626ea83f12460fbeacd87b2d1cf3437fbb840a14de3f01805a53315a69b97b84ea106a628240f1fd2b99ddb0385f
7
+ data.tar.gz: a9a59c4e8f4bd049011eee27589a573dc85ee272d15e010fbf3f17b645d22d11e68e9493dc2acfaef18dd0e8ebac572d2ca4a18830d1adb03591153239ebf0d9
data/bin/can CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'can'
4
5
 
5
- Can::can
6
+ Can.can
data/can.gemspec CHANGED
@@ -8,7 +8,22 @@ Gem::Specification.new do |s|
8
8
  s.description = 'A command-line trashcan interface implementing the FreeDesktop trash specification as a drop-in replacement for rm.'
9
9
  s.authors = ['Sawyer Shepherd']
10
10
  s.email = 'contact@sawyershepherd.org'
11
- s.files = `git ls-files -z`.split "\x0"
11
+ s.files = [
12
+ 'LICENSE',
13
+ 'README.md',
14
+ 'bin/can',
15
+ 'can.gemspec',
16
+ 'lib/can/argparse.rb',
17
+ 'lib/can/version.rb',
18
+ 'lib/can.rb',
19
+ 'lib/empty.rb',
20
+ 'lib/error.rb',
21
+ 'lib/info.rb',
22
+ 'lib/list.rb',
23
+ 'lib/trash.rb',
24
+ 'lib/trashinfo.rb',
25
+ 'lib/untrash.rb'
26
+ ]
12
27
  s.homepage = 'https://github.com/sawshep/can'
13
28
  s.license = 'GPL-3.0'
14
29
  s.add_runtime_dependency 'highline', '~> 2.0'
data/lib/can/argparse.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
  require 'set'
3
5
  require 'can/version'
@@ -14,29 +16,29 @@ module Can
14
16
  USAGE = 'Usage: can [OPTION] [FILE]...'
15
17
 
16
18
  MODES = {
17
- :list => ['-l', '--list',
18
- 'list files in the trash'],
19
- :info => ['-n', '--info',
20
- 'see information about a trashed file'],
21
- :untrash => ['-u', '--untrash',
22
- 'restore a trashed file'],
23
- :empty => ['-e', '--empty',
24
- 'permanently remove a file from the trash;
19
+ list: ['-l', '--list',
20
+ 'list files in the trash'],
21
+ info: ['-n', '--info',
22
+ 'see information about a trashed file'],
23
+ untrash: ['-u', '--untrash',
24
+ 'restore a trashed file'],
25
+ empty: ['-e', '--empty',
26
+ 'permanently remove a file from the trash;
25
27
  use with no arguments to empty entire
26
- trashcan'],
27
- }
28
+ trashcan']
29
+ }.freeze
28
30
 
29
31
  OPTIONS = {
30
- :force => ['-f', '--force',
31
- 'ignore nonexistent files and arguments,
32
+ force: ['-f', '--force',
33
+ 'ignore nonexistent files and arguments,
32
34
  never prompt'],
33
- :prompt => ['-i', nil, 'prompt before every trashing'],
34
- :recursive => ['-r', '--recursive',
35
- 'trash directories and their contents
35
+ prompt: ['-i', nil, 'prompt before every trashing'],
36
+ recursive: ['-r', '--recursive',
37
+ 'trash directories and their contents
36
38
  recursively']
37
- }
39
+ }.freeze
38
40
 
39
- ALL_FLAGS = MODES.merge(OPTIONS)
41
+ ALL_FLAGS = MODES.merge(OPTIONS).freeze
40
42
 
41
43
  module ArgParse
42
44
  Version = VERSION
@@ -44,16 +46,14 @@ module Can
44
46
  OptionParser.new do |opts|
45
47
  opts.banner = USAGE
46
48
 
47
- ALL_FLAGS.each do |mode,v|
48
- opts.on(short_opt(mode), long_opt(mode), help_string(mode)) do |opt|
49
+ ALL_FLAGS.each do |mode, _v|
50
+ opts.on(short_opt(mode), long_opt(mode), help_string(mode)) do |_opt|
49
51
  $options << mode
50
52
  end
51
53
  end
52
54
  end.parse!
53
55
 
54
- if ArgParse.incompatible_opts?
55
- Error.fatal "Too many mode arguments"
56
- end
56
+ Error.fatal 'Too many mode arguments' if ArgParse.incompatible_opts?
57
57
  end
58
58
 
59
59
  # Sees if $options has incompatible items
@@ -62,31 +62,29 @@ module Can
62
62
  ($options & modes).length > 1
63
63
  end
64
64
 
65
- def self.get_mode
65
+ def self.mode
66
66
  ($options & MODES.keys).first || :trash
67
67
  end
68
68
 
69
- def self.short_opt (mode)
69
+ def self.short_opt(mode)
70
70
  ALL_FLAGS[mode][0]
71
71
  end
72
72
 
73
- def self.long_opt (mode)
73
+ def self.long_opt(mode)
74
74
  ALL_FLAGS[mode][1]
75
75
  end
76
76
 
77
77
  # Returns a mode's help string
78
- def self.help_string (mode)
78
+ def self.help_string(mode)
79
79
  ALL_FLAGS[mode][2]
80
80
  end
81
81
 
82
82
  # Returns an options's corresponding mode, if it is valid
83
- def self.valid_opt? (opt)
84
- result = MODES.find { |k,v|
83
+ def self.valid_opt?(opt)
84
+ result = MODES.find do |_k, v|
85
85
  v[0..2].include? opt
86
- }
87
- if result
88
- result.first
89
86
  end
87
+ result&.first
90
88
  end
91
89
  end
92
90
  end
data/lib/can/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Can
2
- VERSION = '0.1.2'
4
+ VERSION = '0.1.3'
3
5
  end
data/lib/can.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
 
3
5
  require 'can/argparse'
@@ -18,7 +20,7 @@ module Can
18
20
  HOME_TRASH_INFO_DIRECTORY = File.join(HOME_TRASH_DIRECTORY, 'info')
19
21
  HOME_TRASH_FILES_DIRECTORY = File.join(HOME_TRASH_DIRECTORY, 'files')
20
22
 
21
- def self.init_dirs()
23
+ def self.init_dirs
22
24
  FileUtils.mkpath HOME_TRASH_FILES_DIRECTORY
23
25
  FileUtils.mkpath HOME_TRASH_INFO_DIRECTORY
24
26
  end
@@ -26,14 +28,12 @@ module Can
26
28
  def self.can
27
29
  ArgParse.init_args
28
30
 
29
- mode = ArgParse.get_mode
31
+ mode = ArgParse.mode
30
32
 
31
- self.init_dirs
33
+ init_dirs
32
34
 
33
- self.send mode
35
+ send mode
34
36
 
35
- if $options.include? :force
36
- $exit = EXIT_SUCCESS
37
- end
37
+ $exit = EXIT_SUCCESS if $options.include? :force
38
38
  end
39
39
  end
data/lib/empty.rb CHANGED
@@ -1,19 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Can
2
4
  def self.empty
3
5
  # Remove everything in the files and info directory
4
- if ARGV.length == 0
6
+ if ARGV.empty?
5
7
  FileUtils.rm_r Dir.glob("#{HOME_TRASH_INFO_DIRECTORY}/*"), secure: true
6
8
  FileUtils.rm_r Dir.glob("#{HOME_TRASH_FILES_DIRECTORY}/*"), secure: true
7
9
  else
8
- ARGV.map { |filename|
9
- trashinfo_filename = filename + '.trashinfo'
10
+ ARGV.each do |filename|
11
+ trashinfo_filename = "#{filename}.trashinfo"
10
12
 
11
13
  file_path = File.join(HOME_TRASH_FILES_DIRECTORY, filename)
12
14
  trashinfo_file_path = File.join(HOME_TRASH_INFO_DIRECTORY, trashinfo_filename)
13
15
 
14
16
  FileUtils.remove_entry_secure file_path
15
17
  FileUtils.remove_entry_secure trashinfo_file_path
16
- }
18
+ end
17
19
  end
18
20
  end
19
21
  end
data/lib/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  EXIT_SUCCESS = 0
2
4
  EXIT_FAILURE = 1
3
5
 
@@ -8,14 +10,14 @@ at_exit do
8
10
  end
9
11
 
10
12
  module Error
11
- def self.nonfatal (message)
12
- STDERR.puts('can: ' + message)
13
+ def self.nonfatal(message)
14
+ warn "can: #{message}"
13
15
  $exit = EXIT_FAILURE
14
16
  end
15
17
 
16
18
  # Exits without callbacks to at_exit
17
- def self.fatal (message)
18
- STDERR.puts('can: ' + message)
19
+ def self.fatal(message)
20
+ warn "can: #{message}"
19
21
  exit!(EXIT_FAILURE)
20
22
  end
21
23
  end
data/lib/info.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Can
2
4
  # TODO: Parse the .trashinfo files to make them more human
3
5
  # readable. Also, display the filename above the information
@@ -5,19 +7,19 @@ module Can
5
7
  def self.info
6
8
  # Fails with a fatal error even with --force, intended
7
9
  # behavior.
8
- if ARGV.length == 0
10
+ if ARGV.empty?
9
11
  Error.fatal 'missing operand'
10
12
  else
11
- ARGV.each_with_index { |file, i|
12
- trashinfo_filename = file + '.trashinfo'
13
+ ARGV.each_with_index do |file, i|
14
+ trashinfo_filename = "#{file}.trashinfo"
13
15
  trashinfo_path = File.join(HOME_TRASH_INFO_DIRECTORY, trashinfo_filename)
14
16
 
15
- if not File.exist? trashinfo_path
17
+ unless File.exist? trashinfo_path
16
18
  Error.nonfatal "no such file in trashcan: '#{file}'"
17
19
  next
18
20
  end
19
21
 
20
- trashinfo = Trashinfo.parse(File.read trashinfo_path)
22
+ trashinfo = Trashinfo.parse(File.read(trashinfo_path))
21
23
 
22
24
  # TODO: Checking if i is not zero every single
23
25
  # iteration is a little inefficient. Maybe there is a
@@ -28,7 +30,7 @@ module Can
28
30
  Path: #{trashinfo[:path]}
29
31
  Deletion Date: #{trashinfo[:deletion_date]}
30
32
  INFO
31
- }
33
+ end
32
34
  end
33
35
  end
34
36
  end
data/lib/list.rb CHANGED
@@ -1,21 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Can
2
4
  def self.list
3
5
  # Given no args, show every trashed file
4
- if ARGV.length == 0
6
+ if ARGV.empty?
5
7
  puts Dir.children(HOME_TRASH_FILES_DIRECTORY)
6
8
 
7
9
  # Given a regex pattern as an arg, print trashed files
8
10
  # that fit
9
11
  elsif ARGV.length == 1
10
12
  regex = Regexp.new(ARGV[0])
11
- puts Dir.children(HOME_TRASH_FILES_DIRECTORY).select { |file|
12
- regex =~ file
13
- }
13
+ puts(
14
+ Dir.children(HOME_TRASH_FILES_DIRECTORY).select do |file|
15
+ regex =~ file
16
+ end
17
+ )
14
18
 
15
19
  else
16
- raise StandardError.new(
17
- "can: mode --list expects 0 to 1 arguments, given #{ARGV.length}"
18
- )
20
+ raise StandardError, "can: mode --list expects 0 to 1 arguments, given #{ARGV.length}"
19
21
  end
20
22
  end
21
23
  end
data/lib/trash.rb CHANGED
@@ -1,18 +1,19 @@
1
+ # frozen_string_literaL: true
2
+
1
3
  require 'highline'
2
4
 
3
5
  # Returns filename with all trailing extensions removed
4
6
  def strip_extensions(filename)
5
7
  ext = File.extname filename
6
- if ext.empty?
7
- return filename
8
- end
8
+ return filename if ext.empty?
9
+
9
10
  strip_extensions(File.basename(filename, ext))
10
11
  end
11
12
 
12
13
  # Returns all extensions of a filename
13
14
  def gather_extensions(filename)
14
15
  exts = ''
15
- while not File.extname(filename).empty?
16
+ until File.extname(filename).empty?
16
17
  ext = File.extname(filename)
17
18
  exts = ext + exts
18
19
  filename = File.basename(filename, ext)
@@ -22,41 +23,30 @@ end
22
23
 
23
24
  module Can
24
25
  def self.trash
25
- if ARGV.length == 0 and not $options.include? :force
26
- Error.fatal 'missing operand'
27
- end
26
+ Error.fatal 'missing operand' if ARGV.empty? && !$options.include?(:force)
28
27
 
29
28
  ARGV.each do |path|
30
-
31
29
  # TODO: If both `-f` and `-i` are used, can should
32
30
  # prompt if `-i` is used last. If `-f` is used last,
33
31
  # can should not prompt trashings. This follows the
34
32
  # behavior of rm.
35
- if not File.exist?(path)
36
- if not $options.include? :force
37
- Error.nonfatal "cannot trash '#{path}': No such file or directory"
38
- end
33
+ unless File.exist?(path)
34
+ Error.nonfatal "cannot trash '#{path}': No such file or directory" unless $options.include? :force
39
35
  next
40
36
  end
41
37
 
42
38
  # If --recursive is not used and a directory is given as an
43
39
  # argument, a non-zero error code should be returned
44
40
  # regardless if --force is used.
45
- if File.directory? path and not File.symlink? path
46
- if not $options.include? :recursive
47
- Error.nonfatal "cannot remove '#{path}': Is a directory"
48
- end
41
+ if File.directory?(path) && !File.symlink?(path)
42
+ Error.nonfatal "cannot remove '#{path}': Is a directory" unless $options.include? :recursive
49
43
  next
50
44
  end
51
45
 
52
46
  # TODO: Highline.agree prints to stdout, when it should
53
47
  # print to stderr. It also uses `puts`, while this use
54
48
  # case should use `print`.
55
- if $options.include? :prompt
56
- unless HighLine.agree "can: remove file '#{path}'?"
57
- next
58
- end
59
- end
49
+ next if $options.include?(:prompt) && !(HighLine.agree "can: remove file '#{path}'?")
60
50
 
61
51
  filename = File.basename path
62
52
 
@@ -75,12 +65,12 @@ module Can
75
65
  i = 0
76
66
  while existing_trash_files.include?(filename)
77
67
  i += 1
78
- filename = basename + ".#{i}" + exts
68
+ filename = "#{basename}.#{i}#{exts}"
79
69
  end
80
70
 
81
71
  FileUtils.mv(path, File.join(HOME_TRASH_FILES_DIRECTORY, filename))
82
72
 
83
- trashinfo_filename = filename + '.trashinfo'
73
+ trashinfo_filename = "#{filename}.trashinfo"
84
74
  trashinfo_out_path = File.join(HOME_TRASH_INFO_DIRECTORY, trashinfo_filename)
85
75
  File.new(trashinfo_out_path, 'w').syswrite(trashinfo_string)
86
76
  end
data/lib/trashinfo.rb CHANGED
@@ -1,22 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cgi'
2
4
 
3
5
  module Trashinfo
4
- def self.new (path)
5
- trashinfo_string = <<~DESKTOP
6
+ def self.new(path)
7
+ <<~DESKTOP
6
8
  [Trash Info]
7
- Path=#{CGI.escape(File.expand_path path)}
9
+ Path=#{CGI.escape(File.expand_path(path))}
8
10
  DeletionDate=#{Time.now.strftime('%Y-%m-%dT%H:%M:%S')}
9
11
  DESKTOP
10
12
  end
11
13
 
12
- def self.parse (trashinfo)
14
+ def self.parse(trashinfo)
13
15
  regex = /\A\[Trash Info\]\nPath=(?<path>\S+)\nDeletionDate=(?<deletion_date>\S+)/m
14
16
 
15
17
  matches = regex.match trashinfo
16
18
 
17
- parts = {
18
- :path => CGI.unescape(matches[:path]),
19
- :deletion_date => matches[:deletion_date]
19
+ {
20
+ path: CGI.unescape(matches[:path]),
21
+ deletion_date: matches[:deletion_date]
20
22
  }
21
23
  end
22
24
  end
data/lib/untrash.rb CHANGED
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Can
2
4
  def self.untrash
3
5
  ARGV.each do |filename|
4
6
  file_path = File.join(HOME_TRASH_FILES_DIRECTORY, filename)
5
7
 
6
- if not File.exist? file_path
7
- if not $options.include? :force
8
- Error.nonfatal "cannot untrash '#{filename}': No such file or directory in trash"
9
- end
8
+ unless File.exist? file_path
9
+ unless $options.include? :force
10
+ Error.nonfatal "cannot untrash '#{filename}': No such file or directory in trash"
11
+ end
10
12
  next
11
13
  end
12
14
 
13
- trashinfo_filename = filename + '.trashinfo'
15
+ trashinfo_filename = "#{filename}.trashinfo"
14
16
  trashinfo_path = File.join(HOME_TRASH_INFO_DIRECTORY, trashinfo_filename)
15
- trashinfo = Trashinfo.parse(File.read trashinfo_path)
17
+ trashinfo = Trashinfo.parse(File.read(trashinfo_path))
16
18
 
17
19
  original_path = trashinfo[:path]
18
20
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: can_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sawyer Shepherd
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-11 00:00:00.000000000 Z
11
+ date: 2022-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -32,7 +32,6 @@ executables:
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - ".gitignore"
36
35
  - LICENSE
37
36
  - README.md
38
37
  - bin/can
@@ -51,7 +50,7 @@ homepage: https://github.com/sawshep/can
51
50
  licenses:
52
51
  - GPL-3.0
53
52
  metadata: {}
54
- post_install_message:
53
+ post_install_message:
55
54
  rdoc_options: []
56
55
  require_paths:
57
56
  - lib
@@ -66,8 +65,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
65
  - !ruby/object:Gem::Version
67
66
  version: '0'
68
67
  requirements: []
69
- rubygems_version: 3.3.8
70
- signing_key:
68
+ rubygems_version: 3.3.7
69
+ signing_key:
71
70
  specification_version: 4
72
71
  summary: Command-line trash manager
73
72
  test_files: []
data/.gitignore DELETED
@@ -1,56 +0,0 @@
1
- *.gem
2
- *.rbc
3
- /.config
4
- /coverage/
5
- /InstalledFiles
6
- /pkg/
7
- /spec/reports/
8
- /spec/examples.txt
9
- /test/tmp/
10
- /test/version_tmp/
11
- /tmp/
12
-
13
- # Used by dotenv library to load environment variables.
14
- # .env
15
-
16
- # Ignore Byebug command history file.
17
- .byebug_history
18
-
19
- ## Specific to RubyMotion:
20
- .dat*
21
- .repl_history
22
- build/
23
- *.bridgesupport
24
- build-iPhoneOS/
25
- build-iPhoneSimulator/
26
-
27
- ## Specific to RubyMotion (use of CocoaPods):
28
- #
29
- # We recommend against adding the Pods directory to your .gitignore. However
30
- # you should judge for yourself, the pros and cons are mentioned at:
31
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
- #
33
- # vendor/Pods/
34
-
35
- ## Documentation cache and generated files:
36
- /.yardoc/
37
- /_yardoc/
38
- /doc/
39
- /rdoc/
40
-
41
- ## Environment normalization:
42
- /.bundle/
43
- /vendor/bundle
44
- /lib/bundler/man/
45
-
46
- # for a library or gem, you might want to ignore these files since the code is
47
- # intended to run in multiple environments; otherwise, check them in:
48
- Gemfile.lock
49
- # .ruby-version
50
- # .ruby-gemset
51
-
52
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
- .rvmrc
54
-
55
- # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
- # .rubocop-https?--*