Class: Typr::Browser
Overview
A file-system directory browser built on Grid. Renders entries as rows with columns for name, symlink target, permissions, owner/group, size, timestamps, and MIME type. Directories sort to the top and appear in yellow; files get per-MIME-type foreground colors.
Column Views
:simple - name
:compact - name, size, type
:stats - name, size, , owner, group, modified
:full - all columns
Navigation Keys (interactive picker)
[h] | help
[r] | reset view
[d] | directory history
[m] / [M] | mark / mark range
[a] / [i] | mark all / invert mark
[`] / [~] / [..] | root / home / back
[v] | switch view
[s] / [f] | sort / filter
Return | confirm (cd on directories)
Escape | quit, returns nil
Constant Summary
Constants included from Typr
ALT_SCREEN_OFF, ALT_SCREEN_ON, COLORS, COLOR_MAP, DEFAULT_KEYS, ERASE_LINE, INPUT, KEY_ALT_BACKSPACE, KEY_ALT_LEFT, KEY_ALT_RIGHT, KEY_BACK_TAB, KEY_ESCAPE, KEY_PAGEDOWN, KEY_PAGEUP, KEY_RETURN, KEY_TAB, MIMETYPES, MODES, MOUSE_OFF, MOUSE_ON, ORIG_COLORS, TERMINFO
Instance Attribute Summary collapse
-
#directory ⇒ Object
Returns the value of attribute directory.
-
#mimetype_db ⇒ Object
Returns the value of attribute mimetype_db.
-
#mimetype_magic ⇒ Object
Returns the value of attribute mimetype_magic.
-
#pwd ⇒ Object
Returns the value of attribute pwd.
-
#user ⇒ Object
Returns the value of attribute user.
-
#view ⇒ Object
Returns the value of attribute view.
Attributes inherited from Grid
#align, #data, #filters, #format, #map, #procs, #rawfilter, #rawsort, #reverse, #sequence
Attributes inherited from Stack
#header, #hints, #hints_start, #keymap, #modifier, #selected, #separator, #start
Attributes inherited from Space
#borders, #colors, #interval, #left, #margin, #right
Instance Method Summary collapse
-
#back ⇒ Object
Navigate up one directory.
-
#bottom ⇒ Object
Height minus 2 rows reserved for path bar and command line.
-
#cd(dir, append = false) ⇒ Object
Change to
dir(absolute path,"..","~", or integer index into dir_history). -
#change_view(view = nil) ⇒ Object
Switch to a named or indexed column view.
-
#check(row) ⇒ Object
True when the row is a directory or passes base Grid filtering.
-
#confirm ⇒ Object
Returns the current directory path as the confirm result.
-
#directories ⇒ Object
Returns row ids for all directories in the current listing.
-
#filter_display ⇒ String
Formats active filters as 'column: query', joined by ' / '.
-
#filter_view ⇒ Object
Open a filter popup on the chosen row/column and apply the input.
-
#help ⇒ Object
Display a help grid listing all keybindings.
-
#home ⇒ Object
Navigate to the home directory.
-
#initialize(args = {}) ⇒ Browser
constructor
Construct a Browser widget.
-
#mark ⇒ Object
Prompts to select rows by index.
-
#mark_all ⇒ Object
Selects all non-directory rows.
-
#mark_invert ⇒ Object
Inverts selection across all non-directory rows.
-
#mark_range ⇒ Object
Toggles selection for every row within a "from..to" range.
-
#pick(type = 'file', **kw) ⇒ Object
Interactive file/directory picker.
-
#popup(args = {}) ⇒ Object
Create a small Grid popup under an info bar item for column selection.
-
#process(row) ⇒ Object
Colors symlink names green/red based on target existence and applies per-MIME-type foreground colors from
@colors[:types]. -
#reset_view ⇒ Object
Reset display, selection, and position state then re-sort.
-
#root ⇒ Object
Navigate to the root directory.
-
#scan_file(file) ⇒ Object
Build a row for a single directory entry from filesystem metadata only.
-
#search ⇒ Object
Open live
/search filtered on the name column. -
#send(key) ⇒ Object
Resolves hint characters typed on a row.
-
#show ⇒ Object
Renders the grid with an info bar above showing the current directory path and colored status items for filter, sort, and view.
-
#sort ⇒ Object
Sort by NAME by default; directories always appear before files within each prefix grouping.
-
#sort_view ⇒ Object
Open a sort-picker popup to choose a column to sort by.
-
#toggle_hidden ⇒ Object
Toggle visibility of hidden files (those starting with a dot).
-
#top ⇒ Object
Top offset plus one row for the path info bar.
-
#views ⇒ Object
Open a view-picker popup and switch to the selected view.
Methods inherited from Grid
#<<, #[], #[]=, #add_filter, #clear, #columns, #filter, #header=, #ids, #is_hash?, #page, #positions, #print, #reset, #rows, #sort_by, #sorted_by, #width_for
Methods inherited from Stack
#cycle, #cycle_back, #data_at, #down, #draw_hints, #headspace, #height, #hit, #page, #page_down, #page_up, #print, #reset, #to_bottom, #to_top, #up
Methods inherited from Space
#border=, #data_at, #draw_border, #extract_key, #height, #start, #stop, #symbolize, #width
Methods included from Typr
#background, clear, #clip, #coerce_type, #color, #color_code, column, decode_mouse, #draw, exit, #fade, #foreground, #get_background, #get_foreground, height, init, #mode, #mode_code, #move, #move_code, on_resize, position, #prepare, read_key, read_line, #real_size, row, #sanitize, size, slice_width, text_width, width, word_next, word_prev
Constructor Details
#initialize(args = {}) ⇒ Browser
Construct a Browser widget. Keyword arguments:
Option | Default | Description
--------------------|---------------------------------|-----------------------------------
+directory+ | +"~"+ | Starting directory to browse
+mimetype_db+ | true | Load MIME from file extensions
+mimetype_magic+ | true | Use +file --mime-type+ for unknowns
+colors[:actions]+ | { "[f]ilter": :red, ... } | Status item colors
+colors[:dir_history]+ | :yellow | History picker column color
+colors[:types]+ | (see below) | Per MIME-type foreground color
Type Color Defaults
image: :blue audio: :green video: :cyan
text: 146 pdf: 136 inode: :magenta
directory: :yellow symlink: 123 'x-empty': :grey70
'x-msdownload': :red 'x-pie-executable': :red
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
# File 'lib/browser.rb', line 440 def initialize args={} @mimetype_db, @mimetype_magic = true, true @view, @sort, @views, @positions, @show_hidden, @show_path = :compact, 0, {}, {}, false, false @filter_dirs = args[:filter_dirs] super @left ||= 0 @top ||= 0 @directory ||= ?~ @colors[:actions] = { "[f]ilter": :red, "[s]ort": :blue, "[v]iews": :green }.merge @colors[:actions] || {} @colors[ :types ] = { image: :blue, audio: :green, video: :cyan, text: 146, pdf: 136, 'epub+zip': 136, html: 150, xhtml: 150, javascript: 150, 'x-bzip2': 190, 'x-xz': 190, 'x-compressed': 190, inode: :magenta, blockdevice:148, chardevice:144, symlink:123, directory: :yellow, 'x-empty': :grey70, '?': :grey70, 'x-msdownload': :red, 'x-pie-executable': :red }.merge( @colors[ :types ] || {} ) @keymap = { back: KEY_BACKSPACE, confirm: KEY_RETURN, help: ?h, home: ?~, views: ?v, sort_view: ?s, search: ?/, mark: ?m, mark_range: ?M, mark_all: ?a, mark_invert: ?i, filter_view: ?f, reset_view: ?r, toggle_hidden: ?H}.merge @keymap self.header = %w[ name target permissions executable owner group size accessed modified created type subtype path ] @format[NAME] = :max @format[TYPE] = 5 @ignore[NAME] = @ignore[TARGET] = true @hints = "1234567890" [NAME, SIZE, ACCESSED, MODIFIED, CREATED].each{|col| @rawsort[col] = true} @procs[ACCESSED] = @procs[MODIFIED] = @procs[CREATED] = :datetime @procs[SIZE] = :magnitudes @procs[OWNER] = Proc.new{|uid| Etc.getpwuid(uid).name rescue uid } @procs[GROUP] = Proc.new{|gid| Etc.getgrgid(gid).name rescue gid } @procs[NAME] = Proc.new{ |name, row| target = @data[row][TARGET] File.basename(name.to_s) + ( target ? " > " + color_code(File.exist?(target) ? :green : :red) + target : "" ) } @views = { simple: i[ name ], compact: i[ name size type], stats: i[ name size owner group modified ], full: i[ name size executable owner group accessed modified created type subtype ] }.merge @views @parent = self @head ||= Grid.new( parent:self, left: ->{@parent.left}, margin: '', right: ->{@parent.width + @parent.left - 1}, top: ->{@parent.top-1}, input: [ [->{Etc.getpwuid(Process.euid).name rescue ENV["USER"] || Etc.getlogin}, ->{@parent.directory}, ->{@parent.filter_display}, ->{ (s = @parent.sorted_by(true)) && "#{s} #{@parent.reverse ? "\u2193" : "\u2191"}"}, ->{@parent.view} ] ], format: [:min, :max, :min, :min, :min], colors: { columns: [@colors[:default], @colors[:default], @colors[:actions][:"[f]ilter"], @colors[:actions][:"[s]ort"], @colors[:actions][:"[v]iews"]] } ) @head.define_singleton_method( :data_at ) do |x, y| return unless x and y and y.between?( top + 1, bottom + 1 ) and x.between?( left, right ) offs = positions( 0 ) col = offs.each_index.find { |i| x <= left + offs[i] + width_for( i ) - 1 } @parent.instance_variable_get( :@positions ).keys[ col - 2 ] if col and col >= 2 end @head.define_singleton_method( :path_at ) do |x, y| return unless x and y and y.between?( top + 1, bottom + 1 ) x -= 1 return unless x.between?( left, right ) offs = positions( 0 ) col = offs.each_index.find { |i| x <= left + offs[i] + width_for( i ) - 1 } return (Etc.getpwuid(Process.euid).dir rescue (Dir.home rescue "~")) if col == 0 return unless col == 1 and @parent.directory.is_a?( String ) text = ((@layer and @layer[0] and @layer[0][1]) || @data[0][1].call).to_s rel = x - ( left + offs[1] ) return if rel < 0 or rel >= real_size( text ) pre = prepare( text, rel + 1 ) ( pre + ( pre.end_with?( "/" ) ? "" : text[pre.length..-1][/\A[^\/]*/] ) ).sub( %r{(?<=.)/$}, "" ) end @user ||= Line.new( parent:self, left:->{@parent.left},top:->{@parent.bottom+1}, bindings: %w[ [h]elp [/]:search ] + @colors[:actions].map{|name,color| color_code( color ) + name.to_s + color_code(@colors[:default]) } + %w[ [r]eset [d]irectories [m]ark [M]ark_range mark_[a]ll [i]nvert_mark [~]:home [H]idden_files [back]:.. [up] [down] [pageup] [pagedown] [home] [end] [esc]:quit [return]:confirm\ ]) cd @directory end |
Instance Attribute Details
#directory ⇒ Object
Returns the value of attribute directory.
36 37 38 |
# File 'lib/browser.rb', line 36 def directory @directory end |
#mimetype_db ⇒ Object
Returns the value of attribute mimetype_db.
37 38 39 |
# File 'lib/browser.rb', line 37 def mimetype_db @mimetype_db end |
#mimetype_magic ⇒ Object
Returns the value of attribute mimetype_magic.
37 38 39 |
# File 'lib/browser.rb', line 37 def mimetype_magic @mimetype_magic end |
#pwd ⇒ Object
Returns the value of attribute pwd.
36 37 38 |
# File 'lib/browser.rb', line 36 def pwd @pwd end |
#user ⇒ Object
Returns the value of attribute user.
36 37 38 |
# File 'lib/browser.rb', line 36 def user @user end |
#view ⇒ Object
Returns the value of attribute view.
36 37 38 |
# File 'lib/browser.rb', line 36 def view @view end |
Instance Method Details
#back ⇒ Object
Navigate up one directory.
browser.back # equivalent to cd ".."
231 |
# File 'lib/browser.rb', line 231 def back; cd ".." end |
#bottom ⇒ Object
Height minus 2 rows reserved for path bar and command line.
41 |
# File 'lib/browser.rb', line 41 def bottom; super - 1 end |
#cd(dir, append = false) ⇒ Object
Change to dir (absolute path, "..", "~", or integer index into
dir_history). When append is false (default), clears data and colors
before scanning. Pushes onto dir_history.
browser.cd "/tmp" # => changes to /tmp
browser.cd "~" # => changes to home
browser.cd ".." # => parent directory
browser.cd 2 # => jump to history entry 2
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/browser.rb', line 57 def cd dir, append=false return unless dir data, missing = [],{} unless append begin path = File.( dir ) Dir.chdir( path ) entries = Dir.new( path ).children rescue SystemCallError @user.show "cannot open directory: #{dir}" Typr.read_key return false end @colors[:fields] = {} clear @directory = path else entries = Dir.new( @directory ).children end data = entries.reject{|f| !@show_hidden and f[0] == ?. }.map { |file| scan_file file } data.each_with_index{ |row, id| file = row[NAME] ftype = File.ftype(file) rescue next ftype = File.stat(file).ftype if ftype == 'link' and File.exist?(file) mime = { 'directory' => 'inode/directory', 'characterSpecial' => 'inode/chardevice', 'blockSpecial' => 'inode/blockdevice', 'link' => 'inode/symlink', 'fifo' => 'inode/fifo', 'socket' => 'inode/socket' }[ftype] unless mime if @mimetype_db and ext = file.match(/.+\.(\w+)$/) mime = MIMETYPES[ext[1].to_sym] end missing[file] = id unless mime end row[TYPE, 2] = mime.to_s.split( ?/ ) if mime } if @mimetype_magic and missing.any? begin out = IO.popen(['file', '--mime-type', *missing.keys]){ |io| io.read } rescue Errno::ENOENT out = '' end out.split($/).each{ |line| file, mime = line.match(/^(.*):\s+(\w+\/[\w\-\.]+)$/)&.captures next unless file data[ missing[file] ][TYPE, 2] = mime.split( ?/ ) if missing[file] } end data.each { |row| row[0] = File.join(@directory, row[0]) } self << data sort filter unless append @directory += ?/ unless @directory == ?/ change_view @view reset :position end return end |
#change_view(view = nil) ⇒ Object
Switch to a named or indexed column view. Resets format widths.
browser.change_view :full # all columns
browser.change_view 0 # first view key
browser.change_view :stats # name, size, perms, owner, group, modified
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/browser.rb', line 158 def change_view view=nil return unless view view = @views.keys[ view ] if view.is_a? Integer @sequence = @views[ view ].map{|title| @header.index title.to_s} if @show_path @data.each { |row| row[PATH] = File.dirname(row[NAME]) } if @data.any? @sequence.insert(@sequence.index(NAME) || 0, PATH) unless @sequence.include?(PATH) end reset :format @view = view return end |
#check(row) ⇒ Object
True when the row is a directory or passes base Grid filtering.
browser.check 0 # => true if navigable
298 |
# File 'lib/browser.rb', line 298 def check row; super or ( !@filter_dirs and @data[row][SUBTYPE] == "directory" ) end |
#confirm ⇒ Object
Returns the current directory path as the confirm result.
198 |
# File 'lib/browser.rb', line 198 def confirm; return @directory end |
#directories ⇒ Object
Returns row ids for all directories in the current listing.
browser.directories # => [0, 1, 3]
390 |
# File 'lib/browser.rb', line 390 def directories; ids.select{ |id| @data[id][SUBTYPE] == 'directory' } end |
#filter_display ⇒ String
Formats active filters as 'column: query', joined by ' / '.
browser.filter_display # => "name: foo / size: big"
378 379 380 381 382 383 384 |
# File 'lib/browser.rb', line 378 def filter_display return "no filter" if @filters.empty? @filters.map { |col, q| q = "/#{q.source}/" if q.is_a?(Regexp) "#{col.is_a?(Symbol) ? col : @header[col] || col}:#{q}" }.join(" / ") end |
#filter_view ⇒ Object
Open a filter popup on the chosen row/column and apply the input.
browser.filter_view # prompts for filter text
269 270 |
# File 'lib/browser.rb', line 269 def filter_view; add_filter *@user.ask( filter: [ popup( type: :"[f]ilter" ), :row, NAME, { column: 0 }], with: :line ) end |
#help ⇒ Object
Display a help grid listing all keybindings.
256 |
# File 'lib/browser.rb', line 256 def help; @user.help end |
#home ⇒ Object
Navigate to the home directory.
browser.home # => cd "~"
243 |
# File 'lib/browser.rb', line 243 def home; cd ?~ end |
#mark ⇒ Object
Prompts to select rows by index. Returns chosen ids or nil.
browser.mark # => [0, 2, 5] or nil
204 |
# File 'lib/browser.rb', line 204 def mark; return @user.ask( 'mark files': [self, :rows] ) end |
#mark_all ⇒ Object
Selects all non-directory rows.
browser.mark_all # => [0, 3, 7] (file ids only)
219 |
# File 'lib/browser.rb', line 219 def mark_all; return @selected[:rows] = ids - directories end |
#mark_invert ⇒ Object
Inverts selection across all non-directory rows.
browser.mark_invert # => toggled ids
225 |
# File 'lib/browser.rb', line 225 def mark_invert; return @selected[:rows] = ids - @selected[:rows] end |
#mark_range ⇒ Object
Toggles selection for every row within a "from..to" range.
browser.mark_range # prompts for from/to, toggles selection
210 211 212 213 |
# File 'lib/browser.rb', line 210 def mark_range; return ids[ ( eval @user.ask( 'mark from': [self, :relative_row], 'to': [self, :relative_row] ).join '..' ) ].each{|id| @selected[:rows].include?(id) ? @selected[:rows].delete(id) : @selected[:rows] << id } end |
#pick(type = 'file', **kw) ⇒ Object
Interactive file/directory picker. Blocks until a selection or Escape.
Return on a file yields its raw absolute path; multi-select joins the
chosen paths double-quoted with spaces. Enter on a directory triggers
cd. type optionally filters by MIME family (audio, video, image,
text, application, inode). Mouse: left-click a row to pick it; wheel
up/down scrolls the listing.
browser.pick # => /home/user/file.txt
browser.pick 'image' # => /path/to/photo.png (images only)
browser.pick nil # => anything, same as 'file'
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/browser.rb', line 312 def pick type='file', **kw type ||= 'file' type = type.to_s return super(type, **kw) if type[/row|column|field|none/] types = %w[audio video image text application inode] add_filter( types.include?( type ) ? TYPE : SUBTYPE, type ) if type == 'directory' or types.include?( type ) loop do show draw_hints :row key = Typr.read_key if key == @keymap[:exit] @filters.clear sort return end if key == @keymap[:confirm] and type == 'directory' @filters.clear sort return @directory end if key.is_a?(Typr::Mouse) choice = send key next if choice == :scroll or choice == :outside else next unless choice = send( key ) end next unless choice case choice when Array; choice = choice.map{ |id| @data[id][NAME] }.join('" "') when Integer; file = @data[ choice ] if file[SUBTYPE] == 'directory'; cd file[TARGET] || file[NAME]; next else choice = file[NAME] end end @filters.clear sort return choice end end |
#popup(args = {}) ⇒ Object
Create a small Grid popup under an info bar item for column selection.
args must include :type matching an actions key for positioning.
browser.popup type: :"[s]ort" # sort-picker popup
412 413 414 415 416 417 418 419 |
# File 'lib/browser.rb', line 412 def popup args={} Grid.new( { alternate:false, border: :light, borders:{ top:nil, top_left:nil, top_right:nil }, top: top, align: [:right], input:@header, left: left + ( @positions[args[:type]] || 0 ) - ( args[:input] || @header ).map( &:size ).max - 1, colors:{ columns: [ @colors[:actions][args[:type]] ] } }.merge args ) end |
#process(row) ⇒ Object
Colors symlink names green/red based on target existence and applies
per-MIME-type foreground colors from @colors[:types].
browser.process 0 # => sets colors for row 0
145 146 147 148 149 |
# File 'lib/browser.rb', line 145 def process row; super color = @colors[:types][@data[row][SUBTYPE].to_sym] || @colors[:types][@data[row][TYPE].to_sym] @colors[:fields][[row,NAME]] = color if color end |
#reset_view ⇒ Object
Reset display, selection, and position state then re-sort.
browser.reset_view
263 |
# File 'lib/browser.rb', line 263 def reset_view; cd @directory; reset [:display, :selection, :position]; sort end |
#root ⇒ Object
Navigate to the root directory.
browser.root # => cd "/"
237 |
# File 'lib/browser.rb', line 237 def root; cd ?/ end |
#scan_file(file) ⇒ Object
Build a row for a single directory entry from filesystem metadata only.
MIME type detection (extension database and file --mime-type) happens
in a batch pass inside #cd; type/subtype are left as "?" here.
browser.scan_file "image.png" # => 12-column row
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/browser.rb', line 125 def scan_file file target = nil if File.symlink? file target = File.readlink( file ) rescue $!.to_s return [file, target, "????", false, "?", "?", 0, 0, 0, 0, "?", "?", nil] unless File.exist?(file) end stat = File.stat(file) rescue nil return [file, "", "????", false, "?", "?", 0, 0, 0, 0, "?", "?", nil] unless stat [ file, target, stat.mode.to_s(8)[-3..-1].chars.map{|d| "rwx".chars.map.with_index{|c,i| d.to_i[2-i]==0 ? ?- : c } }.join, ( File.executable?(file) and stat.file? ), stat.uid, stat.gid, stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i, "?", "?", nil ] end |
#search ⇒ Object
Open live / search filtered on the name column.
browser.search # type to narrow, Escape restores, Enter commits
276 277 278 279 280 |
# File 'lib/browser.rb', line 276 def search @suppress_user = true pick :none, column: NAME @suppress_user = false end |
#send(key) ⇒ Object
Resolves hint characters typed on a row. Returns the matching row id for fast navigation, otherwise falls through to Stack#send.
browser.send "1" # => row id if hint "1" is visible
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/browser.rb', line 177 def send key if key.is_a?(Typr::Mouse) and key.press? and key.left? [@head, @user].each do |w| next unless w.respond_to?(:data_at) value = w.data_at(key.x, key.y) next unless value key = extract_key(value.to_s) while key.is_a?(String) key = send(key) end return key end end if key.is_a?(String) and id = @hints[0..[height, rows-1+headspace].min-@hints_start-1].index(key) return page[id+@hints_start] else super end end |
#show ⇒ Object
Renders the grid with an info bar above showing the current directory path and colored status items for filter, sort, and view.
browser.show # shows browser with info bar
357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/browser.rb', line 357 def show; super user = Etc.getpwuid(Process.euid).name rescue ENV["USER"] || Etc.getlogin @head.colors[:columns][0] = user == "root" ? [:red, :black] : [:green, :black] @head.reset :format @head.show move @head.positions(0)[1] - @head.separator.size, @parent.top - 1 color @colors[:default] draw '@' @positions = { :"[f]ilter" => 2, :"[s]ort" => 3, :"[v]iews" => 4 }.transform_values do |col| @head.left + @head.positions(0)[col] + @head.width_for(col) - 1 end @user.show unless @suppress_user end |
#sort ⇒ Object
Sort by NAME by default; directories always appear before files within each prefix grouping.
browser.sort # re-sorts with dirs first
398 399 400 401 402 403 404 |
# File 'lib/browser.rb', line 398 def sort @sort ||= NAME super dirs = ids.select{ |id| @data[id][SUBTYPE] == 'directory' } @map = (directories + ids).uniq nil end |
#sort_view ⇒ Object
Open a sort-picker popup to choose a column to sort by.
browser.sort_view # pick a column header to sort
286 |
# File 'lib/browser.rb', line 286 def sort_view; sort_by @user.ask( "sort by": [ popup( type: :"[s]ort" ), :row, nil, { column: 0 }] ) end |
#toggle_hidden ⇒ Object
Toggle visibility of hidden files (those starting with a dot).
browser.toggle_hidden
249 250 251 252 |
# File 'lib/browser.rb', line 249 def toggle_hidden @show_hidden = !@show_hidden cd @directory end |
#top ⇒ Object
Top offset plus one row for the path info bar.
45 |
# File 'lib/browser.rb', line 45 def top; super + 1 end |
#views ⇒ Object
Open a view-picker popup and switch to the selected view.
browser.views # choose :simple, :compact, :stats, or :full
292 |
# File 'lib/browser.rb', line 292 def views; change_view( popup( type: :"[v]iews", input: @views.keys ).pick( :row, column: 0 ) ) end |