Skip to content

Instantly share code, notes, and snippets.

@yoshikouki
Last active June 24, 2020 06:11
Show Gist options
  • Save yoshikouki/a44477f32a84a45f158e3802e80d88df to your computer and use it in GitHub Desktop.
Save yoshikouki/a44477f32a84a45f158e3802e80d88df to your computer and use it in GitHub Desktop.
calコマンドをrubyで実装して、中央寄せ表示するだけのスクリプトです。
# frozen_string_literal: true
require 'optparse'
require 'date'
require 'curses'
# 表示する年月を取得
# 戻り値 { :year, :month }
def get_date
# コマンド引数を Hash で取得
params = ARGV.getopts('y:m:c')
# cオプションを保存
@puts_center = params['c']
# 引数の有無により、年月を初期設定
{ year: params['y'].nil? ? Date.today.year : params['y'].to_i,
month: params['m'].nil? ? Date.today.month : params['m'].to_i }
end
# 引数の年月から日付配列を作成
# 戻り値 [[Date, Date, ...], [Date, Date, ...], ...]
def create_month_days(date)
year = date[:year]
month = date[:month]
# 月末の Date オブジェクトを取得
end_of_month = Date.new(year, month, -1).day
# 当該月の日数配列を作成する
month_days = []
week_days = []
(1..end_of_month).map do |day|
date = Date.new(year, month, day)
week_days << date
if date.saturday? || end_of_month == day
month_days << week_days.dup
week_days.clear
end
end
month_days
end
# 引数をカレンダーに整形後、表示するstrを配列に入れて返す
# 戻り値 [String, String, ...]
def generate_calender(date, month_days)
year = date[:year]
month = date[:month]
# 表示文字列の配列を作成
str_array = ["#{month}月 #{year}".center(CALENDER_WIDTH),
'日 月 火 水 木 金 土']
# 日付テーブルを配列で作成(各行はString)
days_table = month_days.map do |week_days|
week_row = ''
week_days.each { |date| week_row += sprintf('%2d', date.day) + ' ' }
week_row
end
# 日付テーブルの第一週にインデントを追加
days_table[0].insert(0, ' ' * month_days[0][0].wday) unless month_days[0][0].wday == 0
str_array.push *days_table
end
def using_curses(calender)
cu = Curses
# 画面初期化
cu.init_screen
# 表示位置を設定
position_y = (Curses.lines - calender.size) / 2
position_x = (Curses.cols - CALENDER_WIDTH) / 2
begin
# 表示文字列を処理
calender.each do |str|
cu.setpos position_y, position_x
cu.addstr str
position_y += 1
end
# 画面を更新
cu.refresh
# 処理を一時停止
cu.getch
ensure
# 画面削除
cu.close_screen
end
end
def using_kernel(calender)
calender.each { |str| puts str }
end
def puts_calender(calender)
@puts_center ? using_curses(calender) : using_kernel(calender)
end
CALENDER_WIDTH = 20
# 処理実行
date = get_date
month_days = create_month_days(date)
calender = generate_calender(date, month_days)
puts_calender(calender)
@udzura
Copy link

udzura commented Jun 24, 2020

あ、あと、ほとんどるりまぐらいしか情報がない Curses をちゃんと使えているのは素直に素晴らしいです。

@udzura
Copy link

udzura commented Jun 24, 2020

あああもう一点あって、よしコーさんがコメントされているような内容は、YARDというRubyのコメントフォーマットで記述したほうが何かといいかもしれません。
https://rubydoc.info/gems/yard/file/docs/GettingStarted.md

コアライブラリだとRDocの場合もあるかも。
https://docs.ruby-lang.org/ja/latest/library/rdoc.html

まずはYARD覚えてみてください。こんな感じになるかな。

# 引数をカレンダー向けに整形後、表示するstrを配列に入れて返す
#
# @param date [Hash] 日付情報のハッシュ。 :year :month のキー必須
# @return [Array<String>] 行ごとの表示文字列
def create_month_days(date)
  ...
end

@yoshikouki
Copy link
Author

とても詳細なところまでありがとうございます

適性までお伝えいただけて凄く参考になります
今はまだ可能性があるくらいのものではありますが、オブジェクト指向、意識してみたいと思います!

前職でFile Makerを使っているときにDB設計が面白くて本を購入して読んだ(達人に学ぶDB設計徹底指南書)ことがあるのですが、
もしかしてそういうのも関係しているのでしょうか・・・
フィヨルド研修のカリキュラムにこの本が入っていたので感動しました

いただいた内容を精査し、コード修正します!
YARDやGistも(Gistはlsコマンドを修了してから)覚えたいと思います

お忙しいところ本当にありがとうございました!!!

@udzura
Copy link

udzura commented Jun 24, 2020

ああ、なるほどですね! > DB設計が面白くて

達人に学ぶDB設計徹底指南書は良書だと思います。私は楽々ERDレッスン(そっちも参考書にあるかな?)と応用情報処理でDB設計の修行をしました。
楽々ERDレッスンの著者の人が書かれているのが「はじめよう!要件定義」で、この本もペパボでは新卒研修で使っています。
設計が面白いというのはアプリケーションエンジニアの適性がありそうです!

研修まだまだ大変ですが、楽しんでいきましょう〜

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment