about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2009-07-24 02:10:05 +0200
committerhut <hut@lavabit.com>2009-07-24 02:10:05 +0200
commitcbda44e7ca9d957dd48b231b7d463e89d5081053 (patch)
tree06ce04b5eaa8ac0c02a186cf2c9bdfdee2155ada
parent3cd5b440d7d7e4714726fa3a68b9724d1bc6d0bc (diff)
downloadranger-cbda44e7ca9d957dd48b231b7d463e89d5081053.tar.gz
implemented #13 (special keys for quick navigation)
-rw-r--r--TODO2
-rw-r--r--code/draw.rb2
-rw-r--r--code/fm.rb1
-rw-r--r--code/help.rb4
-rw-r--r--code/keys.rb88
-rw-r--r--code/search.rb141
-rwxr-xr-xranger1
7 files changed, 167 insertions, 72 deletions
diff --git a/TODO b/TODO
index c33a0571..7ef6cc45 100644
--- a/TODO
+++ b/TODO
@@ -48,7 +48,7 @@ Features
    ( ) #9   09/07/17  build an abstract layer for file system operations
                this would encourage the addition of ftp or ssh protocols
    (X) #11  09/07/17  specify flags at data/types.rb
-   ( ) #13  09/07/17  special keys for quick navigation
+   (X) #13  09/07/17  special keys for quick navigation
                cycle in a certain order, like creation-time, newest first.
    ( ) #19  09/07/19  make path clickable
    ( ) #20  09/07/19  accelerate mouse wheel scrolling after a while
diff --git a/code/draw.rb b/code/draw.rb
index 6b3acc8b..ef1fd35b 100644
--- a/code/draw.rb
+++ b/code/draw.rb
@@ -294,6 +294,8 @@ module Fm
 				puti btm, "Toggle (h)idden_files (d)irs_first (f)ilepreview (p)review (w)idebar (c)d (!)confirm"
 			when 'e'
 				puti btm, "Edit (a)pplications file(t)ypes"
+			when 'f'
+				puti btm, "Find by (r)egexp (s)ize (h)andler (m)time (c)time"
 			else
 				owner = "#{Etc.getpwuid(cf.stat.uid).name}:#{Etc.getgrgid(cf.stat.gid).name}"
 				attr_set(Color.base)
diff --git a/code/fm.rb b/code/fm.rb
index 793c118a..edf8b80c 100644
--- a/code/fm.rb
+++ b/code/fm.rb
@@ -16,6 +16,7 @@ module Fm
 		@buffer = ''
 		@pwd = nil
 		@search_string = ''
+		@search_reset = true
 		@copy = []
 		@ignore_until = nil
 		@trash = File.expand_path('~/.trash')
diff --git a/code/help.rb b/code/help.rb
index c514fc4c..ed452d9b 100644
--- a/code/help.rb
+++ b/code/help.rb
@@ -125,10 +125,10 @@ module Fm
 
 	key:f
 	/<expr>    Search for a "regular expression"
-	f<expr>    Like / but enters/runs the first non-ambiguous match
+	fr<expr>   Like / but executes the first non-ambiguous match
 	F<expr>    Shows only files which match the regular expression.
+	f<x>       Walks through the files in a specific order, defined by <x>
 	n or N     goes to the next or previous match.
-	           if you search for nothing, n goes to the newest file.
 
 	What is a regular expression:
 	A very flexible way of defining patterns in text. By writing
diff --git a/code/keys.rb b/code/keys.rb
index d35e6107..b7822d19 100644
--- a/code/keys.rb
+++ b/code/keys.rb
@@ -238,14 +238,10 @@ module Fm
 			end
 
 		when 'n'
-			if @search_string.empty?
-				find_newest
-			else
-				search(@search_string, 1)
-			end
+			quicksearch(1)
 
 		when 'N'
-			search(@search_string, 0, true)
+			quicksearch(-1)
 
 		when /^cd(.+)$/
 			str = $1
@@ -275,11 +271,22 @@ module Fm
 		when /^um(.)$/
 			@memory.delete($1)
 
-		when /^f(.+)$/
+		when FIND_KEY_REGEXP
+			Option.search_method = FIND_PROPERTIES[$1]
+			search_reset!
+			quicksearch(1)
+
+		when 'fh'
+			Option.search_method = :handler
+			quicksearch(1)
+
+
+		when /^f[rf](.+)$/
 			str = $1
+			Option.search_method = :regexp
 			if str =~ /^\s?(.*)(L|;|<cr>|<esc>)$/
 				@buffer = ''
-				@search_string = $1
+				@search_string = $1 unless $1.empty?
 				press('l') if $2 == ';' or $2 == 'L'
 			else
 				test = hints(str)
@@ -297,6 +304,7 @@ module Fm
 			str = $1
 			if str =~ /^\s?(.*)(L|;|<cr>|<esc>)$/
 				@buffer = ''
+				Option.search_method = :regexp
 				@search_string = $1
 
 				press 'l' if $2 == ';' or $2 == 'L'
@@ -601,7 +609,7 @@ module Fm
 		# and do NOT use spaces or newlines inside a regexp
 
 		@@key_combinations = %w[
-			g y c Z cu
+			g y c Z cu f
 			ter ta S e
 			?? ?g ?f ?m ?l ?c ?o ?z ?s
 			o m ` ' go
@@ -609,8 +617,8 @@ module Fm
 			um
 
 			/:[^<]*/
-			/[fF/!].*/
-			/(r|cw|cm|co|cd|mv|gf).*/
+			/[F/!].*/
+			/(r|ff|fr|cw|cm|co|cd|mv|gf).*/
 			/b(l(o(c(k(.*)?)?)?)?)?/
 			/g(r(e(p(.*)?)?)?)?/
 			/m(k(d(i(r(.*)?)?)?)?)?/
@@ -669,64 +677,6 @@ module Fm
 		@ignore_until = Time.now + t
 	end
 
-	def search(str, offset=0, backwards=false)
-		begin
-			rx = Regexp.new(str, Regexp::IGNORECASE)
-		rescue
-			return false
-		end
-
-		ary = @pwd.files_raw.dup
-		ary.wrap(@pwd.pos + offset)
-
-		ary.reverse! if backwards
-
-		for f in ary
-			g = File.basename(f)
-			if g =~ rx
-				@pwd.pointed_file = f
-				break
-			end
-		end
-	end
-
-	def find_newest()
-		newest = nil
-		for f in @pwd.files
-			if newest.nil? or newest.ctime < f.ctime
-				newest = f
-			end
-		end
-		@pwd.pointed_file = newest.path
-	end
-
-	def hints(str)
-		begin
-			rx = Regexp.new(str, Regexp::IGNORECASE)
-		rescue
-			return false
-		end
-
-		ary = @pwd.files_raw.dup
-		ary.wrap(@pwd.pos)
-
-		n = 0
-		pointed = false
-		for f in ary
-			g = File.basename(f)
-			if g =~ rx
-				unless pointed
-					log "point at #{f}"
-					@pwd.pointed_file = f
-					pointed = true
-				end
-				n += 1
-			end
-		end
-
-		return n
-	end
-
 	def self.remember_dir
 		@memory["`"] = @memory["'"] = @pwd.path
 	end
diff --git a/code/search.rb b/code/search.rb
new file mode 100644
index 00000000..2952f59a
--- /dev/null
+++ b/code/search.rb
@@ -0,0 +1,141 @@
+module Fm
+	def goto(arg)
+		if arg.is_a? Directory::Entry
+			@pwd.pointed_file = arg.path
+
+		elsif arg.is_a? String
+			@pwd.pointed_file = arg
+
+		elsif arg.is_a? Numeric
+			@pwd.pos = arg
+
+		else
+			lograise ArgumentError.new
+		end
+	end
+
+	FIND_PROPERTIES = {
+		's' => :size,
+		'm' => :mtime,
+		'c' => :ctime,
+	}
+	FIND_KEY_REGEXP = /f([#{ FIND_PROPERTIES.keys.join("") }])/
+	
+	def quicksearch(n)
+		log Option.search_method
+		case Option.search_method
+		when *FIND_PROPERTIES.values
+			quicksearch_by_property(n, Option.search_method)
+		when :handler
+			quicksearch_by_handler(n)
+		when :regexp
+			quicksearch_by_regexp(n)
+		else
+			raise "Wrong search method!"
+		end rescue lograise
+	end
+
+	def quicksearch_by_property(n, property)
+		sorted = @pwd.files.sort do |a, b|
+			b.send(property) <=> a.send(property)
+		end
+
+		if @search_reset
+			@search_reset = false
+		else
+			sorted.wrap(sorted.index(currentfile) + n)
+		end
+
+		goto(sorted.first)
+	end
+
+	def quicksearch_by_handler(n)
+		sorted = @pwd.files.sort do |a, b|
+			a.handler.to_s <=> b.handler.to_s
+		end
+
+		goto(sorted.first)
+	end
+
+	def quicksearch_by_regexp(n)
+		begin
+			rx = Regexp.new(@search_string, Regexp::IGNORECASE)
+		rescue
+			return false
+		end
+
+		ary = @pwd.files.dup
+		ary.wrap(@pwd.pos)
+		if n < 0
+			ary.wrap(1)
+			ary.reverse!
+		end
+		ary.wrap(n.abs)
+
+		for file in ary
+			if file.basename =~ rx
+				return goto(file)
+			end
+		end
+	end
+
+	def search_reset!
+		@search_reset = true
+	end
+
+	def search_reset(array)
+		if @search_reset
+			@search_reset = false
+			sorted.wrap(sorted.index(currentfile) + n)
+		end
+	end
+
+	def search(str, offset=0, backwards=false)
+		begin
+			rx = Regexp.new(str, Regexp::IGNORECASE)
+		rescue
+			return false
+		end
+
+		ary = @pwd.files_raw.dup
+		ary.wrap(@pwd.pos + offset)
+
+		ary.reverse! if backwards
+
+		for f in ary
+			g = File.basename(f)
+			if g =~ rx
+				@pwd.pointed_file = f
+				break
+			end
+		end
+	end
+
+	def hints(str)
+		begin
+			rx = Regexp.new(str, Regexp::IGNORECASE)
+		rescue
+			return false
+		end
+
+		ary = @pwd.files_raw.dup
+		ary.wrap(@pwd.pos)
+
+		n = 0
+		pointed = false
+		for f in ary
+			g = File.basename(f)
+			if g =~ rx
+				unless pointed
+					log "point at #{f}"
+					@pwd.pointed_file = f
+					pointed = true
+				end
+				n += 1
+			end
+		end
+
+		return n
+	end
+
+end
diff --git a/ranger b/ranger
index 99144c62..7f3602d2 100755
--- a/ranger
+++ b/ranger
@@ -68,6 +68,7 @@ opt = {
 	:confirm                => true,
 	:file_preview           => true,
 	:preview                => true,
+	:search_method          => :ctime,
 	:mouse                  => true,
 	:mouse_interval         => 200,
 	:debug_level            => 0,