Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions 07.ls_object/basic_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require_relative 'file_info'

class BasicFormat
def initialize(file_paths)
@files = file_paths.map { |file_path| FileInfo.new(file_path) }
end

def format_lines
NotImplementedError
end
end
27 changes: 27 additions & 0 deletions 07.ls_object/detailed_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require_relative 'basic_format'

class DetailedFormat < BasicFormat
def format_lines
@files.map do |file|
file.full_info_format(max_lengths)
end
end

def calculate_total_blocks
@files.sum(&:blocks)
end

private

def max_lengths
max_lengths = {}
max_lengths[:size] = @files.map { |file| file.size.to_s.length }.max
max_lengths[:nlink] = @files.map { |file| file.link_num.to_s.length }.max
max_lengths[:user] = @files.map { |file| file.user.length }.max
max_lengths[:group] = @files.map { |file| file.group.length }.max

max_lengths
end
end
75 changes: 75 additions & 0 deletions 07.ls_object/file_info.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

require 'etc'

PERMISSIONS = { '0' => '---', '1' => '--x', '2' => '-w-', '3' => '-wx',
'4' => 'r--', '5' => 'r-x', '6' => 'rw-', '7' => 'rwx' }.freeze

class FileInfo
def initialize(file_path)
@file_path = file_path
end

def base_name
File.basename(@file_path)
end

def type
file_lstat = File.lstat(@file_path)
if file_lstat.directory?
'd'
elsif file_lstat.symlink?
'l'
else
'-'
end
end

def mode
file_stat.mode.to_s(8).slice(-3, 3).chars.to_a.map { |n| PERMISSIONS[n] }.join
end

def link_num
file_stat.nlink
end

def size
file_stat.size
end

def user
Etc.getpwuid(file_stat.uid).name
end

def group
Etc.getgrgid(file_stat.gid).name
end

def last_access_time
file_stat.mtime.strftime('%_m %_d %H:%M')
end

def symlink?
mode_num = File.lstat(@file_path).mode.to_s(8)
mode_num[0, 2] == '12'
end

def blocks
file_stat.blocks
end

def full_info_format(max_lengths)
"#{type}#{mode} "\
"#{link_num.to_s.rjust(max_lengths[:nlink])} "\
"#{user.rjust(max_lengths[:user])} #{group.to_s.rjust(max_lengths[:group])} "\
"#{size.to_s.rjust(max_lengths[:size])} "\
"#{last_access_time} #{base_name}"\
"#{" -> #{File.readlink(@file_path)}" if symlink?}"
end

private

def file_stat
File::Stat.new(@file_path)
end
end
14 changes: 14 additions & 0 deletions 07.ls_object/ls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require_relative 'ls_command'
require 'optparse'

opt = OptionParser.new
options = {}
opt.on('-a') { |v| options[:a] = v }
opt.on('-r') { |v| options[:r] = v }
opt.on('-l') { |v| options[:l] = v }
opt.parse!(ARGV)

path = ARGV[0] || '.'
LsCommand.new(path, options).display
28 changes: 28 additions & 0 deletions 07.ls_object/ls_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require_relative 'short_format'
require_relative 'detailed_format'

class LsCommand
def initialize(path, options)
@path = path
@options = options
end

def display
puts "total #{formatter.calculate_total_blocks}" if @options[:l]
puts formatter.format_lines
end

private

def file_paths
file_pattern = File.join(@path, '*')
file_paths = @options[:a] ? Dir.glob(file_pattern, File::FNM_DOTMATCH) : Dir.glob(file_pattern)
@options[:r] ? file_paths.reverse : file_paths
end

def formatter
@options[:l] ? DetailedFormat.new(file_paths) : ShortFormat.new(file_paths)
end
end
31 changes: 31 additions & 0 deletions 07.ls_object/short_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require_relative 'basic_format'

class ShortFormat < BasicFormat
COLUMN_NUM = 3

def format_lines
files_grouped_into_lines.map do |line|
line.map do |file|
file_name = file.base_name
file_name.ljust(max_length)
end.join(' ')
end
end

private

def files_grouped_into_lines
total_line_count = (@files.size.to_f / COLUMN_NUM).ceil
files_sliced = @files.each_slice(total_line_count).to_a

total_line_count.times.map do |index|
files_sliced.map { |files| files[index] }.compact
end
end

def max_length
@files.map { |file| file.base_name.size }.max
end
end