lessons_indexer 0.0.2.2 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 700b6b45e2dcbff289222f9c44f1eaea2fcb9997
4
- data.tar.gz: 156538d022744cc4520352f90ca375e76266a288
3
+ metadata.gz: a7243e7160db8957d476986d9f39a7798a37f2b2
4
+ data.tar.gz: 99309f57fe10c2a1553d70f44d61a35626fd4a7d
5
5
  SHA512:
6
- metadata.gz: e6dec8a959a6ab12f203001e164ffd0cf3836bc090c64853078fa18c9417dab332d6c2fbb4629111128ad01fb794b4cfe0dfb1a62f1fb7df1e8b4b157ee9cd20
7
- data.tar.gz: 02fae34b5d7415b1b8d4a476e873b49e5132cf4224af35966fb0e34304e919a938ff0b8ff08cf2c3eea904bee706388bda5ecba26b7cde854c7feedcf0c80e3e
6
+ metadata.gz: 5e903f04e4067dd895c6d0883d0b8494b5c6e195f63f1bb71b82231a93b5f2a57145e8b23443ce81577d3ad3a71c14ef85445e5cfb805ecc0edf44c62483e777
7
+ data.tar.gz: aaeeed24149cc80a1382a2817bdadf12b07e97600512423a9f183dfd4be39b2fbd61f8f8eeba86ff41c4179724f083ea0d5910c5529dd71121837f59f73a86d8
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color --format doc --order rand --require spec_helper
1
+ --color --format doc --order rand --require spec_helper
@@ -10,4 +10,4 @@ install: bundle install --retry=3
10
10
 
11
11
  addons:
12
12
  code_climate:
13
- repo_token: df97d1d00135276a49d16e84df69eaa77e6cf3e9cd27c3e165b32524eee567cf
13
+ repo_token: 130f102bb847552a17b84646d50dba4809adf2af84aff06d8413dbe4d79ce8c0
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
- [![Build Status](https://travis-ci.org/bodrovis/LessonsIndexer.svg?branch=master)](https://travis-ci.org/bodrovis/LessonsIndexer)
2
- [![Code Climate](https://codeclimate.com/github/bodrovis/LessonsIndexer/badges/gpa.svg)](https://codeclimate.com/github/bodrovis/LessonsIndexer)
3
- [![Test Coverage](https://codeclimate.com/github/bodrovis/LessonsIndexer/badges/coverage.svg)](https://codeclimate.com/github/bodrovis/LessonsIndexer/coverage)
4
- [![Dependency Status](https://gemnasium.com/bodrovis/LessonsIndexer.svg)](https://gemnasium.com/bodrovis/LessonsIndexer)
1
+ [![Gem Version](https://badge.fury.io/rb/lessons_indexer.svg)](http://badge.fury.io/rb/lessons_indexer)
2
+ [![Build Status](https://travis-ci.org/bodrovis/lessons_indexer.svg?branch=master)](https://travis-ci.org/bodrovis/lessons_indexer)
3
+ [![Code Climate](https://codeclimate.com/github/bodrovis/lessons_indexer/badges/gpa.svg)](https://codeclimate.com/github/bodrovis/lessons_indexer)
4
+ [![Test Coverage](https://codeclimate.com/github/bodrovis/lessons_indexer/badges/coverage.svg)](https://codeclimate.com/github/bodrovis/lessons_indexer/coverage)
5
+ [![Dependency Status](https://gemnasium.com/bodrovis/lessons_indexer.svg)](https://gemnasium.com/bodrovis/lessons_indexer)
5
6
  # Lessons Indexer for Learnable
6
7
 
7
8
  Builds an index in Markdown format for the lesson files in the provided directory, adds heading images to the files,
@@ -49,7 +50,7 @@ is not set.
49
50
  * `-i` (`--headings`) - if present, heading images will be added to the beginning of each lesson file. If the file already
50
51
  has a heading in the beginning, it will be skipped.
51
52
  * `-d` (`--headings_dir`) - relative path to the directory with heading images.
52
- Defaults to `headers`, has no effect if the `-i` flag is not set.
53
+ Defaults to `headings`, has no effect if the `-i` flag is not set.
53
54
 
54
55
  ## Some Assumptions
55
56
 
@@ -19,8 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.add_dependency "facets", "~> 3.0"
20
20
  spec.add_dependency "colorize", "~> 0.7.7"
21
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"
22
+ spec.add_development_dependency "rake", "~> 10.4"
23
+ spec.add_development_dependency "rspec", "~> 3.2"
24
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4"
26
25
  end
@@ -2,14 +2,23 @@ require 'facets/string/titlecase'
2
2
  require 'slop'
3
3
  require 'colorize'
4
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
5
  require 'lessons_indexer/addons/file_manager'
11
6
  require 'lessons_indexer/addons/git_manager'
12
7
  require 'lessons_indexer/addons/utils'
13
8
 
9
+ require 'lessons_indexer/models/base'
10
+ require 'lessons_indexer/models/heading'
11
+ require 'lessons_indexer/models/lesson'
12
+
13
+ require 'lessons_indexer/collections/base'
14
+ require 'lessons_indexer/collections/headings_list'
15
+ require 'lessons_indexer/collections/lessons_list'
16
+
17
+ require 'lessons_indexer/version'
18
+ require 'lessons_indexer/options'
19
+ require 'lessons_indexer/course'
20
+ require 'lessons_indexer/indexer'
21
+ require 'lessons_indexer/starter'
22
+
14
23
  module LessonsIndexer
15
24
  end
@@ -1,28 +1,33 @@
1
1
  module LessonsIndexer
2
- class Writer
3
- attr_reader :name
2
+ module Addons
3
+ module FileManager
4
+ class Writer
5
+ attr_reader :name
4
6
 
5
- def initialize(name)
6
- @name = name
7
- end
7
+ def initialize(name)
8
+ @name = name
9
+ end
8
10
 
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
11
+ def prepend_data(data)
12
+ begin
13
+ old_data = File.read(name)
14
+ rescue StandardError => e
15
+ warning `ls`
16
+ warning e.message
17
+ end
18
+ unless old_data.start_with?(data)
19
+ new_data = old_data.prepend(data)
20
+ self << new_data
21
+ end
22
+ end
20
23
 
21
- def <<(*args)
22
- begin
23
- File.open(name, 'w+') { |f| f.write(args.join) }
24
- rescue StandardError => e
25
- warning e.message
24
+ def <<(*args)
25
+ begin
26
+ File.open(name, 'w+') { |f| f.write(args.join) }
27
+ rescue StandardError => e
28
+ warning e.message
29
+ end
30
+ end
26
31
  end
27
32
  end
28
33
  end
@@ -1,34 +1,36 @@
1
1
  module LessonsIndexer
2
- module GitManager
3
- class Pusher
4
- attr_reader :message
2
+ module Addons
3
+ module GitManager
4
+ class Pusher
5
+ attr_reader :message
5
6
 
6
- def initialize(message)
7
- @message = message
8
- end
7
+ def initialize(message)
8
+ @message = message
9
+ end
9
10
 
10
- def push!
11
- %x{git add .}
12
- %x{git commit -am "#{message}"}
13
- %x{git push origin HEAD}
11
+ def push!
12
+ %x{git add .}
13
+ %x{git commit -am "#{message}"}
14
+ %x{git push origin HEAD}
15
+ end
14
16
  end
15
- end
16
17
 
17
- class Brancher
18
- attr_reader :ignore_master
18
+ class Brancher
19
+ attr_reader :ignore_master
19
20
 
20
- def initialize(ignore_master = true)
21
- @ignore_master = ignore_master
22
- end
21
+ def initialize(ignore_master = true)
22
+ @ignore_master = ignore_master
23
+ end
23
24
 
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
25
+ def get_branches
26
+ branches = %x{git branch}.split("\n").map {|br| br.strip.gsub(/\A\*\s*/, '') }
27
+ ignore_master ? branches.reject {|el| el == 'master'} : branches
28
+ end
28
29
 
29
- def within_branch(branch)
30
- %x{git checkout #{branch} --force}
31
- yield if block_given?
30
+ def within_branch(branch)
31
+ %x{git checkout #{branch} --force}
32
+ yield if block_given?
33
+ end
32
34
  end
33
35
  end
34
36
  end
@@ -0,0 +1,17 @@
1
+ module LessonsIndexer
2
+ module Collections
3
+ class Base
4
+ include Enumerable
5
+
6
+ attr_reader :list
7
+
8
+ def initialize(list)
9
+ @list = list
10
+ end
11
+
12
+ def each
13
+ list.map { |heading| yield heading }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module LessonsIndexer
2
+ module Collections
3
+ class HeadingsList < Base
4
+ def for(lesson)
5
+ detect do |heading|
6
+ lesson.major == heading.major && lesson.minor == heading.minor
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module LessonsIndexer
2
+ module Collections
3
+ class LessonsList < Base
4
+ end
5
+ end
6
+ end
@@ -1,32 +1,50 @@
1
1
  module LessonsIndexer
2
2
  class Course
3
- STEP_LESSON_PATTERN = /(\d+)(?:\.|-)(\d+)/
3
+ include Models
4
+ include Collections
4
5
 
5
- attr_reader :dir, :title, :lessons
6
+ attr_reader :dir, :headings_dir, :title, :lessons, :headings
6
7
 
7
- def initialize(course_dir)
8
+ def initialize(course_dir, headings_dir)
8
9
  @dir = course_dir
10
+ @headings_dir = headings_dir
9
11
  @title = dir.gsub(/_handouts\z/i, '').titlecase
10
- @lessons = get_lessons
12
+ @headings = []
11
13
  end
12
14
 
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
15
+ def generate_index
16
+ lessons.list.sort.inject("# Index for the " + title + " course\n\n") do |memo, lesson|
17
+ memo + lesson.link(dir)
18
+ end
19
+ end
20
+
21
+ def generate_headings
22
+ lessons.each do |lesson|
23
+ lesson_heading = headings.for(lesson)
24
+ if lesson_heading
25
+ yield "![](#{headings_dir}/#{lesson_heading.file_name})\n\n", lesson.path
26
+ else
27
+ warning "I was not able to find heading image for the #{lesson.name}"
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ def load_headings!
33
+ within(dir + '/' + headings_dir, true) do
34
+ @headings = HeadingsList.new(all_with_pattern(Heading::VERSION_PATTERN).map {|heading| Heading.new(heading)})
35
+ end
36
+ end
37
+
38
+ def load_lessons!
39
+ within(dir, true) do
40
+ @lessons = LessonsList.new(all_with_pattern(Lesson::NAME_PATTERN).map {|lesson| Lesson.new(lesson)})
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def all_with_pattern(pattern)
47
+ Dir.entries('.').keep_if {|f| f =~ pattern }
48
+ end
31
49
  end
32
50
  end
@@ -1,6 +1,7 @@
1
1
  module LessonsIndexer
2
2
  class Indexer
3
- STEP_LESSON_PATTERN = /(\d+)(?:\.|-)(\d+)/
3
+ include Addons::FileManager
4
+ include Addons::GitManager
4
5
 
5
6
  attr_reader :options
6
7
 
@@ -8,88 +9,36 @@ module LessonsIndexer
8
9
  @options = options
9
10
  end
10
11
 
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
12
+ def do_work!
13
+ course = Course.new(get_course_dir, options.headings_dir)
17
14
 
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
15
+ build_index(course) unless options.skip_index
16
+ add_headings(course) if options.headings
17
+ git_push! if options.git
25
18
  end
26
19
 
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!("![](#{options.headings_dir}/#{lesson_image})\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
20
+ def build_index(course)
21
+ course.load_lessons!
22
+ with_messages("Starting to build index...", "Index for the #{course.title} course is generated!") do
23
+ write! course.generate_index, options.output
47
24
  end
48
25
  end
49
26
 
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 ''
27
+ def add_headings(course)
28
+ course.load_lessons!
29
+ course.load_headings!
30
+ with_messages("Starting to add headings...", "Headings for the lesson files of #{course.title} course were added!") do
31
+ course.generate_headings { |heading_line, lesson_file| prepend!(heading_line, lesson_file) }
65
32
  end
66
33
  end
67
34
 
68
- def get_dir_name
69
- dir = get_files.detect {|el| el =~ /_handouts\z/i}
35
+ def get_course_dir
36
+ dir = Dir.entries('.').detect {|el| el =~ /_handouts\z/i}
70
37
  exit_msg("Lesson files were not found inside the provided directory. Aborting...") if dir.nil?
71
38
  dir
72
39
  end
73
40
 
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
41
+ private
93
42
 
94
43
  def write!(contents, file)
95
44
  writer = Writer.new(file)
@@ -100,5 +49,10 @@ module LessonsIndexer
100
49
  writer = Writer.new(file)
101
50
  writer.prepend_data(contents)
102
51
  end
52
+
53
+ def git_push!
54
+ pusher = Pusher.new(options.message)
55
+ pusher.push!
56
+ end
103
57
  end
104
58
  end
@@ -0,0 +1,25 @@
1
+ module LessonsIndexer
2
+ module Models
3
+ class Base
4
+ include Comparable
5
+
6
+ VERSION_PATTERN = /(?<minor_major>(?<major>(\d+))(?:\.|-)(?<minor>(\d+)))/i
7
+ attr_reader :file_name, :major, :minor, :path
8
+
9
+ def initialize(file_name)
10
+ @file_name = file_name
11
+ @path = File.expand_path(file_name)
12
+ @major = file_name.match(VERSION_PATTERN)[:major].to_i
13
+ @minor = file_name.match(VERSION_PATTERN)[:minor].to_i
14
+ end
15
+
16
+ def <=>(other)
17
+ if self.major == other.major
18
+ self.minor <=> other.minor
19
+ else
20
+ self.major <=> other.major
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end