Module: Tt

Defined in:
lib/tt.rb,
lib/tt/smrty.rb

Defined Under Namespace

Classes: Smrty

Constant Summary collapse

FORMAT =
"%Y-%m-%dT%H:%MZ"
SCREEN_FORMAT =
"%Y-%m-%d %H:%M"

Class Method Summary collapse

Class Method Details

.clearObject



129
130
131
# File 'lib/tt.rb', line 129

def self.clear
  tt_path.unlink
end

.csv_engineObject



8
9
10
11
12
13
14
15
16
# File 'lib/tt.rb', line 8

def self.csv_engine
  if RUBY_VERSION =~ /^1\.8/ then
    require "fastercsv"
    FasterCSV
  else
    require "csv"
    CSV
  end
end

.dropObject



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/tt.rb', line 116

def self.drop
  csv_engine.open(tt_path.to_s + ".new", "wb") do |io|
    lastrow = nil
    csv_engine.foreach(tt_path, "rb") do |row|
      io << lastrow if lastrow
      lastrow = row
    end
  end

  tt_path.unlink
  File.rename(tt_path.to_s + ".new", tt_path)
end

.each_lineObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/tt.rb', line 59

def self.each_line
  tt_dir.mkdir unless tt_dir.directory?
  line, state, dir, intime, outtime, comment = 0, :out, nil, nil, nil, nil

  csv_engine.foreach(tt_path) do |row|
    line += 1

    case row[0]
    when "in"
      case state
      when :out # punch in
        dir = row[1]
        intime = Time.parse(row[2])
        outtime = nil
        comment = row[3]
        state = :in
      when :in # switch task
        outtime = Time.parse(row[2])
        yield(dir, intime, outtime, [comment, row[3]].compact.join("; "))

        dir = row[1]
        intime = Time.parse(row[2])
        outtime = nil
        comment = nil
      else
        raise ArgumentError, "Unknown processing state: #{state}, expected one of in/out"
      end
    when "out"
      case state
      when :in # punch out
        outtime = Time.parse(row[2])
        yield(dir, intime, outtime, [comment, row[3]].compact.join("; "))

        dir, intime, outtime, comment = nil
        state = :out
      when :out
        $stderr.puts "WARNING: out when already out on line #{line}"
      else
        raise ArgumentError, "Unknown processing state: #{state}, expected one of in/out"
      end
    else
      raise SyntaxError, "Error on line \##{line} of #{tt_path}: unknown reference in column 0: #{row[0]}"
    end
  end if tt_path.file?

  case state
  when :in
    yield(dir, intime, nil, comment)
  end
end

.punch_in(cwd, comment = nil) ⇒ Object



30
31
32
33
34
35
# File 'lib/tt.rb', line 30

def self.punch_in(cwd, comment=nil)
  tt_dir.mkdir unless tt_dir.directory?
  csv_engine.open(tt_path, "ab") do |io|
    io << ["in", cwd, Time.now.utc.strftime(FORMAT), comment]
  end
end

.punch_out(cwd, comment = nil) ⇒ Object



37
38
39
40
41
42
# File 'lib/tt.rb', line 37

def self.punch_out(cwd, comment=nil)
  tt_dir.mkdir unless tt_dir.directory?
  csv_engine.open(tt_path, "ab") do |io|
    io << ["out", cwd, Time.now.utc.strftime(FORMAT), comment]
  end
end

.report(stream = STDOUT) ⇒ Object



110
111
112
113
114
# File 'lib/tt.rb', line 110

def self.report(stream=STDOUT)
  each_line do |dir, intime, outtime, comment|
    report_line(dir, intime, outtime, comment, stream)
  end
end

.report_line(dir, intime, outtime, comment, stream = STDOUT) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/tt.rb', line 44

def self.report_line(dir, intime, outtime, comment, stream=STDOUT)
  ltime = Time.now
  intime = intime + ltime.utc_offset
  endtime = (outtime.nil? ? Time.now.utc : outtime) + ltime.utc_offset
  outtime = outtime + ltime.utc_offset if outtime

  duration_in_seconds = endtime - intime
  duration_in_minutes = duration_in_seconds / 60
  duration_as_human_string = "%02d:%02d" % [duration_in_minutes / 60, duration_in_minutes % 60]

  stream.print "%-40s %16s %16s %5s" % [dir, intime.strftime(SCREEN_FORMAT), outtime ? outtime.strftime(SCREEN_FORMAT) : "", duration_as_human_string]
  stream.print " - %s" % comment if comment && !comment.empty?
  stream.puts
end

.rootObject



18
19
20
# File 'lib/tt.rb', line 18

def self.root
  @root ||= ENV["CLITT_ROOT"].to_s.empty? ? ENV["HOME"] : ENV["CLITT_ROOT"]
end

.tt_dirObject



22
23
24
# File 'lib/tt.rb', line 22

def self.tt_dir
  Pathname.new(root) + ".tt"
end

.tt_pathObject



26
27
28
# File 'lib/tt.rb', line 26

def self.tt_path
  tt_dir + "entries.csv"
end