lessons_indexer 0.0.2.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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +74 -0
- data/Rakefile +6 -0
- data/bin/lessons_indexer +5 -0
- data/bin/lessons_indexer.bat +1 -0
- data/lessons_indexer.gemspec +26 -0
- data/lib/lessons_indexer/addons/file_manager.rb +29 -0
- data/lib/lessons_indexer/addons/git_manager.rb +35 -0
- data/lib/lessons_indexer/addons/utils.rb +30 -0
- data/lib/lessons_indexer/course.rb +32 -0
- data/lib/lessons_indexer/indexer.rb +104 -0
- data/lib/lessons_indexer/options.rb +35 -0
- data/lib/lessons_indexer/starter.rb +41 -0
- data/lib/lessons_indexer/version.rb +3 -0
- data/lib/lessons_indexer.rb +15 -0
- data/spec/addons/file_manager_spec.rb +30 -0
- data/spec/addons/utils_spec.rb +66 -0
- data/spec/options_spec.rb +28 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/spec_utils.rb +23 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d6f88831e8ce052dcc32bb7fa5dee852704b3133
|
4
|
+
data.tar.gz: c12ce22e7c5ef3750693ad4899bff238f6f8271f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5e7f484749590e07157356103a05129e93f6be49eda8bcacfb55842145274947a44e03847518460c7426cc14f662f4b85b5da39be35aef5ec4f79ec0631361ad
|
7
|
+
data.tar.gz: 890cae777e1935c86f9a9ce626f88840adc19e905ff613789c4cb9c0dab9b11aae8e9779fcec0e2922363db8f85aa40251333f6e92991ee73a77eeb9604b1bd6
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format doc --order rand --require spec_helper
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Ilya Bodrov
|
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,74 @@
|
|
1
|
+
[](https://travis-ci.org/bodrovis/LessonsIndexer)
|
2
|
+
[](https://codeclimate.com/github/bodrovis/LessonsIndexer)
|
3
|
+
[](https://codeclimate.com/github/bodrovis/LessonsIndexer/coverage)
|
4
|
+
[](https://gemnasium.com/bodrovis/LessonsIndexer)
|
5
|
+
# Lessons Indexer for Learnable
|
6
|
+
|
7
|
+
Builds an index in Markdown format for the lesson files in the provided directory and optionally adds heading images to the files. Available options:
|
8
|
+
|
9
|
+
* `-p` (`--path`) - path to the working directory. Defaults to `.`.
|
10
|
+
* `-s` (`--skip_index`) - skip index generation. Defaults to `false`.
|
11
|
+
* `-o` (`--output`) - output file to save index to. Defaults to `README.md`. The file will be creating in the working
|
12
|
+
directory if it does not exist. If it does exist, all its contents **will be erased**. Has no effect if `-s` is set.
|
13
|
+
* `-g` (`--git`) - if present, pushes changes to the remote branch (with the name equal to the local branch).
|
14
|
+
* `-m` (`--message`) - which commit message should be specified. Default to "Added index". Has no effect if the `-g` flag
|
15
|
+
is not set.
|
16
|
+
* `-a` (`--all`) - if present, will work with **all** branches of the specified directory (except for `master`).
|
17
|
+
* `-i` (`--headings`) - if present, heading images will be added to the beginning of each lesson file. If the file already
|
18
|
+
has a heading in the beginning, it will be skipped.
|
19
|
+
* `-d` (`--headings_dir`) - relative path to the directory with heading images.
|
20
|
+
Defaults to `headers`, has no effect if the `-i` flag is not set.
|
21
|
+
|
22
|
+
## Running
|
23
|
+
|
24
|
+
Requires Ruby 2.0+. Install the necessary gems using
|
25
|
+
|
26
|
+
```
|
27
|
+
bundle install
|
28
|
+
```
|
29
|
+
|
30
|
+
To run on nix systems use
|
31
|
+
|
32
|
+
```
|
33
|
+
bin/lessons_indexer <options>
|
34
|
+
```
|
35
|
+
|
36
|
+
For Windows use
|
37
|
+
|
38
|
+
```
|
39
|
+
bin/lessons_indexer.bat <options>
|
40
|
+
```
|
41
|
+
|
42
|
+
If any option's value contains spaces, it has to be surrounded with quotes:
|
43
|
+
|
44
|
+
```
|
45
|
+
bin/lessons_indexer -p "C:\User\my test dir\"
|
46
|
+
```
|
47
|
+
|
48
|
+
## Some Assumptions
|
49
|
+
|
50
|
+
Here are some guidelines to follow when using the program:
|
51
|
+
|
52
|
+
* The working directory (provided with the `-p` flag) should have a nested folder that contains all lesson files. This folder should be named after
|
53
|
+
the course and end with the `_handouts` (the program will do its best to convert folder's name to proper title, for example "Introduction_to_less_handouts" will
|
54
|
+
be converted to "Introduction To Less").
|
55
|
+
* Lesson files should have the lesson and step numbers in their title separated by `.` or `-`. It may contain any other
|
56
|
+
words, but they have to have *.md* extension. Here is an example of a valid file name: `lesson3.2.md` or `h3-2.md`. All other
|
57
|
+
files will be ignored.
|
58
|
+
* If the `-i` flag is set (to add headings to the lesson files), the `*_handouts` folder has to contain directory with the images.
|
59
|
+
This directory's name can be provided with the `-d` flag. Files inside should follow the same naming conditions as for the lesson
|
60
|
+
files (of course, they don't need to have the *.md* extension). Valid files names: `Git Course 1.1.jpg` or `google_maps10-3.png`.
|
61
|
+
All other files will be ignored. If the program cannot find a header image for a specific step,
|
62
|
+
this step will be just skipped and the corresponding warning message will be displayed.
|
63
|
+
|
64
|
+
## Testing
|
65
|
+
|
66
|
+
```
|
67
|
+
rspec .
|
68
|
+
```
|
69
|
+
|
70
|
+
## License
|
71
|
+
|
72
|
+
Licensed under the [MIT License](https://github.com/bodrovis/LessonsIndexer/blob/master/LICENSE).
|
73
|
+
|
74
|
+
Copyright (c) 2015 [Ilya Bodrov](http://radiant-wind.com)
|
data/Rakefile
ADDED
data/bin/lessons_indexer
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
@"ruby.exe" "%~dpn0" %*
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path("../lib/lessons_indexer/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "lessons_indexer"
|
5
|
+
spec.version = LessonsIndexer::VERSION
|
6
|
+
spec.authors = ["Ilya Bodrov"]
|
7
|
+
spec.email = ["golosizpru@gmail.com"]
|
8
|
+
spec.homepage = "https://github.com/bodrovis/lessons_indexer"
|
9
|
+
spec.summary = %q{Lessons Indexer for Learnable}
|
10
|
+
spec.description = %q{Lessons Indexer for Learnable}
|
11
|
+
spec.license = "MIT"
|
12
|
+
|
13
|
+
spec.files = `git ls-files -z`.split("\x0")
|
14
|
+
spec.executables = ["lessons_indexer"]#spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
15
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
|
+
spec.require_paths = ["lib"]
|
17
|
+
|
18
|
+
spec.add_dependency "slop", "~> 4.1"
|
19
|
+
spec.add_dependency "facets", "~> 3.0"
|
20
|
+
spec.add_dependency "colorize", "~> 0.7.7"
|
21
|
+
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
class Writer
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def prepend_data(data)
|
10
|
+
begin
|
11
|
+
old_data = File.read(name)
|
12
|
+
rescue StandardError => e
|
13
|
+
warning e.message
|
14
|
+
end
|
15
|
+
unless old_data.start_with?(data)
|
16
|
+
new_data = old_data.prepend(data)
|
17
|
+
self << new_data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(*args)
|
22
|
+
begin
|
23
|
+
File.open(name, 'w+') { |f| f.write(args.join) }
|
24
|
+
rescue StandardError => e
|
25
|
+
warning e.message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
module GitManager
|
3
|
+
class Pusher
|
4
|
+
attr_reader :message
|
5
|
+
|
6
|
+
def initialize(message)
|
7
|
+
@message = message
|
8
|
+
end
|
9
|
+
|
10
|
+
def push!
|
11
|
+
%x{git add .}
|
12
|
+
%x{git commit -am "#{message}"}
|
13
|
+
%x{git push origin HEAD}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Brancher
|
18
|
+
attr_reader :ignore_master
|
19
|
+
|
20
|
+
def initialize(ignore_master = true)
|
21
|
+
@ignore_master = ignore_master
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_branches
|
25
|
+
branches = %x{git branch}.split("\n").map {|br| br.strip.gsub(/\A\*\s*/, '') }
|
26
|
+
ignore_master ? branches.reject {|el| el == 'master'} : branches
|
27
|
+
end
|
28
|
+
|
29
|
+
def within_branch(branch)
|
30
|
+
%x{git checkout #{branch} --force}
|
31
|
+
yield if block_given?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Kernel
|
2
|
+
def with_messages(prior = '', after = '', delimiter = true, output = $stdout)
|
3
|
+
return unless block_given?
|
4
|
+
prior, after = String(prior).to_s, String(after).to_s
|
5
|
+
|
6
|
+
output.puts prior.magenta unless prior == ''
|
7
|
+
yield
|
8
|
+
output.puts after.green unless after == ''
|
9
|
+
output.puts "=".yellow * 50 if delimiter
|
10
|
+
end
|
11
|
+
|
12
|
+
def warning(*msg)
|
13
|
+
warn "[WARNING] #{msg.join(' ')}".cyan
|
14
|
+
end
|
15
|
+
|
16
|
+
def exit_msg(*msg)
|
17
|
+
abort "[ERROR] #{msg.join(' ')}".red
|
18
|
+
end
|
19
|
+
|
20
|
+
def within(path, ret = false)
|
21
|
+
return unless block_given?
|
22
|
+
initial = Dir.getwd
|
23
|
+
Dir.chdir(path)
|
24
|
+
val = yield
|
25
|
+
Dir.chdir(initial) if ret
|
26
|
+
return val
|
27
|
+
rescue Errno::ENOENT
|
28
|
+
exit_msg "The provided directory #{path} was not found! Aborting..."
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
class Course
|
3
|
+
STEP_LESSON_PATTERN = /(\d+)(?:\.|-)(\d+)/
|
4
|
+
|
5
|
+
attr_reader :dir, :title, :lessons
|
6
|
+
|
7
|
+
def initialize(course_dir)
|
8
|
+
@dir = course_dir
|
9
|
+
@title = dir.gsub(/_handouts\z/i, '').titlecase
|
10
|
+
@lessons = get_lessons
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_lessons
|
14
|
+
#TODO: Lesson class
|
15
|
+
within(dir, true) do
|
16
|
+
Dir.entries('.').keep_if {|f| f =~ /\.md\z/i }.sort do |a, b|
|
17
|
+
begin
|
18
|
+
step_a, step_b = a.match(STEP_LESSON_PATTERN), b.match(STEP_LESSON_PATTERN)
|
19
|
+
major_a, minor_a, major_b, minor_b = step_a[1].to_i, step_a[2].to_i, step_b[1].to_i, step_b[2].to_i
|
20
|
+
if major_a == major_b
|
21
|
+
minor_a <=> minor_b
|
22
|
+
else
|
23
|
+
major_a <=> major_b
|
24
|
+
end
|
25
|
+
rescue NoMethodError
|
26
|
+
warning "Found the #{lesson} file which does not have proper naming. File name should contain lesson and step, for example: 'lesson3.2.md'. Skipping this file."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
class Indexer
|
3
|
+
STEP_LESSON_PATTERN = /(\d+)(?:\.|-)(\d+)/
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_index!
|
12
|
+
course = Course.new(get_dir_name)
|
13
|
+
with_messages("Starting to build index...", "Index for the #{course.title} course is generated!") do
|
14
|
+
generate_index_for course
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_headings!
|
19
|
+
with_messages("Starting to add headings...", "Headings for the lesson files were added!") do
|
20
|
+
course = Course.new(get_dir_name)
|
21
|
+
within(course.dir, true) do
|
22
|
+
generate_headings_for course
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_headings_for(course)
|
30
|
+
images = within(options.headings_dir, true) { get_files }.keep_if {|f| f.match(STEP_LESSON_PATTERN)}
|
31
|
+
|
32
|
+
course.lessons.each do |lesson_file|
|
33
|
+
step_lesson = lesson_file.match(STEP_LESSON_PATTERN)
|
34
|
+
begin
|
35
|
+
lesson_image = images.detect do |image|
|
36
|
+
step_image = image.match(STEP_LESSON_PATTERN)
|
37
|
+
step_lesson[1] == step_image[1] && step_lesson[2] == step_image[2]
|
38
|
+
end
|
39
|
+
if lesson_image
|
40
|
+
prepend!("\n\n", lesson_file)
|
41
|
+
else
|
42
|
+
warning "I was not able to find heading image for the lesson #{step_lesson[0]}"
|
43
|
+
end
|
44
|
+
rescue NoMethodError
|
45
|
+
warning "Found the #{lesson_file} file which does not have proper naming. File name should contain lesson and step, for example: 'lesson3.2.md'. Skipping this file."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_index_for(course)
|
51
|
+
write!(
|
52
|
+
course.lessons.inject("# Index for the " + course.title + " course\n\n") do |memo, lesson|
|
53
|
+
memo + display_lesson_link(lesson, course.dir)
|
54
|
+
end, options.output
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def display_lesson_link(lesson, dir)
|
59
|
+
step = lesson.match(STEP_LESSON_PATTERN)
|
60
|
+
begin
|
61
|
+
"* [Lesson #{step[1]}.#{step[2]}](#{dir}/#{lesson})\n"
|
62
|
+
rescue NoMethodError
|
63
|
+
warning "Found the #{lesson} file which does not have proper naming. File name should contain lesson and step, for example: 'lesson3.2.md'. Skipping this file."
|
64
|
+
return ''
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_dir_name
|
69
|
+
dir = get_files.detect {|el| el =~ /_handouts\z/i}
|
70
|
+
exit_msg("Lesson files were not found inside the provided directory. Aborting...") if dir.nil?
|
71
|
+
dir
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_files
|
75
|
+
Dir.entries('.').delete_if {|f| f == '.' || f == '..' || f == '.git' || f == '.gitignore' }
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_lessons
|
79
|
+
Dir.entries('.').keep_if {|f| f =~ /\.md\z/i }.sort do |a, b|
|
80
|
+
begin
|
81
|
+
step_a, step_b = a.match(STEP_LESSON_PATTERN), b.match(STEP_LESSON_PATTERN)
|
82
|
+
major_a, minor_a, major_b, minor_b = step_a[1].to_i, step_a[2].to_i, step_b[1].to_i, step_b[2].to_i
|
83
|
+
if major_a == major_b
|
84
|
+
minor_a <=> minor_b
|
85
|
+
else
|
86
|
+
major_a <=> major_b
|
87
|
+
end
|
88
|
+
rescue NoMethodError
|
89
|
+
warning "Found the #{lesson} file which does not have proper naming. File name should contain lesson and step, for example: 'lesson3.2.md'. Skipping this file."
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def write!(contents, file)
|
95
|
+
writer = Writer.new(file)
|
96
|
+
writer << contents
|
97
|
+
end
|
98
|
+
|
99
|
+
def prepend!(contents, file)
|
100
|
+
writer = Writer.new(file)
|
101
|
+
writer.prepend_data(contents)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
class Options
|
3
|
+
def initialize(argv)
|
4
|
+
parse_args(argv).each do |k, v|
|
5
|
+
# attr_accessor for each possible option
|
6
|
+
self.class.class_eval do
|
7
|
+
attr_accessor k
|
8
|
+
end
|
9
|
+
|
10
|
+
# setting each option as instance variable
|
11
|
+
self.instance_variable_set "@#{k}", v
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse_args(argv)
|
18
|
+
begin
|
19
|
+
Slop.parse(argv, strict: true, help: true,
|
20
|
+
banner: 'Welcome to Lessons Indexer. Here is the list of available options:') do |o|
|
21
|
+
o.string '-p', '--path', 'Path to the directory with the course', default: '.'#, argument: true
|
22
|
+
o.bool '-s', '--skip_index', 'Skip index generation for the course', default: false
|
23
|
+
o.string '-o', '--output', 'Output file', default: 'README.md'#, as: String, argument: true
|
24
|
+
o.bool '-g', '--git', 'Push changes to the remote Git branch?', default: false
|
25
|
+
o.string '-m', '--message', 'Commit message', default: 'Added index'#, as: String, argument: true
|
26
|
+
o.bool '-a', '--all', 'Work with all branches (except for master)', default: false
|
27
|
+
o.bool '-i', '--headings', 'Add heading images to the beginning of the lesson files?', default: false
|
28
|
+
o.string '-d', '--headings_dir', 'Relative path to the directory with heading images', default: 'headers'#, as: String, argument: true
|
29
|
+
end.to_hash
|
30
|
+
rescue Slop::Error => e
|
31
|
+
exit_msg e.message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
class Starter
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize(argv)
|
6
|
+
@options = Options.new(argv)
|
7
|
+
end
|
8
|
+
|
9
|
+
def start!
|
10
|
+
with_messages("Welcome to Lessons Indexer ver#{LessonsIndexer::VERSION}!", "=== [ DONE. ] ===", false) do
|
11
|
+
indexer = Indexer.new(options)
|
12
|
+
|
13
|
+
within options.path do
|
14
|
+
if options.all
|
15
|
+
brancher = GitManager::Brancher.new
|
16
|
+
brancher.get_branches.each do |branch|
|
17
|
+
brancher.within_branch branch do
|
18
|
+
work_with indexer
|
19
|
+
end
|
20
|
+
end
|
21
|
+
else
|
22
|
+
work_with indexer
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def work_with(indexer)
|
31
|
+
indexer.build_index! unless options.skip_index
|
32
|
+
indexer.add_headings! if options.headings
|
33
|
+
git_push! if options.git
|
34
|
+
end
|
35
|
+
|
36
|
+
def git_push!
|
37
|
+
pusher = GitManager::Pusher.new(options.message)
|
38
|
+
pusher.push!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'facets/string/titlecase'
|
2
|
+
require 'slop'
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
require 'lessons_indexer/version'
|
6
|
+
require 'lessons_indexer/starter'
|
7
|
+
require 'lessons_indexer/indexer'
|
8
|
+
require 'lessons_indexer/options'
|
9
|
+
require 'lessons_indexer/course'
|
10
|
+
require 'lessons_indexer/addons/file_manager'
|
11
|
+
require 'lessons_indexer/addons/git_manager'
|
12
|
+
require 'lessons_indexer/addons/utils'
|
13
|
+
|
14
|
+
module LessonsIndexer
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
RSpec.describe Writer do
|
3
|
+
before :each do
|
4
|
+
@writer = Writer.new('test.txt')
|
5
|
+
@writer << 'test'
|
6
|
+
end
|
7
|
+
after(:all) {File.delete('test.txt')}
|
8
|
+
|
9
|
+
specify "#name" do
|
10
|
+
expect(@writer.name).to eq('test.txt')
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "#<<" do
|
14
|
+
contents = IO.read(@writer.name)
|
15
|
+
expect(contents).to eq('test')
|
16
|
+
end
|
17
|
+
|
18
|
+
context "#prepend_data" do
|
19
|
+
before(:each) {@writer.prepend_data('prepended')}
|
20
|
+
it "should add data to the beginning" do
|
21
|
+
expect(IO.read(@writer.name)).to eq('prependedtest')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not add data to the beginning if data is already present" do
|
25
|
+
@writer.prepend_data('prepended')
|
26
|
+
expect(IO.read(@writer.name)).to eq('prependedtest')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Kernel
|
2
|
+
RSpec.describe "helper utils" do
|
3
|
+
context "#within" do
|
4
|
+
before(:all) {@original_path = Dir.getwd}
|
5
|
+
after(:each) {Dir.chdir(@original_path)}
|
6
|
+
|
7
|
+
it "should return result of the block" do
|
8
|
+
expect(Kernel.within('/') {1 + 1}).to eq(2)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return immediately if no block is given" do
|
12
|
+
expect(Kernel.within('/')).to eq(nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise an error if directory does not exist" do
|
16
|
+
err = capture_stderr do
|
17
|
+
expect(-> { Kernel.within('non_existent_dir') {1 + 1} }).to raise_error(SystemExit)
|
18
|
+
end.uncolorize
|
19
|
+
expect(err).to eq("[ERROR] The provided directory non_existent_dir was not found! Aborting...\n")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return to the original directory" do
|
23
|
+
Kernel.within('/', true) {1 + 1}
|
24
|
+
expect(Dir.getwd).to eq(@original_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not return to the original directory by default" do
|
28
|
+
Kernel.within('/') {1 + 1}
|
29
|
+
expect(Dir.getwd).not_to eq(@original_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "#with_messages" do
|
34
|
+
let(:after_msg) {"after"}
|
35
|
+
let(:before_msg) {"before"}
|
36
|
+
it "should handle block and display messages and delimiter" do
|
37
|
+
info = capture_stdout do
|
38
|
+
with_messages(before_msg, after_msg) { 1 + 1 }
|
39
|
+
end.uncolorize
|
40
|
+
expect(info).to eq("#{before_msg}\n#{after_msg}\n#{'=' * 50}\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should not display delimiter when false is passed" do
|
44
|
+
info = capture_stdout do
|
45
|
+
with_messages(before_msg, after_msg, false) { 1 + 1 }
|
46
|
+
end.uncolorize
|
47
|
+
expect(info).to eq("#{before_msg}\n#{after_msg}\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "#warning" do
|
52
|
+
expect(Kernel).to respond_to(:warning)
|
53
|
+
err = capture_stderr do
|
54
|
+
warning "alert"
|
55
|
+
end.uncolorize
|
56
|
+
expect(err).to eq("[WARNING] alert\n")
|
57
|
+
end
|
58
|
+
|
59
|
+
specify "#exit_msg" do
|
60
|
+
err = capture_stderr do
|
61
|
+
expect(-> {exit_msg('critical')}).to raise_error(SystemExit)
|
62
|
+
end.uncolorize
|
63
|
+
expect(err).to eq("[ERROR] critical\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module LessonsIndexer
|
2
|
+
RSpec.describe Options do
|
3
|
+
let(:argv) { Array.new }
|
4
|
+
|
5
|
+
it "should assign default options if no arguments are given" do
|
6
|
+
options = Options.new(argv)
|
7
|
+
expect(options.path).to eq('.')
|
8
|
+
expect(options.skip_index).to be_falsey
|
9
|
+
expect(options.output).to eq('README.md')
|
10
|
+
expect(options.git).to be_falsey
|
11
|
+
expect(options.message).to eq('Added index')
|
12
|
+
expect(options.all).to be_falsey
|
13
|
+
expect(options.headings).to be_falsey
|
14
|
+
expect(options.headings_dir).to eq('headers')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow to override some options" do
|
18
|
+
argv = ['-p', 'test_path', '-g', '-o', 'test.md']
|
19
|
+
options = Options.new(argv)
|
20
|
+
expect(options.path).to eq('test_path')
|
21
|
+
expect(options.output).to eq('test.md')
|
22
|
+
expect(options.git).to be_truthy
|
23
|
+
expect(options.message).to eq('Added index')
|
24
|
+
expect(options.all).to be_falsey
|
25
|
+
expect(options.headings).to be_falsey
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "codeclimate-test-reporter"
|
2
|
+
CodeClimate::TestReporter.start
|
3
|
+
|
4
|
+
$LOAD_PATH << File.expand_path('../../../lib', __FILE__)
|
5
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
6
|
+
|
7
|
+
require 'lessons_indexer'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include SpecUtils
|
11
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpecUtils
|
2
|
+
def capture_stderr(&block)
|
3
|
+
original_stderr = $stderr
|
4
|
+
$stderr = fake = StringIO.new
|
5
|
+
begin
|
6
|
+
yield
|
7
|
+
ensure
|
8
|
+
$stderr = original_stderr
|
9
|
+
end
|
10
|
+
fake.string
|
11
|
+
end
|
12
|
+
|
13
|
+
def capture_stdout(&block)
|
14
|
+
original_stdout = $stdout
|
15
|
+
$stdout = fake = StringIO.new
|
16
|
+
begin
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
$stdout = original_stdout
|
20
|
+
end
|
21
|
+
fake.string
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lessons_indexer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ilya Bodrov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: slop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: facets
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.7.7
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.7.7
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Lessons Indexer for Learnable
|
112
|
+
email:
|
113
|
+
- golosizpru@gmail.com
|
114
|
+
executables:
|
115
|
+
- lessons_indexer
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".rspec"
|
121
|
+
- ".travis.yml"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/lessons_indexer
|
127
|
+
- bin/lessons_indexer.bat
|
128
|
+
- lessons_indexer.gemspec
|
129
|
+
- lib/lessons_indexer.rb
|
130
|
+
- lib/lessons_indexer/addons/file_manager.rb
|
131
|
+
- lib/lessons_indexer/addons/git_manager.rb
|
132
|
+
- lib/lessons_indexer/addons/utils.rb
|
133
|
+
- lib/lessons_indexer/course.rb
|
134
|
+
- lib/lessons_indexer/indexer.rb
|
135
|
+
- lib/lessons_indexer/options.rb
|
136
|
+
- lib/lessons_indexer/starter.rb
|
137
|
+
- lib/lessons_indexer/version.rb
|
138
|
+
- spec/addons/file_manager_spec.rb
|
139
|
+
- spec/addons/utils_spec.rb
|
140
|
+
- spec/options_spec.rb
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
- spec/support/spec_utils.rb
|
143
|
+
homepage: https://github.com/bodrovis/lessons_indexer
|
144
|
+
licenses:
|
145
|
+
- MIT
|
146
|
+
metadata: {}
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
requirements: []
|
162
|
+
rubyforge_project:
|
163
|
+
rubygems_version: 2.4.6
|
164
|
+
signing_key:
|
165
|
+
specification_version: 4
|
166
|
+
summary: Lessons Indexer for Learnable
|
167
|
+
test_files:
|
168
|
+
- spec/addons/file_manager_spec.rb
|
169
|
+
- spec/addons/utils_spec.rb
|
170
|
+
- spec/options_spec.rb
|
171
|
+
- spec/spec_helper.rb
|
172
|
+
- spec/support/spec_utils.rb
|