about summary refs log blame commit diff stats
path: root/code/directory.rb
blob: 8e8f2269ff607e1f1395b63c1ad131fc5a497c3f (plain) (tree)
1
2
3
4
5
6
7
8
9
                               
 

                      
                             

                                               

                            
                           

                                   
                                     
                             
                             
                                 

                                  
 


                       




                                      

                                          
                         
                                                     
                                     
                                            
                    
                                                                          
                   
 
                           
                                                        

                   

                                     

                   


                                                                 

           
                                                            
                                                                      

                                 




                                                                       
                                                       

                                       


                        
                                              
                                             


                      


                                               
                                            

















                                                  





                                        
                            
                                         
                                         
                                                  





                                    



                                                          
                                         






                                                                              









                                                                        
                                                                                 
                                                              




                                                                                       




                                                       
                   
                            
                               

           
                               

                                       

                                              
                   


                                                            
                   
                              



                                                   
           
 
                      
                                 


                      
                                       

                             
                    



                                                   
           
 





                                            
                          
                                



                                                         





                                           
                                  
                                                 

                   

                  
                                     
                                          
                                                








                                                                                 


                                                     
           



                                           

   
require 'code/extensions/basic'

class Directory
	@@filter = nil
	BAD_TIME = Time.at(1)

	def initialize(path, allow_delay=false)
		@path = path
		@pos = 0
		@files = []
		@file_size = 0
		@pointed_file = nil
		@sort_time = BAD_TIME
		@width = 1000
		@read = false
		@free_space = nil
		@empty = true
		@scheduled = false

		refresh
	end

	def inspect
		"<Directory: #{path}>"
	end
	alias to_s inspect

	def read_dir
		@mtime = File.mtime(@path)
		log @path
		files = Dir.new(@path).to_a rescue []
		if Option.show_hidden
			files -= ['.', '..']
		else
			files.reject!{|x| x[0] == ?. or x == 'lost+found'}
		end

		if @@filter
			files.reject!{|x| x !~ @@filter}
		end

		if files.empty?
			files = ['.']
		end

		@files_raw = files.map{|bn| File.join(@path, bn)}
		files.map!{|basename| Entry.new(@path, basename)}
		@files = files
	end

	attr_reader(:path, :files, :pos, :width, :files_raw,
					:file_size, :read, :sort_time)
	attr_accessor(:scheduled)

	def self.filter=(x)
		@@filter = Regexp.new(x, Regexp::IGNORECASE) rescue nil
	end
	def self.filter() @@filter end

	def schedule_resort() @sort_time = BAD_TIME end
	def scheduled?() @scheduled end
	def read?() @read end

	def pos=(x)
		@pos = x
		make_sure_cursor_is_in_range()
		@pointed_file = @files_raw[x]
		resize
	end

	def make_sure_cursor_is_in_range()
		if @files.size <= 1 or @pos < 0
			@pos = 0
		elsif @pos > @files.size - 1
			@pos = @files.size - 1
		end
	end

	def find_file(x)
		x = File.basename(x)

		files.each_with_index do |file, i|
			if file.basename == x
				self.pos = i
			end
		end
	end

	def empty?()
		Dir.entries(@path).size <= 2
	end

	def restore()
		for f in @files
			f.marked = false
		end
	end

	def pointed_file=(x)
		if @files_raw.include?(x)
			@pointed_file = x
			@pos = @files_raw.index(x)
		else
			self.pos = 0
		end
		resize
	end

	def free_space()
		if @free_space then return @free_space end

		@free_space = 0
		out = `df -PB 1 #{~path}`
		out = out[out.index("\n")+1, out.index("\n", out.index("\n"))]
		if out =~ /^[^\s]+ \s+ \d+ \s+ \d+ \s+  (\d+)  \s+/x
			@free_space = $1.to_i
		end
		@free_space
	end

	def size() @files.size end

	def resize()
		pos = Fm.get_offset(self, lines)
		if @files.empty?
			@width = 0
		else
			@width = 0
			@files[pos, lines-2].each_with_index do |fn, ix|
				ix += pos
				sz = fn.displayname.size + fn.infostring.size + 2
				@width = sz + 3 if @width < sz
			end
#			@width = @files[pos,lines-2].map{|x| File.basename(x).size}.max
		end
	end

	def get_file_info()
		@file_size = 0
		@files.each do |f|
			f.refresh
			@file_size += f.size if f.file?
		end
		@read = true
		schedule_resort
	end

	def refresh(info=false)
		oldfile = @pointed_file

		if File.mtime(@path) != @mtime
			read_dir
		end
		if info
			log("getting file info of #{@path}")
			get_file_info 
		end
		sort_if_needed

		if @files.include? oldfile
			self.pointed_file = oldfile
		end
	end

	def schedule()
		Scheduler << self
	end

	def refresh!()
		oldfile = @pointed_file
		read_dir
		get_file_info
		sort

		if @files.include? oldfile
			self.pointed_file = oldfile
		end
	end

	def sort_if_needed
		if @sort_time < Fm.sort_time
			sort
		end
	end

	def sort_sub(x, y)
		case Option.sort
		when :ext
			x.ext <=> y.ext
		when :type
			x.ext.filetype <=> y.ext.filetype
		when :size
			x.size <=> y.size
		when :ctime
			x.ctime <=> y.ctime
		when :mtime
			x.mtime <=> y.mtime
		when :name, Object
			x.basename <=> y.basename
		end
	end

	def sort()
		@sort_time = Time.now
		files = @files.sort {|x,y|
			if Option.list_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 Option.sort_reverse
		@files_raw = files.map{|x| x.to_s}
		@files = files
	end

	def changed?
		File.mtime(@path) != @mtime
	end
end