cetus 0.1.21 → 0.1.22

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cetus +1040 -711
  3. data/cetus.gemspec +10 -10
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e35fd2792cfb584909c6ddadfaeb6b30e92ff09b4f838585a85f8de977c333e
4
- data.tar.gz: f2b2f7e300a593f9ba2973d8451f4148f9057c5bc4680ad3c9ac77075ae6f19e
3
+ metadata.gz: 040badb6cd9462f5d5a2fe5f5b5e320c03fbbd80984d71e526c500bdd0781822
4
+ data.tar.gz: c48f55c076c32815785341986791e680b990b3fbf3bf1d519835b70331790a52
5
5
  SHA512:
6
- metadata.gz: 6ab765cb054741e0d6951040d7b655d7235d1c583646c96f8bd1b12d74778fd05a735b0a3864e3f87e4b1652316a3bef6b966745bba3d3efe113d46cde306826
7
- data.tar.gz: 1d723a6b666671544a081e426ecf34df28a6fa02bd158fed08f9c89873dbef12a050f66caf286f3231847aa622783abcb41da1285ce0b75104a9fe999658ee1c
6
+ metadata.gz: a7a6655724e7b3e5e46d20d8bf0cc90a3032aacdca0dbbbb4d4348c87c845e8a974574f2530781ff44a7860ed1d3f9eb8e0c5caa952411963106ac3622fc39f9
7
+ data.tar.gz: c61c40989b45d3e4c2ecc04d6a04ceae2722fbf3d0d582e37fb86b4e00b5d78582c16edd18fef1c58ad86e3c20038d4ae3b5455270c7da25dba2bcdb19f27c75
data/bin/cetus CHANGED
@@ -1,19 +1,20 @@
1
1
  #!/usr/bin/env ruby
2
- # ----------------------------------------------------------------------------- #
2
+ # --------------------------------------------------------------------------- #
3
3
  # File: cetus
4
4
  # Description: Fast file navigation, a tiny version of zfm
5
5
  # but with a different indexing mechanism
6
6
  # Author: rkumar http://github.com/rkumar/cetus/
7
7
  # Date: 2013-02-17 - 17:48
8
8
  # License: GPL
9
- # Last update: 2019-03-04 23:50
10
- # ----------------------------------------------------------------------------- #
11
- # cetus.rb Copyright (C) 2012-2013 rahul kumar
9
+ # Last update: 2019-03-10 15:07
10
+ # --------------------------------------------------------------------------- #
11
+ # cetus.rb Copyright (C) 2012-2019 rahul kumar
12
12
  # == CHANGELOG
13
13
  # 2019-02-20 - added smcup and rmcup so alt-screen is used. works a bit
14
14
  # 2019-03-04 - change clear to go to 0,0 and clear down to reduce pollution
15
15
  # 2019-03-04 - changed quit to q (earlier Q)
16
16
  # 2019-03-04 - first dirs then files
17
+ # 2019-03-10 - changing selected_files to have fullpath
17
18
  # == TODO
18
19
  # To dirs add GEMHOME RUBYLIB PYTHONILB or PYTHONPATH,
19
20
  # Make rubygem aware : gemspec or Gemfile the expand lib and bin
@@ -23,10 +24,9 @@ require 'readline'
23
24
  require 'io/wait'
24
25
  # http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html
25
26
  require 'shellwords'
27
+ # https://docs.ruby-lang.org/en/2.6.0/FileUtils.html
26
28
  require 'fileutils'
27
29
  # -- requires 1.9.3 for io/wait
28
- # -- cannot do with Highline since we need a timeout on wait,
29
- # not sure if HL can do that
30
30
 
31
31
  ## INSTALLATION
32
32
  # copy into PATH
@@ -35,113 +35,119 @@ require 'fileutils'
35
35
 
36
36
  # 2019-02-20 - added so alt-screen is used
37
37
  system 'tput smcup'
38
- VERSION = '0.1.21.0'
38
+ VERSION = '0.1.22.0'.freeze
39
39
  O_CONFIG = true
40
- CONFIG_FILE = '~/.lyrainfo'
40
+ # CONFIG_FILE = '~/.lyrainfo'.freeze
41
+ CONFIG_FILE = '~/.config/cetus/conf.yml'.freeze
41
42
 
42
43
  $bindings = {}
43
44
  $bindings = {
44
- '`' => 'main_menu',
45
- '=' => 'toggle_menu',
46
- '!' => 'command_mode',
47
- '@' => 'selection_mode_toggle',
45
+ '`' => 'main_menu',
46
+ '=' => 'toggle_menu',
47
+ '!' => 'command_mode',
48
+ '@' => 'selection_mode_toggle',
48
49
  'M-a' => 'select_all',
49
50
  'M-A' => 'unselect_all',
50
- ',' => 'goto_parent_dir',
51
- '+' => 'goto_dir',
52
- '.' => 'pop_dir',
53
- ':' => 'subcommand',
54
- "'" => 'goto_bookmark',
55
- '/' => 'enter_regex',
56
- 'M-p' => 'prev_page',
57
- 'M-n' => 'next_page',
58
- 'SPACE' => 'next_page',
59
- 'M-f' => 'select_visited_files',
60
- 'M-d' => 'select_used_dirs',
61
- 'M-b' => 'select_bookmarks',
62
- 'M-m' => 'create_bookmark',
63
- 'M-M' => 'show_marks',
64
- 'C-c' => 'escape',
65
- 'ESCAPE' => 'escape',
66
- 'TAB' => 'views',
67
- 'C-i' => 'views',
68
- '?' => 'dirtree',
69
- 'ENTER' => 'select_current',
70
- 'D' => 'delete_file',
71
- 'M' => 'file_actions most',
72
- 'q' => 'quit_command', # was Q now q 2019-03-04 -
73
- #"RIGHT" => "column_next",
74
- 'RIGHT' => 'select_current', # changed 2018-03-12 - for faster navigation
75
- 'LEFT' => 'goto_parent_dir', # changed on 2018-03-12 - earlier column_next 1
76
- ']' => 'column_next',
77
- '[' => 'column_next 1',
78
- 'C-x' => 'file_actions',
79
- 'M--' => 'columns_incdec -1',
80
- 'M-+' => 'columns_incdec 1',
81
- 'S' => 'command_file list y ls -lh',
82
- 'L' => 'command_file Page n less',
83
- 'C-d' => 'cursor_scroll_dn',
84
- 'C-b' => 'cursor_scroll_up',
85
- 'UP' => 'cursor_up',
86
- 'DOWN' => 'cursor_dn',
51
+ ',' => 'goto_parent_dir',
52
+ '~' => 'goto_home_dir',
53
+ '-' => 'goto_previous_dir', # 2019-03-07 - added. like 'cd ='
54
+ '+' => 'goto_dir', # 2019-03-07 - TODO: change binding
55
+ '.' => 'pop_dir',
56
+ ':' => 'subcommand',
57
+ "'" => 'goto_bookmark',
58
+ '/' => 'enter_regex',
59
+ 'M-p' => 'prev_page',
60
+ 'M-n' => 'next_page',
61
+ 'SPACE' => 'next_page',
62
+ 'M-f' => 'select_visited_files',
63
+ 'M-d' => 'select_used_dirs',
64
+ 'M-b' => 'select_bookmarks',
65
+ 'M-m' => 'create_bookmark',
66
+ 'M-M' => 'show_marks',
67
+ 'C-c' => 'escape',
68
+ 'ESCAPE' => 'escape',
69
+ 'TAB' => 'views',
70
+ 'C-i' => 'views',
71
+ '?' => 'dirtree',
72
+ 'ENTER' => 'select_current',
73
+ 'C-p' => 'page_current',
74
+ 'C-e' => 'edit_current',
75
+ 'C-o' => 'edit_current',
76
+ 'D' => 'delete_file',
77
+ 'M' => 'file_actions most',
78
+ 'q' => 'quit_command', # was Q now q 2019-03-04 -
79
+ # "RIGHT" => "column_next",
80
+ 'RIGHT' => 'select_current', # changed 2018-03-12 - for faster navigation
81
+ 'LEFT' => 'goto_parent_dir', # changed on 2018-03-12 - earlier column_next 1
82
+ ']' => 'column_next',
83
+ '[' => 'column_next 1',
84
+ 'C-x' => 'file_actions',
85
+ 'M--' => 'columns_incdec -1',
86
+ 'M-+' => 'columns_incdec 1',
87
+ 'S' => 'command_file list y ls -lh',
88
+ 'L' => 'command_file Page n less',
89
+ 'C-d' => 'cursor_scroll_dn',
90
+ 'C-b' => 'cursor_scroll_up',
91
+ 'UP' => 'cursor_up',
92
+ 'DOWN' => 'cursor_dn',
87
93
  'C-SPACE' => 'visual_mode_toggle',
88
94
 
89
- 'M-?' => 'print_help',
90
- 'F1' => 'print_help',
91
- 'F2' => 'child_dirs',
92
- 'F3' => 'dirtree',
93
- 'F4' => 'tree',
94
- 'S-F1' => 'dirtree',
95
- 'S-F2' => 'tree'
95
+ 'M-?' => 'print_help',
96
+ 'F1' => 'print_help',
97
+ 'F2' => 'child_dirs',
98
+ 'F3' => 'dirtree',
99
+ 'F4' => 'tree',
100
+ 'S-F1' => 'dirtree',
101
+ 'S-F2' => 'tree'
96
102
 
97
103
  }
98
104
 
99
105
  ## clean this up a bit, copied from shell program and macro'd
100
- $kh=Hash.new
101
- $kh["OP"]="F1"
102
- $kh[""]="UP"
103
- $kh["[5~"]="PGUP"
104
- $kh['']="ESCAPE"
105
- KEY_PGDN="[6~"
106
- KEY_PGUP="[5~"
106
+ $kh = {}
107
+ $kh["\eOP"] = 'F1'
108
+ $kh["\e[A"] = 'UP'
109
+ $kh["\e[5~"] = 'PGUP'
110
+ $kh[''] = 'ESCAPE'
111
+ KEY_PGDN = "\e[6~".freeze
112
+ KEY_PGUP = "\e[5~".freeze
107
113
  ## I needed to replace the O with a [ for this to work
108
114
  # in Vim Home comes as ^[OH whereas on the command line it is correct as ^[[H
109
- KEY_HOME=''
110
- KEY_END=""
111
- KEY_F1="OP"
112
- KEY_UP=""
113
- KEY_DOWN=""
114
-
115
- $kh[KEY_PGDN]="PgDn"
116
- $kh[KEY_PGUP]="PgUp"
117
- $kh[KEY_HOME]="Home"
118
- $kh[KEY_END]="End"
119
- $kh[KEY_F1]="F1"
120
- $kh[KEY_UP]="UP"
121
- $kh[KEY_DOWN]="DOWN"
122
- KEY_LEFT=''
123
- KEY_RIGHT=''
124
- $kh["OQ"]="F2"
125
- $kh["OR"]="F3"
126
- $kh["OS"]="F4"
127
- $kh[KEY_LEFT] = "LEFT"
128
- $kh[KEY_RIGHT]= "RIGHT"
129
- KEY_F5='[15~'
130
- KEY_F6='[17~'
131
- KEY_F7='[18~'
132
- KEY_F8='[19~'
133
- KEY_F9='[20~'
134
- KEY_F10='[21~'
135
- KEY_S_F1=''
136
- $kh[KEY_F5]="F5"
137
- $kh[KEY_F6]="F6"
138
- $kh[KEY_F7]="F7"
139
- $kh[KEY_F8]="F8"
140
- $kh[KEY_F9]="F9"
141
- $kh[KEY_F10]="F10"
115
+ KEY_HOME = ''.freeze
116
+ KEY_END = "\e[F".freeze
117
+ KEY_F1 = "\eOP".freeze
118
+ KEY_UP = "\e[A".freeze
119
+ KEY_DOWN = "\e[B".freeze
120
+
121
+ $kh[KEY_PGDN] = 'PgDn'
122
+ $kh[KEY_PGUP] = 'PgUp'
123
+ $kh[KEY_HOME] = 'Home'
124
+ $kh[KEY_END] = 'End'
125
+ $kh[KEY_F1] = 'F1'
126
+ $kh[KEY_UP] = 'UP'
127
+ $kh[KEY_DOWN] = 'DOWN'
128
+ KEY_LEFT = ''.freeze
129
+ KEY_RIGHT = ''.freeze
130
+ $kh["\eOQ"] = 'F2'
131
+ $kh["\eOR"] = 'F3'
132
+ $kh["\eOS"] = 'F4'
133
+ $kh[KEY_LEFT] = 'LEFT'
134
+ $kh[KEY_RIGHT] = 'RIGHT'
135
+ KEY_F5 = '[15~'.freeze
136
+ KEY_F6 = '[17~'.freeze
137
+ KEY_F7 = '[18~'.freeze
138
+ KEY_F8 = '[19~'.freeze
139
+ KEY_F9 = '[20~'.freeze
140
+ KEY_F10 = '[21~'.freeze
141
+ KEY_S_F1 = ''.freeze
142
+ $kh[KEY_F5] = 'F5'
143
+ $kh[KEY_F6] = 'F6'
144
+ $kh[KEY_F7] = 'F7'
145
+ $kh[KEY_F8] = 'F8'
146
+ $kh[KEY_F9] = 'F9'
147
+ $kh[KEY_F10] = 'F10'
142
148
  # testing out shift+Function. these are the codes my kb generates
143
- $kh[KEY_S_F1]="S-F1"
144
- $kh['']="S-F2"
149
+ $kh[KEY_S_F1] = 'S-F1'
150
+ $kh[''] = 'S-F2'
145
151
 
146
152
  def old_clear_screen
147
153
  system 'clear'
@@ -169,16 +175,16 @@ end
169
175
  # copied from fff
170
176
  # Call before shelling to editor pager and when exiting
171
177
  def reset_terminal
172
- # Reset the terminal to a useable state (undo all changes).
173
- # '\e[?7h': Re-enable line wrapping.
174
- # '\e[?25h': Unhide the cursor.
175
- # '\e[2J': Clear the terminal.
176
- # '\e[;r': Set the scroll region to its default value.
177
- # Also sets cursor to (0,0).
178
- print "\e[?7h\e[?25h\e[2J\e[;r"
178
+ # Reset the terminal to a useable state (undo all changes).
179
+ # '\e[?7h': Re-enable line wrapping.
180
+ # '\e[?25h': Unhide the cursor.
181
+ # '\e[2J': Clear the terminal.
182
+ # '\e[;r': Set the scroll region to its default value.
183
+ # Also sets cursor to (0,0).
184
+ print "\e[?7h\e[?25h\e[2J\e[;r"
179
185
 
180
- # Show user input.
181
- system 'stty echo'
186
+ # Show user input.
187
+ system 'stty echo'
182
188
  end
183
189
 
184
190
  # copied from fff
@@ -197,107 +203,115 @@ def setup_terminal
197
203
  system 'stty -echo'
198
204
  end
199
205
 
206
+ # wrap readline so C-c can be ignored, but blank is taken as default
207
+ def readline
208
+ begin
209
+ target = Readline.readline('>', true)
210
+ rescue Interrupt
211
+ return nil
212
+ end
213
+ target
214
+ end
215
+
200
216
  ## get a character from user and return as a string
201
217
  # Adapted from:
202
- #http://stackoverflow.com/questions/174933/how-to-get-a-single-character-without-pressing-enter/8274275#8274275
218
+ # http://stackoverflow.com/questions/174933/how-to-get-a-single-character-without-pressing-enter/8274275#8274275
203
219
  # Need to take complex keys and matc against a hash.
204
220
  def get_char
205
- begin
206
- system('stty raw -echo 2>/dev/null') # turn raw input on
207
- c = nil
208
- #if $stdin.ready?
209
- c = $stdin.getc
210
- cn = c.ord
211
- return 'ENTER' if cn == 10 || cn == 13
212
- return 'BACKSPACE' if cn == 127
213
- return 'C-SPACE' if cn == 0
214
- return 'SPACE' if cn == 32
215
- # next does not seem to work, you need to bind C-i
216
- return 'TAB' if cn == 8
217
-
218
- if cn >= 0 && cn < 27
219
- x = cn + 96
220
- return "C-#{x.chr}"
221
- end
222
- if c == ''
223
- buff=c.chr
224
- while true
225
- k = nil
226
- if $stdin.ready?
227
- k = $stdin.getc
228
- #puts "got #{k}"
229
- buff += k.chr
230
- else
231
- x = $kh[buff]
232
- return x if x
233
-
234
- # puts "returning with #{buff}"
235
- if buff.size == 2
236
- ## possibly a meta/alt char
237
- k = buff[-1]
238
- return "M-#{k.chr}"
239
- end
240
- return buff
221
+ system('stty raw -echo 2>/dev/null') # turn raw input on
222
+ c = nil
223
+ # if $stdin.ready?
224
+ c = $stdin.getc
225
+ cn = c.ord
226
+ return 'ENTER' if cn == 10 || cn == 13
227
+ return 'BACKSPACE' if cn == 127
228
+ return 'C-SPACE' if cn == 0
229
+ return 'SPACE' if cn == 32
230
+ # next does not seem to work, you need to bind C-i
231
+ return 'TAB' if cn == 8
232
+
233
+ if cn >= 0 && cn < 27
234
+ x = cn + 96
235
+ return "C-#{x.chr}"
236
+ end
237
+ if c == ''
238
+ buff = c.chr
239
+ loop do
240
+ k = nil
241
+ if $stdin.ready?
242
+ k = $stdin.getc
243
+ # puts "got #{k}"
244
+ buff += k.chr
245
+ else
246
+ x = $kh[buff]
247
+ return x if x
248
+
249
+ # puts "returning with #{buff}"
250
+ if buff.size == 2
251
+ ## possibly a meta/alt char
252
+ k = buff[-1]
253
+ return "M-#{k.chr}"
241
254
  end
255
+ return buff
242
256
  end
243
257
  end
244
- #end
245
- return c.chr if c
246
- ensure
247
- #system "stty -raw echo" # turn raw input off
248
- system('stty -raw echo 2>/dev/null') # turn raw input on
249
258
  end
259
+ # end
260
+ return c.chr if c
261
+ ensure
262
+ # system "stty -raw echo" # turn raw input off
263
+ system('stty -raw echo 2>/dev/null') # turn raw input on
250
264
  end
251
265
 
252
266
  ## GLOBALS
253
- #$IDX="123456789abcdefghijklmnoprstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
254
- #$IDX="abcdefghijklmnopqrstuvwxy"
255
- $IDX=('a'..'y').to_a
267
+ # $IDX="123456789abcdefghijklmnoprstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
268
+ # $IDX="abcdefghijklmnopqrstuvwxy"
269
+ $IDX = ('a'..'y').to_a
256
270
  $IDX.delete 'q'
257
271
  $IDX.concat ('za'..'zz').to_a
258
272
  $IDX.concat ('Za'..'Zz').to_a
259
273
  $IDX.concat ('ZA'..'ZZ').to_a
260
274
 
261
- $selected_files = Array.new
275
+ $selected_files = []
262
276
  $bookmarks = {}
263
277
  $mode = nil
264
- $glines=%x(tput lines).to_i
265
- $gcols=%x(tput cols).to_i
278
+ $glines = `tput lines`.to_i
279
+ $gcols = `tput cols`.to_i
266
280
  $grows = $glines - 3
267
281
  $pagesize = 60
268
282
  $gviscols = 3
269
283
  $pagesize = $grows * $gviscols
270
284
  $stact = 0
271
- #$editor_mode = true
285
+ # $editor_mode = true
272
286
  $editor_mode = false # changed 2018-03-12 - so we start in pager mode
273
287
  $enhanced_mode = true
274
288
  $visual_block_start = nil
275
289
  $pager_command = {
276
- :text => 'most',
277
- :image => 'open',
278
- :zip => 'tar ztvf %% | most',
279
- :unknown => 'open'
290
+ text: 'most',
291
+ image: 'open',
292
+ zip: 'tar ztvf %% | most',
293
+ unknown: 'open'
280
294
  }
281
295
  $dir_position = {}
282
296
  ## CONSTANTS
283
- GMARK='*'
284
- CURMARK='>'
297
+ GMARK = '*'.freeze
298
+ CURMARK = '>'.freeze
285
299
  MSCROLL = 10
286
- SPACE=" "
287
- CLEAR = "\e[0m"
288
- BOLD = "\e[1m"
289
- BOLD_OFF = "\e[22m"
290
- RED = "\e[31m"
291
- ON_RED = "\e[41m"
292
- GREEN = "\e[32m"
293
- YELLOW = "\e[33m"
294
- BLUE = "\e[1;34m"
295
-
296
- ON_BLUE = "\e[44m"
297
- REVERSE = "\e[7m"
298
- UNDERLINE = "\e[4m"
300
+ SPACE = ' '.freeze
301
+ CLEAR = "\e[0m".freeze
302
+ BOLD = "\e[1m".freeze
303
+ BOLD_OFF = "\e[22m".freeze
304
+ RED = "\e[31m".freeze
305
+ ON_RED = "\e[41m".freeze
306
+ GREEN = "\e[32m".freeze
307
+ YELLOW = "\e[33m".freeze
308
+ BLUE = "\e[1;34m".freeze
309
+
310
+ ON_BLUE = "\e[44m".freeze
311
+ REVERSE = "\e[7m".freeze
312
+ UNDERLINE = "\e[4m".freeze
299
313
  CURSOR_COLOR = ON_BLUE
300
- $patt=nil
314
+ $patt = nil
301
315
  $ignorecase = true
302
316
  $quitting = false
303
317
  $modified = $writing = false
@@ -306,20 +320,20 @@ $visited_files = []
306
320
  $visited_dirs = []
307
321
  ## dirs where some work has been done, for saving and restoring
308
322
  $used_dirs = []
309
- $default_sort_order = "om"
323
+ $default_sort_order = 'om'
310
324
  $sorto = $default_sort_order
311
325
  $viewctr = 0
312
326
  $history = []
313
327
  $sta = $cursor = 0
314
328
  $visual_mode = false
315
- #$help = "#{BOLD}1-9a-zA-Z#{BOLD_OFF} Select #{BOLD}/#{BOLD_OFF} Grep #{BOLD}'#{BOLD_OFF} First char #{BOLD}M-n/p#{BOLD_OFF} Paging #{BOLD}!#{BOLD_OFF} Command Mode #{BOLD}@#{BOLD_OFF} Selection Mode #{BOLD}q#{BOLD_OFF} Quit"
329
+ # $help = "#{BOLD}1-9a-zA-Z#{BOLD_OFF} Select #{BOLD}/#{BOLD_OFF} Grep #{BOLD}'#{BOLD_OFF} First char #{BOLD}M-n/p#{BOLD_OFF} Paging #{BOLD}!#{BOLD_OFF} Command Mode #{BOLD}@#{BOLD_OFF} Selection Mode #{BOLD}q#{BOLD_OFF} Quit"
316
330
 
317
331
  $help = "#{BOLD}M-?#{BOLD_OFF} Help #{BOLD}`#{BOLD_OFF} Menu #{BOLD}!#{BOLD_OFF} Command #{BOLD}=#{BOLD_OFF} Toggle #{BOLD}@#{BOLD_OFF} Selection Mode #{BOLD}q#{BOLD_OFF} Quit "
318
332
 
319
- ## main loop which calls all other programs
333
+ ## main loop which calls all other programs
320
334
  def run
321
- home=ENV['HOME']
322
- ctr=0
335
+ home = ENV['HOME']
336
+ ctr = 0
323
337
  config_read
324
338
  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}M)'`.split("\n")
325
339
  $files = sort_file_list $files
@@ -327,27 +341,27 @@ def run
327
341
  ## added by RK 2014-03-31 - 00:29 since too many duplicates
328
342
  $files = $files.uniq if $enhanced_mode
329
343
 
330
- fl=$files.size
344
+ fl = $files.size
331
345
 
332
346
  selectedix = nil
333
- $patt=""
334
- $sta=0
335
- while true
347
+ $patt = ''
348
+ $sta = 0
349
+ loop do
336
350
  i = 0
337
- if $patt
338
- if $ignorecase
339
- $view = $files.grep(/#{$patt}/i)
340
- else
341
- $view = $files.grep(/#{$patt}/)
342
- end
343
- else
344
- $view = $files
345
- end
346
- fl=$view.size
351
+ $view = if $patt
352
+ if $ignorecase
353
+ $files.grep(/#{$patt}/i)
354
+ else
355
+ $files.grep(/#{$patt}/)
356
+ end
357
+ else
358
+ $files
359
+ end
360
+ fl = $view.size
347
361
  $sta = 0 if $sta >= fl || $sta < 0
348
362
  $viewport = $view[$sta, $pagesize]
349
363
  fin = $sta + $viewport.size
350
- $title ||= Dir.pwd.sub(home, "~")
364
+ $title ||= Dir.pwd.sub(home, '~')
351
365
  clear_screen
352
366
  # title
353
367
  print "#{GREEN}#{$help} #{BLUE}cetus #{VERSION}#{CLEAR}\n"
@@ -355,36 +369,34 @@ def run
355
369
  t = t[t.size - $gcols..-1] if t.size >= $gcols
356
370
  print "#{BOLD}#{t}#{CLEAR}\n"
357
371
  ## nilling the title means a superimposed one gets cleared.
358
- #$title = nil
372
+ # $title = nil
359
373
  # split into 2 procedures so columnate can e clean and reused.
360
- buff = format $viewport
374
+ buff = _format $viewport
361
375
  buff = columnate buff, $grows
362
376
  # needed the next line to see how much extra we were going in padding
363
- #buff.each {|line| print "#{REVERSE}#{line}#{CLEAR}\n" }
364
- buff.each {|line| print line, "\n" }
377
+ # buff.each {|line| print "#{REVERSE}#{line}#{CLEAR}\n" }
378
+ buff.each { |line| print line, "\n" }
365
379
  print
366
380
  # prompt
367
- #print "#{$files.size}, #{view.size} sta=#{sta} (#{patt}): "
368
- _mm = ""
381
+ # print "#{$files.size}, #{view.size} sta=#{sta} (#{patt}): "
382
+ _mm = ''
369
383
  _mm = "[#{$mode}] " if $mode
370
384
  print "\r#{_mm}#{$patt} >"
371
385
  ch = get_char
372
- #puts
373
- #break if ch == "q"
374
- #elsif ch =~ /^[1-9a-zA-Z]$/
386
+ # puts
387
+ # break if ch == "q"
388
+ # elsif ch =~ /^[1-9a-zA-Z]$/
375
389
  # 2019-03-04 - ignore q since that is quit key now
376
- #if ch =~ /^[a-zZ]$/
390
+ # if ch =~ /^[a-zZ]$/
377
391
  if ch =~ /^[a-pr-zZ]$/
378
392
  # hint mode
379
393
  select_hint $viewport, ch
380
394
  ctr = 0
381
- elsif ch == "BACKSPACE"
382
- if $patt && $patt.size > 0
383
- $patt = $patt[0..-2]
384
- end
395
+ elsif ch == 'BACKSPACE'
396
+ $patt = $patt[0..-2] if $patt && !$patt.empty?
385
397
  ctr = 0
386
398
  else
387
- #binding = $bindings[ch]
399
+ # binding = $bindings[ch]
388
400
  x = $bindings[ch]
389
401
  x = x.split if x
390
402
  if x
@@ -392,57 +404,56 @@ def run
392
404
  args = x
393
405
  send(binding, *args) if binding
394
406
  else
395
- #perror "No binding for #{ch}"
407
+ perror "No binding for #{ch}"
396
408
  end
397
- #p ch
409
+ # p ch
398
410
  end
399
411
  break if $quitting
400
412
  end
401
413
  write_curdir
402
- puts "bye"
414
+ puts 'bye'
403
415
  config_write if $writing
404
416
  end
405
417
 
406
418
  ## write current dir to a file so we can ccd to it when exiting
407
419
  def write_curdir
408
-
409
- f = File.expand_path("~/.fff_d")
420
+ f = File.expand_path('~/.fff_d')
410
421
  s = Dir.pwd
411
- File.open(f, "w") do |f2|
422
+ File.open(f, 'w') do |f2|
412
423
  f2.puts s
413
424
  end
414
- #puts "Written #{s} to #{f}"
425
+ # puts "Written #{s} to #{f}"
415
426
  end
416
427
 
417
-
418
428
  ## code related to long listing of files
419
- GIGA_SIZE = 1073741824.0
420
- MEGA_SIZE = 1048576.0
429
+ GIGA_SIZE = 1_073_741_824.0
430
+ MEGA_SIZE = 1_048_576.0
421
431
  KILO_SIZE = 1024.0
422
432
 
423
433
  # Return the file size with a readable style.
434
+ # NOTE format is a kernel method.
424
435
  def readable_file_size(size, precision)
425
- case
426
- #when size == 1 : "1 B"
427
- when size < KILO_SIZE then "%d B" % size
428
- when size < MEGA_SIZE then "%.#{precision}f K" % (size / KILO_SIZE)
429
- when size < GIGA_SIZE then "%.#{precision}f M" % (size / MEGA_SIZE)
430
- else "%.#{precision}f G" % (size / GIGA_SIZE)
436
+ if size < KILO_SIZE then format('%d B', size)
437
+ elsif size < MEGA_SIZE then format("%.#{precision}f K", (size / KILO_SIZE))
438
+ elsif size < GIGA_SIZE then format("%.#{precision}f M", (size / MEGA_SIZE))
439
+ else format("%.#{precision}f G", (size / GIGA_SIZE))
431
440
  end
432
441
  end
442
+
433
443
  ## format date for file given stat
434
- def date_format t
435
- t.strftime "%Y/%m/%d"
444
+ def date_format(t)
445
+ t.strftime '%Y/%m/%d'
436
446
  end
447
+
437
448
  ##
438
449
  #
439
450
  # print in columns
440
451
  # ary - array of data
441
452
  # sz - lines in one column
442
453
  #
443
- def columnate ary, sz
444
- buff=Array.new
445
- return buff if ary.nil? || ary.size == 0
454
+ def columnate(ary, sz)
455
+ buff = []
456
+ return buff if ary.nil? || ary.empty?
446
457
 
447
458
  # determine width based on number of files to show
448
459
  # if less than sz then 1 col and full width
@@ -454,39 +465,35 @@ def columnate ary, sz
454
465
  if ars <= sz
455
466
  wid = $gcols - d
456
467
  else
457
- tmp = (ars * 1.000/ sz).ceil
468
+ tmp = (ars * 1.000 / sz).ceil
458
469
  wid = $gcols / tmp - d
459
470
  end
460
- #elsif ars < sz * 2
461
- #wid = $gcols/2 - d
462
- #elsif ars < sz * 3
463
- #wid = $gcols/3 - d
464
- #else
465
- #wid = $gcols/$gviscols - d
466
- #end
471
+ # elsif ars < sz * 2
472
+ # wid = $gcols/2 - d
473
+ # elsif ars < sz * 3
474
+ # wid = $gcols/3 - d
475
+ # else
476
+ # wid = $gcols/$gviscols - d
477
+ # end
467
478
 
468
479
  # ix refers to the index in the complete file list, wherease we only show 60 at a time
469
- ix=0
470
- while true
480
+ ix = 0
481
+ loop do
471
482
  ## ctr refers to the index in the column
472
- ctr=0
483
+ ctr = 0
473
484
  while ctr < sz
474
485
 
475
486
  f = ary[ix]
476
487
  fsz = f.size
477
488
  if fsz > wid
478
- f = f[0, wid-2]+"$ "
489
+ f = f[0, wid - 2] + '$ '
479
490
  ## we do the coloring after trunc so ANSI escpe seq does not get get
480
- if ix + $sta == $cursor
481
- f = "#{CURSOR_COLOR}#{f}#{CLEAR}"
482
- end
491
+ f = "#{CURSOR_COLOR}#{f}#{CLEAR}" if ix + $sta == $cursor
483
492
  else
484
493
  ## we do the coloring before padding so the entire line does not get padded, only file name
485
- if ix + $sta == $cursor
486
- f = "#{CURSOR_COLOR}#{f}#{CLEAR}"
487
- end
488
- #f = f.ljust(wid)
489
- f << " " * (wid-fsz)
494
+ f = "#{CURSOR_COLOR}#{f}#{CLEAR}" if ix + $sta == $cursor
495
+ # f = f.ljust(wid)
496
+ f << ' ' * (wid - fsz)
490
497
  end
491
498
 
492
499
  if buff[ctr]
@@ -495,156 +502,188 @@ def columnate ary, sz
495
502
  buff[ctr] = f
496
503
  end
497
504
 
498
- ctr+=1
499
- ix+=1
505
+ ctr += 1
506
+ ix += 1
500
507
  break if ix >= ary.size
501
508
  end
502
509
  break if ix >= ary.size
503
510
  end
504
- return buff
511
+ buff
505
512
  end
513
+
506
514
  ## formats the data with number, mark and details
507
- def format ary
508
- #buff = Array.new
515
+ # 2019-03-09 - at some time this got renamed to `format` which is a kernel
516
+ # method and this overshadowed that method.
517
+ def _format(ary)
518
+ # buff = Array.new
509
519
  buff = Array.new(ary.size)
510
- return buff if ary.nil? || ary.size == 0
520
+ return buff if ary.nil? || ary.empty?
511
521
 
512
522
  # determine width based on number of files to show
513
523
  # if less than sz then 1 col and full width
514
524
  #
515
525
  # ix refers to the index in the complete file list, wherease we only show 60 at a time
516
- ix=0
517
- ctr=0
526
+ ix = 0
527
+ ctr = 0
518
528
  ary.each do |f|
519
529
  ## ctr refers to the index in the column
520
530
  ind = get_shortcut(ix)
521
- mark=SPACE
522
- cur=SPACE
531
+ mark = SPACE
532
+ cur = SPACE
523
533
  cur = CURMARK if ix + $sta == $cursor
524
- mark=GMARK if $selected_files.index(ary[ix])
534
+ # TODO: add full path TESTME
535
+ # mark = GMARK if $selected_files.index(ary[ix])
536
+ mark = GMARK if selected?(ary[ix])
525
537
 
526
538
  if $long_listing
527
539
  begin
528
- unless File.exist? f
529
- last = f[-1]
530
- if last == " " || last == "@" || last == '*'
531
- stat = File.stat(f.chop)
532
- end
533
- else
540
+ if File.exist? f
534
541
  stat = File.stat(f)
542
+ else
543
+ last = f[-1]
544
+ stat = File.stat(f.chop) if last == ' ' || last == '@' || last == '*'
535
545
  end
536
- f = "%10s %s %s" % [readable_file_size(stat.size,1), date_format(stat.mtime), f]
546
+ f = format('%10s %s %s', readable_file_size(stat.size, 1),
547
+ date_format(stat.mtime), f)
537
548
  rescue Exception => e
538
- f = "%10s %s %s" % ["?", "??????????", f]
549
+ f = format('%10s %s %s', '?', '??????????', f)
539
550
  end
540
551
  end
541
552
 
542
553
  s = "#{ind}#{mark}#{cur}#{f}"
543
554
  # I cannot color the current line since format does the chopping
544
- # so not only does the next lines alignment get skeweed, but also if the line is truncated
555
+ # so not only does the next lines alignment get skewed,
556
+ # but also if the line is truncated
545
557
  # then the color overflows.
546
- #if ix + $sta == $cursor
547
- #s = "#{RED}#{s}#{CLEAR}"
548
- #end
558
+ # if ix + $sta == $cursor
559
+ # s = "#{RED}#{s}#{CLEAR}"
560
+ # end
549
561
 
550
562
  buff[ctr] = s
551
563
 
552
- ctr+=1
553
- ix+=1
564
+ ctr += 1
565
+ ix += 1
554
566
  end
555
- return buff
567
+ buff
556
568
  end
569
+
557
570
  ## select file based on key pressed
558
- def select_hint view, ch
571
+ def select_hint(view, ch)
559
572
  # a to y is direct
560
573
  # if x or z take a key IF there are those many
561
574
  #
562
575
  ix = get_index(ch, view.size)
563
- if ix
564
- f = view[ix]
565
- return unless f
566
- $cursor = $sta + ix
567
-
568
- if $mode == 'SEL'
569
- toggle_select f
570
- elsif $mode == 'COM'
571
- run_command f
572
- else
573
- open_file f
574
- end
575
- #selectedix=ix
576
+ return unless ix
577
+
578
+ f = view[ix]
579
+ return unless f
580
+
581
+ $cursor = $sta + ix
582
+
583
+ if $mode == 'SEL'
584
+ toggle_select f
585
+ elsif $mode == 'COM'
586
+ run_command f
587
+ else
588
+ open_file f
576
589
  end
590
+ # selectedix=ix
577
591
  end
592
+
578
593
  ## toggle selection state of file
579
- def toggle_select f
580
- if $selected_files.index f
581
- $selected_files.delete f
594
+ def toggle_select(f)
595
+ # dir = Dir.pwd
596
+ # file = File.join(dir, f)
597
+ if selected? f
598
+ remove_from_selection f
582
599
  else
583
- $selected_files.push f
600
+ add_to_selection f
584
601
  end
585
602
  end
586
603
 
587
604
  ## open file or directory
588
- def open_file f
605
+ def open_file(f)
589
606
  return unless f
590
- if f[0] == "~"
591
- f = File.expand_path(f)
592
- end
607
+
608
+ f = File.expand_path(f) if f[0] == '~'
593
609
  unless File.exist? f
594
610
  # this happens if we use (T) in place of (M)
595
611
  # it places a space after normal files and @ and * which borks commands
596
612
  last = f[-1]
597
- if last == " " || last == "@" || last == '*'
598
- f = f.chop
599
- end
613
+ f = f.chop if last == ' ' || last == '@' || last == '*'
600
614
  end
601
615
  nextpos = nil
602
616
 
603
617
  # could be a bookmark with position attached to it
604
- if f.index(":")
605
- f, nextpos = f.split(":")
606
- end
618
+ f, nextpos = f.split(':') if f.index(':')
607
619
  if File.directory? f
608
620
  save_dir_pos
609
621
  change_dir f, nextpos
610
622
  elsif File.readable? f
611
- $default_command ||= "$EDITOR"
623
+ $default_command ||= '$PAGER'
612
624
  if !$editor_mode
613
625
  ft = filetype f
614
626
  if ft
615
627
  comm = $pager_command[ft]
616
628
  else
617
629
  comm = $pager_command[File.extname(f)]
618
- comm = $pager_command["unknown"] unless comm
630
+ comm ||= $pager_command['unknown']
619
631
  end
620
632
  else
621
633
  comm = $default_command
622
634
  end
623
635
  comm ||= $default_command
624
- if comm.index("%%")
625
- comm = comm.gsub("%%", Shellwords.escape(f))
626
- else
627
- comm = comm + " #{Shellwords.escape(f)}"
628
- end
636
+ comm = if comm.index('%%')
637
+ comm.gsub('%%', Shellwords.escape(f))
638
+ else
639
+ comm + " #{Shellwords.escape(f)}"
640
+ end
629
641
  clear_screen
630
642
  reset_terminal
631
- system("#{comm}")
643
+ system(comm.to_s)
632
644
  setup_terminal
633
- f = Dir.pwd + "/" + f if f[0] != '/'
645
+ f = Dir.pwd + '/' + f if f[0] != '/'
634
646
  $visited_files.insert(0, f)
635
647
  push_used_dirs Dir.pwd
636
648
  else
637
649
  perror "open_file: (#{f}) not found"
638
- # could check home dir or CDPATH env variable DO
650
+ # could check home dir or CDPATH env variable DO
639
651
  end
640
652
  end
641
653
 
654
+ # regardless of mode, view the current file using pager
655
+ def page_current
656
+ command = ENV['MANPAGER'] || ENV['PAGER'] || 'less'
657
+ run_on_current command
658
+ end
659
+
660
+ # regardless of mode, edit the current file using editor
661
+ def edit_current
662
+ command = ENV['EDITOR'] || ENV['VISUAL'] || 'vim'
663
+ run_on_current command
664
+ $visited_files.insert(0, current_file)
665
+ end
666
+
667
+ # run given command on current file
668
+ def run_on_current(command)
669
+ f = $view[$cursor]
670
+ return unless f
671
+ f = File.expand_path(f)
672
+ return unless File.readable?(f)
673
+
674
+ clear_screen
675
+ reset_terminal
676
+ comm = "#{command} #{f}"
677
+ system(comm.to_s)
678
+ setup_terminal
679
+ end
680
+
642
681
  ## run command on given file/s
643
682
  # Accepts command from user
644
683
  # After putting readline in place of gets, pressing a C-c has a delayed effect. It goes intot
645
684
  # exception bloack after executing other commands and still does not do the return !
646
- def run_command f
647
- files=nil
685
+ def run_command(f)
686
+ files = nil
648
687
  case f
649
688
  when Array
650
689
  # escape the contents and create a string
@@ -654,13 +693,14 @@ def run_command f
654
693
  end
655
694
  print "Run a command on #{files}: "
656
695
  begin
657
- #Readline::HISTORY.push(*values)
658
- command = Readline::readline('>', true)
659
- #command = gets().chomp
660
- return if command.size == 0
661
- print "Second part of command: "
662
- #command2 = gets().chomp
663
- command2 = Readline::readline('>', true)
696
+ # Readline::HISTORY.push(*values)
697
+ command = Readline.readline('>', true)
698
+ # command = gets().chomp
699
+ return if command.empty?
700
+
701
+ print 'Second part of command: '
702
+ # command2 = gets().chomp
703
+ command2 = Readline.readline('>', true)
664
704
  puts "#{command} #{files} #{command2}"
665
705
  system "#{command} #{files} #{command2}"
666
706
  rescue Exception => ex
@@ -672,27 +712,33 @@ def run_command f
672
712
  end
673
713
 
674
714
  refresh
675
- puts "Press a key ..."
715
+ puts 'Press a key ...'
676
716
  push_used_dirs Dir.pwd
677
717
  get_char
678
718
  end
679
719
 
680
720
  ## cd to a dir
681
- def change_dir f, pos = nil
721
+ def change_dir(f, pos = nil)
682
722
  $visited_dirs.insert(0, Dir.pwd)
683
723
  f = File.expand_path(f)
684
724
  Dir.chdir f
685
- $filterstr ||= "M"
725
+ $filterstr ||= 'M'
686
726
  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
687
727
  $files = sort_file_list $files
688
728
  post_cd
689
729
  if pos
690
730
  # convert curpos to sta also
691
- #$cursor = pos.to_i
731
+ # $cursor = pos.to_i
692
732
  goto_line pos.to_i
693
733
  end
694
734
  end
695
735
 
736
+ def goto_previous_dir
737
+ prev_dir = $visited_dirs.first
738
+ return unless prev_dir
739
+ change_dir prev_dir
740
+ end
741
+
696
742
  ## clear sort order and refresh listing, used typically if you are in some view
697
743
  # such as visited dirs or files
698
744
  def escape
@@ -700,25 +746,25 @@ def escape
700
746
  $sorto = $default_sort_order
701
747
  $viewctr = 0
702
748
  $title = nil
703
- $filterstr = "M"
749
+ $filterstr = 'M'
704
750
  visual_block_clear
705
751
  refresh
706
752
  end
707
753
 
708
754
  ## refresh listing after some change like option change, or toggle
709
755
  def refresh
710
- $filterstr ||= "M"
711
- $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
712
- # first put dirs then files
713
- $files = sort_file_list $files
714
- $patt = nil
715
- $title = nil
756
+ $filterstr ||= 'M'
757
+ $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
758
+ # first put dirs then files
759
+ $files = sort_file_list $files
760
+ $patt = nil
761
+ $title = nil
716
762
  end
717
763
 
718
- def sort_file_list files
719
- _dirs = $files.select { |f| File.directory?(f) }
720
- _files = $files.select { |f| File.file?(f) }
721
- return _dirs + _files
764
+ def sort_file_list(_files)
765
+ _dirs = $files.select { |f| File.directory?(f) }
766
+ _files = $files.select { |f| File.file?(f) }
767
+ _dirs + _files
722
768
  end
723
769
 
724
770
  ## unselect all files
@@ -729,31 +775,31 @@ end
729
775
 
730
776
  ## select all files
731
777
  def select_all
732
- $selected_files = $view.dup
778
+ # TODO: add path TESTME
779
+ dir = Dir.pwd
780
+ $selected_files = $view.map { |file| File.join(dir, file) }
733
781
  end
734
782
 
735
783
  ## accept dir to goto and change to that ( can be a file too)
736
784
  def goto_dir
737
- print "Enter path: "
785
+ print 'Enter path: '
738
786
  begin
739
- #path = gets.chomp
740
- path = Readline::readline('>', true)
741
- return if path == ""
742
- #rescue => ex
787
+ # path = gets.chomp
788
+ path = Readline.readline('>', true)
789
+ return if path == ''
790
+ # rescue => ex
743
791
  rescue Exception => ex
744
- perror "Cancelled cd, press a key"
792
+ perror 'Cancelled cd, press a key'
745
793
  return
746
794
  end
747
795
  f = File.expand_path(path)
748
796
  unless File.directory? f
749
797
  ## check for env variable
750
798
  tmp = ENV[path]
751
- if tmp.nil? || !File.directory?( tmp )
799
+ if tmp.nil? || !File.directory?(tmp)
752
800
  ## check for dir in home
753
801
  tmp = File.expand_path("~/#{path}")
754
- if File.directory? tmp
755
- f = tmp
756
- end
802
+ f = tmp if File.directory? tmp
757
803
  else
758
804
  f = tmp
759
805
  end
@@ -769,15 +815,14 @@ end
769
815
  def selection_mode_toggle
770
816
  if $mode == 'SEL'
771
817
  # we seem to be coming out of select mode with some files
772
- if $selected_files.size > 0
773
- run_command $selected_files
774
- end
818
+ run_command $selected_files unless $selected_files.empty?
775
819
  $mode = nil
776
820
  else
777
- #$selection_mode = !$selection_mode
821
+ # $selection_mode = !$selection_mode
778
822
  $mode = 'SEL'
779
823
  end
780
824
  end
825
+
781
826
  ## toggle command mode
782
827
  def command_mode
783
828
  if $mode == 'COM'
@@ -786,24 +831,32 @@ def command_mode
786
831
  end
787
832
  $mode = 'COM'
788
833
  end
834
+
789
835
  def goto_parent_dir
790
836
  change_dir '..'
791
837
  end
838
+
839
+ def goto_home_dir
840
+ change_dir '~'
841
+ end
842
+
792
843
  ## This actually filters, in zfm it goes to that entry since we have a cursor there
793
844
  #
794
- def goto_entry_starting_with fc=nil
845
+ def goto_entry_starting_with(fc = nil)
795
846
  unless fc
796
- print "Entries starting with: "
847
+ print 'Entries starting with: '
797
848
  fc = get_char
798
849
  end
799
850
  return if fc.size != 1
851
+
800
852
  ## this is wrong and duplicates the functionality of /
801
853
  # It shoud go to cursor of item starting with fc
802
854
  $patt = "^#{fc}"
803
855
  end
804
- def goto_bookmark ch=nil
856
+
857
+ def goto_bookmark(ch = nil)
805
858
  unless ch
806
- print "Enter bookmark char: "
859
+ print 'Enter bookmark char: '
807
860
  ch = get_char
808
861
  end
809
862
  if ch =~ /^[0-9A-Z]$/
@@ -812,122 +865,173 @@ def goto_bookmark ch=nil
812
865
  # this way we leave the position as is, so it gets written back
813
866
  nextpos = nil
814
867
  if d
815
- if d.index(":")
816
- ix = d.index(":")
817
- nextpos = d[ix+1..-1]
818
- d = d[0,ix]
868
+ if d.index(':')
869
+ ix = d.index(':')
870
+ nextpos = d[ix + 1..-1]
871
+ d = d[0, ix]
819
872
  end
820
873
  change_dir d, nextpos
821
874
  else
822
875
  perror "#{ch} not a bookmark"
823
876
  end
824
877
  else
825
- #goto_entry_starting_with ch
878
+ # goto_entry_starting_with ch
826
879
  file_starting_with ch
827
880
  end
828
881
  end
829
882
 
830
-
831
883
  ## take regex from user, to run on files on screen, user can filter file names
832
884
  def enter_regex
833
- print "Enter (regex) pattern: "
834
- #$patt = gets().chomp
835
- $patt = Readline::readline('>', true)
885
+ print 'Enter (regex) pattern: '
886
+ # $patt = gets().chomp
887
+ $patt = Readline.readline('>', true)
836
888
  ctr = 0
837
889
  end
890
+
838
891
  def next_page
839
892
  $sta += $pagesize
840
893
  end
894
+
841
895
  def prev_page
842
896
  $sta -= $pagesize
843
897
  end
844
898
 
899
+ # print help on key-bindings
900
+ # 2019-03-08 - write to temp file and user PAGER
845
901
  def print_help
846
- clear_screen
847
- puts "HELP"
848
- puts
849
- puts "To open a file or dir press 1-9 a-z A-Z "
850
- puts "Command Mode: Will prompt for a command to run on a file, after selecting using hotkey"
851
- puts "Selection Mode: Each selection adds to selection list (toggles)"
852
- puts " Upon exiting mode, user is prompted for a command to run on selected files"
853
- puts
854
- ary = []
855
- $bindings.each_pair { |k, v| ary.push "#{k.ljust(7)} => #{v}" }
856
- ary = columnate ary, $grows - 7
857
- ary.each {|line| print line, "\n" }
858
- get_char
902
+ require 'tempfile'
903
+ file = Tempfile.new('help')
904
+ begin
905
+ file.puts ' HELP'
906
+
907
+ file.puts
908
+ file.puts 'To open a file or dir press 1-9 a-z A-Z '
909
+ file.puts 'Command Mode: Will prompt for a command to run on a file, after selecting using hotkey'
910
+ file.puts 'Selection Mode: Each selection adds to selection list (toggles)'
911
+ file.puts ' Execute commands on selected files. e.g D '
912
+ file.puts ' Upon exiting mode, user is prompted for a command to run on selected files'
913
+ file.puts
914
+ ary = []
915
+ $bindings.each_pair { |k, v| ary.push "#{k.ljust(7)} => #{v}" }
916
+ ary = columnate ary, (ary.size/2)+1
917
+ ary.each { |line| file.puts line }
918
+ file.flush
919
+ system "$PAGER #{file.path}"
920
+ rescue
921
+ file.close
922
+ file.unlink
923
+ end
924
+ end #
859
925
 
860
- end
861
926
  def show_marks
862
927
  puts
863
- puts "Bookmarks: "
928
+ puts 'Bookmarks: '
864
929
  $bookmarks.each_pair { |k, v| puts "#{k.ljust(7)} => #{v}" }
865
930
  puts
866
- print "Enter bookmark to goto: "
931
+ print 'Enter bookmark to goto: '
867
932
  ch = get_char
868
933
  goto_bookmark(ch) if ch =~ /^[0-9A-Z]$/
869
934
  end
935
+
870
936
  # MENU MAIN -- keep consistent with zfm
871
937
  def main_menu
872
938
  h = {
873
- :a => :ack,
874
- "/" => :ffind,
939
+ :a => :ag,
940
+ '/' => :ffind,
875
941
  :l => :locate,
876
- :v => :viminfo,
942
+ :V => :viminfo,
943
+ :v => :vidir,
877
944
  :z => :z_interface,
878
945
  :d => :child_dirs,
879
946
  :r => :recent_files,
947
+ '1' => :select_visited_files,
948
+ '2' => :select_used_dirs,
880
949
  :t => :dirtree,
881
- "4" => :tree,
950
+ '4' => :tree,
882
951
  :s => :sort_menu,
883
952
  :F => :filter_menu,
884
- :c => :command_menu ,
953
+ :c => :command_menu,
885
954
  :B => :bindkey_ext_command,
886
955
  :M => :newdir,
887
- "%" => :newfile,
956
+ '%' => :newfile,
957
+ 'S' => :scripts,
888
958
  :x => :extras
889
959
  }
890
- menu "Main Menu", h
960
+ menu 'Main Menu', h
961
+ end
962
+
963
+ # trying out fzf instead
964
+ # 2019-03-08 - 23:46
965
+ # FIXME returns a String not symbol, so some callers can fail
966
+ def fzfmenu(title, h)
967
+ return unless h
968
+
969
+ pbold title.to_s
970
+ values = h.values.join("\n")
971
+ binding = `echo "#{values}" | fzf --prompt="#{title.to_s} :"`
972
+ # h.each_pair { |k, v| puts " #{k}: #{v}" }
973
+ # ch = get_char
974
+ # binding = h[ch]
975
+ # binding ||= h[ch.to_sym]
976
+ # FIXME we have converted symbol to string
977
+ ch = nil
978
+ if binding
979
+ binding = binding.chomp
980
+ send(binding) if respond_to?(binding, true)
981
+ ch = h.key(binding)
982
+ end
983
+ [ch, binding]
891
984
  end
892
- def menu title, h
985
+
986
+ # this style used hotkeys which I remember. But it can get long.
987
+ # and I have to fix a hotkey for each new entry
988
+ def menu(title, h)
893
989
  return unless h
894
990
 
895
- pbold "#{title}"
896
- h.each_pair { |k, v| puts " #{k}: #{v}" }
991
+ pbold title.to_s
992
+ # h.each_pair { |k, v| puts " #{k}: #{v}" }
993
+ # 2019-03-09 - trying out using `column` to print in cols
994
+ ary = []
995
+ h.each_pair { |k, v| ary << " #{k}: #{v}" }
996
+ x = ary.join("\n")
997
+ puts %x{echo "#{x}" | column}
998
+
897
999
  ch = get_char
898
1000
  binding = h[ch]
899
- binding = h[ch.to_sym] unless binding
1001
+ binding ||= h[ch.to_sym]
900
1002
  if binding
901
- if respond_to?(binding, true)
902
- send(binding)
903
- end
1003
+ send(binding) if respond_to?(binding, true)
904
1004
  end
905
- return ch, binding
1005
+ [ch, binding]
906
1006
  end
1007
+
907
1008
  def toggle_menu
908
- h = { :h => :toggle_hidden, :c => :toggle_case, :l => :toggle_long_list , "1" => :toggle_columns,
909
- :p => :toggle_pager_mode, :e => :toggle_enhanced_list}
910
- ch, menu_text = menu "Toggle Menu", h
1009
+ h = { :h => :toggle_hidden, :c => :toggle_case, :l => :toggle_long_list, '1' => :toggle_columns,
1010
+ :p => :toggle_pager_mode, :e => :toggle_enhanced_list }
1011
+ ch, menu_text = menu 'Toggle Menu', h
1012
+ # NOTE fzfmenu returns string not symbol
1013
+ return unless menu_text
1014
+
911
1015
  case menu_text
912
1016
  when :toggle_hidden
913
- $hidden = $hidden ? nil : "D"
1017
+ $hidden = $hidden ? nil : 'D'
914
1018
  refresh
915
1019
  when :toggle_case
916
- #$ignorecase = $ignorecase ? "" : "i"
1020
+ # $ignorecase = $ignorecase ? "" : "i"
917
1021
  $ignorecase = !$ignorecase
918
1022
  refresh
919
1023
  when :toggle_columns
920
1024
  $gviscols = 3 if $gviscols == 1
921
- #$long_listing = false if $gviscols > 1
1025
+ # $long_listing = false if $gviscols > 1
922
1026
  x = $grows * $gviscols
923
- $pagesize = $pagesize==x ? $grows : x
1027
+ $pagesize = $pagesize == x ? $grows : x
924
1028
  when :toggle_pager_mode
925
1029
  $editor_mode = !$editor_mode
926
- if $editor_mode
927
- $default_command = nil
928
- else
929
- $default_command = ENV['MANPAGER'] || ENV['PAGER']
930
- end
1030
+ $default_command = if $editor_mode
1031
+ ENV['EDITOR'] # earlier nil # 2019-03-10 -
1032
+ else
1033
+ ENV['MANPAGER'] || ENV['PAGER']
1034
+ end
931
1035
  when :toggle_enhanced_list
932
1036
  $enhanced_mode = !$enhanced_mode
933
1037
 
@@ -938,7 +1042,7 @@ def toggle_menu
938
1042
  $pagesize = $grows
939
1043
  else
940
1044
  x = $grows * $gviscols
941
- $pagesize = $pagesize==x ? $grows : x
1045
+ $pagesize = $pagesize == x ? $grows : x
942
1046
  end
943
1047
  refresh
944
1048
  end
@@ -946,34 +1050,34 @@ end
946
1050
 
947
1051
  def sort_menu
948
1052
  lo = nil
949
- h = { :n => :newest, :a => :accessed, :o => :oldest,
950
- :l => :largest, :s => :smallest , :m => :name , :r => :rname, :d => :dirs, :c => :clear }
951
- ch, menu_text = menu "Sort Menu", h
1053
+ h = { n: :newest, a: :accessed, o: :oldest,
1054
+ l: :largest, s: :smallest, m: :name, r: :rname, d: :dirs, c: :clear }
1055
+ ch, menu_text = menu 'Sort Menu', h
952
1056
  case menu_text
953
1057
  when :newest
954
- lo="om"
1058
+ lo = 'om'
955
1059
  when :accessed
956
- lo="oa"
1060
+ lo = 'oa'
957
1061
  when :oldest
958
- lo="Om"
1062
+ lo = 'Om'
959
1063
  when :largest
960
- lo="OL"
1064
+ lo = 'OL'
961
1065
  when :smallest
962
- lo="oL"
1066
+ lo = 'oL'
963
1067
  when :name
964
- lo="on"
1068
+ lo = 'on'
965
1069
  when :rname
966
- lo="On"
1070
+ lo = 'On'
967
1071
  when :dirs
968
- lo="/"
1072
+ lo = '/'
969
1073
  when :clear
970
- lo=""
1074
+ lo = ''
971
1075
  end
972
1076
  ## This needs to persist and be a part of all listings, put in change_dir.
973
1077
  $sorto = lo
974
1078
  $files = `zsh -c 'print -rl -- *(#{lo}#{$hidden}M)'`.split("\n") if lo
975
1079
  $title = nil
976
- #$files =$(eval "print -rl -- ${pattern}(${MFM_LISTORDER}$filterstr)")
1080
+ # $files =$(eval "print -rl -- ${pattern}(${MFM_LISTORDER}$filterstr)")
977
1081
  end
978
1082
 
979
1083
  def command_menu
@@ -986,13 +1090,14 @@ def command_menu
986
1090
  # should be able to sort THIS listing and not rerun command. But for that I'd need to use
987
1091
  # xargs ls -t etc rather than the zsh sort order. But we can run a filter using |.
988
1092
  #
989
- h = { :t => :today, :D => :default_command , :R => :remove_from_list}
990
- if $editor_mode
991
- h[:e] = :pager_mode
992
- else
993
- h[:e] = :editor_mode
994
- end
995
- ch, menu_text = menu "Command Menu", h
1093
+ h = { t: :today, D: :default_command, R: :remove_from_list,
1094
+ v: :page_selection }
1095
+ h[:e] = if $editor_mode
1096
+ :pager_mode
1097
+ else
1098
+ :editor_mode
1099
+ end
1100
+ _, menu_text = menu 'Command Menu', h
996
1101
  case menu_text
997
1102
  when :pager_mode
998
1103
  $editor_mode = false
@@ -1008,26 +1113,27 @@ def command_menu
1008
1113
  $files = `zsh -c 'print -rl -- *(#{$hidden}Mm0)'`.split("\n")
1009
1114
  $title = "Today's files"
1010
1115
  when :default_command
1011
- print "Selecting a file usually invokes $EDITOR, what command do you want to use repeatedly on selected files: "
1012
- $default_command = gets().chomp
1013
- if $default_command != ""
1014
- print "Second part of command (maybe blank): "
1015
- $default_command2 = gets().chomp
1116
+ print 'Selecting a file usually invokes $EDITOR, what command do you want to use repeatedly on selected files: '
1117
+ $default_command = gets.chomp
1118
+ if $default_command != ''
1119
+ print 'Second part of command (maybe blank): '
1120
+ $default_command2 = gets.chomp
1016
1121
  else
1017
- print "Cleared default command, will default to $EDITOR"
1122
+ print 'Cleared default command, will default to $EDITOR'
1018
1123
  $default_command2 = nil
1019
1124
  $default_command = nil
1020
1125
  end
1021
1126
  end
1022
1127
  end
1128
+
1023
1129
  def extras
1024
- h = { "1" => :one_column, "2" => :multi_column, :c => :columns, :r => :config_read , :w => :config_write}
1025
- ch, menu_text = menu "Extras Menu", h
1130
+ h = { '1' => :one_column, '2' => :multi_column, :c => :columns, :r => :config_read, :w => :config_write }
1131
+ ch, menu_text = menu 'Extras Menu', h
1026
1132
  case menu_text
1027
1133
  when :one_column
1028
1134
  $pagesize = $grows
1029
1135
  when :multi_column
1030
- #$pagesize = 60
1136
+ # $pagesize = 60
1031
1137
  $pagesize = $grows * $gviscols
1032
1138
  when :columns
1033
1139
  print "How many columns to show: 1-6 [current #{$gviscols}]? "
@@ -1039,44 +1145,50 @@ def extras
1039
1145
  end
1040
1146
  end
1041
1147
  end
1148
+
1042
1149
  def filter_menu
1043
- h = { :d => :dirs, :f => :files, :e => :emptydirs , "0" => :emptyfiles}
1044
- ch, menu_text = menu "Filter Menu", h
1150
+ h = { :d => :dirs, :f => :files, :e => :emptydirs, '0' => :emptyfiles }
1151
+ ch, menu_text = menu 'Filter Menu', h
1045
1152
  files = nil
1046
1153
  case menu_text
1047
1154
  when :dirs
1048
- $filterstr = "/M"
1155
+ $filterstr = '/M'
1049
1156
  files = `zsh -c 'print -rl -- *(#{$sorto}/M)'`.split("\n")
1050
- $title = "Filter: directories only"
1157
+ $title = 'Filter: directories only'
1051
1158
  when :files
1052
- $filterstr = "."
1159
+ $filterstr = '.'
1053
1160
  files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}.)'`.split("\n")
1054
- $title = "Filter: files only"
1161
+ $title = 'Filter: files only'
1055
1162
  when :emptydirs
1056
- $filterstr = "/D^F"
1163
+ $filterstr = '/D^F'
1057
1164
  files = `zsh -c 'print -rl -- *(#{$sorto}/D^F)'`.split("\n")
1058
- $title = "Filter: empty directories"
1165
+ $title = 'Filter: empty directories'
1059
1166
  when :emptyfiles
1060
- $filterstr = ".L0"
1167
+ $filterstr = '.L0'
1061
1168
  files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}.L0)'`.split("\n")
1062
- $title = "Filter: empty files"
1169
+ $title = 'Filter: empty files'
1063
1170
  end
1064
1171
  if files
1065
1172
  $files = files
1066
1173
  $stact = 0
1067
1174
  end
1068
1175
  end
1176
+
1069
1177
  def select_used_dirs
1070
- $title = "Used Directories"
1071
- $files = $used_dirs.uniq
1178
+ $title = 'Used Directories'
1179
+ home = File.expand_path '~'
1180
+ $files = $used_dirs.uniq.map { |path| path.sub("#{home}", '~') }
1072
1181
  end
1182
+
1073
1183
  def select_visited_files
1074
1184
  # not yet a unique list, needs to be unique and have latest pushed to top
1075
- $title = "Visited Files"
1076
- $files = $visited_files.uniq
1185
+ $title = 'Visited Files'
1186
+ home = File.expand_path '~'
1187
+ $files = $visited_files.uniq.map { |path| path.sub("#{home}", '~') }
1077
1188
  end
1189
+
1078
1190
  def select_bookmarks
1079
- $title = "Bookmarks"
1191
+ $title = 'Bookmarks'
1080
1192
  $files = $bookmarks.values
1081
1193
  end
1082
1194
 
@@ -1084,15 +1196,13 @@ end
1084
1196
  # or we'll be stuck in a cycle
1085
1197
  def pop_dir
1086
1198
  # the first time we pop, we need to put the current on stack
1087
- if !$visited_dirs.index(Dir.pwd)
1088
- $visited_dirs.push Dir.pwd
1089
- end
1199
+ $visited_dirs.push Dir.pwd unless $visited_dirs.index(Dir.pwd)
1090
1200
  ## XXX make sure thre is something to pop
1091
1201
  d = $visited_dirs.delete_at 0
1092
1202
  ## XXX make sure the dir exists, cuold have been deleted. can be an error or crash otherwise
1093
1203
  $visited_dirs.push d
1094
1204
  Dir.chdir d
1095
- $filterstr ||= "M"
1205
+ $filterstr ||= 'M'
1096
1206
  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}#{$filterstr})'`.split("\n")
1097
1207
  $files = sort_file_list $files
1098
1208
  post_cd
@@ -1100,14 +1210,14 @@ end
1100
1210
 
1101
1211
  # after changing directory
1102
1212
  def post_cd
1103
- $patt=nil
1213
+ $patt = nil
1104
1214
  $sta = $cursor = 0
1105
1215
  $title = nil
1106
- if $selected_files.size > 0
1107
- $selected_files = []
1108
- end
1216
+ # 2019-03-10 - why am I clearing selected when dir changed !!! FIXME
1217
+ # $selected_files = [] unless $selected_files.empty?
1109
1218
  $visual_block_start = nil
1110
1219
  $stact = 0
1220
+ $current_dir = Dir.pwd # 2019-03-10 - so i don't keep doing in functions
1111
1221
  screen_settings
1112
1222
  # i think this will screw with the dir_pos since it is not filename based.
1113
1223
  enhance_file_list
@@ -1118,103 +1228,108 @@ end
1118
1228
 
1119
1229
  ## read dirs and files and bookmarks from file
1120
1230
  def config_read
1121
- #f = File.expand_path("~/.zfminfo")
1122
- f = File.expand_path(CONFIG_FILE)
1123
- if File.readable? f
1124
- load f
1125
- # maybe we should check for these existing else crash will happen.
1126
- $used_dirs.push(*(DIRS.split ":"))
1127
- $used_dirs.concat get_env_paths
1128
- $visited_files.push(*(FILES.split ":"))
1129
- #$bookmarks.push(*bookmarks) if bookmarks
1130
- chars = ('A'..'Z').to_a
1131
- chars.concat( ('0'..'9').to_a )
1132
- chars.each do |ch|
1133
- if Kernel.const_defined? "BM_#{ch}"
1134
- $bookmarks[ch] = Kernel.const_get "BM_#{ch}"
1135
- end
1136
- end
1137
- end
1231
+ # f = File.expand_path("~/.zfminfo")
1232
+ f = File.expand_path(CONFIG_FILE)
1233
+ return unless File.readable? f
1234
+
1235
+ hash = loadYML(f)
1236
+ $used_dirs = hash['DIRS']
1237
+ $visited_files = hash['FILES']
1238
+ $bookmarks = hash['BOOKMARKS']
1239
+ $used_dirs.concat get_env_paths
1138
1240
  end
1241
+
1139
1242
  def get_env_paths
1140
1243
  files = []
1141
- %w{ GEM_HOME PYTHONHOME}.each do |p|
1244
+ %w[GEM_HOME PYTHONHOME].each do |p|
1142
1245
  d = ENV[p]
1143
1246
  files.push d if d
1144
1247
  end
1145
- %w{ RUBYLIB RUBYPATH GEM_PATH PYTHONPATH }.each do |p|
1248
+ %w[RUBYLIB RUBYPATH GEM_PATH PYTHONPATH].each do |p|
1146
1249
  d = ENV[p]
1147
- files.concat d.split(":") if d
1250
+ files.concat d.split(':') if d
1148
1251
  end
1149
- return files
1252
+ files
1150
1253
  end
1151
1254
 
1152
1255
  ## save dirs and files and bookmarks to a file
1256
+ # - moved to yml 2019-03-09
1153
1257
  def config_write
1154
1258
  # Putting it in a format that zfm can also read and write
1155
- #f1 = File.expand_path("~/.zfminfo")
1156
- f1 = File.expand_path(CONFIG_FILE)
1157
- d = $used_dirs.join ":"
1158
- f = $visited_files.join ":"
1159
- File.open(f1, 'w+') do |f2|
1160
- # use "\n" for two lines of text
1161
- f2.puts "DIRS=\"#{d}\""
1162
- f2.puts "FILES=\"#{f}\""
1163
- $bookmarks.each_pair { |k, val|
1164
- f2.puts "BM_#{k}=\"#{val}\""
1165
- #f2.puts "BOOKMARKS[\"#{k}\"]=\"#{val}\""
1166
- }
1167
- end
1259
+ f1 = File.expand_path(CONFIG_FILE)
1260
+ hash = {}
1261
+ hash['DIRS'] = $used_dirs.select {|dir| File.exist? dir}
1262
+ hash['FILES'] = $visited_files.select {|file| File.exist? file}
1263
+ hash['BOOKMARKS'] = $bookmarks
1264
+ writeYML hash, f1
1168
1265
  $writing = $modified = false
1169
1266
  end
1170
1267
 
1268
+ # {{{ YML
1269
+ require 'yaml'
1270
+ def loadYML( filename)
1271
+ hash = YAML::load( File.open( filename ) )
1272
+ if $opt_debug
1273
+ $stderr.puts hash.keys.size
1274
+ end
1275
+ return hash
1276
+ end
1277
+ def writeYML obj, filename
1278
+ File.open(filename, 'w') {|f| f.write obj.to_yaml }
1279
+ if $opt_debug
1280
+ $stderr.puts "Written to file #{filename}"
1281
+ end
1282
+ end
1283
+ # }}}
1171
1284
  ## accept a character to save this dir as a bookmark
1172
1285
  def create_bookmark
1173
- print "Enter A to Z or 0-9 for bookmark: "
1286
+ print 'Enter A to Z or 0-9 for bookmark: '
1174
1287
  ch = get_char
1175
1288
  if ch =~ /^[0-9A-Z]$/
1176
1289
  $bookmarks[ch] = "#{Dir.pwd}:#{$cursor}"
1177
1290
  $modified = true
1178
1291
  else
1179
- perror "Bookmark must be upper-case character or number."
1292
+ perror 'Bookmark must be upper-case character or number.'
1180
1293
  end
1181
1294
  end
1295
+
1182
1296
  def subcommand
1183
- print "Enter command: "
1297
+ print 'Enter command: '
1184
1298
  begin
1185
- #command = gets().chomp
1186
- command = Readline::readline('>', true)
1187
- return if command == ""
1299
+ # command = gets().chomp
1300
+ command = Readline.readline('>', true)
1301
+ return if command == ''
1188
1302
  rescue Exception => ex
1189
1303
  return
1190
1304
  end
1191
- if command == "q"
1305
+ if command == 'q'
1192
1306
  if $modified
1193
- print "Do you want to save bookmarks? (y/n): "
1307
+ print 'Do you want to save bookmarks? (y/n): '
1194
1308
  ch = get_char
1195
- if ch == "y"
1309
+ if ch == 'y'
1196
1310
  $writing = true
1197
1311
  $quitting = true
1198
- elsif ch == "n"
1312
+ elsif ch == 'n'
1199
1313
  $quitting = true
1200
- print "Quitting without saving bookmarks"
1314
+ print 'Quitting without saving bookmarks'
1201
1315
  else
1202
- perror "No action taken."
1316
+ perror 'No action taken.'
1203
1317
  end
1204
1318
  else
1205
1319
  $quitting = true
1206
1320
  end
1207
- elsif command == "wq"
1321
+ elsif command == 'wq'
1208
1322
  $quitting = true
1209
1323
  $writing = true
1210
- elsif command == "x"
1324
+ elsif command == 'x'
1211
1325
  $quitting = true
1212
1326
  $writing = true if $modified
1213
- elsif command == "p"
1327
+ elsif command == 'p'
1214
1328
  system 'echo $PWD | pbcopy'
1215
1329
  puts 'Stored PWD in clipboard (using pbcopy)'
1216
1330
  end
1217
1331
  end
1332
+
1218
1333
  def quit_command
1219
1334
  if $modified
1220
1335
  puts 'Press w to save bookmarks before quitting ' if $modified
@@ -1228,91 +1343,102 @@ def quit_command
1228
1343
  end
1229
1344
 
1230
1345
  def views
1231
- views=%w[/ om oa Om OL oL On on]
1232
- viewlabels=%w[Dirs Newest Accessed Oldest Largest Smallest Reverse Name]
1346
+ views = %w[/ om oa Om OL oL On on]
1347
+ viewlabels = %w[Dirs Newest Accessed Oldest Largest Smallest Reverse Name]
1233
1348
  $sorto = views[$viewctr]
1234
1349
  $title = viewlabels[$viewctr]
1235
1350
  $viewctr += 1
1236
1351
  $viewctr = 0 if $viewctr > views.size
1237
1352
 
1238
1353
  $files = `zsh -c 'print -rl -- *(#{$sorto}#{$hidden}M)'`.split("\n")
1239
-
1240
1354
  end
1355
+
1241
1356
  def child_dirs
1242
- $title = "Child directories"
1357
+ $title = 'Child directories'
1243
1358
  $files = `zsh -c 'print -rl -- *(/#{$sorto}#{$hidden}M)'`.split("\n")
1244
1359
  end
1360
+
1245
1361
  def dirtree
1246
- $title = "Child directories"
1362
+ $title = 'Child directories'
1247
1363
  $files = `zsh -c 'print -rl -- **/*(/#{$sorto}#{$hidden}M)'`.split("\n")
1248
1364
  end
1365
+
1249
1366
  #
1250
1367
  # Get a full recursive listing of what's in this dir - useful for small projects with more
1251
1368
  # structure than files.
1252
1369
  def tree
1253
1370
  # Caution: use only for small projects, don't use in root.
1254
- $title = "Full Tree"
1371
+ $title = 'Full Tree'
1255
1372
  $files = `zsh -c 'print -rl -- **/*(#{$sorto}#{$hidden}M)'`.split("\n")
1256
1373
  end
1374
+
1257
1375
  # lists recent files in current dir
1258
- # TODO in some cases it shows mostly .git files, we need to prune those
1376
+ # In some cases it shows mostly .git files, we need to prune those
1259
1377
  def recent_files
1260
1378
  # print -rl -- **/*(Dom[1,10])
1261
- $title = "Recent files"
1262
- $files = `zsh -c 'print -rl -- **/*(Dom[1,15])'`.split("\n")
1379
+ $title = 'Recent files'
1380
+ $files = `zsh -c 'print -rl -- **/*(Dom[1,15])'`.split("\n").reject {|f| f[0] == '.'}
1263
1381
  end
1264
1382
 
1265
1383
  def select_current
1266
1384
  ## vp is local there, so i can do $vp[0]
1267
- #open_file $view[$sta] if $view[$sta]
1385
+ # open_file $view[$sta] if $view[$sta]
1268
1386
  open_file $view[$cursor] if $view[$cursor]
1269
1387
  end
1270
1388
 
1271
1389
  ## create a list of dirs in which some action has happened, for saving
1272
- def push_used_dirs d=Dir.pwd
1390
+ def push_used_dirs(d = Dir.pwd)
1273
1391
  $used_dirs.index(d) || $used_dirs.push(d)
1274
1392
  end
1275
- def pbold text
1393
+
1394
+ def pbold(text)
1276
1395
  puts "#{BOLD}#{text}#{BOLD_OFF}"
1277
1396
  end
1278
- def perror text
1397
+
1398
+ def perror(text)
1279
1399
  puts "#{RED}#{text}#{CLEAR}"
1280
1400
  get_char
1281
1401
  end
1282
- def pause text=" Press a key ..."
1402
+
1403
+ def pause(text = ' Press a key ...')
1283
1404
  print text
1284
1405
  get_char
1285
1406
  end
1407
+
1286
1408
  ## return shortcut for an index (offset in file array)
1287
1409
  # use 2 more arrays to make this faster
1288
1410
  # if z or Z take another key if there are those many in view
1289
1411
  # Also, display ROWS * COLS so now we are not limited to 60.
1290
- def get_shortcut ix
1291
- return "<" if ix < $stact
1412
+ def get_shortcut(ix)
1413
+ return '<' if ix < $stact
1414
+
1292
1415
  ix -= $stact
1293
1416
  i = $IDX[ix]
1294
1417
  return i if i
1295
- return "->"
1418
+
1419
+ '->'
1296
1420
  end
1421
+
1297
1422
  ## returns the integer offset in view (file array based on a-y za-zz and Za - Zz
1298
1423
  # Called when user types a key
1299
1424
  # should we even ask for a second key if there are not enough rows
1300
1425
  # What if we want to also trap z with numbers for other purposes
1301
- def get_index key, vsz=999
1426
+ def get_index(key, vsz = 999)
1302
1427
  i = $IDX.index(key)
1303
- return i+$stact if i
1304
- #sz = $IDX.size
1428
+ return i + $stact if i
1429
+
1430
+ # sz = $IDX.size
1305
1431
  zch = nil
1306
1432
  if vsz > 25
1307
- if key == "z" || key == "Z"
1433
+ if key == 'z' || key == 'Z'
1308
1434
  print key
1309
1435
  zch = get_char
1310
1436
  print zch
1311
1437
  i = $IDX.index("#{key}#{zch}")
1312
- return i+$stact if i
1438
+ return i + $stact if i
1313
1439
  end
1314
1440
  end
1315
- return nil
1441
+ nil
1316
1442
  end
1317
1443
 
1318
1444
  def delete_file
@@ -1323,21 +1449,22 @@ end
1323
1449
  # prompt is the user friendly text of command such as list for ls, or extract for dtrx, page for less
1324
1450
  # pauseyn is whether to pause after command as in file or ls
1325
1451
  #
1326
- def command_file prompt, *command
1452
+ def command_file(prompt, *command)
1327
1453
  pauseyn = command.shift
1328
- command = command.join " "
1329
- print "[#{prompt}] Choose a file [#{$view[$cursor]}]: "
1330
- file = ask_hint $view[$cursor]
1331
- #print "#{prompt} :: Enter file shortcut: "
1332
- #file = ask_hint
1333
- perror "Command Cancelled" unless file
1454
+ command = command.join ' '
1455
+ print "[#{prompt}] Choose a file [#{$view[$cursor]}]: "
1456
+ file = ask_hint $view[$cursor]
1457
+ # print "#{prompt} :: Enter file shortcut: "
1458
+ # file = ask_hint
1459
+ perror 'Command Cancelled' unless file
1334
1460
  return unless file
1461
+
1335
1462
  file = File.expand_path(file)
1336
- if File.exists? file
1463
+ if File.exist? file
1337
1464
  file = Shellwords.escape(file)
1338
1465
  pbold "#{command} #{file} (#{pauseyn})"
1339
1466
  system "#{command} #{file}"
1340
- pause if pauseyn == "y"
1467
+ pause if pauseyn == 'y'
1341
1468
  refresh
1342
1469
  else
1343
1470
  perror "File #{file} not found"
@@ -1346,31 +1473,30 @@ end
1346
1473
 
1347
1474
  ## prompt user for file shortcut and return file or nil
1348
1475
  #
1349
- def ask_hint deflt=nil
1476
+ def ask_hint(deflt = nil)
1350
1477
  f = nil
1351
1478
  ch = get_char
1352
- if ch == "ENTER"
1353
- return deflt
1354
- end
1479
+ return deflt if ch == 'ENTER'
1480
+
1355
1481
  ix = get_index(ch, $viewport.size)
1356
1482
  f = $viewport[ix] if ix
1357
- return f
1483
+ f
1358
1484
  end
1359
1485
 
1360
1486
  ## check screen size and accordingly adjust some variables
1361
1487
  #
1362
1488
  def screen_settings
1363
- $glines = %x(tput lines).to_i
1364
- $gcols = %x(tput cols).to_i
1489
+ $glines = `tput lines`.to_i
1490
+ $gcols = `tput cols`.to_i
1365
1491
  $grows = $glines - 3
1366
1492
  $pagesize = 60
1367
- #$gviscols = 3
1493
+ # $gviscols = 3
1368
1494
  $pagesize = $grows * $gviscols
1369
1495
  end
1370
1496
 
1371
1497
  ## moves column offset so we can reach unindexed columns or entries
1372
1498
  # 0 forward and any other back/prev
1373
- def column_next dir = 0
1499
+ def column_next(dir = 0)
1374
1500
  if dir == 0
1375
1501
  $stact += $grows
1376
1502
  $stact = 0 if $stact >= $viewport.size
@@ -1382,12 +1508,14 @@ end
1382
1508
 
1383
1509
  # currently i am only passing the action in from the list there as a key
1384
1510
  # I should be able to pass in new actions that are external commands
1385
- def file_actions(action=nil)
1386
- h = { :d => :delete, :m => :move, :r => :rename, :v => ENV["EDITOR"] || :vim,
1387
- :c => :copy, :C => :chdir,
1388
- :l => :less, :s => :most , :f => :file , :o => :open, :x => :dtrx, :z => :zip }
1389
- #acttext = h[action.to_sym] || action
1390
- acttext = action || ""
1511
+ # 2019-03-08 - TODO when a file name changes or moves it must be removed
1512
+ # from selection
1513
+ def file_actions(action = nil)
1514
+ h = { d: :delete, m: :move, r: :rename, v: ENV['EDITOR'] || :vim,
1515
+ c: :copy, C: :chdir, W: :remspace,
1516
+ l: :less, s: :most, f: :file, o: :open, x: :dtrx, z: :zip }
1517
+ # acttext = h[action.to_sym] || action
1518
+ acttext = action || ''
1391
1519
  file = nil
1392
1520
 
1393
1521
  sct = $selected_files.size
@@ -1395,11 +1523,20 @@ def file_actions(action=nil)
1395
1523
  text = "#{sct} files"
1396
1524
  file = $selected_files
1397
1525
  else
1398
- print "[#{acttext}] Choose a file [#{$view[$cursor]}]: "
1399
- file = ask_hint $view[$cursor]
1526
+ # 2019-03-07 - trying out direct deletes
1527
+ # why were we aksing to select a file when user is on a file
1528
+ # print "[#{acttext}] Choose a file [#{$view[$cursor]}]: "
1529
+ # file = ask_hint $view[$cursor]
1530
+ file = $view[$cursor]
1531
+ unless file
1532
+ file = ask_hint $view[$cursor]
1533
+ end
1400
1534
  return unless file
1535
+
1401
1536
  text = file
1402
1537
  end
1538
+ # 2019-03-07 - NOTE at this point file can be one or more files.
1539
+ # 2019-03-07 - text can be a file or count of files, so unreliable !!! FIXME
1403
1540
 
1404
1541
  case file
1405
1542
  when Array
@@ -1409,67 +1546,138 @@ def file_actions(action=nil)
1409
1546
  files = Shellwords.escape(file)
1410
1547
  end
1411
1548
 
1412
-
1413
1549
  ch = nil
1414
1550
  if action
1415
- menu_text = action
1551
+ menu_text = action
1416
1552
  else
1417
1553
  ch, menu_text = menu "File Menu for #{text}", h
1418
1554
  menu_text = :quit if ch == 'q'
1419
1555
  end
1556
+ return unless menu_text # pressed some wrong key
1557
+
1420
1558
  case menu_text.to_sym
1559
+
1421
1560
  when :quit
1561
+
1422
1562
  when :delete
1423
- print "rmtrash #{files} ?[yn]: "
1563
+ delcommand = 'rmtrash'
1564
+ print "#{delcommand} #{files} ?[yn]: "
1424
1565
  ch = get_char
1425
- return if ch != "y"
1426
- system "rmtrash #{files}"
1566
+ return if ch != 'y'
1567
+
1568
+ system "#{delcommand} #{files}"
1427
1569
  refresh
1570
+
1428
1571
  when :move
1572
+ # 2019-03-07 - NOTE this will only work with single file selection
1429
1573
  print "move #{text} to : "
1430
- #target = gets().chomp
1431
- target = Readline::readline('>', true)
1432
- text=File.expand_path(text)
1433
- return if target == ""
1574
+ # target = gets().chomp
1575
+ # target = Readline.readline('>', true)
1576
+ target = readline
1577
+ return unless target
1578
+
1579
+ target = '.' if target == ''
1580
+ # 2019-03-07 - NOTE cannot use text if multiple files
1581
+ # text = File.expand_path(text)
1582
+ target = File.expand_path(target)
1583
+ return if target == ''
1584
+
1434
1585
  if File.directory? target
1435
- FileUtils.mv text, target
1586
+ begin
1587
+ FileUtils.mv file, target
1588
+ rescue StandardError => exc
1589
+ perror exc.to_s
1590
+ end
1591
+ # 2019-03-08 - TODO if success remove from selection
1436
1592
  refresh
1437
1593
  else
1438
- perror "Target not a dir"
1594
+ perror 'Target not a dir'
1439
1595
  end
1596
+
1440
1597
  when :copy
1598
+ # Target must be directory
1441
1599
  print "copy #{text} to : "
1442
- target = Readline::readline('>', true)
1443
- return if target == ""
1444
- text=File.expand_path(text)
1445
- target = File.basename(text) if target == "."
1446
- if File.exists? target
1447
- perror "Target (#{target}) exists"
1448
- else
1449
- FileUtils.cp text, target
1600
+ target = readline
1601
+ return unless target # C-c
1602
+
1603
+ target = '.' if target == ''
1604
+ target = File.expand_path(target)
1605
+ return if target == ''
1606
+
1607
+ if File.directory? target
1608
+ begin
1609
+ FileUtils.cp file, target
1610
+ rescue StandardError => exc
1611
+ perror exc.to_s
1612
+ end
1450
1613
  refresh
1614
+ else
1615
+ perror 'Copy target must be a dir'
1451
1616
  end
1617
+
1452
1618
  when :chdir
1453
1619
  change_dir File.dirname(text)
1620
+
1454
1621
  when :zip
1455
- print "Archive name: "
1456
- #target = gets().chomp
1457
- target = Readline::readline('>', true)
1458
- return if target == ""
1622
+ print 'Archive name: '
1623
+ # target = gets().chomp
1624
+ target = Readline.readline('>', true)
1625
+ return if target == ''
1626
+
1459
1627
  # don't want a blank space or something screwing up
1460
1628
  if target && target.size > 3
1461
- if File.exists? target
1629
+ if File.exist? target
1462
1630
  perror "Target (#{target}) exists"
1463
1631
  else
1464
1632
  system "tar zcvf #{target} #{files}"
1465
1633
  refresh
1466
1634
  end
1467
1635
  end
1636
+
1468
1637
  when :rename
1638
+ # 2019-03-07 NOTE works for single file FIXME
1639
+ # 2019-03-07 - TODO for n files replace pattern with string
1640
+ print "rename #{text} to : "
1641
+ target = Readline.readline('>', true)
1642
+ return if target == ''
1643
+
1644
+ text = File.expand_path(text)
1645
+ target = File.basename(text) if target == '.'
1646
+ if File.exist? target
1647
+ perror "Target (#{target}) exists"
1648
+ else
1649
+ FileUtils.mv text, target
1650
+ refresh
1651
+ end
1469
1652
  when :most, :less, :vim
1470
1653
  system "#{menu_text} #{files}"
1654
+ # should we remove from selection ?
1655
+
1656
+ when :remspace
1657
+ # 2019-03-08 - 00:07 added replace space with underscore in filename
1658
+ print "Remove spaces from #{file}"
1659
+ pause
1660
+ farray = nil
1661
+
1662
+ # stupidly using one variable for scalar and array DUH !
1663
+ case file
1664
+ when String
1665
+ farray = [file]
1666
+ when Array
1667
+ farray = file
1668
+ end
1669
+
1670
+ farray.each do |f|
1671
+ if f.index ' '
1672
+ nname = f.tr(' ', '_')
1673
+ FileUtils.mv f, nname unless File.exist? nname
1674
+ # if success then remove from selection
1675
+ end
1676
+ end
1677
+ refresh
1471
1678
  else
1472
1679
  return unless menu_text
1680
+
1473
1681
  print "#{menu_text} #{files}"
1474
1682
  pause
1475
1683
  print
@@ -1477,13 +1685,16 @@ def file_actions(action=nil)
1477
1685
  refresh
1478
1686
  pause
1479
1687
  end
1480
- # remove non-existent files from select list due to move or delete or rename or whatever
1688
+
1689
+ # remove non-existent files from select list due to move or delete
1690
+ # or rename or whatever
1481
1691
  if sct > 0
1482
- $selected_files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
1692
+ $selected_files.select! { |x| x = File.expand_path(x); File.exist?(x) }
1483
1693
  end
1484
1694
  end
1485
1695
 
1486
- def columns_incdec howmany
1696
+ # increase or decrease column
1697
+ def columns_incdec(howmany)
1487
1698
  $gviscols += howmany.to_i
1488
1699
  $gviscols = 1 if $gviscols < 1
1489
1700
  $gviscols = 6 if $gviscols > 6
@@ -1493,59 +1704,65 @@ end
1493
1704
  # bind a key to an external command wich can be then be used for files
1494
1705
  def bindkey_ext_command
1495
1706
  print
1496
- pbold "Bind a capital letter to an external command"
1497
- print "Enter a capital letter to bind: "
1707
+ pbold 'Bind a capital letter to an external command'
1708
+ print 'Enter a capital letter to bind: '
1498
1709
  ch = get_char
1499
- return if ch == "Q"
1710
+ return if ch == 'Q'
1711
+
1500
1712
  if ch =~ /^[A-Z]$/
1501
1713
  print "Enter an external command to bind to #{ch}: "
1502
- com = gets().chomp
1503
- if com != ""
1504
- print "Enter prompt for command (blank if same as command): "
1505
- pro = gets().chomp
1506
- pro = com if pro == ""
1714
+ com = gets.chomp
1715
+ if com != ''
1716
+ print 'Enter prompt for command (blank if same as command): '
1717
+ pro = gets.chomp
1718
+ pro = com if pro == ''
1507
1719
  end
1508
- print "Pause after output [y/n]: "
1720
+ print 'Pause after output [y/n]: '
1509
1721
  yn = get_char
1510
1722
  $bindings[ch] = "command_file #{pro} #{yn} #{com}"
1511
1723
  end
1512
1724
  end
1513
- def ack
1514
- print "Enter a pattern to search (ack): "
1515
- #pattern = gets.chomp
1516
- pattern = Readline::readline('>', true)
1517
- return if pattern == ""
1518
- $title = "Files found using 'ack' #{pattern}"
1519
- system("ack #{pattern}")
1725
+
1726
+ def ag
1727
+ print 'Enter a pattern to search (ag): '
1728
+ pattern = Readline.readline('>', true)
1729
+ return if pattern == ''
1730
+
1731
+ $title = "Files found using 'ag' #{pattern}"
1732
+ system("ag #{pattern}")
1520
1733
  pause
1521
- files = `ack -l #{pattern}`.split("\n")
1522
- if files.size == 0
1523
- perror "No files found."
1734
+ files = `ag -l #{pattern}`.split("\n")
1735
+ if files.empty?
1736
+ perror 'No files found.'
1524
1737
  else
1525
1738
  $files = files
1526
1739
  end
1527
1740
  end
1741
+
1528
1742
  def ffind
1529
- print "Enter a file name pattern to find: "
1530
- pattern = Readline::readline('>', true)
1531
- return if pattern == ""
1743
+ print 'Enter a file name pattern to find: '
1744
+ pattern = Readline.readline('>', true)
1745
+ return if pattern == ''
1746
+
1532
1747
  $title = "Files found using 'find' #{pattern}"
1533
1748
  files = `find . -name '#{pattern}'`.split("\n")
1534
- if files.size == 0
1535
- perror "No files found."
1749
+ if files.empty?
1750
+ perror 'No files found.'
1536
1751
  else
1537
1752
  $files = files
1538
1753
  end
1539
1754
  end
1755
+
1540
1756
  def locate
1541
- print "Enter a file name pattern to locate: "
1542
- pattern = Readline::readline('>', true)
1543
- return if pattern == ""
1757
+ print 'Enter a file name pattern to locate: '
1758
+ pattern = Readline.readline('>', true)
1759
+ return if pattern == ''
1760
+
1544
1761
  $title = "Files found using 'locate' #{pattern}"
1545
1762
  files = `locate #{pattern}`.split("\n")
1546
- files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
1547
- if files.size == 0
1548
- perror "No files found."
1763
+ files.select! { |x| x = File.expand_path(x); File.exist?(x) }
1764
+ if files.empty?
1765
+ perror 'No files found.'
1549
1766
  else
1550
1767
  $files = files
1551
1768
  end
@@ -1555,12 +1772,12 @@ end
1555
1772
  # then you can modify this accordingly.
1556
1773
  #
1557
1774
  def viminfo
1558
- file = File.expand_path("~/.viminfo")
1559
- if File.exists? file
1560
- $title = "Files from ~/.viminfo"
1561
- #$files = `grep '^>' ~/.viminfo | cut -d ' ' -f 2- | sed "s#~#$HOME#g"`.split("\n")
1775
+ file = File.expand_path('~/.viminfo')
1776
+ if File.exist? file
1777
+ $title = 'Files from ~/.viminfo'
1778
+ # $files = `grep '^>' ~/.viminfo | cut -d ' ' -f 2- | sed "s#~#$HOME#g"`.split("\n")
1562
1779
  $files = `grep '^>' ~/.viminfo | cut -d ' ' -f 2- `.split("\n")
1563
- $files.reject! {|x| x = File.expand_path(x); !File.exists?(x) }
1780
+ $files.select! { |x| x = File.expand_path(x); File.exist?(x) }
1564
1781
  end
1565
1782
  end
1566
1783
 
@@ -1568,43 +1785,49 @@ end
1568
1785
  # modify this accordingly
1569
1786
  #
1570
1787
  def z_interface
1571
- file = File.expand_path("~/.z")
1572
- if File.exists? file
1573
- $title = "Directories from ~/.z"
1788
+ file = File.expand_path('~/.z')
1789
+ if File.exist? file
1790
+ $title = 'Directories from ~/.z'
1574
1791
  $files = `sort -rn -k2 -t '|' ~/.z | cut -f1 -d '|'`.split("\n")
1575
1792
  home = ENV['HOME']
1576
1793
  $files.collect! do |f|
1577
- f.sub(/#{home}/,"~")
1794
+ f.sub(/#{home}/, '~')
1578
1795
  end
1579
1796
  end
1580
1797
  end
1581
1798
 
1799
+ def vidir
1800
+ system "vidir"
1801
+ end
1582
1802
  ## there is no one consisten way i am getting.
1583
1803
  # i need to do a shell join if I am to pipe ffiles to say: xargs ls -t
1584
1804
  # but if i want to pipe names to grep xxx then i need to join with newlines
1585
- def pipe
1586
- end
1805
+ def pipe; end
1587
1806
 
1588
1807
  ## some cursor movement functions
1589
1808
  ##
1590
1809
  #
1591
1810
  def cursor_scroll_dn
1592
- moveto(pos() + MSCROLL)
1811
+ moveto(pos + MSCROLL)
1593
1812
  end
1813
+
1594
1814
  def cursor_scroll_up
1595
- moveto(pos() - MSCROLL)
1815
+ moveto(pos - MSCROLL)
1596
1816
  end
1817
+
1597
1818
  def cursor_dn
1598
- moveto(pos() + 1)
1819
+ moveto(pos + 1)
1599
1820
  end
1821
+
1600
1822
  def cursor_up
1601
- moveto(pos() - 1)
1823
+ moveto(pos - 1)
1602
1824
  end
1825
+
1603
1826
  def pos
1604
1827
  $cursor
1605
1828
  end
1606
1829
 
1607
- def moveto pos
1830
+ def moveto(pos)
1608
1831
  orig = $cursor
1609
1832
  $cursor = pos
1610
1833
  $cursor = [$cursor, $view.size - 1].min
@@ -1613,21 +1836,62 @@ def moveto pos
1613
1836
  fin = [orig, $cursor].max
1614
1837
  if $visual_mode
1615
1838
  # PWD has to be there in selction
1616
- if $selected_files.index $view[$cursor]
1839
+ # TODO: add full path TESTME
1840
+ if selected? current_file
1617
1841
  # this depends on the direction
1618
- $selected_files = $selected_files - $view[star..fin]
1842
+ # $selected_files = $selected_files - $view[star..fin]
1843
+ remove_from_selection $view[star..fin]
1619
1844
  ## current row remains in selection always.
1620
- $selected_files.push $view[$cursor]
1845
+ add_to_selection current_file
1621
1846
  else
1622
- $selected_files.concat $view[star..fin]
1847
+ # $selected_files.concat $view[star..fin]
1848
+ add_to_selection $view[star..fin]
1623
1849
  end
1624
1850
  end
1625
1851
  end
1852
+
1853
+ # is given file in selected array
1854
+ def selected?(file)
1855
+ $current_dir ||= Dir.pwd
1856
+ file = File.join($current_dir, file)
1857
+ return $selected_files.index file
1858
+ end
1859
+
1860
+ # TODO: can be array
1861
+ def add_to_selection(file)
1862
+ ff = file
1863
+ case file
1864
+ when String
1865
+ ff = [file]
1866
+ end
1867
+ $current_dir ||= Dir.pwd
1868
+ ff.each do |f|
1869
+ full = File.join($current_dir, f)
1870
+ $selected_files.push full
1871
+ end
1872
+ end
1873
+
1874
+ # TODO: can be array
1875
+ def remove_from_selection(file)
1876
+ ff = file
1877
+ case file
1878
+ when String
1879
+ ff = [file]
1880
+ end
1881
+ $current_dir ||= Dir.pwd
1882
+ ff.each do |f|
1883
+ full = File.join($current_dir, f)
1884
+ $selected_files.delete full
1885
+ end
1886
+ end
1887
+
1626
1888
  def visual_mode_toggle
1627
1889
  $visual_mode = !$visual_mode
1628
1890
  if $visual_mode
1629
1891
  $visual_block_start = $cursor
1630
- $selected_files.push $view[$cursor]
1892
+ # TODO: add full path TESTME
1893
+ # $selected_files.push $view[$cursor]
1894
+ add_to_selection current_file
1631
1895
  end
1632
1896
  end
1633
1897
 
@@ -1635,69 +1899,77 @@ def visual_block_clear
1635
1899
  if $visual_block_start
1636
1900
  star = [$visual_block_start, $cursor].min
1637
1901
  fin = [$visual_block_start, $cursor].max
1638
- $selected_files = $selected_files - $view[star..fin]
1902
+ # TODO: add full path TESTME
1903
+ # $selected_files = $selected_files - $view[star..fin]
1904
+ remove_from_selection $view[star..fin]
1639
1905
  end
1640
1906
  $visual_block_start = nil
1641
1907
  $visual_mode = nil
1642
1908
  end
1643
1909
 
1644
- def file_starting_with fc
1645
- ix = return_next_match(method(:file_matching?), "^#{fc}")
1646
- if ix
1647
- goto_line ix
1648
- end
1910
+ def file_starting_with(first_char)
1911
+ ix = return_next_match(method(:file_matching?), "^#{first_char}")
1912
+ goto_line ix if ix
1649
1913
  end
1650
- def file_matching? file, patt
1914
+
1915
+ def file_matching?(file, patt)
1651
1916
  file =~ /#{patt}/
1652
1917
  end
1653
1918
 
1654
1919
  ## generic method to take cursor to next position for a given condition
1655
- def return_next_match binding, *args
1920
+ def return_next_match(binding, *args)
1656
1921
  first = nil
1657
1922
  ix = 0
1658
- $view.each_with_index do |elem,ii|
1659
- if binding.call(elem, *args)
1660
- first ||= ii
1661
- if ii > $cursor
1662
- ix = ii
1663
- break
1664
- end
1923
+ $view.each_with_index do |elem, ii|
1924
+ next unless binding.call(elem, *args)
1925
+
1926
+ first ||= ii
1927
+ if ii > $cursor
1928
+ ix = ii
1929
+ break
1665
1930
  end
1666
1931
  end
1667
1932
  return first if ix == 0
1668
- return ix
1933
+
1934
+ ix
1669
1935
  end
1936
+
1670
1937
  ##
1671
1938
  # position cursor on a specific line which could be on a nother page
1672
1939
  # therefore calculate the correct start offset of the display also.
1673
- def goto_line pos
1674
- pages = ((pos * 1.00)/$pagesize).ceil
1940
+ def goto_line(pos)
1941
+ pages = ((pos * 1.00) / $pagesize).ceil
1675
1942
  pages -= 1
1676
1943
  $sta = pages * $pagesize + 1
1677
1944
  $cursor = pos
1678
1945
  end
1679
- def filetype f
1946
+
1947
+ def filetype(f)
1680
1948
  return nil unless f
1949
+
1681
1950
  f = Shellwords.escape(f)
1682
1951
  s = `file #{f}`
1683
- if s.index "text"
1952
+ if s.index 'text'
1684
1953
  return :text
1685
1954
  elsif s.index(/[Zz]ip/)
1686
1955
  return :zip
1687
- elsif s.index("archive")
1956
+ elsif s.index('archive')
1688
1957
  return :zip
1689
- elsif s.index "image"
1958
+ elsif s.index 'image'
1690
1959
  return :image
1691
- elsif s.index "data"
1960
+ elsif s.index 'data'
1692
1961
  return :text
1693
1962
  end
1963
+
1694
1964
  nil
1695
1965
  end
1696
1966
 
1697
1967
  def save_dir_pos
1698
1968
  return if $sta == 0 && $cursor == 0
1969
+
1699
1970
  $dir_position[Dir.pwd] = [$sta, $cursor]
1700
1971
  end
1972
+
1701
1973
  def revert_dir_pos
1702
1974
  $sta = 0
1703
1975
  $cursor = 0
@@ -1706,50 +1978,108 @@ def revert_dir_pos
1706
1978
  $sta = a.first
1707
1979
  $cursor = a[1]
1708
1980
  raise "sta is nil for #{Dir.pwd} : #{$dir_position[Dir.pwd]}" unless $sta
1709
- raise "cursor is nil" unless $cursor
1981
+ raise 'cursor is nil' unless $cursor
1710
1982
  end
1711
1983
  end
1984
+
1712
1985
  def newdir
1713
1986
  print
1714
- print "Enter directory name: "
1715
- str = Readline::readline('>', true)
1716
- return if str == ""
1717
- if File.exists? str
1987
+ print 'Enter directory name: '
1988
+ str = Readline.readline('>', true)
1989
+ return if str == ''
1990
+
1991
+ if File.exist? str
1718
1992
  perror "#{str} exists."
1719
1993
  return
1720
1994
  end
1721
1995
  begin
1722
1996
  FileUtils.mkdir str
1723
- $used_dirs.insert(0, str) if File.exists?(str)
1997
+ $used_dirs.insert(0, str) if File.exist?(str)
1724
1998
  refresh
1725
1999
  rescue Exception => ex
1726
2000
  perror "Error in newdir: #{ex}"
1727
2001
  end
1728
2002
  end
2003
+
1729
2004
  def newfile
1730
2005
  print
1731
- print "Enter file name: "
1732
- str = Readline::readline('>', true)
1733
- return if str == ""
1734
- system "$EDITOR #{str}"
1735
- $visited_files.insert(0, str) if File.exists?(str)
2006
+ print 'Enter file name: '
2007
+ str = Readline.readline('>', true)
2008
+ return if str == ''
2009
+
2010
+ # FIXME a file with space will not create single file
2011
+ # 2019-03-10 - maybe touch a file
2012
+
2013
+ system %($EDITOR "#{str}")
2014
+ $visited_files.insert(0, str) if File.exist?(str)
1736
2015
  refresh
1737
2016
  end
1738
2017
 
2018
+
2019
+
2020
+ def current_file
2021
+ $view[$cursor]
2022
+ end
2023
+
2024
+ def current_or_selected_files
2025
+ return $selected_files if $selected_files.size > 0
2026
+
2027
+ return [current_file]
2028
+ end
2029
+
2030
+ # ------------------- scripts ------------------ #
2031
+ # prompt for scripts to execute, giving selected file names
2032
+ def scripts
2033
+ title = 'Select a script'
2034
+ script_path = '~/.config/cetus/scripts'
2035
+ binding = `find #{script_path} -type f | fzf --prompt="#{title.to_s} :"`
2036
+ return unless binding
2037
+
2038
+ binding = binding.chomp if binding
2039
+ # TODO: check if binding is a file and executable
2040
+ # xargs only seems to take the first file
2041
+ # cf = current_or_selected_files.join('\0')
2042
+ # cf = Shellwords.join(current_or_selected_files)
2043
+ current_or_selected_files.each do |file|
2044
+ system %( #{binding} "#{file}" )
2045
+ end
2046
+ # system %(echo "#{cf}" | xargs #{binding})
2047
+ pause
2048
+ end
2049
+ # ------------- end of scripts --------------------------------#
2050
+
2051
+ # ------------------- page_selection ------------------ #
2052
+ def page_selection
2053
+ require 'tempfile'
2054
+ file = Tempfile.new('selected_files')
2055
+ begin
2056
+ $selected_files.each { |row| file.puts row }
2057
+ file.flush
2058
+ system "$PAGER #{file.path}"
2059
+ rescue
2060
+ file.close
2061
+ file.unlink
2062
+ end
2063
+ end
2064
+ # ------------- end of page_selection --------------------------------#
1739
2065
  ##
1740
2066
  # Editing of the User Dir List.
1741
2067
  # remove current entry from used dirs list, since we may not want some entries being there
1742
2068
  #
1743
2069
  def remove_from_list
1744
- if $selected_files.size > 0
2070
+ unless $selected_files.empty?
1745
2071
  sz = $selected_files.size
1746
2072
  print "Remove #{sz} files from used list (y)?: "
1747
2073
  ch = get_char
1748
- return if ch != "y"
1749
- $used_dirs = $used_dirs - $selected_files
1750
- $visited_files = $visited_files - $selected_files
2074
+ return if ch != 'y'
2075
+
2076
+ arr = $selected_files.map { |path| File.expand_path(path) }
2077
+
2078
+ $used_dirs = $used_dirs - arr
2079
+ $visited_files = $visited_files - arr
1751
2080
  unselect_all
1752
2081
  $modified = true
2082
+ refresh
1753
2083
  return
1754
2084
  end
1755
2085
  print
@@ -1757,7 +2087,8 @@ def remove_from_list
1757
2087
  file = $view[$cursor]
1758
2088
  print "Remove #{file} from used list (y)?: "
1759
2089
  ch = get_char
1760
- return if ch != "y"
2090
+ return if ch != 'y'
2091
+
1761
2092
  file = File.expand_path(file)
1762
2093
  if File.directory? file
1763
2094
  $used_dirs.delete(file)
@@ -1767,6 +2098,7 @@ def remove_from_list
1767
2098
  refresh
1768
2099
  $modified = true
1769
2100
  end
2101
+
1770
2102
  #
1771
2103
  # If there's a short file list, take recently mod and accessed folders and put latest
1772
2104
  # files from there and insert it here. I take both since recent mod can be binaries / object
@@ -1775,15 +2107,16 @@ end
1775
2107
  # include files.
1776
2108
  def enhance_file_list
1777
2109
  return unless $enhanced_mode
2110
+
1778
2111
  # if only one entry and its a dir
1779
2112
  # get its children and maybe the recent mod files a few
1780
2113
 
1781
2114
  if $files.size == 1
1782
2115
  # its a dir, let give the next level at least
1783
- if $files.first[-1] == "/"
2116
+ if $files.first[-1] == '/'
1784
2117
  d = $files.first
1785
2118
  f = `zsh -c 'print -rl -- #{d}*(omM)'`.split("\n")
1786
- if f && f.size > 0
2119
+ if f && !f.empty?
1787
2120
  $files.concat f
1788
2121
  $files.concat get_important_files(d)
1789
2122
  return
@@ -1797,28 +2130,28 @@ def enhance_file_list
1797
2130
  # check if a ruby project dir, although it could be a backup file too,
1798
2131
  # if so , expand lib and maby bin, put a couple recent files
1799
2132
  #
1800
- if $files.index("Gemfile") || $files.grep(/\.gemspec/).size > 0
2133
+ if $files.index('Gemfile') || !$files.grep(/\.gemspec/).empty?
1801
2134
  # usually the lib dir has only one file and one dir
1802
2135
  flg = false
1803
2136
  $files.concat get_important_files(Dir.pwd)
1804
- if $files.index("lib/")
2137
+ if $files.index('lib/')
1805
2138
  f = `zsh -c 'print -rl -- lib/*(om[1,5]M)'`.split("\n")
1806
- if f && f.size() > 0
1807
- insert_into_list("lib/", f)
2139
+ if f && !f.empty?
2140
+ insert_into_list('lib/', f)
1808
2141
  flg = true
1809
2142
  end
1810
2143
  dd = File.basename(Dir.pwd)
1811
2144
  if f.index("lib/#{dd}/")
1812
2145
  f = `zsh -c 'print -rl -- lib/#{dd}/*(om[1,5]M)'`.split("\n")
1813
- if f && f.size() > 0
2146
+ if f && !f.empty?
1814
2147
  insert_into_list("lib/#{dd}/", f)
1815
2148
  flg = true
1816
2149
  end
1817
2150
  end
1818
2151
  end
1819
- if $files.index("bin/")
2152
+ if $files.index('bin/')
1820
2153
  f = `zsh -c 'print -rl -- bin/*(om[1,5]M)'`.split("\n")
1821
- insert_into_list("bin/", f) if f && f.size() > 0
2154
+ insert_into_list('bin/', f) if f && !f.empty?
1822
2155
  flg = true
1823
2156
  end
1824
2157
  return if flg
@@ -1830,15 +2163,11 @@ def enhance_file_list
1830
2163
 
1831
2164
  ## first check accessed else modified will change accessed
1832
2165
  moda = `zsh -c 'print -rn -- *(/oa[1]M)'`
1833
- if moda && moda != ""
2166
+ if moda && moda != ''
1834
2167
  modf = `zsh -c 'print -rn -- #{moda}*(oa[1]M)'`
1835
- if modf && modf != ""
1836
- insert_into_list moda, modf
1837
- end
2168
+ insert_into_list moda, modf if modf && modf != ''
1838
2169
  modm = `zsh -c 'print -rn -- #{moda}*(om[1]M)'`
1839
- if modm && modm != "" && modm != modf
1840
- insert_into_list moda, modm
1841
- end
2170
+ insert_into_list moda, modm if modm && modm != '' && modm != modf
1842
2171
  end
1843
2172
  ## get last modified dir
1844
2173
  modm = `zsh -c 'print -rn -- *(/om[1]M)'`
@@ -1853,38 +2182,38 @@ def enhance_file_list
1853
2182
  # are the same dir, so we need to find the second modified dir
1854
2183
  end
1855
2184
  end
1856
- def insert_into_list dir, file
1857
- #ix = $files.index(dir)
1858
- #raise "something wrong can find #{dir}." unless ix
1859
- #$files.insert ix, *file
2185
+
2186
+ def insert_into_list(_dir, file)
2187
+ # ix = $files.index(dir)
2188
+ # raise "something wrong can find #{dir}." unless ix
2189
+ # $files.insert ix, *file
1860
2190
  # 2013-03-19 - 19:42 adding at end to avoid confusion
1861
- #$files.concat file
2191
+ # $files.concat file
1862
2192
  $files.push *file
1863
2193
  end
1864
- def get_important_files dir
2194
+
2195
+ def get_important_files(dir)
1865
2196
  # checks various lists like visited_files and bookmarks
1866
2197
  # to see if files from this dir or below are in it.
1867
2198
  # More to be used in a dir with few files.
1868
2199
  list = []
1869
2200
  l = dir.size + 1
1870
2201
  $visited_files.each do |e|
1871
- if e.index(dir) == 0
1872
- list << e[l..-1]
1873
- end
2202
+ list << e[l..-1] if e.index(dir) == 0
1874
2203
  end
1875
2204
  # bookmarks have : which needs to be removed
1876
- #list1 = $bookmarks.values.select do |e|
1877
- #e.index(dir) == 0
1878
- #end
1879
- #list.concat list1
1880
- return list
2205
+ # list1 = $bookmarks.values.select do |e|
2206
+ # e.index(dir) == 0
2207
+ # end
2208
+ # list.concat list1
2209
+ list
1881
2210
  end
1882
2211
 
1883
- Signal.trap('EXIT') {
2212
+ Signal.trap('EXIT') do
1884
2213
  reset_terminal
1885
2214
  # system 'tput rmcup'
1886
2215
  exit
1887
- }
2216
+ end
1888
2217
  run
1889
2218
  # 2019-02-20 - added so alt-screen is used
1890
2219
  system 'tput rmcup'