Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions 08.ls_object/base_view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

class BaseView
def initialize(file_names)
@file_names = file_names
@file_infos = file_names.map do |file_name|
File.lstat(file_name)
end
end

def render
raise NotImplementedError, 'renderはサブクラスで定義する'
end
end
30 changes: 30 additions & 0 deletions 08.ls_object/column_view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require_relative 'base_view'

class ColumnView < BaseView
def initialize(file_names, columns = 3)
super(file_names)
@columns = columns
end

def render
max_len = @file_names.map(&:length).max
rows = display_rows(@file_names)

rows.times do |row_index|
@columns.times do
break if row_index > @file_names.size

file = @file_names[row_index]
print file.ljust(max_len).concat("\t") unless file.nil?
row_index += rows
end
print "\n"
end
end

def display_rows(list)
(list.size.to_r / @columns.to_r).to_f.ceil
end
end
77 changes: 77 additions & 0 deletions 08.ls_object/list_view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

require 'etc'
require_relative 'base_view'

class ListView < BaseView
FILE_TYPE_STR = {
'file' => '-',
'blockSpecial' => 'b',
'characterSpecial' => 'c',
'directory' => 'd',
'link' => 'l',
'fifo' => 'p',
'socket' => 's',
'unknown' => '?'
}.freeze

PERMISSION_STR = {
0 => '-',
4 => 'r',
2 => 'w',
1 => 'x'
}.freeze

def render
display_file_infos = display_file_info
row_max_len = row_max_lenght(display_file_infos)
puts "total #{display_file_infos.map { |v| v[:blocks] }.sum}"
display_file_infos.each do |file|
print file[:type].rjust(row_max_len[:type])
print "#{file[:permission].rjust(row_max_len[:permission])} "
print "#{file[:hard_link].rjust(row_max_len[:hard_link])} "
print "#{file[:owner].ljust(row_max_len[:owner])} "
print "#{file[:group].ljust(row_max_len[:group])} "
print "#{file[:file_size].to_s.rjust(row_max_len[:file_size])} "
print "#{file[:timestamp].rjust(row_max_len[:timestamp])} "
print "#{file[:file_name]} "
print " -> #{File.readlink(file[:file_name])}" if file[:file_name] == 'l'
print "\n"
end
end

def display_file_info
@file_names.map do |file_name|
stat = File.lstat(file_name)
display = {
file_name: file_name,
type: FILE_TYPE_STR[stat.ftype],
permission: print_permission(stat.mode, PERMISSION_STR),
hard_link: stat.nlink.to_s,
owner: Etc.getpwuid(stat.uid).name,
group: Etc.getgrgid(stat.gid).name,
file_size: stat.size,
timestamp: stat.mtime.strftime('%_m %_d %H:%M'),
blocks: stat.blocks
}
display
end
end

def row_max_lenght(display_file_infos)
max_len = Hash.new(0)
display_file_infos.each do |item|
item.each do |key, value|
max_len[key] = [max_len[key], value.to_s.length].max
end
end
max_len
end

def print_permission(mode, permission_str)
# 0100744 -> 774
mode.to_s(8)[-3, 3].split('').map do |v|
2.downto(0).map { |count| permission_str[v.to_i & (1 << count)] }.join
end.join
end
end
8 changes: 8 additions & 0 deletions 08.ls_object/ls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require_relative 'option'
require_relative 'ls_command'

options = Option.new(ARGV)
LsCommand.new.run(options)
21 changes: 21 additions & 0 deletions 08.ls_object/ls_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require_relative 'list_view'
require_relative 'column_view'

class LsCommand
def run(options)
file_names = target_files(options)
file_names.reverse! if options.reverse_order

view = options.list_mode ? ListView.new(file_names) : ColumnView.new(file_names, 3)
view.render
end

def target_files(options)
flag = 0
flag = File::FNM_DOTMATCH if options.include_dotfiles

Dir.glob('*', flag)
end
end
11 changes: 11 additions & 0 deletions 08.ls_object/option.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class Option
attr_reader :include_dotfiles, :reverse_order, :list_mode

def initialize(argv)
@include_dotfiles, @reverse_order, @list_mode = %w[a r l].map do |opt|
argv.any? { |v| v.start_with?('-') && v.include?(opt) }
end
end
end