code 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 +7 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +162 -0
- data/Rakefile +30 -0
- data/code.gemspec +23 -0
- data/lib/code.rb +60 -0
- data/lib/code/version.rb +5 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7a7b939fc81c175fd4e2b1f0b1c80c48c0b0581c
|
4
|
+
data.tar.gz: 8bf7922b9a0248111210ffb31a291af4c46df40f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cbf364a3586ae292ca1bd595f4e5100c911f6b2461f993384dd9b2576b07c6fd9d6430e3f2cf3b2593ac84aadbc68d83a84bfbcfae68e1c15535fdc6f35d9a5e
|
7
|
+
data.tar.gz: 2e5b379b87ca8bf7d5260899fe33fdd826c375063865a4b9a63dd58b850ee37b39318058ad64a4f17fb22744a82841f5d149d8f1fbd1d7ad13e011ce72168e48
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/CHANGELOG.md
ADDED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 Jan Lelis, mail@janlelis.de
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
# code [![[version]](https://badge.fury.io/rb/code.svg)](http://badge.fury.io/rb/code)
|
2
|
+
|
3
|
+
Shows a method's code with syntax highlighting. Tries to find the Ruby definition of method first, then falls back to the C version (if the `core_docs` gem is available).
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install code core_docs
|
9
|
+
```
|
10
|
+
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# in /home/jan/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:38
|
16
|
+
##
|
17
|
+
# When RubyGems is required, Kernel#require is replaced with our own which
|
18
|
+
# is capable of loading gems on demand.
|
19
|
+
#
|
20
|
+
# When you call <tt>require 'x'</tt>, this is what happens:
|
21
|
+
# * If the file can be loaded from the existing Ruby loadpath, it
|
22
|
+
# is.
|
23
|
+
# * Otherwise, installed gems are searched for a file that matches.
|
24
|
+
# If it's found in gem 'y', that gem is activated (added to the
|
25
|
+
# loadpath).
|
26
|
+
#
|
27
|
+
# The normal <tt>require</tt> functionality of returning false if
|
28
|
+
# that file has already been loaded is preserved.
|
29
|
+
def require path
|
30
|
+
RUBYGEMS_ACTIVATION_MONITOR.enter
|
31
|
+
|
32
|
+
path = path.to_path if path.respond_to? :to_path
|
33
|
+
|
34
|
+
spec = Gem.find_unresolved_default_spec(path)
|
35
|
+
if spec
|
36
|
+
Gem.remove_unresolved_default_spec(spec)
|
37
|
+
gem(spec.name)
|
38
|
+
end
|
39
|
+
|
40
|
+
# If there are no unresolved deps, then we can use just try
|
41
|
+
# normal require handle loading a gem from the rescue below.
|
42
|
+
|
43
|
+
if Gem::Specification.unresolved_deps.empty? then
|
44
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
45
|
+
return gem_original_require(path)
|
46
|
+
end
|
47
|
+
|
48
|
+
# If +path+ is for a gem that has already been loaded, don't
|
49
|
+
# bother trying to find it in an unresolved gem, just go straight
|
50
|
+
# to normal require.
|
51
|
+
#--
|
52
|
+
# TODO request access to the C implementation of this to speed up RubyGems
|
53
|
+
|
54
|
+
spec = Gem::Specification.stubs.find { |s|
|
55
|
+
s.activated? and s.contains_requirable_file? path
|
56
|
+
}
|
57
|
+
|
58
|
+
begin
|
59
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
60
|
+
return gem_original_require(spec.to_fullpath(path) || path)
|
61
|
+
end if spec
|
62
|
+
|
63
|
+
# Attempt to find +path+ in any unresolved gems...
|
64
|
+
|
65
|
+
found_specs = Gem::Specification.find_in_unresolved path
|
66
|
+
|
67
|
+
# If there are no directly unresolved gems, then try and find +path+
|
68
|
+
# in any gems that are available via the currently unresolved gems.
|
69
|
+
# For example, given:
|
70
|
+
#
|
71
|
+
# a => b => c => d
|
72
|
+
#
|
73
|
+
# If a and b are currently active with c being unresolved and d.rb is
|
74
|
+
# requested, then find_in_unresolved_tree will find d.rb in d because
|
75
|
+
# it's a dependency of c.
|
76
|
+
#
|
77
|
+
if found_specs.empty? then
|
78
|
+
found_specs = Gem::Specification.find_in_unresolved_tree path
|
79
|
+
|
80
|
+
found_specs.each do |found_spec|
|
81
|
+
found_spec.activate
|
82
|
+
end
|
83
|
+
|
84
|
+
# We found +path+ directly in an unresolved gem. Now we figure out, of
|
85
|
+
# the possible found specs, which one we should activate.
|
86
|
+
else
|
87
|
+
|
88
|
+
# Check that all the found specs are just different
|
89
|
+
# versions of the same gem
|
90
|
+
names = found_specs.map(&:name).uniq
|
91
|
+
|
92
|
+
if names.size > 1 then
|
93
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
94
|
+
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Ok, now find a gem that has no conflicts, starting
|
98
|
+
# at the highest version.
|
99
|
+
valid = found_specs.select { |s| s.conflicts.empty? }.last
|
100
|
+
|
101
|
+
unless valid then
|
102
|
+
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
|
103
|
+
le.name = names.first
|
104
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
105
|
+
raise le
|
106
|
+
end
|
107
|
+
|
108
|
+
valid.activate
|
109
|
+
end
|
110
|
+
|
111
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
112
|
+
return gem_original_require(path)
|
113
|
+
rescue LoadError => load_error
|
114
|
+
RUBYGEMS_ACTIVATION_MONITOR.enter
|
115
|
+
|
116
|
+
if load_error.message.start_with?("Could not find") or
|
117
|
+
(load_error.message.end_with?(path) and Gem.try_activate(path)) then
|
118
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
119
|
+
return gem_original_require(path)
|
120
|
+
else
|
121
|
+
RUBYGEMS_ACTIVATION_MONITOR.exit
|
122
|
+
end
|
123
|
+
|
124
|
+
raise load_error
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
```c
|
129
|
+
>> Code.for File, :open #=> nil
|
130
|
+
// in io.c:6219
|
131
|
+
// call-seq:
|
132
|
+
// IO.open(fd, mode="r" [, opt]) -> io
|
133
|
+
// IO.open(fd, mode="r" [, opt]) { |io| block } -> obj
|
134
|
+
//
|
135
|
+
// With no associated block, <code>IO.open</code> is a synonym for IO.new. If
|
136
|
+
// the optional code block is given, it will be passed +io+ as an argument,
|
137
|
+
// and the IO object will automatically be closed when the block terminates.
|
138
|
+
// In this instance, IO.open returns the value of the block.
|
139
|
+
//
|
140
|
+
// See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
|
141
|
+
static VALUE
|
142
|
+
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
|
143
|
+
{
|
144
|
+
VALUE io = rb_class_new_instance(argc, argv, klass);
|
145
|
+
|
146
|
+
if (rb_block_given_p()) {
|
147
|
+
return rb_ensure(rb_yield, io, io_close, io);
|
148
|
+
}
|
149
|
+
|
150
|
+
return io;
|
151
|
+
}
|
152
|
+
|
153
|
+
```
|
154
|
+
|
155
|
+
## Goal
|
156
|
+
|
157
|
+
Be as powerful as pry's source browsing: https://github.com/pry/pry/wiki/Source-browsing
|
158
|
+
|
159
|
+
|
160
|
+
## MIT License
|
161
|
+
|
162
|
+
Copyright (C) 2015 Jan Lelis <http://janlelis.com>. Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# # #
|
2
|
+
# Get gemspec info
|
3
|
+
|
4
|
+
gemspec_file = Dir['*.gemspec'].first
|
5
|
+
gemspec = eval File.read(gemspec_file), binding, gemspec_file
|
6
|
+
info = "#{gemspec.name} | #{gemspec.version} | " \
|
7
|
+
"#{gemspec.runtime_dependencies.size} dependencies | " \
|
8
|
+
"#{gemspec.files.size} files"
|
9
|
+
|
10
|
+
|
11
|
+
# # #
|
12
|
+
# Gem build and install task
|
13
|
+
|
14
|
+
desc info
|
15
|
+
task :gem do
|
16
|
+
puts info + "\n\n"
|
17
|
+
print " "; sh "gem build #{gemspec_file}"
|
18
|
+
FileUtils.mkdir_p 'pkg'
|
19
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
20
|
+
puts; sh %{gem install --no-document pkg/#{gemspec.name}-#{gemspec.version}.gem}
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# # #
|
25
|
+
# Start an IRB session with the gem loaded
|
26
|
+
|
27
|
+
desc "#{gemspec.name} | IRB"
|
28
|
+
task :irb do
|
29
|
+
sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}"
|
30
|
+
end
|
data/code.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/lib/code/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "code"
|
7
|
+
gem.version = Code::VERSION
|
8
|
+
gem.summary = "Displays a method's code."
|
9
|
+
gem.description = "Displays a method's code (from source or docs)."
|
10
|
+
gem.authors = ["Jan Lelis"]
|
11
|
+
gem.email = "mail@janlelis.de"
|
12
|
+
gem.homepage = "https://github.com/janlelis/code"
|
13
|
+
gem.license = "MIT"
|
14
|
+
|
15
|
+
gem.files = Dir['{**/}{.*,*}'].select{ |path| File.file?(path) && path !~ /^pkg/ }
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.required_ruby_version = "~> 2.0"
|
21
|
+
gem.add_dependency "method_source", "~> 0.8", ">= 0.8.2"
|
22
|
+
gem.add_dependency "coderay", "~> 1.1"
|
23
|
+
end
|
data/lib/code.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative "code/version"
|
2
|
+
|
3
|
+
require 'method_source'
|
4
|
+
require 'coderay'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'core_docs'
|
8
|
+
rescue LoadError
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
module Code
|
13
|
+
class NotFound < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
# API for end user
|
17
|
+
def self.for(object = self, method_name)
|
18
|
+
m = object.method(method_name)
|
19
|
+
begin
|
20
|
+
from_ruby(m)
|
21
|
+
rescue MethodSource::SourceNotFoundError
|
22
|
+
from_docs(m)
|
23
|
+
end
|
24
|
+
rescue NameError, NotFound
|
25
|
+
warn $!.message
|
26
|
+
end
|
27
|
+
|
28
|
+
# Syntax highlight code string
|
29
|
+
def self.display(string, language = :ruby)
|
30
|
+
puts CodeRay.scan(string, language).term
|
31
|
+
end
|
32
|
+
|
33
|
+
# Find Ruby definition of code
|
34
|
+
def self.from_ruby(m)
|
35
|
+
source = m.source || ""
|
36
|
+
indent = source.match(/\A +/)
|
37
|
+
source = source.gsub(/^#{indent}/,"")
|
38
|
+
comment = m.comment && !m.comment.empty? ? "#{ m.comment }" : ""
|
39
|
+
location = m.source_location ? "# in #{ m.source_location*':' }\n" : ""
|
40
|
+
|
41
|
+
display location + comment + source
|
42
|
+
end
|
43
|
+
|
44
|
+
# Find C definition of Code
|
45
|
+
def self.from_docs(m)
|
46
|
+
if RUBY_ENGINE != "ruby"
|
47
|
+
raise Code::NotFound, "Method source not found for non-CRuby."
|
48
|
+
elsif !defined?(CoreDocs)
|
49
|
+
raise Code::NotFound, 'Method source not found. Might be possible with core_docs gem'
|
50
|
+
elsif !(method_info = CoreDocs::MethodInfo.info_for(m))
|
51
|
+
raise Code::NotFound, 'Method source not found.'
|
52
|
+
else
|
53
|
+
source = method_info.source
|
54
|
+
location = "// in #{method_info.file}:#{method_info.line}\n"
|
55
|
+
comment = method_info.docstring ? method_info.docstring.gsub(/^/, '// ') + "\n" : ""
|
56
|
+
|
57
|
+
display location + comment + source, :c
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/code/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: code
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Lelis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: method_source
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.8.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.8'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: coderay
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.1'
|
47
|
+
description: Displays a method's code (from source or docs).
|
48
|
+
email: mail@janlelis.de
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- ".gitignore"
|
54
|
+
- CHANGELOG.md
|
55
|
+
- MIT-LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- code.gemspec
|
59
|
+
- lib/code.rb
|
60
|
+
- lib/code/version.rb
|
61
|
+
homepage: https://github.com/janlelis/code
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '2.0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.4.6
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Displays a method's code.
|
85
|
+
test_files: []
|
86
|
+
has_rdoc:
|