core_docs 0.9.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef9c9b9dc66c55c7cfa891c263014f2c2e76d7eb
4
+ data.tar.gz: 987df53f273c819846120fcc6f09b8274cc1cbec
5
+ SHA512:
6
+ metadata.gz: db62934c09ab1be4ca56cc44a93a95e1f1908a3cc41259cd49044d4cc5d72e8a5ce8d263ba94691ef76aef61db6c8259e81fb04aeb1eaef20a4f7c10b7752d5e
7
+ data.tar.gz: b23f4960d820ab46968dca9d17bb8ab6ff2644ee9e393f569df1228ea1a61e6282194ce847c2571ccdbece946f95dce8965863680409be0cfba81c5de1dbff5d
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ Makefile
2
+ *.so
3
+ *.o
4
+ *.def
5
+ doc/
6
+ pkg/
7
+ .yardoc/
8
+ *.gem
9
+ Gemfile.lock
10
+ *~
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.0
5
+ - 2.1.1
6
+ - ruby-head
7
+
8
+ script:
9
+ - rake spec
10
+
11
+ branches:
12
+ only:
13
+ - master
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ Core Docs changelog
2
+ ===================
3
+
4
+ ### v0.9.0
5
+
6
+ * Ported from pry-doc
7
+ * Remove 1.9, add 2.2, and rebuild 2.1, 2.0 docs
8
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ License
2
+ -------
3
+
4
+ (The MIT License)
5
+
6
+ Copyright (c) 2013 John Mair (banisterfiend)
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ 'Software'), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ MRI Core Docs
2
+ =============
3
+
4
+ Core Docs is a fork from [pry-doc](https://github.com/pry/pry-doc) that separates its functionality from the pry repl.
5
+
6
+ Experimental, don't consider this battle-proof.
7
+
8
+
9
+ TODO
10
+ ----
11
+
12
+ Polish and get specs to run.
13
+
14
+
15
+ License
16
+ -------
17
+
18
+ The project uses the MIT Licencse. See LICENSE file for more information.
data/Rakefile ADDED
@@ -0,0 +1,107 @@
1
+ dlext = RbConfig::CONFIG['DLEXT']
2
+ direc = File.dirname(__FILE__)
3
+
4
+ PROJECT_NAME = "core_docs"
5
+
6
+ require 'latest_ruby'
7
+ require 'rake/clean'
8
+ require "#{direc}/lib/#{PROJECT_NAME}/version"
9
+
10
+ desc "run tests"
11
+ task :test do
12
+ sh "bacon -k #{direc}/spec/core_docs_spec.rb"
13
+ end
14
+ task :spec => :test
15
+
16
+ task :default => :test
17
+
18
+ desc "reinstall gem"
19
+ task :reinstall => :gems do
20
+ sh "gem uninstall core_docs" rescue nil
21
+ sh "gem install #{direc}/pkg/core_docs-#{CoreDocs::VERSION}.gem"
22
+ end
23
+
24
+ desc "build all platform gems at once"
25
+ task :gems => :rmgems do
26
+ mkdir_p "pkg"
27
+ sh 'gem build *.gemspec'
28
+ mv "core_docs-#{CoreDocs::VERSION}.gem", "pkg"
29
+ end
30
+
31
+ desc "remove all platform gems"
32
+ task :rmgems do
33
+ rm_rf 'pkg'
34
+ end
35
+
36
+ desc "Build gemspec"
37
+ task :gemspec => "ruby:gemspec"
38
+
39
+ desc "Show version"
40
+ task :version do
41
+ puts "CoreDocs version: #{CoreDocs::VERSION}"
42
+ end
43
+
44
+ desc "build and push latest gems"
45
+ task :pushgems => :gems do
46
+ chdir("#{direc}/pkg") do
47
+ Dir["*.gem"].each do |gemfile|
48
+ sh "gem push #{gemfile}"
49
+ end
50
+ end
51
+ end
52
+
53
+ def download_ruby(ruby)
54
+ system "mkdir rubies"
55
+ system "wget #{ ruby.link } --directory-prefix=rubies --no-clobber"
56
+ File.join('rubies', ruby.filename)
57
+ end
58
+
59
+ def unpackage_ruby(path)
60
+ system "mkdir rubies/ruby"
61
+ system "tar xzvf #{ path } --directory=rubies/ruby"
62
+ end
63
+
64
+ def cd_into_ruby
65
+ Dir.chdir(Dir['rubies/ruby/*'].first)
66
+ end
67
+
68
+ def generate_yard
69
+ system %{
70
+ bash -c "paste <(find . -maxdepth 1 -name '*.c') <(find ext -name '*.c') |
71
+ xargs yardoc --no-output"
72
+ }
73
+ end
74
+
75
+ def replace_existing_docs(ver)
76
+ target_dir = "../../../lib/core_docs/core_docs_#{ ver }"
77
+ system %|mkdir -p #{ target_dir } && cp -r .yardoc/* #{ target_dir }|
78
+ Dir.chdir(File.expand_path(File.dirname(__FILE__)))
79
+ end
80
+
81
+ def clean_up
82
+ system "rm -rf rubies"
83
+ end
84
+
85
+ def generate_docs_for(ruby_ver, latest_ruby)
86
+ path = download_ruby(latest_ruby)
87
+ unpackage_ruby(path)
88
+ cd_into_ruby
89
+ generate_yard
90
+ replace_existing_docs(ruby_ver)
91
+ clean_up
92
+ end
93
+
94
+ desc "Generate the latest Ruby 2.0 docs"
95
+ task "gen20" do
96
+ generate_docs_for('20', Latest.ruby20)
97
+ end
98
+
99
+ desc "Generate the latest Ruby 2.1 docs"
100
+ task "gen21" do
101
+ generate_docs_for('21', Latest.ruby21)
102
+ end
103
+
104
+ desc "Generate the latest Ruby 2.2 docs"
105
+ task "gen22" do
106
+ generate_docs_for('22', Latest.ruby22)
107
+ end
data/core_docs.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ require './lib/core_docs/version.rb'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "core_docs"
5
+ s.version = CoreDocs::VERSION
6
+
7
+ s.authors = ["John Mair (banisterfiend)", "Jan Lelis (non-pry version)"]
8
+ s.email = ["jrmair@gmail.com", "mail@janlelis.de"]
9
+ s.summary = 'Provides YARD and extended documentation support for Pry'
10
+ s.description = <<DESCR
11
+ Pry Doc is a Pry REPL plugin. It provides extended documentation support for the
12
+ REPL by means of improving the `show-doc` and `show-source` commands. With help
13
+ of the plugin the commands are be able to display the source code and the docs
14
+ of Ruby methods and classes implemented in C.
15
+ documentation
16
+ DESCR
17
+ s.homepage = "https://github.com/janlelis/core_docs"
18
+ s.license = 'MIT'
19
+
20
+ s.require_paths = ["lib"]
21
+ s.files = `git ls-files`.split("\n")
22
+
23
+ s.required_ruby_version = "~> 2.0"
24
+ s.add_dependency 'yard', "~> 0.8"
25
+ s.add_development_dependency 'latest_ruby', "~> 0.0"
26
+ s.add_development_dependency 'bacon', "~> 1.1"
27
+ end
data/lib/core_docs.rb ADDED
@@ -0,0 +1,228 @@
1
+ # based on pry-doc.rb
2
+ # (C) John Mair (banisterfiend); MIT license
3
+
4
+ direc = File.dirname(__FILE__)
5
+
6
+ require "#{direc}/core_docs/version"
7
+ require "yard"
8
+
9
+ module CoreDocs
10
+ def self.load_yardoc(version)
11
+ path = "#{File.dirname(__FILE__)}/core_docs/core_docs_#{ version }"
12
+ YARD::Registry.load_yardoc(path)
13
+ end
14
+ end
15
+
16
+ case RUBY_VERSION
17
+ when /\A2\.1/
18
+ CoreDocs.load_yardoc('21')
19
+ else
20
+ CoreDocs.load_yardoc('20')
21
+ end
22
+
23
+ # do not use pry-doc if rbx is active
24
+ # if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
25
+ # self.config.has_pry_doc = true
26
+ # end
27
+
28
+ module CoreDocs
29
+ module MethodInfo
30
+
31
+ # Convert a method object into the `Class#method` string notation.
32
+ # @param [Method, UnboundMethod] meth
33
+ # @return [String] The method in string receiver notation.
34
+ # @note This mess is needed in order to support all the modern Rubies. YOU
35
+ # must figure out a better way to distinguish between class methods and
36
+ # instance methods.
37
+ def self.receiver_notation_for(meth)
38
+ match = meth.inspect.match(/\A#<(?:Unbound)?Method: (.+)([#\.].+)>\z/)
39
+ owner = meth.owner.to_s.sub(/#<.+?:(.+?)>/, '\1')
40
+ name = match[2]
41
+ name.sub!('#', '.') if match[1] =~ /\A#<Class:/
42
+ owner + name
43
+ end
44
+
45
+ # Retrives aliases of a method
46
+ # @param [Method, UnboundMethod] meth The method object.
47
+ # @return [Array] The aliases of a method if it exists
48
+ # otherwise, return empty array
49
+ def self.aliases(meth)
50
+ # host = is_singleton?(meth) ? meth.receiver : meth.owner
51
+ # method_type = is_singleton?(meth) ? :method : :instance_method
52
+
53
+ # methods = Pry::Method.send(:all_from_common, host, method_type, false).
54
+ # map { |m| m.instance_variable_get(:@method) }
55
+
56
+ # methods.select { |m| host.send(method_type,m.name) == host.send(method_type,meth.name) }.
57
+ # reject { |m| m.name == meth.name }.
58
+ # map { |m| host.send(method_type,m.name) }
59
+ []
60
+ end
61
+
62
+ # Checks whether method is a singleton (i.e class method)
63
+ # @param [Method, UnboundMethod] meth
64
+ # @param [Boolean] true if singleton
65
+ def self.is_singleton?(meth)
66
+ receiver_notation_for(meth).include?('.')
67
+ end
68
+
69
+ # Check whether the file containing the method is already cached.
70
+ # @param [Method, UnboundMethod] meth The method object.
71
+ # @return [Boolean] Whether the method is cached.
72
+ def self.cached?(meth)
73
+ !!registry_lookup(meth)
74
+ end
75
+
76
+ def self.registry_lookup(meth)
77
+ obj = YARD::Registry.at(receiver_notation_for(meth))
78
+ if obj.nil?
79
+ if !(aliases = aliases(meth)).empty?
80
+ obj = YARD::Registry.at(receiver_notation_for(aliases.first))
81
+ elsif meth.owner == Kernel
82
+ # YARD thinks that some methods are on Object when
83
+ # they're actually on Kernel; so try again on Object if Kernel fails.
84
+ obj = YARD::Registry.at("Object##{meth.name}")
85
+ end
86
+ end
87
+ obj
88
+ end
89
+
90
+ # Retrieve the YARD object that contains the method data.
91
+ # @param [Method, UnboundMethod] meth The method object.
92
+ # @return [YARD::CodeObjects::MethodObject] The YARD data for the method.
93
+ def self.info_for(meth)
94
+ cache(meth)
95
+ registry_lookup(meth)
96
+ end
97
+
98
+ # Determine whether a method is an eval method.
99
+ # @return [Boolean] Whether the method is an eval method.
100
+ def self.is_eval_method?(meth)
101
+ file, _ = meth.source_location
102
+ if file =~ /(\(.*\))|<.*>/
103
+ true
104
+ else
105
+ false
106
+ end
107
+ end
108
+
109
+ # Attempts to find the c source files if method belongs to a gem
110
+ # and use YARD to parse and cache the source files for display
111
+ #
112
+ # @param [Method, UnboundMethod] meth The method object.
113
+ def self.parse_and_cache_if_gem_cext(meth)
114
+ if gem_dir = find_gem_dir(meth)
115
+ if c_files_found?(gem_dir)
116
+ warn "Scanning and caching *.c files..."
117
+ YARD.parse("#{gem_dir}/**/*.c")
118
+ end
119
+ end
120
+ end
121
+
122
+ # @param [String] root directory path of gem that method belongs to
123
+ # @return [Boolean] true if c files exist?
124
+ def self.c_files_found?(gem_dir)
125
+ Dir.glob("#{gem_dir}/**/*.c").count > 0
126
+ end
127
+
128
+ # @return [Object] The host of the method (receiver or owner).
129
+ def self.method_host(meth)
130
+ is_singleton?(meth) && Module === meth.receiver ? meth.receiver : meth.owner
131
+ end
132
+
133
+ # FIXME: this is unnecessarily limited to ext/ and lib/ folders
134
+ # @return [String] The root folder of a given gem directory.
135
+ def self.gem_root(dir)
136
+ if index = dir.rindex(/\/(?:lib|ext)(?:\/|$)/)
137
+ dir[0..index-1]
138
+ end
139
+ end
140
+
141
+ # @param [Method, UnboundMethod] meth The method object.
142
+ # @return [String] root directory path of gem that method belongs to,
143
+ # nil if could not be found
144
+ def self.find_gem_dir(meth)
145
+ # host = method_host(meth)
146
+
147
+ # begin
148
+ # host_source_location, _ = WrappedModule.new(host).source_location
149
+ # break if host_source_location != nil
150
+ # return unless host.name
151
+ # host = eval(host.namespace_name)
152
+ # end while host
153
+
154
+ # # we want to exclude all source_locations that aren't gems (i.e
155
+ # # stdlib)
156
+ # if host_source_location && host_source_location =~ %r{/gems/}
157
+ # gem_root(host_source_location)
158
+ # else
159
+
160
+ # the WrappedModule approach failed, so try our backup approach
161
+ gem_dir_from_method(meth)
162
+ # end
163
+ end
164
+
165
+ # Try to guess what the gem name will be based on the name of the module.
166
+ # We try a few approaches here depending on the `guess` parameter.
167
+ # @param [String] name The name of the module.
168
+ # @param [Fixnum] guess The current guessing approach to use.
169
+ # @return [String, nil] The guessed gem name, or `nil` if out of guesses.
170
+ def self.guess_gem_name_from_module_name(name, guess)
171
+ case guess
172
+ when 0
173
+ name.downcase
174
+ when 1
175
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_')
176
+ when 2
177
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_').sub("_", "-")
178
+ when 3
179
+ name.scan(/[A-Z][a-z]+/).map(&:downcase).join('-')
180
+ when 4
181
+ name
182
+ else
183
+ nil
184
+ end
185
+ end
186
+
187
+ # Try to recover the gem directory of a gem based on a method object.
188
+ # @param [Method, UnboundMethod] meth The method object.
189
+ # @return [String, nil] The located gem directory.
190
+ def self.gem_dir_from_method(meth)
191
+ guess = 0
192
+
193
+ host = method_host(meth)
194
+ return unless host.name
195
+ root_module_name = host.name.split("::").first
196
+ while gem_name = guess_gem_name_from_module_name(root_module_name, guess)
197
+ matches = $LOAD_PATH.grep %r{/gems/#{gem_name}} if !gem_name.empty?
198
+ if matches && matches.any?
199
+ return gem_root(matches.first)
200
+ else
201
+ guess += 1
202
+ end
203
+ end
204
+
205
+ nil
206
+ end
207
+
208
+ # Cache the file that holds the method or return immediately if file is
209
+ # already cached. Return if the method cannot be cached -
210
+ # i.e is a C stdlib method.
211
+ # @param [Method, UnboundMethod] meth The method object.
212
+ def self.cache(meth)
213
+ file, _ = meth.source_location
214
+
215
+ return if is_eval_method?(meth)
216
+ return if cached?(meth)
217
+
218
+ if !file
219
+ parse_and_cache_if_gem_cext(meth)
220
+ return
221
+ end
222
+
223
+ log.enter_level(Logger::FATAL) do
224
+ YARD.parse(file)
225
+ end
226
+ end
227
+ end
228
+ end