dle 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
+ SHA1:
3
+ metadata.gz: 954b6dbb956a5a13cab35c61df14f1d614f246d2
4
+ data.tar.gz: 5e80a17b73437a40587f6be58b1d0f48d87d33bf
5
+ SHA512:
6
+ metadata.gz: 1a75351e1d3d18792ed530564364a773a8d5e7e83fe65cea779c232c6f35ad448184c93ef33f82085482bba4616962aea4283cb5d9390ca781b47d25eacbcafe
7
+ data.tar.gz: 2e13b0f57002f7e517cbbbc166cd1aec9bd41d42a7cd6960711f19a18306d495f769e1cd36f98a5a818c18fcd58659e91fe151ae8a454517fd55501c1004e041
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dle.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Sven Pachnit
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # DLE
2
+
3
+ **Directory List Edit – Edit file structures in your favorite editor!**
4
+ You can copy, move, rename, chmod, chown or remove individual files or directories with your favorite text editor.
5
+
6
+ **BETA product, use at your own risk, use `--simulate` to be sure, always have a backup!**
7
+
8
+ ## Requirements
9
+
10
+ You will need a UNIX system with a working Ruby installation, sorry Windozer!
11
+
12
+ ## Installation
13
+
14
+ Simple as:
15
+
16
+ $ gem install dle
17
+
18
+ You may also want to define your favorite editor by setting this enviromental variable (in your profile or bashrc):
19
+
20
+ export DLE_EDITOR="subl -w"
21
+
22
+ Note that you need a blocking call to the editor (for GUI editors). Sublime and Textmate both accept `-w` or `--wait`.
23
+
24
+ ## Usage
25
+
26
+ To get a list of available options invoke DLE with the `--help` or `-h` option:
27
+
28
+ Usage: dle [options] base_directory
29
+ -d, --dotfiles Include dotfiles (unix invisible)
30
+ -r, --skip-review Skip review changes before applying
31
+ -s, --simulate Don't apply changes, show commands instead
32
+ -f, --file DLFILE Use input file (be careful)
33
+ -m, --monochrome Don't colorize output
34
+ -h, --help Shows this help
35
+ -v, --version Shows version and other info
36
+ -z Do not check for updates on GitHub (with -v/--version)
37
+
38
+ Change into a directory you want to work with and invoke DLE:
39
+
40
+ dle .
41
+ dle ~/some_path
42
+
43
+ Your editor will open with a list of your directory structure which you can edit accordingly to these rules:
44
+
45
+ * If you remove a line we just don't care!
46
+ * If you add a line we just don't care!
47
+ * If you change a path we will "mkdir -p" the destination and move the file/dir
48
+ * If you change the owner we will "chown" the file/dir
49
+ * If you change the mode we will "chmod" the file/dir
50
+ * If you change the mode to "cp" and modify the path we will copy instead of moving/renaming
51
+ * If you change the mode to "del" we will "rm" the file
52
+ * If you change the mode to "delr" we will "rm" the file or directory
53
+ * If you change the mode to "delf" or "delrf" we will "rm -f" the file or directory
54
+ * We will apply changes in this order (inside-out):
55
+ * Ownership
56
+ * Permissions
57
+ * Rename/Move
58
+ * Copy
59
+ * Delete
60
+
61
+ ## Caveats
62
+
63
+ DLE relies on inode values, do not use with hardlinks! This may lead to unexpected file operations or data loss!
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it ( http://github.com/2called-chaos/dle/fork )
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/dle ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require "dle"
3
+ Dle::Application.dispatch(ENV, ARGV)
data/bin/dle.sh ADDED
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ # That's __FILE__ in BASH :)
4
+ # From: http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
5
+ SOURCE="${BASH_SOURCE[0]}"
6
+ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
7
+ MCLDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
8
+ SOURCE="$(readlink "$SOURCE")"
9
+ [[ $SOURCE != /* ]] && SOURCE="$MCLDIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
10
+ done
11
+ PROJECT_ROOT="$( cd -P "$( dirname "$SOURCE" )"/.. && pwd )"
12
+
13
+ # Actually run script
14
+ cd $PROJECT_ROOT && bundle exec ruby bin/dle "$@"
data/dle.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dle/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dle"
8
+ spec.version = Dle::VERSION
9
+ spec.authors = ["Sven Pachnit"]
10
+ spec.email = ["sven@bmonkeys.net"]
11
+ spec.summary = %q{Directory List Edit – Edit file structures in your favorite editor!}
12
+ spec.description = %q{You can move, rename, chmod, chown or remove individual files or directories with your favorite text editor.}
13
+ spec.homepage = "https://github.com/2called-chaos/dle"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "pry"
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake"
24
+ end
@@ -0,0 +1,112 @@
1
+ # encoding: utf-8
2
+
3
+ class Object
4
+ # An object is blank if it's false, empty, or a whitespace string.
5
+ # For example, '', ' ', +nil+, [], and {} are all blank.
6
+ #
7
+ # This simplifies:
8
+ #
9
+ # if address.nil? || address.empty?
10
+ #
11
+ # ...to:
12
+ #
13
+ # if address.blank?
14
+ def blank?
15
+ respond_to?(:empty?) ? empty? : !self
16
+ end
17
+
18
+ # An object is present if it's not <tt>blank?</tt>.
19
+ def present?
20
+ !blank?
21
+ end
22
+
23
+ # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
24
+ # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
25
+ #
26
+ # This is handy for any representation of objects where blank is the same
27
+ # as not present at all. For example, this simplifies a common check for
28
+ # HTTP POST/query parameters:
29
+ #
30
+ # state = params[:state] if params[:state].present?
31
+ # country = params[:country] if params[:country].present?
32
+ # region = state || country || 'US'
33
+ #
34
+ # ...becomes:
35
+ #
36
+ # region = params[:state].presence || params[:country].presence || 'US'
37
+ def presence
38
+ self if present?
39
+ end
40
+ end
41
+
42
+ class NilClass
43
+ # +nil+ is blank:
44
+ #
45
+ # nil.blank? # => true
46
+ #
47
+ def blank?
48
+ true
49
+ end
50
+ end
51
+
52
+ class FalseClass
53
+ # +false+ is blank:
54
+ #
55
+ # false.blank? # => true
56
+ #
57
+ def blank?
58
+ true
59
+ end
60
+ end
61
+
62
+ class TrueClass
63
+ # +true+ is not blank:
64
+ #
65
+ # true.blank? # => false
66
+ #
67
+ def blank?
68
+ false
69
+ end
70
+ end
71
+
72
+ class Array
73
+ # An array is blank if it's empty:
74
+ #
75
+ # [].blank? # => true
76
+ # [1,2,3].blank? # => false
77
+ #
78
+ alias_method :blank?, :empty?
79
+ end
80
+
81
+ class Hash
82
+ # A hash is blank if it's empty:
83
+ #
84
+ # {}.blank? # => true
85
+ # {:key => 'value'}.blank? # => false
86
+ #
87
+ alias_method :blank?, :empty?
88
+ end
89
+
90
+ class String
91
+ # A string is blank if it's empty or contains whitespaces only:
92
+ #
93
+ # ''.blank? # => true
94
+ # ' '.blank? # => true
95
+ # ' '.blank? # => true
96
+ # ' something here '.blank? # => false
97
+ #
98
+ def blank?
99
+ self !~ /[^[:space:]]/
100
+ end
101
+ end
102
+
103
+ class Numeric #:nodoc:
104
+ # No number is blank:
105
+ #
106
+ # 1.blank? # => false
107
+ # 0.blank? # => false
108
+ #
109
+ def blank?
110
+ false
111
+ end
112
+ end
@@ -0,0 +1,53 @@
1
+ class Object
2
+ # Invokes the public method identified by the symbol +method+, passing it any arguments
3
+ # and/or the block specified, just like the regular Ruby <tt>Object#public_send</tt> does.
4
+ #
5
+ # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
6
+ # and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
7
+ #
8
+ # If try is called without a method to call, it will yield any given block with the object.
9
+ #
10
+ # ==== Examples
11
+ #
12
+ # Without +try+
13
+ # @person && @person.name
14
+ # or
15
+ # @person ? @person.name : nil
16
+ #
17
+ # With +try+
18
+ # @person.try(:name)
19
+ #
20
+ # +try+ also accepts arguments and/or a block, for the method it is trying
21
+ # Person.try(:find, 1)
22
+ # @people.try(:collect) {|p| p.name}
23
+ #
24
+ # Without a method argument try will yield to the block unless the receiver is nil.
25
+ # @person.try { |p| "#{p.first_name} #{p.last_name}" }
26
+ #--
27
+ # +try+ behaves like +Object#public_send+, unless called on +NilClass+.
28
+ def try(*a, &b)
29
+ if a.empty? && block_given?
30
+ yield self
31
+ else
32
+ public_send(*a, &b)
33
+ end
34
+ end
35
+ end
36
+
37
+ class NilClass
38
+ # Calling +try+ on +nil+ always returns +nil+.
39
+ # It becomes specially helpful when navigating through associations that may return +nil+.
40
+ #
41
+ # === Examples
42
+ #
43
+ # nil.try(:name) # => nil
44
+ #
45
+ # Without +try+
46
+ # @person && !@person.children.blank? && @person.children.first.name
47
+ #
48
+ # With +try+
49
+ # @person.try(:children).try(:first).try(:name)
50
+ def try(*args)
51
+ nil
52
+ end
53
+ end
@@ -0,0 +1,258 @@
1
+ module Banana
2
+ # This class provides a simple logger which maintains and displays the runtime of the logger instance.
3
+ # It is intended to be used with the colorize gem but it brings its own colorization to eliminate a
4
+ # dependency. You should initialize the logger as soon as possible to get an accurate runtime.
5
+ #
6
+ # @example
7
+ # logger = Banana::Logger.new
8
+ # logger.log "foo"
9
+ # logger.prefix = "[a] "
10
+ # logger.debug "bar"
11
+ # sleep 2
12
+ # logger.ensure_prefix("[b] ") { logger.warn "baz" }
13
+ # logger.log("rab!", :abort)
14
+ #
15
+ # # Result:
16
+ # # [00:00:00.000 INFO] foo
17
+ # # [00:00:00.000 DEBUG] [a] bar
18
+ # # [00:00:02.001 WARN] [b] baz
19
+ # # [00:00:02.001 ABORT] [a] rab!
20
+ #
21
+ # @!attribute [r] startup
22
+ # @return [DateTime] Point of time where the logger was initiated.
23
+ # @!attribute [r] channel
24
+ # @return [Object] The object where messages are getting send to.
25
+ # @!attribute [r] method
26
+ # @return [Object] The method used to send messages to {#channel}.
27
+ # @!attribute [r] logged
28
+ # @return [Integer] Amount of messages send to channel.
29
+ # @note This counter starts from 0 in every {#ensure_method} or {#log_with_print} block but gets
30
+ # added to the main counter after the call.
31
+ # @!attribute timestr
32
+ # @return [Boolean] Set to false if the runtime indicator should not be printed (default: true).
33
+ # @!attribute colorize
34
+ # @return [Boolean] Set to false if output should not be colored (default: true).
35
+ # @!attribute prefix
36
+ # @return [String] Current prefix string for logged messages.
37
+ class Logger
38
+ attr_reader :startup, :channel, :method, :logged
39
+ attr_accessor :colorize, :prefix
40
+
41
+ # Foreground color values
42
+ COLORMAP = {
43
+ black: 30,
44
+ red: 31,
45
+ green: 32,
46
+ yellow: 33,
47
+ blue: 34,
48
+ magenta: 35,
49
+ cyan: 36,
50
+ white: 37,
51
+ }
52
+
53
+ # Initializes a new logger instance. The internal runtime measurement starts here!
54
+ #
55
+ # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
56
+ # All are enabled by default. You propably want to {#disable disable(:debug)}.
57
+ #
58
+ # @param scope Only for backward compatibility, not used
59
+ # @todo add option hash
60
+ def initialize scope = nil
61
+ @startup = Time.now.utc
62
+ @colorize = true
63
+ @prefix = ""
64
+ @enabled = true
65
+ @timestr = true
66
+ @channel = ::Kernel
67
+ @method = :puts
68
+ @logged = 0
69
+ @levels = {
70
+ info: { color: "yellow", enabled: true },
71
+ warn: { color: "red", enabled: true },
72
+ abort: { color: "red", enabled: true },
73
+ debug: { color: "blue", enabled: true },
74
+ }
75
+ end
76
+
77
+ # The default channel is `Kernel` which is Ruby's normal `puts`.
78
+ # Attach it to a open file with write access and it will write into
79
+ # the file. Ensure to close the file in your code.
80
+ #
81
+ # @param channel Object which responds to puts and print
82
+ def attach channel
83
+ @channel = channel
84
+ end
85
+
86
+ # Print raw message onto {#channel} using {#method}.
87
+ #
88
+ # @param [String] msg Message to send to {#channel}.
89
+ # @param [Symbol] method Override {#method}.
90
+ def raw msg, method = @method
91
+ @channel.send(method, msg)
92
+ end
93
+
94
+ # Add additional log levels which are automatically enabled.
95
+ # @param [Hash] levels Log levels in the format `{ debug: "red" }`
96
+ def log_level levels = {}
97
+ levels.each do |level, color|
98
+ @levels[level.to_sym] ||= { enabled: true }
99
+ @levels[level.to_sym][:color] = color
100
+ end
101
+ end
102
+
103
+ # Calls the block with the given prefix and ensures that the prefix
104
+ # will be the same as before.
105
+ #
106
+ # @param [String] prefix Prefix to use for the block
107
+ # @param [Proc] block Block to call
108
+ def ensure_prefix prefix, &block
109
+ old_prefix, @prefix = @prefix, prefix
110
+ block.call
111
+ ensure
112
+ @prefix = old_prefix
113
+ end
114
+
115
+ # Calls the block after changing the output method.
116
+ # It also ensures to set back the method to what it was before.
117
+ #
118
+ # @param [Symbol] method Method to call on {#channel}
119
+ def ensure_method method, &block
120
+ old_method, old_logged = @method, @logged
121
+ @method, @logged = method, 0
122
+ block.call
123
+ ensure
124
+ @method = old_method
125
+ @logged += old_logged
126
+ end
127
+
128
+ # Calls the block after changing the output method to `:print`.
129
+ # It also ensures to set back the method to what it was before.
130
+ #
131
+ # @param [Boolean] clear If set to true and any message was printed inside the block
132
+ # a \n newline character will be printed.
133
+ def log_with_print clear = true, &block
134
+ ensure_method :print do
135
+ begin
136
+ block.call
137
+ ensure
138
+ puts if clear && @logged > 0
139
+ end
140
+ end
141
+ end
142
+
143
+ # Calls the block after disabling the runtime indicator.
144
+ # It also ensures to set back the old setting after execution.
145
+ def log_without_timestr &block
146
+ timestr, @timestr = @timestr, false
147
+ block.call
148
+ ensure
149
+ @timestr = timestr
150
+ end
151
+
152
+ # @return [Boolean] returns true if the log level format :debug is enabled.
153
+ def debug?
154
+ enabled? :debug
155
+ end
156
+
157
+ # If a `level` is provided it will return true if this log level is enabled.
158
+ # If no `level` is provided it will return true if the logger is enabled generally.
159
+ #
160
+ # @return [Boolean] returns true if the given log level is enabled
161
+ def enabled? level = nil
162
+ level.nil? ? @enabled : @levels[level.to_sym][:enabled]
163
+ end
164
+
165
+ # Same as {#enabled?} just negated.
166
+ def disabled? level = nil
167
+ !enabled?(level)
168
+ end
169
+
170
+ # Same as {#enable} just negated.
171
+ #
172
+ # @param [Symbol, String] level Loglevel to disable.
173
+ def disable level = nil
174
+ if level.nil?
175
+ @enabled = false
176
+ else
177
+ @levels[level.to_sym][:enabled] = false
178
+ end
179
+ end
180
+
181
+ # Enables the given `level` or the logger generally if no `level` is given.
182
+ # If the logger is disabled no messages will be printed. If it is enabled
183
+ # only messages for enabled log levels will be printed.
184
+ #
185
+ # @param [Symbol, String] level Loglevel to enable.
186
+ def enable level = nil
187
+ if level.nil?
188
+ @enabled = true
189
+ else
190
+ @levels[level.to_sym][:enabled] = true
191
+ end
192
+ end
193
+
194
+ # Colorizes the given string with the given color. It uses the build-in
195
+ # colorization feature. You may want to use the colorize gem.
196
+ #
197
+ # @param [String] str The string to colorize
198
+ # @param [Symbol, String] color The color to use (see {COLORMAP})
199
+ # @raise [ArgumentError] if color does not exist in {COLORMAP}.
200
+ def colorize str, color
201
+ ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
202
+ "\e[#{ccode}m#{str}\e[0m"
203
+ end
204
+
205
+ def colorize?
206
+ @colorize
207
+ end
208
+
209
+ # This method is the only method which sends the message `msg` to `@channel` via `@method`.
210
+ # It also increments the message counter `@logged` by one.
211
+ #
212
+ # This method instantly returns nil if the logger or the given log level `type` is disabled.
213
+ #
214
+ # @param [String] msg The message to send to the channel
215
+ # @param [Symbol] type The log level
216
+ def log msg, type = :info
217
+ return if !@enabled || !@levels[type][:enabled]
218
+ if @levels[type.to_sym] || !@levels.key?(type.to_sym)
219
+ time = Time.at(Time.now.utc - @startup).utc
220
+ timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""
221
+
222
+ if @colorize
223
+ msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
224
+ "#{@prefix}" <<
225
+ "#{colorize(msg, @levels[type.to_sym][:color])}"
226
+ else
227
+ msg = "#{timestr}#{@prefix}#{msg}"
228
+ end
229
+ @logged += 1
230
+ @channel.send(@method, msg)
231
+ end
232
+ end
233
+ alias_method :info, :log
234
+
235
+ # Shortcut for {#log #log(msg, :debug)}
236
+ #
237
+ # @param [String] msg The message to send to {#log}.
238
+ def debug msg
239
+ log(msg, :debug)
240
+ end
241
+
242
+ # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
243
+ #
244
+ # @param [String] msg The message to send to {#log}.
245
+ def warn msg
246
+ ensure_method(:warn) { log(msg, :warn) }
247
+ end
248
+
249
+ # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
250
+ #
251
+ # @param [String] msg The message to send to {#log}.
252
+ # @param [Integer] exit_code Exits with given code or does nothing when falsy.
253
+ def abort msg, exit_code = false
254
+ ensure_method(:warn) { log(msg, :abort) }
255
+ exit(exit_code) if exit_code
256
+ end
257
+ end
258
+ end