timeless 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.org +202 -0
- data/elisp/forms.el +2 -0
- data/lib/timeless/cli/command_semantics.rb +17 -27
- data/lib/timeless/cli/command_syntax.rb +36 -0
- data/lib/timeless/storage.rb +57 -42
- data/lib/timeless/version.rb +1 -1
- metadata +3 -3
- data/README.md +0 -152
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f271794edee45ff107dcd0d7858e9fb01c4f670e8b98b76e2c70de39d3353498
|
4
|
+
data.tar.gz: 9e80d347a218de303b7697265e07410d1a460b4262c928fe48bfe711a83002fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7d5c0d76111c83e186b38f6be6ccb1d4170ccd27e427f775fa81ce3bcfd69173228b8fe47adea40e926c37f61cb3d1b6c75e808c6926eeb801d9119ce3a5400
|
7
|
+
data.tar.gz: 95b7c4020f915c4807b71c5d3afa05da17e1c1da18bd9b161bfc346a554e935e006d6305b326743d57363ce1a7bb75172a4e24330d913147514e4f73a4cbdf54
|
data/README.org
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
#+TITLE: Timeless README
|
2
|
+
#+AUTHOR: Adolfo Villafiorita
|
3
|
+
#+STARTUP: showall
|
4
|
+
|
5
|
+
Timeless is a simple command line time tracker which supports
|
6
|
+
stopwatches, pomodoro timers, and key-value pair in notes.
|
7
|
+
|
8
|
+
Some non nominal conditions are also handled (e.g., starting a clock
|
9
|
+
twice, trying to stop when no clock was started).
|
10
|
+
|
11
|
+
* Installation
|
12
|
+
:PROPERTIES:
|
13
|
+
:CUSTOM_ID: installation
|
14
|
+
:END:
|
15
|
+
|
16
|
+
Install the gem:
|
17
|
+
|
18
|
+
#+BEGIN_EXAMPLE
|
19
|
+
$ gem install timeless
|
20
|
+
#+END_EXAMPLE
|
21
|
+
|
22
|
+
* Usage
|
23
|
+
:PROPERTIES:
|
24
|
+
:CUSTOM_ID: usage
|
25
|
+
:END:
|
26
|
+
|
27
|
+
Run a pomodoro timer:
|
28
|
+
|
29
|
+
#+BEGIN_EXAMPLE
|
30
|
+
timeless pom p:project meeting with c:john
|
31
|
+
timeless pom --duration 60 p:prj2
|
32
|
+
timeless pom --long # default to 50 minutes
|
33
|
+
#+END_EXAMPLE
|
34
|
+
|
35
|
+
Start clocking using a stopwatch:
|
36
|
+
|
37
|
+
#+BEGIN_EXAMPLE
|
38
|
+
timeless start requirements doc
|
39
|
+
timeless start --at 'thirty minutes ago' fixing bug 182 for c:tim
|
40
|
+
timeless start --force --at 'five minutes ago' requirements document for p:prj1
|
41
|
+
#+END_EXAMPLE
|
42
|
+
|
43
|
+
Stop clocking:
|
44
|
+
|
45
|
+
#+BEGIN_EXAMPLE
|
46
|
+
timeless stop
|
47
|
+
timeless stop forgot notes on start
|
48
|
+
timeless stop --last # reuse the notes of previous entry
|
49
|
+
timeless stop --at 'five minutes ago'
|
50
|
+
timeless stop --start '1 hour ago' --at 'now' clocked a full entry
|
51
|
+
#+END_EXAMPLE
|
52
|
+
|
53
|
+
Enter a full entry:
|
54
|
+
|
55
|
+
#+BEGIN_EXAMPLE
|
56
|
+
timeless clock activity on p:project # from end of last entry to now
|
57
|
+
timeless clock --start 'three hours ago' --stop 'five minutes ago'
|
58
|
+
#+END_EXAMPLE
|
59
|
+
|
60
|
+
What was i doing?
|
61
|
+
|
62
|
+
#+BEGIN_EXAMPLE
|
63
|
+
timeless current # print current entry
|
64
|
+
timeless forget # forget pending clock
|
65
|
+
#+END_EXAMPLE
|
66
|
+
|
67
|
+
What did I do?
|
68
|
+
|
69
|
+
#+BEGIN_EXAMPLE
|
70
|
+
timeless last # print last entry
|
71
|
+
#+END_EXAMPLE
|
72
|
+
|
73
|
+
Reporting and exporting
|
74
|
+
|
75
|
+
#+BEGIN_EXAMPLE
|
76
|
+
timeless statement
|
77
|
+
timeless balance --from yesterday --filter p:project
|
78
|
+
timeless export
|
79
|
+
#+END_EXAMPLE
|
80
|
+
|
81
|
+
Notice that even though =timeless= uses CSV as its native format, the
|
82
|
+
export command generates a CSV file which is more easily parsed by a
|
83
|
+
spreadsheet application such as LibreOffice.
|
84
|
+
|
85
|
+
If you do not want to type =timeless= every time, you can invoke a
|
86
|
+
console:
|
87
|
+
|
88
|
+
#+BEGIN_EXAMPLE
|
89
|
+
timeless console
|
90
|
+
timeless:000> start
|
91
|
+
timeless:001> stop
|
92
|
+
timeless:002>
|
93
|
+
#+END_EXAMPLE
|
94
|
+
|
95
|
+
More information with:
|
96
|
+
|
97
|
+
#+BEGIN_EXAMPLE
|
98
|
+
timeless help # get list of available commands
|
99
|
+
timeless help command # help about command
|
100
|
+
timeless man # output this README file
|
101
|
+
#+END_EXAMPLE
|
102
|
+
|
103
|
+
* Key-Value pairs
|
104
|
+
:PROPERTIES:
|
105
|
+
:CUSTOM_ID: key-value-pairs
|
106
|
+
:END:
|
107
|
+
|
108
|
+
Timeless has some basic support for key-pair values in the notes
|
109
|
+
field.
|
110
|
+
|
111
|
+
A key-pair value is entered as:
|
112
|
+
|
113
|
+
#+BEGIN_EXAMPLE
|
114
|
+
key:value
|
115
|
+
#+END_EXAMPLE
|
116
|
+
|
117
|
+
where =key= is any string starting with a letter and containing letters,
|
118
|
+
numbers, and underscores; and =value= is *anything but a space*.
|
119
|
+
|
120
|
+
For instance a note field could look like:
|
121
|
+
|
122
|
+
#+BEGIN_EXAMPLE
|
123
|
+
working for c:john_smith on a:writing_documentation
|
124
|
+
#+END_EXAMPLE
|
125
|
+
|
126
|
+
Key value pairs can be used to assign a special meaning to some
|
127
|
+
strings and improve filtering and exporting.
|
128
|
+
|
129
|
+
Three special keys are =p= for projects, =c= for clients, and =a= for
|
130
|
+
activity. These keys get dedicated columns in the csv file when using
|
131
|
+
the =export= command.
|
132
|
+
|
133
|
+
* If something goes wrong
|
134
|
+
:PROPERTIES:
|
135
|
+
:CUSTOM_ID: if-something-goes-wrong
|
136
|
+
:END:
|
137
|
+
|
138
|
+
Timeless writes entries on =~/.timeless.csv=, storing the following
|
139
|
+
information:
|
140
|
+
|
141
|
+
1. start date and time
|
142
|
+
2. end date and time
|
143
|
+
3. notes
|
144
|
+
|
145
|
+
You can edit the file to manually fix entries if you make some
|
146
|
+
mistake.
|
147
|
+
|
148
|
+
The =~/timeless.csv= file should contain only correct entries, that
|
149
|
+
is, entries with start, stop, and (possibly empty) notes.
|
150
|
+
|
151
|
+
When using a stopwatch, a temporary file =~/.timeless-tmp.csv= is used
|
152
|
+
to store the timestamp of the start command.
|
153
|
+
|
154
|
+
* Version History
|
155
|
+
:PROPERTIES:
|
156
|
+
:CUSTOM_ID: version-history
|
157
|
+
:END:
|
158
|
+
|
159
|
+
*** 0.6.0
|
160
|
+
|
161
|
+
- support for generic keys in notes. Possibility of specifying the same
|
162
|
+
key multiple times in a single note field
|
163
|
+
- balance now produces distinct reports for each key (on top of the three
|
164
|
+
already generated for projects, activities, and clients)
|
165
|
+
- management of empty lines in ~/timeless.csv
|
166
|
+
|
167
|
+
*** 0.5.0
|
168
|
+
|
169
|
+
- updated origin in Gem specification
|
170
|
+
|
171
|
+
*** 0.4.0
|
172
|
+
|
173
|
+
- second public release
|
174
|
+
- new =balance= command
|
175
|
+
- the =report= command has been renamed =statement=
|
176
|
+
- interactive =console=
|
177
|
+
- more detailed help for commands
|
178
|
+
- fixed a bug in the last command: now it returns the last activity in
|
179
|
+
chronological order (rather than the last activity which has been
|
180
|
+
clocked)
|
181
|
+
|
182
|
+
*** 0.2.0
|
183
|
+
|
184
|
+
- initial public release
|
185
|
+
|
186
|
+
** License
|
187
|
+
:PROPERTIES:
|
188
|
+
:CUSTOM_ID: license
|
189
|
+
:END:
|
190
|
+
|
191
|
+
Licensed under the terms of the MIT License.
|
192
|
+
|
193
|
+
** Contributing
|
194
|
+
:PROPERTIES:
|
195
|
+
:CUSTOM_ID: contributing
|
196
|
+
:END:
|
197
|
+
|
198
|
+
1. Fork it ( https://github.com/[my-github-username]/timeless/fork )
|
199
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
200
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
201
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
202
|
+
5. Create a new Pull Request
|
data/elisp/forms.el
CHANGED
@@ -17,7 +17,7 @@ module Timeless
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.man opts = nil, argv = []
|
20
|
-
path = File.join(File.dirname(__FILE__), "/../../../README.
|
20
|
+
path = File.join(File.dirname(__FILE__), "/../../../README.org")
|
21
21
|
file = File.open(path, "r")
|
22
22
|
contents = file.read
|
23
23
|
puts contents
|
@@ -215,6 +215,7 @@ module Timeless
|
|
215
215
|
to = opts.to_hash[:to] ? Chronic.parse(opts.to_hash[:to]) : nil
|
216
216
|
|
217
217
|
entries = Timeless::Storage.get(from, to, opts.to_hash[:filter])
|
218
|
+
|
218
219
|
# it could become a function of a reporting module
|
219
220
|
printf "%-18s %-5s - %-5s %-8s %-s\n", "Day", "Start", "End", "Duration", "Notes"
|
220
221
|
total = 0
|
@@ -248,42 +249,31 @@ module Timeless
|
|
248
249
|
# {key1 => {value1 => total .. } , ... }
|
249
250
|
hash = Timeless::Storage::balance from, to, opts.to_hash[:filter]
|
250
251
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
hash["p"].each do |key, value|
|
255
|
-
printf "%-20s%5s\n", key, in_hours(value)
|
256
|
-
total += value
|
257
|
-
end
|
258
|
-
puts "-------------------------"
|
259
|
-
printf "%-20s%5s\n", "Total", in_hours(total)
|
252
|
+
report "Projects", "p", hash
|
253
|
+
report "Clients", "c", hash
|
254
|
+
report "Activities", "a", hash
|
260
255
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
puts "======="
|
265
|
-
hash["c"].each do |key, value|
|
266
|
-
printf "%-20s%5s\n", key, in_hours(value)
|
267
|
-
total += value
|
256
|
+
remaining_tags = hash.reject! { |k| ["p", "c", "a"].include? k }
|
257
|
+
remaining_tags.keys.each do |k|
|
258
|
+
report k, k, remaining_tags
|
268
259
|
end
|
269
|
-
|
270
|
-
|
260
|
+
end
|
261
|
+
|
262
|
+
private
|
271
263
|
|
264
|
+
def self.report title, key, hash
|
272
265
|
total = 0
|
273
266
|
puts ""
|
274
|
-
puts
|
275
|
-
puts "
|
276
|
-
hash[
|
277
|
-
printf "%-20s%5s\n",
|
278
|
-
total +=
|
267
|
+
puts title
|
268
|
+
puts "=" * title.size
|
269
|
+
(hash[key] || []).each do |k, v|
|
270
|
+
printf "%-20s%5s\n", k, in_hours(v)
|
271
|
+
total += v
|
279
272
|
end
|
280
273
|
puts "-------------------------"
|
281
274
|
printf "%-20s%5s\n", "Total", in_hours(total)
|
282
275
|
end
|
283
276
|
|
284
|
-
|
285
|
-
private
|
286
|
-
|
287
277
|
def self.in_hours value
|
288
278
|
sprintf "%02i:%02i", value / 60, value % 60
|
289
279
|
end
|
@@ -372,7 +372,12 @@ DESCRIPTION
|
|
372
372
|
a project "project_1", using "p:project_1"
|
373
373
|
|
374
374
|
EXAMPLES
|
375
|
+
# extract all entries which have the string p:project_1 in the notes field
|
376
|
+
# (that is, all entries related to project_1)
|
375
377
|
timeless statement --filter p:project_1
|
378
|
+
|
379
|
+
# extract all entries which have the word documentation in the notes field
|
380
|
+
timeless statement --filter documentation
|
376
381
|
EOS
|
377
382
|
return { statement: [opts, :statement, help] }
|
378
383
|
end
|
@@ -407,5 +412,36 @@ EXAMPLES
|
|
407
412
|
EOS
|
408
413
|
return { balance: [opts, :balance, help] }
|
409
414
|
end
|
415
|
+
|
416
|
+
def self.export_opts
|
417
|
+
opts = Slop::Options.new
|
418
|
+
opts.banner = "export -- export timeless.csv to CSV"
|
419
|
+
help = <<EOS
|
420
|
+
NAME
|
421
|
+
#{opts.banner}
|
422
|
+
|
423
|
+
SYNOPSYS
|
424
|
+
#{opts.to_s}
|
425
|
+
|
426
|
+
DESCRIPTION
|
427
|
+
Print data to CSV, with the following columns:
|
428
|
+
|
429
|
+
- Start Date
|
430
|
+
- Start Time
|
431
|
+
- End Date
|
432
|
+
- End Time
|
433
|
+
- Duration in seconds
|
434
|
+
- First project found in notes
|
435
|
+
- First activity found in notes
|
436
|
+
- First client found in notes
|
437
|
+
- Notes attached to entry
|
438
|
+
|
439
|
+
EXAMPLES
|
440
|
+
timeless export
|
441
|
+
timeless export > data.csv
|
442
|
+
EOS
|
443
|
+
return { export: [opts, :export, help] }
|
444
|
+
end
|
445
|
+
|
410
446
|
end
|
411
447
|
end
|
data/lib/timeless/storage.rb
CHANGED
@@ -11,11 +11,11 @@ module Timeless
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.last
|
14
|
-
|
14
|
+
my_read(TIMELESS_FILE).sort { |x, y| x[1] <=> y[1] }.last
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.get from_date=nil, to_date=nil, filter=nil
|
18
|
-
entries =
|
18
|
+
entries = my_read(TIMELESS_FILE)
|
19
19
|
entries.select do |x|
|
20
20
|
(from_date ? Time.parse(x[0]) >= from_date : true) and
|
21
21
|
(to_date ? Time.parse(x[1]) <= to_date : true) and
|
@@ -23,70 +23,85 @@ module Timeless
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
# get all unique
|
27
|
-
def self.
|
28
|
-
|
29
|
-
|
26
|
+
# get all unique tags in file
|
27
|
+
def self.get_tags
|
28
|
+
tags_regexp = /([a-zA-Z][0-9a-zA-Z_]*):([^ ]+)/
|
29
|
+
|
30
|
+
entries = my_read(TIMELESS_FILE)
|
31
|
+
entries.map { |x|
|
32
|
+
# match returns only the first match, while scan does it for the string
|
33
|
+
# scan returns an array of array ("a:b c:d".scan(tags_regexp) => [["a", "b"], ["c", "d"]]
|
34
|
+
(x[2] || "").scan(tags_regexp).map { |x| x[0] }
|
35
|
+
}.flatten.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
# get all unique keys of a given tag in file
|
39
|
+
def self.get_key tag
|
40
|
+
entries = my_read(TIMELESS_FILE)
|
41
|
+
entries.map { |x| extract_kpv tag, x[2] }.flatten.uniq.sort
|
30
42
|
end
|
31
43
|
|
32
44
|
def self.balance from, to, filter
|
33
|
-
|
34
|
-
|
35
|
-
hash = {
|
45
|
+
# hash of all keys defined in file
|
46
|
+
array = get_tags
|
47
|
+
hash = Hash[array.collect { |item| [item, {}] } ]
|
36
48
|
|
49
|
+
entries = Timeless::Storage.get(from, to, filter)
|
37
50
|
entries.each do |entry|
|
38
51
|
start = Time.parse(entry[0])
|
39
52
|
stop = Time.parse(entry[1])
|
40
53
|
duration = (stop - start) / 60
|
41
54
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
hash["a"][activity] = (hash["a"][activity] || 0) + duration if activity != ""
|
49
|
-
|
55
|
+
hash.keys.each do |key|
|
56
|
+
values = extract_kpv key, entry[2]
|
57
|
+
values.each do |value|
|
58
|
+
hash[key][value] = (hash[key][value] || 0) + duration
|
59
|
+
end
|
60
|
+
end
|
50
61
|
end
|
51
62
|
hash
|
52
63
|
end
|
53
|
-
|
54
|
-
|
55
64
|
def self.export
|
56
|
-
entries =
|
65
|
+
entries = my_read(TIMELESS_FILE)
|
57
66
|
|
58
67
|
CSV { |csvout| csvout << ["Start Date", "Start Time", "End Date", "End Time", "Duration (s)", "Project", "Client", "Activity", "Notes"] }
|
59
68
|
CSV do |csvout|
|
60
69
|
entries.each do |entry|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
70
|
+
if entry[0] and entry[1]
|
71
|
+
start = Time.parse(entry[0])
|
72
|
+
stop = Time.parse(entry[1])
|
73
|
+
|
74
|
+
start_date = start.strftime("%Y-%m-%d")
|
75
|
+
start_time = start.strftime("%H:%M:%S")
|
76
|
+
|
77
|
+
stop_date = stop.strftime("%Y-%m-%d")
|
78
|
+
stop_time = stop.strftime("%H:%M:%S")
|
79
|
+
|
80
|
+
duration = stop - start
|
81
|
+
|
82
|
+
# extract first project, first client, and first activity, if present
|
83
|
+
project = extract_kpv("p", entry[2]).first
|
84
|
+
client = extract_kpv("c", entry[2]).first
|
85
|
+
activity = extract_kpv("a", entry[2]).first
|
86
|
+
|
87
|
+
notes = entry[2]
|
88
|
+
|
89
|
+
csvout << [start_date, start_time, stop_date, stop_time, duration, project, client, activity, notes]
|
90
|
+
end
|
80
91
|
end
|
81
92
|
end
|
82
93
|
end
|
83
94
|
|
84
95
|
private
|
85
96
|
|
86
|
-
#
|
97
|
+
# read the timeless file into a CSV skipping lines with empty start end stop time
|
98
|
+
def self.my_read timeless_file
|
99
|
+
CSV.read(timeless_file).select { |x| x[0] != nil and x[1] != nil }
|
100
|
+
end
|
101
|
+
|
102
|
+
# return all the values of a given key in string
|
87
103
|
def self.extract_kpv key, string
|
88
|
-
|
89
|
-
match ? match[1] : ""
|
104
|
+
(string || "").scan(/(#{key}):([^ ]+)/).map { |x| x[1] }
|
90
105
|
end
|
91
106
|
end
|
92
107
|
end
|
data/lib/timeless/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timeless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adolfo Villafiorita
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -107,7 +107,7 @@ files:
|
|
107
107
|
- ".gitignore"
|
108
108
|
- Gemfile
|
109
109
|
- LICENSE.txt
|
110
|
-
- README.
|
110
|
+
- README.org
|
111
111
|
- Rakefile
|
112
112
|
- bin/console
|
113
113
|
- bin/setup
|
data/README.md
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
Timeless
|
2
|
-
========
|
3
|
-
|
4
|
-
Timeless is a simple command line time tracker.
|
5
|
-
|
6
|
-
Installation
|
7
|
-
------------
|
8
|
-
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
ruby
|
12
|
-
gem 'timeless'
|
13
|
-
|
14
|
-
And then execute:
|
15
|
-
|
16
|
-
$ bundle
|
17
|
-
|
18
|
-
Or install it yourself as:
|
19
|
-
|
20
|
-
$ gem install timeless
|
21
|
-
|
22
|
-
Usage
|
23
|
-
-----
|
24
|
-
|
25
|
-
timeless is a simple command line time tracker. Entries store the
|
26
|
-
following information:
|
27
|
-
|
28
|
-
1. start time
|
29
|
-
2. end time
|
30
|
-
3. notes
|
31
|
-
|
32
|
-
timeless allows one to
|
33
|
-
|
34
|
-
- run a pomodoro timer
|
35
|
-
- clock time using a "stopwatch" (with start and stop commands)
|
36
|
-
- manually entering data
|
37
|
-
- print a text report, possibly filtered by date ranges of notes'
|
38
|
-
content
|
39
|
-
- export to csv
|
40
|
-
|
41
|
-
Timeless has also some basic support for key-pair values in the notes
|
42
|
-
form. They can be used to assign a special meaning to some strings and
|
43
|
-
improve filtering and exporting. Two special keys are `p` for projects
|
44
|
-
and `c` for clients. These two keys are exported in dedicated columns
|
45
|
-
when exporting data to csv.
|
46
|
-
|
47
|
-
Some non nominal conditions are also handled (e.g., starting a clock
|
48
|
-
twice, trying to stop when no clock was started).
|
49
|
-
|
50
|
-
If you do not want to type `timeless` every time, you can invoke a console:
|
51
|
-
|
52
|
-
timeless console
|
53
|
-
timeless:000> start
|
54
|
-
timeless:001> stop
|
55
|
-
timeless:002>
|
56
|
-
|
57
|
-
More information with:
|
58
|
-
|
59
|
-
timeless help # get list of available commands
|
60
|
-
timeless help command # help about command
|
61
|
-
timeless man # output this README file
|
62
|
-
|
63
|
-
|
64
|
-
Examples
|
65
|
-
--------
|
66
|
-
|
67
|
-
Get information about command syntax:
|
68
|
-
|
69
|
-
timeless -h
|
70
|
-
|
71
|
-
Run a pomodoro timer:
|
72
|
-
|
73
|
-
timeless pom p:project meeting with c:john
|
74
|
-
timeless pom --duration 60 p:prj2
|
75
|
-
timeless pom --long # default to 50 minutes
|
76
|
-
|
77
|
-
Start clocking using a stopwatch:
|
78
|
-
|
79
|
-
timeless start requirements doc
|
80
|
-
timeless start --at 'thirty minutes ago' fixing bug 182 for c:tim
|
81
|
-
timeless start --force --at 'five minutes ago' requirements document for p:prj1
|
82
|
-
|
83
|
-
Stop clocking:
|
84
|
-
|
85
|
-
timeless stop
|
86
|
-
timeless stop forgot notes on start
|
87
|
-
timeless stop --last # reuse the notes of last entry
|
88
|
-
timeless stop --at 'five minutes ago'
|
89
|
-
timeless stop --start '1 hour ago' --at 'now' clocked a full entry
|
90
|
-
|
91
|
-
Enter a full entry:
|
92
|
-
|
93
|
-
timeless clock activity on p:project # from end of last entry to now
|
94
|
-
timeless clock --start 'three hours ago' --stop 'five minutes ago'
|
95
|
-
|
96
|
-
What was i doing?
|
97
|
-
|
98
|
-
timeless current # print current entry
|
99
|
-
timeless forget # forget pending clock
|
100
|
-
|
101
|
-
What did I do?
|
102
|
-
|
103
|
-
timeless last # print last entry
|
104
|
-
|
105
|
-
Reporting and exporting
|
106
|
-
|
107
|
-
timeless statement
|
108
|
-
timeless balance --from yesterday --filter p:project
|
109
|
-
timeless export
|
110
|
-
|
111
|
-
Notice that even though `timeless` uses CSV as its native format, the
|
112
|
-
export command exports to a CSV file which is more easily parsed by a
|
113
|
-
Spreadsheet such as LibreOffice.
|
114
|
-
|
115
|
-
If something goes wrong
|
116
|
-
-----------------------
|
117
|
-
|
118
|
-
Data is stored in the CSV file `~/.timeless.csv`. You can edit the file
|
119
|
-
to manually fix entries if you make some mistake.
|
120
|
-
|
121
|
-
Version History
|
122
|
-
---------------
|
123
|
-
|
124
|
-
**0.4.0**
|
125
|
-
|
126
|
-
- second public release
|
127
|
-
- new `balance` command
|
128
|
-
- the `report` command has been renamed `statement`
|
129
|
-
- interactive `console`
|
130
|
-
- more detailed help for commands
|
131
|
-
- fixed a bug in the last command: now it returns the last activity in
|
132
|
-
chronological order (rather than the last activity which has been clocked)
|
133
|
-
|
134
|
-
**0.2.0**
|
135
|
-
- initial public release
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
License
|
140
|
-
-------
|
141
|
-
|
142
|
-
Licensed under the terms of the MIT License.
|
143
|
-
|
144
|
-
Contributing
|
145
|
-
------------
|
146
|
-
|
147
|
-
1. Fork it ( https://github.com/\[my-github-username\]/timeless/fork )
|
148
|
-
2. Create your feature branch (\`git checkout -b my-new-feature\`)
|
149
|
-
3. Commit your changes (\`git commit -am 'Add some feature'\`)
|
150
|
-
4. Push to the branch (\`git push origin my-new-feature\`)
|
151
|
-
5. Create a new Pull Request
|
152
|
-
|