koi 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/VERSION +1 -1
  2. data/koi.gemspec +5 -4
  3. data/lib/koi.rb +67 -30
  4. data/spec/koi_spec.rb +31 -5
  5. metadata +2 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
data/koi.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{koi}
8
- s.version = "0.2.2"
8
+ s.version = "0.2.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["cloudhead"]
12
- s.date = %q{2009-10-20}
12
+ s.date = %q{2010-03-06}
13
13
  s.default_executable = %q{koi}
14
14
  s.description = %q{minimalist console-based task management for hackers}
15
15
  s.email = %q{self@cloudhead.net}
@@ -57,3 +57,4 @@ Gem::Specification.new do |s|
57
57
  s.add_dependency(%q<mutter>, [">= 0.4"])
58
58
  end
59
59
  end
60
+
data/lib/koi.rb CHANGED
@@ -5,12 +5,16 @@ require 'fileutils'
5
5
 
6
6
  module Koi
7
7
 
8
- Path = {root: ".koi", db: ".koi/database.yml"}
8
+ Path = {root: ".koi", db: ".koi/database.yml", paths: ".koi/paths"}
9
9
 
10
10
  def self.init dir = Dir.pwd
11
11
  unless init?
12
12
  FileUtils.mkdir File.join(dir, Path[:root])
13
13
  FileUtils.touch File.join(dir, Path[:db])
14
+ FileUtils.mkdir File.join(ENV['HOME'], Path[:root]) rescue nil
15
+ File.open(File.join(ENV['HOME'], Path[:paths]), 'a+') do |f|
16
+ f.write File.expand_path(dir).to_s
17
+ end
14
18
  end
15
19
  end
16
20
 
@@ -20,15 +24,15 @@ module Koi
20
24
  end
21
25
 
22
26
  def self.init? dir = root
23
- File.exist? File.join(dir, Path[:root]) if dir
27
+ File.exist? File.join(dir, Path[:db]) if dir
24
28
  end
25
-
29
+
26
30
  def self.run *args
27
31
  cmd = Command.new(*args)
28
32
  cmd[:silent] = true
29
33
  cmd.run
30
34
  end
31
-
35
+
32
36
  def self.version
33
37
  File.read(File.join(File.dirname(__FILE__), '..', 'VERSION')).strip
34
38
  end
@@ -49,7 +53,7 @@ module Koi
49
53
  :init, :add, :list, :tag,
50
54
  :done, :did, :log, :status,
51
55
  :remove, :float, :sink,
52
- :ls, :rm
56
+ :ls, :rm, :rise
53
57
  ]
54
58
  Initializers = [:init, :add]
55
59
  Special = {"!" => :done, "?" => :status}
@@ -61,13 +65,14 @@ module Koi
61
65
  @param = param =~ /^\d+$/ ? param.to_i : param
62
66
  @options = options || {}
63
67
  @db = Koi.init?? Database.new(File.join(Koi.root, Path[:db])) : Database.new
64
- @mut = Mutter.new(blue: '#', underline: "''", cyan: '@@', green: '!!', yellow: '^').clear(:default)
68
+ @mut = Mutter.new(blue: '#', underline: "''", red: '++', cyan: '@@', green: '!!', yellow: '^').clear(:default)
65
69
  end
66
70
 
67
71
  def run
68
72
  if Commands.include? @command
69
73
  if Koi.init? or Initializers.include? @command
70
74
  if !@param or @command == :add or @param = @db.find(@param)
75
+ @param ||= @db.last if [:float, :sink, :rm, :tag, :done].include? @command
71
76
  if send(@command, *[@param, *@args].compact.flatten)
72
77
  save
73
78
  else
@@ -77,39 +82,37 @@ module Koi
77
82
  err "task wasn't found"
78
83
  end
79
84
  else
80
- err "'it' is not initialized here, please run `it init`"
85
+ err "'koi' is not initialized here, please run `koi init`"
81
86
  end
82
87
  else
83
88
  err "#{@command} is not a valid command."
84
89
  end
85
90
  end
86
-
91
+
87
92
  def []= key, val
88
93
  @options[key] = val
89
94
  end
90
-
95
+
91
96
  def [] key
92
97
  @options[key]
93
98
  end
94
99
 
95
100
  def init
96
101
  unless Koi.init
97
- err "'it' has already been initialized here"
102
+ err "'koi' has already been initialized here"
98
103
  else
99
104
  true
100
105
  end
101
106
  end
102
-
107
+
103
108
  def status
104
109
  out "in the water (#{@db.select {|e| e.new? }.size})"
105
110
 
106
111
  self.list 5
107
112
 
108
- out "recently fished (#{@db.select {|e| e.completed? }.size})"
109
-
110
113
  @db.select {|e| e[:status] == :completed }.
111
114
  sort_by {|e| e[:completed_at] }[0..3].reverse.each do |e|
112
- out "- !!#{e[:title]}!!"
115
+ out " #[x]# !!#{e[:title]}!!"
113
116
  end
114
117
 
115
118
  out
@@ -121,9 +124,9 @@ module Koi
121
124
  #
122
125
  def list count = 10, index = -1
123
126
  out
124
-
125
- @db.select {|e| e.new? }[0..count].each do |e|
126
- out "#[#{index += 1}]# ''#{e[:title]}'' @@#{e[:tags].join(' ')}@@" unless e[:status] == :removed
127
+
128
+ @db.list[0..count].each do |e|
129
+ out " #[#{index += 1}]##{e.sticky?? "++ + ++" : " "}''#{e[:title]}'' @@#{e[:tags].join(' ')}@@" unless e[:status] == :removed
127
130
  end.tap do |list|
128
131
  out " !!nothing left to do!!" if list.size.zero?
129
132
  end
@@ -132,11 +135,24 @@ module Koi
132
135
  true
133
136
  end
134
137
  alias :ls list
135
-
136
- def float
138
+
139
+ def swim entry, n
140
+ v = @db.index(entry) + @db.size / 3 * n
141
+ @db.delete entry
142
+ @db.insert([[v, 0].max, @db.size].min, entry)
143
+ end
144
+
145
+ def rise entry
146
+ swim entry, -1
147
+ end
148
+
149
+ def sink entry
150
+ swim entry, 1
137
151
  end
138
152
 
139
- def sink
153
+ def float entry
154
+ entry[:sticky] = ! entry[:sticky]
155
+ true
140
156
  end
141
157
 
142
158
  #
@@ -145,9 +161,9 @@ module Koi
145
161
  def log
146
162
  @db.map do |entity|
147
163
  Entity::Status.map do |status|
148
- { title: entity[:title],
164
+ { title: entity[:title],
149
165
  action: status,
150
- time: entity[:"#{status}_at"]
166
+ time: entity[:"#{status}_at"].strftime("%Y/%m/%d %H:%m")
151
167
  } if entity[:"#{status}_at"]
152
168
  end.compact
153
169
  end.flatten.sort_by {|e| e[:time]}.reverse.each do |entry|
@@ -188,7 +204,7 @@ module Koi
188
204
  def save
189
205
  File.open(File.join(Koi.root, Path[:db]), 'w') {|f| f.write @db.to_yaml }
190
206
  end
191
-
207
+
192
208
  #
193
209
  # Mark task as :removed (doesn't show up anywhere)
194
210
  #
@@ -214,13 +230,32 @@ module Koi
214
230
  if key.is_a? String
215
231
  @data.find {|e| e[:title].include? key }
216
232
  elsif key.is_a? Fixnum
217
- @data.select {|e| e[:status] == :created}[key]
233
+ entities = @data.select {|e| e[:status] == :created}
234
+ (entities.select(&:sticky?) + entities.reject(&:sticky?))[key]
218
235
  else
219
236
  raise ArgumentError, "key must be a String or Fixnum, but is #{key.class}"
220
237
  end
221
238
  end
222
239
  alias :[] find
223
-
240
+
241
+ def fresh
242
+ @data.select {|e| e.new? }
243
+ end
244
+
245
+ def list
246
+ fresh.select(&:sticky?) + fresh.reject(&:sticky?)
247
+ end
248
+
249
+ #
250
+ # Hash-like methods on @data
251
+ #
252
+ def size; fresh.size end
253
+ def first; fresh.first end
254
+ def last; fresh.last end
255
+ def delete(arg) @data.delete arg end
256
+ def insert(*args) @data.insert *args end
257
+ def index(*args, &blk) @data.index *args, &blk end
258
+
224
259
  def load path = @path || Path[:db]
225
260
  @data = if db = YAML.load_file(path)
226
261
  db.map {|e| Entity.new(e) }
@@ -250,17 +285,19 @@ module Koi
250
285
  self.replace status: :created,
251
286
  created_at: Time.now,
252
287
  owner: ENV['USER'],
253
- velocity: 0,
254
- freshness: 0,
255
- depth: 0,
256
- tags: []
288
+ tags: [],
289
+ sticky: false
257
290
  merge!(data)
258
291
  end
259
-
292
+
260
293
  def new?
261
294
  self[:status] == :created
262
295
  end
263
296
 
297
+ def sticky?
298
+ self[:sticky]
299
+ end
300
+
264
301
  def status= st
265
302
  self[:status] = st
266
303
  self[:"#{st}_at"] = Time.now
data/spec/koi_spec.rb CHANGED
@@ -6,12 +6,21 @@ describe Koi do
6
6
  context "in a new project" do
7
7
  before(:each) do
8
8
  FileUtils.rm_rf(Koi::Path[:root])
9
+ FileUtils.rm_rf(File.join(ENV['HOME'], Koi::Path[:root]))
9
10
  end
10
11
 
11
- it "should initialize the directory" do
12
+ it "should initialize the .koi directory" do
12
13
  Koi.run(:init)
13
- File.exist?(Koi::Path[:root]).should be_true
14
- File.exist?(Koi::Path[:db]).should be_true
14
+ File.exist?(Koi::Path[:root]).should == true
15
+ File.exist?(Koi::Path[:db]).should == true
16
+ end
17
+
18
+ it "should create a .koi in ~" do
19
+ Koi.run(:init)
20
+ File.exist?(File.join(ENV['HOME'], Koi::Path[:root])).
21
+ should == true
22
+ File.read(File.join(ENV['HOME'], Koi::Path[:paths])).
23
+ split(/\n/).should include(File.expand_path(Dir.pwd))
15
24
  end
16
25
 
17
26
  it "should warn that the project isn't initialized" do
@@ -23,12 +32,12 @@ describe Koi do
23
32
  before(:all) do
24
33
  Koi.init!
25
34
  end
26
-
35
+
27
36
  context "with no tasks" do
28
37
  it "shouldn't try to init" do
29
38
  -> {Koi.run(:init)}.should raise_error(SystemExit)
30
39
  end
31
-
40
+
32
41
  it "should warn about invalid commands" do
33
42
  -> {Koi.run(:choo)}.should raise_error(SystemExit)
34
43
  end
@@ -70,9 +79,26 @@ describe Koi do
70
79
  @db.load.find(TASKS[1])[:tags].should include("food")
71
80
  end
72
81
 
82
+ it "should rise tasks" do
83
+ Koi.run(:rise, TASKS[2])
84
+ @db.load[1][:title].should == TASKS[2]
85
+ end
86
+
87
+ it "should sink tasks" do
88
+ Koi.run(:sink, TASKS[1])
89
+ @db.load.last[:title].should == TASKS[1]
90
+ end
91
+
92
+ it "should sticky tasks" do
93
+ Koi.run(:float, TASKS[2])
94
+ @db.load.list[0][:title].should == TASKS[2]
95
+ @db.load.find(TASKS[2])[:sticky].should be_true
96
+ end
97
+
73
98
  it "should warn when the task wasn't found" do
74
99
  -> {Koi.run(:did, "celery")}.should raise_error(SystemExit)
75
100
  end
76
101
  end
77
102
  end
78
103
  end
104
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: koi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - cloudhead
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-20 00:00:00 -04:00
12
+ date: 2010-03-06 00:00:00 -05:00
13
13
  default_executable: koi
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency