Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3e9e24a
とりあえず-aオプション、-rオプションを渡して正常に動作したので、クラスに分割
Miya096jp Dec 16, 2024
4d0ace7
ベタ打ちでlオプションに対応し、クラスに分割
Miya096jp Dec 17, 2024
1b19a84
Entryクラスから、各メタデータの出力フォーマットに関する処理をLsLongクラスに移動
Miya096jp Dec 17, 2024
1593e41
特殊権限の表示に対応
Miya096jp Dec 18, 2024
c275ef2
コマンドに直接ディレクトリを渡す処理を削除(修了要件になかったため)
Miya096jp Dec 19, 2024
6153cb3
クラスごとにファイルを分割し動作確認
Miya096jp Dec 19, 2024
60bbae7
Lsクラスのself.runメソッド内の複数の処理をメソッドに分割/Optionsクラスの引数としてARGVを渡すように変更し依存を軽減
Miya096jp Dec 19, 2024
b771621
LsShortクラス, LsLongクラスのprintメソッドをparseメソッドに修正し、ターミナルに結果を出力する責任をls.rbのト…
Miya096jp Dec 19, 2024
33423f0
Lsクラスのrunメソッドに対してユニットテストを作成
Miya096jp Dec 19, 2024
9c3fe89
LsLongクラスのformat_typeメソッドを修正/test_ls.rbの各ユニットテストのHEARドキュメントのデータを修正しテス…
Miya096jp Dec 19, 2024
932b7c4
LsLongクラスのformat_modeメソッドのロジックを修正
Miya096jp Dec 20, 2024
1e61dff
test_ls.rbの-lオプション、-arlオプションのヒアドキュメントに渡すデータを修正, テスト成功
Miya096jp Dec 20, 2024
ba13f48
LsLongクラスのformat_modeを再度修正し、それに伴いEntryクラスのuser, group, othersメソッドを削除
Miya096jp Dec 20, 2024
3d5be9b
ls.rbの定数FILETYPEをls_long.rbのLsLongクラスに移動
Miya096jp Dec 27, 2024
3524152
ls_short.rbのLsShortクラスをShortFormatterに、ls_long.rbのLsLongクラスをLongForma…
Miya096jp Dec 27, 2024
ac9342a
EntryクラスをFileMetadataクラスに変更し、ファイル名をfile_metadate.rbに変更
Miya096jp Dec 27, 2024
227ebc3
FileMetadataクラスへのクラス名変更に伴い、ls.rbのparse_entriesメソッドをbuild_file_metadat…
Miya096jp Dec 27, 2024
78f4377
ShortFormatterクラスのインスタンス変数を@entriesから@file_metadata_listに変更/count_row…
Miya096jp Dec 27, 2024
297004b
LongFormatterクラスのインスタンス変数を@entriesから@file_metadata_listに変更。それに伴い各メソッド…
Miya096jp Dec 27, 2024
a51fe51
ShortFormatterクラスとLongFormatterクラスのparseメソッドをformatメソッドに変更し、ls.rbの呼び出…
Miya096jp Dec 27, 2024
2096210
LongFormatterクラスとShortFormatterクラスのparseメソッドをformat_outputメソッドに名称変更
Miya096jp Dec 27, 2024
44049e6
定数REGULAR_MODE, SUID_SGID, STICKY_BITをLongFormatterクラスへ移動, 定数COLUMNをS…
Miya096jp Dec 27, 2024
b8ff95c
LongFormatterクラスのformat_modeメソッドにおける特殊権限設定のロジックを修正
Miya096jp Dec 29, 2024
3a05d94
Pathクラスの引数optionsを、dot_matchとreverseに分割しスタンプ結合を解消
Miya096jp Dec 29, 2024
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
68 changes: 68 additions & 0 deletions 07.ls_object/lib/file_metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# frozen_string_literal: true

require 'etc'

class FileMetadata
def initialize(path, stat)
@path = path
@stat = stat
end

def name
File.basename(@path)
end

def type
format_type(@stat)
end

def mode
format_mode(@stat)
end

def setuid?
@stat.setuid?
end

def setgid?
@stat.setgid?
end

def sticky?
@stat.sticky?
end

def nlink
@stat.nlink
end

def username
Etc.getpwuid(@stat.uid).name
end

def groupname
Etc.getgrgid(@stat.gid).name
end

def bytesize
@stat.size
end

def mtime
@stat.mtime
end

def blocks
@stat.blocks
end

private

def format_type(stat)
stat.mode.to_s(8)[..-5]
end

def format_mode(stat)
stat.mode.to_s(8)[-3..]
end
end
103 changes: 103 additions & 0 deletions 07.ls_object/lib/formatter/long_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# frozen_string_literal: true

class LongFormatter
def initialize(file_metadata_list)
@file_metadata_list = file_metadata_list
end

FILETYPE = {
'1' => 'p',
'2' => 'c',
'4' => 'd',
'6' => 'b',
'10' => '-',
'12' => 'l',
'14' => 's'
}.freeze

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

SUID_SGID = {
'0' => '---',
'1' => '--s',
'2' => '-wS',
'3' => '-ws',
'4' => 'r-S',
'5' => 'r-s',
'6' => 'rwS',
'7' => 'rws'
}.freeze

STICKY_BIT = {
'0' => '---',
'1' => '--t',
'2' => '-wT',
'3' => '-wt',
'4' => 'r-T',
'5' => 'r-t',
'6' => 'rwT',
'7' => 'rwt'
}.freeze

private_constant :FILETYPE, :REGULAR_MODE, :SUID_SGID, :STICKY_BIT

def format_output
max_size = build_max_size
"#{build_total_row}\n#{build_body(max_size)}\n"
end

private

def build_max_size
{
nlink: @file_metadata_list.map { |file_metadata| file_metadata.nlink.to_s.size }.max,
username: @file_metadata_list.map { |file_metadata| file_metadata.username.size }.max,
groupname: @file_metadata_list.map { |file_metadata| file_metadata.groupname.size }.max,
bytesize: @file_metadata_list.map { |file_metadata| file_metadata.bytesize.to_s.size }.max
}
end

def build_total_row
total = @file_metadata_list.sum { |file_metadata| file_metadata.blocks.to_i }
"total: #{total}"
end

def build_body(max_size)
@file_metadata_list.map do |file_metadata|
[
"#{format_type(file_metadata)}#{format_mode(file_metadata)}",
file_metadata.nlink.to_s.rjust(max_size[:nlink] + 1),
file_metadata.username.rjust(max_size[:username] + 1),
file_metadata.groupname.rjust(max_size[:groupname] + 1),
file_metadata.bytesize.to_s.rjust(max_size[:bytesize] + 1),
" #{format_mtime(file_metadata.mtime)}",
" #{file_metadata.name}"
].join
end.join("\n")
end

def format_type(file_metadata)
FILETYPE[file_metadata.type]
end

def format_mode(file_metadata)
user, group, others = file_metadata.mode.split('')
user_permission = file_metadata.setuid? ? SUID_SGID : REGULAR_MODE
group_permission = file_metadata.setgid? ? SUID_SGID : REGULAR_MODE
others_permission = file_metadata.sticky? ? STICKY_BIT : REGULAR_MODE
[user_permission[user], group_permission[group], others_permission[others]].join
end

def format_mtime(mtime)
format('%<mon>2d %<mday>2d %<hour>2d:%<min>2d', mon: mtime.mon, mday: mtime.mday, hour: mtime.hour, min: mtime.min)
end
end
37 changes: 37 additions & 0 deletions 07.ls_object/lib/formatter/short_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

class ShortFormatter
def initialize(file_metadata_list)
@file_metadata_list = file_metadata_list
end

COLUMN = 3

private_constant :COLUMN

def format_output
entries = justfy_entries
row = count_row(entries)
sliced_entries = slice_entries(entries, row)
"#{transpose(sliced_entries).map { |entry| entry.join.rstrip }.join("\n")}\n"
end

private

def justfy_entries
max_length = @file_metadata_list.map { |file_metadata| file_metadata.name.size }.max
@file_metadata_list.map { |file_metadata| file_metadata.name.ljust(max_length + 1) }
end

def count_row(entries)
(entries.size.to_f / COLUMN).ceil
end

def slice_entries(entries, row)
entries.each_slice(row).to_a
end

def transpose(sliced_entries)
sliced_entries[0].zip(*sliced_entries[1..])
end
end
25 changes: 25 additions & 0 deletions 07.ls_object/lib/options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require 'optparse'

class Options
def initialize(arguments)
opts = OptionParser.new
opts.on('-l') { |v| @long_format = v }
opts.on('-r') { |v| @reverse = v }
opts.on('-a') { |v| @dot_match = v }
opts.parse!(arguments)
end

def long_format?
@long_format
end

def reverse?
@reverse
end

def dot_match?
@dot_match
end
end
25 changes: 25 additions & 0 deletions 07.ls_object/lib/paths.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require 'pathname'

class Paths
attr_reader :paths

def initialize(pathname, dot_match, reverse)
@pathname = pathname
@dot_match = dot_match
@reverse = reverse
@paths = collect_paths
end

private

def collect_paths
paths = @dot_match ? Dir.glob(@pathname, File::FNM_DOTMATCH).sort : Dir.glob(@pathname)
reverse(paths)
end

def reverse(paths)
@reverse ? paths.reverse : paths
end
end
43 changes: 43 additions & 0 deletions 07.ls_object/ls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env ruby

# frozen_string_literal: true

require_relative './lib/options'
require_relative './lib/file_metadata'
require_relative './lib/paths'
require_relative './lib/formatter/short_formatter'
require_relative './lib/formatter/long_formatter'
require 'pathname'

class Ls
def initialize(pathname, options)
@pathname = pathname
@options = options
end

def run
paths = collect_paths(@pathname, @options.dot_match?, @options.reverse?)
file_metadata_list = build_file_metadata_list(paths)
formatter = select_formatter(file_metadata_list, @options.long_format?)
formatter.format_output
end

private

def collect_paths(pathname, dot_match, reverse)
Paths.new(pathname, dot_match, reverse).paths
end

def build_file_metadata_list(paths)
paths.map { |path| FileMetadata.new(path, File::Stat.new(path)) }
end

def select_formatter(file_metadata_list, long_format)
long_format ? LongFormatter.new(file_metadata_list) : ShortFormatter.new(file_metadata_list)
end
end

pathname = Pathname('./*')
options = Options.new(ARGV)
ls = Ls.new(pathname, options)
puts ls.run
Empty file.
Empty file.
5 changes: 5 additions & 0 deletions 07.ls_object/test/fixtures/test_ls/file_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
るに馬の頭部の近辺に或ある異常な光の現象が起こるというふうに解釈される。
 次に注意すべきは、この怪異の起こる時の時間的分布である。すなわち「濃州のうしゅうでは四月から七月までで、別して五六月が多いという。七月になりかかると、秋風が立ち初める、とギバの難は影を隠してしまう。武州ぶしゅう常州じょうしゅうあたりでもやはり四月から七月と言っている」。また晴天には現われず「晴れては曇り曇っては晴れる、村雲などが出たりはいったりする日に限って」現われるとある。また一日じゅうの時刻については「朝五つ時前(午前八時)、夕七つ時過ぎ(午後四時)にはかけられない、多くは日盛りであるという」とある。
 またこの出現するのにおのずから場所が定まっている傾向があり、たとえば一里塚いちりづかのような所の例があげられている。
 もう一つ参考になるのは、馬をギバの難から救う方法として、これが襲いかかった時に、半纏はんてんでも風呂敷ふろしきでも莚むしろでも、そういうものを馬の首からかぶせるといいということがある。もちろん、その上に、尾の上の背骨に針を打ち込んだりするそうであるが、このようにものをかぶせる事が「針よりも大切なまじない」だと考えられている。またこれと共通な点のあるのは、平生のギバよけのまじないとして、馬に腹当てをさせるとよい、ただしそれは「大津東町上下仕合」と白く染めぬいたものを用いる。「このアブヨケをした馬がギバにかけられてたおれたのを見た事がないと、言われている」。
 別の説として美濃みのでは「ギバは白虻しろあぶのような、目にも見えない虫だという説がある、また常陸ひたちではその虫を大津虫と呼んでいる。虫は玉虫色をしていて
3 changes: 3 additions & 0 deletions 07.ls_object/test/fixtures/test_ls/file_2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
 これに反して、ギバがなんらかの空中放電によるものと考えると、たてがみが立ち上がったり、光の線条が見えたり、玉虫色の光が馬の首を包んだりする事が、全部生きた科学的記述としての意味をもって来る。また衣服その他で頭をおおい、また腹部を保護するという事は、つまり電気の半導体で馬の身体の一部を被覆して、放電による電流が直接にその局部の肉体に流れるのを防ぐという意味に解釈されて来るのである。
 またこういう放電現象が夏期に多い事、および日中に多い事は周知の事実であるので、前述の時間分布は、これときわめてよく符合する事になる。
 場所のおのずから定まる傾向については、自分は何事も具体的のことをいうだけの材料を持ち合わせないが、これも調べてみたら、おそらく放電現象の多い場所と符合するようなことがありはし
1 change: 1 addition & 0 deletions 07.ls_object/test/fixtures/test_ls/file_3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
 物理学の学徒としての自分は、日常普通に身辺に起こる自然現象に不思議を感ずる事は多いが、古来のいわゆる「怪異」なるものの存在を信ずることはできない。しかし昔からわれわれの祖先が多くの「怪異」に遭遇しそれを「目撃」して来たという人事的現象としての「事実」を否定するものではない。われわれの役目はただそれらの怪異現象の記録を現代科学上の語彙ごいを借りて翻訳するだけの事でなければならない。この仕事はしかしはなはだ困難なものである。錯覚や誇張さらに転訛てんかのレンズによってはなはだしくゆがめられた影像からその本体を言い当てなければならない。それを的確に成効しうるためにはそのレンズに関する方則を正確に知らなければならない、のみならず、またその個々の場合における決定条件として多様の因子を逐一に明らかにしなければならない。この前者の方則については心理学のほうから若干の根拠は供給されるとしても、後者に関する資料はほとんどすべての場合において永久に失われている。従ってほんとうに科学的な推定を下すということはほとんど望み難いことである。ただできうる唯一の方法としては、有るだけの材料から、科学的に合理的な一つの「可能性」を指摘するに過ぎない。もっともこの可能性が非常に多様であれば、その中の二三を指摘してみても、それは結局なんらの価値もない漫談となってしまうであろうが、多くの場合に必ずしもそうとは限らない。ことにある一種の怪異に関する記録が豊富にあればあるほど、この可能性の範囲はかなりまで押しせばめられる。従ってやや「もっともらしい仮説」というまでには漕こぎつけられる見込みがあるのである。そこまで行けば、それはともかくも一つの仮説として存在する価値を認めなければならず、また実際科学者たちにある暗示を提供するだけの効果をもつ事も有りうるであろうと思われる。
5 changes: 5 additions & 0 deletions 07.ls_object/test/fixtures/test_ls/file_4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
 その怪異の第一は、自分の郷里高知こうち付近で知られている「孕はらみのジャン」と称するものである。孕は地名で、高知の海岸に並行する山脈が浦戸湾うらどわんに中断されたその両側の突端の地とその海峡とを込めた名前である。この現象については、最近に、土佐とさ郷土史きょうどしの権威として知られた杜山居士とざんこじ寺石正路てらいしまさみち氏が雑誌「土佐史壇」第十七号に「郷土史断片」その三〇として記載されたものがある。「(前略)昔はだいぶ評判の事であったが、このごろは全くその沙汰さたがない、根拠の無き話かと思えば、「土佐今昔物語」という書に、沼澄ぬまずみ(鹿持雅澄かもちまさずみ翁おう)の名をもって左のとおりしるされている。
孕の海にジャンと唱うる稀有けうのものありけり、たれしの人もいまだその形を見たるものなく、その物は夜半にジャーンと鳴り響きて海上を過ぎ行くなりけり、漁業をして世を渡るどちに、夜半に小舟浮かべて、あるは釣つりをたれ、あるいは網を打ちて幸さち多かるも、このも[#「も」に「原」の注記]海上を行き過ぐればたちまちに魚騒ぎ走りて、時を移すともその夜はまた幸さちなかりけり、高知ほとりの方言に、ものの破談になりたる事をジャンになりたりというも、この海上行き過ぐるものよりいでたることなん語り伝えたりとや。
 この文は鹿持翁の筆なればおおよそ小百年前のことにして孕はらみのジャンはこのほどの昔よりもすでにその伝があったことが知れる(後略)。」寺石氏はこのジャンの意味の転用に関する上記の説の誤謬ごびゅうを指摘している。また終わりに諏訪湖すわこの神渡りの音響の事を引き、孕のジャンは「何か微妙な地の震動に関したことではあるまいか」と述べておられる。
 私は幼時近所の老人からたびたびこれと同様な話を聞かされた。そしてもし記憶の誤りでなければ、このジャンの音響とともに「水面にさざ波が立つ」という事が上記の記載に付加されていた。
 この話を導き出しそうな音の原因に関する自分のはじめの考えは、もしや昆虫こんちゅうかあるいは鳥類の群れが飛び立つ音ではないかと思ってみたが、しかしそれは夜半の事だというし、また魚が釣つれなくなるという事が確実とすれば単に空中の音波のためとは考えにくいと思われた。ところが先年筑波山つくばさんの北側の柿岡かきおかの盆地へ行った時にかの地には珍しくない「地鳴り」の現象を数回体験した。その時に自分は全く神来的に「孕はらみのジャンはこれだ」と感じた。この地鳴りの音は考え方によってはやはりジャーンとも形容されうる種類の雑音であるし、またその地盤の性質、地表の形状や被覆物の種類によってはいっそうジャーンと聞こえやすくなるであろうと思われうるたちのものである。そして明らかに一方から一方へ「過ぎ行く」音で、それが空中ともなく地中ともなく過ぎ去って行くのは実際他に比較するもののない奇異の感じを起こさせるものである。ちょうど自分が観測室内にいた時に起こった地鳴りの際には、磁力計の頂上に付いている管が共鳴してその頭が少なくも数ミリほど振動するのを明らかに認める事ができたし、また山中で聞いた時は立っている靴くつの底に明らかにきわめて短週期の震動を感じた。これだけの振動があれば、適当な境界条件の下に水面のさざ波を起こしうるはずであるし、また水中の魚類の耳石等にもこれを感じなければならないわけである。もっとも、魚類がこの種の短週期弾性波に対してどう反応するかについて自分はあまりよく知らないが、これだけの振動に全然無感覚であろうとは想像し難い。
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Loading