notes 0.1.0.pre → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,10 @@
1
- == 0.1.0-pre1
1
+ == 0.1.0
2
+
3
+ * improve scanner and executable
4
+ * some compatibility fixes
5
+ * change -t option into -a
6
+
7
+ == 0.1.0-pre
2
8
 
3
9
  Complete refactoring of Notes: LESS IS MORE!
4
10
 
data/LICENSE CHANGED
@@ -1,6 +1,4 @@
1
- ----------------------------------------------------------------------------
2
1
  "THE BEER-WARE LICENSE" (Revision 42):
3
2
  <vivien@didelot.org> wrote this code. As long as you retain this notice you
4
3
  can do whatever you want with this stuff. If we meet some day, and you think
5
4
  this stuff is worth it, you can buy me a beer in return Vivien Didelot
6
- ----------------------------------------------------------------------------
@@ -0,0 +1,92 @@
1
+ = Notes
2
+
3
+ <b>Stupidly grep tags in source code.</b>
4
+
5
+ This gem provides a command line tool and a Ruby library to find tags in
6
+ source code. Defaults tags are *TODO*, *FIXME*, and *XXX*.
7
+ Custom tags can be found as well.
8
+
9
+ It's kind of a generic version of the Ruby on Rails <tt>rake notes</tt> command,
10
+ for any project/source.
11
+
12
+ == Command line tool
13
+
14
+ Usage:
15
+
16
+ $ notes [options] [file...]
17
+
18
+ With no argument, <tt>notes</tt> will search recursively in the current
19
+ directory. For details, see <tt>notes --help</tt>.
20
+
21
+ Examples:
22
+
23
+ $ notes
24
+ $ notes foo.h src/
25
+ $ notes --tag @@@
26
+ $ notes --no-{todo,fixme,xxx} --tag FOO
27
+
28
+ === Integration with Git
29
+
30
+ A cool thing to do is to add a Git alias to parse every versionned files:
31
+
32
+ $ git config --global alias.n '!git ls-files | xargs notes'
33
+
34
+ Now, running <tt>git n</tt> in any Git repository will search
35
+ notes in every files under version control!
36
+
37
+ === Convention over configuration
38
+
39
+ No custom output.
40
+
41
+ It uses a grep-style display, which makes it easy to fit your
42
+ needs. <tt>cut</tt> is great:
43
+
44
+ $ notes | cut -d: -f3,4-
45
+
46
+ will display this:
47
+
48
+ TODO: /* add a cool feature */
49
+
50
+ instead of the normal output:
51
+
52
+ foo.c:42:TODO: /* add a cool feature */
53
+
54
+ And colors will still be displayed.
55
+
56
+ Notes won't filter.
57
+
58
+ <tt>find</tt>, <tt>xargs</tt> are your friends:
59
+
60
+ $ find . -name '*.rb' | xargs notes
61
+
62
+ Or get the list of tagged files in the current directory with:
63
+
64
+ $ notes | cut -d: -f1 | sort -u
65
+
66
+ == Installation
67
+
68
+ Notes is available on Rubygems.org[http://rubygems.org/gems/notes] and
69
+ can be installed with:
70
+
71
+ $ [sudo] gem install notes
72
+
73
+ Or you can install from the source directory with:
74
+
75
+ $ rake install
76
+
77
+ == The Notes library
78
+
79
+ The Notes module provides convenient methods.
80
+
81
+ require 'notes'
82
+
83
+ Notes.scan_file("foo.c") do |note|
84
+ puts "#{note.tag} found at line #{note.line}!"
85
+ end
86
+
87
+ Notes can also extend an object to add a new method (see Notes#notes),
88
+ or allow you to create your own scanner (see the Notes::Scanner).
89
+
90
+ == License
91
+
92
+ That's free and friendly for sure! See the LICENSE file.
data/bin/notes CHANGED
@@ -1,40 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # ----------------------------------------------------------------------------
4
- # "THE BEER-WARE LICENSE" (Revision 42):
5
- # <vivien@didelot.org> wrote this file. As long as you retain this notice you
6
- # can do whatever you want with this stuff. If we meet some day, and you think
7
- # this stuff is worth it, you can buy me a beer in return Vivien Didelot
8
- # ----------------------------------------------------------------------------
9
-
3
+ require 'rubygems'
10
4
  require 'notes'
11
5
  require 'optparse'
12
6
  require 'paint'
13
7
  require 'find'
14
8
 
15
- # grep-style display
16
- def pretty_print(note, colors)
17
- col = Paint[':', :cyan]
18
- format = Paint['%s', :magenta] + col
19
- format << Paint['%s', :green] + col
20
- format << Paint['%s', colors[note.tag] || colors[:custom], :bold] + col
21
- format << "%s\n"
22
- printf(format,
23
- note.source,
24
- note.line,
25
- note.tag,
26
- note.text.rstrip)
27
- end
28
-
29
- tags = Notes::TAGS.dup
30
- colors = {
31
- "TODO" => 'green',
32
- "FIXME" => 'yellow',
33
- "XXX" => 'red',
34
- :custom => 'cyan'
35
- }
36
-
37
9
  usage = 'Usage: notes [OPTION]... [FILE]...'
10
+ tags = Notes::TAGS.dup
38
11
 
39
12
  ARGV.options do |o|
40
13
  o.version = Notes::VERSION
@@ -42,12 +15,17 @@ ARGV.options do |o|
42
15
  o.on( '--no-todo', 'Do not search TODO tags') { tags -= ['TODO'] }
43
16
  o.on( '--no-fixme', 'Do not search FIXME tags') { tags -= ['FIXME'] }
44
17
  o.on( '--no-xxx', 'Do not search XXX tags') { tags -= ['XXX'] }
45
- o.on('-t', '--tag=TAG', 'Search TAG tags') { |tag| tags |= [tag] }
18
+ o.on('-a', '--tag=TAG', 'Search TAG tags') { |tag| tags |= [tag] }
46
19
  o.on( '--no-color', 'Do not colorize ouput') { Paint.mode = 0 }
47
20
  end
48
21
 
49
22
  begin
50
23
  ARGV.options.parse!
24
+ if ARGV.empty?
25
+ paths = [Dir.pwd]
26
+ else
27
+ paths = ARGV.map { |p| File.exist? p or raise Errno::ENOENT, p ; p }
28
+ end
51
29
  rescue => e
52
30
  STDERR.puts "notes: #{e.message}"
53
31
  STDERR.puts usage
@@ -55,15 +33,23 @@ rescue => e
55
33
  exit 1
56
34
  end
57
35
 
36
+ # grep-style display
37
+ c = Paint[':', :cyan]
38
+ format = Paint['%s', :magenta] + c + Paint['%s', :green] + c + '%s' + c + "%s\n"
39
+ colors = {
40
+ 'TODO' => 'green',
41
+ 'FIXME' => 'yellow',
42
+ 'XXX' => 'red',
43
+ :custom => 'cyan'
44
+ }
45
+
58
46
  scanner = Notes::Scanner.new
59
- scanner.look_for tags
47
+ scanner.tags = tags
60
48
  scanner.on_note do |note|
61
- pretty_print(note, colors)
49
+ tag = Paint[note.tag, colors[note.tag] || colors[:custom], :bold]
50
+ printf(format, note.file, note.line, tag, note.text.rstrip)
62
51
  end
63
52
 
64
- paths = ARGV.dup
65
- paths.empty? and paths << Dir.pwd
66
-
67
53
  Find.find(*paths) do |path|
68
54
  unless paths.include? path
69
55
  Find.prune if File.basename(path).start_with? '.'
@@ -72,6 +58,8 @@ Find.find(*paths) do |path|
72
58
 
73
59
  begin
74
60
  scanner.scan_file(path)
61
+ rescue Errno::ENOENT => e
62
+ STDERR.puts "notes: #{e.message} (broken symlink?)"
75
63
  rescue => e
76
64
  STDERR.puts "notes: #{path}: #{e.message}"
77
65
  end
@@ -1,35 +1,91 @@
1
- # ------------------------------------------------------------------------------
2
- # "THE BEER-WARE LICENSE" (Revision 42):
3
- # <vivien.didelot@gmail.com> wrote this file. As long as you retain this notice
4
- # you can do whatever you want with this stuff. If we meet some day, and you
5
- # think this stuff is worth it, you can buy me a beer in return. Vivien Didelot
6
- # ------------------------------------------------------------------------------
7
-
8
1
  require 'notes/version'
9
2
  require 'notes/scanner'
10
3
 
11
4
  module Notes
12
5
 
13
6
  # Default tags to grep in source code.
7
+ # They are *TODO*, *FIXME*, and *XXX*.
14
8
  TAGS = %w[TODO FIXME XXX]
15
9
 
16
- Note = Struct.new(:tag, :text, :line, :source)
10
+ # The Note class. This is basically an object with accessors to four attributes:
11
+ # * tag: Tag the line is marked with;
12
+ # * text: The line of text containing the tag;
13
+ # * line: The line number;
14
+ # * file: The filename of the input source.
15
+ Note = Struct.new(:tag, :text, :line, :file)
17
16
 
18
- # TODO doc
17
+ # Scan a source string
18
+ #
19
+ # @example
20
+ # Notes.scan("...\nXXX fix this asap!") do |note|
21
+ # puts note.text
22
+ # end
23
+ #
24
+ # @param [String] source
25
+ # input source to scan
26
+ #
27
+ # @params [Array] tags
28
+ # tags to look for
29
+ # if nil, tags will be the defaults (TODO, FIXME, XXX)
30
+ #
31
+ # @params [Proc] block
32
+ # callback to execute when a note is found
33
+ #
34
+ # @return [Enumerator]
35
+ # an enumerator on notes when no block is given
19
36
  def self.scan(source, tags = nil, &block)
20
37
  block.nil? and return enum_for(__method__, source, tags, &block)
21
38
  scanner = Scanner.new(tags, &block)
22
39
  scanner.scan(source)
23
40
  end
24
41
 
25
- # TODO doc
42
+ # Scan a file
43
+ #
44
+ # @example
45
+ # Notes.scan_file("src/foo.c") do |note|
46
+ # puts note.text
47
+ # end
48
+ #
49
+ # Notes.scan_file("bar.hs", ['@@@']) do |note|
50
+ # puts "File to fix: #{note.file}!"
51
+ # end
52
+ #
53
+ # @param [String] filename
54
+ # name of the file to scan
55
+ #
56
+ # @params [Array] tags
57
+ # tags to look for
58
+ # if nil, tags will be the defaults (TODO, FIXME, XXX)
59
+ #
60
+ # @params [Proc] block
61
+ # callback to execute when a note is found
62
+ #
63
+ # @return [Enumerator]
64
+ # an enumerator on notes when no block is given
26
65
  def self.scan_file(file, tags = nil, &block)
27
66
  block.nil? and return enum_for(__method__, file, tags, &block)
28
67
  scanner = Scanner.new(tags, &block)
29
68
  scanner.scan_file(file)
30
69
  end
31
70
 
32
- # TODO doc
71
+ # Add a :notes method to an object
72
+ #
73
+ # @example
74
+ # file = File.new("foo.c")
75
+ # file.extend Notes
76
+ # file.notes do |note|
77
+ # puts note.text
78
+ # end
79
+ #
80
+ # @params [Array] tags
81
+ # tags to look for
82
+ # if nil, tags will be the defaults (TODO, FIXME, XXX)
83
+ #
84
+ # @params [Proc] block
85
+ # callback to execute when a note is found
86
+ #
87
+ # @return [Enumerator]
88
+ # an enumerator on notes when no block is given
33
89
  def notes(tags = nil, &block)
34
90
  block.nil? and return enum_for(__method__, tags, &block)
35
91
  scanner = Scanner.new(tags, &block)
@@ -1,45 +1,84 @@
1
1
  module Notes
2
2
  class Scanner
3
3
 
4
- attr_accessor :tags, :action
4
+ # The array of tags to look for
5
+ #
6
+ # @example
7
+ # scanner.tags << "FOO"
8
+ #
9
+ # @return [Array]
10
+ # the tags list
11
+ attr_accessor :tags
5
12
 
6
- # TODO doc
13
+ # The block to execute when a note is found
14
+ #
15
+ # @example
16
+ # scanner.callback = proc { |note| puts note.file }
17
+ #
18
+ # @see :on_note
19
+ attr_accessor :callback
20
+
21
+ # Create a new scanner
22
+ #
23
+ # @example
24
+ # scan = Notes::Scanner.new(["TODO", "@@@"]) do |note|
25
+ # puts "#{note.file} contains notes!"
26
+ # end
27
+ #
28
+ # class NotesCounter < Notes::Scanner
29
+ # attr_reader :notes
30
+ #
31
+ # def initialize tags = nil
32
+ # super(tags)
33
+ # @notes = []
34
+ # @callback = proc { |note| @notes << note }
35
+ # end
36
+ # end
7
37
  def initialize tags = nil, &block
8
38
  @tags = tags || TAGS.dup
9
- @action = block || proc { |note| tag(note) }
39
+ @callback = block
10
40
  end
11
41
 
12
- # TODO doc
13
- alias look_for tags=
14
-
15
- # TODO doc
42
+ # Define the callback to execute when a note is given
43
+ #
44
+ # @example
45
+ # scanner.on_note do |note|
46
+ # puts note.text
47
+ # end
48
+ #
49
+ # @see :callback=
16
50
  def on_note &block
17
- @action = block
51
+ @callback = block
18
52
  end
19
53
 
20
- # TODO doc
54
+ # Scan a source string
55
+ #
56
+ # @example
57
+ # scanner.scan("...//XXX urgent fix!")
21
58
  def scan source
59
+ return if tags.empty? || callback.nil?
60
+ rxp = regexp
22
61
  source.split("\n").each_with_index do |line, i|
23
- if line =~ regexp
24
- @action.call Note.new($1, line, i + 1)
62
+ if rxp =~ line
63
+ callback.call Note.new($1, line, i + 1)
25
64
  end
26
65
  end
27
66
  end
28
67
 
29
- # TODO doc
68
+ # Scan a file
69
+ #
70
+ # @example
71
+ # scanner.scan_file("foo.c")
30
72
  def scan_file path
31
- file = File.open(path, 'r')
32
- file.each_with_index do |line, i|
33
- if line =~ regexp
34
- @action.call Note.new($1, line, i + 1, path)
73
+ return if tags.empty? || callback.nil?
74
+ rxp = regexp
75
+ File.open(path, 'r') do |file|
76
+ file.each_with_index do |line, i|
77
+ if rxp =~ line
78
+ callback.call Note.new($1, line, i + 1, path)
79
+ end
35
80
  end
36
81
  end
37
- file.close
38
- end
39
-
40
- # TODO doc
41
- def tag note
42
- puts "#{note.type} on line #{note.line}: #{note.text.strip}"
43
82
  end
44
83
 
45
84
  private
@@ -1,4 +1,4 @@
1
1
  module Notes
2
- VERSION = "0.1.0.pre"
2
+ VERSION = "0.1.0"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: notes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre
5
- prerelease: 6
4
+ version: 0.1.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Vivien Didelot
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000 Z
12
+ date: 2012-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: paint
16
- requirement: &20331680 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: 0.8.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *20331680
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.4
25
30
  description:
26
31
  email: vivien.didelot@gmail.com
27
32
  executables:
@@ -32,10 +37,11 @@ files:
32
37
  - lib/notes.rb
33
38
  - lib/notes/scanner.rb
34
39
  - lib/notes/version.rb
35
- - README.md
40
+ - README.rdoc
36
41
  - CHANGELOG.rdoc
37
42
  - LICENSE
38
- - bin/notes
43
+ - !binary |-
44
+ YmluL25vdGVz
39
45
  homepage:
40
46
  licenses: []
41
47
  post_install_message:
@@ -51,13 +57,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
57
  required_rubygems_version: !ruby/object:Gem::Requirement
52
58
  none: false
53
59
  requirements:
54
- - - ! '>'
60
+ - - ! '>='
55
61
  - !ruby/object:Gem::Version
56
- version: 1.3.1
62
+ version: '0'
57
63
  requirements: []
58
64
  rubyforge_project:
59
- rubygems_version: 1.8.15
65
+ rubygems_version: 1.8.21
60
66
  signing_key:
61
67
  specification_version: 3
62
- summary: A Ruby gem to grep tags in source files.
68
+ summary: Stupidly grep tags in source code.
63
69
  test_files: []
data/README.md DELETED
@@ -1,105 +0,0 @@
1
- # Notes
2
-
3
- grep tags in source files
4
-
5
- This gem provides a command line tool and a Ruby library to find tags in
6
- source code. Defaults tags are *TODO*, *FIXME*, and *XXX*.
7
- Custom tags can be found as well.
8
-
9
- It's kind of a generic version of the `rake notes` command,
10
- which is only available in Ruby on Rails applications.
11
-
12
- ## Command line tool
13
-
14
- Usage:
15
-
16
- $ notes [options] [file...]
17
-
18
- With no argument, `notes` will search recursively in the current
19
- directory. For details, see `notes --help`.
20
-
21
- Examples:
22
-
23
- $ notes
24
- $ notes foo.h src/
25
- $ notes --tag @@@
26
- $ notes --no-{todo,fixme,xxx} --tag FOO
27
-
28
- ### Convention over configuration
29
-
30
- Notes won't filter. `find`, `xargs` are here for you:
31
-
32
- $ find . -name '*.rb' | xargs notes
33
-
34
- No custom output. It uses a grep-style display, which makes it easy to
35
- fit your needs. Try:
36
-
37
- $ notes | cut -d: -f3,4-
38
-
39
- Or get the list of tagged files in the current directory with:
40
-
41
- $ notes | cut -d: -f1 | sort -u
42
-
43
- ## Installation
44
-
45
- Notes is available on [Rubygems.org](http://rubygems.org/gems/notes) and
46
- can be installed with:
47
-
48
- $ [sudo] gem install notes
49
-
50
- ## The Notes library
51
-
52
- Module functions:
53
-
54
- require 'notes'
55
-
56
- Notes.scan_file("foo.c") do |note|
57
- puts "#{note.tag} found at line #{note.line}!"
58
- end
59
-
60
- Notes.scan("...\nXXX: an urgent note!") do |note|
61
- putes note.text
62
- end
63
-
64
- Extending the Notes module:
65
-
66
- require 'notes'
67
-
68
- file = File.new("foo.c")
69
- file.extend Notes
70
- file.notes { |note| puts note.text }
71
-
72
- Using the Notes scanner:
73
-
74
- require 'notes'
75
-
76
- scan = Notes::Scanner.new
77
- scan.tags = Notes::TAGS + "FOO"
78
- scan.on_note do |note|
79
- puts "found!"
80
- end
81
- scan.scan_file("foo.c")
82
- scan.scan_file("bar.c")
83
-
84
- Create your own scanner:
85
-
86
- require 'notes'
87
-
88
- class Foo < Notes::Scanner
89
- attr_reader :notes
90
-
91
- def initialize tags = nil
92
- super(tags)
93
- @notes = []
94
- end
95
-
96
- # Called if no action block set. So override it.
97
- def tag note
98
- @notes << note
99
- end
100
- end
101
-
102
- License
103
- -------
104
-
105
- That's free for sure! See the LICENSE file.