clitasks 0.0.3
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 +7 -0
- data/bin/task +29 -0
- data/lib/clitasks/commands.rb +80 -0
- data/lib/clitasks/link_builder.rb +76 -0
- data/lib/clitasks/runner.rb +17 -0
- data/lib/clitasks/simple_dsl.rb +33 -0
- data/lib/clitasks/story.rb +44 -0
- data/lib/clitasks/story_reader.rb +13 -0
- data/lib/clitasks/viewer.rb +42 -0
- data/lib/clitasks/world.rb +14 -0
- data/lib/clitasks.rb +17 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8b3bf9526e0ed143b51fafe5ff7f46bf71790cd
|
4
|
+
data.tar.gz: f5a371089e0306e5d65eebd711f38b8535b2612e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 37035c652d2994b2416d7026098f9646927d4d085255bf540f5ab0305b894786b80bff04fc3d7a5b0605ae9ccd475b51528b8e374d9d64d4ca6d8ea57292e92f
|
7
|
+
data.tar.gz: 2a4d7b4a2f1440b90c12c6cee8285c4684da467b5a7ed866cf16658e195d669bdb42efd67f329a6c06d0d5cd289049500fea80b436ca8ffa9cddd260196e6950
|
data/bin/task
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'clitasks'
|
5
|
+
|
6
|
+
command = ARGV.shift
|
7
|
+
|
8
|
+
case command
|
9
|
+
when 'rebuild'
|
10
|
+
CliTasks::Commands.rebuild
|
11
|
+
when 'create'
|
12
|
+
CliTasks::Commands.create *ARGV
|
13
|
+
CliTasks::Commands.rebuild
|
14
|
+
when 'edit'
|
15
|
+
CliTasks::Commands.edit *ARGV
|
16
|
+
CliTasks::Commands.rebuild
|
17
|
+
when 'search'
|
18
|
+
CliTasks::Commands.search *ARGV
|
19
|
+
CliTasks::Commands.rebuild
|
20
|
+
when 'start'
|
21
|
+
when 'finish'
|
22
|
+
when 'tag'
|
23
|
+
when 'comment'
|
24
|
+
when 'list'
|
25
|
+
CliTasks::Commands.list *ARGV
|
26
|
+
else
|
27
|
+
CliTasks::Commands.list *ARGV.unshift(command)
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module CliTasks
|
2
|
+
class Commands
|
3
|
+
class << self
|
4
|
+
def edit(*args)
|
5
|
+
files = grep(*args)
|
6
|
+
system(ENV['EDITOR'] || 'vim', *files)
|
7
|
+
end
|
8
|
+
|
9
|
+
def search(*args)
|
10
|
+
if (args[0] || '').strip =~ /-(s|-simple)/i
|
11
|
+
puts grep(*args.tap(&:shift))
|
12
|
+
else
|
13
|
+
Viewer.print(*grep(*args))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(*args)
|
18
|
+
name = args.join ' '
|
19
|
+
timestamp = Time.now.strftime('%Y%m%d%H%M%S')
|
20
|
+
filename = "./stories/index/#{timestamp}.rb"
|
21
|
+
|
22
|
+
FileUtils.mkdir_p("./stories/index")
|
23
|
+
checklog("Creating '#{filename}'"){ IO.write(filename, template(name)) }
|
24
|
+
checklog("Opening '#{filename}'"){ system(ENV['EDITOR'] || 'vim', filename) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def rebuild
|
28
|
+
LinkBuilder.all
|
29
|
+
end
|
30
|
+
|
31
|
+
def stories
|
32
|
+
@stories ||= World.instance.stories
|
33
|
+
end
|
34
|
+
|
35
|
+
def list(*args)
|
36
|
+
if args.any?
|
37
|
+
Viewer.print *args
|
38
|
+
else
|
39
|
+
Viewer.print 'stories/index/*'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def grep(*args)
|
46
|
+
args.inject(['stories/index']){|files,arg|
|
47
|
+
#pp "grep -ril '#{arg}' -- '#{files.join "' '"}'"
|
48
|
+
grep = `grep -ril '#{arg}' -- '#{files.join "' '"}'`
|
49
|
+
lines = grep.lines.map(&:chomp)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def checklog(msg, &block)
|
54
|
+
print "#{msg}..."
|
55
|
+
block.call
|
56
|
+
puts 'done'
|
57
|
+
end
|
58
|
+
|
59
|
+
def template(name)
|
60
|
+
data = <<-STORY
|
61
|
+
story %q(#{name}) do
|
62
|
+
status queued
|
63
|
+
points 1
|
64
|
+
created_by :unassigned
|
65
|
+
assigned_to :unassigned
|
66
|
+
tags *%w() # *%w(example example_two)
|
67
|
+
|
68
|
+
description <<-DESCRIPTION
|
69
|
+
DESCRIPTION
|
70
|
+
|
71
|
+
comment :author, <<-COMMENT
|
72
|
+
COMMENT
|
73
|
+
end
|
74
|
+
STORY
|
75
|
+
pattern = data.scan(/\A(\s+)/).uniq.min_by{|s| s.length }.first
|
76
|
+
data.gsub(/^#{pattern}/, '')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module CliTasks
|
2
|
+
class LinkBuilder
|
3
|
+
attr_reader :world
|
4
|
+
def initialize(path='stories')
|
5
|
+
@path = path
|
6
|
+
@world = World.instance
|
7
|
+
Runner.run [path, 'index'].join(?/)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.all
|
11
|
+
LinkBuilder.new.tap do |links|
|
12
|
+
links.remove_all_symlinks
|
13
|
+
links.by_tag
|
14
|
+
links.by_status
|
15
|
+
links.by_creator
|
16
|
+
links.by_assignment
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove_all_symlinks
|
21
|
+
Dir[ [@path, '**/*'].join(?/) ].each do |file|
|
22
|
+
next unless File.symlink?(file)
|
23
|
+
FileUtils.rm(file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_link(type, dir, story)
|
28
|
+
dir = sanitize(dir) || return
|
29
|
+
dest = File.join(@path, type, dir)
|
30
|
+
link story, dest
|
31
|
+
end
|
32
|
+
|
33
|
+
def by_tag
|
34
|
+
world.stories.each do |story|
|
35
|
+
story.tags.each do |tag|
|
36
|
+
create_link('tags', tag, story)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def by_status
|
42
|
+
world.stories.each do |story|
|
43
|
+
create_link('status', story.status, story)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def by_creator
|
48
|
+
world.stories.each do |story|
|
49
|
+
Array(story.created_by).each do |creator|
|
50
|
+
create_link('created_by', creator, story)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def by_assignment
|
56
|
+
world.stories.each do |story|
|
57
|
+
Array(story.assigned_to).each do |assignment|
|
58
|
+
create_link('assigned_to', assignment, story)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def sanitize(name)
|
66
|
+
return unless name.is_a?(String) || name.is_a?(Symbol)
|
67
|
+
String(name).gsub(/(\W|_)+/, '_')
|
68
|
+
end
|
69
|
+
|
70
|
+
def link(story, dest)
|
71
|
+
FileUtils.mkdir_p File.expand_path(dest)
|
72
|
+
src = Pathname.new(File.expand_path(story.file))
|
73
|
+
FileUtils.ln_s src.relative_path_from(Pathname.new(File.expand_path(dest))), File.join(dest, sanitize(story.name))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module CliTasks
|
2
|
+
class Runner
|
3
|
+
def self.run(*files)
|
4
|
+
world.reset
|
5
|
+
files.flat_map{|file|
|
6
|
+
Dir[File.directory?(file) && [file,'/**/*'].join || file]
|
7
|
+
}.map{|file|
|
8
|
+
load File.expand_path(file)
|
9
|
+
world.stories.last.file = file
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.world
|
14
|
+
@world ||= World.instance
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class SimpleDSL
|
2
|
+
class << self
|
3
|
+
def values(*names)
|
4
|
+
names.each do |name|
|
5
|
+
define_method(name) do
|
6
|
+
"#{name}".to_sym
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def fields(*names)
|
12
|
+
names.each do |name|
|
13
|
+
define_method(name) do |val|
|
14
|
+
instance_variable_set "@#{name}".to_sym, val
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def groups(*names)
|
20
|
+
names.each do |name|
|
21
|
+
define_method(name) do |*vals|
|
22
|
+
instance_variable_set "@#{name}".to_sym, vals
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def custom(*names, &block)
|
28
|
+
names.each do |name|
|
29
|
+
define_method(name, &block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CliTasks
|
2
|
+
class Story
|
3
|
+
attr_accessor :file
|
4
|
+
attr_reader :id, :status, :points, :name, :description
|
5
|
+
def initialize(builder)
|
6
|
+
builder.instance_variables.each{|name| instance_variable_set name, builder.instance_variable_get(name) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def id
|
10
|
+
@id ||= File.basename(file).sub(/[.]rb$/, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def tags
|
14
|
+
@tags ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def comments
|
18
|
+
@comments ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def created_by
|
22
|
+
@created_by ||= []
|
23
|
+
@created_by &&= Array(@created_by)
|
24
|
+
end
|
25
|
+
|
26
|
+
def assigned_to
|
27
|
+
@assigned_to ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.build(name, &block)
|
31
|
+
Story.new StoryReader.new(name, &block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def story(name, &block)
|
36
|
+
stories << Story.build(name, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def stories
|
40
|
+
World.instance.stories
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
extend CliTasks
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class StoryReader < SimpleDSL
|
2
|
+
def initialize(name, &block)
|
3
|
+
@name = name
|
4
|
+
instance_eval &block
|
5
|
+
end
|
6
|
+
|
7
|
+
values :queued, :started, :finished,
|
8
|
+
:accepted, :rejected, :delivered
|
9
|
+
|
10
|
+
fields :id, :status, :points, :description, :created_by
|
11
|
+
groups :assigned_to, :tags
|
12
|
+
custom :comment do |author, body| (@comments ||= []) << {author: author, body: body} end
|
13
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module CliTasks
|
2
|
+
class Viewer
|
3
|
+
def initialize(*args)
|
4
|
+
@files = args
|
5
|
+
if args.any?
|
6
|
+
Runner.run *args
|
7
|
+
else
|
8
|
+
Runner.run 'stories/index/*'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.print(*args)
|
13
|
+
new(*args).print
|
14
|
+
end
|
15
|
+
|
16
|
+
def print
|
17
|
+
puts header
|
18
|
+
|
19
|
+
puts stories.sort_by{|s| s.name }.inject({}){|hash,s|
|
20
|
+
hash.merge( s.status => hash.fetch(s.status, []) << s )
|
21
|
+
}.map{|status,group|
|
22
|
+
[separator] + group.map{|s| story(s) }
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def header
|
27
|
+
sprintf(" %-10s | %-20s | %-6s | %-60s | %-s", :status, :id, :points, :name, :tags)
|
28
|
+
end
|
29
|
+
|
30
|
+
def separator
|
31
|
+
sprintf(" %-10s | %-20s | %-6s | %-60s | %-s", ?-*10, ?-*20, ?-*6, ?-*60, ?-*20)
|
32
|
+
end
|
33
|
+
|
34
|
+
def story(s)
|
35
|
+
sprintf(" %-10s | %-20s | %-6s | %-60s | %-s", s.status, s.id, ?* * s.points.to_i, s.name.slice(0,60), Array(s.tags).join(', '))
|
36
|
+
end
|
37
|
+
|
38
|
+
def stories
|
39
|
+
@stories ||= World.instance.stories
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/clitasks.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'pp'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
require 'clitasks/world'
|
7
|
+
require 'clitasks/simple_dsl'
|
8
|
+
require 'clitasks/story_reader'
|
9
|
+
require 'clitasks/story'
|
10
|
+
require 'clitasks/runner'
|
11
|
+
require 'clitasks/link_builder'
|
12
|
+
require 'clitasks/viewer'
|
13
|
+
require 'clitasks/commands'
|
14
|
+
|
15
|
+
module CliTasks
|
16
|
+
end
|
17
|
+
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clitasks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua "unixsuperhero" Toyota
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: File-based, command-line project manager.
|
14
|
+
email: jearsh@gmail.com
|
15
|
+
executables:
|
16
|
+
- task
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/clitasks.rb
|
21
|
+
- lib/clitasks/commands.rb
|
22
|
+
- lib/clitasks/link_builder.rb
|
23
|
+
- lib/clitasks/runner.rb
|
24
|
+
- lib/clitasks/simple_dsl.rb
|
25
|
+
- lib/clitasks/story.rb
|
26
|
+
- lib/clitasks/story_reader.rb
|
27
|
+
- lib/clitasks/viewer.rb
|
28
|
+
- lib/clitasks/world.rb
|
29
|
+
- bin/task
|
30
|
+
homepage: http://github.com/unixsuperhero/clitasks
|
31
|
+
licenses:
|
32
|
+
- MIT
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 2.0.3
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: CLI Tasks
|
54
|
+
test_files: []
|