From b9c4e93c323d1959e2366318579bc60fd14cac5c Mon Sep 17 00:00:00 2001 From: shibainurou Date: Thu, 25 Jan 2024 21:37:20 +0900 Subject: [PATCH 1/7] =?UTF-8?q?ls=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=82=92=E3=82=AF=E3=83=A9=E3=82=B9=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/base_view.rb | 14 ++++++ 08.ls_object/column_view.rb | 27 ++++++++++++ 08.ls_object/list_view.rb | 85 +++++++++++++++++++++++++++++++++++++ 08.ls_object/ls.rb | 8 ++++ 08.ls_object/ls_command.rb | 26 ++++++++++++ 08.ls_object/option.rb | 11 +++++ 6 files changed, 171 insertions(+) create mode 100644 08.ls_object/base_view.rb create mode 100644 08.ls_object/column_view.rb create mode 100644 08.ls_object/list_view.rb create mode 100755 08.ls_object/ls.rb create mode 100644 08.ls_object/ls_command.rb create mode 100644 08.ls_object/option.rb diff --git a/08.ls_object/base_view.rb b/08.ls_object/base_view.rb new file mode 100644 index 0000000000..e187c3a4b3 --- /dev/null +++ b/08.ls_object/base_view.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class BaseView + def initialize(file_names) + @file_names = file_names + @file_infos = file_names.map do |filename| + File.lstat(filename) + end + end + + def render + raise NotImplementedError, 'renderはサブクラスで定義する' + end +end diff --git a/08.ls_object/column_view.rb b/08.ls_object/column_view.rb new file mode 100644 index 0000000000..7c6397f3eb --- /dev/null +++ b/08.ls_object/column_view.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require_relative 'base_view' + +class ColumnView < BaseView + COLUMNS = 3 + + 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 diff --git a/08.ls_object/list_view.rb b/08.ls_object/list_view.rb new file mode 100644 index 0000000000..170d94d15c --- /dev/null +++ b/08.ls_object/list_view.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'etc' +require_relative 'base_view' + +class ListView < BaseView + Struct.new('Display', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp, :blocks) + Struct.new('MaxLenght', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp) + + 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(&: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.hardlink.rjust(row_max_len.hardlink)} " + print "#{file.owner.ljust(row_max_len.owner)} " + print "#{file.group.ljust(row_max_len.group)} " + print "#{file.filesize.to_s.rjust(row_max_len.filesize)} " + print "#{file.timestamp.rjust(row_max_len.timestamp)} " + print file.filename + print " -> #{File.readlink(file.filename)}" if file.type == 'l' + print "\n" + end + end + + def display_file_info + @file_names.map do |f| + d = Struct::Display.new(f) + stat = File.lstat(f) + d.filename = f + d.type = FILE_TYPE_STR[stat.ftype] + d.permission = print_permission(stat.mode, PERMISSION_STR) + d.hardlink = stat.nlink.to_s + d.owner = Etc.getpwuid(stat.uid).name + d.group = Etc.getgrgid(stat.gid).name + d.filesize = stat.size + d.timestamp = stat.mtime.strftime('%_m %_d %H:%M') + d.blocks = stat.blocks + d + end + end + + def row_max_lenght(display_file_infos) + max_len = Struct::MaxLenght.new(0, 0, 0, 0, 0, 0, 0, 0) + display_file_infos.each do |v| + max_len.filename = [max_len.filename, v.filename.length].max + max_len.type = [max_len.type, v.type.length].max + max_len.permission = [max_len.permission, v.permission.length].max + max_len.hardlink = [max_len.hardlink, v.hardlink.length].max + max_len.owner = [max_len.owner, v.owner.length].max + max_len.group = [max_len.group, v.group.length].max + max_len.filesize = [max_len.filesize, v.filesize.to_s.length].max + max_len.timestamp = [max_len.timestamp, v.timestamp.length].max + 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 diff --git a/08.ls_object/ls.rb b/08.ls_object/ls.rb new file mode 100755 index 0000000000..6315c21483 --- /dev/null +++ b/08.ls_object/ls.rb @@ -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) diff --git a/08.ls_object/ls_command.rb b/08.ls_object/ls_command.rb new file mode 100644 index 0000000000..5100ad35b2 --- /dev/null +++ b/08.ls_object/ls_command.rb @@ -0,0 +1,26 @@ +# 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 = + if options.list_mode + ListView.new(file_names) + else + ColumnView.new(file_names) + end + view.render + end + + def target_files(options) + flag = 0 + flag = File::FNM_DOTMATCH if options.include_dotfiles + + Dir.glob('*', flag) + end +end diff --git a/08.ls_object/option.rb b/08.ls_object/option.rb new file mode 100644 index 0000000000..eda910f68f --- /dev/null +++ b/08.ls_object/option.rb @@ -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 From 21e24a9428f09c1fe70e0f7d744c3b63d7509b7a Mon Sep 17 00:00:00 2001 From: shibainurou Date: Wed, 7 May 2025 22:01:57 +0900 Subject: [PATCH 2/7] =?UTF-8?q?List=E3=81=A8ColumnView=E3=81=AE=E5=88=86?= =?UTF-8?q?=E5=B2=90=E3=81=AF=E3=82=AF=E3=83=A9=E3=82=B9=E5=90=8D=E3=81=A7?= =?UTF-8?q?=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/ls_command.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/08.ls_object/ls_command.rb b/08.ls_object/ls_command.rb index 5100ad35b2..29217f805a 100644 --- a/08.ls_object/ls_command.rb +++ b/08.ls_object/ls_command.rb @@ -8,12 +8,8 @@ def run(options) file_names = target_files(options) file_names.reverse! if options.reverse_order - view = - if options.list_mode - ListView.new(file_names) - else - ColumnView.new(file_names) - end + klass = options.list_mode ? ListView : ColumnView + view = klass.new(file_names) view.render end From 7c5735f794e60a4d201745ec683504e313a6bdcc Mon Sep 17 00:00:00 2001 From: shibainurou Date: Wed, 7 May 2025 22:07:45 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E7=9C=81=E7=95=A5=E3=81=97=E3=81=99?= =?UTF-8?q?=E3=81=8E=E3=81=9F=E5=A4=89=E6=95=B0=E5=90=8D=E3=82=92=E5=85=83?= =?UTF-8?q?=E3=81=AB=E6=88=BB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/object_ls.rb | 155 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100755 08.ls_object/object_ls.rb diff --git a/08.ls_object/object_ls.rb b/08.ls_object/object_ls.rb new file mode 100755 index 0000000000..b71ef88838 --- /dev/null +++ b/08.ls_object/object_ls.rb @@ -0,0 +1,155 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'etc' + +Struct.new('Display', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp, :blocks) +Struct.new('MaxLenght', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp) + +def colmuns_information(file_list) + list = [] + max_len = 0 + file_list.each do |v| + list.push(Struct::Display.new(v)) + max_len = [max_len, v.length].max + end + [list, max_len] +end + +def list_information(file_list, file_type_str, permission_str) + file_list.map do |file_name| + stat = File.lstat(file_name) + display = Struct::Display.new(file_name) + display.filename = file_name + display.type = file_type_str[stat.ftype] + display.permission = print_permission(stat.mode, permission_str) + display.hardlink = stat.nlink.to_s + display.owner = Etc.getpwuid(stat.uid).name + display.group = Etc.getgrgid(stat.gid).name + display.filesize = stat.size + display.timestamp = stat.mtime.strftime('%_m %_d %H:%M') + display.blocks = stat.blocks + display + end +end + +def max_lenght(list) + max = Struct::MaxLenght.new(0, 0, 0, 0, 0, 0, 0, 0) + list.each do |v| + max.filename = [max.filename, v.filename.length].max + max.type = [max.type, v.type.length].max + max.permission = [max.permission, v.permission.length].max + max.hardlink = [max.hardlink, v.hardlink.length].max + max.owner = [max.owner, v.owner.length].max + max.group = [max.group, v.group.length].max + max.filesize = [max.filesize, v.filesize.to_s.length].max + max.timestamp = [max.timestamp, v.timestamp.length].max + end + max +end + +def display_rows(list, columns) + (list.size.to_r / columns.to_r).to_f.ceil +end + +def target_files(show_dotfile_flag) + flag = 0 + flag = File::FNM_DOTMATCH if show_dotfile_flag + + Dir.glob('*', flag) +end + + +def print_file_info(file, max_len) + print file.type.rjust(max_len.type) + print "#{file.permission.rjust(max_len.permission)} " + print "#{file.hardlink.rjust(max_len.hardlink)} " + print "#{file.owner.ljust(max_len.owner)} " + print "#{file.group.ljust(max_len.group)} " + print "#{file.filesize.to_s.rjust(max_len.filesize)} " + print "#{file.timestamp.rjust(max_len.timestamp)} " + print file.filename + print " -> #{File.readlink(file.filename)}" if file.type == 'l' +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 + +def show_list(file_list, max_len) + puts "total #{file_list.map(&:blocks).sum}" + + file_list.each do |v| + print_file_info(v, max_len) + print "\n" + end +end + +def show_columns(file_list, max_len) + column_count = 3 + rows_num = display_rows(file_list, column_count) + + rows_num.times do |row| + print_index = row + column_count.times do + break if print_index > file_list.size + + file = file_list[print_index] + print file.filename.ljust(max_len).concat("\t") unless file.nil? + print_index += rows_num + end + print "\n" + end +end + +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 + +class OptionParser + attr_reader :show_dotfile_flag, :reverse_flag, :list_flag + + def initialize(argv) + show_dotfile_flag, reverse_flag, list_flag = option(argv) + end + + def option(argv) + %w[a r l].map do |opt| + ARGV.any? { |v| v.start_with?('-') && v.include?(opt) } + end + end +end + +option = OptionParser.new(ARGV) + +files = target_files(option.show_dotfile_flag) +files.reverse! if option.reverse_flag + +if option.list_flag + file_list = list_information(files, file_type_str, permission_str) + show_list(file_list, max_lenght(file_list)) +else + file_list, max_len = colmuns_information(files) + show_columns(file_list, max_len) +end + +option = OptionParser.new(ARGV) +x = xxx(option) +x.show From 63ad7f4e3b3a6f614cdf34b453e5ed33a45541dd Mon Sep 17 00:00:00 2001 From: shibainurou Date: Sun, 25 May 2025 22:37:52 +0900 Subject: [PATCH 4/7] =?UTF-8?q?display=E3=81=A8max=5Flen=E3=82=92Struct?= =?UTF-8?q?=E3=81=8B=E3=82=89=E9=85=8D=E5=88=97=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=20=E6=96=87=E5=AD=97=E5=88=97=E3=81=AE=E6=9C=80=E5=A4=A7?= =?UTF-8?q?=E9=95=B7=E3=81=AE=E5=8F=96=E5=BE=97=E3=82=92=E3=82=A4=E3=83=86?= =?UTF-8?q?=E3=83=AC=E3=83=BC=E3=82=BF=E3=82=92=E4=BD=BF=E3=81=A3=E3=81=A6?= =?UTF-8?q?=E5=8F=96=E5=BE=97=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E3=81=99=E3=82=8B=E3=81=9F=E3=82=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/base_view.rb | 4 +-- 08.ls_object/list_view.rb | 75 +++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/08.ls_object/base_view.rb b/08.ls_object/base_view.rb index e187c3a4b3..2caa9fb542 100644 --- a/08.ls_object/base_view.rb +++ b/08.ls_object/base_view.rb @@ -3,8 +3,8 @@ class BaseView def initialize(file_names) @file_names = file_names - @file_infos = file_names.map do |filename| - File.lstat(filename) + @file_infos = file_names.map do |file_name| + File.lstat(file_name) end end diff --git a/08.ls_object/list_view.rb b/08.ls_object/list_view.rb index 170d94d15c..0199e96f92 100644 --- a/08.ls_object/list_view.rb +++ b/08.ls_object/list_view.rb @@ -4,8 +4,19 @@ require_relative 'base_view' class ListView < BaseView - Struct.new('Display', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp, :blocks) - Struct.new('MaxLenght', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp) + LEN_INDEX_MAX = 8 + + module DisplayIndex + FILE_NAME = 0 + TYPE = 1 + PERMISSION = 2 + HARD_LINK = 3 + OWNER = 4 + GROUP = 5 + FILE_SIZE = 6 + TIMESTAMP = 7 + BLOCKS = 8 + end FILE_TYPE_STR = { 'file' => '-', @@ -28,50 +39,44 @@ class ListView < BaseView def render display_file_infos = display_file_info row_max_len = row_max_lenght(display_file_infos) - - puts "total #{display_file_infos.map(&:blocks).sum}" + puts "total #{display_file_infos.map { |v| v[DisplayIndex::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.hardlink.rjust(row_max_len.hardlink)} " - print "#{file.owner.ljust(row_max_len.owner)} " - print "#{file.group.ljust(row_max_len.group)} " - print "#{file.filesize.to_s.rjust(row_max_len.filesize)} " - print "#{file.timestamp.rjust(row_max_len.timestamp)} " - print file.filename - print " -> #{File.readlink(file.filename)}" if file.type == 'l' + print file[DisplayIndex::TYPE].rjust(row_max_len[DisplayIndex::TYPE]) + print "#{file[DisplayIndex::PERMISSION].rjust(row_max_len[DisplayIndex::TYPE])} " + print "#{file[DisplayIndex::HARD_LINK].rjust(row_max_len[DisplayIndex::HARD_LINK])} " + print "#{file[DisplayIndex::OWNER].ljust(row_max_len[DisplayIndex::OWNER])} " + print "#{file[DisplayIndex::GROUP].ljust(row_max_len[DisplayIndex::GROUP])} " + print "#{file[DisplayIndex::FILE_SIZE].to_s.rjust(row_max_len[DisplayIndex::FILE_SIZE])} " + print "#{file[DisplayIndex::TIMESTAMP].rjust(row_max_len[DisplayIndex::TIMESTAMP])} " + print "#{file[DisplayIndex::FILE_NAME]} " + print " -> #{File.readlink(file[DisplayIndex::FILE_NAME])}" if file[DisplayIndex::TYPE] == 'l' print "\n" end end def display_file_info - @file_names.map do |f| - d = Struct::Display.new(f) - stat = File.lstat(f) - d.filename = f - d.type = FILE_TYPE_STR[stat.ftype] - d.permission = print_permission(stat.mode, PERMISSION_STR) - d.hardlink = stat.nlink.to_s - d.owner = Etc.getpwuid(stat.uid).name - d.group = Etc.getgrgid(stat.gid).name - d.filesize = stat.size - d.timestamp = stat.mtime.strftime('%_m %_d %H:%M') - d.blocks = stat.blocks - d + @file_names.map do |file_name| + display = [] + stat = File.lstat(file_name) + display[DisplayIndex::FILE_NAME] = file_name + display[DisplayIndex::TYPE] = FILE_TYPE_STR[stat.ftype] + display[DisplayIndex::PERMISSION] = print_permission(stat.mode, PERMISSION_STR) + display[DisplayIndex::HARD_LINK] = stat.nlink.to_s + display[DisplayIndex::OWNER] = Etc.getpwuid(stat.uid).name + display[DisplayIndex::GROUP] = Etc.getgrgid(stat.gid).name + display[DisplayIndex::FILE_SIZE] = stat.size + display[DisplayIndex::TIMESTAMP] = stat.mtime.strftime('%_m %_d %H:%M') + display[DisplayIndex::BLOCKS] = stat.blocks + display end end def row_max_lenght(display_file_infos) - max_len = Struct::MaxLenght.new(0, 0, 0, 0, 0, 0, 0, 0) + max_len = [] display_file_infos.each do |v| - max_len.filename = [max_len.filename, v.filename.length].max - max_len.type = [max_len.type, v.type.length].max - max_len.permission = [max_len.permission, v.permission.length].max - max_len.hardlink = [max_len.hardlink, v.hardlink.length].max - max_len.owner = [max_len.owner, v.owner.length].max - max_len.group = [max_len.group, v.group.length].max - max_len.filesize = [max_len.filesize, v.filesize.to_s.length].max - max_len.timestamp = [max_len.timestamp, v.timestamp.length].max + LEN_INDEX_MAX.times do |index| + max_len[index] = [max_len[index].to_i, v[index].to_s.length].max + end end max_len end From 31842f146a4f8e660b2795885e15139c58c283de Mon Sep 17 00:00:00 2001 From: shibainurou Date: Mon, 26 May 2025 07:25:32 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=82=AB=E3=83=A9?= =?UTF-8?q?=E3=83=A0=E6=95=B0=E3=82=92ColumnView.new=E3=81=AE=E5=BC=95?= =?UTF-8?q?=E6=95=B0=E3=81=AB=E6=8C=81=E3=81=9F=E3=81=9B=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/column_view.rb | 9 ++++++--- 08.ls_object/ls_command.rb | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/08.ls_object/column_view.rb b/08.ls_object/column_view.rb index 7c6397f3eb..32673699f6 100644 --- a/08.ls_object/column_view.rb +++ b/08.ls_object/column_view.rb @@ -3,14 +3,17 @@ require_relative 'base_view' class ColumnView < BaseView - COLUMNS = 3 + 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 + @columns.times do break if row_index > @file_names.size file = @file_names[row_index] @@ -22,6 +25,6 @@ def render end def display_rows(list) - (list.size.to_r / COLUMNS.to_r).to_f.ceil + (list.size.to_r / @columns.to_r).to_f.ceil end end diff --git a/08.ls_object/ls_command.rb b/08.ls_object/ls_command.rb index 29217f805a..13bb19c132 100644 --- a/08.ls_object/ls_command.rb +++ b/08.ls_object/ls_command.rb @@ -8,8 +8,7 @@ def run(options) file_names = target_files(options) file_names.reverse! if options.reverse_order - klass = options.list_mode ? ListView : ColumnView - view = klass.new(file_names) + view = options.list_mode ? ListView.new(file_names) : ColumnView.new(file_names, 3) view.render end From 79e789ec5516e0dd75caacc5dc24e9c7ec90b3d4 Mon Sep 17 00:00:00 2001 From: shibainurou Date: Wed, 28 May 2025 07:12:49 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/object_ls.rb | 155 -------------------------------------- 1 file changed, 155 deletions(-) delete mode 100755 08.ls_object/object_ls.rb diff --git a/08.ls_object/object_ls.rb b/08.ls_object/object_ls.rb deleted file mode 100755 index b71ef88838..0000000000 --- a/08.ls_object/object_ls.rb +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -require 'etc' - -Struct.new('Display', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp, :blocks) -Struct.new('MaxLenght', :filename, :type, :permission, :hardlink, :owner, :group, :filesize, :timestamp) - -def colmuns_information(file_list) - list = [] - max_len = 0 - file_list.each do |v| - list.push(Struct::Display.new(v)) - max_len = [max_len, v.length].max - end - [list, max_len] -end - -def list_information(file_list, file_type_str, permission_str) - file_list.map do |file_name| - stat = File.lstat(file_name) - display = Struct::Display.new(file_name) - display.filename = file_name - display.type = file_type_str[stat.ftype] - display.permission = print_permission(stat.mode, permission_str) - display.hardlink = stat.nlink.to_s - display.owner = Etc.getpwuid(stat.uid).name - display.group = Etc.getgrgid(stat.gid).name - display.filesize = stat.size - display.timestamp = stat.mtime.strftime('%_m %_d %H:%M') - display.blocks = stat.blocks - display - end -end - -def max_lenght(list) - max = Struct::MaxLenght.new(0, 0, 0, 0, 0, 0, 0, 0) - list.each do |v| - max.filename = [max.filename, v.filename.length].max - max.type = [max.type, v.type.length].max - max.permission = [max.permission, v.permission.length].max - max.hardlink = [max.hardlink, v.hardlink.length].max - max.owner = [max.owner, v.owner.length].max - max.group = [max.group, v.group.length].max - max.filesize = [max.filesize, v.filesize.to_s.length].max - max.timestamp = [max.timestamp, v.timestamp.length].max - end - max -end - -def display_rows(list, columns) - (list.size.to_r / columns.to_r).to_f.ceil -end - -def target_files(show_dotfile_flag) - flag = 0 - flag = File::FNM_DOTMATCH if show_dotfile_flag - - Dir.glob('*', flag) -end - - -def print_file_info(file, max_len) - print file.type.rjust(max_len.type) - print "#{file.permission.rjust(max_len.permission)} " - print "#{file.hardlink.rjust(max_len.hardlink)} " - print "#{file.owner.ljust(max_len.owner)} " - print "#{file.group.ljust(max_len.group)} " - print "#{file.filesize.to_s.rjust(max_len.filesize)} " - print "#{file.timestamp.rjust(max_len.timestamp)} " - print file.filename - print " -> #{File.readlink(file.filename)}" if file.type == 'l' -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 - -def show_list(file_list, max_len) - puts "total #{file_list.map(&:blocks).sum}" - - file_list.each do |v| - print_file_info(v, max_len) - print "\n" - end -end - -def show_columns(file_list, max_len) - column_count = 3 - rows_num = display_rows(file_list, column_count) - - rows_num.times do |row| - print_index = row - column_count.times do - break if print_index > file_list.size - - file = file_list[print_index] - print file.filename.ljust(max_len).concat("\t") unless file.nil? - print_index += rows_num - end - print "\n" - end -end - -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 - -class OptionParser - attr_reader :show_dotfile_flag, :reverse_flag, :list_flag - - def initialize(argv) - show_dotfile_flag, reverse_flag, list_flag = option(argv) - end - - def option(argv) - %w[a r l].map do |opt| - ARGV.any? { |v| v.start_with?('-') && v.include?(opt) } - end - end -end - -option = OptionParser.new(ARGV) - -files = target_files(option.show_dotfile_flag) -files.reverse! if option.reverse_flag - -if option.list_flag - file_list = list_information(files, file_type_str, permission_str) - show_list(file_list, max_lenght(file_list)) -else - file_list, max_len = colmuns_information(files) - show_columns(file_list, max_len) -end - -option = OptionParser.new(ARGV) -x = xxx(option) -x.show From 9efc55efe8dd76ded02e328e84fee2976016337a Mon Sep 17 00:00:00 2001 From: shibainurou Date: Thu, 29 May 2025 07:02:30 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=E3=83=87=E3=83=BC=E3=82=BF=E5=9E=8B?= =?UTF-8?q?=E3=82=92=E9=85=8D=E5=88=97=E3=81=8B=E3=82=89hash=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08.ls_object/list_view.rb | 63 ++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/08.ls_object/list_view.rb b/08.ls_object/list_view.rb index 0199e96f92..42995b0ab6 100644 --- a/08.ls_object/list_view.rb +++ b/08.ls_object/list_view.rb @@ -4,20 +4,6 @@ require_relative 'base_view' class ListView < BaseView - LEN_INDEX_MAX = 8 - - module DisplayIndex - FILE_NAME = 0 - TYPE = 1 - PERMISSION = 2 - HARD_LINK = 3 - OWNER = 4 - GROUP = 5 - FILE_SIZE = 6 - TIMESTAMP = 7 - BLOCKS = 8 - end - FILE_TYPE_STR = { 'file' => '-', 'blockSpecial' => 'b', @@ -39,43 +25,44 @@ module DisplayIndex 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[DisplayIndex::BLOCKS] }.sum}" + puts "total #{display_file_infos.map { |v| v[:blocks] }.sum}" display_file_infos.each do |file| - print file[DisplayIndex::TYPE].rjust(row_max_len[DisplayIndex::TYPE]) - print "#{file[DisplayIndex::PERMISSION].rjust(row_max_len[DisplayIndex::TYPE])} " - print "#{file[DisplayIndex::HARD_LINK].rjust(row_max_len[DisplayIndex::HARD_LINK])} " - print "#{file[DisplayIndex::OWNER].ljust(row_max_len[DisplayIndex::OWNER])} " - print "#{file[DisplayIndex::GROUP].ljust(row_max_len[DisplayIndex::GROUP])} " - print "#{file[DisplayIndex::FILE_SIZE].to_s.rjust(row_max_len[DisplayIndex::FILE_SIZE])} " - print "#{file[DisplayIndex::TIMESTAMP].rjust(row_max_len[DisplayIndex::TIMESTAMP])} " - print "#{file[DisplayIndex::FILE_NAME]} " - print " -> #{File.readlink(file[DisplayIndex::FILE_NAME])}" if file[DisplayIndex::TYPE] == 'l' + 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| - display = [] stat = File.lstat(file_name) - display[DisplayIndex::FILE_NAME] = file_name - display[DisplayIndex::TYPE] = FILE_TYPE_STR[stat.ftype] - display[DisplayIndex::PERMISSION] = print_permission(stat.mode, PERMISSION_STR) - display[DisplayIndex::HARD_LINK] = stat.nlink.to_s - display[DisplayIndex::OWNER] = Etc.getpwuid(stat.uid).name - display[DisplayIndex::GROUP] = Etc.getgrgid(stat.gid).name - display[DisplayIndex::FILE_SIZE] = stat.size - display[DisplayIndex::TIMESTAMP] = stat.mtime.strftime('%_m %_d %H:%M') - display[DisplayIndex::BLOCKS] = stat.blocks + 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 = [] - display_file_infos.each do |v| - LEN_INDEX_MAX.times do |index| - max_len[index] = [max_len[index].to_i, v[index].to_s.length].max + 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