how 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 48c8bf4b4a85f36d528ac753d12c49abb0757417
4
+ data.tar.gz: d6eab7ef8176e1656aa72ee98804afcde05f194a
5
+ SHA512:
6
+ metadata.gz: 57db65eea8c56c6ae4ec4962500a1dfed07657abf34ff8293d19612f2f54c666d13cf388847d6e88486bba9d6b54244140b37ed2b2df3a6d766797562d286de7
7
+ data.tar.gz: 253e335a0d5336a8d29dba75ad26ff30e8bca00b504ff7113f434b06f18d5664a17e45e2b3c6fe4e3441a90b65e1dd1acc7489c12f18a8cff40078bb7d1acc90
@@ -0,0 +1,21 @@
1
+ /*.gem
2
+ /*.rbc
3
+ /.bundle
4
+ /.config
5
+ /coverage
6
+ /InstalledFiles
7
+ /lib/bundler/man
8
+ /pkg
9
+ /rdoc
10
+ /spec/reports
11
+ /test/tmp
12
+ /test/version_tmp
13
+ /tmp
14
+
15
+ # YARD artifacts
16
+ /.yardoc
17
+ /_yardoc
18
+ /doc/
19
+
20
+
21
+ /reference/javascript/node_modules
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2014, Nick Sinopoli <nsinopoli@gmail.com>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice, this
11
+ list of conditions and the following disclaimer in the documentation and/or
12
+ other materials provided with the distribution.
13
+
14
+ * Neither the name of Nick Sinopoli nor the names of his
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,14 @@
1
+ all: style test
2
+
3
+ install:
4
+ gem install rubocop
5
+
6
+ style:
7
+ rubocop lib
8
+
9
+ test:
10
+ ruby spec.rb
11
+
12
+ .PHONY: test
13
+
14
+
@@ -0,0 +1,34 @@
1
+ # how
2
+
3
+ **how** is a reference manual for programmers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ gem install how
9
+ ```
10
+
11
+ For syntax highlighting, be sure to install [Pygments](http://pygments.org/).
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ how [domain] [keywords]
17
+ ```
18
+
19
+ **how** takes two arguments:
20
+
21
+ 1. `domain` is the domain to be searched. The following domains are currently supported:
22
+
23
+ + [js](reference/javascript/README.md) (JavaScript)
24
+
25
+ 1. `keywords` are the search terms. (All keywords are used to find a match. If your search yields no results, try using fewer keywords.)
26
+
27
+ ### Example
28
+
29
+ ```bash
30
+ # How do I capitalize a string in JavaScript?
31
+ how js capitalize string
32
+ ```
33
+
34
+ The results will be paged in the program set in `$PAGER`. (If `$PAGER` isn't set, [less](http://www.greenwoodsoftware.com/less/) will be used.) Additionally, if [Pygments](http://pygments.org/) is installed, the syntax will be highlighted.
data/bin/how ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
4
+
5
+ require 'how'
6
+
7
+ def run(argv)
8
+ args = { domain: argv.shift, keywords: argv }
9
+
10
+ domain_path = How::IO.get_domain_path args[:domain]
11
+ abort 'Invalid domain.' if !domain_path
12
+
13
+ matches = Dir.glob(domain_path).reduce([]) do |list, filename|
14
+ contents = File.read filename
15
+ blocks = How::Text.find_blocks contents, args[:keywords]
16
+ next list if blocks.empty?
17
+ list << blocks.map { |block| How::Text.drop_first_and_last_lines block }
18
+ end
19
+
20
+ abort 'No results found. Try changing your search terms.' if matches.empty?
21
+
22
+ results = matches.join "\n\n"
23
+
24
+ if RUBY_PLATFORM =~ /win32/ || !$stdout.tty?
25
+ return $stdout.puts results
26
+ end
27
+
28
+ if How::IO.which 'pygmentize'
29
+ lexer = How::SyntaxHighlighter.get_pygments_lexer args[:domain]
30
+ results = How::IO.pygmentize results, lexer
31
+ end
32
+
33
+ How::IO.page results
34
+ end
35
+
36
+ run ARGV
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'how/version'
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'how'
6
+ gem.version = How::Version::VERSION
7
+ gem.summary = 'A reference manual for programmers'
8
+ gem.description = 'Eliminates the tedium of hunting for answers to common programming questions'
9
+ gem.license = 'BSD (3-Clause)'
10
+ gem.authors = ['Nick Sinopoli']
11
+ gem.email = 'NSinopoli@gmail.com'
12
+ gem.homepage = 'https://github.com/NSinopoli/how'
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(spec)/})
17
+ gem.require_paths = ['lib']
18
+ end
@@ -0,0 +1,5 @@
1
+ require 'how/version'
2
+
3
+ require 'how/io'
4
+ require 'how/syntax_highlighter'
5
+ require 'how/text'
@@ -0,0 +1,65 @@
1
+ module How
2
+ # This module contains methods to handle IO-related operations.
3
+ module IO
4
+ # Retrieves the filepath (relative to the root of this project) of the
5
+ # reference files for the supplied domain.
6
+ #
7
+ # @param [String] domain The domain
8
+ # @return [String, nil]
9
+ def self.get_domain_path(domain)
10
+ root = File.expand_path '../..', File.dirname(__FILE__)
11
+
12
+ case domain.downcase
13
+ when 'rb', 'ruby'
14
+ File.join root, 'reference', 'ruby', 'lib', '*.rb'
15
+ when 'js', 'javascript'
16
+ File.join root, 'reference', 'javascript', 'lib', '*.js'
17
+ end
18
+ end
19
+
20
+ # Runs the supplied text through the pager defined in $PAGER.
21
+ #
22
+ # @param [String] text The text
23
+ def self.page(text)
24
+ pager = ENV['PAGER'] || 'less'
25
+ ::IO.popen(pager, 'w') { |process| process.puts text }
26
+ end
27
+
28
+ # Pygmentizes the supplied text. A lexer will be inferred (based on
29
+ # syntax) if it is not supplied.
30
+ #
31
+ # @param [String] text The text to be pygmentized
32
+ # @param [String] lexer The lexer
33
+ # @return [String]
34
+ def self.pygmentize(text, lexer = nil)
35
+ if !lexer
36
+ command = 'pygmentize -g'
37
+ else
38
+ command = "pygmentize -l '#{lexer}'"
39
+ end
40
+
41
+ ::IO.popen(command, 'r+') do |process|
42
+ process.puts text
43
+ process.close_write
44
+ process.read
45
+ end
46
+ end
47
+
48
+ # Finds the supplied command (if it exists) within the $PATH.
49
+ #
50
+ # @param [String] command The command
51
+ # @return [String, nil]
52
+ def self.which(command)
53
+ extensions = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
54
+
55
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
56
+ extensions.each do |extension|
57
+ exe = File.join path, "#{command}#{extension}"
58
+ return exe if File.executable? exe
59
+ end
60
+ end
61
+
62
+ nil
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ module How
2
+ # This module contains methods to handle syntax highlighting.
3
+ module SyntaxHighlighter
4
+ # Retrieves the Pygments lexer corresponding to the supplied syntax type.
5
+ #
6
+ # @see http://pygments.org/docs/lexers/
7
+ # @param [String] syntax The type of syntax
8
+ # @return [String, nil]
9
+ def self.get_pygments_lexer(syntax)
10
+ case syntax.downcase
11
+ when 'rb', 'ruby'
12
+ 'rb'
13
+ when 'js', 'javascript'
14
+ 'js'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ module How
2
+ # This module contains methods to handle text manipulation.
3
+ module Text
4
+ # Drops the first and last lines of the supplied text.
5
+ #
6
+ # @param [String] text The text
7
+ # @return [String]
8
+ def self.drop_first_and_last_lines(text)
9
+ _, *body, _ = text.lines
10
+ body.join.chomp
11
+ end
12
+
13
+ # Finds the blocks identified by the supplied keywords within the
14
+ # supplied text.
15
+ #
16
+ # @param [String] text The text
17
+ # @param [Array] keywords The keywords
18
+ # @return [Array]
19
+ def self.find_blocks(text, keywords)
20
+ return [] if keywords.empty?
21
+
22
+ # If keywords is, for example, ['capitalize', 'string'], this will
23
+ # create a regex that looks like this:
24
+ # (?=Tags:.*\bcapitalize\b)(?=Tags:.*\bstring\b)[\S\s]*?!~!
25
+ block_regex = keywords.reduce('') do |result, keyword|
26
+ result + '(?=Tags:.*\b' + keyword.downcase + '\b)'
27
+ end + '[\S\s]*?!~!'
28
+
29
+ text.scan(/#{block_regex}/)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module How
2
+ # This module holds the How version information.
3
+ module Version
4
+ # The current version
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
@@ -0,0 +1,57 @@
1
+ {
2
+ /*
3
+ * ENVIRONMENTS
4
+ * =================
5
+ */
6
+
7
+ // Define globals exposed by modern browsers.
8
+ "browser": true,
9
+
10
+ // Define globals exposed by jQuery.
11
+ "jquery": true,
12
+
13
+ // Define globals exposed by Node.js.
14
+ "node": true,
15
+
16
+ /*
17
+ * ENFORCING OPTIONS
18
+ * =================
19
+ */
20
+
21
+ // Force all variable names to use either camelCase style or UPPER_CASE
22
+ // with underscores.
23
+ "camelcase": true,
24
+
25
+ // Prohibit use of == and != in favor of === and !==.
26
+ "eqeqeq": true,
27
+
28
+ // Suppress warnings about == null comparisons.
29
+ "eqnull": true,
30
+
31
+ // Enforce tab width of 2 spaces.
32
+ "indent": 2,
33
+
34
+ // Prohibit use of a variable before it is defined.
35
+ "latedef": true,
36
+
37
+ // Require capitalized names for constructor functions.
38
+ "newcap": true,
39
+
40
+ // Enforce use of single quotation marks for strings.
41
+ "quotmark": "single",
42
+
43
+ // Prohibit trailing whitespace.
44
+ "trailing": true,
45
+
46
+ // Prohibit use of explicitly undeclared variables.
47
+ "undef": true,
48
+
49
+ // Warn when variables are defined but never used.
50
+ "unused": true,
51
+
52
+ // Enforce line length to 80 characters
53
+ "maxlen": 80,
54
+
55
+ // Enforce placing 'use strict' at the top function scope
56
+ "strict": true
57
+ }
@@ -0,0 +1,12 @@
1
+ all: jshint test
2
+
3
+ install:
4
+ npm install mocha should jshint
5
+
6
+ jshint:
7
+ ./node_modules/.bin/jshint lib
8
+
9
+ test:
10
+ ./node_modules/.bin/mocha --reporter list
11
+
12
+ .PHONY: test
@@ -0,0 +1,14 @@
1
+ ## Style Guide
2
+
3
+ All code conforms to the
4
+ [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript).
5
+
6
+ jshint?
7
+
8
+ ## Documentation
9
+
10
+ All code is documented using [jsdoc](http://usejsdoc.org/).
11
+
12
+ ## Testing
13
+
14
+ mocha
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ // Tags: capitalize capital uppercase first letter string
4
+ // Compatibility notes: TODO
5
+ /**
6
+ * Capitalizes the first letter of the supplied string.
7
+ *
8
+ * @param {string} string The string
9
+ * @returns {string} The capitalized string
10
+ */
11
+ function capitalize(string) {
12
+ return string.charAt(0).toUpperCase() + string.slice(1);
13
+ }
14
+ // !~!
15
+
16
+ exports.capitalize = capitalize;
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var should = require('should'),
4
+ string = require('../lib/string.js');
5
+
6
+ describe('capitalize', function() {
7
+
8
+ it('capitalizes the first letter of the supplied string', function() {
9
+ string.capitalize('hello world!').should.equal('Hello world!');
10
+ string.capitalize('Hello world!').should.equal('Hello world!');
11
+ });
12
+
13
+ it('leaves the other letters unchanged', function() {
14
+ string.capitalize('FOO').should.equal('FOO');
15
+ string.capitalize('bar BAR bar').should.equal('Bar BAR bar');
16
+ });
17
+
18
+ it('returns an empty string when supplied with an empty string', function() {
19
+ string.capitalize('').should.equal('');
20
+ });
21
+ });
data/spec.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dir.glob('spec/**/*.rb').each do |file|
2
+ require_relative file.sub(/\.rb$/, '')
3
+ end
@@ -0,0 +1,40 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/how/io'
3
+
4
+ describe How::IO do
5
+
6
+ describe '.get_domain_path' do
7
+
8
+ root = File.expand_path '../..', File.dirname(__FILE__)
9
+
10
+ describe 'when the domain can be identified' do
11
+ it 'returns the correct path' do
12
+ %w(rb ruby RB Ruby).each do |contents|
13
+ actual = How::IO.get_domain_path contents
14
+ expected = File.join root, 'reference', 'ruby', 'lib', '*.rb'
15
+ actual.must_equal expected
16
+ end
17
+
18
+ %w(js javascript JS JavaScript).each do |contents|
19
+ actual = How::IO.get_domain_path contents
20
+ expected = File.join root, 'reference', 'javascript', 'lib', '*.js'
21
+ actual.must_equal expected
22
+ end
23
+ end
24
+ end
25
+
26
+ describe 'when the domain cannot be identified' do
27
+ it 'returns nil' do
28
+ contents = 'doesnotexist'
29
+ actual = How::IO.get_domain_path contents
30
+ expected = nil
31
+ actual.must_equal expected
32
+
33
+ contents = ''
34
+ actual = How::IO.get_domain_path contents
35
+ expected = nil
36
+ actual.must_equal expected
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/how/syntax_highlighter'
3
+
4
+ describe How::SyntaxHighlighter do
5
+
6
+ describe '.get_pygments_lexer' do
7
+ describe 'when the syntax can be identified' do
8
+ it 'returns the correct lexer' do
9
+ %w(rb ruby RB Ruby).each do |contents|
10
+ actual = How::SyntaxHighlighter.get_pygments_lexer contents
11
+ expected = 'rb'
12
+ actual.must_equal expected
13
+ end
14
+
15
+ %w(js javascript JS JavaScript).each do |contents|
16
+ actual = How::SyntaxHighlighter.get_pygments_lexer contents
17
+ expected = 'js'
18
+ actual.must_equal expected
19
+ end
20
+ end
21
+ end
22
+
23
+ describe 'when the syntax cannot be identified' do
24
+ it 'returns nil' do
25
+ contents = 'doesnotexist'
26
+ actual = How::SyntaxHighlighter.get_pygments_lexer contents
27
+ expected = nil
28
+ actual.must_equal expected
29
+
30
+ contents = ''
31
+ actual = How::SyntaxHighlighter.get_pygments_lexer contents
32
+ expected = nil
33
+ actual.must_equal expected
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,134 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/how/text'
3
+
4
+ describe How::Text do
5
+
6
+ describe '.drop_first_and_last_lines' do
7
+ describe 'when the supplied string contains at least three lines' do
8
+ it 'removes the first and last lines' do
9
+ contents = "first\nmiddle\nlast"
10
+ actual = How::Text.drop_first_and_last_lines contents
11
+ expected = 'middle'
12
+ actual.must_equal expected
13
+
14
+ contents = "first\nsecond\nthird\nfourth"
15
+ actual = How::Text.drop_first_and_last_lines contents
16
+ expected = "second\nthird"
17
+ actual.must_equal expected
18
+ end
19
+ end
20
+
21
+ describe 'when the supplied string contains less than three lines' do
22
+ it 'returns an empty string' do
23
+ contents = "first\nlast"
24
+ actual = How::Text.drop_first_and_last_lines contents
25
+ expected = ''
26
+ actual.must_equal expected
27
+
28
+ contents = 'first'
29
+ actual = How::Text.drop_first_and_last_lines contents
30
+ expected = ''
31
+ actual.must_equal expected
32
+
33
+ contents = ''
34
+ actual = How::Text.drop_first_and_last_lines contents
35
+ expected = ''
36
+ actual.must_equal expected
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '.find_blocks' do
42
+ contents = []
43
+ contents << <<-BLOCK
44
+ // Tags: capitalize capital uppercase first letter string
45
+ /**
46
+ * Capitalizes the first letter of the supplied string.
47
+ *
48
+ * @param {string} string The string
49
+ * @returns {string} The capitalized string
50
+ */
51
+ function capitalize(string) {
52
+ return string.charAt(0).toUpperCase() + string.slice(1);
53
+ }
54
+ // !~!
55
+ BLOCK
56
+
57
+ contents << <<-BLOCK
58
+ # Tags: nothing
59
+ # Does nothing.
60
+ #
61
+ # @param [String] flavor The flavor of nothing
62
+ # @return [nil]
63
+ def nothing(flavor)
64
+ nil
65
+ end
66
+ # !~!
67
+ BLOCK
68
+
69
+ contents << <<-BLOCK
70
+ # Tags: reverse string
71
+ def reverse(string):
72
+ """Reverse a string.
73
+
74
+ :Parameters:
75
+ - `string`: The string to reverse
76
+ """
77
+ return string[::-1]
78
+ # !~!
79
+ BLOCK
80
+
81
+ describe 'when the supplied keyword matches multiple blocks' do
82
+ it 'finds all of the matching blocks' do
83
+ actual = How::Text.find_blocks contents.join, ['string']
84
+ expected = trim_blocks [contents[0], contents[2]]
85
+ actual.must_equal expected
86
+ end
87
+ end
88
+
89
+ describe 'when the supplied keyword matches only one block' do
90
+ it 'finds the one matching block' do
91
+ actual = How::Text.find_blocks contents.join, ['capitalize']
92
+ expected = trim_blocks [contents[0]]
93
+ actual.must_equal expected
94
+ end
95
+ end
96
+
97
+ describe 'when the keyword matches only one block' do
98
+ it 'finds the one matching block' do
99
+ actual = How::Text.find_blocks contents.join, ['capitalize']
100
+ expected = trim_blocks [contents[0]]
101
+ actual.must_equal expected
102
+ end
103
+ end
104
+
105
+ describe 'when the (case-insensitive) keyword matches a block' do
106
+ it 'finds the one matching block' do
107
+ actual = How::Text.find_blocks contents.join, ['NOTHING']
108
+ expected = trim_blocks [contents[1]]
109
+ actual.must_equal expected
110
+ end
111
+ end
112
+
113
+ describe 'when the keywords match no blocks' do
114
+ it 'returns an empty array' do
115
+ actual = How::Text.find_blocks contents.join, %w(nothing sorry)
116
+ expected = []
117
+ actual.must_equal expected
118
+
119
+ actual = How::Text.find_blocks contents.join, ['sorry']
120
+ expected = []
121
+ actual.must_equal expected
122
+ end
123
+
124
+ end
125
+ end
126
+
127
+ end
128
+
129
+ def trim_blocks(blocks)
130
+ blocks.map do |block|
131
+ first, *rest = block.lines
132
+ first.gsub(/^.*?T/, 'T') + rest.join.chomp
133
+ end
134
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: how
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Sinopoli
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Eliminates the tedium of hunting for answers to common programming questions
14
+ email: NSinopoli@gmail.com
15
+ executables:
16
+ - how
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - LICENSE
22
+ - Makefile
23
+ - README.md
24
+ - bin/how
25
+ - how.gemspec
26
+ - lib/how.rb
27
+ - lib/how/io.rb
28
+ - lib/how/syntax_highlighter.rb
29
+ - lib/how/text.rb
30
+ - lib/how/version.rb
31
+ - reference/javascript/.jshintrc
32
+ - reference/javascript/Makefile
33
+ - reference/javascript/README.md
34
+ - reference/javascript/lib/string.js
35
+ - reference/javascript/test/string.js
36
+ - spec.rb
37
+ - spec/lib/io_spec.rb
38
+ - spec/lib/syntax_highlighter_spec.rb
39
+ - spec/lib/text_spec.rb
40
+ homepage: https://github.com/NSinopoli/how
41
+ licenses:
42
+ - BSD (3-Clause)
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.1.4
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: A reference manual for programmers
64
+ test_files:
65
+ - spec/lib/io_spec.rb
66
+ - spec/lib/syntax_highlighter_spec.rb
67
+ - spec/lib/text_spec.rb