Class: PunchClock

Inherits:
Object
  • Object
show all
Includes:
OptionParsing
Defined in:
lib/punch_clock.rb

Constant Summary collapse

VERSION_NAME =
"The Baddest Man on the Planet"
MIDNIGHT_MADNESS_NOTES =
[
  "Get some sleep!",
  "Don't you have any hobbies?",
  "Get some rest, (wo)man...",
  "You should go to bed.",
  "That can't be healthy.",
  "You might need therapy.",
  "All work and no play makes Jack a dull boy.",
  "You need to get your priorities straight.",
  "Work-life balance. Ever heard of it?",
  "Did you know that the average adult needs 7-8 hours of sleep?"
]
CARD_RGX =

Card names are a restricted form of identifiers.

/^(?!now)([a-z_][a-zA-Z0-9_]*)$/
OPTIONS =

For easy bash completion export.

%w(
--backup
--brf
--card-config
--cards
--clear-tags
--config
--config-reset
--config-update
--console
--coverage
--day
--diagram
--doc
--dry-run
--edit
--engine
--format
--full
--github
--hack
--help
--hours
--interactive
--log
--mail
--merge
--month
--next
--options
--previous
--raw
--remove
--review
--stats
--tag
--test
--travis
--trello
--undo
--update
--version
--whoami
--year
--yesterday

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from OptionParsing

#args, #args=, #flag, #switch

Constructor Details

#initialize(args) ⇒ PunchClock

Returns a new instance of PunchClock.


74
75
76
# File 'lib/punch_clock.rb', line 74

def initialize(args)
  self.args = args
end

Instance Attribute Details

#brf_filepathObject (readonly)

Returns the value of attribute brf_filepath


70
71
72
# File 'lib/punch_clock.rb', line 70

def brf_filepath
  @brf_filepath
end

#monthObject (readonly)

Returns the value of attribute month


70
71
72
# File 'lib/punch_clock.rb', line 70

def month
  @month
end

#month_nameObject (readonly)

Returns the value of attribute month_name


70
71
72
# File 'lib/punch_clock.rb', line 70

def month_name
  @month_name
end

#yearObject (readonly)

Returns the value of attribute year


70
71
72
# File 'lib/punch_clock.rb', line 70

def year
  @year
end

Instance Method Details

#configObject


410
411
412
# File 'lib/punch_clock.rb', line 410

def config
  Punch.config
end

#edit_brf(application = nil) ⇒ Object

Parameters:

  • application (String) (defaults to: nil)

    which application to open file with, e.g. “TextEdit”


416
417
418
419
# File 'lib/punch_clock.rb', line 416

def edit_brf(application = nil)
  open brf_filepath, application
  exit
end

#hand_in_dateObject


110
111
112
# File 'lib/punch_clock.rb', line 110

def hand_in_date
  config.hand_in_date
end

#help_fileObject


94
95
96
# File 'lib/punch_clock.rb', line 94

def help_file
  "#{punch_folder}/help.txt"
end

#hours_folderObject


82
83
84
# File 'lib/punch_clock.rb', line 82

def hours_folder
  @hours_folder ||= config.hours_folder
end

#last_releaseObject


90
91
92
# File 'lib/punch_clock.rb', line 90

def last_release
  @last_release ||= `cd #{punch_folder} && git log -1 --format=%cr HEAD`.chomp
end

421
422
423
424
# File 'lib/punch_clock.rb', line 421

def print_version
  puts "#{VERSION_NAME.highlighted} #{version.highlighted} "\
    "released #{last_release}"
end

#punchObject


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/punch_clock.rb', line 114

def punch
  # Load card if one is active.
  Punch.load_card config.active_card if config.active_card?

  # Load passed cards.
  while CARD_RGX =~ @args.first
    card = @args.shift
    Punch.load_card card
  end

  # Prepend default arguments.
  unless config.default_args.empty?
    @args.unshift(*config.default_args.split(' '))
  end

  switch "--dry-run" do
    dry_run!
  end

  switch "--options" do
    puts OPTIONS.join("\n")
    exit
  end

  switch "--cards" do
    puts config.cards.keys.join("\n")
    exit
  end

  switch '--card-config' do
    puts "  #{literal(config.cards)}"
    exit
  end

  switch '--hours', '--brf' do
    system "#{config.text_editor} #{hours_folder}"
    exit
  end

  switch "--hack" do
    system "cd #{punch_folder} && #{config.text_editor} #{PUNCH_FILE}"
    exit
  end

  switch "-h", "--help" do
    generate_and_open_help_file
    exit
  end

  switch "--doc" do
    system "cd #{punch_folder} && yard && open doc/index.html"
    exit
  end

  switch "--diagram" do
    generate_and_open_dependency_diagram
    exit
  end

  switch "-u", "--update" do
    update_punch
    exit
  end

  switch "--test" do
    system "#{config.system_ruby} #{test_file}"
    exit
  end

  switch "--coverage" do
    generate_and_open_coverage
    exit
  end

  switch "-v", "--version" do
    print_version
    exit
  end

  switch "--engine" do
    puts "#{RUBY_ENGINE} #{RUBY_VERSION}"
    exit
  end

  flag "-l", "--log" do |n|
    system "cd #{punch_folder} && #{log(n)}"
    exit
  end

  switch "--review" do
    system "cd #{punch_folder} && pronto run"
    exit
  end

  switch "--travis" do
    system "open https://travis-ci.org/rathrio/punch"
    exit
  end

  switch "--trello" do
    system "open https://trello.com/b/xfN8alsq/punch"
    exit
  end

  switch "--github" do
    system "open https://github.com/rathrio/punch"
    exit
  end

  switch "--whoami" do
    puts "You are the sunshine of my life, #{config.name}.".highlighted
    exit
  end

  switch "-c", "--config" do
    open_or_generate_config_file
    exit
  end

  switch "--config-reset" do
    if yes? "Are you sure you want to reset ~/.punchrc?"
      config.reset!
      generate_and_open_config_file
    end
    exit
  end

  switch "--config-update" do
    generate_and_open_config_file
    exit
  end

  switch "--full" do
    print_full_month!
  end

  month_year = MonthYear.new(:month => now.month, :year => now.year)
  month_year = month_year.next if now.day > hand_in_date

  switch "-n", "--next" do
    month_year = month_year.next
  end

  switch "-p", "--previous" do
    month_year = month_year.prev
  end

  flag "--month" do |month|
    month_year = MonthYear.new(:month => month, :year => month_year.year)
  end

  flag "--year" do |year|
    month_year = MonthYear.new(:month => month_year.month, :year => year)
  end

  @month_name = Month.name month_year.month

  switch "-m", "--merge" do
    puts Merger.new(@args, month_year).month
    exit
  end

  @brf_filepath = generate_brf_filepath month_name, month_year.year

  switch "-b", "--backup" do
    path = @args.shift
    system "cp #{brf_filepath} #{path}"
    exit
  end

  flag "-e", "--edit" do |application|
    edit_brf application
  end

  switch "--raw" do
    puts raw_brf
    exit
  end

  switch "--mail" do
    mailer = BRFMailer.new(brf_filepath, month_name)
    # Print non-encoded version for confirmation.
    puts mailer.message false
    mailer.deliver if yes?("Do you want to send this mail?".highlighted)
    exit
  end

  File.open brf_filepath, 'r+' do |file|
    @month = Month.from(file.read, month_year.month, month_year.year)

    switch "--undo" do
      exit
    end

    switch "-f", "--format" do
      puts "Before formatting:\n".highlighted
      puts raw_brf
      @month.cleanup! :remove_ongoing_blocks => true
      write! file
      puts "\nAfter formatting:\n".highlighted
      puts raw_brf
      exit
    end

    switch "--console" do
      require 'pry'
      binding.pry
      exit
    end

    switch "-i", "--interactive" do
      Editor.new(@month).run
      write! file
    end

    switch "-s", "--stats" do
      puts Stats.new(month)
      exit
    end

    unless @args.empty?
      day = nil

      # The --day flag might set a day to edit.
      flag "-d", "--day" do |date|
        day = month.find_or_create_day_by_date(date)
      end

      # If not, auto-determine which day to edit.
      if day.nil?
        time_to_edit = now
        switch "-y", "--yesterday" do
          time_to_edit = now.prev_day
        end
        unless (day = month.days.find { |d| d.at? time_to_edit })
          # Create that day if it doesn't exist yet.
          day = Day.new
          day.set time_to_edit
          month.add day
        end
      end

      flag "-t", "--tag" do |tag_str|
        day.extract_tags tag_str
      end

      switch "--clear-tags" do
        day.clear_tags
      end

      # Add or remove blocks.
      action = :add
      switch "-r", "--remove" do
        action = :remove
      end
      blocks = @args.map do |block_str|
        BlockParser.parse block_str, day
      end
      day.send action, *blocks

      # Cleanup in case we have empty days after a remove.
      month.cleanup! if action == :remove

      puts "#{MIDNIGHT_MADNESS_NOTES.sample.highlighted}\n" if day.unhealthy?

      write! file
    end

    # Print month with an empty current day if necessary.
    if month.days.none? { |d| d.at? now }
      today = Day.new
      today.set now
      month.add today
    end

    system "clear" if config.clear_buffer_before_punch?

    if print_full_month?
      puts month.full
    else
      puts month.fancy
    end
  end

rescue BRFParser::ParserError => e
  raise e if config.debug?
  puts "Couldn't parse #{brf_filepath.highlighted}."
rescue Interrupt
  puts "\nExiting...".highlighted
  exit
rescue => e
  raise e if config.debug?
  puts "That's not a valid argument, dummy.\n"\
    "Run #{"punch -h".highlighted} for help."
end

#punch_folderObject


78
79
80
# File 'lib/punch_clock.rb', line 78

def punch_folder
  @punch_folder ||= File.dirname(PUNCH_FILE)
end

#raw_brfObject


426
427
428
# File 'lib/punch_clock.rb', line 426

def raw_brf
  `cat #{brf_filepath}`
end

#test_fileObject


98
99
100
# File 'lib/punch_clock.rb', line 98

def test_file
  "#{punch_folder}/test/punch_test.rb"
end

#versionObject


86
87
88
# File 'lib/punch_clock.rb', line 86

def version
  @version ||= `cd #{punch_folder} && git rev-parse --short HEAD`.chomp
end

#write!(file) ⇒ Object


102
103
104
105
106
107
108
# File 'lib/punch_clock.rb', line 102

def write!(file)
  return 0 if dry_run?
  file.rewind
  file.truncate 0
  file.write month
  file.rewind
end