rfd 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +128 -3
- data/lib/rfd.rb +37 -40
- data/lib/rfd/commands.rb +2 -2
- data/lib/rfd/item.rb +8 -0
- data/lib/rfd/windows.rb +4 -1
- data/rfd.gemspec +1 -1
- data/spec/controller_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfede93c56a43d3df90257d60df31b8934b6891f
|
4
|
+
data.tar.gz: d5187481f8cb6076394a4337ae85a1799120f2a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 427efc2d0a2a5e6fba9e4ad7de07dc791b335e6b59ca0f21c62dd3760999816d338f58cd233eddcc80c8849232302808911d447878b3cd1824765e872cba5044
|
7
|
+
data.tar.gz: 4f41128bcd148e16149a4ce40ea1485be8e11b989bcb280a69e31074088e50865488097434ecfaa0daf623218df09723454ee5789f9132c56a4740d69f632105
|
data/README.md
CHANGED
@@ -16,15 +16,140 @@ rfd is a terminal based File explorer, inpsired by the legendary freesoft MS-DOS
|
|
16
16
|
|
17
17
|
Mac OS X Mountain Lion, Mac OS X Lion
|
18
18
|
|
19
|
-
##
|
19
|
+
## Screenshot
|
20
|
+
|
21
|
+
![screenshot](https://www.evernote.com/shard/s20/sh/0bec8345-46c6-45f9-989b-c979b060f5a6/1cffd4c54b30204426251d8561c084a2/res/659f4073-10cc-48f5-a3d2-eb5fe54fba45/skitch.png?resizeSmall&width=768)
|
22
|
+
|
23
|
+
## Start Me Up
|
20
24
|
|
21
25
|
Open up your terminal and type in:
|
22
26
|
|
23
27
|
% rfd
|
24
28
|
|
25
|
-
You can
|
29
|
+
You can also pass in a starting directory name, which is defaulted to `.`.
|
30
|
+
|
31
|
+
% rfd ~/src/rails
|
32
|
+
|
33
|
+
## Commands
|
34
|
+
|
35
|
+
You can command rfd by pressing some chars on your keyboard, just like Vim. If you're totally unfamiliar with this sort of command system, I recommend you to play with `vimtutor` before you go any further.
|
36
|
+
|
37
|
+
All available commands in rfd are defined as Ruby methods here. https://github.com/amatsuda/rfd/tree/master/lib/rfd/commands.rb
|
38
|
+
|
39
|
+
### Changing the current directory
|
40
|
+
|
41
|
+
* **\<Enter\>**: cd into the directory where the cursor is on.
|
42
|
+
* **\<Delete\>** (or \<Backspace\> on you keyboard, probably?): Go up to the upper directory (cd ..).
|
43
|
+
* **-**: Get back to where you once belonged (popd).
|
44
|
+
|
45
|
+
### Moving the cursor
|
46
|
+
|
47
|
+
* **j**: Move downward.
|
48
|
+
* **k**: Move upward.
|
49
|
+
* **h**: Move to the left column. At the left end column, move to the right end column at the previous page.
|
50
|
+
* **l**: Move to the right column. At the right end column, move to the left end column at the next page.
|
51
|
+
|
52
|
+
### The {count} parameter
|
53
|
+
|
54
|
+
Some commands such as `j` or `k` take a number parameter called {count}. For passing a {count} parameter, just type in a number prior to the command.
|
55
|
+
For example, `3j` moves the cursor to 3 lines below, and `999k` will take your cursor to 999 lines above.
|
56
|
+
|
57
|
+
### Jumping the cursor
|
58
|
+
|
59
|
+
* **H**: Move to the top of the current page.
|
60
|
+
* **M**: Move to the middle of the current page.
|
61
|
+
* **L**: Move to the bottom of the current page.
|
62
|
+
|
63
|
+
### Switching the page
|
64
|
+
|
65
|
+
* **ctrl-n, ctrl-f**: Move to the top of the next page.
|
66
|
+
* **ctrl-p, ctrl-b**: Move to the top of the previous page.
|
67
|
+
* **g**: Move to the top of the first page.
|
68
|
+
* **G**: Move to the bottom of the last page.
|
69
|
+
|
70
|
+
### Finding a file / directory
|
71
|
+
|
72
|
+
You can find a file by typing the first letter of it immediately after the find commands.
|
73
|
+
|
74
|
+
* **f{char}**: Move to the next file / directory of which name starts with the given char.
|
75
|
+
* **F{char}**: Move to the previous file / directory of which name starts with the given char.
|
76
|
+
* **n**: Repeat the last `f` or `F`.
|
77
|
+
|
78
|
+
### Searching, sorting
|
79
|
+
|
80
|
+
For commands like these that require a parameter string, type the parameter in the command line at the bottom of the screen, and press \<Enter\>.
|
81
|
+
|
82
|
+
* **/**: Grep the current directory with the given parameter. The parameter will be interpreted as Ruby Regexp (e.g. `.*\.rb$`).
|
83
|
+
* **s**: Sort files / directories in the current directory in the given order.
|
84
|
+
* (none): by name
|
85
|
+
* r : reverse order by name
|
86
|
+
* s, S : order by file size
|
87
|
+
* sr, Sr: reverse order by file size
|
88
|
+
* t : order by mtime
|
89
|
+
* tr : reverse order by mtime
|
90
|
+
* c : order by ctime
|
91
|
+
* cr : reverse order by ctime
|
92
|
+
* u : order by atime
|
93
|
+
* ur : reverse order by atime
|
94
|
+
* e : order by extname
|
95
|
+
* er : reverse order by extname
|
96
|
+
|
97
|
+
### Marking files / directories
|
98
|
+
|
99
|
+
You can send a command to the file / directory on which the cursor is on. Or, you can send a command to multiple files / directories at once by marking them first.
|
100
|
+
The mark is drawn as a `*` char on the left of each file / directory name.
|
101
|
+
|
102
|
+
* **\<Space\>**: Mark / unmark current file / directory.
|
103
|
+
* **ctrl-a**: Mark / unmark all file / directories in the current directory.
|
104
|
+
|
105
|
+
### Manipulating files / directories
|
106
|
+
|
107
|
+
As stated above, you can send a command to one or more files / directories. In this document, the term "selected items" means "(the marked files / directories) || (the file / directory on which the cursor is on)".
|
108
|
+
|
109
|
+
* **c**: Copy selected items (cp).
|
110
|
+
* **m**: Move selected items (mv).
|
111
|
+
* **d**: Move selected items into the Trash.
|
112
|
+
* **D**: Delete selected items.
|
113
|
+
* **r**: Rename selected items.
|
114
|
+
|
115
|
+
### Creating files / directories
|
116
|
+
|
117
|
+
* **t**: Create a new file (touch).
|
118
|
+
* **K**: Creat a new directory (mkdir).
|
119
|
+
* **S**: Create new symlink to the current file / directory (ln -s).
|
120
|
+
|
121
|
+
### Attributes
|
122
|
+
|
123
|
+
* **a**: Change permission of selected items (chmod).
|
124
|
+
* **w**: Change the owner of of selected items (chown).
|
125
|
+
|
126
|
+
### Viewing, Editing, Opening
|
127
|
+
|
128
|
+
* **\<Enter\>**: View current file with the system $VIEWER such as `less`.
|
129
|
+
* **v**: View current file with the system $VIEWER such as `less`.
|
130
|
+
* **e**: Edit current file with the system $EDITOR such as `vim`.
|
131
|
+
* **o**: Send the `open` command.
|
132
|
+
|
133
|
+
### Manipulating archives
|
134
|
+
|
135
|
+
* **u**: Unarchive .zip, .gz, or .tar.gz file into the current directory.
|
136
|
+
* **z**: Archive selected items into a .zip file with the given name.
|
137
|
+
|
138
|
+
### Handling .zip files
|
139
|
+
|
140
|
+
You can `cd` into a .zip file as if it's just a directory, then unarchive selected items, view files in it, and even create new files or edit files in the archive.
|
141
|
+
|
142
|
+
### Splitting columns
|
143
|
+
|
144
|
+
* **ctrl-w**: Change the window split size to the {count} value (e.g. `4<C-w>` to split the window into 4 columns). The default number of columns is 2.
|
145
|
+
|
146
|
+
### Misc
|
26
147
|
|
27
|
-
|
148
|
+
* **ctrl-l**: Refresh the whole screen.
|
149
|
+
* **C**: Copy selected items' paths to the clipboard.
|
150
|
+
* **O**: Open a new terminal window at the current directory.
|
151
|
+
* **!**: Execute a shell command.
|
152
|
+
* **q**: Quit the app.
|
28
153
|
|
29
154
|
## Contributing
|
30
155
|
|
data/lib/rfd.rb
CHANGED
@@ -171,23 +171,15 @@ module Rfd
|
|
171
171
|
|
172
172
|
# Change the current directory.
|
173
173
|
def cd(dir, pushd: true)
|
174
|
-
|
175
|
-
|
174
|
+
dir = load_item expand_path(dir) unless dir.is_a? Item
|
175
|
+
unless dir.zip?
|
176
|
+
Dir.chdir dir
|
177
|
+
@current_zip = nil
|
176
178
|
else
|
177
|
-
|
178
|
-
if File.readable? target
|
179
|
-
Dir.chdir target
|
180
|
-
@dir_history << current_dir if current_dir && pushd
|
181
|
-
@current_dir, @current_page, @current_row, @current_zip = target, 0, nil, nil
|
182
|
-
main.activate_pane 0
|
183
|
-
end
|
179
|
+
@current_zip = dir
|
184
180
|
end
|
185
|
-
|
186
|
-
|
187
|
-
def cd_into_zip(zipfile)
|
188
|
-
@current_zip = zipfile
|
189
|
-
@dir_history << current_dir if current_dir
|
190
|
-
@current_dir, @current_page, @current_row = zipfile.path, 0, nil
|
181
|
+
@dir_history << current_dir if current_dir && pushd
|
182
|
+
@current_dir, @current_page, @current_row = dir, 0, nil
|
191
183
|
main.activate_pane 0
|
192
184
|
end
|
193
185
|
|
@@ -266,7 +258,7 @@ module Rfd
|
|
266
258
|
def fetch_items_from_filesystem_or_zip
|
267
259
|
unless in_zip?
|
268
260
|
@items = Dir.foreach(current_dir).map {|fn|
|
269
|
-
stat = File.lstat
|
261
|
+
stat = File.lstat current_dir.join(fn)
|
270
262
|
Item.new dir: current_dir, name: fn, stat: stat, window_width: maxx
|
271
263
|
}.to_a
|
272
264
|
else
|
@@ -311,7 +303,7 @@ module Rfd
|
|
311
303
|
# Update the main window with the loaded files and directories. Also update the header.
|
312
304
|
def draw_items
|
313
305
|
main.draw_items_to_each_pane (@displayed_items = items[current_page * max_items, max_items])
|
314
|
-
header_l.draw_path_and_page_number path: current_dir, current: current_page + 1, total: total_pages
|
306
|
+
header_l.draw_path_and_page_number path: current_dir.path, current: current_page + 1, total: total_pages
|
315
307
|
end
|
316
308
|
|
317
309
|
# Sort the loaded files and directories in already given sort order.
|
@@ -367,11 +359,11 @@ module Rfd
|
|
367
359
|
# Copy selected files and directories to the destination.
|
368
360
|
def cp(dest)
|
369
361
|
unless in_zip?
|
370
|
-
src = (m = marked_items).any? ? m.map(&:path) : current_item
|
362
|
+
src = (m = marked_items).any? ? m.map(&:path) : current_item
|
371
363
|
FileUtils.cp_r src, expand_path(dest)
|
372
364
|
else
|
373
365
|
raise 'cping multiple items in .zip is not supported.' if selected_items.size > 1
|
374
|
-
Zip::File.open(current_zip
|
366
|
+
Zip::File.open(current_zip) do |zip|
|
375
367
|
entry = zip.find_entry(selected_items.first.name).dup
|
376
368
|
entry.name, entry.name_length = dest, dest.size
|
377
369
|
zip.instance_variable_get(:@entry_set) << entry
|
@@ -383,7 +375,7 @@ module Rfd
|
|
383
375
|
# Move selected files and directories to the destination.
|
384
376
|
def mv(dest)
|
385
377
|
unless in_zip?
|
386
|
-
src = (m = marked_items).any? ? m.map(&:path) : current_item
|
378
|
+
src = (m = marked_items).any? ? m.map(&:path) : current_item
|
387
379
|
FileUtils.mv src, expand_path(dest)
|
388
380
|
else
|
389
381
|
raise 'mving multiple items in .zip is not supported.' if selected_items.size > 1
|
@@ -402,10 +394,10 @@ module Rfd
|
|
402
394
|
unless in_zip?
|
403
395
|
selected_items.each do |item|
|
404
396
|
name = item.name.gsub from, to
|
405
|
-
FileUtils.mv item
|
397
|
+
FileUtils.mv item, current_dir.join(name) if item.name != name
|
406
398
|
end
|
407
399
|
else
|
408
|
-
Zip::File.open(current_zip
|
400
|
+
Zip::File.open(current_zip) do |zip|
|
409
401
|
selected_items.each do |item|
|
410
402
|
name = item.name.gsub from, to
|
411
403
|
zip.rename item.name, name
|
@@ -439,7 +431,7 @@ module Rfd
|
|
439
431
|
unless in_zip?
|
440
432
|
FileUtils.rm_rf selected_items.map(&:path)
|
441
433
|
else
|
442
|
-
Zip::File.open(current_zip
|
434
|
+
Zip::File.open(current_zip) do |zip|
|
443
435
|
zip.select {|e| selected_items.map(&:name).include? e.to_s}.each do |entry|
|
444
436
|
if entry.name_is_directory?
|
445
437
|
zip.dir.delete entry.to_s
|
@@ -456,9 +448,9 @@ module Rfd
|
|
456
448
|
# Create a new directory.
|
457
449
|
def mkdir(dir)
|
458
450
|
unless in_zip?
|
459
|
-
FileUtils.mkdir_p
|
451
|
+
FileUtils.mkdir_p current_dir.join(dir)
|
460
452
|
else
|
461
|
-
Zip::File.open(current_zip
|
453
|
+
Zip::File.open(current_zip) do |zip|
|
462
454
|
zip.dir.mkdir dir
|
463
455
|
end
|
464
456
|
end
|
@@ -468,11 +460,11 @@ module Rfd
|
|
468
460
|
# Create a new empty file.
|
469
461
|
def touch(filename)
|
470
462
|
unless in_zip?
|
471
|
-
FileUtils.touch
|
463
|
+
FileUtils.touch current_dir.join(filename)
|
472
464
|
else
|
473
|
-
Zip::File.open(current_zip
|
465
|
+
Zip::File.open(current_zip) do |zip|
|
474
466
|
# zip.file.open(filename, 'w') {|_f| } #HAXX this code creates an unneeded temporary file
|
475
|
-
zip.instance_variable_get(:@entry_set) << Zip::Entry.new(current_zip
|
467
|
+
zip.instance_variable_get(:@entry_set) << Zip::Entry.new(current_zip, filename)
|
476
468
|
end
|
477
469
|
end
|
478
470
|
ls
|
@@ -480,7 +472,7 @@ module Rfd
|
|
480
472
|
|
481
473
|
# Create a symlink to the current file or directory.
|
482
474
|
def symlink(name)
|
483
|
-
FileUtils.ln_s current_item
|
475
|
+
FileUtils.ln_s current_item, name
|
484
476
|
ls
|
485
477
|
end
|
486
478
|
|
@@ -498,11 +490,11 @@ module Rfd
|
|
498
490
|
selected_items.each do |item|
|
499
491
|
next if item.symlink?
|
500
492
|
if item.directory?
|
501
|
-
Dir[
|
493
|
+
Dir[item.join('**/**')].each do |file|
|
502
494
|
zipfile.add file.sub("#{current_dir}/", ''), file
|
503
495
|
end
|
504
496
|
else
|
505
|
-
zipfile.add item.name, item
|
497
|
+
zipfile.add item.name, item
|
506
498
|
end
|
507
499
|
end
|
508
500
|
end
|
@@ -514,18 +506,18 @@ module Rfd
|
|
514
506
|
unless in_zip?
|
515
507
|
zips, gzs = selected_items.partition(&:zip?).tap {|z, others| break [z, *others.partition(&:gz?)]}
|
516
508
|
zips.each do |item|
|
517
|
-
FileUtils.mkdir_p
|
518
|
-
Zip::File.open(item
|
509
|
+
FileUtils.mkdir_p current_dir.join(item.basename)
|
510
|
+
Zip::File.open(item) do |zip|
|
519
511
|
zip.each do |entry|
|
520
|
-
FileUtils.mkdir_p File.join(
|
512
|
+
FileUtils.mkdir_p File.join(item.basename, File.dirname(entry.to_s))
|
521
513
|
zip.extract(entry, File.join(item.basename, entry.to_s)) { true }
|
522
514
|
end
|
523
515
|
end
|
524
516
|
end
|
525
517
|
gzs.each do |item|
|
526
|
-
Zlib::GzipReader.open(item
|
518
|
+
Zlib::GzipReader.open(item) do |gz|
|
527
519
|
Gem::Package::TarReader.new(gz) do |tar|
|
528
|
-
dest_dir =
|
520
|
+
dest_dir = current_dir.join (gz.orig_name || item.basename).sub(/\.tar$/, '')
|
529
521
|
tar.each do |entry|
|
530
522
|
dest = nil
|
531
523
|
if entry.full_name == '././@LongLink'
|
@@ -551,7 +543,7 @@ module Rfd
|
|
551
543
|
end
|
552
544
|
end
|
553
545
|
else
|
554
|
-
Zip::File.open(current_zip
|
546
|
+
Zip::File.open(current_zip) do |zip|
|
555
547
|
zip.select {|e| selected_items.map(&:name).include? e.to_s}.each do |entry|
|
556
548
|
FileUtils.mkdir_p File.join(current_zip.dir, current_zip.basename, File.dirname(entry.to_s))
|
557
549
|
zip.extract(entry, File.join(current_zip.dir, current_zip.basename, entry.to_s)) { true }
|
@@ -662,7 +654,7 @@ module Rfd
|
|
662
654
|
else
|
663
655
|
begin
|
664
656
|
tmpdir, tmpfile_name = nil
|
665
|
-
Zip::File.open(current_zip
|
657
|
+
Zip::File.open(current_zip) do |zip|
|
666
658
|
tmpdir = Dir.mktmpdir
|
667
659
|
FileUtils.mkdir_p File.join(tmpdir, File.dirname(current_item.name))
|
668
660
|
tmpfile_name = File.join(tmpdir, current_item.name)
|
@@ -687,7 +679,7 @@ module Rfd
|
|
687
679
|
else
|
688
680
|
begin
|
689
681
|
tmpdir, tmpfile_name = nil
|
690
|
-
Zip::File.open(current_zip
|
682
|
+
Zip::File.open(current_zip) do |zip|
|
691
683
|
tmpdir = Dir.mktmpdir
|
692
684
|
FileUtils.mkdir_p File.join(tmpdir, File.dirname(current_item.name))
|
693
685
|
tmpfile_name = File.join(tmpdir, current_item.name)
|
@@ -720,7 +712,12 @@ module Rfd
|
|
720
712
|
end
|
721
713
|
|
722
714
|
def expand_path(path)
|
723
|
-
File.expand_path path.
|
715
|
+
File.expand_path path.start_with?('/') || path.start_with?('~') ? path : current_dir ? current_dir.join(path) : path
|
716
|
+
end
|
717
|
+
|
718
|
+
def load_item(path)
|
719
|
+
stat = File.lstat path
|
720
|
+
Item.new dir: File.dirname(path), name: File.basename(path), stat: stat, window_width: maxx
|
724
721
|
end
|
725
722
|
|
726
723
|
def osx?
|
data/lib/rfd/commands.rb
CHANGED
@@ -266,8 +266,8 @@ module Rfd
|
|
266
266
|
|
267
267
|
# cd to the upper hierarchy.
|
268
268
|
def del
|
269
|
-
if current_dir != '/'
|
270
|
-
cd File.expand_path(
|
269
|
+
if current_dir.path != '/'
|
270
|
+
cd File.expand_path(current_dir.join(['..'] * times))
|
271
271
|
ls
|
272
272
|
end
|
273
273
|
end
|
data/lib/rfd/item.rb
CHANGED
@@ -20,6 +20,10 @@ module Rfd
|
|
20
20
|
@extname ||= File.extname name
|
21
21
|
end
|
22
22
|
|
23
|
+
def join(*ary)
|
24
|
+
File.join path, ary
|
25
|
+
end
|
26
|
+
|
23
27
|
def full_display_name
|
24
28
|
n = @name.dup
|
25
29
|
n << " -> #{target}" if symlink?
|
@@ -187,6 +191,10 @@ module Rfd
|
|
187
191
|
"#{current_mark}#{mb_ljust(display_name, @window_width - 15)}#{size_or_dir.rjust(13)}"
|
188
192
|
end
|
189
193
|
|
194
|
+
def to_str
|
195
|
+
path
|
196
|
+
end
|
197
|
+
|
190
198
|
def <=>(o)
|
191
199
|
if directory? && !o.directory?
|
192
200
|
1
|
data/lib/rfd/windows.rb
CHANGED
data/rfd.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "rfd"
|
7
|
-
spec.version = '0.
|
7
|
+
spec.version = '0.3.0'
|
8
8
|
spec.authors = ["Akira Matsuda"]
|
9
9
|
spec.email = ["ronnie@dio.jp"]
|
10
10
|
spec.description = 'Ruby on Files & Directories'
|
data/spec/controller_spec.rb
CHANGED
@@ -106,13 +106,13 @@ describe Rfd::Controller do
|
|
106
106
|
before do
|
107
107
|
controller.cd 'dir1'
|
108
108
|
end
|
109
|
-
its(
|
109
|
+
its('current_dir.path') { should == File.join(tmpdir, 'dir1') }
|
110
110
|
|
111
111
|
describe '#popd' do
|
112
112
|
before do
|
113
113
|
controller.popd
|
114
114
|
end
|
115
|
-
its(
|
115
|
+
its('current_dir.path') { should == tmpdir }
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rfd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akira Matsuda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi-ncurses
|