Class: Rfd::Item
Constant Summary collapse
- ICON_DIRECTORY =
Nerd Font icons (requires Nerd Font installed)
"\uf07c"- ICON_SYMLINK =
"\uf0c1"- ICON_EXEC =
"\uf013"- ICON_FILE =
"\uf15b"- ICON_RUBY =
"\ue791"- ICON_PYTHON =
"\ue73c"- ICON_JS =
"\ue74e"- ICON_TS =
"\ue628"- ICON_HTML =
"\ue736"- ICON_CSS =
"\ue749"- ICON_JSON =
"\ue60b"- ICON_MARKDOWN =
"\ue73e"- ICON_SHELL =
"\uf489"- ICON_C =
"\ue61e"- ICON_CPP =
"\ue61d"- ICON_GO =
"\ue626"- ICON_RUST =
"\ue7a8"- ICON_JAVA =
"\ue738"- ICON_PHP =
"\ue73d"- ICON_SWIFT =
"\ue755"- ICON_VIM =
"\ue62b"- ICON_LUA =
"\ue620"- ICON_SQL =
"\uf1c0"- ICON_PDF =
"\uf1c1"- ICON_ARCHIVE =
"\uf1c6"- ICON_IMAGE =
"\uf1c5"- ICON_AUDIO =
"\uf1c7"- ICON_VIDEO =
"\uf1c8"- ICON_FONT =
"\uf031"- ICON_LOCK =
"\uf023"- ICON_CONFIG =
"\ue615"- ICON_LOG =
"\uf18d"- FILE_ICONS =
{ '.rb' => ICON_RUBY, '.rake' => ICON_RUBY, '.gemspec' => ICON_RUBY, '.py' => ICON_PYTHON, '.pyc' => ICON_PYTHON, '.js' => ICON_JS, '.mjs' => ICON_JS, '.cjs' => ICON_JS, '.jsx' => ICON_JS, '.ts' => ICON_TS, '.tsx' => ICON_TS, '.html' => ICON_HTML, '.htm' => ICON_HTML, '.css' => ICON_CSS, '.scss' => ICON_CSS, '.sass' => ICON_CSS, '.json' => ICON_JSON, '.yaml' => ICON_CONFIG, '.yml' => ICON_CONFIG, '.md' => ICON_MARKDOWN, '.markdown' => ICON_MARKDOWN, '.sh' => ICON_SHELL, '.bash' => ICON_SHELL, '.zsh' => ICON_SHELL, '.c' => ICON_C, '.h' => ICON_C, '.cpp' => ICON_CPP, '.hpp' => ICON_CPP, '.cc' => ICON_CPP, '.go' => ICON_GO, '.rs' => ICON_RUST, '.java' => ICON_JAVA, '.jar' => ICON_JAVA, '.php' => ICON_PHP, '.swift' => ICON_SWIFT, '.vim' => ICON_VIM, '.lua' => ICON_LUA, '.sql' => ICON_SQL, '.pdf' => ICON_PDF, '.zip' => ICON_ARCHIVE, '.tar' => ICON_ARCHIVE, '.gz' => ICON_ARCHIVE, '.rar' => ICON_ARCHIVE, '.7z' => ICON_ARCHIVE, '.png' => ICON_IMAGE, '.jpg' => ICON_IMAGE, '.jpeg' => ICON_IMAGE, '.gif' => ICON_IMAGE, '.svg' => ICON_IMAGE, '.webp' => ICON_IMAGE, '.ico' => ICON_IMAGE, '.heic' => ICON_IMAGE, '.heif' => ICON_IMAGE, '.mp3' => ICON_AUDIO, '.wav' => ICON_AUDIO, '.flac' => ICON_AUDIO, '.ogg' => ICON_AUDIO, '.mp4' => ICON_VIDEO, '.avi' => ICON_VIDEO, '.mov' => ICON_VIDEO, '.mkv' => ICON_VIDEO, '.webm' => ICON_VIDEO, '.ttf' => ICON_FONT, '.otf' => ICON_FONT, '.woff' => ICON_FONT, '.lock' => ICON_LOCK, '.env' => ICON_CONFIG, '.log' => ICON_LOG, }.freeze
Instance Attribute Summary collapse
-
#dir ⇒ Object
readonly
Returns the value of attribute dir.
-
#index ⇒ Object
Returns the value of attribute index.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#stat ⇒ Object
readonly
Returns the value of attribute stat.
Instance Method Summary collapse
- #<=>(o) ⇒ Object
- #archive? ⇒ Boolean
- #atime ⇒ Object
- #audio? ⇒ Boolean
- #basename ⇒ Object
- #color ⇒ Object
- #ctime ⇒ Object
- #current_mark ⇒ Object
- #directory? ⇒ Boolean
- #display_name ⇒ Object
- #executable? ⇒ Boolean
- #extname ⇒ Object
- #full_display_name ⇒ Object
- #gz? ⇒ Boolean
- #heic? ⇒ Boolean
- #hidden? ⇒ Boolean
- #icon ⇒ Object
- #image? ⇒ Boolean
-
#initialize(path: nil, dir: nil, name: nil, stat: nil, window_width: nil) ⇒ Item
constructor
A new instance of Item.
- #join(*ary) ⇒ Object
- #markdown? ⇒ Boolean
- #marked? ⇒ Boolean
- #mb_char_size(c) ⇒ Object
- #mb_left(str, size) ⇒ Object
- #mb_ljust(str, size) ⇒ Object
- #mb_size(str) ⇒ Object
- #mode ⇒ Object
- #mtime ⇒ Object
- #path ⇒ Object
- #pdf? ⇒ Boolean
-
#preview_type ⇒ Object
Returns the preview type symbol for the preview server.
- #realpath ⇒ Object
- #size ⇒ Object
- #size_or_dir ⇒ Object
- #svg? ⇒ Boolean
- #symlink? ⇒ Boolean
- #target ⇒ Object
- #to_s ⇒ Object
- #to_str ⇒ Object
- #toggle_mark ⇒ Object
- #video? ⇒ Boolean
- #zip? ⇒ Boolean
Constructor Details
#initialize(path: nil, dir: nil, name: nil, stat: nil, window_width: nil) ⇒ Item
Returns a new instance of Item.
8 9 10 11 |
# File 'lib/rfd/item.rb', line 8 def initialize(path: nil, dir: nil, name: nil, stat: nil, window_width: nil) @path, @dir, @name, @stat, @window_width, @marked = path, dir || File.dirname(path), name || File.basename(path), stat, window_width, false @stat = File.lstat self.path unless stat end |
Instance Attribute Details
#dir ⇒ Object (readonly)
Returns the value of attribute dir.
5 6 7 |
# File 'lib/rfd/item.rb', line 5 def dir @dir end |
#index ⇒ Object
Returns the value of attribute index.
6 7 8 |
# File 'lib/rfd/item.rb', line 6 def index @index end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
5 6 7 |
# File 'lib/rfd/item.rb', line 5 def name @name end |
#stat ⇒ Object (readonly)
Returns the value of attribute stat.
5 6 7 |
# File 'lib/rfd/item.rb', line 5 def stat @stat end |
Instance Method Details
#<=>(o) ⇒ Object
361 362 363 364 365 366 367 368 369 |
# File 'lib/rfd/item.rb', line 361 def <=>(o) if directory? && !o.directory? 1 elsif !directory? && o.directory? -1 else name <=> o.name end end |
#archive? ⇒ Boolean
151 152 153 |
# File 'lib/rfd/item.rb', line 151 def archive? zip? || gz? end |
#atime ⇒ Object
71 72 73 |
# File 'lib/rfd/item.rb', line 71 def atime stat.atime.strftime('%Y-%m-%d %H:%M:%S') end |
#audio? ⇒ Boolean
207 208 209 |
# File 'lib/rfd/item.rb', line 207 def audio? !directory? && %w[.mp3 .wav .flac .ogg .m4a .aac .aiff .wma].include?(extname.downcase) end |
#basename ⇒ Object
17 18 19 |
# File 'lib/rfd/item.rb', line 17 def basename @basename ||= File.basename name, extname end |
#color ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/rfd/item.rb', line 49 def color if symlink? Curses::COLOR_MAGENTA elsif hidden? Curses::COLOR_GREEN elsif directory? Curses::COLOR_CYAN elsif executable? Curses::COLOR_RED else Curses::COLOR_WHITE end end |
#ctime ⇒ Object
75 76 77 |
# File 'lib/rfd/item.rb', line 75 def ctime stat.ctime.strftime('%Y-%m-%d %H:%M:%S') end |
#current_mark ⇒ Object
251 252 253 |
# File 'lib/rfd/item.rb', line 251 def current_mark marked? ? '*' : ' ' end |
#directory? ⇒ Boolean
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/rfd/item.rb', line 103 def directory? @directory ||= if symlink? begin File.stat(path).directory? rescue Errno::ENOENT false end else stat.directory? end end |
#display_name ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rfd/item.rb', line 35 def display_name @display_name ||= begin n = full_display_name offset = ENV['RFD_NO_ICONS'] ? 15 : 18 if mb_size(n) <= @window_width - offset n elsif symlink? mb_left n, @window_width - offset - 1 else "#{mb_left(basename, @window_width - offset - 1 - extname.size)}…#{extname}" end end end |
#executable? ⇒ Boolean
123 124 125 |
# File 'lib/rfd/item.rb', line 123 def executable? stat.executable? end |
#extname ⇒ Object
21 22 23 |
# File 'lib/rfd/item.rb', line 21 def extname @extname ||= File.extname name end |
#full_display_name ⇒ Object
29 30 31 32 33 |
# File 'lib/rfd/item.rb', line 29 def full_display_name n = @name.dup n << " -> #{target}" if symlink? n end |
#gz? ⇒ Boolean
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rfd/item.rb', line 139 def gz? @gz_ ||= begin if directory? false else File.binread(realpath, 2).unpack('n').first == 0x1f8b end rescue false end end |
#heic? ⇒ Boolean
170 171 172 173 174 175 176 177 178 179 |
# File 'lib/rfd/item.rb', line 170 def heic? @heic ||= begin return false if directory? return true if %w[.heic .heif].include?(extname.downcase) magic = File.binread(realpath, 12).bytes magic[4..7] == [0x66, 0x74, 0x79, 0x70] # "ftyp" at offset 4 rescue false end end |
#hidden? ⇒ Boolean
119 120 121 |
# File 'lib/rfd/item.rb', line 119 def hidden? name.start_with?('.') && (name != '.') && (name != '..') end |
#icon ⇒ Object
320 321 322 323 324 325 326 |
# File 'lib/rfd/item.rb', line 320 def icon return '' if ENV['RFD_NO_ICONS'] return ICON_DIRECTORY if directory? return ICON_SYMLINK if symlink? return ICON_EXEC if executable? FILE_ICONS[extname.downcase] || ICON_FILE end |
#image? ⇒ Boolean
155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/rfd/item.rb', line 155 def image? @image ||= begin return false if directory? return true if svg? return true if heic? magic = File.binread(realpath, 12).bytes (magic[0..3] == [0x89, 0x50, 0x4E, 0x47]) || # PNG (magic[0..2] == [0xFF, 0xD8, 0xFF]) || # JPEG (magic[0..2] == [0x47, 0x49, 0x46]) || # GIF (magic[0..3] == [0x52, 0x49, 0x46, 0x46] && magic[8..11] == [0x57, 0x45, 0x42, 0x50]) # WebP (RIFF....WEBP) rescue false end end |
#join(*ary) ⇒ Object
25 26 27 |
# File 'lib/rfd/item.rb', line 25 def join(*ary) File.join path, ary end |
#markdown? ⇒ Boolean
203 204 205 |
# File 'lib/rfd/item.rb', line 203 def markdown? !directory? && %w[.md .markdown].include?(extname.downcase) end |
#marked? ⇒ Boolean
247 248 249 |
# File 'lib/rfd/item.rb', line 247 def marked? @marked end |
#mb_char_size(c) ⇒ Object
337 338 339 |
# File 'lib/rfd/item.rb', line 337 def mb_char_size(c) c == '…' ? 1 : c.bytesize == 1 ? 1 : 2 end |
#mb_left(str, size) ⇒ Object
328 329 330 331 332 333 334 335 |
# File 'lib/rfd/item.rb', line 328 def mb_left(str, size) len = 0 index = str.each_char.with_index do |c, i| break i if len + mb_char_size(c) > size len += mb_size c end str[0, index] end |
#mb_ljust(str, size) ⇒ Object
345 346 347 |
# File 'lib/rfd/item.rb', line 345 def mb_ljust(str, size) "#{str}#{' ' * [0, size - mb_size(str)].max}" end |
#mb_size(str) ⇒ Object
341 342 343 |
# File 'lib/rfd/item.rb', line 341 def mb_size(str) str.each_char.inject(0) {|l, c| l += mb_char_size(c)} end |
#mode ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/rfd/item.rb', line 83 def mode @mode ||= begin m = stat.mode ft = directory? ? 'd' : symlink? ? 'l' : '-' owner = (m >> 6) & 07 group = (m >> 3) & 07 other = m & 07 ret = [owner, group, other].inject(ft) do |str, perms| str + "#{perms & 4 != 0 ? 'r' : '-'}#{perms & 2 != 0 ? 'w' : '-'}#{perms & 1 != 0 ? 'x' : '-'}" end # setuid: 's' if execute set, 'S' if not ret[3] = (owner & 1 != 0 ? 's' : 'S') if m & 04000 != 0 # setgid: 's' if execute set, 'S' if not ret[6] = (group & 1 != 0 ? 's' : 'S') if m & 02000 != 0 # sticky: 't' if execute set, 'T' if not ret[9] = (other & 1 != 0 ? 't' : 'T') if m & 01000 != 0 ret end end |
#mtime ⇒ Object
79 80 81 |
# File 'lib/rfd/item.rb', line 79 def mtime stat.mtime.strftime('%Y-%m-%d %H:%M:%S') end |
#path ⇒ Object
13 14 15 |
# File 'lib/rfd/item.rb', line 13 def path @path ||= File.join @dir, @name end |
#pdf? ⇒ Boolean
193 194 195 196 197 198 199 200 201 |
# File 'lib/rfd/item.rb', line 193 def pdf? @pdf ||= begin return false if directory? magic = File.binread(realpath, 4).bytes magic == [0x25, 0x50, 0x44, 0x46] # %PDF rescue false end end |
#preview_type ⇒ Object
Returns the preview type symbol for the preview server
Order matters here:
-
video? must come before heic? because MOV/MP4 files share the same “ftyp” magic bytes at offset 4 that heic? checks for
-
heic? must come before image? because HEIC conversion is slow and needs async handling, while other image formats can be displayed directly
222 223 224 225 226 227 228 229 230 |
# File 'lib/rfd/item.rb', line 222 def preview_type return :directory if directory? return :video if video? return :heic if heic? return :image if image? return :pdf if pdf? return :markdown if markdown? :text end |
#realpath ⇒ Object
236 237 238 |
# File 'lib/rfd/item.rb', line 236 def realpath @realpath ||= File.realpath path end |
#size ⇒ Object
63 64 65 |
# File 'lib/rfd/item.rb', line 63 def size directory? ? 0 : stat.size end |
#size_or_dir ⇒ Object
67 68 69 |
# File 'lib/rfd/item.rb', line 67 def size_or_dir directory? ? '<DIR>' : size.to_s end |
#svg? ⇒ Boolean
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/rfd/item.rb', line 181 def svg? @svg ||= begin return false if directory? return true if extname.downcase == '.svg' # Check content for <svg tag content = File.binread(realpath, 256) content.include?('<svg') rescue false end end |
#symlink? ⇒ Boolean
115 116 117 |
# File 'lib/rfd/item.rb', line 115 def symlink? stat.symlink? end |
#target ⇒ Object
232 233 234 |
# File 'lib/rfd/item.rb', line 232 def target File.readlink path if symlink? end |
#to_s ⇒ Object
349 350 351 352 353 354 355 |
# File 'lib/rfd/item.rb', line 349 def to_s if ENV['RFD_NO_ICONS'] "#{current_mark}#{mb_ljust(display_name, @window_width - 15)}#{size_or_dir.rjust(13)}" else "#{current_mark}#{icon} #{mb_ljust(display_name, @window_width - 18)}#{size_or_dir.rjust(13)}" end end |
#to_str ⇒ Object
357 358 359 |
# File 'lib/rfd/item.rb', line 357 def to_str path end |
#toggle_mark ⇒ Object
240 241 242 243 244 245 |
# File 'lib/rfd/item.rb', line 240 def toggle_mark unless %w(. ..).include? name @marked = !@marked true end end |
#video? ⇒ Boolean
211 212 213 |
# File 'lib/rfd/item.rb', line 211 def video? !directory? && %w[.mp4 .avi .mov .mkv .webm .flv .wmv .m4v .mpeg .mpg].include?(extname.downcase) end |
#zip? ⇒ Boolean
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/rfd/item.rb', line 127 def zip? @zip_ ||= begin if directory? false else File.binread(realpath, 4).unpack('V').first == 0x04034b50 end rescue false end end |