diff options
Diffstat (limited to 'code/extensions.rb')
-rw-r--r-- | code/extensions.rb | 487 |
1 files changed, 442 insertions, 45 deletions
diff --git a/code/extensions.rb b/code/extensions.rb index db238614..a15fc952 100644 --- a/code/extensions.rb +++ b/code/extensions.rb @@ -1,13 +1,348 @@ +class Bar + def initialize( text = '' ) + @text = text + @done = 0 + @thread = nil + @update_proc = nil + Fm.bar_add(self) + end + + def kill(evil = true) + Fm.bar_del(self) + Fm.force_update + + @thread.kill + end + + def update(&block) + if block + @update_proc = block + elsif @update_proc + @update_proc.call(self) + end + end + + attr_accessor :text, :done, :thread +end + +class CopyBar < Bar + def initialize( text = '' ) + super + + @update_proc = proc do |b| + begin + b.done = File.size(fname).to_f / finished + rescue + b.done = 0 + end + end + end +end + +module Action +# def self.get_all_files(path) +# glob = Dir.new(path).to_a +# end + + def self.make_a_bar_for_one(text, command) + bar = CopyBar.new(test) + + finished = File.size(from[0]).to_f + fname = File.join(to, File.basename(from[0])) + + bar.thread = Thread.new do + begin + system('ionice', '-c3', command, *(from + [to])) + ensure + bar.kill(false) + end + end + end + + def self.copy(from, to) +# log [from, to] + +# if String === from[0] +# from[0] = Directory::Entry.new(from[0]) +# end + + if from.size == 1 and from[0].file? + from = from[0] + bar = Bar.new("Copying...") + finished = from.size.to_f + fname = File.join(to, from.basename) + + bar.update do |b| + begin + b.done = File.size(fname).to_f / finished + rescue + b.done = 0 + end + end + + bar.thread = Thread.new do + begin + system('cp', from.to_s, to) + ensure + bar.kill(false) + end + end + + else + bar = Bar.new("Copying...") + from = from.dup + from = [from] unless Array === from + finished = Dir.number_of_files(*from.map{|x| x.to_s}) + count = 0 + + bar.update do |b| + begin + b.done = count / finished + rescue + b.done = 0 + end + end + + from.map!{|x| x.to_s} + bar.thread = Thread.new do + begin + system('cp', '-r', *(from + [to.to_s])) +# IO.popen("cp -vr #{from.join(' ')} #{to.sh}") do |f| +# IO.popen(['cp', '-vr', *(from + [to])]) do |f| +# count += 1 while f.gets =~ /' -> `/ +# end + ensure + bar.kill(false) + end + end + end + end + + def self.move(from, to) +# log [from, to] + +# if String === from[0] +# from[0] = Directory::Entry.new(from[0]) +# end + + if from.size == 1 and from[0].file? + from = from[0] + bar = Bar.new("Moving...") + finished = from.size.to_f + fname = File.join(to, from.basename) + + bar.update do |b| + begin + b.done = File.size(fname).to_f / finished + rescue + b.done = 0 + end + end + + bar.thread = Thread.new do + begin + system('mv', from.to_s, to) + ensure + bar.kill(false) + end + end + + else + bar = Bar.new("Moving...") + from = from.dup + from = [from] unless Array === from + finished = Dir.number_of_files(*from.map{|x| x.to_s}) + count = 0 + + bar.update do |b| + begin + b.done = count / finished + rescue + b.done = 0 + end + end + + from.map!{|x| x.to_s} + bar.thread = Thread.new do + begin + system('mv', *(from + [to.to_s])) +# IO.popen("mv -v #{from.join(' ')} #{to.sh}") do |f| +# count += 1 while f.gets =~ /' -> `/ +# end + ensure + bar.kill(false) + end + end + end + end +end + class Directory - def initialize(path) + BAD_TIME = Time.at(0) + class Entry #{{{ + # Let's just cache every shit, because i don't want + # to call File methods all the time + + + def initialize(dirname, basename=nil) + if basename + @path = File.join(dirname, basename) + @dirname = dirname + @basename = basename + else + @path = dirname + @dirname = File.dirname(dirname) + @basename = File.basename(dirname) + end + @size = 0 + @exists = false + @rights = '----------' + @readlink = '' + @symlink = false + @writable = false + @infostring = '' + @executable = false + @type = :nonexistent + @mtime = BAD_TIME + @ctime = BAD_TIME + @marked = false + end + + attr_reader(:basename, :mtime, :rights, :type, :path, + :infostring, :readlink, :basename, :size, :ctime) + + attr_accessor(:marked) + + def to_s() @path end + def exists?() @exists end + def marked?() @marked end + def symlink?() @symlink end + def broken_symlink?() @symlink and !@exists end + def dir?() @type == :dir end + def file?() @type == :file end + def writable?() @writable end + def executable?() @executable end + + def delete! + if @type == :dir + Dir.delete(@path) rescue nil + else + File.delete(@path) rescue nil + end + end + + def refresh + if File.exists?(@path) + if File.ctime(@path) != @ctime + get_data + end + else + get_data + end + end + + def sh + res = @path.dup + res.gsub!('\\\\', "\000") + res.gsub!(' ', '\\ ') + res.gsub!('(', '\\(') + res.gsub!('&', '\\&') + res.gsub!(')', '\\)') + res.gsub!('*', '\\*') + res.gsub!('\'', '\\\'') + res.gsub!('"', '\\"') + res.gsub!("\000", '\\\\') + return res + end + + def in? path + to_s[0, path.size] == path + end + + def get_data + @size = 0 + @infostring = '' + + @exists = File.exists?(@path) + if @exists + @writable = File.writable?(@path) + @symlink = File.symlink?(@path) + if @symlink + @readlink = File.readlink(@path) + end + if File.directory?(@path) + @type = :dir + begin + sz = Dir.entries(@path).size - 2 + @size = sz + rescue + sz = "?" + end + @infostring << "#{sz}" + elsif File.socket?(@path) + @type = :socket + else + @type = :file + @size = File.size(@path) + if File.size?(@path) + @infostring << " #{File.size(@path).bytes 2}" + else + @infostring << "" + end + end + @rights = File.modestr(@path) + @executable = File.executable?(@path) + @mtime = File.mtime(@path) + @ctime = File.ctime(@path) + + else + if File.symlink?(@path) + @readlink = File.readlink(@path) + @infostring = '->' + @symlink = true + else + @symlink = false + end + @executable = false + @writable = false + @type = :nonexistent + @rights = '----------' + @mtime = BAD_TIME + @ctime = BAD_TIME + end + end + end #}}} + + PLACEHOLDER = Entry.new('/', 'placeholder') + + def initialize(path, allow_delay=false) @path = path @pos = 0 - @pointed_file = '' - @width = 0 + @files = [PLACEHOLDER] + @file_size = 0 + @pointed_file = nil + @width = 1000 + refresh end - attr_reader(:path, :files, :pos, :width, :infos) + def read_dir + @mtime = File.mtime(@path) + @files = Dir.new(@path).to_a + if OPTIONS['hidden'] + @files -= ['.', '..', 'lost+found'] + else + @files.reject!{|x| x[0] == ?. or x == 'lost+found'} + end + if @files.empty? + @files = ['.'] + end + + @files_raw = @files.map{|bn| File.join(@path, bn)} + @files.map!{|basename| Entry.new(@path, basename)} + end + + attr_reader(:path, :files, :pos, :width, :files_raw, :file_size) def pos=(x) @pos = x @@ -15,10 +350,16 @@ class Directory resize end + def restore() + for f in @files + f.marked = false + end + end + def pointed_file=(x) - if @files.include?(x) + if @files_raw.include?(x) @pointed_file = x - @pos = @files.index(x) + @pos = @files_raw.index(x) else self.pos = 0 end @@ -35,57 +376,90 @@ class Directory @width = 0 @files[pos, lines-2].each_with_index do |fn, ix| ix += pos -# log File.basename(fn) + @infos[ix] - sz = File.basename(fn).size + @infos[ix].size + 2 + sz = fn.basename.size + fn.infostring.size + 2 @width = sz if @width < sz end # @width = @files[pos,lines-2].map{|x| File.basename(x).size}.max end end - def get_file_infos() - @infos = [] - @files.each do |fn| - if File.directory?(fn) - begin - sz = Dir.entries(fn).size - 2 - rescue - sz = "?" - end - @infos << "#{sz}" - else - if File.size?(fn) - @infos << " #{File.size(fn).bytes 2}" - else - @infos << "" - end - end + def get_file_info() + @file_size = 0 + @files.each do |f| + f.refresh + @file_size += f.size if f.file? end end - def refresh() - glob = Dir.new(@path).to_a.sort! - if OPTIONS['hidden'] - glob -= ['.', '..', 'lost+found'] - else - glob.reject!{|x| x[0] == ?. or x == 'lost+found'} +# def refresh() +# @files = Dir.new(@path).to_a +# if OPTIONS['hidden'] +# @files -= ['.', '..', 'lost+found'] +# else +# @files.reject!{|x| x[0] == ?. or x == 'lost+found'} +# end +# if @files.empty? +# @files = ['.'] +# end +# @files.map!{|basename| Entry.new(@path, basename)} +# +# if @pos >= @files.size +# @pos = @files.size - 1 +# elsif @files.include?(@pointed_file) +# @pos = @files.index(@pointed_file) +# end +# end + def refresh(info=false) + if File.mtime(@path) != @mtime + read_dir end - if glob.empty? - glob = ['.'] + if info + log("getting file info of #{@path}") + get_file_info end - glob.map!{|x| File.join(@path, x)} - dirs = glob.select{|x| File.directory?(x)} - @files = dirs + (glob - dirs) + sort + end - get_file_infos - resize + def schedule() + Fm.schedule(self) + end + + def refresh!() + read_dir + get_file_info + sort + end - if @pos >= @files.size - @pos = @files.size - 1 - elsif @files.include?(@pointed_file) - @pos = @files.index(@pointed_file) + def sort_sub(x, y) + case OPTIONS['sort'] + when :name + x.basename <=> y.basename + when :size + x.size <=> y.size + when :ctime + x.ctime <=> y.ctime + when :mtime + x.mtime <=> y.mtime + else + x.basename <=> y.basename end end + + def sort() + @files = @files.sort {|x,y| + if OPTIONS['dir_first'] + if x.dir? + if y.dir? then sort_sub(x, y) else -1 end + else + if y.dir? then 1 else sort_sub(x, y) end + end + else + sort_sub(x, y) + end + } + @files.reverse! if OPTIONS['sort_reverse'] + @files_raw = @files.map{|x| x.to_s} + end end @@ -122,12 +496,27 @@ class File end end +class Dir + def self.number_of_files(*dirs) + n = 0 + dirs.each do |entry| + if File.directory?(entry) + n += 1 + number_of_files(*(Dir.new(entry).to_a - ['.', '..']).map\ + {|x| File.join entry, x } ) + else + n += 1 + end + end + return n + end +end + class Numeric def limit(max, min = 0) self < min ? min : (self > max ? max : self) end - def bytes n_round = 2 + def bytes space = true, n_round = 2 n = 1024 a = %w(B K M G T Y) @@ -146,7 +535,7 @@ class Numeric int = flt.to_i flt = int if int == flt - return flt.to_s + ' ' + a[i] + return flt.to_s + (space ? ' ' + a[i] : a[i]) end end @@ -160,11 +549,18 @@ class String def clear replace String.new end + if RUBY_VERSION < '1.9' + def ord + self[0] + end + end + def sh - res = dup + res = self.dup res.gsub!('\\\\', "\000") res.gsub!(' ', '\\ ') res.gsub!('(', '\\(') + res.gsub!('&', '\\&') res.gsub!(')', '\\)') res.gsub!('*', '\\*') res.gsub!('\'', '\\\'') @@ -172,5 +568,6 @@ class String res.gsub!("\000", '\\\\') return res end + end |