cetus 0.1.38 → 0.1.39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cetus +148 -51
  3. data/cetus.gemspec +1 -1
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0adbfa483176301769749c1f1756cf6ae616ee572ad5b2ca56c28b2339f0386f
4
- data.tar.gz: 2506a1e5264337d8648022083d7c37a6616d36e1be12b65d29b5172211cbdc67
3
+ metadata.gz: 501ef34e9afd0b98b8cfda66aa5c98fb46d6529f507e95c18951833edc467a0f
4
+ data.tar.gz: 722a4926a42bd426cfac568b2166c041b6a4dda63939e04ea5b6e5c2f3127de6
5
5
  SHA512:
6
- metadata.gz: 7e18775e80ebc7cf5367e4040fb27c73eb2cff2e0cabac603afd1958de18cc1a82055b51c3b13eaaef2b03c0937b9aeff045a29f255b4ab8f7221821e0dc97f0
7
- data.tar.gz: d7efa83ac9196fc74768e6fad5e87df973ec9ba49a44921310462cfe834cd53bb288be52d76f92d7ca6d45b9363e0545dac584ea5a3e47dad28e2fd0344c0daa
6
+ metadata.gz: b19bc7bbf440a8c9df34165c35e5b19134e9b3e3023e348e8eec52a770e784359ca02b7d8618d3b311b9bb802676f252274c8fe8e228a1ddf825fd0016a438eb
7
+ data.tar.gz: 41ad81c2cda30e5a20cc35ea22d4ec0e96630d3e907053713f733d3d61b6ba0fb42a6d9e1de8e367733aeca8a26cb2465f5af3dd7e1848a79cc8a78027640881
data/bin/cetus CHANGED
@@ -8,7 +8,7 @@
8
8
  # Author: rkumar http://github.com/rkumar/cetus/
9
9
  # Date: 2013-02-17 - 17:48
10
10
  # License: GPL
11
- # Last update: 2019-04-19 09:51
11
+ # Last update: 2019-04-21 23:46
12
12
  # --------------------------------------------------------------------------- #
13
13
  # cetus.rb Copyright (C) 2012-2019 rahul kumar
14
14
  # == CHANGELOG
@@ -19,6 +19,7 @@
19
19
  # 2019-03-04 - changed quit to q (earlier Q)
20
20
  # 2019-03-04 - first dirs then files
21
21
  # 2019-03-22 - refactoring the code, esp run()
22
+ # 2019-04-21 - search_as_you_type
22
23
  # == TODO
23
24
 
24
25
  require 'readline'
@@ -29,6 +30,8 @@ require 'shellwords'
29
30
  require 'fileutils'
30
31
  require 'logger'
31
32
  @log = Logger.new(File.expand_path('~/tmp/log.txt'))
33
+ now = Time.now.strftime("%Y-%m-%d %H:%M:%S")
34
+ @log.info "========== cetus started at : #{now} ================= ----------"
32
35
  # @log = Logger.new('log.txt')
33
36
 
34
37
  ## INSTALLATION
@@ -36,7 +39,7 @@ require 'logger'
36
39
  # alias c=~/bin/cetus.rb
37
40
  # c
38
41
 
39
- VERSION = '0.1.38.0'
42
+ VERSION = '0.1.39.0'
40
43
  CONFIG_PATH = ENV['XDG_CONFIG_HOME'] || File.join(ENV['HOME'], '.config')
41
44
  CONFIG_FILE = "#{CONFIG_PATH}/cetus/conf.yml"
42
45
 
@@ -64,7 +67,7 @@ CONFIG_FILE = "#{CONFIG_PATH}/cetus/conf.yml"
64
67
  ':' => 'subcommand',
65
68
  "'" => 'goto_bookmark',
66
69
  '"' => 'file_starting_with',
67
- '/' => 'enter_regex',
70
+ '/' => 'ask_regex',
68
71
  'M-p' => 'prev_page',
69
72
  'M-n' => 'next_page',
70
73
  'PgUp' => 'prev_page',
@@ -191,6 +194,20 @@ def reset_terminal
191
194
  # Show user input.
192
195
  system 'stty echo'
193
196
  end
197
+ # Call before shelling to editor pager and when exiting
198
+ def partial_reset_terminal
199
+ # Reset the terminal to a useable state (undo all changes).
200
+ # '\e[?7h': Re-enable line wrapping.
201
+ # '\e[?25h': Unhide the cursor.
202
+ # '\e[2J': Clear the terminal.
203
+ # '\e[;r': Set the scroll region to its default value.
204
+ # Also sets cursor to (0,0).
205
+ # '\e[?1049l: Restore main screen buffer.
206
+ print "\e[?7h\e[?25h\e[;r\e[?1049l"
207
+
208
+ # Show user input.
209
+ system 'stty echo'
210
+ end
194
211
 
195
212
  # copied from fff
196
213
  # call AFTER shelling to most or vim
@@ -215,7 +232,7 @@ end
215
232
  def readline prompt='>'
216
233
  clear_last_line
217
234
  print "\r"
218
- # do we need to clear till end of line, see enter_regex commented
235
+ # do we need to clear till end of line, see ask_regex commented
219
236
  # unhide cursor
220
237
  print "\e[?25h"
221
238
  system 'stty echo'
@@ -318,7 +335,7 @@ PAGER_COMMAND = {
318
335
  unknown: 'open'
319
336
  }.freeze
320
337
  @dir_position = {}
321
- @movement = @old_cursor = nil # cursor movement has happened only, don't repaint
338
+ @cursor_movement = @old_cursor = nil # cursor movement has happened only, don't repaint
322
339
  ## FLAGS
323
340
  @multiple_selection = true # single select
324
341
  @group_dirs = true
@@ -345,7 +362,8 @@ PAGER_COMMAND = {
345
362
  editor_mode: false,
346
363
  selection_mode: false, # typing hint adds to selection, does not open
347
364
  debug_flag: false,
348
- toggle_filename_status_line: true
365
+ toggle_filename_status_line: true,
366
+ instant_search: true
349
367
  }
350
368
  # @cycles = { truncate_from: :center,
351
369
  # show_hidden: nil }
@@ -662,8 +680,6 @@ def redraw flag=false
662
680
  end
663
681
 
664
682
  def draw_directory
665
- # all this seems to be happening for each keystroke even if
666
- # not really required. FIXME maybe reduce and call when required
667
683
 
668
684
  # view consists of all files (filtered by pattern if necessary)
669
685
  # viewport is only that subset of view that is displayed on screen
@@ -751,13 +767,15 @@ def resolve_key key
751
767
  ret = true
752
768
  clear_message
753
769
 
770
+ return true if search_as_you_type(key)
771
+
754
772
  if key.match?(/^[a-pr-zZ]$/)
755
773
  # hint mode
756
774
  ret = select_hint @viewport, key
757
775
  elsif key == 'BACKSPACE'
758
- # do we really need this TODO
759
776
  @patt = @patt[0..-2] if @patt && !@patt.empty?
760
777
  @message = @patt = nil if @patt == ''
778
+ @title = nil unless @patt
761
779
  elsif '0123456789'.include? key
762
780
  resolve_numeric_key key
763
781
  else
@@ -798,6 +816,70 @@ def resolve_numeric_key key
798
816
  message "Created bookmark #{key}."
799
817
  end
800
818
 
819
+ IGNORE_KEY = true
820
+ PROCESS_KEY = false
821
+
822
+ # Display search results as user types search pattern.
823
+ # returning false allows these keys to be processed
824
+ # returning true means that these keys will be ignored
825
+ def search_as_you_type key
826
+ return false unless @searching
827
+
828
+ # @log.info "sayt: #{key}, patt: #{@patt}"
829
+
830
+ # escape should nil patt and come out of search.
831
+ if key == 'ESCAPE'
832
+ exit_search
833
+ return IGNORE_KEY
834
+ end
835
+
836
+ # We exit the search but screen shows search results.
837
+ if key == 'ENTER' # || key == 'TAB'
838
+ @searching = false
839
+ redraw_required true # ??? any effect ?
840
+ @mode = 'NORM'
841
+ # nilifying patt means we will not see searched results. we want to stay there.
842
+ @title = 'Search Results (ESCAPE to return)'
843
+ message ' '
844
+ status_line
845
+ return IGNORE_KEY
846
+ end
847
+
848
+ if key == 'BACKSPACE' && @patt
849
+ @patt = @patt[0..-2]
850
+ exit_search if @patt == ''
851
+ return IGNORE_KEY
852
+ end
853
+
854
+ # XXX should not changing directory cancel the search ?
855
+ if key == 'UP' || key == 'DOWN' || key == 'RIGHT' || key == 'LEFT'
856
+ return PROCESS_KEY
857
+ end
858
+
859
+ # if key is not one of allowed keys, then cancel the search.
860
+ # No, we allow it as in toggle or menu ?
861
+ unless key.match?(/^[a-zA-Z0-9\. _]$/)
862
+ # exit_search
863
+ # @mode = @title = nil
864
+ # redraw_required true
865
+ return PROCESS_KEY
866
+ end
867
+
868
+ @mode = 'INST'
869
+ @title = 'Search results: Use ENTER to return, ESCAPE to cancel.'
870
+ @patt ||= '' + '' # rubocop suggestion to get unfrozen string
871
+ @patt += key
872
+ message "> #{@patt} "
873
+ redraw_required true
874
+
875
+ return IGNORE_KEY
876
+ end
877
+
878
+ def exit_search
879
+ @searching = @mode = @title = @patt = nil
880
+ status_line
881
+ end
882
+
801
883
  def set_bookmark key, dir=Dir.pwd
802
884
  @bookmarks[key] = dir
803
885
  end
@@ -870,7 +952,6 @@ def columnate ary, siz
870
952
 
871
953
  elsif unformatted_len < wid
872
954
 
873
- # f = f.ljust(wid)
874
955
  f << ' ' * (wid - unformatted_len)
875
956
 
876
957
  end
@@ -1335,7 +1416,9 @@ def escape
1335
1416
  @viewctr = 0
1336
1417
  @title = nil
1337
1418
  @filterstr = 'M'
1419
+ @searching = false
1338
1420
  @message = nil
1421
+ @mode = nil
1339
1422
  visual_block_clear
1340
1423
  refresh
1341
1424
  end
@@ -1465,11 +1548,21 @@ def goto_bookmark key=nil
1465
1548
  end
1466
1549
 
1467
1550
  ## take regex from user, to run on files on screen, user can filter file names
1468
- def enter_regex
1469
- # print 'Enter (regex) pattern: '
1470
- # move to beginning of line, and clear till EOL
1471
- # print "\r\e[K"
1472
- @patt = readline '/'
1551
+ def ask_regex
1552
+ unless cget(:instant_search)
1553
+ @log.info "Inside ask_regex readline."
1554
+ @patt = readline '/'
1555
+ @title = 'Search Results: (Press Escape to return)'
1556
+ @mode = 'SEARCH'
1557
+ return
1558
+ end
1559
+
1560
+ # this is the instant search as you type thingie
1561
+ @patt = nil
1562
+ @log.info "Inside ask_regex instant."
1563
+ message 'I/'
1564
+ @searching = true
1565
+ status_line
1473
1566
  end
1474
1567
 
1475
1568
  # page/scroll down.
@@ -1684,7 +1777,8 @@ def toggle_menu
1684
1777
  'S' => :selection_mode,
1685
1778
  v: :visual_mode,
1686
1779
  t: :truncate_from,
1687
- n: :enhanced_mode }
1780
+ n: :enhanced_mode,
1781
+ i: :instant_search }
1688
1782
  # TODO: add other values at end, what key ?
1689
1783
 
1690
1784
  _, menu_text = menu 'Toggle Menu', h
@@ -1971,7 +2065,6 @@ def filter_menu
1971
2065
  @files = files
1972
2066
  @stact = 0
1973
2067
  @message = "Filtered on #{menu_text}. Press ESC to return."
1974
- # redraw
1975
2068
  else
1976
2069
  perror 'Sorry, No files. '
1977
2070
  @title = nil
@@ -1998,7 +2091,6 @@ def select_from_used_dirs
1998
2091
  @title = 'Used Directories'
1999
2092
  home = File.expand_path '~'
2000
2093
  @files = @used_dirs.uniq.map { |path| path.sub(home.to_s, '~') }
2001
- # redraw
2002
2094
  end
2003
2095
 
2004
2096
  def select_from_visited_files
@@ -2006,7 +2098,6 @@ def select_from_visited_files
2006
2098
  @title = 'Visited Files'
2007
2099
  home = File.expand_path '~'
2008
2100
  @files = @visited_files.uniq.map { |path| path.sub(home.to_s, '~') }
2009
- # redraw
2010
2101
  end
2011
2102
 
2012
2103
  # maybe unused ??? XXX
@@ -2110,7 +2201,6 @@ def create_bookmark
2110
2201
  else
2111
2202
  perror 'Bookmark must be alpha character or number.'
2112
2203
  end
2113
- # redraw
2114
2204
  end
2115
2205
 
2116
2206
  # allow user to exit using :q :wq :x
@@ -2163,10 +2253,15 @@ def subcommand
2163
2253
  else
2164
2254
  perror "Don't know about command #{command}. Try :h or :help"
2165
2255
  end
2166
- # redraw
2167
2256
  end
2168
2257
 
2169
2258
  def quit_command
2259
+ # if we are in some mode, like search results then 'q' should come out.
2260
+ if @mode
2261
+ escape
2262
+ return
2263
+ end
2264
+
2170
2265
  if @modified
2171
2266
  last_line
2172
2267
  puts 'Press y to save bookmarks before quitting ' if @modified
@@ -2188,7 +2283,6 @@ def views
2188
2283
  @viewctr = 0 if @viewctr > views.size
2189
2284
 
2190
2285
  @files = `zsh -c 'print -rl -- *(#{@sorto}#{@hidden}M)'`.split("\n")
2191
- # redraw
2192
2286
  end
2193
2287
 
2194
2288
  def child_dirs
@@ -2197,7 +2291,6 @@ def child_dirs
2197
2291
  # @files = `zsh -c 'print -rl -- *(/#{@sorto}#{@hidden}M)'`.split("\n")
2198
2292
  @files = dirs
2199
2293
  message "#{@files.size} directories."
2200
- # redraw
2201
2294
  end
2202
2295
 
2203
2296
  def dirs dir='*'
@@ -2218,7 +2311,6 @@ def dirtree
2218
2311
  # files1 = `zsh -c 'print -rl -- **/*(/#{@sorto}#{@hidden}M)'`.split("\n")
2219
2312
  @files = Dir['**/']
2220
2313
  message "#{@files.size} files."
2221
- # redraw
2222
2314
  end
2223
2315
 
2224
2316
  #
@@ -2230,7 +2322,6 @@ def tree
2230
2322
  # @files = `zsh -c 'print -rl -- **/*(#{@sorto}#{@hidden}M)'`.split("\n")
2231
2323
  @files = Dir['**/*']
2232
2324
  message "#{@files.size} files."
2233
- # redraw
2234
2325
  end
2235
2326
 
2236
2327
  # lists recent files in current dir
@@ -2241,7 +2332,6 @@ def recent_files
2241
2332
  # zsh D DOT_GLOB, show dot files
2242
2333
  # zsh om order on modification time
2243
2334
  @files = `zsh -c 'print -rl -- **/*(Dom[1,15])'`.split("\n").reject { |f| f[0] == '.' }
2244
- # redraw
2245
2335
  end
2246
2336
 
2247
2337
  def select_current
@@ -2702,7 +2792,6 @@ def column_next direction=0
2702
2792
  # We are trying to maintain offset
2703
2793
  @cursor += @grows if @cursor < 0
2704
2794
  end
2705
- # redraw
2706
2795
  end
2707
2796
 
2708
2797
  # currently i am only passing the action in from the list there as a key
@@ -2901,7 +2990,6 @@ def ag
2901
2990
  return
2902
2991
  end
2903
2992
  @files = files
2904
- # redraw
2905
2993
  end
2906
2994
 
2907
2995
  def ffind
@@ -2917,7 +3005,6 @@ def ffind
2917
3005
  else
2918
3006
  @files = files
2919
3007
  end
2920
- # redraw
2921
3008
  end
2922
3009
 
2923
3010
  def locate
@@ -2933,7 +3020,6 @@ def locate
2933
3020
  else
2934
3021
  @files = files
2935
3022
  end
2936
- # redraw
2937
3023
  end
2938
3024
 
2939
3025
  ## takes directories from the z program, if you use autojump you can
@@ -2950,7 +3036,6 @@ def z_interface
2950
3036
  @files.collect! do |f|
2951
3037
  f.sub(/#{home}/, '~')
2952
3038
  end
2953
- # redraw
2954
3039
  end
2955
3040
 
2956
3041
  def vidir
@@ -2963,25 +3048,25 @@ end
2963
3048
 
2964
3049
  ## scroll cursor down
2965
3050
  def cursor_scroll_dn
2966
- @movement = :down
3051
+ @cursor_movement = :down
2967
3052
  moveto(pos + MSCROLL)
2968
3053
  end
2969
3054
 
2970
3055
  def cursor_scroll_up
2971
- @movement = :up
3056
+ @cursor_movement = :up
2972
3057
  moveto(pos - MSCROLL)
2973
3058
  end
2974
3059
 
2975
3060
  # move cursor down a line
2976
3061
  def cursor_dn
2977
- @movement = :down
3062
+ @cursor_movement = :down
2978
3063
  @old_cursor = @cursor
2979
3064
  moveto(pos + 1)
2980
3065
  end
2981
3066
 
2982
3067
  def cursor_up
2983
3068
  @old_cursor = @cursor
2984
- @movement = :up
3069
+ @cursor_movement = :up
2985
3070
  moveto(pos - 1)
2986
3071
  end
2987
3072
 
@@ -2999,8 +3084,8 @@ def moveto position
2999
3084
 
3000
3085
  # try to stop it from landing on separator
3001
3086
  if current_file == SEPARATOR
3002
- @cursor += 1 if @movement == :down
3003
- @cursor -= 1 if @movement == :up
3087
+ @cursor += 1 if @cursor_movement == :down
3088
+ @cursor -= 1 if @cursor_movement == :up
3004
3089
  return
3005
3090
  end
3006
3091
 
@@ -3019,13 +3104,13 @@ def moveto position
3019
3104
  # @sta = @cursor
3020
3105
  end
3021
3106
 
3022
- @movement = nil if oldsta != @sta # we need to redraw
3107
+ @cursor_movement = nil if oldsta != @sta # we need to redraw
3023
3108
 
3024
3109
  star = [orig, @cursor].min
3025
3110
  fin = [orig, @cursor].max
3026
3111
  return unless @visual_mode
3027
3112
 
3028
- @movement = nil # visual mode needs to redraw page
3113
+ @cursor_movement = nil # visual mode needs to redraw page
3029
3114
 
3030
3115
  # PWD has to be there in selction
3031
3116
  if selected? current_file
@@ -3039,8 +3124,6 @@ def moveto position
3039
3124
  add_to_selection @view[star..fin]
3040
3125
  end
3041
3126
  message "#{@selected_files.count} files selected. "
3042
- # ensure
3043
- # redraw
3044
3127
  end
3045
3128
  # --
3046
3129
 
@@ -3262,7 +3345,8 @@ def scripts binding=nil
3262
3345
 
3263
3346
  unless binding
3264
3347
  title = 'Select a script'
3265
- script_path = '~/.config/cetus/scripts'
3348
+ # script_path = '~/.config/cetus/scripts'
3349
+ script_path = File.join(CONFIG_PATH, 'cetus', 'scripts')
3266
3350
  binding = `find #{script_path} -type f | fzf --prompt="#{title} :"`.chomp
3267
3351
  return if binding.nil? || binding == ''
3268
3352
  end
@@ -3284,7 +3368,7 @@ def scripts binding=nil
3284
3368
  # script may ignore this and use selected_files
3285
3369
 
3286
3370
  # reset clears the screen, we don't want that. just unhide cursor and echo keys TODO
3287
- reset_terminal
3371
+ partial_reset_terminal
3288
3372
  system %( #{binding} "#{current_file}" )
3289
3373
 
3290
3374
  # system %(echo "#{cf}" | xargs #{binding})
@@ -3297,9 +3381,13 @@ end
3297
3381
  # this is quite important and should not be left to a script
3298
3382
  # example of calling a script from somewhere directly without selection
3299
3383
  def execute_script filename
3300
- script_path = '~/.config/cetus/scripts'
3301
- script = File.expand_path(File.join(script_path, 'filename'))
3302
- return unless File.exist? script
3384
+ # script_path = '~/.config/cetus/scripts'
3385
+ script_path = File.join(CONFIG_PATH, 'cetus', 'scripts')
3386
+ script = File.expand_path(File.join(script_path, filename))
3387
+ unless File.exist? script
3388
+ perror "Unable to find #{filename}: #{script}"
3389
+ return
3390
+ end
3303
3391
 
3304
3392
  scripts script
3305
3393
  end
@@ -3316,6 +3404,7 @@ def generators
3316
3404
 
3317
3405
  title = 'Select a generator'
3318
3406
  script_path = '~/.config/cetus/generators'
3407
+ script_path = File.join(CONFIG_PATH, 'cetus', 'generators')
3319
3408
  binding = `find #{script_path} -type f | fzf --prompt="#{title} :"`.chomp
3320
3409
  return if binding.nil? || binding == ''
3321
3410
 
@@ -3714,12 +3803,12 @@ end
3714
3803
  # returns true if only cursor moved and redrawing not required
3715
3804
  def only_cursor_moved?
3716
3805
  # only movement has happened within this page, don't redraw
3717
- return unless @movement && @old_cursor
3806
+ return unless @cursor_movement && @old_cursor
3718
3807
 
3719
3808
  # if cursor has not moved (first or last item on screen)
3720
3809
  # keep testing this out 2019-04-14 -
3721
3810
  if @old_cursor == @cursor
3722
- @movement = false
3811
+ @cursor_movement = false
3723
3812
  return true # next in the loop
3724
3813
  end
3725
3814
 
@@ -3732,10 +3821,15 @@ def only_cursor_moved?
3732
3821
  end
3733
3822
 
3734
3823
  place_cursor
3735
- @movement = false
3824
+ @cursor_movement = false
3736
3825
  return true # next in the loop
3737
3826
  end
3738
3827
 
3828
+ # indicate that only cursor moved, so don't redraw or rescan
3829
+ def only_cursor_moved flag=true
3830
+ @cursor_movement = flag
3831
+ end
3832
+
3739
3833
  # main loop which calls all other programs
3740
3834
  def run
3741
3835
  Signal.trap('EXIT') do
@@ -3751,7 +3845,7 @@ def run
3751
3845
  redraw true
3752
3846
  place_cursor
3753
3847
 
3754
- # do we need this, have they changed after redraw
3848
+ # do we need this, have they changed after redraw XXX
3755
3849
  @patt = nil
3756
3850
  @sta = 0
3757
3851
 
@@ -3764,12 +3858,15 @@ def run
3764
3858
  next
3765
3859
  end
3766
3860
 
3861
+ break if @quitting
3862
+
3767
3863
  next if only_cursor_moved?
3768
3864
 
3865
+ next unless @redraw_required # no change, or ignored key
3866
+
3769
3867
  redraw rescan?
3770
3868
  place_cursor
3771
3869
 
3772
- break if @quitting
3773
3870
  end
3774
3871
  write_curdir
3775
3872
  puts 'bye'
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'cetus'
9
- spec.version = '0.1.38'
9
+ spec.version = '0.1.39'
10
10
  spec.authors = ['Rahul Kumar']
11
11
  spec.email = ['oneness.univ@gmail.com']
12
12
  spec.description = %q{lightning fast file navigator}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cetus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.38
4
+ version: 0.1.39
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahul Kumar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-19 00:00:00.000000000 Z
11
+ date: 2019-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler