fjord/ls.rb
2024-05-11 10:59:59 +09:00

118 lines
2.6 KiB
Ruby

# frozen_string_literal: true
require 'optparse'
require 'etc'
COLUMNS = 3
SIZE_INDENT = 3
def run
listed_filenames = list_filenames
filenames_matrix = slice_filenames(listed_filenames)
filled_filenames = fill_filenames(filenames_matrix)
arrange_filenames(filled_filenames)
end
def list_filenames
params = ARGV.getopts('a', 'r', 'l')
flags = params['a'] ? File::FNM_DOTMATCH : 0
filenames = Dir.glob('*', flags)
params['l'] ? ownerinfo(filenames) : filenames
if params['r']
filenames.reverse
else
filenames
end
end
def ownerinfo(filenames)
filenames.each do |file|
file_stat = File::Stat.new(file)
file_type(file_stat)
permission(file_stat)
print " #{file_stat.nlink}"
print " #{Etc.getpwuid(file_stat.uid).name}"
print " #{Etc.getgrgid(file_stat.gid).name}"
print " #{file_stat.size}".rjust(file_size(filenames))
timestamp(file_stat)
symbolic(file)
puts
end
end
def symbolic(file)
if File.lstat(file).symlink?
print " #{file} -> #{File.readlink(file)}"
else
print " #{file}"
end
end
def permission(file_stat)
(-3..-1).each do |index|
case file_stat.mode.to_s(8)[index]
when '0' then print '---'
when '1' then print '--x'
when '2' then print '-w-'
when '3' then print '-wx'
when '4' then print 'r--'
when '5' then print 'r-x'
when '6' then print 'rw-'
when '7' then print 'rwx'
end
end
end
def file_type(file_stat)
case file_stat.ftype
when 'file'
print '-'
when 'directory'
print 'd'
when 'characterSpecial'
print 'c'
when 'fifo'
print 'p'
when 'link'
print 'l'
when 'socket'
print 's'
end
end
def file_size(filenames)
filenames.map { |file| File.size(file) }.max.to_s.length + SIZE_INDENT
end
def timestamp(file_stat)
if Time.now - file_stat.mtime >= (60 * 60 * 24 * (365 / 2.0)) || (Time.now - file_stat.mtime).negative?
print " #{file_stat.mtime.strftime('%_m %_d %Y')}"
else
print " #{file_stat.mtime.strftime('%_m %_d %H:%M')}"
end
end
def slice_filenames(listed_filenames)
columns_size = listed_filenames.size.ceildiv(COLUMNS)
listed_filenames.each_slice(columns_size).to_a
end
def fill_filenames(filenames_matrix)
array_size = filenames_matrix.map(&:size).max
filenames_matrix.each do |slice|
slice << '' while slice.size < array_size
end
filenames_matrix.transpose
end
def arrange_filenames(filled_filenames)
filenames_count = filled_filenames.flatten.map(&:size).max
filled_filenames.each do |arrange|
arrange.each do |arranged|
print arranged.ljust(filenames_count + 5)
end
puts
end
end
run