Class: Marvi::Renderer::Curses::FilePicker
- Inherits:
-
Object
- Object
- Marvi::Renderer::Curses::FilePicker
- Defined in:
- lib/marvi/renderer/curses/file_picker.rb
Overview
Candidate discovery, filtering, and tab-completion behind the o
(open file) picker. Pure filesystem/string logic with no curses calls,
so it can be tested headlessly.
Two modes, decided per keystroke from the typed input:
- list mode: filter documents scanned under the base directory; every whitespace-separated term must match somewhere in the path.
- path mode (input starts with /, ~, ./ or ../): complete the typed path against the filesystem, shell-style.
Constant Summary collapse
- SCAN_GLOB =
"**/*.{md,markdown,mdown,mkd,txt}"- MAX_FILES =
2000
Instance Method Summary collapse
-
#all_files ⇒ Object
Documents under the base directory, capped to keep the picker snappy in huge trees.
- #candidates(input) ⇒ Object
-
#complete(input) ⇒ Object
Longest unambiguous extension of the typed path.
- #filter(input) ⇒ Object
-
#initialize(base_dir = Dir.pwd) ⇒ FilePicker
constructor
A new instance of FilePicker.
- #path_mode?(input) ⇒ Boolean
Constructor Details
#initialize(base_dir = Dir.pwd) ⇒ FilePicker
Returns a new instance of FilePicker.
19 20 21 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 19 def initialize(base_dir = Dir.pwd) @base_dir = base_dir end |
Instance Method Details
#all_files ⇒ Object
Documents under the base directory, capped to keep the picker snappy in huge trees. Dir.glob skips hidden directories by default.
25 26 27 28 29 30 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 25 def all_files @all_files ||= Dir.glob(SCAN_GLOB, base: @base_dir) .reject { |path| File.directory?(File.join(@base_dir, path)) } .sort .first(MAX_FILES) end |
#candidates(input) ⇒ Object
36 37 38 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 36 def candidates(input) path_mode?(input) ? path_candidates(input) : filter(input) end |
#complete(input) ⇒ Object
Longest unambiguous extension of the typed path. A lone directory match gains a trailing slash so the next Tab descends into it.
52 53 54 55 56 57 58 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 52 def complete(input) cands = path_candidates(input) return input if cands.empty? prefix = common_prefix(cands) (prefix.length > input.length) ? prefix : input end |
#filter(input) ⇒ Object
40 41 42 43 44 45 46 47 48 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 40 def filter(input) terms = input.downcase.split return all_files if terms.empty? all_files.select do |path| haystack = path.downcase terms.all? { |term| haystack.include?(term) } end end |
#path_mode?(input) ⇒ Boolean
32 33 34 |
# File 'lib/marvi/renderer/curses/file_picker.rb', line 32 def path_mode?(input) input.start_with?("/", "~", "./", "../") end |