Class: Rfd::Controller
Instance Attribute Summary collapse
-
#command_line ⇒ Object
readonly
Returns the value of attribute command_line.
-
#current_dir ⇒ Object
readonly
Returns the value of attribute current_dir.
-
#current_page ⇒ Object
readonly
Returns the value of attribute current_page.
-
#current_row ⇒ Object
readonly
Returns the value of attribute current_row.
-
#current_zip ⇒ Object
readonly
Returns the value of attribute current_zip.
-
#displayed_items ⇒ Object
readonly
Returns the value of attribute displayed_items.
-
#header_l ⇒ Object
readonly
Returns the value of attribute header_l.
-
#header_r ⇒ Object
readonly
Returns the value of attribute header_r.
-
#items ⇒ Object
readonly
Returns the value of attribute items.
-
#main ⇒ Object
readonly
Returns the value of attribute main.
Instance Method Summary collapse
-
#ask(prompt = '(y/n)') ⇒ Object
Let the user answer y or n.
-
#cd(dir = '~', pushd: true) ⇒ Object
Change the current directory.
-
#chmod(mode = nil) ⇒ Object
Change the file permission of the selected files and directories.
-
#chown(user_and_group) ⇒ Object
Change the file owner of the selected files and directories.
- #clear_command_line ⇒ Object
-
#clipboard ⇒ Object
Copy selected files and directories’ path into clipboard on OSX.
-
#cp(dest) ⇒ Object
Copy selected files and directories to the destination.
-
#current_item ⇒ Object
The file or directory on which the cursor is on.
-
#delete ⇒ Object
Delete selected files and directories.
-
#draw_items ⇒ Object
Update the main window with the loaded files and directories.
-
#draw_marked_items ⇒ Object
Update the header information concerning currently marked files or directories.
-
#draw_total_items ⇒ Object
Update the header information concerning total files and directories in the current directory.
-
#edit ⇒ Object
Open current file or directory with the editor.
-
#fetch_items_from_filesystem_or_zip ⇒ Object
Fetch files from current directory or current .zip file.
-
#find(str) ⇒ Object
Focus at the first file or directory of which name starts with the given String.
-
#find_reverse(str) ⇒ Object
Focus at the last file or directory of which name starts with the given String.
-
#first_page? ⇒ Boolean
Current page is the first page?.
-
#get_char ⇒ Object
Get a char as a String from user input.
-
#grep(pattern = '.*') ⇒ Object
Search files and directories from the current directory, and update the screen.
-
#initialize ⇒ Controller
constructor
:nodoc:.
-
#last_page? ⇒ Boolean
Do we have more pages?.
-
#ls ⇒ Object
Fetch files from current directory.
-
#marked_items ⇒ Object
-
marked files and directories.
-
-
#max_items ⇒ Object
Number of files or directories that the current main window can show in a page.
-
#maxy ⇒ Object
Height of the currently active pane.
-
#mkdir(dir) ⇒ Object
Create a new directory.
-
#move_cursor(row = nil) ⇒ Object
Move the cursor to specified row.
- #move_cursor_by_click(y: nil, x: nil) ⇒ Object
-
#mv(dest) ⇒ Object
Move selected files and directories to the destination.
-
#paste ⇒ Object
Paste yanked files / directories here.
-
#popd ⇒ Object
cd to the previous directory.
-
#process_command_line(preset_command: nil) ⇒ Object
Accept user input, and directly execute it as a Ruby method call to the controller.
-
#process_shell_command ⇒ Object
Accept user input, and directly execute it in an external shell.
-
#rename(pattern) ⇒ Object
Rename selected files and directories.
-
#run ⇒ Object
The main loop.
-
#selected_items ⇒ Object
Marked files and directories or Array(the current file or directory).
-
#sort(direction = nil) ⇒ Object
Sort the whole files and directories in the current directory, then refresh the screen.
-
#sort_items_according_to_current_direction ⇒ Object
Sort the loaded files and directories in already given sort order.
-
#spawn_panes(num) ⇒ Object
Change the number of columns in the main window.
-
#switch_page(page) ⇒ Object
Move to the given page number.
-
#symlink(name) ⇒ Object
Create a symlink to the current file or directory.
-
#times ⇒ Object
Number of times to repeat the next command.
-
#toggle_mark ⇒ Object
Swktch on / off marking on the current file or directory.
-
#total_pages ⇒ Object
Number of pages in the current directory.
-
#touch(filename) ⇒ Object
Create a new empty file.
-
#trash ⇒ Object
Soft delete selected files and directories.
-
#unarchive ⇒ Object
Unarchive .zip and .tar.gz files within selected files and directories into current_directory.
-
#view ⇒ Object
Open current file or directory with the viewer.
-
#yank ⇒ Object
Yank selected file / directory names.
-
#zip(zipfile_name) ⇒ Object
Archive selected files and directories into a .zip file.
Methods included from Commands
#-, #/, #C, #D, #F, #G, #H, #K, #L, #M, #O, #S, #a, #c, #click, #ctrl_a, #ctrl_b, #ctrl_f, #ctrl_l, #ctrl_n, #ctrl_p, #ctrl_w, #d, #del, #double_click, #e, #enter, #f, #g, #h, #j, #k, #l, #m, #n, #o, #p, #q, #q!, #r, #s, #space, #t, #u, #v, #w, #y, #z
Constructor Details
#initialize ⇒ Controller
:nodoc:
51 52 53 54 55 56 57 58 |
# File 'lib/rfd.rb', line 51 def initialize @main = MainWindow.new @header_l = HeaderLeftWindow.new @header_r = HeaderRightWindow.new @command_line = CommandLineWindow.new @debug = DebugWindow.new if ENV['DEBUG'] @direction, @dir_history, @last_command, @times, @yanked_items = nil, [], nil, nil, nil end |
Instance Attribute Details
#command_line ⇒ Object (readonly)
Returns the value of attribute command_line.
48 49 50 |
# File 'lib/rfd.rb', line 48 def command_line @command_line end |
#current_dir ⇒ Object (readonly)
Returns the value of attribute current_dir.
48 49 50 |
# File 'lib/rfd.rb', line 48 def current_dir @current_dir end |
#current_page ⇒ Object (readonly)
Returns the value of attribute current_page.
48 49 50 |
# File 'lib/rfd.rb', line 48 def current_page @current_page end |
#current_row ⇒ Object (readonly)
Returns the value of attribute current_row.
48 49 50 |
# File 'lib/rfd.rb', line 48 def current_row @current_row end |
#current_zip ⇒ Object (readonly)
Returns the value of attribute current_zip.
48 49 50 |
# File 'lib/rfd.rb', line 48 def current_zip @current_zip end |
#displayed_items ⇒ Object (readonly)
Returns the value of attribute displayed_items.
48 49 50 |
# File 'lib/rfd.rb', line 48 def displayed_items @displayed_items end |
#header_l ⇒ Object (readonly)
Returns the value of attribute header_l.
48 49 50 |
# File 'lib/rfd.rb', line 48 def header_l @header_l end |
#header_r ⇒ Object (readonly)
Returns the value of attribute header_r.
48 49 50 |
# File 'lib/rfd.rb', line 48 def header_r @header_r end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
48 49 50 |
# File 'lib/rfd.rb', line 48 def items @items end |
#main ⇒ Object (readonly)
Returns the value of attribute main.
48 49 50 |
# File 'lib/rfd.rb', line 48 def main @main end |
Instance Method Details
#ask(prompt = '(y/n)') ⇒ Object
Let the user answer y or n.
Parameters
-
prompt
- Prompt message
671 672 673 674 675 676 677 678 679 680 |
# File 'lib/rfd.rb', line 671 def ask(prompt = '(y/n)') command_line.set_prompt prompt command_line.refresh while (c = Curses.getch) next unless [?N, ?Y, ?n, ?y, 3, 27] .include? c # N, Y, n, y, ^c, esc command_line.clear command_line.noutrefresh break (c == 'y') || (c == 'Y') end end |
#cd(dir = '~', pushd: true) ⇒ Object
Change the current directory.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/rfd.rb', line 173 def cd(dir = '~', pushd: true) dir = load_item path: (dir) unless dir.is_a? Item unless dir.zip? Dir.chdir dir @current_zip = nil else @current_zip = dir end @dir_history << current_dir if current_dir && pushd @current_dir, @current_page, @current_row = dir, 0, nil main.activate_pane 0 ls @current_dir end |
#chmod(mode = nil) ⇒ Object
Change the file permission of the selected files and directories.
Parameters
-
mode
- Unix chmod string (e.g. +w, g-r, 755, 0644)
235 236 237 238 239 240 241 242 243 244 |
# File 'lib/rfd.rb', line 235 def chmod(mode = nil) return unless mode begin Integer mode mode = Integer mode.size == 3 ? "0#{mode}" : mode rescue ArgumentError end FileUtils.chmod mode, selected_items.map(&:path) ls end |
#chown(user_and_group) ⇒ Object
Change the file owner of the selected files and directories.
Parameters
-
user_and_group
- user name and group name separated by : (e.g. alice, nobody:nobody, :admin)
250 251 252 253 254 255 |
# File 'lib/rfd.rb', line 250 def chown(user_and_group) return unless user_and_group user, group = user_and_group.split(':').map {|s| s == '' ? nil : s} FileUtils.chown user, group, selected_items.map(&:path) ls end |
#clear_command_line ⇒ Object
631 632 633 634 635 |
# File 'lib/rfd.rb', line 631 def clear_command_line command_line.writeln 0, "" command_line.clear command_line.noutrefresh end |
#clipboard ⇒ Object
Copy selected files and directories’ path into clipboard on OSX.
508 509 510 |
# File 'lib/rfd.rb', line 508 def clipboard IO.popen('pbcopy', 'w') {|f| f << selected_items.map(&:path).join(' ')} if osx? end |
#cp(dest) ⇒ Object
Copy selected files and directories to the destination.
356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/rfd.rb', line 356 def cp(dest) unless in_zip? src = (m = marked_items).any? ? m.map(&:path) : current_item FileUtils.cp_r src, (dest) else raise 'cping multiple items in .zip is not supported.' if selected_items.size > 1 Zip::File.open(current_zip) do |zip| entry = zip.find_entry(selected_items.first.name).dup entry.name, entry.name_length = dest, dest.size zip.instance_variable_get(:@entry_set) << entry end end ls end |
#current_item ⇒ Object
The file or directory on which the cursor is on.
131 132 133 |
# File 'lib/rfd.rb', line 131 def current_item items[current_row] end |
#delete ⇒ Object
Delete selected files and directories.
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/rfd.rb', line 430 def delete unless in_zip? FileUtils.rm_rf selected_items.map(&:path) else Zip::File.open(current_zip) do |zip| zip.select {|e| selected_items.map(&:name).include? e.to_s}.each do |entry| if entry.name_is_directory? zip.dir.delete entry.to_s else zip.file.delete entry.to_s end end end end @current_row -= selected_items.count {|i| i.index <= current_row} ls end |
#draw_items ⇒ Object
Update the main window with the loaded files and directories. Also update the header.
298 299 300 301 302 303 |
# File 'lib/rfd.rb', line 298 def draw_items main.newpad items @displayed_items = items[current_page * max_items, max_items] main.display current_page header_l.draw_path_and_page_number path: current_dir.path, current: current_page + 1, total: total_pages end |
#draw_marked_items ⇒ Object
Update the header information concerning currently marked files or directories.
610 611 612 613 |
# File 'lib/rfd.rb', line 610 def draw_marked_items items = marked_items header_r.draw_marked_items count: items.size, size: items.inject(0) {|sum, i| sum += i.size} end |
#draw_total_items ⇒ Object
Update the header information concerning total files and directories in the current directory.
616 617 618 |
# File 'lib/rfd.rb', line 616 def draw_total_items header_r.draw_total_items count: items.size, size: items.inject(0) {|sum, i| sum += i.size} end |
#edit ⇒ Object
Open current file or directory with the editor.
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 |
# File 'lib/rfd.rb', line 683 def edit execute_external_command do editor = ENV['EDITOR'] || 'vim' unless in_zip? system %Q[#{editor} "#{current_item.path}"] else begin tmpdir, tmpfile_name = nil Zip::File.open(current_zip) do |zip| tmpdir = Dir.mktmpdir FileUtils.mkdir_p File.join(tmpdir, File.dirname(current_item.name)) tmpfile_name = File.join(tmpdir, current_item.name) File.open(tmpfile_name, 'w') {|f| f.puts zip.file.read(current_item.name)} system %Q[#{editor} "#{tmpfile_name}"] zip.add(current_item.name, tmpfile_name) { true } end ls ensure FileUtils.remove_entry_secure tmpdir if tmpdir end end end end |
#fetch_items_from_filesystem_or_zip ⇒ Object
Fetch files from current directory or current .zip file.
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/rfd.rb', line 258 def fetch_items_from_filesystem_or_zip unless in_zip? @items = Dir.foreach(current_dir).map {|fn| load_item dir: current_dir, name: fn }.to_a.partition {|i| %w(. ..).include? i.name}.flatten else @items = [load_item(dir: current_dir, name: '.', stat: File.stat(current_dir)), load_item(dir: current_dir, name: '..', stat: File.stat(File.dirname(current_dir)))] zf = Zip::File.new current_dir zf.each {|entry| next if entry.name_is_directory? stat = zf.file.stat entry.name @items << load_item(dir: current_dir, name: entry.name, stat: stat) } end end |
#find(str) ⇒ Object
Focus at the first file or directory of which name starts with the given String.
276 277 278 279 |
# File 'lib/rfd.rb', line 276 def find(str) index = items.index {|i| i.index > current_row && i.name.start_with?(str)} || items.index {|i| i.name.start_with? str} move_cursor index if index end |
#find_reverse(str) ⇒ Object
Focus at the last file or directory of which name starts with the given String.
282 283 284 285 |
# File 'lib/rfd.rb', line 282 def find_reverse(str) index = items.reverse.index {|i| i.index < current_row && i.name.start_with?(str)} || items.reverse.index {|i| i.name.start_with? str} move_cursor items.size - index - 1 if index end |
#first_page? ⇒ Boolean
Current page is the first page?
585 586 587 |
# File 'lib/rfd.rb', line 585 def first_page? current_page == 0 end |
#get_char ⇒ Object
Get a char as a String from user input.
626 627 628 629 |
# File 'lib/rfd.rb', line 626 def get_char c = Curses.getch c if (0..255) === c.ord end |
#grep(pattern = '.*') ⇒ Object
Search files and directories from the current directory, and update the screen.
-
pattern
- Search pattern against file names in Ruby Regexp string.
Example
a : Search files that contains the letter “a” in their file name .*.pdf$ : Search PDF files
344 345 346 347 348 349 350 351 352 353 |
# File 'lib/rfd.rb', line 344 def grep(pattern = '.*') regexp = Regexp.new(pattern) fetch_items_from_filesystem_or_zip @items = items.shift(2) + items.select {|i| i.name =~ regexp} sort_items_according_to_current_direction draw_items draw_total_items switch_page 0 move_cursor 0 end |
#last_page? ⇒ Boolean
Do we have more pages?
590 591 592 |
# File 'lib/rfd.rb', line 590 def last_page? current_page == total_pages - 1 end |
#ls ⇒ Object
Fetch files from current directory. Then update each windows reflecting the newest information.
195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/rfd.rb', line 195 def ls fetch_items_from_filesystem_or_zip sort_items_according_to_current_direction @current_page ||= 0 draw_items move_cursor (current_row ? [current_row, items.size - 1].min : nil) draw_marked_items draw_total_items true end |
#marked_items ⇒ Object
-
marked files and directories.
136 137 138 |
# File 'lib/rfd.rb', line 136 def marked_items items.select(&:marked?) end |
#max_items ⇒ Object
Number of files or directories that the current main window can show in a page.
293 294 295 |
# File 'lib/rfd.rb', line 293 def max_items main.max_items end |
#maxy ⇒ Object
Height of the currently active pane.
288 289 290 |
# File 'lib/rfd.rb', line 288 def maxy main.maxy end |
#mkdir(dir) ⇒ Object
Create a new directory.
449 450 451 452 453 454 455 456 457 458 |
# File 'lib/rfd.rb', line 449 def mkdir(dir) unless in_zip? FileUtils.mkdir_p current_dir.join(dir) else Zip::File.open(current_zip) do |zip| zip.dir.mkdir dir end end ls end |
#move_cursor(row = nil) ⇒ Object
Move the cursor to specified row.
The main window and the headers will be updated reflecting the displayed files and directories. The row number can be out of range of the current page.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/rfd.rb', line 151 def move_cursor(row = nil) if row if (prev_item = items[current_row]) main.draw_item prev_item end page = row / max_items switch_page page if page != current_page main.activate_pane row / maxy @current_row = row else @current_row = 0 end item = items[current_row] main.draw_item item, current: true main.display current_page header_l.draw_current_file_info item @current_row end |
#move_cursor_by_click(y: nil, x: nil) ⇒ Object
730 731 732 733 734 735 |
# File 'lib/rfd.rb', line 730 def move_cursor_by_click(y: nil, x: nil) if (idx = main.pane_index_at(y: y, x: x)) row = current_page * max_items + main.maxy * idx + y - main.begy move_cursor row if (row >= 0) && (row < items.size) end end |
#mv(dest) ⇒ Object
Move selected files and directories to the destination.
372 373 374 375 376 377 378 379 380 381 |
# File 'lib/rfd.rb', line 372 def mv(dest) unless in_zip? src = (m = marked_items).any? ? m.map(&:path) : current_item FileUtils.mv src, (dest) else raise 'mving multiple items in .zip is not supported.' if selected_items.size > 1 rename "#{selected_items.first.name}/#{dest}" end ls end |
#paste ⇒ Object
Paste yanked files / directories here.
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/rfd.rb', line 485 def paste if @yanked_items if current_item.directory? FileUtils.cp_r @yanked_items.map(&:path), current_item else @yanked_items.each do |item| if items.include? item i = 1 while i += 1 new_item = load_item dir: current_dir, name: "#{item.basename}_#{i}#{item.extname}", stat: item.stat break unless File.exist? new_item.path end FileUtils.cp_r item, new_item else FileUtils.cp_r item, current_dir end end end ls end end |
#popd ⇒ Object
cd to the previous directory.
189 190 191 |
# File 'lib/rfd.rb', line 189 def popd cd @dir_history.pop, pushd: false if @dir_history.any? end |
#process_command_line(preset_command: nil) ⇒ Object
Accept user input, and directly execute it as a Ruby method call to the controller.
Parameters
-
preset_command
- A command that would be displayed at the command line before user input.
641 642 643 644 645 646 647 648 649 650 651 652 |
# File 'lib/rfd.rb', line 641 def process_command_line(preset_command: nil) prompt = preset_command ? ":#{preset_command} " : ':' command_line.set_prompt prompt cmd, *args = command_line.get_command(prompt: prompt).split(' ') if cmd && !cmd.empty? && respond_to?(cmd) ret = self.public_send cmd, *args clear_command_line ret end rescue Interrupt clear_command_line end |
#process_shell_command ⇒ Object
Accept user input, and directly execute it in an external shell.
655 656 657 658 659 660 661 662 663 664 665 |
# File 'lib/rfd.rb', line 655 def process_shell_command command_line.set_prompt ':!' cmd = command_line.get_command(prompt: ':!')[1..-1] execute_external_command pause: true do system cmd end rescue Interrupt ensure command_line.clear command_line.noutrefresh end |
#rename(pattern) ⇒ Object
Rename selected files and directories.
Parameters
-
pattern
- new filename, or a shash separated Regexp like string
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'lib/rfd.rb', line 387 def rename(pattern) from, to = pattern.sub(/^\//, '').sub(/\/$/, '').split '/' if to.nil? from, to = current_item.name, from else from = Regexp.new from end unless in_zip? selected_items.each do |item| name = item.name.gsub from, to FileUtils.mv item, current_dir.join(name) if item.name != name end else Zip::File.open(current_zip) do |zip| selected_items.each do |item| name = item.name.gsub from, to zip.rename item.name, name end end end ls end |
#run ⇒ Object
The main loop.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/rfd.rb', line 61 def run loop do begin number_pressed = false ret = case (c = Curses.getch) when 10, 13 # enter, return enter when 27 # ESC q when ' ' # space space when 127 # DEL del when Curses::KEY_DOWN j when Curses::KEY_UP k when Curses::KEY_LEFT h when Curses::KEY_RIGHT l when Curses::KEY_CTRL_A..Curses::KEY_CTRL_Z chr = ((c - 1 + 65) ^ 0b0100000).chr public_send "ctrl_#{chr}" if respond_to?("ctrl_#{chr}") when ?0..?9 public_send c number_pressed = true when ?!..?~ if respond_to? c public_send c else debug "key: #{c}" if ENV['DEBUG'] end when Curses::KEY_MOUSE if (mouse_event = Curses.getmouse) case mouse_event.bstate when Curses::BUTTON1_CLICKED click y: mouse_event.y, x: mouse_event.x when Curses::BUTTON1_DOUBLE_CLICKED double_click y: mouse_event.y, x: mouse_event.x end end else debug "key: #{c}" if ENV['DEBUG'] end Curses.doupdate if ret @times = nil unless number_pressed rescue StopIteration raise rescue => e command_line.show_error e.to_s raise if ENV['DEBUG'] end end ensure Curses.close_screen end |
#selected_items ⇒ Object
Marked files and directories or Array(the current file or directory).
. and .. will not be included.
143 144 145 |
# File 'lib/rfd.rb', line 143 def selected_items ((m = marked_items).any? ? m : Array(current_item)).reject {|i| %w(. ..).include? i.name} end |
#sort(direction = nil) ⇒ Object
Sort the whole files and directories in the current directory, then refresh the screen.
Parameters
-
direction
- Sort order in a String.nil : order by name r : reverse order by name s, S : order by file size sr, Sr: reverse order by file size t : order by mtime tr : reverse order by mtime c : order by ctime cr : reverse order by ctime u : order by atime ur : reverse order by atime e : order by extname er : reverse order by extname
224 225 226 227 228 229 |
# File 'lib/rfd.rb', line 224 def sort(direction = nil) @direction, @current_page = direction, 0 sort_items_according_to_current_direction switch_page 0 move_cursor 0 end |
#sort_items_according_to_current_direction ⇒ Object
Sort the loaded files and directories in already given sort order.
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/rfd.rb', line 306 def sort_items_according_to_current_direction case @direction when nil @items = items.shift(2) + items.partition(&:directory?).flat_map(&:sort) when 'r' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort.reverse} when 'S', 's' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by {|i| -i.size}} when 'Sr', 'sr' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:size)} when 't' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.mtime <=> x.mtime}} when 'tr' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:mtime)} when 'c' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.ctime <=> x.ctime}} when 'cr' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:ctime)} when 'u' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.atime <=> x.atime}} when 'ur' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:atime)} when 'e' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.extname <=> x.extname}} when 'er' @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:extname)} end items.each.with_index {|item, index| item.index = index} end |
#spawn_panes(num) ⇒ Object
Change the number of columns in the main window.
120 121 122 123 |
# File 'lib/rfd.rb', line 120 def spawn_panes(num) main.number_of_panes = num @current_row = @current_page = 0 end |
#switch_page(page) ⇒ Object
Move to the given page number.
Parameters
-
page
- Target page number
603 604 605 606 607 |
# File 'lib/rfd.rb', line 603 def switch_page(page) main.display (@current_page = page) @displayed_items = items[current_page * max_items, max_items] header_l.draw_path_and_page_number path: current_dir.path, current: current_page + 1, total: total_pages end |
#symlink(name) ⇒ Object
Create a symlink to the current file or directory.
474 475 476 477 |
# File 'lib/rfd.rb', line 474 def symlink(name) FileUtils.ln_s current_item, name ls end |
#times ⇒ Object
Number of times to repeat the next command.
126 127 128 |
# File 'lib/rfd.rb', line 126 def times (@times || 1).to_i end |
#toggle_mark ⇒ Object
Swktch on / off marking on the current file or directory.
621 622 623 |
# File 'lib/rfd.rb', line 621 def toggle_mark main.toggle_mark current_item end |
#total_pages ⇒ Object
Number of pages in the current directory.
595 596 597 |
# File 'lib/rfd.rb', line 595 def total_pages (items.size - 1) / max_items + 1 end |
#touch(filename) ⇒ Object
Create a new empty file.
461 462 463 464 465 466 467 468 469 470 471 |
# File 'lib/rfd.rb', line 461 def touch(filename) unless in_zip? FileUtils.touch current_dir.join(filename) else Zip::File.open(current_zip) do |zip| # zip.file.open(filename, 'w') {|_f| } #HAXX this code creates an unneeded temporary file zip.instance_variable_get(:@entry_set) << Zip::Entry.new(current_zip, filename) end end ls end |
#trash ⇒ Object
Soft delete selected files and directories.
If the OS is not OSX, performs the same as ‘delete` command.
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
# File 'lib/rfd.rb', line 413 def trash unless in_zip? if osx? FileUtils.mv selected_items.map(&:path), File.('~/.Trash/') else #TODO support other OS FileUtils.rm_rf selected_items.map(&:path) end else return unless ask %Q[Trashing zip entries is not supported. Actually the files will be deleted. Are you sure want to proceed? (y/n)] delete end @current_row -= selected_items.count {|i| i.index <= current_row} ls end |
#unarchive ⇒ Object
Unarchive .zip and .tar.gz files within selected files and directories into current_directory.
533 534 535 536 537 538 539 540 541 542 543 544 545 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 |
# File 'lib/rfd.rb', line 533 def unarchive unless in_zip? zips, gzs = selected_items.partition(&:zip?).tap {|z, others| break [z, *others.partition(&:gz?)]} zips.each do |item| FileUtils.mkdir_p current_dir.join(item.basename) Zip::File.open(item) do |zip| zip.each do |entry| FileUtils.mkdir_p File.join(item.basename, File.dirname(entry.to_s)) zip.extract(entry, File.join(item.basename, entry.to_s)) { true } end end end gzs.each do |item| Zlib::GzipReader.open(item) do |gz| Gem::Package::TarReader.new(gz) do |tar| dest_dir = current_dir.join (gz.orig_name || item.basename).sub(/\.tar$/, '') tar.each do |entry| dest = nil if entry.full_name == '././@LongLink' dest = File.join dest_dir, entry.read.strip next end dest ||= File.join dest_dir, entry.full_name if entry.directory? FileUtils.mkdir_p dest, :mode => entry.header.mode elsif entry.file? FileUtils.mkdir_p dest_dir File.open(dest, 'wb') {|f| f.print entry.read} FileUtils.chmod entry.header.mode, dest elsif entry.header.typeflag == '2' # symlink File.symlink entry.header.linkname, dest end unless Dir.exist? dest_dir FileUtils.mkdir_p dest_dir File.open(File.join(dest_dir, gz.orig_name || item.basename), 'wb') {|f| f.print gz.read} end end end end end else Zip::File.open(current_zip) do |zip| zip.select {|e| selected_items.map(&:name).include? e.to_s}.each do |entry| FileUtils.mkdir_p File.join(current_zip.dir, current_zip.basename, File.dirname(entry.to_s)) zip.extract(entry, File.join(current_zip.dir, current_zip.basename, entry.to_s)) { true } end end end ls end |
#view ⇒ Object
Open current file or directory with the viewer.
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
# File 'lib/rfd.rb', line 708 def view pager = ENV['PAGER'] || 'less' execute_external_command do unless in_zip? system %Q[#{pager} "#{current_item.path}"] else begin tmpdir, tmpfile_name = nil Zip::File.open(current_zip) do |zip| tmpdir = Dir.mktmpdir FileUtils.mkdir_p File.join(tmpdir, File.dirname(current_item.name)) tmpfile_name = File.join(tmpdir, current_item.name) File.open(tmpfile_name, 'w') {|f| f.puts zip.file.read(current_item.name)} end system %Q[#{pager} "#{tmpfile_name}"] ensure FileUtils.remove_entry_secure tmpdir if tmpdir end end end end |
#yank ⇒ Object
Yank selected file / directory names.
480 481 482 |
# File 'lib/rfd.rb', line 480 def yank @yanked_items = selected_items end |
#zip(zipfile_name) ⇒ Object
Archive selected files and directories into a .zip file.
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/rfd.rb', line 513 def zip(zipfile_name) return unless zipfile_name zipfile_name += '.zip' unless zipfile_name.end_with? '.zip' Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| selected_items.each do |item| next if item.symlink? if item.directory? Dir[item.join('**/**')].each do |file| zipfile.add file.sub("#{current_dir}/", ''), file end else zipfile.add item.name, item end end end ls end |