lutra 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c8280ec08022d92e00986f7ac57545b6d07a38f8
4
+ data.tar.gz: 83530ac917e962aa083b6d71886d4738d53b7cbc
5
+ SHA512:
6
+ metadata.gz: 9e8003a4e8026dd896dab97c941220c1d07c540e1ae0b9e3e7c1f998624054b17ee938c17d4144c8e35553aa9fa589363ba26ecf806bde636b90751679e2ecb6
7
+ data.tar.gz: b0abd8259bccd4425c3c035caf2a469dd89753c799f16e9cd662f518e61332a3fe5c4e47389c83f8d252b016cbfa87fd9aa06cc18114d539863f41d8da176293
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Yuri Artemev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ ### lutra [![Gem version](https://badge.fury.io/rb/lutra.png)](https://rubygems.org/gems/lutra) [![Build Status](https://secure.travis-ci.org/artemeff/lutra.png)](https://travis-ci.org/artemeff/lutra) [![Code Climate](https://codeclimate.com/github/artemeff/lutra.png)](https://codeclimate.com/github/artemeff/lutra)
2
+
3
+ ---
4
+
5
+ In source annotations parser;
6
+
7
+ ---
8
+
9
+ ### Installation
10
+
11
+ ```bash
12
+ $ gem install lutra
13
+ ```
14
+
15
+ ### Usage
16
+
17
+ ```bash
18
+ $ lutra [OPTIONS] [PATH]
19
+ ```
20
+
21
+ ```
22
+ Usage: lutra [OPTIONS] [PATH]
23
+ -t, --tags=TAG Search for custom tags
24
+ -c, --comments=COM Specify comment lines
25
+ -f, --formatter=NAME Use your own formatter
26
+ -v, --verbose Verbose output
27
+ --hide-tags Hide tags
28
+ ```
29
+
30
+ ---
31
+
32
+ ### Contributing
33
+
34
+ 1. Fork it
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create new Pull Request
data/bin/lutra ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'find'
4
+ require 'lutra'
5
+
6
+ verbose = false
7
+ color = STDOUT.tty?
8
+ usage = 'Usage: lutra [OPTIONS] [PATH]'
9
+ tags = Lutra::TAGS.dup
10
+ comments = Lutra::COMM.dup
11
+ display_tags = true
12
+ formatter_name = :default
13
+
14
+ ARGV.options do |o|
15
+ o.version = Lutra::VERSION
16
+ o.banner = usage
17
+ o.on('-t', '--tags=TAG', 'Search for custom tags') do |tag|
18
+ tags |= [tag]
19
+ end
20
+
21
+ o.on('-c', '--comments=COM', 'Specify comment lines') do |com|
22
+ comments |= [com]
23
+ end
24
+
25
+ o.on('-f', '--formatter=NAME', 'Use your own formatter') do |name|
26
+ formatter_name = name.to_sym
27
+ end
28
+
29
+ o.on('-v', '--verbose', 'Verbose output') do
30
+ verbose = true
31
+ end
32
+
33
+ o.on('--hide-tags', 'Hide tags') do
34
+ display_tags = false
35
+ end
36
+ end
37
+
38
+ begin
39
+ ARGV.options.parse!
40
+ if ARGV.empty?
41
+ paths = '.'
42
+ else
43
+ paths = ARGV.map { |p| File.exist? p or raise Errno::ENOENT, p ; p }
44
+ end
45
+ rescue => e
46
+ STDERR.puts "lutra: #{e.message}"
47
+ STDERR.puts usage
48
+ STDERR.puts "Try 'lutra --help' for more information"
49
+ exit 1
50
+ end
51
+
52
+ scanner = Lutra::Scanner.new(tags: tags, comments: comments)
53
+
54
+ Find.find(*paths) do |path|
55
+ unless paths.include?(path)
56
+ Find.prune if File.basename(path).start_with?('.')
57
+ end
58
+
59
+ next if File.directory?(path)
60
+
61
+ begin
62
+ scanner.scan_file(path)
63
+ rescue Errno::ENOENT => e
64
+ STDERR.puts "lutra: #{e.message} (broken symlink?)" if verbose
65
+ rescue => e
66
+ STDERR.puts "lutra: #{path}: #{e.message}" if verbose
67
+ end
68
+ end
69
+
70
+ formatter = Lutra::Formatter.new(display_tags: display_tags)
71
+ formatter.set(formatter_name)
72
+ formatter.display(scanner.notes)
73
+
74
+ exit
@@ -0,0 +1,43 @@
1
+ module Lutra
2
+ class Formatter
3
+ attr_reader :formatters, :current
4
+
5
+ def initialize(options = {})
6
+ @options = options
7
+ @current = :default
8
+ @formatters = [
9
+ { name: :default, short: :d, class: Lutra::Formatters::Default }
10
+ ]
11
+ end
12
+
13
+ def get(name)
14
+ @formatters.select do |f|
15
+ f[:name] == name || f[:short] == name
16
+ end.first
17
+ end
18
+
19
+ def set(name)
20
+ if get(name)
21
+ @current = name
22
+ else
23
+ raise FormatterNotFound
24
+ end
25
+ end
26
+
27
+ def add(name, short_name, class_name)
28
+ if formatter?(class_name)
29
+ @formatters << { name: name, short: short_name, class: class_name }
30
+ end
31
+ end
32
+
33
+ def display(notes)
34
+ get(@current)[:class].new(@options).display(notes)
35
+ end
36
+
37
+ private
38
+
39
+ def formatter?(class_name)
40
+ class_name.new.respond_to?(:prepare)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ module Lutra
2
+ module Formatters
3
+ class Base
4
+ def initialize(options = {})
5
+ @options = options
6
+ end
7
+
8
+ def display(notes)
9
+ raise NotImplementedError
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Lutra
2
+ module Formatters
3
+ class Default < Lutra::Formatters::Base
4
+ def display(notes)
5
+ indent = notes.map(&:line).flatten.max.to_s.size
6
+
7
+ notes.group_by { |n| n.file }.each do |file, notes|
8
+ puts "#{file[2..-1]}:"
9
+ notes.each do |note|
10
+ puts " * #{prepare(note, indent)}"
11
+ end
12
+ puts
13
+ end
14
+ end
15
+
16
+ def prepare(note, indent)
17
+ s = "[#{note.line.to_s.rjust(indent)}] "
18
+ s << "[#{note.tag}] " if @options[:display_tags]
19
+ s << note.text
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/lutra/note.rb ADDED
@@ -0,0 +1,23 @@
1
+ module Lutra
2
+ class Note
3
+ attr_reader :tag, :source, :line, :file
4
+
5
+ def initialize(data)
6
+ @tag = data[:tag]
7
+ @line = data[:line]
8
+ @file = data[:file]
9
+ @source = data[:source]
10
+ end
11
+
12
+ def text
13
+ extract[:text]
14
+ end
15
+
16
+ private
17
+
18
+ def extract
19
+ @source =~ /(#{@tag})\s(.*)/
20
+ { tag: $1, text: $2 }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ module Lutra
2
+ class Scanner
3
+ attr_accessor :tags, :comments
4
+ attr_reader :notes
5
+
6
+ def initialize(options = {})
7
+ @tags = options[:tags] || TAGS.dup
8
+ @comments = options[:comments] || COMM.dup
9
+ @notes = []
10
+ end
11
+
12
+ def scan(source)
13
+ check_tags and check_comments
14
+ extract(source.split("\n")) and self
15
+ end
16
+
17
+ def scan_file(path)
18
+ check_tags and check_comments
19
+ extract(File.open(path), path) and self
20
+ end
21
+
22
+ private
23
+
24
+ def extract(source, path = nil)
25
+ rxp = regexp
26
+ source.each_with_index do |line, i|
27
+ if rxp =~ line
28
+ raw = { tag: $1, source: line, line: i + 1, file: path }
29
+ @notes << Note.new(raw)
30
+ end
31
+ end
32
+ end
33
+
34
+ def check_tags
35
+ raise EmptyTagListError if @tags.empty?
36
+ end
37
+
38
+ def check_comments
39
+ raise EmptyCommentListError if @comments.empty?
40
+ end
41
+
42
+ def regexp
43
+ /(#{@comments.join('|')})\s*(?<tag>#{@tags.join('|')})\s*(?<text>.*)/
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module Lutra
2
+ VERSION = "0.0.1"
3
+ end
data/lib/lutra.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'lutra/note'
2
+ require 'lutra/scanner'
3
+ require 'lutra/formatter'
4
+ require 'lutra/formatters/base'
5
+ require 'lutra/formatters/default'
6
+ require 'lutra/version'
7
+
8
+ module Lutra
9
+ TAGS = %w[TODO FIXME OPTIMIZE]
10
+ COMM = %w[# % ; // --]
11
+
12
+ # errors
13
+ class NotImplementedError < Exception; end
14
+ class EmptyTagListError < Exception; end
15
+ class EmptyCommentListError < Exception; end
16
+ class FormatterNotFound < Exception; end
17
+ end
data/lutra.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lutra/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "lutra"
7
+ s.version = Lutra::VERSION
8
+ s.authors = ["Yuri Artemev"]
9
+ s.email = ["i@artemeff.com"]
10
+ s.homepage = "http://github.com/artemeff/lutra"
11
+ s.summary = %q{In source annotaions parser}
12
+ s.description = %q{Parse tags (todo, fixme, optimize) in your source code}
13
+ s.licenses = ['MIT']
14
+
15
+ s.files = %w(README.md LICENSE lutra.gemspec)
16
+ s.files += Dir.glob("lib/**/*.rb")
17
+ s.files += Dir.glob("spec/**/*")
18
+ s.require_paths = ['lib']
19
+ s.test_files = Dir.glob("spec/**/*")
20
+
21
+ s.executables << 'lutra'
22
+
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rspec', '>= 2.1'
25
+ end
data/spec/example ADDED
@@ -0,0 +1,4 @@
1
+ # TODO sample todo
2
+ % FIXME sample fixme
3
+ ; OPTIMIZE sample optimize
4
+ TODO don't catch
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra::Formatter do
4
+ subject { described_class }
5
+
6
+ context ".new" do
7
+ it "have one formatter" do
8
+ expect(subject.new.formatters.size).to eq(1)
9
+ end
10
+
11
+ it "have default formatter" do
12
+ expect(subject.new.formatters.first[:name]).to eq(:default)
13
+ end
14
+ end
15
+
16
+ context "#add" do
17
+ it "adds new formatter" do
18
+ expect(subject.new.add(:new, :n, Lutra::Formatters::Default).size).to eq(2)
19
+ end
20
+ end
21
+
22
+ context "#get" do
23
+ subject { described_class.new }
24
+
25
+ it "finds formatter by name" do
26
+ expect(subject.get(:default)[:name]).to eq(:default)
27
+ end
28
+
29
+ it "finds formatter short name" do
30
+ expect(subject.get(:d)[:name]).to eq(:default)
31
+ end
32
+ end
33
+
34
+ context "#set" do
35
+ subject { described_class.new }
36
+
37
+ it "sets default formatter" do
38
+ subject.set(:default)
39
+ expect(subject.current).to eq(:default)
40
+ end
41
+
42
+ it "raise error when formatter dont exist" do
43
+ expect {
44
+ subject.set(:poke)
45
+ }.to raise_error(Lutra::FormatterNotFound)
46
+ end
47
+ end
48
+
49
+ it "#print"
50
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra::Formatters::Base do
4
+ subject { described_class }
5
+
6
+ it ".new raise exception" do
7
+ expect {
8
+ subject.new.display([])
9
+ }.to raise_error(Lutra::NotImplementedError)
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra::Formatters::Default do
4
+ subject { described_class }
5
+
6
+ it "#display"
7
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra do
4
+ end
data/spec/note_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra::Note do
4
+ subject do
5
+ raw = { tag: 'X', source: 'X text', line: 1, file: 'ex.rb' }
6
+ described_class.new(raw)
7
+ end
8
+
9
+ it "#tag" do
10
+ expect(subject.tag).to eq 'X'
11
+ end
12
+
13
+ it "#source" do
14
+ expect(subject.source).to eq 'X text'
15
+ end
16
+
17
+ it "#line" do
18
+ expect(subject.line).to eq 1
19
+ end
20
+
21
+ it "#file" do
22
+ expect(subject.file).to eq 'ex.rb'
23
+ end
24
+
25
+ it "#text" do
26
+ expect(subject.text).to eq 'text'
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lutra::Scanner do
4
+ subject { described_class }
5
+
6
+ context ".new" do
7
+ it "with default tags" do
8
+ expect(subject.new.tags).to eq ['TODO', 'FIXME', 'OPTIMIZE']
9
+ end
10
+
11
+ it "with custom tags" do
12
+ expect(subject.new(tags: ['X']).tags).to eq ['X']
13
+ end
14
+
15
+ it "with default comments" do
16
+ expect(subject.new.comments).to eq ["#", "%", ";", "//", "--"]
17
+ end
18
+
19
+ it "with custom comments" do
20
+ expect(subject.new(comments: ['#']).comments).to eq ["#"]
21
+ end
22
+ end
23
+
24
+ context "#scan_file" do
25
+ let(:notes) do
26
+ subject.new.scan_file("#{File.dirname(__FILE__)}/example").notes
27
+ end
28
+
29
+ it "have todo, fixme and optimize" do
30
+ expect(notes.map(&:tag)).to eq ['TODO', 'FIXME', 'OPTIMIZE']
31
+ end
32
+ end
33
+
34
+ context "#scan" do
35
+ let(:notes) { subject.new.scan(example_data).notes }
36
+
37
+ it "have todo, fixme and optimize" do
38
+ expect(notes.map(&:tag)).to eq ['TODO', 'FIXME', 'OPTIMIZE']
39
+ end
40
+
41
+ it "have only 3 items" do
42
+ expect(notes.size).to eq 3
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ require 'lutra'
2
+
3
+ def example_data
4
+ File.open("#{File.dirname(__FILE__)}/example").read
5
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lutra
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuri Artemev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ description: Parse tags (todo, fixme, optimize) in your source code
42
+ email:
43
+ - i@artemeff.com
44
+ executables:
45
+ - lutra
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - README.md
50
+ - LICENSE
51
+ - lutra.gemspec
52
+ - lib/lutra/formatter.rb
53
+ - lib/lutra/formatters/base.rb
54
+ - lib/lutra/formatters/default.rb
55
+ - lib/lutra/note.rb
56
+ - lib/lutra/scanner.rb
57
+ - lib/lutra/version.rb
58
+ - lib/lutra.rb
59
+ - spec/example
60
+ - spec/formatter_spec.rb
61
+ - spec/formatters/base_spec.rb
62
+ - spec/formatters/default_spec.rb
63
+ - spec/lutra_spec.rb
64
+ - spec/note_spec.rb
65
+ - spec/scanner_spec.rb
66
+ - spec/spec_helper.rb
67
+ - bin/lutra
68
+ homepage: http://github.com/artemeff/lutra
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.1.4
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: In source annotaions parser
92
+ test_files:
93
+ - spec/example
94
+ - spec/formatter_spec.rb
95
+ - spec/formatters/base_spec.rb
96
+ - spec/formatters/default_spec.rb
97
+ - spec/lutra_spec.rb
98
+ - spec/note_spec.rb
99
+ - spec/scanner_spec.rb
100
+ - spec/spec_helper.rb