rfd 0.3.0 → 0.4.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 +67 -50
- data/lib/rfd.rb +44 -15
- data/lib/rfd/commands.rb +16 -1
- data/rfd.gemspec +1 -1
- data/spec/controller_spec.rb +41 -0
- 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: d75fe5bcaf9a3f7a14ba0f23fb6fc475c4aaea68
|
4
|
+
data.tar.gz: 19fad896ea6eec39e417bdfee2bb0bac28d37e96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 778f65ab177d37b688ea9f7dbe678ab3fa5b656cba93096387689cf7521c305f29b6de971a2e1de8f1cdd90918fba0776763df7573c41542adba52f8c4806ff7
|
7
|
+
data.tar.gz: e3d23535bdc25262fa98c802c8a526a76dd25d585722dac423b601ce5c60f7dbab738d20307e76becb7e9133637bdae00004ee524885c305391182c80577161f
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# rfd (Ruby on Files & Directories)
|
2
2
|
|
3
|
-
rfd is a terminal
|
3
|
+
rfd is a terminal-based filesystem explorer, inpsired by the legendary freesoft MS-DOS filer, "FD".
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -12,42 +12,43 @@ rfd is a terminal based File explorer, inpsired by the legendary freesoft MS-DOS
|
|
12
12
|
* NCurses
|
13
13
|
* (FFI)
|
14
14
|
|
15
|
-
## Tested
|
15
|
+
## Tested environments
|
16
16
|
|
17
|
-
Mac OS X Mountain Lion, Mac OS X Lion
|
17
|
+
Mac OS X Mountain Lion, Mac OS X Lion, Ubuntu 13.04
|
18
18
|
|
19
19
|
## Screenshot
|
20
20
|
|
21
|
-
![screenshot](https://www.evernote.com/shard/s20/sh/
|
21
|
+
![screenshot](https://www.evernote.com/shard/s20/sh/a0a275ee-39b5-4ba4-9374-8534f4ee2a24/377c504f45f17a75eb2ea12bd015b6ee/deep/0/rfd_screenshot.png)
|
22
22
|
|
23
23
|
## Start Me Up
|
24
24
|
|
25
|
-
Open up your terminal and type
|
25
|
+
Open up your terminal and type:
|
26
26
|
|
27
27
|
% rfd
|
28
28
|
|
29
|
-
You can also pass in a starting directory name, which
|
29
|
+
You can also pass in a starting directory name, which defaults to `.`.
|
30
30
|
|
31
31
|
% rfd ~/src/rails
|
32
32
|
|
33
33
|
## Commands
|
34
34
|
|
35
|
-
You can
|
35
|
+
You can send commands to rfd by pressing some chars on your keyboard, just like Vim.
|
36
|
+
If you're unfamiliar with this sort of command system, I recommend you to play with `vimtutor` before you go any further.
|
36
37
|
|
37
38
|
All available commands in rfd are defined as Ruby methods here. https://github.com/amatsuda/rfd/tree/master/lib/rfd/commands.rb
|
38
39
|
|
39
40
|
### Changing the current directory
|
40
41
|
|
41
|
-
*
|
42
|
-
*
|
43
|
-
*
|
42
|
+
* `<Enter>`: cd into the directory where the cursor is on.
|
43
|
+
* `<Delete>` (or \<Backspace\> on your keyboard, probably?): Go up to the upper directory (cd ..).
|
44
|
+
* `-`: Get back to where you once belonged (popd).
|
44
45
|
|
45
46
|
### Moving the cursor
|
46
47
|
|
47
|
-
*
|
48
|
-
*
|
49
|
-
*
|
50
|
-
*
|
48
|
+
* `j`: Move down.
|
49
|
+
* `k`: Move up.
|
50
|
+
* `h`: Move left. At the leftmost column, move to the right end column at the previous page.
|
51
|
+
* `l`: Move right. At the rightmost column, move to the left end column at the next page.
|
51
52
|
|
52
53
|
### The {count} parameter
|
53
54
|
|
@@ -56,31 +57,31 @@ For example, `3j` moves the cursor to 3 lines below, and `999k` will take your c
|
|
56
57
|
|
57
58
|
### Jumping the cursor
|
58
59
|
|
59
|
-
*
|
60
|
-
*
|
61
|
-
*
|
60
|
+
* `H`: Move to the top of the current page.
|
61
|
+
* `M`: Move to the middle of the current page.
|
62
|
+
* `L`: Move to the bottom of the current page.
|
62
63
|
|
63
64
|
### Switching the page
|
64
65
|
|
65
|
-
*
|
66
|
-
*
|
67
|
-
*
|
68
|
-
*
|
66
|
+
* `ctrl-n, ctrl-f`: Move to the top of the next page.
|
67
|
+
* `ctrl-p, ctrl-b`: Move to the top of the previous page.
|
68
|
+
* `g`: Move to the top of the first page.
|
69
|
+
* `G`: Move to the bottom of the last page.
|
69
70
|
|
70
71
|
### Finding a file / directory
|
71
72
|
|
72
73
|
You can find a file by typing the first letter of it immediately after the find commands.
|
73
74
|
|
74
|
-
*
|
75
|
-
*
|
76
|
-
*
|
75
|
+
* `f{char}`: Move to the next file / directory of which name starts with the given char.
|
76
|
+
* `F{char}`: Move to the previous file / directory of which name starts with the given char.
|
77
|
+
* `n`: Repeat the last `f` or `F`.
|
77
78
|
|
78
79
|
### Searching, sorting
|
79
80
|
|
80
81
|
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
|
|
82
|
-
*
|
83
|
-
*
|
83
|
+
* `/`: Grep the current directory with the given parameter. The parameter will be interpreted as Ruby Regexp (e.g. `.*\.rb$`).
|
84
|
+
* `s`: Sort files / directories in the current directory in the given order.
|
84
85
|
* (none): by name
|
85
86
|
* r : reverse order by name
|
86
87
|
* s, S : order by file size
|
@@ -99,41 +100,48 @@ For commands like these that require a parameter string, type the parameter in t
|
|
99
100
|
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
101
|
The mark is drawn as a `*` char on the left of each file / directory name.
|
101
102
|
|
102
|
-
*
|
103
|
-
*
|
103
|
+
* `<Space>`: Mark / unmark current file / directory.
|
104
|
+
* `ctrl-a`: Mark / unmark all file / directories in the current directory.
|
104
105
|
|
105
106
|
### Manipulating files / directories
|
106
107
|
|
107
108
|
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
|
|
109
|
-
*
|
110
|
-
*
|
111
|
-
*
|
112
|
-
*
|
113
|
-
*
|
110
|
+
* `c`: Copy selected items (cp).
|
111
|
+
* `m`: Move selected items (mv).
|
112
|
+
* `d`: Move selected items into the Trash.
|
113
|
+
* `D`: Delete selected items.
|
114
|
+
* `r`: Rename selected items. This command takes a sed-like argument separated by a `/`. For example, changing all .html files' extention to .html.erb could be done by `\.html$/.html.erb`.
|
115
|
+
|
116
|
+
### Yank and Paste
|
117
|
+
|
118
|
+
`y` & `p` works just like Windows-c & Windows-v on explorer.exe.
|
119
|
+
|
120
|
+
* `y`: Yank selected items.
|
121
|
+
* `p`: Paste yanked items into the directory on which the cursor is, or into the current directory.
|
114
122
|
|
115
123
|
### Creating files / directories
|
116
124
|
|
117
|
-
*
|
118
|
-
*
|
119
|
-
*
|
125
|
+
* `t`: Create a new file (touch).
|
126
|
+
* `K`: Creat a new directory (mkdir).
|
127
|
+
* `S`: Create new symlink to the current file / directory (ln -s).
|
120
128
|
|
121
129
|
### Attributes
|
122
130
|
|
123
|
-
*
|
124
|
-
*
|
131
|
+
* `a`: Change permission of selected items (chmod). Takes chmod-like argument such as `g+w`, `755`.
|
132
|
+
* `w`: Change the owner of of selected items (chown). Takes chown-like argument such as `alice`, `nobody:nobody`.
|
125
133
|
|
126
134
|
### Viewing, Editing, Opening
|
127
135
|
|
128
|
-
*
|
129
|
-
*
|
130
|
-
*
|
131
|
-
*
|
136
|
+
* `<Enter>`: View current file with the system $VIEWER such as `less`.
|
137
|
+
* `v`: View current file with the system $VIEWER such as `less`.
|
138
|
+
* `e`: Edit current file with the system $EDITOR such as `vim`.
|
139
|
+
* `o`: Send the `open` command.
|
132
140
|
|
133
141
|
### Manipulating archives
|
134
142
|
|
135
|
-
*
|
136
|
-
*
|
143
|
+
* `u`: Unarchive .zip, .gz, or .tar.gz file into the current directory.
|
144
|
+
* `z`: Archive selected items into a .zip file with the given name.
|
137
145
|
|
138
146
|
### Handling .zip files
|
139
147
|
|
@@ -141,15 +149,24 @@ You can `cd` into a .zip file as if it's just a directory, then unarchive select
|
|
141
149
|
|
142
150
|
### Splitting columns
|
143
151
|
|
144
|
-
*
|
152
|
+
* `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.
|
153
|
+
|
154
|
+
### Using mouse
|
155
|
+
|
156
|
+
Mouse is available if your terminal supports it. You can move the cursor by clicking on a file / directory. Double clicking on a file / directory is equivalent to pressing \<Enter\> on it.
|
145
157
|
|
146
158
|
### Misc
|
147
159
|
|
148
|
-
*
|
149
|
-
*
|
150
|
-
*
|
151
|
-
*
|
152
|
-
*
|
160
|
+
* `ctrl-l`: Refresh the whole screen.
|
161
|
+
* `C`: Copy selected items' paths to the clipboard.
|
162
|
+
* `O`: Open a new terminal window at the current directory.
|
163
|
+
* `!`: Execute a shell command.
|
164
|
+
* `q`: Quit the app.
|
165
|
+
|
166
|
+
## How to manually execute a command, or how the commands are executed
|
167
|
+
|
168
|
+
By pressing `:`, you can enter the command-line mode. Any string given in the command line after `:` will be executed as Ruby method call in the `Controller` instance.
|
169
|
+
For instance, `:j` brings your cursor down, `:mkdir foo` makes a directory named "foo". And `:q!` of course works as you might expect, since `q!` method is implemented so.
|
153
170
|
|
154
171
|
## Contributing
|
155
172
|
|
data/lib/rfd.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'ffi-ncurses'
|
2
|
-
require 'ffi-ncurses/mouse'
|
3
2
|
Curses = FFI::NCurses
|
4
3
|
require 'fileutils'
|
5
4
|
require 'tmpdir'
|
@@ -53,7 +52,7 @@ module Rfd
|
|
53
52
|
@header_l = HeaderLeftWindow.new
|
54
53
|
@header_r = HeaderRightWindow.new
|
55
54
|
@command_line = CommandLineWindow.new
|
56
|
-
@direction, @dir_history, @last_command, @times = nil, [], nil, nil
|
55
|
+
@direction, @dir_history, @last_command, @times, @yanked_items = nil, [], nil, nil, nil
|
57
56
|
end
|
58
57
|
|
59
58
|
# The main loop.
|
@@ -308,31 +307,33 @@ module Rfd
|
|
308
307
|
|
309
308
|
# Sort the loaded files and directories in already given sort order.
|
310
309
|
def sort_items_according_to_current_direction
|
311
|
-
|
310
|
+
@items, unsorted = items.partition {|i| %w(. ..).include? i.name}
|
311
|
+
@items.sort!
|
312
|
+
@items += case @direction
|
312
313
|
when nil
|
313
|
-
|
314
|
+
unsorted.partition(&:directory?).flat_map(&:sort)
|
314
315
|
when 'r'
|
315
|
-
|
316
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort.reverse}
|
316
317
|
when 'S', 's'
|
317
|
-
|
318
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by {|i| -i.size}}
|
318
319
|
when 'Sr', 'sr'
|
319
|
-
|
320
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:size)}
|
320
321
|
when 't'
|
321
|
-
|
322
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.mtime <=> x.mtime}}
|
322
323
|
when 'tr'
|
323
|
-
|
324
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:mtime)}
|
324
325
|
when 'c'
|
325
|
-
|
326
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.ctime <=> x.ctime}}
|
326
327
|
when 'cr'
|
327
|
-
|
328
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:ctime)}
|
328
329
|
when 'u'
|
329
|
-
|
330
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.atime <=> x.atime}}
|
330
331
|
when 'ur'
|
331
|
-
|
332
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:atime)}
|
332
333
|
when 'e'
|
333
|
-
|
334
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.extname <=> x.extname}}
|
334
335
|
when 'er'
|
335
|
-
|
336
|
+
unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:extname)}
|
336
337
|
end
|
337
338
|
items.each.with_index {|item, index| item.index = index}
|
338
339
|
end
|
@@ -476,6 +477,34 @@ module Rfd
|
|
476
477
|
ls
|
477
478
|
end
|
478
479
|
|
480
|
+
# Yank selected file / directory names.
|
481
|
+
def yank
|
482
|
+
@yanked_items = selected_items
|
483
|
+
end
|
484
|
+
|
485
|
+
# Paste yanked files / directories here.
|
486
|
+
def paste
|
487
|
+
if @yanked_items
|
488
|
+
if current_item.directory?
|
489
|
+
FileUtils.cp_r @yanked_items.map(&:path), current_item
|
490
|
+
else
|
491
|
+
@yanked_items.each do |item|
|
492
|
+
if items.include? item
|
493
|
+
i = 1
|
494
|
+
while i += 1
|
495
|
+
new_item = Item.new dir: current_dir, name: "#{item.basename}_#{i}#{item.extname}", stat: item.stat, window_width: maxx
|
496
|
+
break unless File.exist? new_item.path
|
497
|
+
end
|
498
|
+
FileUtils.cp_r item, new_item
|
499
|
+
else
|
500
|
+
FileUtils.cp_r item, current_dir
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
ls
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
479
508
|
# Copy selected files and directories' path into clipboard on OSX.
|
480
509
|
def clipboard
|
481
510
|
IO.popen('pbcopy', 'w') {|f| f << selected_items.map(&:path).join(' ')} if osx?
|
data/lib/rfd/commands.rb
CHANGED
@@ -73,11 +73,21 @@ module Rfd
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
# Paste yanked files / directories into the directory on which the cursor is, or into the current directory.
|
77
|
+
def p
|
78
|
+
paste
|
79
|
+
end
|
80
|
+
|
76
81
|
# "q"uit the app.
|
77
82
|
def q
|
78
83
|
raise StopIteration if ask 'Are you sure want to exit? (y/n)'
|
79
84
|
end
|
80
85
|
|
86
|
+
# "q"uit the app!
|
87
|
+
def q!
|
88
|
+
raise StopIteration
|
89
|
+
end
|
90
|
+
|
81
91
|
# "r"ename selected files and directories.
|
82
92
|
def r
|
83
93
|
process_command_line preset_command: 'rename'
|
@@ -108,6 +118,11 @@ module Rfd
|
|
108
118
|
process_command_line preset_command: 'chown'
|
109
119
|
end
|
110
120
|
|
121
|
+
# "y"ank selected file / directory names.
|
122
|
+
def y
|
123
|
+
yank
|
124
|
+
end
|
125
|
+
|
111
126
|
# Archive selected files and directories into a "z"ip file.
|
112
127
|
def z
|
113
128
|
process_command_line preset_command: 'zip'
|
@@ -159,7 +174,7 @@ module Rfd
|
|
159
174
|
|
160
175
|
# "O"pen terminal here.
|
161
176
|
def O
|
162
|
-
dir = current_item.directory? ? current_item.path : current_dir
|
177
|
+
dir = current_item.directory? ? current_item.path : current_dir.path
|
163
178
|
system %Q[osascript -e 'tell app "Terminal"
|
164
179
|
do script "cd #{dir}"
|
165
180
|
end tell'] if osx?
|
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.4.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
@@ -305,6 +305,47 @@ describe Rfd::Controller do
|
|
305
305
|
it { should be_symlink File.join(tmpdir, 'aaa') }
|
306
306
|
end
|
307
307
|
|
308
|
+
describe '#yank' do
|
309
|
+
before do
|
310
|
+
controller.find '.file1'
|
311
|
+
controller.toggle_mark
|
312
|
+
controller.find 'dir3'
|
313
|
+
controller.toggle_mark
|
314
|
+
controller.yank
|
315
|
+
end
|
316
|
+
it 'should be yanked' do
|
317
|
+
controller.instance_variable_get(:@yanked_items).map(&:name).should =~ %w(.file1 dir3)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
describe '#paste' do
|
322
|
+
before do
|
323
|
+
controller.find '.file1'
|
324
|
+
controller.toggle_mark
|
325
|
+
controller.find 'dir3'
|
326
|
+
controller.toggle_mark
|
327
|
+
controller.yank
|
328
|
+
end
|
329
|
+
context 'when the cursor is on a directory' do
|
330
|
+
before do
|
331
|
+
controller.find 'dir1'
|
332
|
+
controller.paste
|
333
|
+
end
|
334
|
+
subject { File }
|
335
|
+
it { should be_exist File.join(tmpdir, 'dir1', '.file1') }
|
336
|
+
it { should be_exist File.join(tmpdir, 'dir1', 'dir3') }
|
337
|
+
end
|
338
|
+
context 'when the cursor is on a file' do
|
339
|
+
before do
|
340
|
+
controller.find 'file2'
|
341
|
+
controller.paste
|
342
|
+
end
|
343
|
+
subject { File }
|
344
|
+
it { should be_exist File.join(tmpdir, '.file1_2') }
|
345
|
+
it { should be_exist File.join(tmpdir, 'dir3_2') }
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
308
349
|
describe '#pbcopy' do
|
309
350
|
before do
|
310
351
|
controller.find '.file1'
|
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.4.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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi-ncurses
|