diff options
-rw-r--r-- | code/action.rb | 55 | ||||
-rw-r--r-- | code/application.rb | 9 | ||||
-rw-r--r-- | code/entry.rb | 26 | ||||
-rw-r--r-- | code/extensions/basic.rb | 13 | ||||
-rw-r--r-- | code/fm/fm.rb | 49 | ||||
-rw-r--r-- | code/fm/keys.rb | 47 | ||||
-rw-r--r-- | code/runcontext.rb | 130 | ||||
-rw-r--r-- | data/apps.rb | 58 | ||||
-rw-r--r-- | data/types.rb | 35 | ||||
-rwxr-xr-x | ranger.rb | 6 |
10 files changed, 336 insertions, 92 deletions
diff --git a/code/action.rb b/code/action.rb index e463e852..34a07242 100644 --- a/code/action.rb +++ b/code/action.rb @@ -1,44 +1,54 @@ module Action - def self.copy(files, path) + extend self + + def close_interface + closei + end + + def start_interface + starti + end + + def copy(files, path) files = [files] unless files.is_a? Array unless files.empty? CopyBar2.new(files, path) end end - def self.move(files, path) + def move(files, path) files = [files] unless files.is_a? Array unless files.empty? MoveBar2.new(files, path) end end - def self.run(hash = {}) - unless OpenStruct === hash - hash = OpenStruct.new(hash) - end + def run(rc = nil) + rc ||= RunContext.new(Fm.getfiles) + assert rc, RunContext cf = Fm.currentfile - all = hash.all.or true - files = hash.files.or(all ? Fm.selection : [cf]) - mode = hash.mode.or 0 - newway = hash.newway.or false + all = rc.all.or true + files = rc.files.or(all ? Fm.selection : [cf]) + mode = rc.mode.or 0 + newway = rc.newway.or false return false if files.nil? if newway - hash = Fm.filehandler(files, hash) - handler = hash.exec +# logpp files.first.handler +# rc = Fm.filehandler(files, struct) + handler = rc.exec else handler, wait = Fm.getfilehandler(*files) end return false unless handler - wait = hash.wait.or wait - new_term = hash.new_term.or false - detach = hash.detach.or false + wait = rc.wait.or wait + new_term = rc.new_term.or false + detach = rc.detach.or false log handler if detach @@ -49,7 +59,7 @@ module Action return true end - def self.run_detached(what, new_term) + def run_detached(what, new_term) if new_term p = fork { exec('x-terminal-emulator', '-e', 'bash', '-c', what) } # Process.detach(p) @@ -59,11 +69,16 @@ module Action end end - def self.run_inside(what, wait) - closei + def run_inside(what, wait) + close_interface system(*what) - gets if wait - starti + wait_for_enter if wait + start_interface + end + + def wait_for_enter + print "Press [ENTER] to continue..." + gets end end diff --git a/code/application.rb b/code/application.rb new file mode 100644 index 00000000..f2397d30 --- /dev/null +++ b/code/application.rb @@ -0,0 +1,9 @@ +module Application + ## to be extended by data/apps.rb + extend self + def self.method_missing(*_) end + def check(rc) + assert rc, RunContext + end +end + diff --git a/code/entry.rb b/code/entry.rb index f2871847..bc0d2d7b 100644 --- a/code/entry.rb +++ b/code/entry.rb @@ -5,8 +5,17 @@ class Directory::Entry # to call File methods all the time BAD_TIME = Time.at(0) - MOVIE_EXTENSIONS = %w(avi mpg mpeg mp4 mp5 ogv ogm wmv mkv flv fid vob div divx) + MIMETYPES = Marshal.load(File.read( + File.join(MYDIR, 'data', 'mime.dat'))) + + ## wrapper + def use() Use end + module Use + def self.method_missing(app,*_) throw(:use, app) end + def self.no_handler() throw(:use, nil) end + end + def initialize(dirname, basename=nil) if basename @path = File.join(dirname, basename) @@ -27,6 +36,7 @@ class Directory::Entry @symlink = false @writable = false @infostring = '' + @mimetype = nil @executable = false @type = :nonexistent @mtime = BAD_TIME @@ -35,7 +45,7 @@ class Directory::Entry end attr_reader(*%w{ - basename mtime rights type path ext + basename mtime rights type path ext mimetype infostring readlink basename size ctime name }) @@ -45,17 +55,18 @@ class Directory::Entry def exists?() @exists end def marked?() @marked end def symlink?() @symlink end + def socket?() @type == :socket 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] + + def handler() + ## get_handler has to be defined in another file + @handler = catch(:use) do + get_handler end end @@ -109,6 +120,7 @@ class Directory::Entry @type = :socket else @type = :file + @mimetype = MIMETYPES[@ext] @size = File.size(@path) if File.size?(@path) @infostring << " #{File.size(@path).bytes 2}" diff --git a/code/extensions/basic.rb b/code/extensions/basic.rb index 1bc67519..1e890a04 100644 --- a/code/extensions/basic.rb +++ b/code/extensions/basic.rb @@ -8,6 +8,7 @@ class MutableNumber end def add(n=1) @value += n end def sub(n=1) @value -= n end + def set(n) @value = n end end class Array @@ -15,6 +16,10 @@ class Array # TODO: this can be done better... n.times { push shift } end + def cdr(n = 1) + self[n .. -1] + end + alias car first end class String @@ -65,6 +70,14 @@ class String res.gsub!("\000", '\\\\') return res end + + ## encodes a string for the shell. + ## peter's song.mp3 -> 'peter'\''s song.mp3' + ## + ## system("mplayer #{ ~some_video_file }") + def ~ + "'#{ gsub("'", "'\\\\''") }'" + end end class Numeric diff --git a/code/fm/fm.rb b/code/fm/fm.rb index 5033c161..91b17f2d 100644 --- a/code/fm/fm.rb +++ b/code/fm/fm.rb @@ -1,3 +1,5 @@ +require 'thread' + OPTIONS = { 'hidden' => false, 'sort' => :name, @@ -18,6 +20,8 @@ module Fm def self.initialize(pwd=nil) @bars = [] @bars_thread = nil + + @entering_directory = true @buffer = '' @pwd = nil @@ -27,33 +31,28 @@ module Fm @trash = File.expand_path('~/.trash') pwd ||= Dir.getwd - # `' and `` are the original PWD unless overwritten by .fmrc + # `' and `` are the original PWD unless overwritten by .rangerrc @memory = { '`' => pwd, '\'' => pwd } - # Read the .fmrc - @fmrc = File.expand_path('~/.fmrc') - if (File.exists?(@fmrc)) - loaded = Marshal.load(File.read(@fmrc)) rescue nil - if Hash === loaded - @memory.update(loaded) + # Read the .rangerrc + @rangerrc = File.expand_path('~/.rangerrc') + if (File.exists?(@rangerrc)) + content = File.read(@rangerrc) + unless content.empty? + loaded = Marshal.load() rescue nil + if Hash === loaded + @memory.update(loaded) + end end end + @dump_config_on_exit = true # `0 is always the original PWD @memory['0'] = pwd - # Give me some way to redraw screen while waiting for - # input from CLI.geti - -# for i in 1..20 -# eval "Signal.trap(#{i}) do -# log #{i} -# exit if #{i} == 9 end" -# end - boot_up(pwd) end @@ -90,10 +89,15 @@ module Fm end def dump - remember_dir - dumped = Marshal.dump(@memory) - File.open(@fmrc, 'w') do |f| - f.write(dumped) + if defined? @dump_config_on_exit + begin + remember_dir + dumped = Marshal.dump(@memory) + File.open(@rangerrc, 'w') do |f| + f.write(dumped) + end + rescue Exception + end end end @@ -198,6 +202,7 @@ module Fm end end + @entering_directory = true Dir.chdir(@pwd.path) end @@ -270,5 +275,9 @@ module Fm @bars_thread = nil end end + + def getfiles() + @marked.empty? ? [currentfile] : @marked + end end diff --git a/code/fm/keys.rb b/code/fm/keys.rb index c7abea17..4e3af766 100644 --- a/code/fm/keys.rb +++ b/code/fm/keys.rb @@ -305,7 +305,7 @@ module Fm if $3 == '<cr>' closei system("bash", "-c", $2) - gets unless $1.empty? + Action.wait_for_enter unless $1.empty? starti @pwd.schedule end @@ -522,47 +522,8 @@ module Fm # w = wait for <enter> after execution # capital letter inverts when /^[ri](\d*)([adetw]*)[ri]$/ - if $2.empty? - f = @marked.empty?? currentfile : @marked.first - flags = get_default_flags(f) - else - flags = $2 - end - opt = OpenStruct.new - opt.newway = true - - opt.mode = $1.to_i unless $1.empty? - - # Set options based on flags - - if flags =~ /a/ - opt.all = true - end - if flags =~ /[de]/ - opt.detach = true - end - if flags =~ /t/ - opt.new_term = true - opt.detach = true - end - if flags =~ /w/ - opt.wait = true - end - - if flags =~ /A/ - opt.all = false - end - if flags =~ /[DE]/ - opt.detach = false - end - if flags =~ /T/ - opt.new_term = false - end - if flags =~ /W/ - opt.wait = false - end - - Action.run(opt.__table__) + run_context = RunContext.new(getfiles, $1, $2) + Action.run(run_context) # when 'ra' # unless File.directory?(currentfile.path) @@ -598,7 +559,7 @@ module Fm cf = currentfile enter = enter_dir_safely(cf.path) unless enter - return Action.run(:detach=>false) + return Action.run(RunContext.new(getfiles)) end return false end diff --git a/code/runcontext.rb b/code/runcontext.rb new file mode 100644 index 00000000..3d9ff457 --- /dev/null +++ b/code/runcontext.rb @@ -0,0 +1,130 @@ +class RunContext + ## accessors {{{ + attr_accessor( *%w[ + all detach wait new_term + files handlers paths + mode + exec + multi + ]) + attr_reader( :flags ) + def flags=(x) + assert x, Array, String + + if x.is_a? Array + @flagstring = x.join('') + @flags = x + elsif x.is_a? String + @flagstring = x + @flags = x.split(//) + end + + parse_flags + return x + end + ## }}} + + def initialize(files, mode=0, flags='') + @mode = mode.to_i + @files = files.dup + self.flags = flags + + @files.reject! {|file| + file.handler == nil or !file.exists? + } + @handlers = @files.map {|file| file.handler} + @paths = @files.map {|file| file.path} + @handler = @handlers.first + + @multi = (@files.size > 1 and @handlers.uniq.size == 1) + + @exec = Application.send(@handler, self) + end + + def has_flag? x + if x.is_a? Regexp + @flagstring =~ x + elsif x.is_a? String + @flags.include? x + else + false + end + end + + def parse_flags + @all = @detach = @new_term = @wait = false + + ## Positive flags + if has_flag? 'a' + @all = true + end + if has_flag? /[de]/ + @detach = true + end + if has_flag? 't' + @new_term = true + @detach = true + end + if has_flag? 'w' + @wait = true + end + + ## Negative flags + if has_flag? 'A' + @all = false + end + if has_flag? /[DE]/ + @detach = false + end + if has_flag? 'T' + @new_term = false + end + if has_flag? 'W' + @wait = false + end + end + + def newway() true end + + def no_mode?() + @mode == 0 + end + + def no_flags?() + @flagstring.empty? + end + + def default_flags=(x) + if @flagstring.empty? + self.flags = x + end + x + end + + ## set the mode and return self. + def with_mode(n) + @mode = n + self + end + + ## wrapper {{{ + + ## escape all files for direct use in the shell. + ## if the _multi_ attribute is true, this is a shortcut for + ## rc.paths.map {|x| ~x}.join(' ') + ## otherwise: + ## ~(rc.paths.first) + def ~() @paths.map {|x| ~x}.join(' ') end + + ## shortcut for _files.size_ + def size() @files.size end + + ## shortcut for _files.first.path_ + def first() @files.first.path end + + ## shortcut for _files.first.name_ + def name() @files.first.name end + + ## }}} +end + diff --git a/data/apps.rb b/data/apps.rb new file mode 100644 index 00000000..6ba7f44b --- /dev/null +++ b/data/apps.rb @@ -0,0 +1,58 @@ +module Application + def mplayer(rc) + check rc + + rc.default_flags = 'd' + + if rc.no_mode? + rc.mode = (rc.name =~ /720p/) ? 2 : 1 + end + + case rc.mode + when 1; "mplayer -fs -sid 0 #{~rc}" + when 2; "mplayer -sid 0 #{~rc}" + when 3; "mplayer -vm sdl -sid 0 #{~rc}" + else nil end + end + + def evince(rc) + check rc + "evince #{~rc}" + end + + def feh(rc) + check rc + case rc.mode + when 4; "feh --bg-scale #{~rc.first}" + when 5; "feh --bg-tile #{~rc.first}" + when 6; "feh --bg-center #{~rc.first}" + when 2; "gimp #{~rc}" + when 1; "feh -F #{~rc}" + else "feh #{~rc}" + end + end + + def interpreted_language(rc) + check rc + case rc.mode + when 1; "./#{~rc.first}" + when 0; vi(rc) + else nil end + end + + def zsnes(rc) + check rc + "zsnes #{~rc.first}" + end + + def vi(rc) + commands = [ + 'map h :quit<cr>', + 'map q h', + 'map H :unmap h<CR>:unmap H<CR>:unmap q<CR>', + ].map {|x| "+'#{x}'"}.join(' ') + + "vi #{commands} #{~rc}" + end +end + diff --git a/data/types.rb b/data/types.rb new file mode 100644 index 00000000..773df758 --- /dev/null +++ b/data/types.rb @@ -0,0 +1,35 @@ +class Directory::Entry + INTERPRETED_LANGUAGES = %w[haskell perl python ruby sh] + MOVIE_EXTENSIONS = %w[avi mpg mpeg mp4 mp5 ogv ogm wmv mkv flv fid vob div divx] + + def get_handler + ## directories or sockets don't have any handler + use.no_handler if dir? or socket? + + ## at first, look at the mime type + case @mimetype + when /^video|audio/ + use.mplayer + + when "application/pdf" + use.evince + + when /^image/ + use.feh + + when /^(text|application).x-(#{INTERPRETED_LANGUAGES.join('|')})$/ + use.interpreted_language + + end + + ## second, look at the extension + case @ext + when 'swc', 'smc' + use.zsnes + + end + + use.vi + end +end + diff --git a/ranger.rb b/ranger.rb index 472f02ae..6f3f3aa2 100755 --- a/ranger.rb +++ b/ranger.rb @@ -34,8 +34,10 @@ for file in Dir.glob "#{MYDIR}/code/**/*.rb" require file [MYDIR.size + 1 ... -3] end +load 'data/types.rb' +load 'data/apps.rb' load 'data/colorscheme/default.rb' -require 'data/screensaver/clock.rb' +load 'data/screensaver/clock.rb' unless ARGV.empty? or File.directory?(pwd) exec(Fm.getfilehandler_frompath(pwd)) @@ -61,7 +63,7 @@ ensure log "exiting!" log "" closei if CLI.running? -# Fm.dump + Fm.dump ERROR_STREAM.close # Kill all other threads |