CoffeeTags 0.0.2.2 → 0.0.2.4

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/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A simple tool for generating CoffeeScript tags (Ctags compatible).
4
4
 
5
+ [![Build Status](https://secure.travis-ci.org/lukaszkorecki/CoffeeTags.png?branch=master)](http://travis-ci.org/lukaszkorecki/CoffeeTags)
6
+
5
7
 
6
8
  ### Example + Screenshot
7
9
  Showing only functions (right) or with variables included (left)
@@ -1,5 +1,7 @@
1
1
  module Coffeetags
2
2
  class Formatter
3
+ # Generates CTAGS header
4
+ # @returns [String] ctags header
3
5
  def self.header
4
6
  return [
5
7
  "!_TAG_FILE_FORMAT 2 /extended format/",
@@ -11,6 +13,10 @@ module Coffeetags
11
13
  ].map { |h| "#{h}\n"}.join ''
12
14
  end
13
15
 
16
+ # New Formatter class
17
+ #
18
+ # @param [String] file file name
19
+ # @param [Array] tree parse tree for given file generated by Coffeetags::Parser
14
20
  def initialize file, tree =[]
15
21
  @file = file
16
22
  @tree = tree
@@ -26,6 +32,7 @@ module Coffeetags
26
32
  end
27
33
 
28
34
 
35
+ # Helper function for formatting a source line into regex
29
36
  def regex_line line
30
37
  "/#{line}/;\""
31
38
  end
@@ -47,8 +54,9 @@ module Coffeetags
47
54
 
48
55
  def parse_tree
49
56
  @lines = @tree.map do | content|
50
- line_to_string content unless content[:line].nil? or content[:name].blank?
51
- end.reject{|l| l.nil? }
57
+ line_to_string content unless content[:line].nil? or content[:name].blank?
58
+ end
59
+ @lines.reject{|l| l.nil? }
52
60
  end
53
61
 
54
62
 
@@ -1,6 +1,11 @@
1
1
  module Coffeetags
2
2
  class Parser
3
3
  attr_reader :tree
4
+ # Creates a new parser
5
+ #
6
+ # @param [String] source source of the CoffeeScript file
7
+ # @param [Bool] include_vars include objects in generated tree (default false)
8
+ # @return [Coffeetags::Parser]
4
9
  def initialize source, include_vars = false
5
10
  @include_vars = include_vars
6
11
  @source = source
@@ -17,12 +22,46 @@ module Coffeetags
17
22
  @var_regex = /([@a-zA-Z0-9_]*)\s*[=:]{1}\s*$/
18
23
  @token_regex = /([@a-zA-Z0-9_]*)\s*[:=]{1}/
19
24
  @iterator_regex = /^\s*for\s*([a-zA-Z0-9_]*)\s*/
25
+ @comment_regex = /^\s*#/
26
+ @block_comment_regex = /^\s*###/
27
+ @comment_lines = mark_commented_lines
20
28
  end
21
29
 
30
+
31
+ # Mark line numbers as commented out
32
+ # either by single line comment (#)
33
+ # or block comments (###~###)
34
+ def mark_commented_lines
35
+ [].tap do |reg|
36
+ in_block_comment = false
37
+ @source.each_with_index do |line, index|
38
+ line_no = index+1
39
+
40
+ in_block_comment = !(in_block_comment) if line =~ @block_comment_regex
41
+ reg << line_no if in_block_comment
42
+ reg << line_no if line =~ @comment_regex and not in_block_comment
43
+ end
44
+ end
45
+ end
46
+
47
+ # Detect current line level based on indentation
48
+ # very useful in parsing, since CoffeeScript's syntax
49
+ # depends on whitespace
50
+ # @param [String] line currently parsed line
51
+ # @return [Integer]
22
52
  def line_level line
23
53
  line.match(/^[ \t]*/)[0].gsub("\t", " ").split('').length
24
54
  end
25
55
 
56
+ # Generate current scope path, for example:
57
+ # e ->
58
+ # f ->
59
+ # z ->
60
+ # Scope path for function z would be:
61
+ # window.e.f
62
+ # @param [Hash, nil] _el element of a prase tree (last one for given tree is used by default)
63
+ # @param [Array, nil] _tree parse tree (or currently built)
64
+ # @returns [String] string representation of scope for given element
26
65
  def scope_path _el = nil, _tree = nil
27
66
  bf = []
28
67
  tree = (_tree || @tree)
@@ -38,40 +77,63 @@ module Coffeetags
38
77
  end
39
78
  end
40
79
  bf.uniq.reverse.join('.')
80
+ end
41
81
 
82
+ # Helper function for generating parse tree elements for given
83
+ # line and regular expression
84
+ #
85
+ # @param [String] line source line currently being parsed
86
+ # @param [RegExp] regex regular expression for matching a syntax element
87
+ # @param [Integer] level current indentation/line level
88
+ # @param [Hash, {}] additional_fields additional fields which need to be added to generated element
89
+ # @returns [Hash,nil] returns a parse tree element consiting of:
90
+ # :name of the element
91
+ # indentation :level of the element
92
+ def item_for_regex line, regex, level, additional_fields={}
93
+ if item = line.match(regex)
94
+ entry_for_item = {
95
+ :name => item[1],
96
+ :level => level
97
+ }
98
+ entry_for_item.merge(additional_fields)
99
+ end
42
100
  end
43
101
 
102
+ # Parse the source and create a tags tree
103
+ # @note this method mutates @tree instance variable of Coffeetags::Parser instance
104
+ # @returns self it can be chained
44
105
  def execute!
45
106
  line_n = 0
46
107
  level = 0
47
- # indentify scopes
48
108
  @source.each_line do |line|
49
109
  line_n += 1
110
+ # indentify scopes
50
111
  level = line_level line
51
112
 
52
113
  # ignore comments!
53
- next if line =~ /^\s*#/
54
-
55
- # FIXME this could be DRYied
56
- if (_class = line.match @class_regex)
57
- @tree << { :name => _class[1], :level => level }
114
+ next if @comment_lines.include? line_n
115
+
116
+ # extract elements for given line
117
+ [
118
+ @class_regex,
119
+ @proto_meths,
120
+ @var_regex
121
+ ].each do |regex|
122
+ mt = item_for_regex line, regex, level
123
+ @tree << mt unless mt.nil?
58
124
  end
59
125
 
60
- if(_proto = line.match @proto_meths)
61
- @tree << { :name => _proto[1], :level => level }
62
- end
63
126
 
64
- if(var = line.match @var_regex)
65
- @tree << { :name => var[1], :level => level }
66
- end
127
+ # does this line contain a block?
128
+ mt = item_for_regex line, @block, level, :kind => 'b'
129
+ @tree << mt unless mt.nil?
67
130
 
68
- if(_block = line.match @block)
69
- @tree << { :name => _block[1], :level => level , :kind => 'b'}
70
- end
71
131
 
132
+ # instance variable or iterator (for/in)?
72
133
  token = line.match(@token_regex )
73
134
  token ||= line.match(@iterator_regex)
74
135
 
136
+ # we have found something!
75
137
  if not token.nil?
76
138
  o = {
77
139
  :name => token[1],
@@ -85,8 +147,8 @@ module Coffeetags
85
147
  # - if a line containes a line like: element.getElement('type=[checkbox]').lol()
86
148
  is_in_string = line =~ /.*['"].*#{token[1]}.*=.*["'].*/
87
149
 
88
- # - scope access and comparison in if x == 'lol'
89
- is_in_comparison = line =~ /::|==/
150
+ # - scope access and comparison in if x == 'lol'
151
+ is_in_comparison = line =~ /::|==/
90
152
 
91
153
  # - objects with blank parent (parser bug?)
92
154
  has_blank_parent = o[:parent] =~ /\.$/
@@ -95,7 +157,7 @@ module Coffeetags
95
157
  is_previous_not_the_same = !(@tree.last and @tree.last[:name] == o[:name] and @tree.last[:level] == o[:level])
96
158
 
97
159
  if is_in_string.nil? and is_in_comparison.nil? and has_blank_parent.nil? and is_previous_not_the_same
98
- o[:kind] = line =~ /[:=]{1}.*[-=]\>/ ? 'f' : 'o'
160
+ o[:kind] = line =~ /[:=]{1}.*[-=]\>/ ? 'f' : 'o'
99
161
  o[:parent] = scope_path o
100
162
  o[:parent] = @fake_parent if o[:parent].empty?
101
163
 
@@ -103,7 +165,9 @@ module Coffeetags
103
165
  @tree << o if o[:kind] == 'o' and @include_vars
104
166
  end
105
167
  end
168
+ # get rid of duplicate entries
106
169
  @tree.uniq!
170
+ self # chain!
107
171
  end
108
172
  end
109
173
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Coffeetags
3
- VERSION = "0.0.2.2"
3
+ VERSION = "0.0.2.4"
4
4
  end
@@ -0,0 +1,7 @@
1
+ ###
2
+ Lol wut
3
+ echo : ->
4
+ echoes
5
+ ###
6
+
7
+ echo2 :-> console.log 'echo'
@@ -0,0 +1,7 @@
1
+ !_TAG_FILE_FORMAT 2 /extended format/
2
+ !_TAG_FILE_SORTED 0 /0=unsorted, 1=sorted, 2=foldcase/
3
+ !_TAG_PROGRAM_AUTHOR Łukasz Korecki /lukasz@coffeesounds.com/
4
+ !_TAG_PROGRAM_NAME CoffeeTags //
5
+ !_TAG_PROGRAM_URL https://github.com/lukaszkorecki/CoffeeTags /GitHub repository/
6
+ !_TAG_PROGRAM_VERSION 0.0.2.4 //
7
+ echo2 spec/fixtures/blockcomment.coffee /echo2/;" f lineno:7 object:window type:function
@@ -3,20 +3,29 @@
3
3
  !_TAG_PROGRAM_AUTHOR Łukasz Korecki /lukasz@coffeesounds.com/
4
4
  !_TAG_PROGRAM_NAME CoffeeTags //
5
5
  !_TAG_PROGRAM_URL https://github.com/lukaszkorecki/CoffeeTags /GitHub repository/
6
- !_TAG_PROGRAM_VERSION 0.0.2.2 //
6
+ !_TAG_PROGRAM_VERSION 0.0.2.4 //
7
7
  bump spec/fixtures/test.coffee /bump/;" f lineno:1 object:window type:function
8
+
8
9
  ho spec/fixtures/test.coffee /ho/;" f lineno:5 object:Wat type:function
10
+
9
11
  bump spec/fixtures/test.coffee /bump/;" f lineno:10 object:Wat.ho.@lolWat type:function
10
12
  bump_up spec/fixtures/test.coffee /bump_up/;" f lineno:12 object:Wat.ho.@lolWat type:function
11
13
  @filter spec/fixtures/test.coffee /@filter/;" f lineno:14 object:Wat.ho type:function
12
14
  _loop spec/fixtures/test.coffee /_loop/;" f lineno:19 object:window type:function
15
+
16
+
17
+
18
+
13
19
  bound_func spec/fixtures/test.coffee /bound_func/;" f lineno:41 object:window type:function
14
20
  beam_magnum spec/fixtures/test.coffee /beam_magnum/;" f lineno:44 object:window type:function
21
+
15
22
  constructor spec/fixtures/campfire.coffee /constructor/;" f lineno:8 object:Campfire type:function
16
23
  handlers spec/fixtures/campfire.coffee /handlers/;" f lineno:14 object:Campfire type:function
24
+
17
25
  onSuccess spec/fixtures/campfire.coffee /onSuccess/;" f lineno:16 object:Campfire.handlers.resp type:function
18
26
  onFailure spec/fixtures/campfire.coffee /onFailure/;" f lineno:24 object:Campfire.handlers.resp type:function
19
27
  rooms spec/fixtures/campfire.coffee /rooms/;" f lineno:29 object:Campfire type:function
20
28
  roomInfo spec/fixtures/campfire.coffee /roomInfo/;" f lineno:34 object:Campfire type:function
21
29
  recent spec/fixtures/campfire.coffee /recent/;" f lineno:40 object:Campfire type:function
30
+
22
31
  bump spec/fixtures/campfire.coffee /bump/;" f lineno:46 object:Test type:function
@@ -3,12 +3,18 @@
3
3
  !_TAG_PROGRAM_AUTHOR Łukasz Korecki /lukasz@coffeesounds.com/
4
4
  !_TAG_PROGRAM_NAME CoffeeTags //
5
5
  !_TAG_PROGRAM_URL https://github.com/lukaszkorecki/CoffeeTags /GitHub repository/
6
- !_TAG_PROGRAM_VERSION 0.0.2.2 //
6
+ !_TAG_PROGRAM_VERSION 0.0.2.4 //
7
7
  bump spec/fixtures/test.coffee /bump/;" f lineno:1 object:window type:function
8
+
8
9
  ho spec/fixtures/test.coffee /ho/;" f lineno:5 object:Wat type:function
10
+
9
11
  bump spec/fixtures/test.coffee /bump/;" f lineno:10 object:Wat.ho.@lolWat type:function
10
12
  bump_up spec/fixtures/test.coffee /bump_up/;" f lineno:12 object:Wat.ho.@lolWat type:function
11
13
  @filter spec/fixtures/test.coffee /@filter/;" f lineno:14 object:Wat.ho type:function
12
14
  _loop spec/fixtures/test.coffee /_loop/;" f lineno:19 object:window type:function
15
+
16
+
17
+
18
+
13
19
  bound_func spec/fixtures/test.coffee /bound_func/;" f lineno:41 object:window type:function
14
20
  beam_magnum spec/fixtures/test.coffee /beam_magnum/;" f lineno:44 object:window type:function
data/spec/parser_spec.rb CHANGED
@@ -167,5 +167,43 @@ describe 'CoffeeTags::Parser' do
167
167
  subject[:parent].should == '_loop'
168
168
  end
169
169
  end
170
+ context 'Block comments' do
171
+ let(:bc_file) { 'spec/fixtures/blockcomment.coffee'}
172
+ let(:bc_ctags_file) { 'spec/fixtures/blockcomment.ctags'}
173
+ let(:blockcomment_file) { File.read(bc_file)}
174
+ let(:blockcomment_tree) {
175
+ [{:level=>0,
176
+ :parent=>"window",
177
+ :source=>"echo2 :-> console.log 'echo'",
178
+ :line=>7,
179
+ :kind=>"f",
180
+ :name=>"echo2"}]
181
+ }
182
+
183
+ subject {
184
+ parser = Coffeetags::Parser.new(blockcomment_file, true)
185
+ parser.execute!
186
+ parser
187
+ }
188
+
189
+ it 'ignores block comments when parsing the contents' do
190
+ subject.tree.first.should == blockcomment_tree.first
191
+ end
192
+
193
+
194
+ context 'top-down test' do
195
+ let(:blockcomment_ctags){ File.read(bc_ctags_file) }
196
+ subject {
197
+ Coffeetags::Utils.run 'test_bc.out', nil, bc_file
198
+ File.read 'test_bc.out'
199
+ }
200
+
201
+ after(:all) { `rm test_bc.out` }
202
+
203
+ it 'ignores block comments in output' do
204
+ subject.should == blockcomment_ctags
205
+ end
206
+ end
207
+ end
170
208
  end
171
209
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: CoffeeTags
3
3
  version: !ruby/object:Gem::Version
4
- hash: 67
4
+ hash: 79
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
9
  - 2
10
- - 2
11
- version: 0.0.2.2
10
+ - 4
11
+ version: 0.0.2.4
12
12
  platform: ruby
13
13
  authors:
14
14
  - "\xC5\x81ukasz Korecki"
@@ -16,8 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-03-06 00:00:00 +00:00
20
- default_executable:
19
+ date: 2012-03-12 00:00:00 Z
21
20
  dependencies: []
22
21
 
23
22
  description: CoffeeTags generates ctags compatibile tags for CoffeeScript.
@@ -45,6 +44,8 @@ files:
45
44
  - lib/CoffeeTags/parser.rb
46
45
  - lib/CoffeeTags/version.rb
47
46
  - spec/coffeetags_spec.rb
47
+ - spec/fixtures/blockcomment.coffee
48
+ - spec/fixtures/blockcomment.ctags
48
49
  - spec/fixtures/campfire.coffee
49
50
  - spec/fixtures/campfire.js
50
51
  - spec/fixtures/campfire.js.tags
@@ -60,7 +61,6 @@ files:
60
61
  - tagbar-info.markdown
61
62
  - test.rb
62
63
  - vim/tagbar-coffee.vim.erb
63
- has_rdoc: true
64
64
  homepage: http://github.com/lukaszkorecki/CoffeeTags
65
65
  licenses: []
66
66
 
@@ -90,12 +90,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
90
  requirements: []
91
91
 
92
92
  rubyforge_project: CoffeeTags
93
- rubygems_version: 1.5.0
93
+ rubygems_version: 1.8.16
94
94
  signing_key:
95
95
  specification_version: 3
96
96
  summary: tags generator for CoffeeScript
97
97
  test_files:
98
98
  - spec/coffeetags_spec.rb
99
+ - spec/fixtures/blockcomment.coffee
100
+ - spec/fixtures/blockcomment.ctags
99
101
  - spec/fixtures/campfire.coffee
100
102
  - spec/fixtures/campfire.js
101
103
  - spec/fixtures/campfire.js.tags