rfd 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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