# frozen_string_literal: true require 'optparse' require 'etc' COLUMNS = 3 MARGIN = 3 PERMISSION = { '0' => '---', '1' => '--x', '2' => '-w-', '3' => '-wx', '4' => 'r--', '5' => 'r-x', '6' => 'rw-', '7' => 'rwx' }.freeze FILETYPE = { '1' => 'p', '2' => 'c', '4' => 'd', '6' => 'b', '10' => '-', '12' => 'l' }.freeze 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') filenames = params['a'] ? Dir.glob('*', File::FNM_DOTMATCH) : Dir.glob('*') filenames = filenames.reverse if params['r'] if params['l'] ownerinfo(filenames) exit else filenames end end def ownerinfo(filenames) file_blocks(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(filenames) if File.lstat(filenames).symlink? print " #{filenames} -> #{File.readlink(filenames)}" else print " #{filenames}" 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) { 'fifo' => 'p', 'characterSpecial' => 'c', 'directory' => 'd', 'blockSpecial' => 'b', 'file' => '-', 'link' => 'l', 'socket' => 's' }[file_stat] end def file_size(filenames) filenames.map { |file| File.size(file) }.max.to_s.length + MARGIN end def timestamp(file_stat) print file_stat.mtime.strftime('%_m %_d %H:%M') end def file_blocks(filenames) blocks = filenames.map do |file| File::Stat.new(file).blocks end puts "total #{blocks.sum}" 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