notes 0.0.1
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/CHANGELOG.rdoc +3 -0
- data/LICENSE +7 -0
- data/README.rdoc +88 -0
- data/bin/notes +65 -0
- data/lib/notes.rb +108 -0
- data/test/data/sample.c +55 -0
- data/test/notes_test.rb +55 -0
- metadata +102 -0
data/CHANGELOG.rdoc
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
-------------------------------------------------------------------------------
|
2
|
+
"THE BEER-WARE LICENSE" (Revision 42):
|
3
|
+
<vivien.didelot@gmail.com> wrote this gem. 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
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
= Notes
|
2
|
+
|
3
|
+
== grep annotations in source files
|
4
|
+
|
5
|
+
This lib provides a Ruby library and command line tool to find annotations in source files such as:
|
6
|
+
* TODO
|
7
|
+
* FIXME
|
8
|
+
* OPTIMIZE
|
9
|
+
Custom tags can also be found.
|
10
|
+
|
11
|
+
The purpose of this code is to get a generic version of the `rake notes' command (only used for Ruby on Rails applications).
|
12
|
+
It will look for tags recursively in every given files (or in current directory by default).
|
13
|
+
|
14
|
+
== Installation
|
15
|
+
|
16
|
+
Notes is available on Rubygems.org[http://rubygems.org/gems/notes] and can be installed with:
|
17
|
+
|
18
|
+
$ gem install notes
|
19
|
+
|
20
|
+
This command needs Rubygems (rubygems package on Ubuntu).
|
21
|
+
|
22
|
+
== Usage
|
23
|
+
|
24
|
+
=== Command line tool
|
25
|
+
|
26
|
+
notes [options] [file...]
|
27
|
+
|
28
|
+
For details, see the help.
|
29
|
+
|
30
|
+
$ ruby notes --help
|
31
|
+
Usage: notes [options] [file...]
|
32
|
+
Search recursively for annotations in source code.
|
33
|
+
By default, notes will search for all annotations in current directory.
|
34
|
+
Available options:
|
35
|
+
-a, --all Search TODO, FIXME and OPTIMIZE annotations
|
36
|
+
-t, --todo Search TODO annotations
|
37
|
+
-f, --fixme Search FIXME annotations
|
38
|
+
-i, --improve Search OPTIMIZE annotations
|
39
|
+
-c, --custom=TAG Search TAG annotations
|
40
|
+
-o, --out=FILE Save output in FILE
|
41
|
+
-v, --version Print notes version
|
42
|
+
Example: notes -ac IMPROVE test.c lib
|
43
|
+
will search for TODO, FIXME, OPTIMIZE and IMPROVE annotations in test.c lib directory.
|
44
|
+
|
45
|
+
Another example:
|
46
|
+
|
47
|
+
$ notes test/data/sample.c
|
48
|
+
../test/data/sample.c:16: TODO: first thing to do
|
49
|
+
../test/data/sample.c:26: FIXME: first fixme thing
|
50
|
+
../test/data/sample.c:32: TODO: second todo thing!
|
51
|
+
../test/data/sample.c:42: OPTIMIZE: make it better
|
52
|
+
../test/data/sample.c:47: TODO: hello world
|
53
|
+
|
54
|
+
If the terminal allows it, colors will be displayed for files and tags.
|
55
|
+
|
56
|
+
Another again:
|
57
|
+
|
58
|
+
$ notes -o TODO.txt test/data/sample.c
|
59
|
+
|
60
|
+
will write all notes to a TODO.txt file. It will look like that:
|
61
|
+
|
62
|
+
* [TODO ] ../test/data/sample.c (16): first thing to do
|
63
|
+
* [FIXME ] ../test/data/sample.c (26): first fixme thing
|
64
|
+
* [TODO ] ../test/data/sample.c (32): second todo thing!
|
65
|
+
* [OPTIMIZE] ../test/data/sample.c (42): make it better
|
66
|
+
* [TODO ] ../test/data/sample.c (47): hello world
|
67
|
+
|
68
|
+
=== Lib
|
69
|
+
|
70
|
+
This code can be used as a Ruby lib. Let's see how it works in irb:
|
71
|
+
|
72
|
+
$ irb
|
73
|
+
>> require 'notes'
|
74
|
+
>> AnnotationExtractor.tags << "FOO"
|
75
|
+
>> notes = AnnotationExtractor.new "test/data/sample.c"
|
76
|
+
>> notes.list
|
77
|
+
>> notes.get "FIXME"
|
78
|
+
>> notes.write "TODO.rdoc"
|
79
|
+
|
80
|
+
== License
|
81
|
+
|
82
|
+
------------------------------------------------------------------------------
|
83
|
+
"THE BEER-WARE LICENSE" (Revision 42):
|
84
|
+
<vivien.didelot@gmail.com> wrote this gem. As long as you retain this notice
|
85
|
+
you can do whatever you want with this stuff. If we meet some day, and you
|
86
|
+
think this stuff is worth it, you can buy me a beer in return. Vivien Didelot
|
87
|
+
------------------------------------------------------------------------------
|
88
|
+
|
data/bin/notes
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# ------------------------------------------------------------------------------
|
4
|
+
# "THE BEER-WARE LICENSE" (Revision 42):
|
5
|
+
# <vivien.didelot@gmail.com> wrote this file. As long as you retain this notice
|
6
|
+
# you can do whatever you want with this stuff. If we meet some day, and you
|
7
|
+
# think this stuff is worth it, you can buy me a beer in return. Vivien Didelot
|
8
|
+
# ------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Command line tool to grep annotations from source files.
|
11
|
+
# Author:: Vivien 'v0n' Didelot <vivien.didelot@gmail.com>
|
12
|
+
|
13
|
+
require 'notes'
|
14
|
+
|
15
|
+
require 'rainbow'
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
def display(list)
|
19
|
+
list.each do |a|
|
20
|
+
color = case a.tag
|
21
|
+
when "TODO" then :yellow
|
22
|
+
when "FIXME" then :red
|
23
|
+
when "OPTIMIZE" then :green
|
24
|
+
else :blue
|
25
|
+
end
|
26
|
+
|
27
|
+
printf("%s:%s: %s: %s\n",
|
28
|
+
a.file.color(:magenta), a.line, a.tag.color(color), a.text)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
tags = []
|
33
|
+
source = []
|
34
|
+
file = nil
|
35
|
+
|
36
|
+
ARGV.options do |o|
|
37
|
+
o.banner = "Usage: #{File.basename $0} [options] [file...]\n"
|
38
|
+
o.banner << "Search recursively for annotations in source code.\n"
|
39
|
+
o.banner << "By default, #{File.basename $0} will search for all annotations in current directory.\n"
|
40
|
+
|
41
|
+
o.on_head("Available options:")
|
42
|
+
o.on("-a", "--all", "Search TODO, FIXME and OPTIMIZE annotations") { tags << AnnotationExtractor::TAGS }
|
43
|
+
o.on("-t", "--todo", "Search TODO annotations") { tags << "TODO" }
|
44
|
+
o.on("-f", "--fixme", "Search FIXME annotations") { tags << "FIXME" }
|
45
|
+
o.on("-z", "--optimize", "Search OPTIMIZE annotations") { tags << "OPTIMIZE" }
|
46
|
+
o.on("-c", "--custom=TAG", String, "Search TAG annotations") { |v| tags << v }
|
47
|
+
o.on("-o", "--out=FILE", String, "Save output in FILE") { |v| file = v }
|
48
|
+
o.on("-v", "--version", "Print notes version") { puts "notes: version #{AnnotationExtractor::VERSION}" ; exit }
|
49
|
+
|
50
|
+
o.on_tail("Example: #{File.basename $0} -ac IMPROVE test.c lib\nwill search for TODO, FIXME, OPTIMIZE and IMPROVE annotations in test.c lib directory.")
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
ARGV.options.parse!
|
55
|
+
AnnotationExtractor.tags = tags.flatten unless tags.empty?
|
56
|
+
source = ARGV
|
57
|
+
|
58
|
+
notes = AnnotationExtractor.new(source)
|
59
|
+
|
60
|
+
file.nil? ? display(notes.list) : notes.write(file)
|
61
|
+
rescue => e
|
62
|
+
STDERR.puts "error: #{e}"
|
63
|
+
end
|
64
|
+
|
65
|
+
exit
|
data/lib/notes.rb
ADDED
@@ -0,0 +1,108 @@
|
|
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
|
+
# Useless, but informs that rak should be installed.
|
9
|
+
require 'rubygems'
|
10
|
+
require 'rak'
|
11
|
+
|
12
|
+
class AnnotationExtractor
|
13
|
+
VERSION = "0.0.1"
|
14
|
+
|
15
|
+
# An annotation class.
|
16
|
+
class Annotation
|
17
|
+
attr_accessor :file, :line, :tag, :text
|
18
|
+
|
19
|
+
# Instanciate a new Annotation from a hash.
|
20
|
+
def initialize(args)
|
21
|
+
@file = args[:file]
|
22
|
+
@line = args[:line]
|
23
|
+
@tag = args[:tag]
|
24
|
+
@text = args[:text]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Default tags list
|
29
|
+
TAGS = ["TODO", "FIXME", "OPTIMIZE"]
|
30
|
+
|
31
|
+
# Trick not to use @@tags class variable, but works the same way.
|
32
|
+
# Custom tags can be added with AnnotationExtractor.tags << "FOO".
|
33
|
+
@tags = TAGS.clone
|
34
|
+
class << self
|
35
|
+
attr_reader :tags
|
36
|
+
def tags=(tags)
|
37
|
+
@tags = tags.is_a?(Array) ? tags : [tags]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The list of all notes.
|
42
|
+
attr_reader :list
|
43
|
+
|
44
|
+
# Instanciate a new extractor for the given target files.
|
45
|
+
def initialize(source = Dir.pwd)
|
46
|
+
@source = [].push(source).flatten
|
47
|
+
@list = Array.new
|
48
|
+
|
49
|
+
extract
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get annotation with tag 'tag' from the list.
|
53
|
+
def get(tag)
|
54
|
+
@list.find_all { |a| a.tag == tag }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Write all annotations to the file 'file'.
|
58
|
+
def write(file)
|
59
|
+
longest_tag = @list.max { |a, b| a.tag.size <=> b.tag.size }.tag.size
|
60
|
+
|
61
|
+
File.open(file, 'w') do |f|
|
62
|
+
@list.each do |a|
|
63
|
+
f.write(sprintf(" * [%-#{longest_tag}s] %s (%s): %s\n",
|
64
|
+
a.tag, a.file, a.line, a.text))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Extract for annotations.
|
72
|
+
def extract
|
73
|
+
tags = self.class.tags.join("|")
|
74
|
+
source = @source.join(" ")
|
75
|
+
|
76
|
+
# Because of different rak versions,
|
77
|
+
# rak system call outputs are not similar.
|
78
|
+
if `rak --version` =~ /rak (\d\.\d)/
|
79
|
+
rak_version = $1
|
80
|
+
else
|
81
|
+
raise "Can't get rak version"
|
82
|
+
end
|
83
|
+
|
84
|
+
# 0.9 is the current rak version from rubygems.
|
85
|
+
# 1.1 is the current rak version from the github repo.
|
86
|
+
if rak_version == "1.1"
|
87
|
+
regex = /^(.*):(\d*):.*(#{tags})\s*(.*)$/
|
88
|
+
else
|
89
|
+
regex = /^([^\s]+)\s+(\d+)\|.*(#{tags})\s*(.*)$/
|
90
|
+
end
|
91
|
+
|
92
|
+
out = `rak '#{tags}' #{source}`.strip
|
93
|
+
|
94
|
+
@list = out.split("\n").map do |l|
|
95
|
+
if l =~ regex
|
96
|
+
Annotation.new({
|
97
|
+
:file => $1,
|
98
|
+
:line => $2.to_i,
|
99
|
+
:tag => $3,
|
100
|
+
:text => $4.strip
|
101
|
+
})
|
102
|
+
else
|
103
|
+
# Just for a debug purpose
|
104
|
+
raise "notes: does not match regexp => \"#{l}\""
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/test/data/sample.c
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
/*
|
2
|
+
* -----------------------------------------------------------------------------
|
3
|
+
* "THE BEER-WARE LICENSE" (Revision 42):
|
4
|
+
* <vivien.didelot@gmail.com> wrote this file. As long as you retain this notice
|
5
|
+
* you can do whatever you want with this stuff. If we meet some day, and you
|
6
|
+
* think this stuff is worth it, you can buy me a beer in return. Vivien Didelot
|
7
|
+
* -----------------------------------------------------------------------------
|
8
|
+
*/
|
9
|
+
|
10
|
+
/* UDP Server */
|
11
|
+
|
12
|
+
#include <netinet/in.h>
|
13
|
+
#include <stdio.h>
|
14
|
+
#include <stdlib.h>
|
15
|
+
|
16
|
+
//TODO first thing to do
|
17
|
+
#define STEP sizeof(char)
|
18
|
+
|
19
|
+
int main()
|
20
|
+
{
|
21
|
+
int sock;
|
22
|
+
size_t size = STEP;
|
23
|
+
size_t a_size = sizeof(struct sockaddr_in);
|
24
|
+
void *buffer = malloc(STEP);
|
25
|
+
|
26
|
+
//FIXME first fixme thing
|
27
|
+
int port = 4242;
|
28
|
+
|
29
|
+
/* address server sock */
|
30
|
+
struct sockaddr_in addr = {AF_INET, htons(port), {htonl(INADDR_ANY)}};
|
31
|
+
|
32
|
+
//TODO second todo thing!
|
33
|
+
/* client sock */
|
34
|
+
struct sockaddr_in client;
|
35
|
+
|
36
|
+
/* socket declaration */
|
37
|
+
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
38
|
+
|
39
|
+
/* bind socket to local */
|
40
|
+
bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
|
41
|
+
|
42
|
+
//OPTIMIZE make it better
|
43
|
+
while(1)
|
44
|
+
{
|
45
|
+
//FOO a custom tag
|
46
|
+
while (recvfrom(sock, buffer, size, MSG_PEEK, NULL, NULL) == size)
|
47
|
+
buffer = realloc(buffer, size += STEP); //TODO hello world
|
48
|
+
|
49
|
+
recvfrom(sock, buffer, size, 0, (struct sockaddr*) &client, &a_size);
|
50
|
+
|
51
|
+
printf("Server receive: \"%s\"\n", (char*) buffer);
|
52
|
+
}
|
53
|
+
|
54
|
+
return 0;
|
55
|
+
}
|
data/test/notes_test.rb
ADDED
@@ -0,0 +1,55 @@
|
|
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
|
+
require "test/unit"
|
9
|
+
require "notes"
|
10
|
+
require "tempfile"
|
11
|
+
|
12
|
+
class NotesTest < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@sample = "#{File.join "..", "test", "data", "sample.c"}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_new
|
18
|
+
notes = AnnotationExtractor.new(@sample)
|
19
|
+
assert_equal 5, notes.list.size
|
20
|
+
notes.list.each { |a| assert_kind_of AnnotationExtractor::Annotation, a }
|
21
|
+
|
22
|
+
AnnotationExtractor.tags << "FOO"
|
23
|
+
notes = AnnotationExtractor.new(@sample)
|
24
|
+
assert_equal 6, notes.list.size
|
25
|
+
|
26
|
+
AnnotationExtractor.tags = "OPTIMIZE"
|
27
|
+
notes = AnnotationExtractor.new(@sample)
|
28
|
+
assert_equal 1, notes.list.size
|
29
|
+
assert_equal "make it better", notes.list.first.text
|
30
|
+
|
31
|
+
AnnotationExtractor.tags = "FOO"
|
32
|
+
notes = AnnotationExtractor.new(@sample)
|
33
|
+
assert_equal 1, notes.list.size
|
34
|
+
assert_equal "a custom tag", notes.list.first.text
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_get
|
38
|
+
notes = AnnotationExtractor.new(@sample)
|
39
|
+
assert_equal 3, notes.get("TODO").size
|
40
|
+
assert_equal 1, notes.get("FIXME").size
|
41
|
+
assert_equal 1, notes.get("OPTIMIZE").size
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_write
|
45
|
+
tempfile = Tempfile.new("notes").path
|
46
|
+
|
47
|
+
AnnotationExtractor.tags = AnnotationExtractor::TAGS
|
48
|
+
notes = AnnotationExtractor.new(@sample)
|
49
|
+
notes.write tempfile
|
50
|
+
|
51
|
+
assert_equal 5, File.readlines(tempfile).size
|
52
|
+
|
53
|
+
File.delete tempfile
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: notes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Vivien Didelot
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-13 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rak
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 15
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
version: "1.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rainbow
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 13
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 1
|
48
|
+
version: "1.1"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
description:
|
52
|
+
email: vivien.didelot@gmail.com
|
53
|
+
executables:
|
54
|
+
- notes
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files: []
|
58
|
+
|
59
|
+
files:
|
60
|
+
- lib/notes.rb
|
61
|
+
- test/notes_test.rb
|
62
|
+
- test/data/sample.c
|
63
|
+
- README.rdoc
|
64
|
+
- CHANGELOG.rdoc
|
65
|
+
- LICENSE
|
66
|
+
- bin/notes
|
67
|
+
has_rdoc: true
|
68
|
+
homepage:
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.3.7
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A Ruby gem to grep annotations in source files.
|
101
|
+
test_files: []
|
102
|
+
|