diff options
Diffstat (limited to 'code/fm/keys.rb')
-rw-r--r-- | code/fm/keys.rb | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/code/fm/keys.rb b/code/fm/keys.rb new file mode 100644 index 00000000..bca4f4cd --- /dev/null +++ b/code/fm/keys.rb @@ -0,0 +1,589 @@ +module Fm + # ALL combinations of multiple keys (but without the last letter) + # or regexps which match combinations need to be in here! + COMBS = %w( + g d df y c Z delet cu + ter ta S ? ?g ?f :q + + /[m`']/ /[fF/!].*/ + /[ri]\d*\w*[^ri]/ + /(cw|cd|mv).*/ + /b(l(o(c(k(.*)?)?)?)?)?/ + /m(k(d(i(r(.*)?)?)?)?)?/ + /r(e(n(a(m(e(.*)?)?)?)?)?)?/ + ) + + # Create a regular expression which detects these combos + ary = [] + for token in COMBS + if token =~ /^\/(.*)\/$/ + ary << $1 + elsif token.size > 0 + ary << token.each_char.map {|t| + if t == '?' + t = '\?' + end + + "(?:#{t}" + }.join + + (')?' * (token.size - 1)) + ')' + end + end + REGX = Regexp.new('^(?:' + ary.uniq.join('|') + ')$') + + def self.ignore_keys_for(t) + @ignore_until = Time.now + t + end + + def self.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 self.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 self.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 + + def self.press(key) + return if @ignore_until and Time.now < @ignore_until + + @ignore_until = nil + + if key == '<bs>' + if @buffer.empty? + @buffer = key + elsif @buffer == 'F' + descend + elsif @buffer[-1] == ?> + @buffer.slice!(/(<.*)?>$/) + else + @buffer.slice!(-1) + end + elsif key == '<c-u>' + @buffer = '' + else + @buffer << key + end + + case @buffer + when '<redraw>' + closei + starti + + when 'j', '<down>' + @pwd.pos += 1 + + when 's' + closei + system('clear') + ls = ['ls'] + ls << '--color=auto' if OPTIONS['color'] + ls << '--group-directories-first' if OPTIONS['color'] + system(*ls) + system('bash') + @pwd.schedule + starti + + + when /^S(.)$/ + OPTIONS['sort_reverse'] = $1.ord.between?(65, 90) + + case $1 + when 'n' + OPTIONS['sort'] = :name + when 'e' + OPTIONS['sort'] = :ext + when 't' + OPTIONS['sort'] = :type + when 's' + OPTIONS['sort'] = :size + when 'm' + OPTIONS['sort'] = :mtime + when 'c' + OPTIONS['sort'] = :ctime + end + @pwd.schedule + + when 'tar' + closei + system('tar', 'cvvf', 'pack.tar', *selection.map{|x| x.basename}) + @pwd.refresh! + starti + + when 'R' + @pwd.refresh! + + when 'a' + Process.kill('INT', Process.pid) +# Process.kill('INT', Process.pid) + + when 'x' + @bars.first.kill unless @bars.empty? + + when 'X' + @bars.last.kill unless @bars.empty? + + when 'J' + @pwd.pos += lines/2 + + when 'K' + @pwd.pos -= lines/2 + + when 'cp', 'yy' + @copy = selection + @cut = false + + when 'cut' + @copy = selection + @cut = true + + when 'n' + if @search_string.empty? + find_newest + else + search(@search_string, 1) + end + + when 'N' + search(@search_string, 0, true) + +# when 'fh' +# @buffer.clear +# press('h') + + when /^F(.+)$/ + str = $1 + if str =~ /^\s?(.*)(<cr>|<esc>)$/ + if $2 == '<cr>' + ascend + @buffer = 'F' + else + @buffer.clear + @search_string = $1 + end + else + test = hints(str) + if test == 1 + if ascend + @buffer.clear + else + @buffer = 'F' + end + ignore_keys_for 0.5 + elsif test == 0 + @buffer = 'F' + ignore_keys_for 1 + end + end + + when 'A' + @buffer = "cw #{currentfile.name}" + + when /^f(.+)$/ + str = $1 + if str =~ /^\s?(.*)(L|;|<cr>|<esc>)$/ + @buffer = '' + @search_string = $1 + press('l') if $2 == ';' or $2 == 'L' + else + test = hints(str) + if test == 1 + @buffer = '' + press('l') + ignore_keys_for 0.5 + elsif test == 0 + @buffer = '' + ignore_keys_for 1 + end + end + + when /^\/(.+)$/ + str = $1 + if str =~ /^\s?(.*)(L|;|<cr>|<esc>)$/ + @buffer = '' + @search_string = $1 + press('l') if $2 == ';' or $2 == 'L' + else + search(str) + end + + when /^mkdir(.*)$/ + str = $1 + if str =~ /^\s?(.*)(<cr>|<esc>)$/ + @buffer = '' + if $2 == '<cr>' + closei + system('mkdir', $1) + starti + @pwd.schedule + end + end + + when /^block.*stop$/ + @buffer = '' + + when /^!(.+)$/ + str = $1 + if str =~ /^(\!?)(.*)(<cr>|<esc>)$/ + @buffer = '' + if $3 == '<cr>' + closei + system("bash", "-c", $2) + gets unless $1.empty? + starti + @pwd.schedule + end + end + + when /^cd(.+)$/ + str = $1 + if str =~ /^\s?(.*)(<cr>|<esc>)$/ + @buffer = '' + if $2 == '<cr>' + remember_dir + enter_dir_safely($1) + end + end + + when /^(mv|cw|rename)(.+)$/ + str = $2 + if $1 == 'mv' + if str =~ /['`"]([\w\d])/ + if path = @memory[$1] + str = '' + @buffer.clear + if File.exists?(path) and File.directory?(path) + Action.move(selection, path) + end + end + end + end + log str + if str =~ /^\s?(.*)(<cr>|<esc>)$/ + @buffer = '' + if $2 == '<cr>' + files = selection + if files.size == 1 + fn = $1 + log "!!! #{fn}" + unless fn.include? '.' + if ext = files.first.basename.from_last('.') + fn << ".#{ext}" + end + log "??? #{ext}" + end + Action.move(files, fn) + @pwd.refresh! + @pwd.find_file(fn) + else + Action.move(files, $1) + @pwd.refresh! + end + end + end + + when 'tc' + OPTIONS['color'] ^= true + + when 'tf' + OPTIONS['filepreview'] ^= true + + when 'th' + OPTIONS['hidden'] ^= true + @pwd.refresh! + + when 'td' + OPTIONS['dir_first'] ^= true + @pwd.schedule + + when 'delete' + files = selection + @marked = [] + for f in files + if f and f.exists? and f.dir? + system('rm', '-r', f.to_s) + @pwd.schedule + end + end + + when 'p' + if @cut + Action.move(@copy, @pwd.path) + @cut = false + else + Action.copy(@copy, @pwd.path) + end + @pwd.refresh! + if @copy.size == 1 + @pwd.find_file(@copy[0].basename) + end + + when /^[`'](.)$/ + if dir = @memory[$1] and not @pwd.path == dir + remember_dir + enter_dir_safely(dir) + end + + when '<s-tab>' + if dir = @memory['`'] and not @pwd.path == dir + remember_dir + enter_dir_safely(dir) + end + + when '<tab>' + if dir = @memory['9'] and dir != '/' + unless @pwd.path == dir + enter_dir_safely(dir) + end + elsif dir = @memory['`'] and not @pwd.path == dir + remember_dir + enter_dir_safely(dir) + end + + + when /^m(.)$/ + @memory[$1] = @pwd.path + + when ' ' + if currentfile.marked + @marked.delete(currentfile) + currentfile.marked = false + else + @marked << currentfile + currentfile.marked = true + end + + @pwd.pos += 1 + + when 'v' + @marked = [] + for file in @pwd.files + if file.marked + file.marked = false + else + file.marked = true + @marked << file + end + end + + when 'V' + for file in @marked + file.marked = false + end + @marked = [] + + + when 'gg' + @pwd.pos = 0 + + when 'dd' + new_path = move_to_trash(currentfile) + if new_path + new_path = Directory::Entry.new(new_path) + new_path.get_data + @copy = [new_path] + @cut = false + end + @pwd.schedule + + when 'dD', 'dfd' + cf = currentfile + if cf and cf.exists? + cf.delete! + @pwd.schedule + end + + when 'term' + fork do exec 'x-terminal-emulator' end + + when 'g0' + remember_dir + enter_dir('/') + + when 'gh' + remember_dir + enter_dir('~') + + when 'gu' + remember_dir + enter_dir('/usr') + + when 'ge' + remember_dir + enter_dir('/etc') + + when 'gm' + remember_dir + enter_dir('/media') + + when 'gt' + remember_dir + enter_dir('~/.trash') + + when 'G' + @pwd.pos = @pwd.size - 1 + + when 'k', '<up>' + @pwd.pos -= 1 + + when '<bs>', 'h', 'H', '<left>' + descend + + when 'E' + cf = currentfile.path + unless cf.nil? or enter_dir_safely(cf) + closei + system VI % cf + starti + end + + when '<cr>', 'l', ';', 'L', '<right>' + ascend(@buffer=='L', @buffer=='l') + + # a = run all + # d or e = detach + # t = run in a terminal + # 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__) + +# when 'ra' +# unless File.directory?(currentfile.path) +# Action.run(:all=>true) +# end + + when 'ZZ', '<c-d>', ':q<cr>', 'Q' + exit + + when '<c-r>' + Fm.boot_up + + when "-", "=" + val = "2#{key=='-' ? '-' : '+'}" + system("amixer", "-q", "set", "PCM", val, "unmute") + + else +# log key.ord + + end + + @buffer = '' unless @buffer == '' or @buffer =~ REGX + end + + def self.ascend(wait = false, all=false) + if all and !@marked.empty? + closei + system(*['mplayer', '-fs', *@marked.map{|x| x.path}]) + starti + return true + else + cf = currentfile + enter = enter_dir_safely(cf.path) + unless enter + return Action.run(:detach=>false) + end + return false + end + end + + def self.descend + unless @path.size == 1 + enter_dir(@buffer=='H' ? '..' : @path[-2].path) + end + end +end + |