about summary refs log tree commit diff stats
path: root/code/directory.rb
diff options
context:
space:
mode:
Diffstat (limited to 'code/directory.rb')
-rw-r--r--code/directory.rb350
1 files changed, 350 insertions, 0 deletions
diff --git a/code/directory.rb b/code/directory.rb
new file mode 100644
index 00000000..c42392aa
--- /dev/null
+++ b/code/directory.rb
@@ -0,0 +1,350 @@
+class Directory
+	BAD_TIME = Time.at(0)
+	MOVIE_EXTENSIONS = %w(avi mpg mpeg mp4 mp5 ogv ogm wmv mkv flv fid vob div divx)
+	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
+			@name, @ext = @basename.split_at_last_dot
+#			@ext = @basename.from_last('.') || ''
+			@movie = MOVIE_EXTENSIONS.include?(@ext)
+			@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 *%w(
+			basename mtime rights type path ext
+			infostring readlink basename size ctime name
+		)
+
+		attr_accessor(:marked)
+		
+		def to_s() @path end
+		def exists?() @exists end
+		def marked?() @marked end
+		def symlink?() @symlink end
+		def movie?() @movie 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 mimetype()
+			if @type == :dir
+				nil
+			else
+				Fm::MIMETYPES[@ext]
+			end
+		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
+			@path.sh
+		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
+		@files = [PLACEHOLDER]
+		@file_size = 0
+		@pointed_file = nil
+		@width = 1000
+		@read = false
+		@empty = true
+		@scheduled = false
+
+		refresh
+	end
+
+	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, :read)
+	attr_accessor(:scheduled)
+
+	def scheduled?() @scheduled end
+	def read?() @read end
+
+	def pos=(x)
+#		if @files.size <= 1 or x < 0
+#			x = 0
+#		elsif x > @files.size
+#			x = @files.size - 1
+#		end
+		@pos = x
+		make_sure_cursor_is_in_range()
+		@pointed_file = @files[x]
+		resize
+	end
+
+	def recheck_stuff()
+#		log "pointed file: #@pointed_file"
+#		log @files_raw
+#		log ""
+		if test = @files_raw.index(@pointed_file)
+#			log("if")
+			@pos = test
+		else
+#			log("else")
+			make_sure_cursor_is_in_range()
+		end
+	end
+
+	def make_sure_cursor_is_in_range()
+		if @files.size <= 1 or @pos < 0
+			@pos = 0
+		elsif @pos > @files.size
+			@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 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.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_info()
+		@file_size = 0
+		@files.each do |f|
+			f.refresh
+			@file_size += f.size if f.file?
+		end
+		@read = true
+	end
+
+#	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 info
+			log("getting file info of #{@path}")
+			get_file_info 
+		end
+		sort
+	end
+
+	def schedule()
+		@scheduled = true
+		Fm.schedule(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_sub(x, y)
+		case OPTIONS['sort']
+		when :name
+			x.basename <=> y.basename
+		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
+		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
+
id='n546' href='#n546'>546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620