rb_tags 0.1.0

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: a67c84f973778879cabed5a52a9bf9b8d9328af9
4
+ data.tar.gz: 230f1a39761dff1665a17db4a88ca8b27c8debb9
5
+ SHA512:
6
+ metadata.gz: b3d389f0dff8660b3d505906545683cea667711e3bf1b52855580637059d2e710dee798169175051a59f5395047790a2b9b7722f52692f889693f9802ef3db43
7
+ data.tar.gz: 54fd41a42fc5f63b2d0b3a63dab5597a3ed8d86599e650633d0241985cd3f6df2a2fad34f6526063c64093833813ed4b65a7e8c8206e9dd7ca2541cbfec99c83
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .tags
2
+ .tags
3
+ pkg/
4
+ ToDos.md
5
+ coverage/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'simplecov', require: false, group: :test
data/Gemfile.lock ADDED
@@ -0,0 +1,103 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rb_tags (0.1.0)
5
+ bundler
6
+ colorize
7
+ gli
8
+ parallel
9
+ parslet
10
+ rake
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ awesome_print (1.6.1)
16
+ blankslate (3.1.3)
17
+ celluloid (0.16.0)
18
+ timers (~> 4.0.0)
19
+ coderay (1.1.0)
20
+ colorize (0.7.7)
21
+ diff-lcs (1.2.5)
22
+ docile (1.1.5)
23
+ ffi (1.9.8)
24
+ formatador (0.2.5)
25
+ gli (2.13.1)
26
+ guard (2.12.5)
27
+ formatador (>= 0.2.4)
28
+ listen (~> 2.7)
29
+ lumberjack (~> 1.0)
30
+ nenv (~> 0.1)
31
+ notiffany (~> 0.0)
32
+ pry (>= 0.9.12)
33
+ shellany (~> 0.0)
34
+ thor (>= 0.18.1)
35
+ guard-bundler (2.1.0)
36
+ bundler (~> 1.0)
37
+ guard (~> 2.2)
38
+ guard-compat (~> 1.1)
39
+ guard-compat (1.2.1)
40
+ guard-rspec (4.5.0)
41
+ guard (~> 2.1)
42
+ guard-compat (~> 1.1)
43
+ rspec (>= 2.99.0, < 4.0)
44
+ hitimes (1.2.2)
45
+ json (1.8.2)
46
+ listen (2.10.0)
47
+ celluloid (~> 0.16.0)
48
+ rb-fsevent (>= 0.9.3)
49
+ rb-inotify (>= 0.9)
50
+ lumberjack (1.0.9)
51
+ method_source (0.8.2)
52
+ nenv (0.2.0)
53
+ notiffany (0.0.6)
54
+ nenv (~> 0.1)
55
+ shellany (~> 0.0)
56
+ parallel (1.6.0)
57
+ parslet (1.7.0)
58
+ blankslate (>= 2.0, <= 4.0)
59
+ pry (0.10.1)
60
+ coderay (~> 1.1.0)
61
+ method_source (~> 0.8.1)
62
+ slop (~> 3.4)
63
+ rake (10.4.2)
64
+ rb-fsevent (0.9.5)
65
+ rb-inotify (0.9.5)
66
+ ffi (>= 0.5.0)
67
+ rspec (3.2.0)
68
+ rspec-core (~> 3.2.0)
69
+ rspec-expectations (~> 3.2.0)
70
+ rspec-mocks (~> 3.2.0)
71
+ rspec-core (3.2.3)
72
+ rspec-support (~> 3.2.0)
73
+ rspec-expectations (3.2.1)
74
+ diff-lcs (>= 1.2.0, < 2.0)
75
+ rspec-support (~> 3.2.0)
76
+ rspec-mocks (3.2.1)
77
+ diff-lcs (>= 1.2.0, < 2.0)
78
+ rspec-support (~> 3.2.0)
79
+ rspec-support (3.2.2)
80
+ shellany (0.0.1)
81
+ simplecov (0.10.0)
82
+ docile (~> 1.1.0)
83
+ json (~> 1.8)
84
+ simplecov-html (~> 0.10.0)
85
+ simplecov-html (0.10.0)
86
+ slop (3.6.0)
87
+ terminal-notifier-guard (1.6.4)
88
+ thor (0.19.1)
89
+ timers (4.0.1)
90
+ hitimes
91
+
92
+ PLATFORMS
93
+ ruby
94
+
95
+ DEPENDENCIES
96
+ awesome_print
97
+ guard-bundler
98
+ guard-rspec
99
+ rb-fsevent
100
+ rb_tags!
101
+ rspec
102
+ simplecov
103
+ terminal-notifier-guard
data/Guardfile ADDED
@@ -0,0 +1,51 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), then you will want to move
18
+ ## the Guardfile to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ guard :bundler do
27
+ require 'guard/bundler'
28
+ require 'guard/bundler/verify'
29
+ helper = Guard::Bundler::Verify.new
30
+
31
+ files = ['Gemfile']
32
+ files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
33
+
34
+ # Assume files are symlinked from somewhere
35
+ files.each { |file| watch(helper.real_path(file)) }
36
+ end
37
+
38
+ guard :rspec, cmd: "bundle exec rspec" do
39
+ require "guard/rspec/dsl"
40
+ dsl = Guard::RSpec::Dsl.new(self)
41
+
42
+ # Ruby files
43
+ ruby = dsl.ruby
44
+ dsl.watch_spec_files_for(ruby.lib_files)
45
+
46
+ # RSpec files
47
+ rspec = dsl.rspec
48
+ watch(rspec.spec_helper) { rspec.spec_dir }
49
+ watch(rspec.spec_support) { rspec.spec_dir }
50
+ watch(rspec.spec_files)
51
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 LeFnord
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # RbTags
2
+
3
+ Generate tags file for your ruby project and bundled gems, based on ctags.
4
+
5
+ ## Installation
6
+
7
+ Install it using
8
+
9
+ `gem install rb_tags`
10
+
11
+ ## Requirements
12
+
13
+ The gem requires that you have
14
+
15
+ * `find`
16
+ * `ctags`
17
+
18
+ in your path.
19
+
20
+ ## Usage
21
+
22
+ `cd` into your project and simple type
23
+
24
+ `rb_tags -h`
25
+
26
+ ```
27
+
28
+ NAME
29
+ rb_tags - Describe your application here
30
+
31
+ SYNOPSIS
32
+ rb_tags [global options] command [command options] [arguments...]
33
+
34
+ VERSION
35
+ 0.0.5
36
+
37
+ GLOBAL OPTIONS
38
+ --help - Show this message
39
+ --version - Display the program version
40
+
41
+ COMMANDS
42
+ find - search for a tag
43
+ help - Shows a list of commands or help for one command
44
+ show - show esisting tags
45
+ tag - tags a given directory
46
+
47
+ ```
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
56
+
57
+
58
+ ## Author
59
+
60
+ LeFnord
61
+
62
+ ## License
63
+
64
+ see [License](LICENSE.txt)
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/rb_tags ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gli'
4
+ require 'readline'
5
+
6
+ begin # XXX: Remove this begin/rescue before distributing your app
7
+ require 'rb_tags'
8
+ self.extend RbTags
9
+ rescue LoadError
10
+ STDERR.puts "In development, you need to use `bundle exec bin/rb_tags` to run your app"
11
+ STDERR.puts "At install-time, RubyGems will make sure lib, etc. are in the load path"
12
+ STDERR.puts "Feel free to remove this message from bin/rb_tags now"
13
+ exit 64
14
+ end
15
+
16
+ include GLI::App
17
+
18
+ program_desc 'Describe your application here'
19
+
20
+ version RbTags::VERSION
21
+
22
+ subcommand_option_handling :normal
23
+ arguments :strict
24
+
25
+ # # global options
26
+ # desc 'Describe some switch here'
27
+ # switch [:s,:switch]
28
+ #
29
+ # desc 'Describe some flag here'
30
+ # default_value 'the default'
31
+ # arg_name 'The name of the argument'
32
+ # flag [:f,:flagname]
33
+
34
+ desc 'tags a given directory'
35
+ command :tag do |c|
36
+ # switches
37
+ c.desc 'tag also bundled gems'
38
+ c.switch [:gems], :default_value => false
39
+
40
+ c.action do |global_options,options,args|
41
+ generate(options)
42
+ end
43
+ end
44
+
45
+ desc 'show esisting tags'
46
+ command :show do |c|
47
+ c.action do |global_options,options,args|
48
+ ap tags
49
+ ap tags.length
50
+ end
51
+ end
52
+
53
+ desc 'search for a tag'
54
+ command :find do |c|
55
+ c.action do |global_options,options,args|
56
+ find
57
+ ap @found
58
+ $stdout.print "open [#{(0 ... @found.length).to_a.join(',')}]: ".green
59
+ what = ''
60
+ while (what += $stdin.getch) !~ /(\w\s)/
61
+ $stdout.print "#{what}".blue
62
+ end
63
+ open what
64
+ end
65
+ end
66
+
67
+ pre do |global,command,options,args|
68
+ # Pre logic here
69
+ # Return true to proceed; false to abort and not call the
70
+ # chosen command
71
+ # Use skips_pre before a command to skip this block
72
+ # on that command only
73
+ true
74
+ end
75
+
76
+ post do |global,command,options,args|
77
+ # Post logic here
78
+ # Use skips_post before a command to skip this
79
+ # block on that command only
80
+ end
81
+
82
+ on_error do |exception|
83
+ # Error logic here
84
+ # return false to skip default error handling
85
+ true
86
+ end
87
+
88
+ # list = self.commands.keys.collect { |x| x.to_s }
89
+ # args = complete(list)
90
+ exit run(ARGV)
@@ -0,0 +1,24 @@
1
+ module Completion
2
+ module_function
3
+
4
+ def complete(list)
5
+ # :nocov:
6
+ comp = proc { |s| list.grep(/^#{Regexp.escape(s)}/) }
7
+
8
+ Readline.completer_word_break_characters = ""
9
+ Readline.completion_append_character = " "
10
+ Readline.completion_proc = comp
11
+
12
+ while line = Readline.readline('$ ', true)
13
+ unless line[-1] =~ /(\n\r)/
14
+ args = line.split(' ')
15
+ break
16
+ end
17
+ end
18
+
19
+ args
20
+ # :nocov:
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,30 @@
1
+ module GenerateTags
2
+ # find ctags and split in single lines
3
+ def find_expressions(dir,mask)
4
+ found_tags = `find #{dir} -name '*.rb' | ctags -x -L -`.split("\n")
5
+ parse_expression_line(found_tags)
6
+ generate_hash
7
+ end
8
+
9
+ #parse found expression line
10
+ def parse_expression_line(found_tags)
11
+ @tags = []
12
+ found_tags.each do |tag_line|
13
+ begin
14
+ parsed_line = Parser.new.parse(tag_line)
15
+ @tags << ParserTransform.new.apply(parsed_line)
16
+ rescue Parslet::ParseFailed => error
17
+ message = ["[RbTags] Error: ", "line: ", "#{tag_line} ", "error: ", "#{error.cause.ascii_tree}"]
18
+ message.each { |m| $stdout.puts "#{m}" }
19
+ @tags << message.join("\n")
20
+ end
21
+ end
22
+
23
+ @tags
24
+ end
25
+
26
+ # converts array of hashes into single hash
27
+ def generate_hash
28
+ @tags.group_by{|x| x[:name]; x.delete(:name) }
29
+ end
30
+ end
@@ -0,0 +1,46 @@
1
+ class Parser < Parslet::Parser
2
+ #atomic rules
3
+ rule(:space) { match['[:space:]'] }
4
+ rule(:spaces) { space.repeat(1) }
5
+ rule(:word) { match['\w'].repeat(1) }
6
+ rule(:line) { match['[:digit:]'].repeat(1) }
7
+ rule(:separator) { str('/') }
8
+
9
+ # composing rules
10
+ ## names, word-or_foo
11
+ rule(:name_adds) { match['$_-'] >> word.repeat(1) }
12
+ rule(:simple_name) { word.repeat(1) >> name_adds.repeat }
13
+ rule(:name) { match['$'].maybe >> simple_name >> match['\S'].maybe | match['\W'].repeat(1,3)}
14
+
15
+ ## part of path, word/
16
+ rule(:path) { separator >> match['\S'].repeat(1) }
17
+
18
+ ## full input
19
+ rule(:whole_line) {
20
+ name.as(:name) >> spaces >>
21
+ (word >> space >> word | word).as(:type) >> spaces >>
22
+ line.as(:line) >> spaces >>
23
+ path.as(:path) >> spaces >>
24
+ any.repeat.as(:definition)
25
+ }
26
+
27
+
28
+ root(:whole_line)
29
+ end
30
+
31
+ class ParserTransform < Parslet::Transform
32
+ rule(name: simple(:name),
33
+ type: simple(:type),
34
+ line: simple(:line),
35
+ path: simple(:path),
36
+ definition: simple(:definition)
37
+ ) {
38
+ {
39
+ name: name.str,
40
+ type: type.str,
41
+ line: line.str,
42
+ path: path.str,
43
+ definition: definition.str
44
+ }
45
+ }
46
+ end
@@ -0,0 +1,21 @@
1
+ # author LeFnord
2
+ # email pscholz.le@gmail.com
3
+ # date 2013-12-18
4
+
5
+
6
+ module SysInfo
7
+ module_function
8
+
9
+ def number_of_processors
10
+ # :nocov:
11
+ if RUBY_PLATFORM =~ /linux/
12
+ return `cat /proc/cpuinfo | grep processor | wc -l`.to_i
13
+ elsif RUBY_PLATFORM =~ /darwin/
14
+ return `sysctl -n hw.logicalcpu`.to_i
15
+ else
16
+ return 2
17
+ end
18
+ # :nocov:
19
+ end
20
+
21
+ end
@@ -0,0 +1,18 @@
1
+ module YamlTasks
2
+ def read_from_yaml_file dir: nil
3
+ YAML.load_file(store(dir)) if File.exist?(store(dir))
4
+ end
5
+
6
+ def write_to_yaml dir: nil, this: {}
7
+ File.open(store(dir), 'w') {|out| YAML.dump this, out}
8
+ end
9
+
10
+ private
11
+ def store(dir = nil)
12
+ if !!dir
13
+ store = File.join(dir,".tags")
14
+ else
15
+ store = File.join(Dir.getwd,".tags")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ class Tags
2
+ include GenerateTags
3
+ include YamlTasks
4
+
5
+ attr_reader :dir, :tags, :names
6
+
7
+ def initialize(dir = Dir.getwd, read: false)
8
+ @dir = dir
9
+ if read
10
+ self.read
11
+ self.names
12
+ end
13
+ end
14
+
15
+ def tag
16
+ FileUtils.cd(@dir) { |dir| @tags = find_expressions(dir, @mask) }
17
+ end
18
+
19
+ def add(tags)
20
+ tags.each do |key,value|
21
+ if self.tags.key?(key)
22
+ self.tags[key] += value
23
+ else
24
+ self.tags[key] = value
25
+ end
26
+ end
27
+ end
28
+
29
+ def save
30
+ write_to_yaml(dir: @dir, this: @tags)
31
+ end
32
+
33
+ def read
34
+ @tags = read_from_yaml_file(dir: @dir)
35
+ tag if @tags.nil?
36
+ end
37
+
38
+ def names
39
+ @name ||= @tags.keys
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module RbTags
2
+ VERSION = '0.1.0'
3
+ end
data/lib/rb_tags.rb ADDED
@@ -0,0 +1,151 @@
1
+ # external requirements
2
+ require 'bundler'
3
+ require 'awesome_print'
4
+ require 'yaml'
5
+ require 'readline'
6
+ require 'parallel'
7
+ require 'parslet'
8
+ require 'parslet/convenience'
9
+ require 'colorize'
10
+
11
+ # internal requirements
12
+ require 'rb_tags/version.rb'
13
+
14
+ require 'rb_tags/concerns/sys_info'
15
+ require 'rb_tags/concerns/generate_tags'
16
+ require 'rb_tags/concerns/parser'
17
+ require 'rb_tags/concerns/yaml_tasks'
18
+ require 'rb_tags/concerns/completion'
19
+
20
+ require 'rb_tags/tags'
21
+
22
+ module RbTags
23
+ include SysInfo
24
+ include Completion
25
+
26
+ def generate(options={})
27
+ tags = Tags.new(default_dir)
28
+ tags.tag
29
+
30
+ default_options(options)
31
+ if @options[:gems]
32
+ result = tag_bundled_gems
33
+ result.each { |g| tags.add(g.tags) }
34
+ end
35
+
36
+ tags.save
37
+ end
38
+
39
+ def tag_bundled_gems
40
+ build_gem_list
41
+ results = ::Parallel.map(@gem_list.each_slice(number_of_processors),
42
+ in_processes: number_of_processors) do |dir_list|
43
+ gem_list = Tags.new(dir_list.shift)
44
+ gem_list.tag
45
+
46
+ dir_list.each do |dir|
47
+ gem_tags = Tags.new(dir, read: true)
48
+ unless !!gem_tags.tags
49
+ gem_tags.tag
50
+ gem_tags.save
51
+ say_tagging(gem_tags.dir)
52
+ end
53
+ gem_list.add(gem_tags.tags)
54
+ end
55
+
56
+ gem_list
57
+ end
58
+
59
+ results
60
+ end
61
+
62
+ def say_tagging(dir)
63
+ $stdout.print "tag gem: ".blue
64
+ $stdout.print "#{dir}".colorize(:yellow_light)
65
+ $stdout.print " first time\n".blue
66
+ end
67
+
68
+ def tags
69
+ get_existend_tags
70
+ @tags.names
71
+ end
72
+
73
+ # used for command line
74
+ def find
75
+ get_existend_tags
76
+ arg = complete(@tags.names).first
77
+ @found = found(arg)
78
+ end
79
+
80
+ def found(arg)
81
+ @tags.tags[arg]
82
+ end
83
+
84
+ def open(what = 0)
85
+ if what !~ /\d+/
86
+ message = "\n sorry '#{what.chomp!}' not yet supported ...\n use an array index\n"
87
+ message.rjust(27).split(//).each do |char|
88
+ $stdout.print char.colorize(:light_red)
89
+ sleep 0.0057
90
+ end
91
+ return
92
+ end
93
+
94
+ opend_found selected: @found[what.to_i], editor: ENV['EDITOR']
95
+ end
96
+
97
+ # attributes
98
+ def options
99
+ @options
100
+ end
101
+
102
+ def gem_list
103
+ @gem_list
104
+ end
105
+
106
+
107
+ private
108
+
109
+ def get_existend_tags
110
+ @tags ||= Tags.new(read: true)
111
+ end
112
+
113
+ def build_gem_list
114
+ if File.exist? gem_file
115
+ @gem_list = Bundler.load.specs.map(&:full_gem_path) - [default_dir]
116
+ end
117
+ end
118
+
119
+ def gem_file
120
+ File.join(default_dir, './Gemfile')
121
+ end
122
+
123
+ def default_options(options)
124
+ @options = options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
125
+ @options.delete(:dir) if @options[:dir].nil?
126
+ @options.merge!(defaults) { |key, opt, default| opt }
127
+ end
128
+
129
+ def defaults
130
+ { gems: false }
131
+ end
132
+
133
+ def default_dir
134
+ Dir.getwd
135
+ end
136
+
137
+ def opend_found selected: {}, editor: 'mate'
138
+ # :nocov:
139
+ file_line = "#{selected[:line]} #{selected[:path]}"
140
+ case editor
141
+ when 'mate'
142
+ `mate -l #{file_line}`
143
+ when 'emacs'
144
+ `emacs --no-splash +#{file_line}`
145
+ else
146
+ `vim +#{file_line}`
147
+ end
148
+ # :nocov:
149
+ end
150
+
151
+ end