#--
# ===========================================================================
# Copyright (c) 2005-2017 Christopher Kleckner
# All rights reserved
#
# This file is part of the Rio library for ruby.
#
# Rio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Rio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Rio; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ===========================================================================
#++
#
module RIO
# Rio Constructor
#
# For purposes of discussion, we divide Rios into two catagories, those that have a path
# and those that don't.
#
# ==== Creating a Rio that has a path
#
# To create a Rio that has a path the arguments to +rio+ may be:
#
# * a string representing the entire path. The separator used for Rios is as specified in RFC1738 ('/').
# rio('adir/afile')
# * a string representing a fully qualified +file+ URL as per RFC1738
# rio('file:///atopleveldir/adir/afile')
# * a +URI+ object representing a +file+ or generic +URL+
# rio(URI('adir/afile'))
# * the components of a path as separate arguments
# rio('adir','afile')
# * the components of a path as an array of separate arguments
# rio(%w/adir afile/)
# * another Rio
# another_rio = rio('adir/afile')
# rio(another_rio)
# * any object whose +to_s+ method returns one of the above
# rio(Pathname.new('apath'))
# * any combination of the above either as separate arguments or as elements of an array,
# another_rio = rio('dir1/dir2')
# auri = URI('dir4/dir5)
# rio(another_rio,'dir3',auri,'dir6/dir7')
#
# ===== Creating a Rio that refers to a web page
#
# To create a Rio that refers to a web page the arguments to +rio+ may be:
#
# * a string representing a fully qualified +http+ URL
# rio('http://ruby-doc.org/index.html')
# * a +URI+ object representing a +http+ +URL+
# rio(URI('http://ruby-doc.org/index.html'))
# * either of the above with additional path elements
# rio('http://www.ruby-doc.org/','core','classes/Object.html')
#
# ===== Creating a Rio that refers to a file or directory on a FTP server
#
# To create a Rio that refers to a file on a FTP server the arguments to +rio+ may be:
#
# * a string representing a fully qualified +ftp+ URL
# rio('ftp://user:password@ftp.example.com/afile.tar.gz')
# * a +URI+ object representing a +ftp+ +URL+
# rio(URI('ftp://ftp.example.com/afile.tar.gz'))
# * either of the above with additional path elements
# rio('ftp://ftp.gnu.org/pub/gnu','emacs','windows','README')
#
# ==== Creating Rios that do not have a path
#
# To create a Rio without a path, the first argument to +rio+ is usually
# either a single character or a symbol.
#
# ===== Creating a Rio that refers to a clone of your programs stdin or stdout.
#
# rio(?-) (mnemonic: '-' is used by some Unix programs to specify stdin or stdout in place of a file)
#
# rio(:stdio)
#
# Just as a Rio that refers to a file, does not know whether that file will be opened for reading or
# writing until an I/O operation is specified, a stdio: Rio does not know whether it will connect
# to stdin or stdout until an I/O operation is specified.
#
# Currently :stdin and :stdout are allowed as synonyms for :stdio. This allows one to write
# rio(:stdout).puts("Hello :stdout")
# which is reasonable. It also allows one to write
# rio(:stdin).puts("Hello :stdin")
# which is not reasonable and will be disallowed in future releases.
#
# ===== Creating a Rio that refers to a clone of your programs stderr.
#
# rio(?=) (mnemonic: '-' refers to fileno 1, so '=' refers to fileno 2)
#
# rio(:stderr)
#
# ===== Creating a Rio that refers to an arbitrary IO object.
#
# an_io = ::File.new('afile')
# rio(an_io)
#
# ===== Creating a Rio that refers to a file descriptor
#
# rio(?#,file_descriptor) (mnemonic: a file descriptor is a number '#')
#
# rio(:fd,file_descriptor)
#
# an_io = ::File.new('afile')
# fnum = an_io.fileno
# rio(?#,fnum)
#
# ===== Creating a Rio that refers to a StringIO object
#
# rio(?") (mnemonic: '"' surrounds strings)
#
# rio(:string)
#
# rio(:strio)
#
# rio(:stringio)
#
#
# * create a Rio that refers to a string that it creates
# rio(?")
# * create a Rio that refers to a string of your choosing
# astring = ""
# rio(?",astring)
#
# ===== Creating a Rio that refers to a temporary object
#
# To create a temporary object that will become a file (Tempfile)
# or a temporary directory, depending on how it is used.
#
# rio(??) (mnemonic: '?' you don't know its name)
#
# rio(:temp)
#
# The following are also supported, to specify file or directory
#
# rio(:tempfile)
#
# rio(:tempdir)
#
# rio(??)
# rio(??,basename='rio',tmpdir=Dir::tmpdir)
#
# To create a temporary object that will become a file
# or a directory, depending on how you use it:
# rio(??)
# rio(??,basename='rio',tmpdir=Dir::tmpdir)
#
# To force it to become a file
# rio(??).file
# or just write to it.
#
# To force it to become a directory:
# rio(??).mkdir
# or
# rio(??).chdir
#
#
# ===== Creating a Rio that refers to an arbitrary TCPSocket
#
# rio('tcp:',hostname,port)
#
# rio('tcp://hostname:port')
#
# rio(:tcp,hostname,port)
#
# ===== Creating a Rio that runs an external program and connects to its stdin and stdout
#
# rio(?-,cmd) (mnemonic: '-' is used by some Unix programs to specify stdin or stdout in place of a file)
#
# rio(?`,cmd) (mnemonic: '`' (backtick) runs an external program in ruby)
#
# rio(:cmdio,cmd)
#
# This is Rio's interface to IO#popen
#
# ===== Creating a Rio that acts like /dev/null
#
# rio(nil)
#
# rio(:null)
#
# This rio behaves like the Unix file /dev/null, but does not depend on it -
# and thus will work on non-Unix systems. Reading behaves as if reading from
# an empty file, and writing to it discards anything written.
#
# ===== Creating a Rio Pipe
#
# A Rio Pipe is a sequence of Rios that are run with the output of each being
# copied to the input of the next.
#
# rio(?|, ario, ...) (mnemonic: '|' is the Unix pipe operator)
#
# rio(:cmdpipe, ario, ...)
#
#
# See also IF::Grande#|
#
#
def rio(*args,&block) # :yields: self
Rio.rio(*args,&block)
end
module_function :rio
# Create a Rio as with RIO#rio which refers to the current working directory
# wd = RIO.cwd
# If passed arguments they are treated as if
# rio(RIO.cwd,*args)
# had been called
def cwd(*args,&block) # :yields: self
Rio.new.getwd(*args,&block)
end
module_function :cwd
# Create a Rio as with RIO#rio which refers to a directory at the root of the file system
# tmpdir = RIO.root('tmp') #=> rio('/tmp')
def root(*args,&block) # :yields: self
Rio.new.rootpath(*args,&block)
end
module_function :root
end
if $0 == __FILE__
eval DATA.read, nil, $0, __LINE__+4
end
__END__
puts
puts("Run the tests that came with the distribution")
puts("From the distribution directory use 'test/runtests.rb'")
puts