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.
-
#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:
50 51 52 53 54 55 56 57 |
# File 'lib/rfd.rb', line 50 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.
47 48 49 |
# File 'lib/rfd.rb', line 47 def command_line @command_line end |
#current_dir ⇒ Object (readonly)
Returns the value of attribute current_dir.
47 48 49 |
# File 'lib/rfd.rb', line 47 def current_dir @current_dir end |
#current_page ⇒ Object (readonly)
Returns the value of attribute current_page.
47 48 49 |
# File 'lib/rfd.rb', line 47 def current_page @current_page end |
#current_row ⇒ Object (readonly)
Returns the value of attribute current_row.
47 48 49 |
# File 'lib/rfd.rb', line 47 def current_row @current_row end |
#current_zip ⇒ Object (readonly)
Returns the value of attribute current_zip.
47 48 49 |
# File 'lib/rfd.rb', line 47 def current_zip @current_zip end |
#displayed_items ⇒ Object (readonly)
Returns the value of attribute displayed_items.
47 48 49 |
# File 'lib/rfd.rb', line 47 def displayed_items @displayed_items end |
#header_l ⇒ Object (readonly)
Returns the value of attribute header_l.
47 48 49 |
# File 'lib/rfd.rb', line 47 def header_l @header_l end |
#header_r ⇒ Object (readonly)
Returns the value of attribute header_r.
47 48 49 |
# File 'lib/rfd.rb', line 47 def header_r @header_r end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
47 48 49 |
# File 'lib/rfd.rb', line 47 def items @items end |
#main ⇒ Object (readonly)
Returns the value of attribute main.
47 48 49 |
# File 'lib/rfd.rb', line 47 def main @main end |
Instance Method Details
#ask(prompt = '(y/n)') ⇒ Object
Let the user answer y or n.
Parameters
-
prompt- Prompt message
663 664 665 666 667 668 669 670 671 672 |
# File 'lib/rfd.rb', line 663 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.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rfd.rb', line 172 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)
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/rfd.rb', line 234 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)
249 250 251 252 253 254 |
# File 'lib/rfd.rb', line 249 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 |
#clipboard ⇒ Object
Copy selected files and directories’ path into clipboard on OSX.
504 505 506 |
# File 'lib/rfd.rb', line 504 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.
130 131 132 |
# File 'lib/rfd.rb', line 130 def current_item items[current_row] end |
#delete ⇒ Object
Delete selected files and directories.
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/rfd.rb', line 426 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.
297 298 299 300 301 302 |
# File 'lib/rfd.rb', line 297 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.
606 607 608 609 |
# File 'lib/rfd.rb', line 606 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.
612 613 614 |
# File 'lib/rfd.rb', line 612 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.
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
# File 'lib/rfd.rb', line 675 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.
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/rfd.rb', line 257 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.
275 276 277 278 |
# File 'lib/rfd.rb', line 275 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.
281 282 283 284 |
# File 'lib/rfd.rb', line 281 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?
581 582 583 |
# File 'lib/rfd.rb', line 581 def first_page? current_page == 0 end |
#get_char ⇒ Object
Get a char as a String from user input.
622 623 624 625 |
# File 'lib/rfd.rb', line 622 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
343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/rfd.rb', line 343 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 switch_page 0 move_cursor 0 draw_total_items end |
#last_page? ⇒ Boolean
Do we have more pages?
586 587 588 |
# File 'lib/rfd.rb', line 586 def last_page? current_page == total_pages - 1 end |
#ls ⇒ Object
Fetch files from current directory. Then update each windows reflecting the newest information.
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rfd.rb', line 194 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.
135 136 137 |
# File 'lib/rfd.rb', line 135 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.
292 293 294 |
# File 'lib/rfd.rb', line 292 def max_items main.max_items end |
#maxy ⇒ Object
Height of the currently active pane.
287 288 289 |
# File 'lib/rfd.rb', line 287 def maxy main.maxy end |
#mkdir(dir) ⇒ Object
Create a new directory.
445 446 447 448 449 450 451 452 453 454 |
# File 'lib/rfd.rb', line 445 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.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rfd.rb', line 150 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
722 723 724 725 726 727 |
# File 'lib/rfd.rb', line 722 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.
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/rfd.rb', line 481 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.
188 189 190 |
# File 'lib/rfd.rb', line 188 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.
631 632 633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'lib/rfd.rb', line 631 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 command_line.clear command_line.noutrefresh ret end rescue Interrupt command_line.clear command_line.noutrefresh end |
#process_shell_command ⇒ Object
Accept user input, and directly execute it in an external shell.
647 648 649 650 651 652 653 654 655 656 657 |
# File 'lib/rfd.rb', line 647 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- / separated Regexp like string
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'lib/rfd.rb', line 387 def rename(pattern) from, to = pattern.split '/' from = Regexp.new from 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.
60 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 |
# File 'lib/rfd.rb', line 60 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.
142 143 144 |
# File 'lib/rfd.rb', line 142 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
223 224 225 226 227 228 |
# File 'lib/rfd.rb', line 223 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.
305 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 |
# File 'lib/rfd.rb', line 305 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.
119 120 121 122 |
# File 'lib/rfd.rb', line 119 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
599 600 601 602 603 |
# File 'lib/rfd.rb', line 599 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.
470 471 472 473 |
# File 'lib/rfd.rb', line 470 def symlink(name) FileUtils.ln_s current_item, name ls end |
#times ⇒ Object
Number of times to repeat the next command.
125 126 127 |
# File 'lib/rfd.rb', line 125 def times (@times || 1).to_i end |
#toggle_mark ⇒ Object
Swktch on / off marking on the current file or directory.
617 618 619 |
# File 'lib/rfd.rb', line 617 def toggle_mark main.toggle_mark current_item end |
#total_pages ⇒ Object
Number of pages in the current directory.
591 592 593 |
# File 'lib/rfd.rb', line 591 def total_pages (items.size - 1) / max_items + 1 end |
#touch(filename) ⇒ Object
Create a new empty file.
457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/rfd.rb', line 457 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.
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/rfd.rb', line 409 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.
529 530 531 532 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 |
# File 'lib/rfd.rb', line 529 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.
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
# File 'lib/rfd.rb', line 700 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.
476 477 478 |
# File 'lib/rfd.rb', line 476 def yank @yanked_items = selected_items end |
#zip(zipfile_name) ⇒ Object
Archive selected files and directories into a .zip file.
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/rfd.rb', line 509 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 |