epitools 0.5.37 → 0.5.38

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74b5a665bc66555050576a5aa863b79017d10e90
4
- data.tar.gz: a860badfc15c9f1f44f7d8db7aa4f47d2ef32bd4
3
+ metadata.gz: 22d5dfb7f91836122b2c98f3699a61a95e564f93
4
+ data.tar.gz: e948af15b3b59d8c1d6fdb8d6077fb83abdcddf0
5
5
  SHA512:
6
- metadata.gz: 1d19c2fd984f89485d8a00f7c2f8c5fb0cdeff916b1bf7fa8ea4a5922c447258a56ea21b610ae20e6c5e0b27d5e4679a4d9617b7263d9dbe1b36eaefff4a8f8e
7
- data.tar.gz: db684ad10202d61c32167346cf6e3032316041308a0914bd3be5ac5b3ef535a687362966be703778f573686180c526ea3d4525957b9042669bb1cbd9d497e888
6
+ metadata.gz: a457026eed7f6db059cdf1638a63515034fec427e3fb61b5eed17f18bd163863175297eab9400bd0a91b030e0893da94173d94dad738df58b5be6eea1c5cb092
7
+ data.tar.gz: e5fe8275dfc204ca5772b33fd3ceae35735a398a073f7201f022a6fcff8c014190a25dd3d0bc39cd54dc1e52c2bc0761cc056a1fe80e00bd11e82d71449d78d3
data/README.rdoc CHANGED
@@ -8,7 +8,7 @@ All epitools modules (and a bunch of Ruby's stdlib) are
8
8
  {loaded on demand with "autoload"}[https://github.com/epitron/epitools/blob/master/lib/epitools/autoloads.rb],
9
9
  so it's really fast. (Require this in your .irbrc or .pryrc, and you'll never have to require another Ruby stdlib module again!)
10
10
 
11
- Enhanced base classes: {Enumerable}[http://rdoc.info/github/epitron/epitools/master/Enumerable], {Hash}[http://rdoc.info/github/epitron/epitools/master/Hash], {String}[http://rdoc.info/github/epitron/epitools/master/String], {Array}[http://rdoc.info/github/epitron/epitools/master/Array], {Object}[http://rdoc.info/github/epitron/epitools/master/Object], {Integer}[http://rdoc.info/github/epitron/epitools/master/Integer], etc.
11
+ Enhanced base classes: {Enumerable}[http://rdoc.info/github/epitron/epitools/master/Enumerable], {Hash}[http://rdoc.info/github/epitron/epitools/master/Hash], {String}[http://rdoc.info/github/epitron/epitools/master/String], {Array}[http://rdoc.info/github/epitron/epitools/master/Array], {File}[http://rdoc.info/github/epitron/epitools/master/File], {Object}[http://rdoc.info/github/epitron/epitools/master/Object], {Integer}[http://rdoc.info/github/epitron/epitools/master/Integer], etc.
12
12
 
13
13
  Extras:
14
14
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.37
1
+ 0.5.38
@@ -8,7 +8,7 @@ class BOFError < Exception; end
8
8
  class File
9
9
 
10
10
  #
11
- # A much faster `reverse_each` implementation.
11
+ # A streaming `reverse_each` implementation. (For large files, it's faster and uses less memory.)
12
12
  #
13
13
  def reverse_each(&block)
14
14
  return to_enum(:reverse_each) unless block_given?
@@ -18,20 +18,33 @@ class File
18
18
  end
19
19
 
20
20
  #
21
- # Read the previous +length+ bytes. After the read, +pos+ will be at the beginning of the region that you just read.
21
+ # Read the previous `length` bytes. After the read, `pos` will be at the beginning of the region that you just read.
22
+ # Returns `nil` when the beginning of the file is reached.
22
23
  #
23
- def read_backwards(length)
24
- old_pos = pos
24
+ # If the `block_aligned` argument is `true`, reads will always be aligned to file positions which are multiples of 512 bytes.
25
+ # (This should increase performance slightly.)
26
+ #
27
+ def reverse_read(length, block_aligned=false)
28
+ raise "length must be a multiple of 512" if block_aligned and length % 512 != 0
29
+
30
+ end_pos = pos
31
+
32
+ if block_aligned
33
+ misalignment = end_pos % length
34
+ length += misalignment
35
+ end
25
36
 
26
- if length > pos
37
+ return nil if end_pos == 0
38
+
39
+ if length >= end_pos # this read will take us to the beginning of the file
27
40
  seek(0)
28
41
  else
29
42
  seek(-length, IO::SEEK_CUR)
30
43
  end
31
44
 
32
- new_pos = pos
33
- data = read(old_pos - new_pos)
34
- seek(new_pos)
45
+ start_pos = pos
46
+ data = read(end_pos - start_pos)
47
+ seek(start_pos)
35
48
 
36
49
  data
37
50
  end
@@ -42,22 +55,17 @@ class File
42
55
  def reverse_each_from_current_pos
43
56
  return to_enum(:reverse_each_from_current_pos) unless block_given?
44
57
 
58
+ # read the rest of the current line, in case we started in the middle of a line
59
+ start_pos = pos
45
60
  fragment = readline rescue ""
61
+ seek(start_pos)
46
62
 
47
- loop do
48
- data = read_backwards(4096) + fragment
49
- loc = data.size-1
50
-
51
- # NOTE: `rindex(str, loc)` includes the character at `loc`
52
- while index = data.rindex("\n", loc-1)
53
- line = data[index+1..loc]
54
- yield line
55
- loc = index
56
- end
63
+ while data = reverse_read(4096)
64
+ data += fragment
65
+ lines = data.lines
66
+ fragment = lines.shift
57
67
 
58
- fragment = data[0..loc]
59
-
60
- break if pos == 0 # we're done reading!
68
+ lines.reverse_each { |line| yield line }
61
69
  end
62
70
 
63
71
  yield fragment
@@ -70,6 +78,13 @@ class File
70
78
  seek(0, IO::SEEK_END)
71
79
  end
72
80
 
81
+ #
82
+ # Seek to `BOF`
83
+ #
84
+ def seek_start
85
+ seek(0)
86
+ end
87
+
73
88
  #
74
89
  # Read the previous line (leaving `pos` at the beginning of the string that was read.)
75
90
  #
@@ -88,7 +103,7 @@ class File
88
103
  #
89
104
  def seek_backwards_to(string, blocksize=512, rindex_end=-1)
90
105
  loop do
91
- data = read_backwards(blocksize)
106
+ data = reverse_read(blocksize)
92
107
 
93
108
  if index = data.rindex(string, rindex_end)
94
109
  seek(index+string.size, IO::SEEK_CUR)
@@ -101,21 +101,32 @@ class String
101
101
  def wrap(width=nil, ignore=nil)
102
102
  if width.nil?
103
103
  require 'io/console'
104
- height, width = STDIN.winsize
104
+ _, width = STDIN.winsize
105
+ width -= 1
105
106
  end
106
107
 
107
- wrap_re = /(?:.{1,#{width}}[ \t]+|.{1,#{width}})/
108
+ return self if size <= width
108
109
 
109
- # TODO: 'ignore' ignores characters matching some regexp
110
- #
111
- # if ignore
112
- # stripped = gsub(ignore, '') # remove whatever we're ignoring
113
- # lines = stripped.scan(wrap_re) # wrap the lines
114
- # lines.each do |line|
115
- # line.
116
- # end
117
-
118
- scan(wrap_re).map(&:rstrip).join("\n")
110
+ strings = []
111
+ start_pos = 0
112
+ end_pos = width
113
+
114
+ loop do
115
+ split_pos = rindex(/\s/, end_pos) || end_pos
116
+
117
+ strings << self[start_pos...split_pos]
118
+
119
+ start_pos = index(/\S/, split_pos)
120
+ break if start_pos == nil
121
+ end_pos = start_pos + width
122
+
123
+ if end_pos > size
124
+ strings << self[start_pos..-1]
125
+ break
126
+ end
127
+ end
128
+
129
+ strings.join("\n")
119
130
  end
120
131
 
121
132
  #
@@ -216,8 +216,10 @@ describe String do
216
216
  it "wraps" do
217
217
  s1 = "Hello there, I am a sentence or series of words."
218
218
  s2 = "012345678901234567890123456789012345678901234567"
219
+ s3 = "hello there"
219
220
  s1.wrap(14).should == "Hello there, I\nam a sentence\nor series of\nwords."
220
221
  s2.wrap(14).should == "01234567890123\n45678901234567\n89012345678901\n234567"
222
+ s3.wrap(80).should == "hello there"
221
223
  end
222
224
 
223
225
  it "indents" do
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.37
4
+ version: 0.5.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - epitron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-23 00:00:00.000000000 Z
11
+ date: 2013-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec