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, default_argument: 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.
-
#touch_t(timestamp) ⇒ Object
Change the timestamp of the selected files and directories.
-
#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, #T, #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:
55 56 57 58 59 60 61 62 |
# File 'lib/rfd.rb', line 55 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.
52 53 54 |
# File 'lib/rfd.rb', line 52 def command_line @command_line end |
#current_dir ⇒ Object (readonly)
Returns the value of attribute current_dir.
52 53 54 |
# File 'lib/rfd.rb', line 52 def current_dir @current_dir end |
#current_page ⇒ Object (readonly)
Returns the value of attribute current_page.
52 53 54 |
# File 'lib/rfd.rb', line 52 def current_page @current_page end |
#current_row ⇒ Object (readonly)
Returns the value of attribute current_row.
52 53 54 |
# File 'lib/rfd.rb', line 52 def current_row @current_row end |
#current_zip ⇒ Object (readonly)
Returns the value of attribute current_zip.
52 53 54 |
# File 'lib/rfd.rb', line 52 def current_zip @current_zip end |
#displayed_items ⇒ Object (readonly)
Returns the value of attribute displayed_items.
52 53 54 |
# File 'lib/rfd.rb', line 52 def displayed_items @displayed_items end |
#header_l ⇒ Object (readonly)
Returns the value of attribute header_l.
52 53 54 |
# File 'lib/rfd.rb', line 52 def header_l @header_l end |
#header_r ⇒ Object (readonly)
Returns the value of attribute header_r.
52 53 54 |
# File 'lib/rfd.rb', line 52 def header_r @header_r end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
52 53 54 |
# File 'lib/rfd.rb', line 52 def items @items end |
#main ⇒ Object (readonly)
Returns the value of attribute main.
52 53 54 |
# File 'lib/rfd.rb', line 52 def main @main end |
Instance Method Details
#ask(prompt = '(y/n)') ⇒ Object
Let the user answer y or n.
Parameters
-
prompt
- Prompt message
688 689 690 691 692 693 694 695 696 |
# File 'lib/rfd.rb', line 688 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 clear_command_line break (c == 'y') || (c == 'Y') end end |
#cd(dir = '~', pushd: true) ⇒ Object
Change the current directory.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/rfd.rb', line 178 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)
240 241 242 243 244 245 246 247 248 249 |
# File 'lib/rfd.rb', line 240 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)
255 256 257 258 259 260 |
# File 'lib/rfd.rb', line 255 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
647 648 649 650 651 |
# File 'lib/rfd.rb', line 647 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.
524 525 526 |
# File 'lib/rfd.rb', line 524 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.
361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/rfd.rb', line 361 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.
136 137 138 |
# File 'lib/rfd.rb', line 136 def current_item items[current_row] end |
#delete ⇒ Object
Delete selected files and directories.
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/rfd.rb', line 435 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.
303 304 305 306 307 308 |
# File 'lib/rfd.rb', line 303 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.
626 627 628 629 |
# File 'lib/rfd.rb', line 626 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.
632 633 634 |
# File 'lib/rfd.rb', line 632 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.
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 |
# File 'lib/rfd.rb', line 699 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.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/rfd.rb', line 263 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.
281 282 283 284 |
# File 'lib/rfd.rb', line 281 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.
287 288 289 290 |
# File 'lib/rfd.rb', line 287 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?
601 602 603 |
# File 'lib/rfd.rb', line 601 def first_page? current_page == 0 end |
#get_char ⇒ Object
Get a char as a String from user input.
642 643 644 645 |
# File 'lib/rfd.rb', line 642 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
349 350 351 352 353 354 355 356 357 358 |
# File 'lib/rfd.rb', line 349 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?
606 607 608 |
# File 'lib/rfd.rb', line 606 def last_page? current_page == total_pages - 1 end |
#ls ⇒ Object
Fetch files from current directory. Then update each windows reflecting the newest information.
200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/rfd.rb', line 200 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.
141 142 143 |
# File 'lib/rfd.rb', line 141 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.
298 299 300 |
# File 'lib/rfd.rb', line 298 def max_items main.max_items end |
#maxy ⇒ Object
Height of the currently active pane.
293 294 295 |
# File 'lib/rfd.rb', line 293 def maxy main.maxy end |
#mkdir(dir) ⇒ Object
Create a new directory.
454 455 456 457 458 459 460 461 462 463 |
# File 'lib/rfd.rb', line 454 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.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/rfd.rb', line 156 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
746 747 748 749 750 751 |
# File 'lib/rfd.rb', line 746 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.
377 378 379 380 381 382 383 384 385 386 |
# File 'lib/rfd.rb', line 377 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.
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 |
# File 'lib/rfd.rb', line 501 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.
194 195 196 |
# File 'lib/rfd.rb', line 194 def popd cd @dir_history.pop, pushd: false if @dir_history.any? end |
#process_command_line(preset_command: nil, default_argument: 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. -
default_argument
- A default argument for the command.
658 659 660 661 662 663 664 665 666 667 668 669 |
# File 'lib/rfd.rb', line 658 def process_command_line(preset_command: nil, default_argument: nil) prompt = preset_command ? ":#{preset_command} " : ':' command_line.set_prompt prompt cmd, *args = command_line.get_command(prompt: prompt, default: default_argument).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.
672 673 674 675 676 677 678 679 680 681 682 |
# File 'lib/rfd.rb', line 672 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
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/rfd.rb', line 392 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.
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 118 119 120 121 122 |
# File 'lib/rfd.rb', line 65 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 Rfd.logger.error e if Rfd.logger 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.
148 149 150 |
# File 'lib/rfd.rb', line 148 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
229 230 231 232 233 234 |
# File 'lib/rfd.rb', line 229 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.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/rfd.rb', line 311 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.
125 126 127 128 |
# File 'lib/rfd.rb', line 125 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
619 620 621 622 623 |
# File 'lib/rfd.rb', line 619 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.
481 482 483 484 |
# File 'lib/rfd.rb', line 481 def symlink(name) FileUtils.ln_s current_item, name ls end |
#times ⇒ Object
Number of times to repeat the next command.
131 132 133 |
# File 'lib/rfd.rb', line 131 def times (@times || 1).to_i end |
#toggle_mark ⇒ Object
Swktch on / off marking on the current file or directory.
637 638 639 |
# File 'lib/rfd.rb', line 637 def toggle_mark main.toggle_mark current_item end |
#total_pages ⇒ Object
Number of pages in the current directory.
611 612 613 |
# File 'lib/rfd.rb', line 611 def total_pages (items.size - 1) / max_items + 1 end |
#touch(filename) ⇒ Object
Create a new empty file.
466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/rfd.rb', line 466 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 move_cursor items.index {|i| i.name == filename} end |
#touch_t(timestamp) ⇒ Object
Change the timestamp of the selected files and directories.
Parameters
-
timestamp
- A string that can be parsed with ‘Time.parse`. Note that this parameter is not compatible with UNIX `touch -t`.
490 491 492 493 |
# File 'lib/rfd.rb', line 490 def touch_t() FileUtils.touch selected_items, mtime: Time.parse() ls end |
#trash ⇒ Object
Soft delete selected files and directories.
If the OS is not OSX, performs the same as ‘delete` command.
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/rfd.rb', line 418 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.
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 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 |
# File 'lib/rfd.rb', line 549 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.
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 |
# File 'lib/rfd.rb', line 724 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.
496 497 498 |
# File 'lib/rfd.rb', line 496 def yank @yanked_items = selected_items end |
#zip(zipfile_name) ⇒ Object
Archive selected files and directories into a .zip file.
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 |
# File 'lib/rfd.rb', line 529 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 |