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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfede93c56a43d3df90257d60df31b8934b6891f
4
- data.tar.gz: d5187481f8cb6076394a4337ae85a1799120f2a6
3
+ metadata.gz: d75fe5bcaf9a3f7a14ba0f23fb6fc475c4aaea68
4
+ data.tar.gz: 19fad896ea6eec39e417bdfee2bb0bac28d37e96
5
5
  SHA512:
6
- metadata.gz: 427efc2d0a2a5e6fba9e4ad7de07dc791b335e6b59ca0f21c62dd3760999816d338f58cd233eddcc80c8849232302808911d447878b3cd1824765e872cba5044
7
- data.tar.gz: 4f41128bcd148e16149a4ce40ea1485be8e11b989bcb280a69e31074088e50865488097434ecfaa0daf623218df09723454ee5789f9132c56a4740d69f632105
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 based File explorer, inpsired by the legendary freesoft MS-DOS filer, "FD".
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 environment
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/0bec8345-46c6-45f9-989b-c979b060f5a6/1cffd4c54b30204426251d8561c084a2/res/659f4073-10cc-48f5-a3d2-eb5fe54fba45/skitch.png?resizeSmall&width=768)
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 in:
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 is defaulted to `.`.
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 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.
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
- * **\<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).
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
- * **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.
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
- * **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.
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
- * **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.
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
- * **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`.
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
- * **/**: 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.
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
- * **\<Space\>**: Mark / unmark current file / directory.
103
- * **ctrl-a**: Mark / unmark all file / directories in the current directory.
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
- * **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.
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
- * **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).
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
- * **a**: Change permission of selected items (chmod).
124
- * **w**: Change the owner of of selected items (chown).
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
- * **\<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.
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
- * **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.
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
- * **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.
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
- * **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.
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
- case @direction
310
+ @items, unsorted = items.partition {|i| %w(. ..).include? i.name}
311
+ @items.sort!
312
+ @items += case @direction
312
313
  when nil
313
- @items = items.shift(2) + items.partition(&:directory?).flat_map(&:sort)
314
+ unsorted.partition(&:directory?).flat_map(&:sort)
314
315
  when 'r'
315
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort.reverse}
316
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort.reverse}
316
317
  when 'S', 's'
317
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by {|i| -i.size}}
318
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by {|i| -i.size}}
318
319
  when 'Sr', 'sr'
319
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:size)}
320
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:size)}
320
321
  when 't'
321
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.mtime <=> x.mtime}}
322
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.mtime <=> x.mtime}}
322
323
  when 'tr'
323
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:mtime)}
324
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:mtime)}
324
325
  when 'c'
325
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.ctime <=> x.ctime}}
326
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.ctime <=> x.ctime}}
326
327
  when 'cr'
327
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:ctime)}
328
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:ctime)}
328
329
  when 'u'
329
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.atime <=> x.atime}}
330
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.atime <=> x.atime}}
330
331
  when 'ur'
331
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:atime)}
332
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort_by(&:atime)}
332
333
  when 'e'
333
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.extname <=> x.extname}}
334
+ unsorted.partition(&:directory?).flat_map {|arr| arr.sort {|x, y| y.extname <=> x.extname}}
334
335
  when 'er'
335
- @items = items.shift(2) + items.partition(&:directory?).flat_map {|arr| arr.sort_by(&:extname)}
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?
@@ -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?
@@ -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.3.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'
@@ -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.3.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-13 00:00:00.000000000 Z
11
+ date: 2013-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi-ncurses