ctags_reader 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: 9689fd7ce96e3dbd6933637c1747693dfa5510fd
4
+ data.tar.gz: 91ec113a5e0660b9228f1df560cc12edc554a408
5
+ SHA512:
6
+ metadata.gz: 54202224751b723409202ea14fdd994ad7dc34a713b74216596270c75495a7df8f312730dd12933a8aa448c112aa2705d98e97c70eba2170af0855d1287d85df
7
+ data.tar.gz: b2bf7bfa87f3abd0c0c5933aea03ce92ff06fbc29ac8716ba79bd142818dc9af4996083c573b9a375cc5075017ecbc624e613cbbe89ef8c5d33e51587f1cd8a2
data/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
2
+
3
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ Ctags "tags" files provide a treasure trove of information on the locations of symbols in a project. Since ruby is such a strongly opinionated language, we can also make some educated guesses in order to get even more useful information out of it.
2
+
3
+ For now, the project only reads the tags and provides a very simple interface to them, but in the future, more stuff may be added.
4
+
5
+ ## Usage
6
+
7
+ ``` ruby
8
+ require 'ctags_reader'
9
+
10
+ reader = CtagsReader.read('~/src/rails/tags')
11
+
12
+ # Look for a direct match
13
+ puts reader.find('Rails')
14
+
15
+ # Get a single tag that starts with the given string
16
+ puts reader.find('^Active')
17
+
18
+ # Get all matching tags
19
+ puts reader.find_all('^Active').shuffle.take(5)
20
+
21
+ # Use Array#bsearch if available
22
+ puts reader.fast_find('^Active')
23
+
24
+ # Use some heuristics for advanced matching
25
+ puts reader.find('ActionController::Metal#initialize')
26
+ ```
@@ -0,0 +1,17 @@
1
+ require 'ctags_reader/reader'
2
+
3
+ module CtagsReader
4
+ # Convenience method to parse a tags file into a Reader object.
5
+ #
6
+ def self.read(filename)
7
+ Reader.new(filename)
8
+ end
9
+
10
+ # While the reader attempts to parse different formats of ctags, the
11
+ # .generate method generates ruby tags in the most convenient way for the
12
+ # reader.
13
+ #
14
+ def self.generate
15
+ system 'ctags --languages=ruby --excmd=number -R .'
16
+ end
17
+ end
@@ -0,0 +1,125 @@
1
+ require 'active_support/inflector/methods'
2
+ require 'ctags_reader/tag'
3
+
4
+ module CtagsReader
5
+ # A Reader can be initialized either with a file (or any IO stream), or with
6
+ # a filename. In the second case, the filename is opened in read-only mode
7
+ # and parsed for tags.
8
+ #
9
+ # Note that parsing is done immediately upon initialization.
10
+ #
11
+ class Reader
12
+ def initialize(file)
13
+ if file.is_a? String
14
+ @filename = File.expand_path(file)
15
+ else
16
+ @file = file
17
+ end
18
+
19
+ @tag_index = nil
20
+ end
21
+
22
+ def tag_index
23
+ parse if not @tag_index
24
+ @tag_index
25
+ end
26
+
27
+ def file(&block)
28
+ if @file
29
+ yield @file
30
+ else
31
+ File.open(@filename, 'r') do |file|
32
+ yield file
33
+ end
34
+ end
35
+ end
36
+
37
+ def names
38
+ @names ||= tag_index.keys
39
+ end
40
+
41
+ def tags
42
+ @tags ||= tag_index.values.flatten
43
+ end
44
+
45
+ def tag_count
46
+ tags.count
47
+ end
48
+
49
+ if [].respond_to?(:bsearch)
50
+ def fast_find(query)
51
+ if query.start_with?('^')
52
+ # drop the ^, look for a prefix
53
+ prefix = query[1..-1]
54
+ tags.bsearch { |tag| prefix <=> tag.name[0...prefix.length] }
55
+ else
56
+ # should be a direct match
57
+ (tag_index[query] || []).first
58
+ end
59
+ end
60
+ else
61
+ def fast_find(query)
62
+ find(query)
63
+ end
64
+ end
65
+
66
+ def find(query)
67
+ find_all(query).first
68
+ end
69
+
70
+ def find_all(query)
71
+ if query.include?('#')
72
+ class_name, method_name = query.split('#')
73
+ class_filenames = find_all(class_name).map(&:filename).uniq
74
+
75
+ find_all(method_name).select do |tag|
76
+ class_filenames.include?(tag.filename)
77
+ end
78
+ elsif query.include?('::')
79
+ filename = class_to_filename(query)
80
+ class_name = query.split('::').last
81
+
82
+ direct_find_all(class_name).select do |tag|
83
+ tag.filename =~ /#{filename}$/
84
+ end
85
+ else
86
+ direct_find_all(query)
87
+ end
88
+ end
89
+
90
+ def to_s
91
+ "#<CtagsReader::Reader:#{object_id} (#{tag_count} tags)>"
92
+ end
93
+
94
+ private
95
+
96
+ def class_to_filename(full_class_name)
97
+ ActiveSupport::Inflector.underscore(full_class_name) + '.rb'
98
+ end
99
+
100
+ def direct_find_all(query)
101
+ if query.start_with?('^')
102
+ # consider it a regex
103
+ pattern = Regexp.new(query)
104
+ tag_index.select { |name, tags| name =~ pattern }.map(&:last).flatten
105
+ else
106
+ # should be a direct match
107
+ tag_index[query] || []
108
+ end
109
+ end
110
+
111
+ def parse
112
+ @tag_index = {}
113
+
114
+ file do |handle|
115
+ handle.each_line do |line|
116
+ next if line.start_with?('!_TAG_')
117
+
118
+ tag = Tag.from_string(line)
119
+ @tag_index[tag.name] ||= []
120
+ @tag_index[tag.name] << tag
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,44 @@
1
+ module CtagsReader
2
+ # The Tag is the representation of each tag in the tags file. It can be
3
+ # initialized manually by giving it its four components, but it can also be
4
+ # created from a tab-delimited line from the file.
5
+ #
6
+ class Tag < Struct.new(:name, :filename, :ex_command, :type)
7
+ def self.from_string(string)
8
+ name, filename, ex_command, type = string.split("\t")
9
+ new(name, filename, ex_command, type)
10
+ end
11
+
12
+ def line_number
13
+ @line_number ||= calculate_line_number
14
+ end
15
+
16
+ private
17
+
18
+ def calculate_line_number
19
+ if ex_command.to_i > 0
20
+ return ex_command.to_i
21
+ end
22
+
23
+ if not File.readable?(filename)
24
+ return 1
25
+ end
26
+
27
+ # remove wrapping / and /;"
28
+ pattern = ex_command.gsub(/^\//, '').gsub(/\/(;")?$/, '')
29
+ regex = Regexp.new(pattern)
30
+
31
+ # try to find line number from file
32
+ File.open(filename, 'r') do |file|
33
+ index = 1
34
+ file.each_line do |line|
35
+ return index if line =~ regex
36
+ index += 1
37
+ end
38
+ end
39
+
40
+ # pattern wasn't found, fall back to line 1
41
+ return 1
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module CtagsReader
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ctags_reader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Radev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.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.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |2
56
+ Ctags "tags" files provide a treasure trove of information on the locations
57
+ of symbols in a project. Since ruby is such a strongly opinionated
58
+ language, we can also make some educated guesses in order to get even more
59
+ useful information out of it.
60
+ email:
61
+ - andrey.radev@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - lib/ctags_reader.rb
67
+ - lib/ctags_reader/reader.rb
68
+ - lib/ctags_reader/version.rb
69
+ - lib/ctags_reader/tag.rb
70
+ - LICENSE
71
+ - README.md
72
+ homepage: http://github.com/AndrewRadev/ctags_reader
73
+ licenses: []
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: 1.3.6
89
+ requirements: []
90
+ rubyforge_project: ctags_reader
91
+ rubygems_version: 2.0.5
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Read a ctags "tags" file and provide an interface to its information
95
+ test_files: []