module Folio require 'folio/xdg' require 'folio/filetest' require 'folio/fileutils' require 'folio/ziputils' require 'folio/multiglob' # = Prompt class # # A Folio Shell object provides a limited file system shell in code. # class Shell # New Shell object. def initialize(*path) opts = (Hash===path.last ? path.pop : {}) mode(opts) if path.empty? path = Dir.pwd else path = File.join(*path) end raise FileNotFound, "#{path}" unless ::File.exist?(path) raise FileNotFound, "#{path}" unless ::File.directory?(path) @work = dir(path) end # Opertaton mode. This can be :noop, :verbose or :dryrun. # The later is the same as the first two combined. def mode(opts=nil) return @mode unless opts opts.each do |key, val| next unless val case key when :noop @mode = (@mode == :verbose ? :dryrun : :noop) when :verbose @mode = (@mode == :noop ? :dryrun : :verbose) when :dryrun @mode = :dryrun end end end # String representation is work directory path. def to_s ; work.to_s ; end # Present working directory as a Directory object. attr :work # Home location. def home ; dir('~') ; end # Root location. def root ; dir('/') ; end # Return a new prompt with the same location. # NOTE: Use #dup or #clone ? #def new ; Prompt.new(work) ; end # Get the FileObject for the given file name. # # TODO: Should there be methods like this for each # type, and raise an error if not the right type? # # def [](name) FileObject[name] end def file(name) FileObject[name] end def pathname(name) Pathname.new(name) end def doc(name) Document.new(name) end def dir(name) Directory.new(name) end # Join paths. def +(fname) @work =+ fname end alias_method '/', '+' # Lists all entries. def entries work.entries end alias_method :ls, :entries # Lists directory entries. def directory_entries work.directory_entries end # Lists directory entries. def document_entries work.document_entries end # Returns Enumerator of files objects. def files ; work.files ; end # Returns Enumerator of directories. def documents ; work.documents ; end # Returns Enumerator of documents. def directories ; work.directories ; end # Glob pattern. Returns matches as strings. def glob(*patterns, &block) opts = (::Integer===patterns.last ? patterns.pop : 0) patterns = localize(patterns) matches = patterns.map{ |pattern| ::Dir.glob(pattern, opts) }.flatten if block_given? matches.each(&block) end end # TODO: Ultimately merge #glob and #multiglob. def multiglob(*a) Dir.multiglob(*a) end def multiglob_r(*a) Dir.multiglob_r(*a) end # Match pattern. Like #glob but returns file objects. def match(*patterns, &block) opts = (::Integer===patterns.last ? patterns.pop : 0) patterns = localize(patterns) matches = patterns.map{ |pattern| ::Dir.glob(pattern, opts) }.flatten matches = matches.map{ |f| FileObject[f] } if block_given? matches.each(&block) end end # Chage working directory. def cd(dir, &block) if block Dir.chdir(localize(dir), &block) else @work += dir end end alias_method :chdir, :cd ############# # FileTest # ############# # def size(path) ; FileTest.size(localize(path)) ; end def size?(path) ; FileTest.size(localize(path)) ; end def directory?(path) ; FileTest.directory?(localize(path)) ; end def symlink?(path) ; FileTest.symlink?(localize(path)) ; end def readable?(path) ; FileTest.readable?(localize(path)) ; end def size?(path) ; FileTest.size?(localize(path)) ; end def chardev?(path) ; FileTest.chardev?(localize(path)) ; end def exist?(path) ; FileTest.exist?(localize(path)) ; end def exists?(path) ; FileTest.exists?(localize(path)) ; end def zero?(path) ; FileTest.zero?(localize(path)) ; end def pipe?(path) ; FileTest.pipe?(localize(path)) ; end def file?(path) ; FileTest.file?(localize(path)) ; end def sticky?(path) ; FileTest.sticky?(localize(path)) ; end def blockdev?(path) ; FileTest.blockdev?(localize(path)) ; end def grpowned?(path) ; FileTest.grpowned?(localize(path)) ; end def setgid?(path) ; FileTest.setgid?(localize(path)) ; end def setuid?(path) ; FileTest.setuid?(localize(path)) ; end def socket?(path) ; FileTest.socket?(localize(path)) ; end def directory?(path) ; FileTest.directory?(localize(path)) ; end def owned?(path) ; FileTest.owned?(localize(path)) ; end def identical?(path) ; FileTest.identical?(localize(path)) ; end def writable?(path) ; FileTest.writable?(localize(path)) ; end def executable?(path) ; FileTest.executable?(localize(path)) ; end def writable_real?(path) ; FileTest.writable_real?(localize(path)) ; end def executable_real?(path) ; FileTest.executable_real?(localize(path)) ; end def readable_real?(path) ; FileTest.readable_real?(localize(path)) ; end def safe?(path) ; FileTest.safe?(localize(path)) ; end # TODO: Is #out_of_date? this the same as #uptodate? def out_of_date?(path, *sources) FileTest.out_of_date?(localize(path), *localize(sources)) end def relative?(path) ; FileTest.relative?(path) ; end def absolute?(path) ; FileTest.absolute?(path) ; end ############# # FileUtils # ############# # Low-level Methods Omitted # ------------------------- # getwd -> pwd # compare_file -> cmp # remove_file -> rm # copy_file -> cp # remove_dir -> rmdir # safe_unlink -> rm_f # makedirs -> mkdir_p # rmtree -> rm_rf # copy_stream # remove_entry # copy_entry # remove_entry_secure # compare_stream # Present working directory. def pwd work.to_s end # Same as identical? def cmp(a,b) fileutils.cmp(a,b) end # def uptodate?(new, old_list, options=nil) new = localize(new) old = localize(old_list) fileutils.uptodate?(new, old, options) end # def mkdir(dir, options={}) dir = localize(dir) fileutils.mkdir(dir, options) end def mkdir_p(dir, options={}) dir = localize(dir) fileutils.mkdir_p(dir, options) end alias_method :mkpath, :mkdir_p def rmdir(dir, options={}) dir = localize(dir) fileutils.rmdir(dir, options) end # ln(list, destdir, options={}) def ln(old, new, options={}) old = localize(old) new = localize(new) fileutils.ln(old, new, options) end alias_method :link, :ln # ln_s(list, destdir, options={}) def ln_s(old, new, options={}) old = localize(old) new = localize(new) fileutils.ln_s(old, new, options) end alias_method :symlink, :ln_s def ln_sf(old, new, options={}) old = localize(old) new = localize(new) fileutils.ln_sf(old, new, options) end # cp(list, dir, options={}) def cp(src, dest, options={}) src = localize(src) dest = localize(dest) fileutils.cp(src, dest, options) end alias_method :copy, :cp # cp_r(list, dir, options={}) def cp_r(src, dest, options={}) src = localize(src) dest = localize(dest) fileutils.cp_r(src, dest, options) end # mv(list, dir, options={}) def mv(src, dest, options={}) src = localize(src) dest = localize(dest) fileutils.mv(src, dest, options) end alias_method :move, :mv def rm(list, options={}) list = localize(list) fileutils.rm(list, options) end alias_method :remove, :rm def rm_r(list, options={}) list = localize(list) fileutils.rm_r(list, options) end def rm_f(list, options={}) list = localize(list) fileutils.rm_f(list, options) end def rm_rf(list, options={}) list = localize(list) fileutils.rm_rf(list, options) end def install(src, dest, mode, options={}) src = localize(src) dest = localize(dest) fileutils.install(src, dest, mode, options) end def chmod(mode, list, options={}) list = localize(list) fileutils.chmod(mode, list, options) end def chmod_r(mode, list, options={}) list = localize(list) fileutils.chmod_r(mode, list, options) end #alias_method :chmod_R, :chmod_r def chown(user, group, list, options={}) list = localize(list) fileutils.chown(user, group, list, options) end def chown_r(user, group, list, options={}) list = localize(list) fileutils.chown_r(user, group, list, options) end #alias_method :chown_R, :chown_r def touch(list, options={}) list = localize(list) fileutils.touch(list, options) end # def stage(stage_directory, files) dir = localize(stage_directory) files = localize(files) fileutils.stage(dir, files) end ############# # ZipUtils # ############# # Compress directory to file. Format is determined # by file extension. def compress(folder, file, options={}) ziputils.compress(folder, file, options) end # def gzip(file=nil, options={}) file = localize(file) ziputils.gzip(file, options) end # def bzip2(file=nil, options={}) file = localize(file) ziputils.bzip2(file, options) end # Create a zip file of a directory. def zip(folder, file=nil, options={}) folder = localize(folder) file = localize(file) ziputils.zip(folder, file, options) end # def tar(folder, file=nil, options={}) folder = localize(folder) file = localize(file) ziputils.tar_gzip(folder, file, options) end # Create a tgz file of a directory. def tar_gzip(folder, file=nil, options={}) folder = localize(folder) file = localize(file) ziputils.tar_gzip(folder, file, options) end alias_method :tgz, :tar_gzip # Create a tar.bz2 file of a directory. def tar_bzip2(folder, file=nil, options={}) folder = localize(folder) file = localize(file) ziputils.tar_bzip2(folder, file, options) end def ungzip(file, options) file = localize(file) ziputils.ungzip(file, options) end def unbzip2(file, options) file = localize(file) ziputils.unbzip2(file, options) end def unzip(file, options) file = localize(file) ziputils.unzip(file, options) end def untar(file, options) file = localize(file) ziputils.untar(file, options) end def untar_gzip(file, options) file = localize(file) ziputils.untar_gzip(file, options) end def untar_bzip2(file, options) file = localize(file) ziputils.untar_bzip2(file, options) end ################# # XDG locations # ################# # Look up a config file. def config(path) file(XDG.xdg_config_file(path)) end # Look up a data file. def data(path) file(XDG.xdg_data_file(path)) end # Look up a cache file. def cache(path) file(XDG.xdg_cache_file(path)) end # Return a enumertor of system config directories. def root_config() #_directories XDG.xdg_config_dirs.to_enum(:each){ |f| dir(f) } end # Return a enumertor of system data directories. def root_data() #_directories XDG.xdg_data_dirs.to_enum(:each){ |f| dir(f) } end # Return the home config directory. def home_config dir(XDG.xdg_config_home) end # Return the home data directory. def home_data dir(XDG.xdg_data_home) end # Return the home cache directory. def home_cache dir(XDG.xdg_cache_home) end # Return the work config directory. def work_config dir(XDG.xdg_config_work) end # Return the work cache directory. def work_cache dir(XDG.xdg_cache_work) end private def localize(local_path) # some path arguments are optional return local_path unless local_path # case local_path when Array local_path.collect do |lp| if absolute?(lp) lp else File.expand_path(File.join(work.to_s, lp)) end end else # do not localize an absolute path return local_path if absolute?(local_path) File.expand_path(File.join(work.to_s, local_path)) end end # Returns FileUtils module based on mode. def fileutils return ::FileUtils unless @mode case @mode when :dryrun ::FileUtils::DryRun when :noop ::FileUtils::Noop when :verbose ::FileUtils::Verbose else ::FileUtils end end # Returns ZipUtils module based on mode. def ziputils return ::ZipUtils unless @mode case @mode when :dryrun ::ZipUtils::DryRun when :noop ::ZipUtils::Noop when :verbose ::ZipUtils::Verbose else ::ZipUtils end end public#class def self.[](path) new(path) end end end # Could the prompt act as a delegate to file objects? # If we did this then the file prompt could actually "cd" into a file. # =begin :nodoc: def initialize(path) @path = path = ::File.join(*path) raise FileNotFound unless ::File.exist?(path) if ::File.blockdev?(path) or chardev?(path) @delegate = Device.new(path) elsif ::File.link?(path) @delegate = Link.new(path) elsif ::File.directory?(path) @delegate = Directory.new(path) else @delegate = Document.new(path) end end def delete @delegate.delete @delegate = nil end =end #++