what_now 0.0.5 → 0.0.6
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.md +15 -7
- data/bin/wnow +21 -5
- data/lib/file_filter.rb +73 -0
- data/lib/what_now.rb +3 -10
- data/spec/file_filter_spec.rb +188 -0
- data/spec/what_now_spec.rb +6 -4
- data/what_now.gemspec +2 -1
- metadata +18 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 544af77f51167e74302cbd4bf98ca400d2b9a695
|
4
|
+
data.tar.gz: d89bba664223614756de397c960463218e483f36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f584e61ff6da4c4d6fcd99da6740086bff4cf0e3ffd10ef490b0268d6aed26d2bce98eee9a9586b0bf87874eaa23a552d5fa2a347c23e637c87944c02734c3c
|
7
|
+
data.tar.gz: 51ccf2fb7e922057fe0fdd0d2cce6c35228bcace881fef56572c87d0ccdbdfe967fbbc1c716ebb1288a58151e5709828211e93d8e55a6e9c39da1fdce85a2695
|
data/README.md
CHANGED
@@ -26,10 +26,18 @@ Will return all the todos in the following format inside files:
|
|
26
26
|
|
27
27
|
* TODO this is the text
|
28
28
|
|
29
|
-
Where 'this is the text' will be returned, together with the path and line number
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
Where 'this is the text' will be returned, together with the relative path and line number
|
30
|
+
|
31
|
+
The output is colored, but if redirected to a non TTY device, a simpler, colorless format
|
32
|
+
will be used.
|
33
|
+
|
34
|
+
Options
|
35
|
+
-------
|
36
|
+
* *--dir, -d*: Specify the directory in which to search the TODO's. It can be an absolute
|
37
|
+
path of anyhwere in the system, or a relative path to the current directory.
|
38
|
+
* *--ext, -e*: Specify the extension of the files to consider. You can pass it with or without
|
39
|
+
the dot (.rb or rb are both valid).
|
40
|
+
* *--regex, -r*: Specify the regular expression (Perl-like) that the file names
|
41
|
+
must match.
|
42
|
+
* *--ignorecase, -i*: When passed, this options matches both the strings *TODO* and *todo*.
|
43
|
+
By default, this options is deactivated.
|
data/bin/wnow
CHANGED
@@ -2,21 +2,37 @@
|
|
2
2
|
require 'thor'
|
3
3
|
require 'colorize'
|
4
4
|
require 'what_now'
|
5
|
+
require 'file_filter'
|
6
|
+
require 'pathname'
|
5
7
|
|
6
8
|
class Wnow < Thor
|
9
|
+
include Filtering
|
7
10
|
default_task :find
|
8
11
|
|
9
12
|
desc 'find', 'search files in directory for todo elements (default command)'
|
10
13
|
option :dir, aliases: '-d'
|
11
14
|
option :ext, aliases: '-e'
|
15
|
+
option :regex, aliases: '-r'
|
12
16
|
option :ignorecase, aliases: '-i'
|
13
17
|
def find
|
18
|
+
# Directory handling
|
19
|
+
current_dir = Pathname.getwd
|
14
20
|
dir = options[:dir] || Dir.pwd
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
absolute_dir = Pathname.new(dir).expand_path.to_s
|
22
|
+
|
23
|
+
filter = NoDirectories
|
24
|
+
.chain(NoBinaries)
|
25
|
+
.chain(OnlyDirectory.new absolute_dir)
|
26
|
+
filter.chain(OnlyExtension.new options[:ext]) if options[:ext]
|
27
|
+
filter.chain(MatchRegex.new options[:regex]) if options[:regex]
|
28
|
+
|
29
|
+
relative_paths = Dir[absolute_dir + '/**/*'].map do |p|
|
30
|
+
Pathname.new(p).relative_path_from(current_dir).to_s
|
31
|
+
end
|
32
|
+
targets = filter.filter relative_paths
|
33
|
+
|
34
|
+
creator = TodoCreator.new(ignorecase: options[:ignorecase], pretty: STDOUT.tty?)
|
35
|
+
TodoFinder.new(targets, creator).find.each do |todo|
|
20
36
|
puts todo
|
21
37
|
puts if STDOUT.tty?
|
22
38
|
end
|
data/lib/file_filter.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Module for handling filtering of
|
2
|
+
# files
|
3
|
+
|
4
|
+
require 'ptools'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module Filtering
|
8
|
+
class Filter
|
9
|
+
attr_reader :predicates
|
10
|
+
|
11
|
+
def initialize &predicate
|
12
|
+
@predicates = [predicate]
|
13
|
+
end
|
14
|
+
|
15
|
+
def apply file
|
16
|
+
@predicates.reduce(true) do |result, p|
|
17
|
+
result && p.call(file)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def chain other=nil
|
22
|
+
raise ArgumentError if (not other and not block_given?)
|
23
|
+
@predicates += other.predicates if other
|
24
|
+
@predicates << Proc.new if block_given?
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def filter files
|
29
|
+
files.keep_if do |f|
|
30
|
+
self.apply f
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
NoDirectories = Filter.new do |path|
|
36
|
+
not File.directory? path
|
37
|
+
end
|
38
|
+
|
39
|
+
NoBinaries = Filter.new do |path|
|
40
|
+
not File.binary? path
|
41
|
+
end
|
42
|
+
|
43
|
+
class OnlyDirectory < Filter
|
44
|
+
def initialize subdirectory
|
45
|
+
base = Pathname.new(subdirectory).expand_path.to_s
|
46
|
+
@predicates = []
|
47
|
+
@predicates << proc do |path|
|
48
|
+
file = Pathname.new(path).expand_path.to_s
|
49
|
+
file.start_with? base
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class OnlyExtension < Filter
|
55
|
+
def initialize ext
|
56
|
+
extension = ext.start_with?('.') ? ext[1..-1] : ext
|
57
|
+
@predicates = []
|
58
|
+
@predicates << proc do |path|
|
59
|
+
path.match(/\.#{extension}$/i) ? true : false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class MatchRegex < Filter
|
65
|
+
def initialize regex
|
66
|
+
@predicates = []
|
67
|
+
@predicates << proc do |path|
|
68
|
+
path.match(regex) ? true : false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/lib/what_now.rb
CHANGED
@@ -13,22 +13,15 @@ class TodoCreator
|
|
13
13
|
def match(line, path, line_number)
|
14
14
|
regex = @ignorecase ? /TODO:?\s*(.+)$/i : /TODO:?\s*(.+)$/
|
15
15
|
text = regex.match(line)
|
16
|
-
@todo_class.new(text[1],
|
16
|
+
@todo_class.new(text[1], path, line_number) if text
|
17
17
|
rescue ArgumentError
|
18
18
|
nil
|
19
19
|
end
|
20
|
-
|
21
|
-
private
|
22
|
-
def shortened_path(path)
|
23
|
-
path[Dir.pwd.length+1..path.length]
|
24
|
-
end
|
25
20
|
end
|
26
21
|
|
27
22
|
class TodoFinder
|
28
|
-
def initialize(
|
29
|
-
@paths =
|
30
|
-
File.directory?(path) || File.binary?(path)
|
31
|
-
end
|
23
|
+
def initialize(paths, creator)
|
24
|
+
@paths = paths
|
32
25
|
@creator = creator
|
33
26
|
end
|
34
27
|
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'fakefs/safe'
|
5
|
+
|
6
|
+
module FakeFS
|
7
|
+
class File
|
8
|
+
def self.binary? file
|
9
|
+
file == '/sample/d2/f3'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
FileFilter = Filtering::Filter
|
15
|
+
|
16
|
+
describe FileFilter do
|
17
|
+
subject do
|
18
|
+
FileFilter.new do |file|
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'public interface' do
|
24
|
+
it 'must respond to apply' do
|
25
|
+
subject.must_respond_to :apply
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'must respond to chain' do
|
29
|
+
subject.must_respond_to :chain
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'must respond to filter' do
|
33
|
+
subject.must_respond_to :filter
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#apply' do
|
38
|
+
it 'is expected to return result of predicate' do
|
39
|
+
subject.apply(nil).must_equal true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#chain' do
|
44
|
+
subject do
|
45
|
+
FileFilter.new do |x|
|
46
|
+
x > 0
|
47
|
+
end.chain do |x|
|
48
|
+
x % 2 == 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns an instance of FileFilter' do
|
53
|
+
subject.must_be_instance_of FileFilter
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'applies all filters when called' do
|
57
|
+
subject.filter([-2, -1, 0, 1, 2, 3, 4]).must_equal [2, 4]
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'with no arguments' do
|
61
|
+
it 'raises an exception' do
|
62
|
+
proc do
|
63
|
+
FileFilter.new do
|
64
|
+
true
|
65
|
+
end.chain
|
66
|
+
end.must_raise ArgumentError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'with instance of filter' do
|
71
|
+
subject do
|
72
|
+
f1 = FileFilter.new do |f|
|
73
|
+
f % 2 == 0
|
74
|
+
end
|
75
|
+
FileFilter.new do |f|
|
76
|
+
f > 0
|
77
|
+
end.chain f1
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns an instance of Filter' do
|
81
|
+
subject.chain(FileFilter.new { |x| x > 0 }).must_be_instance_of FileFilter
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'applies all filters when called' do
|
85
|
+
[-2, -1, 0, 1, 2, 3, 4].keep_if do |n|
|
86
|
+
subject.apply(n)
|
87
|
+
end.must_equal [2, 4]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#filter' do
|
93
|
+
subject do
|
94
|
+
FileFilter.new do |x|
|
95
|
+
x > 2
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'correctly filters the elements' do
|
100
|
+
subject.filter([-2, -1, 0, 1, 2, 3, 4]).must_equal [3, 4]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'specific filters' do
|
106
|
+
before do
|
107
|
+
FakeFS.activate!
|
108
|
+
FileUtils.mkdir_p 'sample/d1'
|
109
|
+
FileUtils.mkdir_p 'sample/d2'
|
110
|
+
FileUtils.touch 'sample/d1/f1.rb'
|
111
|
+
FileUtils.touch 'sample/d1/f2_rb'
|
112
|
+
FileUtils.touch 'sample/d2/f3'
|
113
|
+
end
|
114
|
+
|
115
|
+
after do
|
116
|
+
FakeFS.deactivate!
|
117
|
+
end
|
118
|
+
|
119
|
+
let :paths do
|
120
|
+
Dir['sample/**/*']
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'directory filter' do
|
124
|
+
subject do
|
125
|
+
Filtering::NoDirectories
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'only returns files' do
|
129
|
+
subject.filter(paths).sort!.must_equal ['/sample/d1/f1.rb', '/sample/d1/f2_rb', '/sample/d2/f3'].sort!
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'binary filter' do
|
134
|
+
subject do
|
135
|
+
Filtering::NoBinaries
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'only returns non-binaries' do
|
139
|
+
subject.filter(paths).wont_include '/sample/d2/f3'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'directory filter' do
|
144
|
+
subject do
|
145
|
+
Filtering::OnlyDirectory.new '/sample/d1'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'only returns elements in given subdirectory' do
|
149
|
+
subject.filter(paths).sort!.must_equal ['/sample/d1', '/sample/d1/f1.rb', '/sample/d1/f2_rb'].sort!
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'extension filter' do
|
154
|
+
subject do
|
155
|
+
Filtering::OnlyExtension.new 'rb'
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'only returns elements with the given extension' do
|
159
|
+
subject.filter(paths).sort!.must_equal ['/sample/d1/f1.rb']
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'still returns extension when extension specified with dot' do
|
163
|
+
Filtering::OnlyExtension.new('.rb').filter(paths).must_equal ['/sample/d1/f1.rb']
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'does not match a file that ends with same letter as extension' do
|
167
|
+
subject.filter(paths).wont_include '/sample/d1/f2_rb'
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'treats the extension case insensitively' do
|
171
|
+
Filtering::OnlyExtension.new('RB').filter(paths).must_equal ['/sample/d1/f1.rb']
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'regex filter' do
|
176
|
+
subject do
|
177
|
+
Filtering::MatchRegex.new(/f[0-9]/)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'only returns elements that match regular expression' do
|
181
|
+
subject.filter(paths).sort!.must_equal ['/sample/d1/f1.rb', '/sample/d1/f2_rb', '/sample/d2/f3'].sort!
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'accepts a string as a regular expression' do
|
185
|
+
Filtering::MatchRegex.new('f[0-9]').filter(paths).sort!.must_equal ['/sample/d1/f1.rb', '/sample/d1/f2_rb', '/sample/d2/f3'].sort!
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
data/spec/what_now_spec.rb
CHANGED
@@ -56,8 +56,8 @@ end
|
|
56
56
|
describe TodoFinder do
|
57
57
|
describe 'search single file' do
|
58
58
|
subject do
|
59
|
-
|
60
|
-
TodoFinder.new(
|
59
|
+
paths = Dir[File.dirname(__FILE__) + '/example_file.txt']
|
60
|
+
TodoFinder.new(paths, TodoCreator.new).find
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'found 2 todos' do
|
@@ -74,15 +74,17 @@ describe TodoFinder do
|
|
74
74
|
|
75
75
|
describe 'search with a pattern' do
|
76
76
|
it 'considers only specified pattern' do
|
77
|
+
paths = Dir[File.dirname(__FILE__)+'/**/*.txt']
|
77
78
|
results = TodoFinder.new(
|
78
|
-
|
79
|
+
paths,
|
79
80
|
TodoCreator.new).find
|
80
81
|
results.length.must_equal 2
|
81
82
|
end
|
82
83
|
|
83
84
|
it 'returns empty array if nothing was found' do
|
85
|
+
paths = Dir[File.dirname(__FILE__)+'/**/*.mooo']
|
84
86
|
results = TodoFinder.new(
|
85
|
-
|
87
|
+
paths,
|
86
88
|
TodoCreator.new).find
|
87
89
|
results.must_equal []
|
88
90
|
end
|
data/what_now.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'what_now'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.6'
|
4
4
|
s.date = '2014-02-27'
|
5
5
|
s.summary = 'Find todo comments in your code'
|
6
6
|
s.description = 'Executable for finding todo comments on directories'
|
@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
|
|
19
19
|
|
20
20
|
s.add_development_dependency 'minitest-reporters'
|
21
21
|
s.add_development_dependency 'rake'
|
22
|
+
s.add_development_dependency 'fakefs'
|
22
23
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: what_now
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edgar Cabrera
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fakefs
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Executable for finding todo comments on directories
|
84
98
|
email: edgar@cafeinacode.com
|
85
99
|
executables:
|
@@ -90,9 +104,11 @@ files:
|
|
90
104
|
- LICENSE
|
91
105
|
- README.md
|
92
106
|
- bin/wnow
|
107
|
+
- lib/file_filter.rb
|
93
108
|
- lib/todo.rb
|
94
109
|
- lib/what_now.rb
|
95
110
|
- spec/example_file.txt
|
111
|
+
- spec/file_filter_spec.rb
|
96
112
|
- spec/spec_helper.rb
|
97
113
|
- spec/todo_spec.rb
|
98
114
|
- spec/what_now_spec.rb
|
@@ -126,3 +142,4 @@ test_files:
|
|
126
142
|
- spec/example_file.txt
|
127
143
|
- spec/spec_helper.rb
|
128
144
|
- spec/todo_spec.rb
|
145
|
+
- spec/file_filter_spec.rb
|