Class: Chamomile::List
- Inherits:
-
Object
- Object
- Chamomile::List
- Defined in:
- lib/chamomile/components/list.rb,
lib/chamomile/components/list/key_map.rb
Overview
Batteries-included item browser composing Paginator, TextInput, Spinner, Help.
Constant Summary collapse
- FILTER_UNFILTERED =
:unfiltered- FILTER_FILTERING =
:filtering- FILTER_APPLIED =
:applied- DEFAULT_KEY_MAP =
KeyBinding.normalize({ cursor_up: [[:up, []], ["k", []]], cursor_down: [[:down, []], ["j", []]], next_page: [[:page_down, []], ["n", [:ctrl]]], prev_page: [[:page_up, []], ["p", [:ctrl]]], goto_start: [["g", []], [:home, []]], goto_end: [["G", [:shift]], [:end_key, []]], filter: [["/", []]], clear_filter: [[:escape, []]], accept_filter: [[:enter, []]], show_full_help: [["?", []]], })
Instance Attribute Summary collapse
-
#cursor ⇒ Object
readonly
Returns the value of attribute cursor.
-
#delegate ⇒ Object
Returns the value of attribute delegate.
-
#filter_state ⇒ Object
readonly
Returns the value of attribute filter_state.
-
#filtering_enabled ⇒ Object
Returns the value of attribute filtering_enabled.
-
#height ⇒ Object
Returns the value of attribute height.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#infinite_scroll ⇒ Object
Returns the value of attribute infinite_scroll.
-
#key_map ⇒ Object
Returns the value of attribute key_map.
-
#show_filter ⇒ Object
Returns the value of attribute show_filter.
-
#show_help ⇒ Object
Returns the value of attribute show_help.
-
#show_pagination ⇒ Object
Returns the value of attribute show_pagination.
-
#show_status_bar ⇒ Object
Returns the value of attribute show_status_bar.
-
#show_title ⇒ Object
Returns the value of attribute show_title.
-
#status_message ⇒ Object
readonly
Returns the value of attribute status_message.
-
#title ⇒ Object
Returns the value of attribute title.
-
#width ⇒ Object
Returns the value of attribute width.
Class Method Summary collapse
Instance Method Summary collapse
- #cursor_down ⇒ Object
- #cursor_up ⇒ Object
- #filter_value ⇒ Object
- #global_index ⇒ Object
- #goto_end ⇒ Object
- #goto_start ⇒ Object
- #handle(msg) ⇒ Object (also: #update)
- #index ⇒ Object
-
#initialize(items:, width: 80, height: 24, delegate: nil, key_map: DEFAULT_KEY_MAP) ⇒ List
constructor
A new instance of List.
- #insert_item(index, item) ⇒ Object
- #items ⇒ Object
- #items=(new_items) ⇒ Object
- #new_status_message(text, lifetime: 1.0) ⇒ Object
- #next_page ⇒ Object
- #prev_page ⇒ Object
- #remove_item(index) ⇒ Object
- #reset_filter ⇒ Object
- #selected_item ⇒ Object
- #set_filter_text(text) ⇒ Object
- #set_item(index, item) ⇒ Object
- #spinner_visible? ⇒ Boolean
- #start_spinner ⇒ Object
- #stop_spinner ⇒ Object
- #view ⇒ Object
- #visible_items ⇒ Object
Constructor Details
#initialize(items:, width: 80, height: 24, delegate: nil, key_map: DEFAULT_KEY_MAP) ⇒ List
Returns a new instance of List.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/chamomile/components/list.rb', line 35 def initialize(items:, width: 80, height: 24, delegate: nil, key_map: DEFAULT_KEY_MAP) @id = self.class.next_id @all_items = items.dup @filtered_items = @all_items.dup @width = width @height = height @delegate = delegate @key_map = key_map @title = "" @cursor = 0 @show_title = true @show_filter = true @show_status_bar = true @show_pagination = true @show_help = true @filtering_enabled = true @filter_state = FILTER_UNFILTERED @infinite_scroll = false @spinner_visible = false @status_message = nil @paginator = Paginator.new(per_page: items_per_page) @filter_input = TextInput.new(prompt: "/ ") @spinner = Spinner.new @help = Help.new(width: width) @help_bindings = [ { key: "/", desc: "filter" }, { key: "esc", desc: "clear" }, { key: "q", desc: "quit" }, { key: "?", desc: "more" }, ] recalculate end |
Instance Attribute Details
#cursor ⇒ Object (readonly)
Returns the value of attribute cursor.
29 30 31 |
# File 'lib/chamomile/components/list.rb', line 29 def cursor @cursor end |
#delegate ⇒ Object
Returns the value of attribute delegate.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def delegate @delegate end |
#filter_state ⇒ Object (readonly)
Returns the value of attribute filter_state.
29 30 31 |
# File 'lib/chamomile/components/list.rb', line 29 def filter_state @filter_state end |
#filtering_enabled ⇒ Object
Returns the value of attribute filtering_enabled.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def filtering_enabled @filtering_enabled end |
#height ⇒ Object
Returns the value of attribute height.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def height @height end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
29 30 31 |
# File 'lib/chamomile/components/list.rb', line 29 def id @id end |
#infinite_scroll ⇒ Object
Returns the value of attribute infinite_scroll.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def infinite_scroll @infinite_scroll end |
#key_map ⇒ Object
Returns the value of attribute key_map.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def key_map @key_map end |
#show_filter ⇒ Object
Returns the value of attribute show_filter.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def show_filter @show_filter end |
#show_help ⇒ Object
Returns the value of attribute show_help.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def show_help @show_help end |
#show_pagination ⇒ Object
Returns the value of attribute show_pagination.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def show_pagination @show_pagination end |
#show_status_bar ⇒ Object
Returns the value of attribute show_status_bar.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def @show_status_bar end |
#show_title ⇒ Object
Returns the value of attribute show_title.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def show_title @show_title end |
#status_message ⇒ Object (readonly)
Returns the value of attribute status_message.
29 30 31 |
# File 'lib/chamomile/components/list.rb', line 29 def @status_message end |
#title ⇒ Object
Returns the value of attribute title.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def title @title end |
#width ⇒ Object
Returns the value of attribute width.
30 31 32 |
# File 'lib/chamomile/components/list.rb', line 30 def width @width end |
Class Method Details
.next_id ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/chamomile/components/list.rb', line 17 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}-lst-#{@next_id}" end end |
Instance Method Details
#cursor_down ⇒ Object
130 131 132 133 134 135 136 137 |
# File 'lib/chamomile/components/list.rb', line 130 def cursor_down @cursor = if @infinite_scroll && @cursor >= filtered_count - 1 && filtered_count.positive? 0 else (@cursor + 1).clamp(0, [filtered_count - 1, 0].max) end update_paginator_page end |
#cursor_up ⇒ Object
121 122 123 124 125 126 127 128 |
# File 'lib/chamomile/components/list.rb', line 121 def cursor_up @cursor = if @infinite_scroll && @cursor.zero? && filtered_count.positive? filtered_count - 1 else (@cursor - 1).clamp(0, [filtered_count - 1, 0].max) end update_paginator_page end |
#filter_value ⇒ Object
161 162 163 |
# File 'lib/chamomile/components/list.rb', line 161 def filter_value @filter_input.value end |
#global_index ⇒ Object
114 115 116 117 118 119 |
# File 'lib/chamomile/components/list.rb', line 114 def global_index return nil if @filtered_items.empty? item = selected_item @all_items.index(item) end |
#goto_end ⇒ Object
144 145 146 147 |
# File 'lib/chamomile/components/list.rb', line 144 def goto_end @cursor = [filtered_count - 1, 0].max update_paginator_page end |
#goto_start ⇒ Object
139 140 141 142 |
# File 'lib/chamomile/components/list.rb', line 139 def goto_start @cursor = 0 update_paginator_page end |
#handle(msg) ⇒ Object Also known as: update
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/chamomile/components/list.rb', line 215 def handle(msg) case msg when Chamomile::KeyEvent handle_key(msg) when SpinnerTickMsg @spinner.update(msg) nil when FilterMatchesMsg @filtered_items = msg.matches @cursor = @cursor.clamp(0, [filtered_count - 1, 0].max) recalculate nil when ListStatusTimeoutMsg @status_message = nil if msg.id == @id nil end end |
#index ⇒ Object
110 111 112 |
# File 'lib/chamomile/components/list.rb', line 110 def index @cursor end |
#insert_item(index, item) ⇒ Object
88 89 90 91 92 93 |
# File 'lib/chamomile/components/list.rb', line 88 def insert_item(index, item) index = index.clamp(0, @all_items.length) @all_items.insert(index, item) apply_filter recalculate end |
#items ⇒ Object
70 71 72 |
# File 'lib/chamomile/components/list.rb', line 70 def items @filtered_items end |
#items=(new_items) ⇒ Object
74 75 76 77 78 |
# File 'lib/chamomile/components/list.rb', line 74 def items=(new_items) @all_items = new_items.dup apply_filter recalculate end |
#new_status_message(text, lifetime: 1.0) ⇒ Object
192 193 194 195 196 197 198 199 |
# File 'lib/chamomile/components/list.rb', line 192 def (text, lifetime: 1.0) @status_message = text captured_id = @id -> { sleep(lifetime) ListStatusTimeoutMsg.new(id: captured_id) } end |
#next_page ⇒ Object
155 156 157 158 159 |
# File 'lib/chamomile/components/list.rb', line 155 def next_page @paginator.next_page @cursor = @paginator.page * items_per_page @cursor = @cursor.clamp(0, [filtered_count - 1, 0].max) end |
#prev_page ⇒ Object
149 150 151 152 153 |
# File 'lib/chamomile/components/list.rb', line 149 def prev_page @paginator.prev_page @cursor = @paginator.page * items_per_page @cursor = @cursor.clamp(0, [filtered_count - 1, 0].max) end |
#remove_item(index) ⇒ Object
95 96 97 98 99 100 101 102 |
# File 'lib/chamomile/components/list.rb', line 95 def remove_item(index) return nil if index.negative? || index >= @all_items.length removed = @all_items.delete_at(index) apply_filter recalculate removed end |
#reset_filter ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/chamomile/components/list.rb', line 165 def reset_filter @filter_input.value = "" @filter_state = FILTER_UNFILTERED @filter_input.blur @filtered_items = @all_items.dup @cursor = 0 recalculate end |
#selected_item ⇒ Object
104 105 106 107 108 |
# File 'lib/chamomile/components/list.rb', line 104 def selected_item return nil if @filtered_items.empty? @filtered_items[@cursor] end |
#set_filter_text(text) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/chamomile/components/list.rb', line 174 def set_filter_text(text) if text.nil? || text.empty? reset_filter return end @filter_input.value = text @filter_state = FILTER_APPLIED @filter_input.blur apply_filter recalculate end |
#set_item(index, item) ⇒ Object
80 81 82 83 84 85 86 |
# File 'lib/chamomile/components/list.rb', line 80 def set_item(index, item) return if index.negative? || index >= @all_items.length @all_items[index] = item apply_filter recalculate end |
#spinner_visible? ⇒ Boolean
211 212 213 |
# File 'lib/chamomile/components/list.rb', line 211 def spinner_visible? @spinner_visible end |
#start_spinner ⇒ Object
201 202 203 204 |
# File 'lib/chamomile/components/list.rb', line 201 def start_spinner @spinner_visible = true @spinner.tick_cmd end |
#stop_spinner ⇒ Object
206 207 208 209 |
# File 'lib/chamomile/components/list.rb', line 206 def stop_spinner @spinner_visible = false nil end |
#view ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/chamomile/components/list.rb', line 235 def view sections = [] sections << render_title if @show_title && !@title.empty? sections << render_filter if @show_filter && @filter_state != FILTER_UNFILTERED sections << if @show_status_bar sections << render_items sections << @paginator.view if @show_pagination && @paginator.total_pages > 1 sections << render_help if @show_help sections.compact.reject(&:empty?).join("\n") end |
#visible_items ⇒ Object
187 188 189 190 |
# File 'lib/chamomile/components/list.rb', line 187 def visible_items start, length = @paginator.slice_bounds(filtered_count) @filtered_items[start, length] || [] end |