twkb 0.0.1 → 0.0.2
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.
- data/.rvmrc +1 -0
- data/bin/twkb +6 -0
- data/lib/twkb.rb +50 -0
- data/lib/twkb/config.rb +78 -0
- data/lib/twkb/formatter.rb +48 -0
- data/lib/twkb/task.rb +13 -0
- data/lib/twkb/version.rb +3 -0
- data/twkb.gemspec +23 -0
- metadata +13 -6
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use default@twkb
|
data/bin/twkb
ADDED
data/lib/twkb.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'twkb/config'
|
2
|
+
require 'twkb/task'
|
3
|
+
require 'twkb/formatter'
|
4
|
+
|
5
|
+
module TWKB
|
6
|
+
class App
|
7
|
+
attr_accessor :config
|
8
|
+
attr_accessor :board_name
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@config = TWKB::Config.new
|
12
|
+
@board_name = get_board_name options[:board_name]
|
13
|
+
populate_stages
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_table
|
17
|
+
formatter = TWKB::Formatter.new(:stages => @config.stages, :cell_width => @config['view.cell_width'])
|
18
|
+
puts formatter.table
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def get_board_name(name = nil)
|
23
|
+
name || @config['board_name'] || 'personal'
|
24
|
+
end
|
25
|
+
|
26
|
+
def populate_stages
|
27
|
+
tasks = TWKB::Task.all(:board => @board_name)
|
28
|
+
@config.stage_names.each do |stage|
|
29
|
+
@config.stages[stage][:tasks] = tasks.select{|task|
|
30
|
+
task['stage'] == stage && task['status'] == 'pending'
|
31
|
+
}.sort_by{|k| k['urgency']}.reverse
|
32
|
+
|
33
|
+
# Truncate headers to match cell width
|
34
|
+
@config.stages[stage][:label][:value] = @config.stages[stage][:label][:value][0..@config['view.cell_width']]
|
35
|
+
|
36
|
+
if @config.stages[stage][:wip]
|
37
|
+
label_value = "\n(#{@config.stages[stage][:tasks].length}/#{@config.stages[stage][:wip]})"
|
38
|
+
@config.stages[stage][:label][:value] << label_value[0..@config['view.cell_width']]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# 'Done' is special
|
43
|
+
if @config.stage_names.include? 'done'
|
44
|
+
@config.stages['done'][:tasks] = tasks.select{ |task|
|
45
|
+
task['status'] == 'completed'
|
46
|
+
}.sort_by{|k| k['end'] }.reverse[0..@config['view.done_tasks']-1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/twkb/config.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'parseconfig'
|
2
|
+
|
3
|
+
module TWKB
|
4
|
+
class Config
|
5
|
+
attr_reader :stage_names
|
6
|
+
attr_accessor :stages
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
read
|
10
|
+
prepare
|
11
|
+
build_stages
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](val)
|
15
|
+
@config[val]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def defaults
|
21
|
+
{
|
22
|
+
'twkb.view.cell_width' => '15',
|
23
|
+
'twkb.view.stages.alignment' => 'center',
|
24
|
+
'twkb.view.done_tasks' => '5',
|
25
|
+
'twkb.stages' => 'backlog,next,inprogress,waiting,done',
|
26
|
+
'twkb.stages.backlog.wip' => '10',
|
27
|
+
'twkb.stages.backlog.label.value' => 'Backlog',
|
28
|
+
'twkb.stages.next.wip' => '5',
|
29
|
+
'twkb.stages.next.label.value' => 'Next',
|
30
|
+
'twkb.stages.inprogress.wip' => '3',
|
31
|
+
'twkb.stages.inprogress.label.value' => 'In progress',
|
32
|
+
'twkb.stages.waiting.wip' => '6',
|
33
|
+
'twkb.stages.waiting.label.value' => 'Waiting',
|
34
|
+
'twkb.stages.done.label.value' => 'Done'
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def read
|
39
|
+
begin
|
40
|
+
user_config = ParseConfig.new("#{Dir.home}/.taskrc")
|
41
|
+
if user_config.params['twkb.stages'] and user_config.params['twkb.stages'].empty?
|
42
|
+
user_config.params['twkb.stages'] = defaults['twkb.stages']
|
43
|
+
end
|
44
|
+
@config = defaults.merge(user_config.params)
|
45
|
+
rescue Errno::EACCES
|
46
|
+
puts "Failed to read the configuration. Using defaults."
|
47
|
+
@config = defaults
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def prepare
|
52
|
+
@config.keys.each do |k|
|
53
|
+
# Convert numbers to integers for convenience
|
54
|
+
if @config[k] =~ /^\d+$/
|
55
|
+
@config[k] = @config[k].to_i
|
56
|
+
end
|
57
|
+
# Remove the 'twkb' part for convenience
|
58
|
+
@config[k.gsub(/^twkb\.(.*)/, '\1')] = @config.delete(k)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_stages
|
63
|
+
@stage_names = self['stages'].split(',')
|
64
|
+
@stages = {}
|
65
|
+
@stage_names.each do |stage|
|
66
|
+
@stages[stage] = {
|
67
|
+
:tasks => [],
|
68
|
+
:wip => self["stages.#{stage}.wip"].to_i || nil,
|
69
|
+
:label => {
|
70
|
+
:value => self["stages.#{stage}.label.value"] || stage,
|
71
|
+
:alignment => (self["stages.#{stage}.label.alignment"] || self["view.stages.alignment"]).to_sym
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'terminal-table'
|
2
|
+
require 'rainbow'
|
3
|
+
|
4
|
+
module TWKB
|
5
|
+
class Formatter
|
6
|
+
def initialize(options)
|
7
|
+
raise ArgumentError, 'Missing :stages argument' unless options[:stages]
|
8
|
+
raise ArgumentError, ':stages is not a Hash' unless options[:stages].is_a? Hash
|
9
|
+
@cell_width = options[:cell_width]
|
10
|
+
@cell_width ||= 15
|
11
|
+
@stages = options[:stages]
|
12
|
+
prepare
|
13
|
+
end
|
14
|
+
|
15
|
+
def table
|
16
|
+
stage_labels = @stages.keys.map{|k,v| @stages[k][:label]}
|
17
|
+
Terminal::Table.new :headings => stage_labels, :rows => [@lanes]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def color_box(text, width=15, fg=:black, bg=:white)
|
23
|
+
lines = text.scan /.{1,#{width}}/
|
24
|
+
lines.map!{|line| "#{line.ljust(width).background(bg).foreground(fg)}\n"}
|
25
|
+
lines.join
|
26
|
+
end
|
27
|
+
|
28
|
+
def prepare
|
29
|
+
@lanes = Array.new
|
30
|
+
@stages.each do |k, v|
|
31
|
+
tasks = v[:tasks]
|
32
|
+
text = String.new
|
33
|
+
# Makes sure empty columns have the correct cell width
|
34
|
+
text << ' ' * @cell_width if tasks.count == 0
|
35
|
+
tasks.each do |k, v|
|
36
|
+
next unless k
|
37
|
+
if k['status'] == 'completed'
|
38
|
+
text << color_box("#{k['description']}", @cell_width)
|
39
|
+
else
|
40
|
+
text << color_box("#{k['id']}) #{k['description']}", @cell_width)
|
41
|
+
end
|
42
|
+
text << "\n"
|
43
|
+
end
|
44
|
+
@lanes << text
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/twkb/task.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module TWKB
|
4
|
+
module Task
|
5
|
+
def Task.all(udas = {})
|
6
|
+
f_udas = udas.map {|k,v| "#{k}:#{v}"}.join(' ')
|
7
|
+
cmd = "task rc.verbose=nothing rc.json.array=yes #{f_udas} export"
|
8
|
+
IO.popen(cmd, 'r:UTF-8') { |output|
|
9
|
+
JSON.parse(output.read)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/twkb/version.rb
ADDED
data/twkb.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "twkb/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'twkb'
|
7
|
+
s.version = TWKB::VERSION
|
8
|
+
s.date = '2013-05-01'
|
9
|
+
s.summary = "TaskWarrior Kanban"
|
10
|
+
s.description = "A command line utility based on task warrior to create kanban boards."
|
11
|
+
s.authors = ["Kim Nørgaard"]
|
12
|
+
s.email = 'jasen@jasen.dk'
|
13
|
+
s.files = ["lib/twkb.rb"]
|
14
|
+
s.homepage = ""
|
15
|
+
|
16
|
+
s.add_runtime_dependency 'terminal-table', '~>1.4.5'
|
17
|
+
s.add_runtime_dependency 'parseconfig', '~>1.0.2'
|
18
|
+
s.add_runtime_dependency 'rainbow', '~>1.1.4'
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Kim N\xC3\xB8rgaard"
|
@@ -61,14 +61,21 @@ dependencies:
|
|
61
61
|
version_requirements: *id003
|
62
62
|
description: A command line utility based on task warrior to create kanban boards.
|
63
63
|
email: jasen@jasen.dk
|
64
|
-
executables:
|
65
|
-
|
64
|
+
executables:
|
65
|
+
- twkb
|
66
66
|
extensions: []
|
67
67
|
|
68
68
|
extra_rdoc_files: []
|
69
69
|
|
70
|
-
files:
|
71
|
-
|
70
|
+
files:
|
71
|
+
- .rvmrc
|
72
|
+
- bin/twkb
|
73
|
+
- lib/twkb.rb
|
74
|
+
- lib/twkb/config.rb
|
75
|
+
- lib/twkb/formatter.rb
|
76
|
+
- lib/twkb/task.rb
|
77
|
+
- lib/twkb/version.rb
|
78
|
+
- twkb.gemspec
|
72
79
|
has_rdoc: true
|
73
80
|
homepage: ""
|
74
81
|
licenses: []
|