Class: Chamomile::FilePicker

Inherits:
Object
  • Object
show all
Defined in:
lib/chamomile/components/file_picker.rb,
lib/chamomile/components/file_picker/key_map.rb

Overview

Filesystem browser with async directory reading, navigation, and filtering.

Constant Summary collapse

DEFAULT_KEY_MAP =
KeyBinding.normalize({
  up: [[:up, []], ["k", []]],
  down: [[:down, []], ["j", []]],
  open: [[:right, []], ["l", []], [:enter, []]],
  back: [[:left, []], ["h", []], [:backspace, []]],
  toggle_hidden: [[".", []]],
  page_up: [[:page_up, []], ["b", [:ctrl]]],
  page_down: [[:page_down, []], ["f", [:ctrl]]],
  goto_top: [["g", []], [:home, []]],
  goto_bottom: [["G", [:shift]], [:end_key, []]],
})

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory: Dir.pwd, key_map: DEFAULT_KEY_MAP, height: 10, allowed_types: [], show_permissions: false, show_size: false, show_hidden: false, dir_allowed: false, file_allowed: true, cursor_char: ">") ⇒ FilePicker

Returns a new instance of FilePicker.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/chamomile/components/file_picker.rb', line 28

def initialize(directory: Dir.pwd, key_map: DEFAULT_KEY_MAP, height: 10,
               allowed_types: [], show_permissions: false, show_size: false,
               show_hidden: false, dir_allowed: false, file_allowed: true,
               cursor_char: ">")
  @id = self.class.next_id
  @current_directory = File.expand_path(directory)
  @key_map = key_map
  @height = height
  @allowed_types = allowed_types
  @show_permissions = show_permissions
  @show_size = show_size
  @show_hidden = show_hidden
  @dir_allowed = dir_allowed
  @file_allowed = file_allowed
  @cursor_char = cursor_char
  @cursor = 0
  @entries = []
  @offset = 0
  @selected_path = nil
  @disabled_selected_path = nil
  @dir_stack = []
end

Instance Attribute Details

#allowed_typesObject

Returns the value of attribute allowed_types.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def allowed_types
  @allowed_types
end

#current_directoryObject (readonly)

Returns the value of attribute current_directory.



24
25
26
# File 'lib/chamomile/components/file_picker.rb', line 24

def current_directory
  @current_directory
end

#cursor_charObject

Returns the value of attribute cursor_char.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def cursor_char
  @cursor_char
end

#dir_allowedObject

Returns the value of attribute dir_allowed.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def dir_allowed
  @dir_allowed
end

#file_allowedObject

Returns the value of attribute file_allowed.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def file_allowed
  @file_allowed
end

#heightObject

Returns the value of attribute height.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def height
  @height
end

#idObject (readonly)

Returns the value of attribute id.



24
25
26
# File 'lib/chamomile/components/file_picker.rb', line 24

def id
  @id
end

#key_mapObject

Returns the value of attribute key_map.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def key_map
  @key_map
end

#selected_pathObject (readonly)

Returns the value of attribute selected_path.



24
25
26
# File 'lib/chamomile/components/file_picker.rb', line 24

def selected_path
  @selected_path
end

#show_hiddenObject

Returns the value of attribute show_hidden.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def show_hidden
  @show_hidden
end

#show_permissionsObject

Returns the value of attribute show_permissions.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def show_permissions
  @show_permissions
end

#show_sizeObject

Returns the value of attribute show_size.



25
26
27
# File 'lib/chamomile/components/file_picker.rb', line 25

def show_size
  @show_size
end

Class Method Details

.next_idObject



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/chamomile/components/file_picker.rb', line 12

def self.next_id
  @id_mutex.synchronize do
    if Process.pid != @id_pid
      @id_pid = Process.pid
      @next_id = 0
      @id_mutex = Mutex.new
    end
    @next_id += 1
    "#{@id_pid}-fp-#{@next_id}"
  end
end

Instance Method Details

#did_select_disabled_file?(msg) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
112
113
114
115
116
117
118
119
# File 'lib/chamomile/components/file_picker.rb', line 109

def did_select_disabled_file?(msg)
  return [false, nil] unless msg.is_a?(Chamomile::KeyEvent)

  if @disabled_selected_path
    path = @disabled_selected_path
    @disabled_selected_path = nil
    [true, path]
  else
    [false, nil]
  end
end

#did_select_file?(msg) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
# File 'lib/chamomile/components/file_picker.rb', line 97

def did_select_file?(msg)
  return [false, nil] unless msg.is_a?(Chamomile::KeyEvent)

  if @selected_path
    path = @selected_path
    @selected_path = nil
    [true, path]
  else
    [false, nil]
  end
end

#handle(msg) ⇒ Object Also known as: update



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/chamomile/components/file_picker.rb', line 55

def handle(msg)
  case msg
  when FilePickerReadDirMsg
    return unless msg.id == @id

    @entries = msg.entries
    @cursor = @cursor.clamp(0, [entries_size - 1, 0].max)
    clamp_offset
    nil
  when Chamomile::KeyEvent
    handle_key(msg)
  end
end

#highlighted_pathObject



88
89
90
91
92
93
94
95
# File 'lib/chamomile/components/file_picker.rb', line 88

def highlighted_path
  return nil if @entries.empty?

  entry = @entries[@cursor]
  return nil unless entry

  File.join(@current_directory, entry[:name])
end

#init_cmdObject



51
52
53
# File 'lib/chamomile/components/file_picker.rb', line 51

def init_cmd
  read_dir_cmd(@current_directory)
end

#viewObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/chamomile/components/file_picker.rb', line 71

def view
  return "  (empty)" if @entries.empty?

  visible = visible_entries
  lines = visible.each_with_index.map do |entry, i|
    idx = @offset + i
    prefix = idx == @cursor ? "#{@cursor_char} " : "  "
    line = prefix + format_entry(entry)
    if idx == @cursor
      "\e[7m#{line}\e[0m"
    else
      line
    end
  end
  lines.join("\n")
end