rio 0.3.3 → 0.3.4

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.
Files changed (88) hide show
  1. data/ChangeLog +225 -0
  2. data/README +12 -0
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/doc/ANNOUNCE +160 -71
  6. data/doc/RELEASE_NOTES +71 -2
  7. data/ex/colx.rb +1 -1
  8. data/ex/passwd_report.rb +4 -8
  9. data/ex/riocat +5 -5
  10. data/ex/riogunzip +1 -1
  11. data/ex/riogzip +6 -6
  12. data/ex/rioprompt.rb +6 -0
  13. data/lib/rio.rb +3 -13
  14. data/lib/rio/arycopy.rb +1 -1
  15. data/lib/rio/base.rb +1 -5
  16. data/lib/rio/construct.rb +75 -0
  17. data/lib/rio/constructor.rb +42 -11
  18. data/lib/rio/context.rb +1 -1
  19. data/lib/rio/context/dir.rb +50 -23
  20. data/lib/rio/context/methods.rb +5 -3
  21. data/lib/rio/{cxdir.rb → context/skip.rb} +24 -36
  22. data/lib/rio/context/stream.rb +38 -16
  23. data/lib/rio/cp.rb +24 -5
  24. data/lib/rio/dir.rb +8 -7
  25. data/lib/rio/doc/HOWTO.rb +33 -33
  26. data/lib/rio/doc/INTRO.rb +416 -256
  27. data/lib/rio/doc/MISC.rb +3 -1
  28. data/lib/rio/doc/SYNOPSIS.rb +28 -33
  29. data/lib/rio/entrysel.rb +76 -9
  30. data/lib/rio/file.rb +2 -1
  31. data/lib/rio/filter.rb +95 -0
  32. data/lib/rio/filter/closeoneof.rb +1 -1
  33. data/lib/rio/grande.rb +0 -74
  34. data/lib/rio/if.rb +2 -1
  35. data/lib/rio/if/basic.rb +1 -1
  36. data/lib/rio/if/csv.rb +1 -1
  37. data/lib/rio/if/dir.rb +1 -220
  38. data/lib/rio/if/fileordir.rb +26 -12
  39. data/lib/rio/if/grande.rb +55 -6
  40. data/lib/rio/if/grande_entry.rb +355 -0
  41. data/lib/rio/if/{methods.rb → grande_stream.rb} +69 -88
  42. data/lib/rio/if/path.rb +25 -3
  43. data/lib/rio/if/stream.rb +62 -37
  44. data/lib/rio/if/temp.rb +2 -2
  45. data/lib/rio/if/test.rb +23 -0
  46. data/lib/rio/impl/path.rb +5 -0
  47. data/lib/rio/match.rb +6 -3
  48. data/lib/rio/matchrecord.rb +50 -46
  49. data/lib/rio/{filter/chomp.rb → ops/construct.rb} +12 -20
  50. data/lib/rio/ops/create.rb +3 -0
  51. data/lib/rio/ops/dir.rb +12 -6
  52. data/lib/rio/ops/either.rb +17 -3
  53. data/lib/rio/ops/path.rb +4 -1
  54. data/lib/rio/ops/stream/input.rb +6 -1
  55. data/lib/rio/ops/stream/read.rb +1 -3
  56. data/lib/rio/{context/chomp.rb → prompt.rb} +17 -13
  57. data/lib/rio/rl/base.rb +1 -1
  58. data/lib/rio/rl/builder.rb +3 -1
  59. data/lib/rio/state.rb +7 -13
  60. data/lib/rio/stream.rb +8 -5
  61. data/lib/rio/stream/open.rb +1 -1
  62. data/lib/rio/version.rb +1 -1
  63. data/test/mswin32.rb +1 -1
  64. data/test/runtests_gem.rb +1 -1
  65. data/test/tc/all.rb +3 -0
  66. data/test/tc/copy-from.rb +13 -13
  67. data/test/tc/copy-to.rb +1 -1
  68. data/test/tc/copy.rb +1 -1
  69. data/test/tc/copydir.rb +0 -24
  70. data/test/tc/copysymlink.rb +39 -0
  71. data/test/tc/csv.rb +2 -2
  72. data/test/tc/csv2.rb +4 -4
  73. data/test/tc/misc.rb +16 -16
  74. data/test/tc/nolines.rb +26 -26
  75. data/test/tc/noqae.rb +74 -74
  76. data/test/tc/overload.rb +28 -28
  77. data/test/tc/riorl.rb +36 -0
  78. data/test/tc/selnosel.rb +36 -0
  79. data/test/tc/skip.rb +58 -0
  80. data/test/tc/skiplines.rb +42 -0
  81. data/test/tc/symlink.rb +1 -1
  82. data/test/tc/symlink0.rb +1 -1
  83. data/test/tc/temp.rb +1 -1
  84. data/test/tc/tempdir.rb +1 -1
  85. data/test/tc/testcase.rb +7 -1
  86. metadata +14 -8
  87. data/lib/rio/matchcolumns.rb +0 -266
  88. data/lib/rio/rangemath.rb +0 -44
@@ -321,7 +321,7 @@ module RIO
321
321
  def /(arg) target / arg end
322
322
 
323
323
 
324
- # Create a Rio referencing Rio#to_s + arg.to_s
324
+ # Create a Rio referencing Rio#to_str + arg.to_str
325
325
  #
326
326
  # rio('afile') + '-0.1' #=> rio('afile-0.1')
327
327
  #
@@ -365,7 +365,9 @@ module RIO
365
365
  # Rio#rootpath
366
366
  #
367
367
  #
368
- def rootpath(*args) target.rootpath(*args) end
368
+ def rootpath(*args) # :nodoc:
369
+ target.rootpath(*args)
370
+ end
369
371
 
370
372
 
371
373
  # Rio#root
@@ -386,7 +388,7 @@ module RIO
386
388
  ##def getwd(*args,&block) target.getwd(*args,&block) end
387
389
 
388
390
 
389
- # Returns the scheme for the Rio's URI like URI#scheme where the Rio is represented
391
+ # Returns the scheme for the Rio's URI-like URI#scheme where the Rio is represented
390
392
  # by a standard URI. For Rios that are not represented by standard URIs one of
391
393
  # Rio's non-standard schemes is returned.
392
394
  #
@@ -434,6 +436,26 @@ module RIO
434
436
  #
435
437
  def route_to(other) target.route_to(other) end
436
438
 
439
+ # Calls Pathname#cleanpath
440
+ #
441
+ # Returns a new Rio whose path is the clean pathname of +self+ with
442
+ # consecutive slashes and useless dots
443
+ # removed. The filesystem is not accessed.
444
+ #
445
+ # If +consider_symlink+ is +true+, then a more conservative algorithm is used
446
+ # to avoid breaking symbolic linkages. This may retain more <tt>..</tt>
447
+ # entries than absolutely necessary, but without accessing the filesystem,
448
+ # this can't be avoided. See #realpath.
449
+ #
450
+ def cleanpath(consider_symlink=false) target.cleanpath(consider_symlink) end
437
451
 
452
+ # Calls Pathname#realpath
453
+ #
454
+ # Returns a new Rio whose path is the real (absolute) pathname
455
+ # of +self+ in the actual filesystem.
456
+ # The real pathname doesn't contain symlinks or useless dots.
457
+ #
458
+ def realpath() target.realpath() end
459
+
438
460
  end
439
461
  end
@@ -51,22 +51,11 @@ module RIO
51
51
 
52
52
  # Slurps the contents of the rio into a string. See also Rio#contents
53
53
  #
54
- # astring = rio('afile.txt').slurp # slurp the entire contents of afile.txt into astring
54
+ # astring = rio('afile.txt').contents # slurp the entire contents of afile.txt into astring
55
55
  #
56
- # Alpha Note: Considering removing Rio#contents and Rio#slurp in favor of +to_string+. Is
57
- # this the Ruby way? Is it too confusing with a +to_s+ and +to_str+ already? Is it a good idea?
58
- def slurp() target.slurp() end
59
-
60
- # Returns the contents of the rio as a string. See also Rio#slurp
61
- #
62
- # astring = rio('afile.txt').contents # copies the entire contents of afile.txt into astring
63
- #
64
- # Alpha Note: Considering removing Rio#contents and Rio#slurp in favor of +to_string+. Is
65
- # this the Ruby way? Is it too confusing with a +to_s+ and +to_str+ already? Is it a good idea?
66
56
  def contents() target.contents() end
67
57
 
68
58
 
69
-
70
59
  # Rio#each_record
71
60
  #
72
61
  #
@@ -98,8 +87,8 @@ module RIO
98
87
  def lineno() target.lineno() end
99
88
 
100
89
  # Calls IO#lineno=
101
- # ario.lineno = integer => integer
102
- # Manually sets the current line number to the given value. +$.+ is
90
+ # ario.lineno = integer => integer
91
+ # Manually sets the current line number to the given value. <tt>$.</tt> is
103
92
  # updated only on the next read.
104
93
  #
105
94
  # f = rio("testfile")
@@ -122,35 +111,25 @@ module RIO
122
111
  #
123
112
  # To illustrate: Given a file containing three lines "L0\n","L1\n","L2\n"
124
113
  # and a Range (0..1)
125
- # Each of the following would fill ay with ["L0\n", "L1\n"]
126
- #
127
- # ay = []
114
+ # Each of the following would fill anarray with ["L0\n", "L1\n"]
115
+ #
116
+ # Given:
117
+ # anarray = []
128
118
  # range = (0..1)
129
- # ain = rio('afile').readlines
130
- # ain.each_with_index do |line,i|
131
- # ay << line if range === i
119
+ #
120
+ # all_lines = rio('afile').readlines
121
+ # all_lines.each_with_index do |line,i|
122
+ # anarray << line if range === i
132
123
  # end
133
- #
134
- # ay = rio('afile').lines[0..1]
135
- #
124
+ # # anarray == ["L0\n", "L1\n"]
125
+ #
126
+ # anarray = rio('afile').lines[0..1] # anarray == ["L0\n", "L1\n"]
127
+ #
136
128
  # +recno+ counts the number of times Rio#getrec or Rio#each is used to get a record.
137
129
  # so +recno+ will only concern parts of the file read with grande methods
138
130
  # Rio#each, Rio#[], Rio#getrec
139
131
  #
140
132
  # See also Rio#lineno
141
- # f = rio("afile")
142
- # r1 = (0..1)
143
- # r2 = (100..101)
144
- #
145
- # aout1 = []
146
- # f.each { |rec|
147
- # aout << rec if r1 === f.recno or r2 === f.recno
148
- # }
149
- #
150
- # aout2 = f[r1,r2]
151
- #
152
- # aout1 == aout2 # true
153
- #
154
133
  def recno() target.recno() end
155
134
 
156
135
 
@@ -281,7 +260,7 @@ module RIO
281
260
 
282
261
  # Calls IO#puts
283
262
  #
284
- # Writes the given objects to the rio as with Rio#print .
263
+ # Writes the given objects to the rio as with Rio#print.
285
264
  # Writes a record separator (typically a newline) after any that do not already end with a newline sequence.
286
265
  # If called with an array argument, writes each element on a new line.
287
266
  # If called without arguments, outputs a single record separator.
@@ -595,5 +574,51 @@ module RIO
595
574
  #
596
575
  def ungetc(*args) target.ungetc(*args); self end
597
576
 
577
+ # Sets the 'sync-mode' of the underlying IO using IO#sync=
578
+ # ario.sync(boolean=true,&block) => ario
579
+ # Sets the Rio so that its 'sync mode' will be set to +true+ or +false+ when opened, or set
580
+ # it immediately if already open. When sync mode is
581
+ # true, all output is immediately flushed to the underlying operating
582
+ # system and is not buffered internally. Returns the rio. See
583
+ # also Rio#fsync, Rio#nosync, Rio#sync?.
584
+ #
585
+ # If a block is given behaves like <tt>ario.sync(arg).each(&block)</tt>
586
+ #
587
+ # f = rio("testfile").sync.puts("Hello World")
588
+ # f.sync? # => true
589
+ #
590
+ def sync(arg=true,&block) target.sync(arg,&block); self end
591
+
592
+ # Similar to IO#sync= false
593
+ # ario.nosync(&block) => ario
594
+ # Sets the Rio so that its 'sync mode' will be set to +false+ when opened, or set
595
+ # it immediately if already open. When sync mode is
596
+ # true, all output is immediately flushed to the underlying operating
597
+ # system and is not buffered internally. Returns the rio. See
598
+ # also Rio#fsync, Rio#sync, Rio#sync?.
599
+ #
600
+ # If a block is given behaves like <tt>ario.nosync.each(&block)</tt>
601
+ #
602
+ # f = rio("testfile").sync.puts("Hello World")
603
+ # f.sync? # => true
604
+ # f.nosync
605
+ # f.sync? # => false
606
+ #
607
+ def nosync(arg=false,&block) target.nosync(arg,&block); self end
608
+
609
+ # Query the current "sync mode" with IO#sync
610
+ # ario.sync? => true or false
611
+ # Returns the current "sync mode" of _ario_. When sync mode is true,
612
+ # all output is immediately flushed to the underlying operating
613
+ # system and is not buffered by Ruby internally. See also Rio#fsync,
614
+ # Rio#sync, Rio#nosync
615
+ #
616
+ # f = rio("testfile")
617
+ # f.sync? #=> false
618
+ #
619
+ def sync?() target.sync?() end
620
+
621
+
622
+
598
623
  end
599
624
  end
@@ -37,8 +37,8 @@
37
37
 
38
38
  module RIO
39
39
  class Rio
40
- def file() target.file; self end
41
- def dir() target.dir; self end
40
+ #def file() target.file; self end
41
+ #def dir() target.dir; self end
42
42
 
43
43
 
44
44
  end
@@ -41,27 +41,35 @@ module RIO
41
41
  # rio('afile').blockdev? => true or false
42
42
  # Returns +true+ if the named file is a block device.
43
43
  def blockdev?() target.blockdev?() end
44
+
44
45
  # Calls FileTest#chardev?
45
46
  # rio('afile').chardev? => true or false
46
47
  # Returns +true+ if the named file is a character device.
47
48
  def chardev?() target.chardev? end
49
+
48
50
  # Calls FileTest#directory?
49
51
  # rio('afile').directory? => true or false
50
52
  # Returns +true+ if the named file is a directory, +false+ otherwise.
51
53
  def directory?() target.directory? end
54
+
55
+ # Alias for #directory?
52
56
  def dir?() target.dir? end
57
+
53
58
  # Calls FileTest#exist?
54
59
  # rio('afile').exist?() => true or false
55
60
  # Returns +true+ if the named file exists.
56
61
  def exist?() target.exist? end
62
+
57
63
  # Calls FileTest#file?
58
64
  # rio('afile').file? => true or false
59
65
  # Returns +true+ if the named file exists and is a regular file.
60
66
  def file?() target.file? end
67
+
61
68
  # Calls FileTest#socket?
62
69
  # rio('afile').socket? => true or false
63
70
  # Returns +true+ if the named file is a socket.
64
71
  def socket?() target.socket? end
72
+
65
73
  # Calls FileTest#symlink?
66
74
  # rio('afile').symlink? => true or false
67
75
  # Returns +true+ if the named file is a symbolic link.
@@ -214,6 +222,21 @@ module RIO
214
222
  #
215
223
  def absolute?() target.absolute?() end
216
224
 
225
+ # Calls Pathname#mountpoint?
226
+ #
227
+ # Returns +true+ if <tt>self</tt> points to a mountpoint.
228
+ def mountpoint?() target.mountpoint?() end
229
+
230
+ # Calls Pathname#root?
231
+ #
232
+ # #root? is a predicate for root directories. I.e. it returns +true+ if the
233
+ # pathname consists of consecutive slashes.
234
+ #
235
+ # It doesn't access the actual filesystem. So it may return +false+ for some
236
+ # pathnames which points to roots such as <tt>/usr/..</tt>.
237
+ #
238
+ def root?() target.root?() end
217
239
 
240
+
218
241
  end
219
242
  end
@@ -77,6 +77,11 @@ module RIO
77
77
  def self.writable?(s,*args) ::FileTest.writable?(s,*args) end
78
78
  def self.writable_real?(s,*args) ::FileTest.writable_real?(s,*args) end
79
79
  def self.zero?(s,*args) ::FileTest.zero?(s,*args) end
80
+ require 'pathname'
81
+ def self.root?(s) ::Pathname.new(s).root? end
82
+ def self.mountpoint?(s) ::Pathname.new(s).mountpoint? end
83
+ def self.realpath(s) ::Pathname.new(s).realpath end
84
+ def self.cleanpath(s,*args) ::Pathname.new(s).cleanpath(*args) end
80
85
  end
81
86
  end
82
87
  end
@@ -40,9 +40,12 @@ module RIO
40
40
  module Common
41
41
 
42
42
  def ss_type?(keys)
43
- case
44
- when cx['ss_type'].nil? then keys[0]
45
- when cx['ss_type'].in?(keys) then cx['ss_type']
43
+ #p cx,keys
44
+ case cx['ss_type']
45
+ when nil
46
+ keys[0]
47
+ else
48
+ cx['ss_type']
46
49
  end
47
50
  end
48
51
 
@@ -41,7 +41,7 @@ module RIO
41
41
 
42
42
  class Base
43
43
  def initialize(arg)
44
- @select_arg = arg
44
+ @select_arg = arg
45
45
  end
46
46
  def inspect
47
47
  @select_arg.inspect
@@ -55,40 +55,27 @@ module RIO
55
55
  class All < Base
56
56
  def match?(val,recno) true end
57
57
  def match_all?() true end
58
- def =~(record) true end
59
58
  end
60
59
  class None < Base
61
60
  def match?(val,recno) false end
62
61
  def match_none?() true end
63
- def =~(record) false end
64
62
  end
65
63
  class RegExp < Base
66
64
  def match?(val,recno)
67
65
  @select_arg.match(val)
68
66
  end
69
- def =~(record)
70
- @select_arg =~ record
71
- end
72
67
  end
73
68
  class Range < Base
74
69
  def match?(val,recno)
75
70
  #p "match?(#{val},#{recno}) select_arg=#{@select_arg}"
76
71
  @select_arg === recno
77
72
  end
78
- def =~(record)
79
- #p "=~(#{record},#{record.recno}) select_arg=#{@select_arg}"
80
- @select_arg === record.recno
81
- end
82
73
  end
83
74
  class Fixnum < Base
84
75
  def match?(val,recno)
85
76
  #p "match?(#{val},#{recno}) select_arg=#{@select_arg}"
86
77
  @select_arg === recno
87
78
  end
88
- def =~(record)
89
- #p "=~(#{record},#{record.recno}) select_arg=#{@select_arg}"
90
- @select_arg === record.recno
91
- end
92
79
  end
93
80
  class Proc < Base
94
81
  def initialize(arg,therio)
@@ -99,19 +86,46 @@ module RIO
99
86
  #p "match?(#{val},#{recno}) select_arg=#{@select_arg}"
100
87
  @select_arg.call(val,recno,@therio)
101
88
  end
102
- def =~(record)
103
- @select_arg.call(record,record.recno,@therio)
104
- end
105
89
  end
106
90
  class Symbol < Base
107
91
  def match?(val,recno)
108
92
  #p "match?(#{val},#{recno}) select_arg=#{@select_arg}"
109
93
  val.__send__(@select_arg)
110
94
  end
111
- def =~(record)
112
- record.__send__(@select_arg)
95
+ end
96
+ class And < Base
97
+ def initialize(matches,therio)
98
+ list = []
99
+ matches.each do |arg|
100
+ list << Match::Record.create(therio,arg)
101
+ end
102
+ super(list)
103
+ @therio = therio
104
+ end
105
+ def match?(val,recno)
106
+ #p "match?(#{val},#{recno}) select_arg=#{@select_arg}"
107
+ @select_arg.all? { |sel| sel.match?(val,recno) }
108
+ end
109
+ end
110
+ def create(therio,arg)
111
+ case arg
112
+ when ::Regexp
113
+ Match::Record::RegExp.new(arg)
114
+ when ::Range
115
+ Match::Record::Range.new(arg)
116
+ when ::Proc
117
+ Match::Record::Proc.new(arg,therio)
118
+ when ::Symbol
119
+ Match::Record::Symbol.new(arg)
120
+ when ::Fixnum
121
+ Match::Record::Fixnum.new(arg)
122
+ when ::Array
123
+ Match::Record::And.new(arg,therio)
124
+ else
125
+ raise ArgumentError,"Argument must be a Regexp,Range,Fixnum,Proc, or Symbol"
113
126
  end
114
127
  end
128
+ module_function :create
115
129
  end
116
130
  end
117
131
 
@@ -162,20 +176,23 @@ module RIO
162
176
  @list.nil? ? nil : self
163
177
  end
164
178
  def create_sel(therio,arg)
165
- case arg
166
- when ::Regexp
167
- Match::Record::RegExp.new(arg)
168
- when ::Range
169
- Match::Record::Range.new(arg)
170
- when ::Proc
171
- Match::Record::Proc.new(arg,therio)
172
- when ::Symbol
173
- Match::Record::Symbol.new(arg)
174
- when ::Fixnum
175
- Match::Record::Fixnum.new(arg)
176
- else
177
- raise ArgumentError,"Argument must be a Regexp,Range,Fixnum,Proc, or Symbol"
178
- end
179
+ Match::Record.create(therio,arg)
180
+ # case arg
181
+ # when ::Regexp
182
+ # Match::Record::RegExp.new(arg)
183
+ # when ::Range
184
+ # Match::Record::Range.new(arg)
185
+ # when ::Proc
186
+ # Match::Record::Proc.new(arg,therio)
187
+ # when ::Symbol
188
+ # Match::Record::Symbol.new(arg)
189
+ # when ::Fixnum
190
+ # Match::Record::Fixnum.new(arg)
191
+ # when ::Array
192
+ # Match::Record::And.new(arg)
193
+ # else
194
+ # raise ArgumentError,"Argument must be a Regexp,Range,Fixnum,Proc, or Symbol"
195
+ # end
179
196
  end
180
197
  def match?(val,recno)
181
198
  # !@list.nil? && (@list.empty? || @list.detect { |sel| sel.match?(val,recno) } || false) && true
@@ -190,9 +207,6 @@ module RIO
190
207
  return as if al
191
208
  return false
192
209
  end
193
- def =~(el)
194
- !@list.nil? && (@list.empty? || @list.detect { |sel| sel =~ el } || false) && true
195
- end
196
210
  def always?() !@list.nil? && @list.empty? end
197
211
  def never?() @list.nil? end
198
212
  end
@@ -253,16 +267,6 @@ module RIO
253
267
  ok = ((!@sel.nil? && (as = @sel.match?(val,recno))) && !(!@rej.nil? && @rej.match?(val,recno)))
254
268
  return (ok ? as : ok)
255
269
  end
256
- def =~(el)
257
- return @always unless @always.nil?
258
- (!@sel.nil? && (@sel =~ el)) && !(!@rej.nil? && (@rej =~ el))
259
-
260
- #yes = (!@sel.nil? && (@sel =~ el))
261
- #no = (!@rej.nil? && (@rej =~ el))
262
- #p "yes=#{yes} no=#{no} el=#{el}"
263
- #return yes && !no
264
- #(@sel =~ el) && !(@rej =~ el)
265
- end
266
270
  end
267
271
  end
268
272
  end