watnow 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +93 -0
- data/Rakefile +2 -0
- data/bin/watnow +7 -0
- data/lib/watnow/annotation/annotation.rb +41 -0
- data/lib/watnow/annotation/annotation_line.rb +54 -0
- data/lib/watnow/config.rb +51 -0
- data/lib/watnow/option_parser.rb +53 -0
- data/lib/watnow/version.rb +3 -0
- data/lib/watnow.rb +171 -0
- data/watnow.gemspec +20 -0
- metadata +75 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Etienne Lemay
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Watnow
|
2
|
+
|
3
|
+
<b>Watnow</b> finds and lists your project TODOs and FIXMEs.<br>
|
4
|
+
It basically does what the Rails’ `rake notes` does, but in a more generic way.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
```sh
|
8
|
+
$ gem install watnow
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```sh
|
14
|
+
$ watnow
|
15
|
+
```
|
16
|
+
|
17
|
+
### Help
|
18
|
+
```sh
|
19
|
+
$ watnow --help
|
20
|
+
|
21
|
+
Usage: watnow [options]
|
22
|
+
|
23
|
+
-h, --help show this message
|
24
|
+
-v, --version display version
|
25
|
+
-d, --directory DIR directory DIR to scan (defaults: ./)
|
26
|
+
|
27
|
+
watnow commands:
|
28
|
+
open <ID> open annotation ID in your editor
|
29
|
+
remove <ID> remove annotation ID
|
30
|
+
```
|
31
|
+
|
32
|
+
## Commands
|
33
|
+
### open
|
34
|
+
Opens an annotation in your $EDITOR focused on the annotation line.
|
35
|
+
```sh
|
36
|
+
$ watnow open 13
|
37
|
+
```
|
38
|
+
|
39
|
+
### remove
|
40
|
+
Removes the annotation line from its file.<br>
|
41
|
+
(Make sure there is nothing else on that line)
|
42
|
+
```sh
|
43
|
+
$ watnow remove 13
|
44
|
+
```
|
45
|
+
|
46
|
+
## Features
|
47
|
+
### Mentions
|
48
|
+
```rb
|
49
|
+
# TODO @rafBM: Update user form
|
50
|
+
# TODO Update user controller @rafBM
|
51
|
+
```
|
52
|
+
```sh
|
53
|
+
[ 2 ] TODO: Update user form [ @rafBM ]
|
54
|
+
[ 1 ] TODO: Update user controller [ @rafBM ]
|
55
|
+
```
|
56
|
+
|
57
|
+
### Priority
|
58
|
+
Exclamation mark (!) preceded by a whitespace. (`/\s(!+)\s?/`)
|
59
|
+
|
60
|
+
```rb
|
61
|
+
# TODO !!!: This is level 3 urgent
|
62
|
+
# TODO @rafBM: Just do it !
|
63
|
+
# TODO: This is not a priority!!
|
64
|
+
# TODO !!!!!!!!!!!!! @EtienneLem: This is a nicolas-cage-level urgent task
|
65
|
+
```
|
66
|
+
```sh
|
67
|
+
[ 3 ] TODO: This is not a priority!!
|
68
|
+
[ 2 ] TODO: Just do it [ @rafBM - ! ]
|
69
|
+
[ 1 ] TODO: This is level 3 urgent [ !!! ]
|
70
|
+
[ 4 ] TODO: This is a nicolas-cage-level urgent task [ @EtienneLem - !!!!!!!!!!!!! ]
|
71
|
+
```
|
72
|
+
|
73
|
+
### Super color-friendly
|
74
|
+
(Seriously, I’m open to color suggestions…)
|
75
|
+
![color-friendly](https://s3.amazonaws.com/watnow/colors.png)
|
76
|
+
|
77
|
+
## Watnow config
|
78
|
+
Override defaults in `~/.watnowconfig`. Supported options are:
|
79
|
+
```
|
80
|
+
username (String) | A username so that you can be mentioned in TODOs | Default: ''
|
81
|
+
color (Boolean) | Enable/disable colored output | Default: true
|
82
|
+
patterns (Array) | An array of string/regex that you want to monitor | Default: []
|
83
|
+
```
|
84
|
+
|
85
|
+
Use YAML syntax:
|
86
|
+
```
|
87
|
+
username: EtienneLem
|
88
|
+
color: false
|
89
|
+
patterns: [potato, ba(na)+]
|
90
|
+
```
|
91
|
+
|
92
|
+
## Contribution
|
93
|
+
My Ruby skills are far from exemplary, please teach me.
|
data/Rakefile
ADDED
data/bin/watnow
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Watnow
|
2
|
+
# An Annotation is basically a group of AnnotationLine
|
3
|
+
class Annotation
|
4
|
+
|
5
|
+
@@id = 0
|
6
|
+
@@instances = []
|
7
|
+
|
8
|
+
attr_accessor :id, :file, :lines, :priority
|
9
|
+
|
10
|
+
# An ORM-like method that returns all Annotation instances
|
11
|
+
def self.all
|
12
|
+
@@instances
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(opts)
|
16
|
+
@priority = 0
|
17
|
+
@file = opts[:file]
|
18
|
+
@lines = set_lines(opts[:lines])
|
19
|
+
|
20
|
+
# Auto increment instances id
|
21
|
+
# Push instance into a class array
|
22
|
+
@id = @@id += 1
|
23
|
+
@@instances << self
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Loop through lines data and create AnnotationLine instance
|
29
|
+
# Send self so that an AnnotationLine knows its Annotation and vice versa
|
30
|
+
def set_lines(lines)
|
31
|
+
results = []
|
32
|
+
|
33
|
+
lines.each do |line|
|
34
|
+
results << AnnotationLine.new(line, self)
|
35
|
+
end
|
36
|
+
|
37
|
+
results
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Watnow
|
2
|
+
class AnnotationLine
|
3
|
+
|
4
|
+
@@id = 0
|
5
|
+
@@instances = []
|
6
|
+
@@tag_length = 0
|
7
|
+
|
8
|
+
attr_accessor :id, :lineno, :tag, :priority, :mention, :message, :annotation
|
9
|
+
|
10
|
+
# An ORM-like find method that returns an AnnotationLine instance
|
11
|
+
def self.find(id)
|
12
|
+
@@instances.each do |instance|
|
13
|
+
return instance if instance.id == id
|
14
|
+
end
|
15
|
+
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns longest tag length
|
20
|
+
# Used to format output
|
21
|
+
def self.tag_length
|
22
|
+
@@tag_length
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(opts, annotation)
|
26
|
+
@lineno = opts[:lineno]
|
27
|
+
@tag = opts[:tag]
|
28
|
+
@priority = opts[:priority] || 0
|
29
|
+
@mention = opts[:mention] || ''
|
30
|
+
@message = opts[:message]
|
31
|
+
@annotation = annotation
|
32
|
+
|
33
|
+
@annotation.priority = @priority if @priority > @annotation.priority
|
34
|
+
|
35
|
+
# Auto increment instances id
|
36
|
+
# Push instance into a class array
|
37
|
+
@id = @@id += 1
|
38
|
+
@@instances << self
|
39
|
+
|
40
|
+
# Update class’ tag_length to the longest tag
|
41
|
+
@@tag_length = @tag.length if @tag.length > @@tag_length
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns an array of "meta data"
|
45
|
+
# Namely: The AnnotationLine mention and priority
|
46
|
+
def meta_data
|
47
|
+
data = []
|
48
|
+
data << "@#{@mention}" unless @mention.empty?
|
49
|
+
data << Array.new(@priority + 1).join('!') if @priority > 0
|
50
|
+
data
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Watnow::Config
|
4
|
+
|
5
|
+
# Default constants
|
6
|
+
FOLDER_IGNORE = %w(tmp node_modules db public log)
|
7
|
+
FILE_EXTENSION_IGNORE = %w(tmproj markdown md txt)
|
8
|
+
PATTERNS = %w(TODO FIXME)
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
defaults = {
|
12
|
+
'color' => true,
|
13
|
+
'folder_ignore' => [],
|
14
|
+
'file_extension_ignore' => [],
|
15
|
+
'patterns' => [],
|
16
|
+
'username' => ''
|
17
|
+
}
|
18
|
+
|
19
|
+
# Parse YAML config file (~/.watnowconfig)
|
20
|
+
parser = YamlParser.new
|
21
|
+
custom_options = parser.parse
|
22
|
+
|
23
|
+
# Merge defaults with custom options
|
24
|
+
# Add default constants
|
25
|
+
options = defaults.merge(custom_options)
|
26
|
+
options['folder_ignore'].concat(FOLDER_IGNORE)
|
27
|
+
options['file_extension_ignore'].concat(FILE_EXTENSION_IGNORE)
|
28
|
+
options['patterns'].concat(PATTERNS)
|
29
|
+
|
30
|
+
# Generate singleton methods with options keys for quick access
|
31
|
+
# i.e. self.color, self.patterns, self.username, etc
|
32
|
+
options.each do |option|
|
33
|
+
define_singleton_method option[0] do
|
34
|
+
option[1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Simple YAML parser
|
40
|
+
# Returns empty object if no file found
|
41
|
+
class YamlParser
|
42
|
+
def parse
|
43
|
+
begin
|
44
|
+
YAML.load_file("#{ENV['HOME']}/.watnowconfig")
|
45
|
+
rescue
|
46
|
+
{}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Watnow
|
4
|
+
# Home made Option parser built on top of Ruby’s optparse
|
5
|
+
class OptParser
|
6
|
+
|
7
|
+
def self.parse(args)
|
8
|
+
# Defaults
|
9
|
+
options = {}
|
10
|
+
options[:directory] = '.'
|
11
|
+
|
12
|
+
opts = OptionParser.new('', 24, ' ') do |opts|
|
13
|
+
opts.separator ' Usage: watnow [options]'
|
14
|
+
opts.separator ''
|
15
|
+
|
16
|
+
# Help
|
17
|
+
opts.on('-h', '--help', 'show this message') do
|
18
|
+
puts opts
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
# Version
|
23
|
+
opts.on('-v', '--version', 'display version') do
|
24
|
+
puts VERSION
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
# Directory
|
29
|
+
opts.on('-d', '--directory DIR', 'directory DIR to scan (defaults: ./)') do |d|
|
30
|
+
options[:directory] = d
|
31
|
+
end
|
32
|
+
|
33
|
+
# Commands
|
34
|
+
opts.separator ''
|
35
|
+
opts.separator ' watnow commands:'
|
36
|
+
opts.separator ' open <ID> open annotation ID in your editor'
|
37
|
+
opts.separator ' remove <ID> remove annotation ID'
|
38
|
+
|
39
|
+
options[:open] = get_option_value('open', args)
|
40
|
+
options[:remove] = get_option_value('remove', args)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.parse!(args)
|
45
|
+
options
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.get_option_value(option, args)
|
49
|
+
args.include?(option) ? args[args.index(option) + 1] : nil
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
data/lib/watnow.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'watnow/version'
|
2
|
+
require 'watnow/config'
|
3
|
+
require 'watnow/option_parser'
|
4
|
+
require 'watnow/annotation/annotation'
|
5
|
+
require 'watnow/annotation/annotation_line'
|
6
|
+
require 'colored'
|
7
|
+
|
8
|
+
module Watnow
|
9
|
+
class Extractor
|
10
|
+
include Watnow::Config
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
# Parse options and scan given directory
|
14
|
+
options = OptParser.parse(ARGV)
|
15
|
+
scan(options[:directory])
|
16
|
+
|
17
|
+
# If open command is parsed (`watnow open 13`)
|
18
|
+
if options[:open]
|
19
|
+
id = Integer(options[:open])
|
20
|
+
annotation_line = AnnotationLine.find(id)
|
21
|
+
open_file_at_line(annotation_line.annotation.file, annotation_line.lineno)
|
22
|
+
|
23
|
+
# If remove command is parsed (`watnow remove 13`)
|
24
|
+
elsif options[:remove]
|
25
|
+
id = Integer(options[:remove])
|
26
|
+
annotation_line = AnnotationLine.find(id)
|
27
|
+
remove_line_of_file(annotation_line.annotation.file, annotation_line.lineno)
|
28
|
+
|
29
|
+
# No specific command parsed. Output the annotations list
|
30
|
+
else
|
31
|
+
output(Annotation.all)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Recursively scan given directory
|
38
|
+
# Ignore folders and files from Config
|
39
|
+
# Create a new Annotation when data si found
|
40
|
+
def scan(dir, annotations=[])
|
41
|
+
Dir.glob("#{dir}/*") do |path|
|
42
|
+
next if File.basename(path) =~ /(#{Config.folder_ignore.join('|')})$/
|
43
|
+
|
44
|
+
if File.directory? path
|
45
|
+
scan(path, annotations)
|
46
|
+
else
|
47
|
+
begin
|
48
|
+
next if File.extname(path) =~ /(#{Config.file_extension_ignore.join('|')})$/
|
49
|
+
content = read_file(path, /(#{Config.patterns.join('|')})/i)
|
50
|
+
Annotation.new(content) if content
|
51
|
+
rescue
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Read a file line by line and look for given patterns
|
59
|
+
def read_file(file, patterns)
|
60
|
+
lineno = 0
|
61
|
+
|
62
|
+
result = File.readlines(file).inject([]) do |list, line|
|
63
|
+
lineno += 1
|
64
|
+
next list unless line =~ patterns
|
65
|
+
|
66
|
+
# Pattern is found, save the tag
|
67
|
+
tag = line.slice!($1)
|
68
|
+
|
69
|
+
# Look for priority
|
70
|
+
# Exclamation mark (!) preceded by a whitespace
|
71
|
+
priority = line.slice!(/\s(!+)\s?/)
|
72
|
+
priority = $1 ? $1.length : 0
|
73
|
+
|
74
|
+
# Look for mention
|
75
|
+
# Any word character preceded by @
|
76
|
+
mention = line.slice!(/\s@(\w+)\s*/)
|
77
|
+
mention = $1
|
78
|
+
|
79
|
+
# We assume the message starts with any word character
|
80
|
+
message = line.slice!(/(\w.*)/)
|
81
|
+
message = $1
|
82
|
+
|
83
|
+
# Push data into result
|
84
|
+
# Remove closing comment characters that we didn’t extract from regexs
|
85
|
+
list << {
|
86
|
+
:lineno => lineno,
|
87
|
+
:tag => tag,
|
88
|
+
:priority => priority,
|
89
|
+
:mention => mention,
|
90
|
+
:message => message.gsub(/\s*(\*\/|-->|%>)$/, '')
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns content that is sent to Annotation
|
95
|
+
result.empty? ? nil : { :file => file, :lines => result }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Open a file with the user’s $EDITOR
|
99
|
+
# Automatically focus the annotation line number
|
100
|
+
# Supported editors are TextMate, Vim & Sublime Text
|
101
|
+
def open_file_at_line(filename, line)
|
102
|
+
command = filename
|
103
|
+
|
104
|
+
if ENV['EDITOR'] =~ /mate/
|
105
|
+
command = "#{filename} --line #{line}"
|
106
|
+
elsif ENV['EDITOR'] =~ /vi|vim/
|
107
|
+
command = "+#{line} #{filename}"
|
108
|
+
elsif ENV['EDITOR'] =~ /subl/
|
109
|
+
command = "#{filename}:#{line}"
|
110
|
+
end
|
111
|
+
|
112
|
+
Kernel.system("$EDITOR #{command}")
|
113
|
+
end
|
114
|
+
|
115
|
+
# Remove line from given file
|
116
|
+
def remove_line_of_file(filename, line)
|
117
|
+
file = File.readlines(filename)
|
118
|
+
file.delete_at(line - 1)
|
119
|
+
File.open(filename, 'w+') {|f| f.write file.join() }
|
120
|
+
end
|
121
|
+
|
122
|
+
def output(annotations)
|
123
|
+
# Sort annotations (file) by priority then by id
|
124
|
+
annotations.sort_by! { |a| [a.priority, -a.id] }
|
125
|
+
|
126
|
+
annotations.each do |annotation|
|
127
|
+
# Remove './' prefix in filenames
|
128
|
+
filename = annotation.file.gsub(/^\.\//, '')
|
129
|
+
|
130
|
+
# Display the filename
|
131
|
+
display_line "\n#{filename}", 'magenta'
|
132
|
+
|
133
|
+
# Sort annotation lines by priority DESC
|
134
|
+
# Higher priority is lower in the list
|
135
|
+
annotation.lines.sort! { |a,b| a.priority <=> b.priority }
|
136
|
+
annotation.lines.each do |annotation_line|
|
137
|
+
# Make sure all tags use the same (white)space
|
138
|
+
tag_spaces_count = AnnotationLine.tag_length - annotation_line.tag.length
|
139
|
+
tag_spaces = Array.new(tag_spaces_count + 1).join(' ')
|
140
|
+
|
141
|
+
# Boolean. True if current user is being mentioned in the annotation line
|
142
|
+
is_mentioned = (annotation_line.mention.downcase == Config.username.downcase)
|
143
|
+
|
144
|
+
# The actual outputting
|
145
|
+
display_text '[ ', 'green', is_mentioned
|
146
|
+
display_text annotation_line.id, 'cyan'
|
147
|
+
display_text " ] #{' ' if annotation_line.id < 10}", 'green', is_mentioned
|
148
|
+
display_text "#{annotation_line.tag}: #{tag_spaces}#{annotation_line.message}", 'green', is_mentioned
|
149
|
+
if annotation_line.meta_data.size > 0
|
150
|
+
display_text ' [ ', 'green', is_mentioned
|
151
|
+
display_text annotation_line.meta_data.join(' - '), 'cyan'
|
152
|
+
display_text ' ]', 'green', is_mentioned
|
153
|
+
end
|
154
|
+
display_line ""
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# display_text followed by a newline
|
160
|
+
def display_line(msg, color=nil, color_condition=true)
|
161
|
+
display_text "#{msg}\n", color, color_condition
|
162
|
+
end
|
163
|
+
|
164
|
+
# Output helper. Print text in color if color_condition is truthy
|
165
|
+
def display_text(msg, color=nil, color_condition=true)
|
166
|
+
output = color && color_condition && Config.color ? "#{msg}".send(color) : msg
|
167
|
+
STDOUT.write "#{output}"
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
data/watnow.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/watnow/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Etienne Lemay"]
|
6
|
+
gem.email = ["etienne@heliom.ca"]
|
7
|
+
gem.homepage = "https://github.com/etiennelem/watnow"
|
8
|
+
|
9
|
+
gem.description = "Watnow finds and lists your project todo and fixme"
|
10
|
+
gem.summary = gem.description
|
11
|
+
gem.version = Watnow::VERSION
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = "watnow"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.add_dependency("colored", "~> 1.2")
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: watnow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Etienne Lemay
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: colored
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.2'
|
30
|
+
description: Watnow finds and lists your project todo and fixme
|
31
|
+
email:
|
32
|
+
- etienne@heliom.ca
|
33
|
+
executables:
|
34
|
+
- watnow
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- bin/watnow
|
44
|
+
- lib/watnow.rb
|
45
|
+
- lib/watnow/annotation/annotation.rb
|
46
|
+
- lib/watnow/annotation/annotation_line.rb
|
47
|
+
- lib/watnow/config.rb
|
48
|
+
- lib/watnow/option_parser.rb
|
49
|
+
- lib/watnow/version.rb
|
50
|
+
- watnow.gemspec
|
51
|
+
homepage: https://github.com/etiennelem/watnow
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.23
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Watnow finds and lists your project todo and fixme
|
75
|
+
test_files: []
|