lessons_indexer 0.0.2.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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