notes 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|