epitools 0.5.57 → 0.5.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/epitools/browser.rb +4 -2
- data/lib/epitools/core_ext/enumerable.rb +1 -0
- data/lib/epitools/core_ext/misc.rb +1 -1
- data/lib/epitools/core_ext/numbers.rb +26 -10
- data/lib/epitools/core_ext/range.rb +3 -2
- data/lib/epitools/core_ext/string.rb +8 -6
- data/lib/epitools/hexdump.rb +12 -12
- data/lib/epitools/path.rb +111 -33
- data/spec/path_spec.rb +19 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f476bb597f8724e520b4d9c8dda3a051c4e3bb77
|
4
|
+
data.tar.gz: 3974e9c35019dc899060337650af381aac362c83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef2db918b34d5ecfc0ad79f3709947fd26c194488aa2371502cf69fffcf28c83c9a5949f8cba8230816abf38a31522bdd4e54f805e9f9e91f987304a6232af71
|
7
|
+
data.tar.gz: f02ee7dacfdb34acfefd48bde5112dd097d18470963fbbfa5a7aba8a6761e373ace0ed98e9896923ace059d1145bd82491ec12990c88b1ab6c877700bad67627
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.58
|
data/lib/epitools/browser.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'epitools'
|
2
|
-
gem 'mechanize', '~> 1.0'
|
3
2
|
require 'mechanize'
|
4
3
|
require 'epitools/browser/cache'
|
5
|
-
|
4
|
+
|
5
|
+
if Mechanize::VERSION[/^1\./]
|
6
|
+
require 'epitools/browser/mechanize_progressbar'
|
7
|
+
end
|
6
8
|
|
7
9
|
# TODO: Make socksify optional (eg: if proxy is specified)
|
8
10
|
#require 'socksify'
|
@@ -187,6 +187,23 @@ class Numeric
|
|
187
187
|
result
|
188
188
|
end
|
189
189
|
|
190
|
+
def to_hms_in_words
|
191
|
+
seconds = self
|
192
|
+
|
193
|
+
days, seconds = seconds.divmod(86400)
|
194
|
+
hours, seconds = seconds.divmod(3600)
|
195
|
+
minutes, seconds = seconds.divmod(60)
|
196
|
+
seconds, frac = seconds.divmod(1)
|
197
|
+
|
198
|
+
result = "#{seconds} sec"
|
199
|
+
result = "#{minutes} min, " + result if minutes > 0
|
200
|
+
result = "#{"hour".amount(hours)}, " + result if hours > 0 or days > 0
|
201
|
+
result = "#{"day".amount(days)}, " + result if days > 0
|
202
|
+
# result += ("." + frac.round(2).to_s.split(".").last) if frac > 0
|
203
|
+
|
204
|
+
result
|
205
|
+
end
|
206
|
+
|
190
207
|
end
|
191
208
|
|
192
209
|
|
@@ -304,19 +321,18 @@ end
|
|
304
321
|
end
|
305
322
|
end
|
306
323
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
def bytes
|
313
|
-
nbytes = (bit_length / 8.0).ceil
|
324
|
+
#
|
325
|
+
# Convert the integer into its sequence of bytes (little endian format: lowest-order-byte first)
|
326
|
+
#
|
327
|
+
def bytes
|
328
|
+
nbytes = (bit_length / 8.0).ceil
|
314
329
|
|
315
|
-
|
316
|
-
|
330
|
+
(0..nbytes).map do |current_byte|
|
331
|
+
(self >> (8 * current_byte)) & 0xFF
|
332
|
+
end
|
317
333
|
end
|
334
|
+
|
318
335
|
end
|
319
|
-
|
320
336
|
end
|
321
337
|
|
322
338
|
class Time
|
@@ -8,11 +8,12 @@ class Range
|
|
8
8
|
end
|
9
9
|
|
10
10
|
#
|
11
|
-
# The middle
|
11
|
+
# The number in the middle of this range.
|
12
12
|
#
|
13
|
-
def
|
13
|
+
def mid
|
14
14
|
(min + max) / 2
|
15
15
|
end
|
16
|
+
alias_method :middle, :mid
|
16
17
|
|
17
18
|
#
|
18
19
|
# Return a new range which is the intersection of the two ranges
|
@@ -387,6 +387,14 @@ class String
|
|
387
387
|
nums_and_units.map { |num, units| num.send(units) }.sum
|
388
388
|
end
|
389
389
|
|
390
|
+
#
|
391
|
+
# Print a hexdump of the string to STDOUT (coloured, if the terminal supports it)
|
392
|
+
#
|
393
|
+
def hexdump
|
394
|
+
Hex.dump(self)
|
395
|
+
end
|
396
|
+
|
397
|
+
|
390
398
|
unless public_method_defined? :to_proc
|
391
399
|
|
392
400
|
#
|
@@ -462,12 +470,6 @@ class String
|
|
462
470
|
|
463
471
|
end # unless public_method_defined? :to_proc
|
464
472
|
|
465
|
-
|
466
|
-
def highlight(type=nil)
|
467
|
-
# Coderay highlighting
|
468
|
-
end
|
469
|
-
alias_method :syntax_highlight, :highlight
|
470
|
-
|
471
473
|
end
|
472
474
|
|
473
475
|
|
data/lib/epitools/hexdump.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'epitools'
|
2
2
|
|
3
|
-
ASCII_PRINTABLE = (33..126)
|
4
|
-
|
5
3
|
=begin
|
6
4
|
000352c0 ed 33 8c 85 6e cc f6 f7 72 79 1c e3 3a b4 c2 c6 |.3..n...ry..:...|
|
7
5
|
000352d0 c8 8d d6 ee 3e 68 a1 a5 ae b2 b7 97 a4 1d 5f a7 |....>h........_.|
|
@@ -19,6 +17,8 @@ ASCII_PRINTABLE = (33..126)
|
|
19
17
|
|
20
18
|
module Hex
|
21
19
|
|
20
|
+
ASCII_PRINTABLE = (33..126)
|
21
|
+
|
22
22
|
DUMP_COLORS = Rash.new(
|
23
23
|
/\d/ => 13,
|
24
24
|
/\w/ => 3,
|
@@ -31,15 +31,15 @@ module Hex
|
|
31
31
|
color = options[:color].nil? ? true : options[:color]
|
32
32
|
highlight = options[:highlight]
|
33
33
|
|
34
|
-
p options
|
35
|
-
p color
|
34
|
+
# p options
|
35
|
+
# p color
|
36
36
|
|
37
37
|
lines = data.scan(/.{1,16}/m)
|
38
38
|
max_offset = (base_offset + data.size) / 16 * 16
|
39
39
|
max_offset_width = max_offset.to_s.size
|
40
40
|
max_hex_width = 3 * 16 + 1
|
41
41
|
|
42
|
-
p [max_offset, max_offset_width]
|
42
|
+
# p [max_offset, max_offset_width]
|
43
43
|
lines.each_with_index do |line,n|
|
44
44
|
offset = base_offset + n*16
|
45
45
|
bytes = line.unpack("C*")
|
@@ -53,21 +53,21 @@ module Hex
|
|
53
53
|
end
|
54
54
|
end.join('')
|
55
55
|
|
56
|
-
puts "<11>#{offset.to_s.ljust(max_offset_width)}<3>: <14>#{hex.ljust(max_hex_width)} <8>|<15>#{plain}<8>|".colorize
|
56
|
+
puts "<11>#{offset.to_s.ljust(max_offset_width)}<3>: <14>#{hex.ljust(max_hex_width)} <8>|<15>#{plain}<8>|".colorize(:strip => !color)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
60
|
end
|
61
61
|
|
62
|
-
def hexdump(*args)
|
63
|
-
Hex.dump(*args)
|
64
|
-
end
|
65
|
-
|
66
62
|
if $0 == __FILE__
|
67
63
|
data = (0..64).map{ rand(255).chr }.join('')
|
68
|
-
|
69
|
-
puts
|
64
|
+
|
65
|
+
puts "Random data"
|
70
66
|
Hex.dump(data, :color=>false)
|
67
|
+
|
68
|
+
puts "Random data (now in colour!):"
|
69
|
+
Hex.dump(data)
|
70
|
+
|
71
71
|
puts
|
72
72
|
|
73
73
|
data = "1234567890"*10
|
data/lib/epitools/path.rb
CHANGED
@@ -10,48 +10,100 @@ require 'epitools/core_ext/string'
|
|
10
10
|
#
|
11
11
|
# Path: An object-oriented wrapper for files. (Combines useful methods from FileUtils, File, Dir, and more!)
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# To create a path object, or array of path objects, throw whatever you want into Path[]:
|
14
14
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# dir => just the directory
|
20
|
-
# dirs => an array of directories
|
15
|
+
# These returns a single path object:
|
16
|
+
# passwd = Path["/etc/passwd"]
|
17
|
+
# also_passwd = Path["/etc"] / "passwd" # joins two paths
|
18
|
+
# parent_dir = Path["/usr/local/bin"] / ".." # joins two paths (up one dir)
|
21
19
|
#
|
22
|
-
#
|
23
|
-
#
|
20
|
+
# These return an array of path objects:
|
21
|
+
# pictures = Path["photos/*.{jpg,png}"] # globbing
|
22
|
+
# notes = Path["notes/2014/**/*.txt"] # recursive globbing
|
23
|
+
# everything = Path["/etc"].ls
|
24
24
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
25
|
+
# Each Path object has the following attributes, which can all be modified:
|
26
|
+
#
|
27
|
+
# path => the absolute path, as a string
|
28
|
+
# filename => just the name and extension
|
29
|
+
# basename => just the filename (without extension)
|
30
|
+
# ext => just the extension
|
31
|
+
# dir => just the directory
|
32
|
+
# dirs => an array of directories
|
33
|
+
#
|
34
|
+
# Some commonly used methods:
|
35
|
+
#
|
36
|
+
# path.file?
|
37
|
+
# path.exists?
|
38
|
+
# path.dir?
|
39
|
+
# path.mtime
|
40
|
+
# path.xattrs
|
41
|
+
# path.symlink?
|
42
|
+
# path.broken_symlink?
|
43
|
+
# path.symlink_target
|
44
|
+
# path.executable?
|
45
|
+
# path.chmod(0o666)
|
46
|
+
#
|
47
|
+
# Interesting examples:
|
48
|
+
#
|
49
|
+
# Path["*.jpeg"].each { |path| path.rename(:ext=>"jpg") } # renames .jpeg to .jpg
|
50
|
+
#
|
51
|
+
# files = Path["/etc"].ls # all files in directory
|
52
|
+
# morefiles = Path["/etc"].ls_R # all files in directory tree
|
53
|
+
#
|
54
|
+
# Path["*.txt"].each(&:gzip!)
|
55
|
+
#
|
56
|
+
# Path["filename.txt"] << "Append data!" # appends data to a file
|
57
|
+
#
|
58
|
+
# string = Path["filename.txt"].read # read all file data into a string
|
59
|
+
# json = Path["filename.json"].read_json # read and parse JSON
|
60
|
+
# doc = Path["filename.html"].read_html # read and parse HTML
|
61
|
+
# xml = Path["filename.xml"].parse # figure out the format and parse it (as XML)
|
62
|
+
#
|
63
|
+
# Path["saved_data.marshal"].write(data.marshal) # Save your data!
|
64
|
+
# data = Path["saved_data.marshal"].unmarshal # Load your data!
|
65
|
+
#
|
66
|
+
# Path["unknown_file"].mimetype # sniff the file to determine its mimetype
|
67
|
+
# Path["unknown_file"].mimetype.image? # ...is this some kind of image?
|
68
|
+
#
|
69
|
+
# Path["otherdir/"].cd do # temporarily change to "otherdir/"
|
70
|
+
# p Path.ls
|
71
|
+
# end
|
72
|
+
# p Path.ls
|
73
|
+
#
|
74
|
+
# The `Path#dirs` attribute is a split up version of the directory
|
75
|
+
# (eg: Path["/usr/local/bin"].dirs => ["usr", "local", "bin"]).
|
76
|
+
#
|
77
|
+
# You can modify the dirs array to change subsets of the directory. Here's an example that
|
78
|
+
# finds out if you're in a git repo:
|
79
|
+
#
|
80
|
+
# def inside_a_git_repo?
|
81
|
+
# path = Path.pwd # start at the current directory
|
28
82
|
# while path.dirs.any?
|
29
|
-
#
|
30
|
-
#
|
83
|
+
# if (path/".git").exists?
|
84
|
+
# return true
|
85
|
+
# else
|
86
|
+
# path.dirs.pop # go up one level
|
87
|
+
# end
|
31
88
|
# end
|
32
89
|
# false
|
33
90
|
# end
|
34
91
|
#
|
35
|
-
# More examples:
|
36
|
-
#
|
37
|
-
# Path["*.jpeg"].each { |path| path.rename(:ext=>"jpg") }
|
38
|
-
# Path["filename.txt"] << "Append data!"
|
39
|
-
# etcfiles = Path["/etc"].ls
|
40
|
-
# Path["*.txt"].each(&:gzip)
|
41
|
-
#
|
42
92
|
# Swap two files:
|
43
93
|
#
|
44
94
|
# a, b = Path["file_a", "file_b"]
|
45
|
-
# temp = a.with(:ext=>a.ext+".swapping") # return a modified version of this object
|
95
|
+
# temp = a.with(:ext => a.ext+".swapping") # return a modified version of this object
|
46
96
|
# a.mv(temp)
|
47
97
|
# b.mv(a)
|
48
98
|
# temp.mv(b)
|
49
99
|
#
|
50
|
-
# Paths can be created for existant and non-existant files.
|
51
|
-
#
|
100
|
+
# Paths can be created for existant and non-existant files.
|
101
|
+
#
|
102
|
+
# To create a nonexistant path object that thinks it's a directory, just add a '/' at the end.
|
103
|
+
# (eg: Path["/etc/nonexistant/"]).
|
52
104
|
#
|
53
105
|
# Performance has been an important factor in Path's design, so doing crazy things with Path
|
54
|
-
# usually doesn't kill
|
106
|
+
# usually doesn't kill performance. Go nuts!
|
55
107
|
#
|
56
108
|
#
|
57
109
|
class Path
|
@@ -196,7 +248,7 @@ class Path
|
|
196
248
|
end
|
197
249
|
|
198
250
|
#
|
199
|
-
# Reload this path (
|
251
|
+
# Reload this path (updates cached values.)
|
200
252
|
#
|
201
253
|
def reload!
|
202
254
|
temp = path
|
@@ -286,6 +338,14 @@ class Path
|
|
286
338
|
extensions
|
287
339
|
end
|
288
340
|
|
341
|
+
###############################################################################
|
342
|
+
# inspect
|
343
|
+
###############################################################################
|
344
|
+
|
345
|
+
def inspect
|
346
|
+
"#<Path:#{path}>"
|
347
|
+
end
|
348
|
+
|
289
349
|
###############################################################################
|
290
350
|
# fstat
|
291
351
|
###############################################################################
|
@@ -546,8 +606,21 @@ class Path
|
|
546
606
|
#
|
547
607
|
# All the lines in this file, chomped.
|
548
608
|
#
|
549
|
-
def
|
550
|
-
io.
|
609
|
+
def each_line
|
610
|
+
io.each_line
|
611
|
+
end
|
612
|
+
alias_method :lines, :each_line
|
613
|
+
|
614
|
+
def grep(pat)
|
615
|
+
return to_enum(:grep, pat).to_a unless block_given?
|
616
|
+
|
617
|
+
each_line do |line|
|
618
|
+
yield line if line =~ pat
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
def nicelines
|
623
|
+
lines.map(&:chomp)
|
551
624
|
end
|
552
625
|
|
553
626
|
def unmarshal
|
@@ -733,7 +806,7 @@ class Path
|
|
733
806
|
# Renames the file, but doesn't change the current Path object, and returns a Path that points at the new filename.
|
734
807
|
#
|
735
808
|
# Examples:
|
736
|
-
# Path["file"].rename("newfile")
|
809
|
+
# Path["file"].rename("newfile") #=> Path["newfile"]
|
737
810
|
# Path["SongySong.mp3"].rename(:basename=>"Songy Song")
|
738
811
|
# Path["Songy Song.mp3"].rename(:ext=>"aac")
|
739
812
|
# Path["Songy Song.aac"].rename(:dir=>"/music2")
|
@@ -851,8 +924,7 @@ class Path
|
|
851
924
|
end
|
852
925
|
|
853
926
|
def ln_s(dest)
|
854
|
-
|
855
|
-
FileUtils.ln_s(self, dest)
|
927
|
+
Path.ln_s(self, dest)
|
856
928
|
end
|
857
929
|
|
858
930
|
## Owners and permissions
|
@@ -1179,10 +1251,13 @@ class Path
|
|
1179
1251
|
orig = pwd
|
1180
1252
|
|
1181
1253
|
Dir.chdir(dest)
|
1182
|
-
yield
|
1254
|
+
result = yield dest
|
1183
1255
|
Dir.chdir(orig)
|
1256
|
+
|
1257
|
+
result
|
1184
1258
|
else
|
1185
1259
|
Dir.chdir(dest)
|
1260
|
+
dest
|
1186
1261
|
end
|
1187
1262
|
end
|
1188
1263
|
|
@@ -1190,7 +1265,10 @@ class Path
|
|
1190
1265
|
|
1191
1266
|
def self.ls_r(path); Path[path].ls_r; end
|
1192
1267
|
|
1193
|
-
def self.ln_s(src, dest)
|
1268
|
+
def self.ln_s(src, dest)
|
1269
|
+
FileUtils.ln_s(src, dest)
|
1270
|
+
Path[dest]
|
1271
|
+
end
|
1194
1272
|
|
1195
1273
|
## TODO: Verbose mode
|
1196
1274
|
#def self.verbose=(value); @@verbose = value; end
|
data/spec/path_spec.rb
CHANGED
@@ -460,7 +460,7 @@ describe Path do
|
|
460
460
|
(path.mode & 0o666).should > 0
|
461
461
|
end
|
462
462
|
|
463
|
-
it 'symlinks
|
463
|
+
it 'symlinks files' do
|
464
464
|
path = Path.tmpfile
|
465
465
|
path << "some data"
|
466
466
|
|
@@ -474,6 +474,24 @@ describe Path do
|
|
474
474
|
target.symlink_target.should == path
|
475
475
|
end
|
476
476
|
|
477
|
+
it 'symlinks relative dirs' do
|
478
|
+
dir = Path["/tmp/dir/"]
|
479
|
+
dir.mkdir
|
480
|
+
tmp = Path["/tmp/symlinktarget"]
|
481
|
+
tmp << "data"
|
482
|
+
|
483
|
+
|
484
|
+
link = (dir/"symlink")
|
485
|
+
link.ln_s "../file"
|
486
|
+
|
487
|
+
link.symlink?.should == true
|
488
|
+
|
489
|
+
tmp.read.should ==
|
490
|
+
|
491
|
+
tmp.rm
|
492
|
+
dir.rm
|
493
|
+
end
|
494
|
+
|
477
495
|
it 'swaps two files' do
|
478
496
|
# swap two regular files
|
479
497
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epitools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.58
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- epitron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|