rio 0.3.8 → 0.3.9

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 (223) hide show
  1. data/README +18 -12
  2. data/Rakefile +57 -87
  3. data/build_doc.rb +19 -17
  4. data/doc/ANNOUNCE +3 -32
  5. data/doc/RELEASE_NOTES +4 -5
  6. data/doc/RIOIS +215 -0
  7. data/doc/generators/template/html/rio.css +428 -0
  8. data/doc/generators/template/html/rio.rb +18 -389
  9. data/doc/generators/template/html/ugly.rb +130 -0
  10. data/doc/pkg_def.rb +66 -0
  11. data/ex/catcsv.rb +64 -0
  12. data/ex/colx.rb +8 -0
  13. data/ex/findinruby +15 -0
  14. data/ex/findruby +14 -0
  15. data/ex/passwd_report.rb +8 -0
  16. data/ex/prompt.rb +25 -0
  17. data/ex/rgb.txt.gz +0 -0
  18. data/ex/riocat +42 -0
  19. data/ex/riogunzip +31 -0
  20. data/ex/riogzip +24 -0
  21. data/ex/rioprompt.rb +10 -0
  22. data/ex/targz2zip +17 -0
  23. data/ex/tonl +10 -0
  24. data/lib/rio.rb +16 -10
  25. data/lib/rio/abstract_method.rb +3 -4
  26. data/lib/rio/argv.rb +3 -4
  27. data/lib/rio/arycopy.rb +3 -4
  28. data/lib/rio/assert.rb +3 -4
  29. data/lib/rio/base.rb +3 -4
  30. data/lib/rio/callstr.rb +3 -4
  31. data/lib/rio/const.rb +3 -4
  32. data/lib/rio/construct.rb +3 -4
  33. data/lib/rio/constructor.rb +12 -8
  34. data/lib/rio/context.rb +15 -30
  35. data/lib/rio/context/autoclose.rb +3 -4
  36. data/lib/rio/context/copying.rb +3 -4
  37. data/lib/rio/context/cxx.rb +3 -4
  38. data/lib/rio/context/dir.rb +3 -4
  39. data/lib/rio/context/gzip.rb +3 -4
  40. data/lib/rio/context/methods.rb +16 -5
  41. data/lib/rio/context/skip.rb +3 -4
  42. data/lib/rio/context/stream.rb +42 -5
  43. data/lib/rio/cp.rb +7 -7
  44. data/lib/rio/def.rb +3 -4
  45. data/lib/rio/dir.rb +3 -4
  46. data/lib/rio/doc.rb +4 -5
  47. data/lib/rio/doc/EXAMPLES.rb +299 -0
  48. data/lib/rio/doc/HOWTO.rb +3 -4
  49. data/lib/rio/doc/INTRO.rb +86 -105
  50. data/lib/rio/doc/OPTIONAL.rb +4 -5
  51. data/lib/rio/doc/SYNOPSIS.rb +7 -6
  52. data/lib/rio/entrysel.rb +21 -23
  53. data/lib/rio/exception.rb +3 -4
  54. data/lib/rio/exception/copy.rb +3 -4
  55. data/lib/rio/exception/notimplemented.rb +57 -0
  56. data/lib/rio/exception/notsupported.rb +3 -4
  57. data/lib/rio/exception/open.rb +3 -4
  58. data/lib/rio/exception/state.rb +3 -4
  59. data/lib/rio/ext.rb +47 -13
  60. data/lib/rio/ext/csv.rb +4 -5
  61. data/lib/rio/ext/if.rb +45 -0
  62. data/lib/rio/ext/mp3info.rb +80 -0
  63. data/lib/rio/ext/splitlines.rb +253 -0
  64. data/lib/rio/ext/yaml.rb +9 -5
  65. data/lib/rio/ext/yaml/doc.rb +133 -0
  66. data/lib/rio/ext/yaml/tie.rb +149 -0
  67. data/lib/rio/ext/zipfile.rb +23 -4
  68. data/lib/rio/ext/zipfile/fs.rb +116 -0
  69. data/lib/rio/ext/zipfile/rl.rb +251 -0
  70. data/lib/rio/ext/zipfile/rootdir.rb +117 -0
  71. data/lib/rio/ext/zipfile/state.rb +161 -0
  72. data/lib/rio/ext/zipfile/wrap.rb +204 -0
  73. data/lib/rio/factory.rb +235 -27
  74. data/lib/rio/file.rb +4 -4
  75. data/lib/rio/filter.rb +3 -4
  76. data/lib/rio/filter/closeoneof.rb +3 -4
  77. data/lib/rio/filter/gzip.rb +9 -4
  78. data/lib/rio/fs/base.rb +3 -4
  79. data/lib/rio/fs/impl.rb +4 -5
  80. data/lib/rio/fs/native.rb +3 -4
  81. data/lib/rio/fs/stream.rb +3 -4
  82. data/lib/rio/fs/url.rb +3 -4
  83. data/lib/rio/ftp/conncache.rb +19 -5
  84. data/lib/rio/ftp/dir.rb +3 -4
  85. data/lib/rio/ftp/fs.rb +30 -24
  86. data/lib/rio/grande.rb +27 -7
  87. data/lib/rio/handle.rb +3 -4
  88. data/lib/rio/if.rb +19 -15
  89. data/lib/rio/if/basic.rb +7 -7
  90. data/lib/rio/if/csv.rb +5 -6
  91. data/lib/rio/if/dir.rb +120 -114
  92. data/lib/rio/if/file.rb +52 -44
  93. data/lib/rio/if/fileordir.rb +217 -211
  94. data/lib/rio/if/grande.rb +674 -644
  95. data/lib/rio/if/grande_entry.rb +321 -313
  96. data/lib/rio/if/grande_stream.rb +653 -553
  97. data/lib/rio/if/internal.rb +3 -4
  98. data/lib/rio/if/path.rb +425 -426
  99. data/lib/rio/if/rubyio.rb +681 -0
  100. data/lib/rio/if/string.rb +42 -5
  101. data/lib/rio/if/temp.rb +3 -4
  102. data/lib/rio/if/test.rb +245 -238
  103. data/lib/rio/if/yaml.rb +15 -41
  104. data/lib/rio/ioh.rb +7 -5
  105. data/lib/rio/iomode.rb +19 -7
  106. data/lib/rio/ios/fail.rb +4 -5
  107. data/lib/rio/ios/generic.rb +4 -5
  108. data/lib/rio/ios/mode.rb +4 -5
  109. data/lib/rio/ios/null.rb +6 -7
  110. data/lib/rio/iowrap.rb +3 -4
  111. data/lib/rio/kernel.rb +3 -5
  112. data/lib/rio/local.rb +3 -4
  113. data/lib/rio/match.rb +3 -4
  114. data/lib/rio/matchrecord.rb +3 -4
  115. data/lib/rio/no_warn.rb +3 -4
  116. data/lib/rio/nullio.rb +3 -4
  117. data/lib/rio/open3.rb +4 -5
  118. data/lib/rio/ops/construct.rb +3 -4
  119. data/lib/rio/ops/create.rb +11 -6
  120. data/lib/rio/ops/dir.rb +19 -8
  121. data/lib/rio/ops/either.rb +6 -5
  122. data/lib/rio/ops/file.rb +3 -4
  123. data/lib/rio/ops/path.rb +14 -35
  124. data/lib/rio/ops/stream.rb +3 -4
  125. data/lib/rio/ops/stream/input.rb +4 -7
  126. data/lib/rio/ops/stream/output.rb +3 -4
  127. data/lib/rio/ops/stream/read.rb +6 -5
  128. data/lib/rio/ops/stream/write.rb +3 -4
  129. data/lib/rio/ops/symlink.rb +3 -4
  130. data/lib/rio/path.rb +22 -18
  131. data/lib/rio/path/reset.rb +4 -5
  132. data/lib/rio/piper.rb +3 -4
  133. data/lib/rio/piper/cp.rb +3 -4
  134. data/lib/rio/prompt.rb +10 -5
  135. data/lib/rio/rectype.rb +5 -5
  136. data/lib/rio/rl/base.rb +17 -71
  137. data/lib/rio/rl/builder.rb +14 -38
  138. data/lib/rio/rl/chmap.rb +66 -0
  139. data/lib/rio/rl/fs2url.rb +82 -0
  140. data/lib/rio/rl/ioi.rb +4 -4
  141. data/lib/rio/rl/path.rb +44 -122
  142. data/lib/rio/rl/pathmethods.rb +19 -8
  143. data/lib/rio/rl/uri.rb +137 -60
  144. data/lib/rio/rl/withpath.rb +295 -0
  145. data/lib/rio/scheme/aryio.rb +3 -4
  146. data/lib/rio/scheme/cmdio.rb +3 -4
  147. data/lib/rio/scheme/cmdpipe.rb +4 -4
  148. data/lib/rio/scheme/fd.rb +3 -4
  149. data/lib/rio/scheme/ftp.rb +7 -7
  150. data/lib/rio/scheme/http.rb +4 -5
  151. data/lib/rio/scheme/null.rb +3 -4
  152. data/lib/rio/scheme/path.rb +3 -4
  153. data/lib/rio/scheme/stderr.rb +3 -4
  154. data/lib/rio/scheme/stdio.rb +3 -4
  155. data/lib/rio/scheme/strio.rb +3 -4
  156. data/lib/rio/scheme/sysio.rb +3 -4
  157. data/lib/rio/scheme/tcp.rb +3 -4
  158. data/lib/rio/scheme/temp.rb +6 -6
  159. data/lib/rio/state.rb +18 -46
  160. data/lib/rio/state/error.rb +3 -4
  161. data/lib/rio/stream.rb +4 -4
  162. data/lib/rio/stream/base.rb +3 -4
  163. data/lib/rio/stream/duplex.rb +3 -4
  164. data/lib/rio/stream/open.rb +3 -8
  165. data/lib/rio/symantics.rb +3 -4
  166. data/lib/rio/tempdir.rb +2 -2
  167. data/lib/rio/to_rio.rb +3 -4
  168. data/lib/rio/to_rio/all.rb +3 -4
  169. data/lib/rio/to_rio/array.rb +4 -5
  170. data/lib/rio/to_rio/io.rb +4 -5
  171. data/lib/rio/to_rio/object.rb +4 -5
  172. data/lib/rio/to_rio/string.rb +4 -5
  173. data/lib/rio/uri/file.rb +41 -5
  174. data/lib/rio/util.rb +3 -4
  175. data/lib/rio/version.rb +4 -5
  176. data/setup.rb +368 -339
  177. data/test/bin/list_dir.rb +1 -1
  178. data/test/ftp/anon_misc.rb +13 -1
  179. data/test/ftp/anon_special.rb +6 -6
  180. data/test/ftp/anon_write.rb +10 -3
  181. data/test/ftp/ftp2ftp.rb +2 -2
  182. data/test/ftp/testdef.rb +9 -6
  183. data/test/http/all.rb +3 -0
  184. data/test/http/copy-from-http.rb +140 -0
  185. data/test/lib/temp_server.rb +44 -0
  186. data/test/runalltests.rb +3 -1
  187. data/test/runhttp.rb +12 -0
  188. data/test/runhttptests.rb +1 -1
  189. data/test/runtests.rb +41 -3
  190. data/test/tc/abs.rb +9 -5
  191. data/test/tc/all.rb +9 -4
  192. data/test/tc/base.rb +1 -1
  193. data/test/tc/base2.rb +87 -0
  194. data/test/tc/{methods.rb → clone.rb} +72 -50
  195. data/test/tc/closeoncopy.rb +13 -2
  196. data/test/tc/copy-dir-samevar.rb +91 -0
  197. data/test/tc/dir_iter.rb +0 -1
  198. data/test/tc/empty.rb +6 -2
  199. data/test/tc/expand_path.rb +36 -54
  200. data/test/tc/ext.rb +42 -18
  201. data/test/tc/gzip.rb +30 -3
  202. data/test/tc/likeio.rb +5 -1
  203. data/test/tc/line_record_row.rb +51 -0
  204. data/test/tc/noqae.rb +71 -70
  205. data/test/tc/path_parts.rb +175 -0
  206. data/test/tc/programs_util.rb +3 -3
  207. data/test/tc/rename.rb +4 -5
  208. data/test/tc/riorl.rb +9 -7
  209. data/test/tc/skip.rb +35 -6
  210. data/test/tc/skiplines.rb +34 -5
  211. data/test/tc/split.rb +8 -50
  212. data/test/tc/splitlines.rb +65 -0
  213. data/test/tc/splitpath.rb +83 -0
  214. data/test/tc/testcase.rb +1 -1
  215. data/test/tc/truncate.rb +39 -0
  216. data/test/tc/yaml.rb +9 -8
  217. metadata +261 -207
  218. data/ChangeLog +0 -1418
  219. data/VERSION +0 -1
  220. data/lib/rio/doc/MISC.rb +0 -259
  221. data/lib/rio/if/stream.rb +0 -680
  222. data/lib/rio/impl/path.rb +0 -87
  223. data/test/tc/copy-from-http.rb +0 -89
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # ===============================================================================
3
- # Copyright (c) 2005, 2006 Christopher Kleckner
3
+ # Copyright (c) 2005,2006,2007 Christopher Kleckner
4
4
  # All rights reserved
5
5
  #
6
6
  # This file is part of the Rio library for ruby.
@@ -23,16 +23,15 @@
23
23
  #
24
24
  # To create the documentation for Rio run the command
25
25
  # ruby build_doc.rb
26
- # from the distribution directory. Then point your browser at the 'doc/rdoc' directory.
26
+ # from the distribution directory.
27
27
  #
28
28
  # Suggested Reading
29
29
  # * RIO::Doc::SYNOPSIS
30
30
  # * RIO::Doc::INTRO
31
31
  # * RIO::Doc::HOWTO
32
+ # * RIO::Doc::EXAMPLES
32
33
  # * RIO::Rio
33
34
  #
34
- # <b>Rio is pre-alpha software.
35
- # The documented interface and behavior is subject to change without notice.</b>
36
35
 
37
36
 
38
37
  require 'rio/rl/uri'
@@ -45,6 +44,10 @@ module RIO
45
44
  cp.urlpath = self.pathroot
46
45
  cp.url
47
46
  end
47
+ def pathdepth()
48
+ pth = self.path_no_slash
49
+ (pth == '/' ? 0 : pth.count('/'))
50
+ end
48
51
  def _parts()
49
52
  pr = self.pathroot
50
53
  ur = self.urlroot.sub(/#{pr}$/,'')
@@ -52,10 +55,6 @@ module RIO
52
55
 
53
56
  [ur,pr,up]
54
57
  end
55
- def pathdepth()
56
- pth = self.path_no_slash
57
- (pth == '/' ? 0 : pth.count('/'))
58
- end
59
58
  def split()
60
59
  if absolute?
61
60
  parts = self._parts
@@ -94,6 +93,18 @@ module RIO
94
93
  def merge(other)
95
94
  self.class.new(uri.merge(other.uri))
96
95
  end
96
+ def calc_abs_uri_(path_str,base_str)
97
+ #p path_str,base_str
98
+ path = URI(path_str)
99
+ return path unless base_str
100
+ if path_str[0,1] != '/' and base_str[0,1] == '/'
101
+ abs_str = [base_str,path_str].join('/').squeeze('/')
102
+ return URI(abs_str)
103
+ end
104
+ base = URI(base_str)
105
+ abs = base.merge(path)
106
+ return abs
107
+ end
97
108
 
98
109
  def dirname()
99
110
  ::File.dirname(self.path_no_slash)
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # ===============================================================================
3
- # Copyright (c) 2005, 2006 Christopher Kleckner
3
+ # Copyright (c) 2005,2006,2007 Christopher Kleckner
4
4
  # All rights reserved
5
5
  #
6
6
  # This file is part of the Rio library for ruby.
@@ -23,97 +23,174 @@
23
23
  #
24
24
  # To create the documentation for Rio run the command
25
25
  # ruby build_doc.rb
26
- # from the distribution directory. Then point your browser at the 'doc/rdoc' directory.
26
+ # from the distribution directory.
27
27
  #
28
28
  # Suggested Reading
29
29
  # * RIO::Doc::SYNOPSIS
30
30
  # * RIO::Doc::INTRO
31
31
  # * RIO::Doc::HOWTO
32
+ # * RIO::Doc::EXAMPLES
32
33
  # * RIO::Rio
33
34
  #
34
- # <b>Rio is pre-alpha software.
35
- # The documented interface and behavior is subject to change without notice.</b>
36
35
 
37
36
 
38
37
  require 'rio/rl/base'
38
+ require 'rio/rl/withpath'
39
39
  require 'rio/fs/url'
40
+ require 'rio/fs/native'
41
+ require 'rio/uri/file'
40
42
 
41
43
  module RIO
42
44
  module RL
43
- class URIBase < Base
45
+ class URIBase < WithPath
44
46
  SCHEME = URI::REGEXP::PATTERN::SCHEME
45
- attr_reader :uri
46
- #attr :fs
47
+ HOST = URI::REGEXP::PATTERN::HOST
48
+
49
+ attr_accessor :uri
47
50
  def initialize(u,*args)
48
- #p callstr('initialize',u,*args)
49
51
  # u should be a ::URI or something that can be parsed to one
52
+ #p callstr('initialize',u,*args)
53
+ @base = nil
54
+ @fs = nil
50
55
  args = _get_opts_from_args(args)
51
- @uri = _mkuri(u)
52
- self.join(*args)
53
- @uri.path = '/' if @uri.absolute? and @uri.path == ''
54
- #@fs = self.openfs_
56
+ init_from_args_(u,*args)
55
57
  super
58
+ unless self.absolute? or @base
59
+ @base = ::URI::parse('file://'+RL.fs2url(fs.getwd)+'/')
60
+ end
61
+ @uri.path = '/' if @uri.absolute? and @uri.path == ''
56
62
  end
57
- def openfs_()
58
- RIO::FS::URL.create()
63
+ def arg0_info_(arg0,*args)
64
+ #p "arg0_info_(#{arg0.inspect},#{args.inspect})"
65
+ vuri,vbase,vfs = nil,nil,nil
66
+ case arg0
67
+ when RIO::Rio
68
+ return _init_from_arg(arg0.rl)
69
+ when URIBase
70
+ vuri,vbase,vfs = arg0.uri,arg0.base,arg0.fs
71
+ when ::URI
72
+ vuri = arg0
73
+ when ::String
74
+ vuri = uri_from_string_(arg0) || ::URI.parse(arg0)
75
+ else
76
+ raise(ArgumentError,"'#{arg0}'[#{arg0.class}] can not be used to create a Rio")
77
+ end
78
+ [vuri,vbase,vfs]
79
+ end
80
+ def init_from_args_(arg0,*args)
81
+ #p "init_from_args_(#{arg0.inspect})"
82
+ #p callstr('init_from_args_',arg0.inspect,args)
83
+ vuri,vbase,vfs = self.arg0_info_(arg0,*args)
84
+ #p vuri
85
+ @uri = vuri
86
+ #p args unless args.nil? || args.empty?
87
+ self.join(*args)
88
+ @base = vbase unless @base or vbase.nil?
89
+ fs = vfs if vfs
90
+ end
91
+ def _get_base_from_arg(arg)
92
+ #p "_get_base: #{arg.inspect}"
93
+ case arg
94
+ when RIO::Rio
95
+ arg.abs.to_uri
96
+ when URIBase
97
+ arg.abs.uri
98
+ when ::URI
99
+ arg if arg.absolute?
100
+ when ::String
101
+ uri_from_string_(arg) || ::URI.parse([RL.fs2url(::Dir.getwd+'/'),arg].join('/').squeeze('/'))
102
+ else
103
+ raise(ArgumentError,"'#{arg}' is not a valid base path")
104
+ end
105
+ end
106
+ def _get_opts_from_args(args)
107
+ if !args.empty? and args[-1].kind_of?(::Hash)
108
+ opts = args.pop
109
+ if b = opts[:base]
110
+ @base = _get_base_from_arg(b)
111
+ #@base.path.sub!(%r{/*$},'/')
112
+ end
113
+ if fs = opts[:fs]
114
+ @fs = fs
115
+ end
116
+ end
117
+ args
59
118
  end
60
119
  def initialize_copy(*args)
61
120
  super
62
121
  @uri = @uri.clone unless @uri.nil?
63
122
  @base = @base.clone unless @base.nil?
64
123
  end
65
- def _get_opts_from_args(args)
66
- # args.each { |a| p "get_base len=#{args.length} #{a.class}##{a.to_s}" }
67
- @base = nil
68
- if !args.empty? and args[-1].kind_of?(::Hash) and (b = args.pop[:base])
69
- @base = case b
70
- when URIBase then b.uri if b.uri.absolute?
71
- when ::URI then b if b.absolute?
72
- when ::String then ::URI.parse(b) if b =~ /^#{SCHEME}:/
73
- end
124
+ def absolute?()
125
+ uri.absolute?
126
+ end
127
+ alias :abs? :absolute?
128
+ def openfs_()
129
+ #p callstr('openfs_')
130
+ @fs || RIO::FS::Native.create()
131
+ end
132
+ def url()
133
+ self.uri.to_s
134
+ end
135
+ def to_s()
136
+ self.url
137
+ end
138
+ def urlpath() uri.path end
139
+ def urlpath=(arg)
140
+ #p uri,arg
141
+ uri.path = arg
142
+ end
143
+ def path()
144
+ case scheme
145
+ when 'file','path' then fspath()
146
+ else urlpath()
74
147
  end
75
- args
76
148
  end
77
- def pathroot() '/' end
78
- def _mkuri(arg)
79
- (arg.kind_of?(::URI) ? arg.dup : parse_url(arg.to_s))
149
+ def path=(pth)
150
+ case scheme
151
+ when 'file','path' then self.fspath = pth
152
+ else self.urlpath = pth
153
+ end
80
154
  end
81
- def base(arg=nil)
82
- self.base = arg unless arg.nil? or @uri.absolute?
83
- @base || @uri
155
+ def scheme() uri.scheme end
156
+ def host() uri.host end
157
+ def host=(arg) uri.host = arg end
158
+ def opaque()
159
+ u = uri.clone
160
+ u.query = nil
161
+ u.to_s.sub(/^#{SCHEME}:/,'')
84
162
  end
85
- def base=(arg) @base = _mkuri(arg) end
86
- require 'rio/rl/pathmethods'
87
- include PathMethods
88
-
89
- def urlpath=(pt) @uri.path = pt end
90
- def urlpath() @uri.path end
91
-
92
- def path=(pt) self.urlpath = pt end
93
- def path() self.urlpath end
94
- def path_no_slash() self.path.sub(/\/$/,'') end
95
-
96
- def opaque()
97
- u = @uri.dup
98
- u.scheme = nil
99
- u.to_s
163
+ def pathroot()
164
+ u = uri.clone
165
+ u.query = nil
166
+ case scheme
167
+ when 'file'
168
+ if self.urlpath =~ %r%^(/[a-zA-Z]):% then $1+':/'
169
+ else '/'
170
+ end
171
+ else
172
+ u.path = '/'
173
+ u.to_s
174
+ end
100
175
  end
101
-
102
- def scheme() @uri.scheme end
103
- def host() @uri.host end
104
- def host=(arg) @uri.host = arg end
105
-
106
- def absolute?() @uri.absolute? end
107
- alias abs? absolute?
108
-
109
- def abs()
110
- return self if absolute?
111
- self.class.new(@base.merge(@uri),{:base => @base})
176
+ def urlroot()
177
+ return nil unless absolute?
178
+ cp = self.clone
179
+ cp.urlpath = self.pathroot
180
+ cp.url
181
+ end
182
+ def base()
183
+ @base || self.uri
184
+ end
185
+ def base=(arg)
186
+ #p "uri.rb:base= arg=#{arg.inspect}"
187
+ @base = _uri(arg)
188
+ end
189
+ def join(*args)
190
+ return self if args.empty?
191
+ join_(args.map{ |arg| arg.to_s})
112
192
  end
113
-
114
- def url() @uri.to_s end
115
- def to_s() self.url end
116
-
117
193
  end
118
194
  end
119
195
  end
196
+
@@ -0,0 +1,295 @@
1
+ #--
2
+ # ===============================================================================
3
+ # Copyright (c) 2005,2006,2007 Christopher Kleckner
4
+ # All rights reserved
5
+ #
6
+ # This file is part of the Rio library for ruby.
7
+ #
8
+ # Rio is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Rio is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Rio; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ # ===============================================================================
22
+ #++
23
+ #
24
+ # To create the documentation for Rio run the command
25
+ # ruby build_doc.rb
26
+ # from the distribution directory.
27
+ #
28
+ # Suggested Reading
29
+ # * RIO::Doc::SYNOPSIS
30
+ # * RIO::Doc::INTRO
31
+ # * RIO::Doc::HOWTO
32
+ # * RIO::Doc::EXAMPLES
33
+ # * RIO::Rio
34
+ #
35
+
36
+
37
+ require 'rio/rl/base'
38
+ require 'rio/exception/notimplemented'
39
+ require 'rio/rl/builder'
40
+
41
+ module RIO
42
+ module RL
43
+ module PathUtil
44
+ end
45
+ end
46
+ end
47
+ #
48
+
49
+ module RIO
50
+ module RL
51
+ class WithPath < RIO::RL::Base
52
+ include RIO::RL::PathUtil
53
+ include RIO::Error::NotImplemented
54
+
55
+ # returns an appriate FS object for the scheme
56
+ def openfs_() nodef() end
57
+
58
+ # returns the path portion of a URL. All spaces would be %20
59
+ # returns a String
60
+ def urlpath() nodef() end
61
+ def urlpath=(arg) nodef(arg) end
62
+
63
+ # For RLs that are on the file system this is fspath()
64
+ # For RLs that are remote (http,ftp) this is urlpath()
65
+ # For RLs that have no path this is nil
66
+ # returns a String
67
+ def path() nodef{} end
68
+ def path=(arg) nodef(arg) end
69
+
70
+ # returns A URI object representation of the RL if one exists
71
+ # otherwise it returns nil
72
+ # returns a URI
73
+ def uri() nodef() end
74
+
75
+ # when the URL is legal it is the URI scheme
76
+ # otherwise it is one of Rio's schemes
77
+ # returns a String
78
+ def scheme() nodef() end
79
+
80
+ # returns the host portion of the URI if their is one
81
+ # otherwise it returns nil
82
+ # returns a String
83
+ def host() nodef() end
84
+ def host=(arg) nodef(arg) end
85
+
86
+ # returns the portion of the URL starting after the colon
87
+ # following the scheme, and ending before the query portion
88
+ # of the URL
89
+ # returns a String
90
+ def opaque() nodef() end
91
+
92
+ # returns the portion of the path that when prepended to the
93
+ # path would make it usable.
94
+ # For paths on the file system this would be '/'
95
+ # For http and ftp paths it would be http://host/
96
+ # For zipfile paths it would be ''
97
+ # For windows paths with a drive it would be 'C:/'
98
+ # For windows UNC paths it would be '//host/'
99
+ # returns a String
100
+ def pathroot() nodef() end
101
+
102
+
103
+ # returns the base of a path.
104
+ # merging the value returned with this yields the absolute path
105
+ def base(thebase=nil) nodef(thebase) end
106
+
107
+ end
108
+ end
109
+ end
110
+
111
+ module RIO
112
+ module RL
113
+ class WithPath < RIO::RL::Base
114
+ SCHEME = URI::REGEXP::PATTERN::SCHEME
115
+ HOST = URI::REGEXP::PATTERN::HOST
116
+
117
+ # returns the path as the file system sees it. Spaces are spaces and not
118
+ # %20 etc. This is the path that would be passed to the fs object.
119
+ # For windows RLs this includes the '//host' part and the 'C:' part
120
+ # returns a String
121
+ def fspath()
122
+ RL.url2fs(self.urlpath)
123
+ end
124
+
125
+ def fspath=(fpth)
126
+ #p "FSPATH= #{fpth} => #{RL.fs2url(fpth)}"
127
+ case fpth
128
+ when %r{^//(#{HOST})(/.*)?$}
129
+ self.host = $1
130
+ self.urlpath = RL.fs2url($2||'')
131
+ else
132
+ self.urlpath = RL.fs2url(fpth)
133
+ end
134
+ end
135
+ def is_root?(upth)
136
+ upth =~ %r%^(/?[a-zA-Z]:)?/% or upth =~ %r%^//(#{HOST})%
137
+ end
138
+
139
+ # The value of urlpath() with any trailing slash removed
140
+ # returns a String
141
+ def path_no_slash()
142
+ pth = self.urlpath
143
+ #p "path_no_slash: #{is_root?(pth)} #{pth}"
144
+ is_root?(pth) ? pth : pth.sub(/\/$/,'')
145
+ end
146
+ # The value of fspath() with any trailing slash removed
147
+ # returns a String
148
+ def fspath_no_slash()
149
+ pth = self.fspath
150
+ #p "path_no_slash: #{is_root?(pth)} #{pth}"
151
+ is_root?(pth) ? pth : pth.sub(/\/$/,'')
152
+ end
153
+ def pathdepth()
154
+ pth = self.path_no_slash
155
+ is_root?(pth) ? 0 : pth.count('/')
156
+ end
157
+
158
+ def _uri(arg)
159
+ arg.kind_of?(::URI) ? arg.clone : ::URI.parse(arg.to_s)
160
+ end
161
+ # returns the absolute path. combines the urlpath with the
162
+ # argument, or the value returned by base() to create an
163
+ # absolute path.
164
+ # returns a RL
165
+ def abs(thebase=nil)
166
+ thebase ||= self.base
167
+ base_uri = _uri(thebase)
168
+ path_uri = self.uri.clone
169
+ #p "abs: base_uri=#{base_uri.inspect}"
170
+ #p "abs: path_uri=#{path_uri.inspect}"
171
+ if path_uri.scheme == 'file' and base_uri.scheme != 'file'
172
+ abs_uri = base_uri.merge(path_uri.path)
173
+ else
174
+ abs_uri = base_uri.merge(path_uri)
175
+ end
176
+ #p "abs: abs_uri=#{abs_uri.inspect}"
177
+ _build(abs_uri,{:fs => self.fs})
178
+ end
179
+
180
+
181
+ # returns an array of parts of a RL.
182
+ # 'a/b/c' => ['a','b','c']
183
+ # For absolute paths the first component is the pathroot
184
+ # '/topdir/dir/file' => ['/','topdir','dir','file']
185
+ # 'http://host/dir/file' => ['http://host/','dir','file']
186
+ # '//host/a/b' => ['file://host/','a','b']
187
+ # each element of the array is an RL whose base is
188
+ # set such that the correct absolute path would be returned
189
+ # returns an array of RLs
190
+ def _parts()
191
+ pr = self.pathroot
192
+ ur = self.urlroot.sub(/#{pr}$/,'')
193
+ up = self.urlpath.sub(/^#{pr}/,'')
194
+
195
+ [ur,pr,up]
196
+ end
197
+ def split()
198
+ if absolute?
199
+ parts = self._parts
200
+ sparts = []
201
+ sparts << parts[0] + parts[1]
202
+ sparts += parts[2].split('/')
203
+ else
204
+ sparts = self.urlpath.split('/')
205
+ end
206
+ rlparts = sparts.map { |str| self.class.new(str) }
207
+ (1...sparts.length).each { |i|
208
+ base_str = rlparts[i-1].abs.url
209
+ base_str += '/' unless base_str[-1] == ?/
210
+ rlparts[i].base = base_str
211
+ }
212
+ rlparts
213
+
214
+ end
215
+
216
+ # changes this RLs path so that is consists of this RL's path
217
+ # combined with those of its arguments.
218
+ def join(*args)
219
+ return self if args.empty?
220
+ #sa = args.map { |arg| ::URI.escape(arg.to_s,ESCAPE) }
221
+ sa = args.map { |arg| arg.to_s }
222
+ join_(sa)
223
+ end
224
+ def join_(sa)
225
+ sa.unshift(self.urlpath) unless self.urlpath.empty?
226
+ self.urlpath = sa.join('/').squeeze('/')
227
+ self
228
+ end
229
+ protected :join_
230
+
231
+ # returns the directory portion of the path
232
+ # like File#dirname
233
+ # returns a RL
234
+ def dirname()
235
+ new_rl = self.clone
236
+ #p "dirname: fspath_no_slash(#{self.fspath_no_slash} dn(#{fs.dirname(self.fspath_no_slash)})"
237
+ pth = self.fspath_no_slash
238
+ if pth =~ %r{^//(#{HOST})(/.*)}
239
+ new_rl.fspath = "//#{$1}#{fs.dirname($2)}"
240
+ else
241
+ new_rl.fspath = fs.dirname(pth)
242
+ end
243
+ new_rl
244
+ end
245
+
246
+ # returns the tail portion of the path minus the extension
247
+ # returns a RL
248
+ def basename(ext)
249
+ #p callstr('basename',ext)
250
+ base_rl = self.abs
251
+ base_rl.fspath = fs.dirname(base_rl.fspath_no_slash)
252
+ path_str = fs.basename(self.fspath_no_slash,ext)
253
+ _build(path_str,{:base => base_rl.uri, :fs => self.fs})
254
+ end
255
+ def build_arg0_(path_str)
256
+ path_str
257
+ end
258
+
259
+ # returns the tail portion of the path
260
+ # returns a RL
261
+ def filename()
262
+ basename('')
263
+ end
264
+
265
+
266
+ # calls URI#merge
267
+ # returns a RL
268
+ def merge(other) _build(self.uri.merge(other.uri)) end
269
+
270
+ # calls URI#route_from
271
+ # returns a RL
272
+ def route_from(other) _build(self.uri.route_from(other.uri),{:base => other.uri}) end
273
+
274
+ # calls URI#route_to
275
+ # returns a RL
276
+ def route_to(other) _build(self.uri.route_to(other.uri),{:base => self.uri}) end
277
+
278
+ def _build(*args) RIO::RL::Builder.build(*args) end
279
+
280
+ def uri_from_string_(str)
281
+ case str
282
+ when %r%^file://(#{HOST})?(/.*)?$% then ::URI.parse(str)
283
+ when %r/^[a-zA-Z]:/ then
284
+ ::URI.parse(str)
285
+ when %r/^#{SCHEME}:/ then ::URI.parse(str)
286
+ #when %r{^/} then ::URI.parse('file://'+str+( ( str[-1,0] == '/' ) ? "" : "/"))
287
+ when %r{^/} then ::URI.parse('file://'+RL.fs2url(str))
288
+ else ::URI.parse(str)
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end
294
+
295
+