roject 0.5.0 → 0.6.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: 208a333165807d295fc40b90cfddc1431721cfb4
4
- data.tar.gz: b16f2f8863a41781887024765afbe592ad461503
3
+ metadata.gz: ad19a40c37044d2c05db12edde1618900c5f2897
4
+ data.tar.gz: 4a7050a650334712f4d7b96b4b164e6229aa3404
5
5
  SHA512:
6
- metadata.gz: b0adfc93d7dc2c1add24a6537b217821a30a45f3e4b241036e55229c8a4fbe49169980af3fb1041fe3da14a74ec569ed16edbafc85e97f4fad040dc157747c6c
7
- data.tar.gz: 2e395a73765997c907e5ebd83b0805c1e5abcf6384cfdf329a8a0328c03c48f4038bde95ab73d28b343e25baa534be836855d52b19295c8617b9e5f7a0f5c6fc
6
+ metadata.gz: ba8034309255d69673d30b41c6044fe3c5369ed5fa73003139e58043bc939e43a6f41d258ed07aa422c28645035d0ddf1d0fcddae7382ec572536ea3d7868cee
7
+ data.tar.gz: 9757271c4518331712df7265bd6f2b00e1b01b23886a8ab20712da7a40141a57b9ed779955a1fefcbee80f225698694e4253349328cc8d53dee1fc8936ec413f
@@ -0,0 +1,37 @@
1
+ # Config
2
+ config project_name: "Dre",
3
+ author: "Anshul Kharbanda",
4
+ created: "7 - 23 - 2016",
5
+ short_description: "Forgot about Dre.",
6
+ long_description: "Nowadays everybody wanna talk like" \
7
+ " they got somethin' to say but nothin' comes out" \
8
+ " when they move their lips just a bunch of gibberish" \
9
+ " and they all acting like they forgot about Dre."
10
+
11
+ =begin
12
+
13
+ #---------------------------MAKERS---------------------------
14
+
15
+ # Header file
16
+ file :header,
17
+ path: "include/@(project_name)/@(path)",
18
+ template: "header.general",
19
+ extension: "h"
20
+
21
+ # Source file
22
+ file :source,
23
+ path: "src/@(path)",
24
+ template: "source.general",
25
+ extension: "cpp"
26
+
27
+ # Module includes a source and include
28
+ task :module do |args|
29
+ # Add header id
30
+ args[:header_id] = c_header_id(args[:path])
31
+
32
+ # Create source and header
33
+ make :header, args
34
+ make :source, args
35
+ end
36
+
37
+ =end
@@ -35,7 +35,7 @@ module Roject
35
35
  # Parameter: project - the project running the task
36
36
  # Parameter: args - the args being used to run the task
37
37
  def make project, args
38
- project.instance_exec project.hash.merge(args), &@block
38
+ project.instance_exec project.config.merge(args), &@block
39
39
  end
40
40
  end
41
41
 
@@ -50,9 +50,9 @@ module Roject
50
50
  # Initializes a FileMaker from the given hash
51
51
  #
52
52
  # Parameter: hash - the hash to parse
53
- def initialize hash
53
+ def initialize project, hash
54
54
  @path = General::GTemplate.new hash[:path]
55
- @template = General::GIO.load hash[:template]
55
+ @template = General::GIO.load "#{project.config[:directory][:templates]}/#{hash[:template]}"
56
56
  @extension = hash[:extension]
57
57
  end
58
58
 
@@ -62,7 +62,7 @@ module Roject
62
62
  # Parameter: args - the args being used to create the file
63
63
  def make project, args
64
64
  # merge args with project
65
- args.merge! project.hash
65
+ args.merge! project.config
66
66
 
67
67
  # Get path
68
68
  path = "#{@path.apply(args)}.#{@extension}"
data/lib/project.rb CHANGED
@@ -12,9 +12,8 @@ Created: 7 - 8 - 2016
12
12
  =end
13
13
 
14
14
  # Other modules
15
- require_relative "loadsaveable"
16
15
  require_relative "helpers"
17
- require_relative "maker"
16
+ require_relative "makers"
18
17
 
19
18
  # Roject is a programming project manager written in Ruby.
20
19
  #
@@ -27,60 +26,77 @@ module Roject
27
26
  # Created: 7 - 10 - 2016
28
27
  class Project
29
28
  # Includes
30
- include LoadSaveable
31
29
  include Helpers
32
30
 
33
- # Creates a Project with the given data hash
31
+ # Default configuration
32
+ CONFIG_DEFAULT = {
33
+ project_name: "[project-name]",
34
+ author: "[author]",
35
+ created: "[created]",
36
+ short_description: "[short_description]",
37
+ long_description: "[long_description]",
38
+ directory: {
39
+ templates: "_templates"
40
+ }
41
+ }
42
+
43
+ # Loads a Project from the project file with the given filename
44
+ #
45
+ # Parameter: filename - the name of the file to parse
34
46
  #
35
- # Parameter: hash - the data to be contained in the project
36
- def initialize hash={}
37
- @project = hash
38
- @makers = {}
47
+ # Return: Project loaded from the file
48
+ def self.load filename
49
+ project = Roject::Project.new
50
+ project.instance_eval(IO.read(filename))
51
+ return project
39
52
  end
40
53
 
41
- # Returns a hash of the data contained in the project
42
- #
43
- # Return: a hash of the data contained in the project
44
- def hash; @project; end
54
+ #----------------------------------INIT AND CONFIG----------------------------------
45
55
 
46
- # Attributes part of Project
47
- get :project_name,
48
- :author,
49
- :created,
50
- :short_description,
51
- :long_description,
52
- :directories
56
+ # Called upon the initialization of a Project
57
+ # Creates config and makers hashes
58
+ def initialize; @config = CONFIG_DEFAULT; @makers = {}; end
53
59
 
54
- # Loads the makers in the file with the given filename
60
+ # If a hash is given, sets the Project configuration to the hash.
61
+ # Else, returns the configuration of the Project.
62
+ #
63
+ # Parameter: hash - the hash to configure the project with
55
64
  #
56
- # Parameter: filename - the name of the file to read
57
- def load_makers(filename); instance_eval(IO.read(filename)); end
65
+ # Return: the configuration of the Project
66
+ def config(hash=nil); hash and @config.merge!(hash) or return @config; end
67
+
68
+ #-------------------------------------MAKERS-----------------------------------------
58
69
 
59
70
  # Runs the maker of the given name with the given args
60
71
  #
61
72
  # Parameter: name - the name of the maker to run
62
73
  # Parameter: args - the args to pass to the file
63
- def make name, args
64
- @makers[name].make(self, args)
74
+ def make(name, args)
75
+ if @makers.has_key? name
76
+ @makers[name].make self, args
77
+ else
78
+ raise RuntimeError, "Undefied maker #{name}"
79
+ end
65
80
  end
66
81
 
67
82
  # Creates a file maker with the given name and hash
68
83
  #
69
84
  # Parameter: name - the name of the maker
70
85
  # Parameter: hash - the hash arguments of the maker
71
- def file name, hash
72
- @makers[name] = FileMaker.new(hash)
86
+ def file(name, hash)
87
+ unless @makers.has_key? name
88
+ @makers[name] = FileMaker.new self, hash
89
+ end
73
90
  end
74
91
 
75
- # Adds the recipie specified by the given name and block
76
- # to the makers table
92
+ # Creates a task maker with the given name and block
77
93
  #
78
94
  # Parameter: name - the name of the recipie
79
95
  # Parameter: block - the recipie block
80
- #
81
- # Throw: RuntimeError - if the name is already defined as a filetype
82
- def task name, &block
83
- @makers[name] = TaskMaker.new &block
96
+ def task(name, &block);
97
+ unless @makers.has_key? name
98
+ @makers[name] = TaskMaker.new &block
99
+ end
84
100
  end
85
101
  end
86
102
  end
data/lib/roject.rb CHANGED
@@ -20,5 +20,5 @@ require_relative "project"
20
20
  # Created: 7 - 8 - 2016
21
21
  module Roject
22
22
  # The Version of Roject
23
- VERSION = "0.5.0"
23
+ VERSION = "0.6.0"
24
24
  end
data/spec/project_spec.rb CHANGED
@@ -23,65 +23,187 @@ require_relative "spec_require"
23
23
  describe Roject::Project do
24
24
  # Do before
25
25
  before :all do
26
- Dir.chdir "exp/project"
27
- @project = Roject::Project.load "project.yaml"
26
+ Dir.chdir "exp/project"
27
+ @project = Roject::Project.new
28
+ @config = Roject::Project::CONFIG_DEFAULT.merge({
29
+ project_name: "Foo",
30
+ author: "Anshul Kharbanda",
31
+ created: "7 - 23 - 2016",
32
+ short_description: "Foo bar",
33
+ long_description: "Foo bar baz ju lar laz nu kar kaz"
34
+ })
28
35
  end
29
36
 
30
- # Describe Roject::Project#load_recipies
37
+ # Describe Roject::Project#config
38
+ #
39
+ # If a hash is given, sets the Project configuration to the hash.
40
+ # Else, returns the configuration of the Project.
41
+ #
42
+ # Parameter: hash - the hash to configure the project with
43
+ #
44
+ # Return: the configuration of the Project
45
+ describe '#config' do
46
+ context 'with no arguments given' do
47
+ it 'returns the configuration of the Project' do
48
+ expect(@project.config).to eql Roject::Project::CONFIG_DEFAULT
49
+ end
50
+ end
51
+
52
+ context 'with hash given' do
53
+ it 'configures the Project with the given hash' do
54
+ expect{@project.config(@config)}.not_to raise_error
55
+ expect(@project.config).to eql @config
56
+ end
57
+ end
58
+ end
59
+
60
+ # Describe Roject::Project::load
61
+ #
62
+ # Loads a Project from the project file with the given filename
31
63
  #
32
- # Loads the recipies in the file with the given filename
64
+ # Parameter: filename - the name of the file to parse
33
65
  #
34
- # Parameter: filename - the name of the file to read
35
- describe '#load_recipies' do
36
- it 'reads a recipies file and evaluates it in the context of the Project' do
37
- expect { @project.load_makers("makers.rb") }.not_to raise_error
66
+ # Return: Project loaded from the file
67
+ describe '::load' do
68
+ it 'loads a project from the given filename' do
69
+ expect{@project = Roject::Project.load "project.rb"}.not_to raise_error
70
+ expect(@project).to be_an_instance_of Roject::Project
38
71
  end
39
72
  end
40
73
 
41
- # Describe Roject::Project#make
74
+ # Describe Roject::Project makers
42
75
  #
43
- # Runs the maker of the given name with the given args
76
+ # The system of automating tasks in Roject
44
77
  #
45
- # Parameter: name - the name of the maker to run
46
- # Parameter: args - the args to pass to the file
47
- describe '#make' do
78
+ # Author: Anshul Kharbanda
79
+ # Created: 7 - 24 - 2016
80
+ describe 'makers' do
81
+ # Before all
48
82
  before :all do
49
83
  @path = "path/to/file"
50
84
 
85
+ # ----------------------FILE INFO----------------------
86
+
51
87
  @header = {
52
- type: :header,
53
- out: "include/#{@project.project_name}/#{@path}.h",
88
+ name: :header,
89
+ path: "include/@(project_name)/@(path)",
90
+ template: "header.general",
91
+ extension: "h",
92
+ out: "include/#{@project.config[:project_name]}/#{@path}.h",
54
93
  text: IO.read("output/testheader.h")
55
94
  }
56
95
 
57
96
  @source = {
58
- type: :source,
97
+ name: :source,
98
+ path: "src/@(path)",
99
+ template: "source.general",
100
+ extension: "cpp",
59
101
  out: "src/#{@path}.cpp",
60
102
  text: IO.read("output/testsource.cpp")
61
103
  }
104
+
105
+ # ----------------------TASK INFO----------------------
106
+
107
+ @module = {
108
+ name: :module,
109
+ block: Proc.new do |args|
110
+ args[:header_id] = c_header_id(args[:path])
111
+
112
+ make :header, args
113
+ make :source, args
114
+ end
115
+ }
62
116
  end
63
117
 
64
- # Creating filetype
65
- context 'with a file maker name given' do
66
- it 'creates a file of the given type with the given arguments' do
67
- @project.make @header[:type], path: @path, header_id: @project.c_header_id(@path)
68
- expect(File).to be_file(@header[:out])
69
- expect(IO.read(@header[:out])).to eql @header[:text]
118
+ # Describe Roject::Project#file
119
+ #
120
+ # Creates a file maker with the given name and hash
121
+ #
122
+ # Parameter: name - the name of the maker
123
+ # Parameter: hash - the hash arguments of the maker
124
+ describe '#file' do
125
+ it 'creates a file maker with the given name and hash of arguments' do
126
+ # Each file type
127
+ [@header, @source].each do |ft|
128
+ # Create filemaker
129
+ @project.file ft[:name], ft
130
+
131
+ # Get Filemaker
132
+ fmkr = @project.instance_variable_get(:@makers)[ft[:name]]
133
+ expect(fmkr).to be_an_instance_of Roject::FileMaker
134
+
135
+ # Path
136
+ expect(fmkr.instance_variable_get(:@path)).to be_an_instance_of General::GTemplate
137
+ expect(fmkr.instance_variable_get(:@path).to_s).to eql ft[:path]
138
+
139
+ # Template
140
+ expect(fmkr.instance_variable_get(:@template)).to be_an_instance_of General::GIO
141
+ expect(fmkr.instance_variable_get(:@template).source).to eql "#{@project.config[:directory][:templates]}/#{ft[:template]}"
142
+
143
+ # Extension
144
+ expect(fmkr.instance_variable_get(:@extension)).to eql ft[:extension]
145
+ end
70
146
  end
71
147
  end
72
148
 
73
- # Performing task
74
- context 'with a task maker name given' do
75
- it 'performs the task of the given name with the given arguments' do
76
- @project.make :module, path: @path
77
- [@header, @source].each do |file|
78
- expect(File).to be_file(file[:out])
79
- expect(IO.read(file[:out])).to eql file[:text]
80
- end
149
+ # Describe Roject::Project#task
150
+ #
151
+ # Creates a task maker with the given name and block
152
+ #
153
+ # Parameter: name - the name of the recipie
154
+ # Parameter: block - the recipie block
155
+ describe '#task' do
156
+ it 'creates a task maker with the given name and block' do
157
+ # Create taskmaker
158
+ @project.task @module[:name], &@module[:block]
159
+
160
+ # Get filemaker
161
+ tmkr = @project.instance_variable_get(:@makers)[@module[:name]]
162
+ expect(tmkr).to be_an_instance_of Roject::TaskMaker
81
163
  end
82
164
  end
83
165
 
84
- # Do afterwards
85
- after :each do FileUtils.rmtree(@project.directories) end
166
+ # Describe Roject::Project#make
167
+ #
168
+ # Runs the maker of the given name with the given args
169
+ #
170
+ # Parameter: name - the name of the maker to run
171
+ # Parameter: args - the args to pass to the file
172
+ describe '#make' do
173
+ # Creating filetype
174
+ context 'with a file maker name given' do
175
+ it 'creates a file of the given type with the given arguments' do
176
+ # Each file type
177
+ [@header, @source].each do |ft|
178
+ # Make Header
179
+ @project.make ft[:name],
180
+ path: @path,
181
+ header_id: @project.c_header_id(@path)
182
+
183
+ # Test output
184
+ expect(File).to be_file(ft[:out])
185
+ expect(IO.read(ft[:out])).to eql ft[:text]
186
+ end
187
+ end
188
+ end
189
+
190
+ # Performing task
191
+ context 'with a task maker name given' do
192
+ it 'performs the task of the given name with the given arguments' do
193
+ # Do task
194
+ @project.make @module[:name], path: @path
195
+
196
+ # Each header
197
+ [@header, @source].each do |file|
198
+ # Test output
199
+ expect(File).to be_file(file[:out])
200
+ expect(IO.read(file[:out])).to eql file[:text]
201
+ end
202
+ end
203
+ end
204
+
205
+ # Do afterwards
206
+ after :each do FileUtils.rmtree ["include", "src"] end
207
+ end
86
208
  end
87
209
  end
data/spec/spec_require.rb CHANGED
@@ -11,71 +11,5 @@ Created: 7 - 8 - 2016
11
11
 
12
12
  =end
13
13
 
14
- # Required libraries
15
- require "json"
16
- require "yaml"
17
-
18
14
  # Required files for spec
19
- require_relative "../lib/parsers"
20
- require_relative "../lib/project"
21
- require_relative "../lib/loadsaveable"
22
-
23
- #-----------------------HASHMOD METHODS------------------------
24
-
25
- # Returns the hash with all of the keys converted to symbols
26
- #
27
- # Parameter: hash - the hash to symbolize
28
- #
29
- # Return: the hash with all of the keys converted to symbols
30
- def symbolized hash
31
- hash.each_pair.collect { |k, v| [k.to_sym, v.is_a?(Hash) ? symbolized(v) : v] }.to_h
32
- end
33
-
34
- # Returns the hash with all of the keys converted to strings
35
- #
36
- # Parameter: hash - the hash to stringify
37
- #
38
- # Return: the hash with all of the keys converted to strings
39
- def stringified hash
40
- hash.each_pair.collect { |k, v| [k.to_s, v.is_a?(Hash) ? stringified(v) : v] }.to_h
41
- end
42
-
43
- #------------------------READER METHODS------------------------
44
-
45
- # Reads JSON from the file with the given filename
46
- #
47
- # Parameter: filename - the name of the file to read
48
- #
49
- # Return: hash parsed from JSON file
50
- def read_json filename
51
- JSON.parse IO.read(filename), symbolize_names: true
52
- end
53
-
54
- # Reads YAML from the file with the given filename
55
- #
56
- # Parameter: filename - the name of the file to read
57
- #
58
- # Return: hash parsed from YAML file
59
- def read_yaml filename
60
- symbolized YAML.load IO.read(filename)
61
- end
62
-
63
- #------------------------WRITER METHODS------------------------
64
-
65
- # Writes the given hash as JSON to the file with the
66
- # given filename
67
- #
68
- # Parameter: filename - the name of the file to write to
69
- # Parameter: hash - the hash to write
70
- def write_json filename, hash
71
- IO.write filename, JSON.pretty_generate(hash, indent: "\t")
72
- end
73
-
74
- # Writes the given hash as YAML to the file with the
75
- # given filename
76
- #
77
- # Parameter: filename - the name of the file to write to
78
- # Parameter: hash - the hash to write
79
- def write_yaml filename, hash
80
- IO.write filename, YAML.dump(stringified(hash))
81
- end
15
+ require_relative "../lib/project"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roject
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anshul Kharbanda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-24 00:00:00.000000000 Z
11
+ date: 2016-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: general
@@ -81,20 +81,15 @@ files:
81
81
  - exp/loadsaveable/foo.json
82
82
  - exp/loadsaveable/foo.yaml
83
83
  - exp/loadsaveable/foo.yml
84
- - exp/project/makers.rb
84
+ - exp/project/_templates/header.general
85
+ - exp/project/_templates/source.general
85
86
  - exp/project/output/testheader.h
86
87
  - exp/project/output/testsource.cpp
87
- - exp/project/project.yaml
88
- - exp/project/templates/header.general
89
- - exp/project/templates/source.general
88
+ - exp/project/project.rb
90
89
  - lib/helpers.rb
91
- - lib/loadsaveable.rb
92
- - lib/maker.rb
93
- - lib/parsers.rb
90
+ - lib/makers.rb
94
91
  - lib/project.rb
95
92
  - lib/roject.rb
96
- - spec/loadsaveable_spec.rb
97
- - spec/parsers_spec.rb
98
93
  - spec/project_spec.rb
99
94
  - spec/spec_require.rb
100
95
  homepage:
@@ -1,21 +0,0 @@
1
- # Header file
2
- file :header,
3
- path: "include/@(project_name)/@(path)",
4
- template: "templates/header.general",
5
- extension: "h"
6
-
7
- # Source file
8
- file :source,
9
- path: "src/@(path)",
10
- template: "templates/source.general",
11
- extension: "cpp"
12
-
13
- # Module includes a source and include
14
- task :module do |args|
15
- # Add header id
16
- args[:header_id] = c_header_id(args[:path])
17
-
18
- # Create source and header
19
- make :header, args
20
- make :source, args
21
- end
@@ -1,9 +0,0 @@
1
- ---
2
- project_name: Dre
3
- author: Anshul Kharbanda
4
- created: 7 - 23 - 2016
5
- short_description: Forgot about Dre.
6
- long_description: Nowadays everybody wanna talk like they got somethin' to say but nothin' comes out when they move their lips just a bunch of gibberish and they all acting like they forgot about Dre.
7
- directories:
8
- - include
9
- - src
data/lib/loadsaveable.rb DELETED
@@ -1,121 +0,0 @@
1
- =begin
2
-
3
- Program: Roject
4
-
5
- Roject is a programming project manager written in Ruby.
6
- With Roject, you can create and edit projects based on templates
7
- using simple commands without a heavy IDE.
8
-
9
- Author: Anshul Kharbanda
10
- Created: 7 - 8 - 2016
11
-
12
- =end
13
-
14
- # Parsers
15
- require_relative "parsers"
16
-
17
- # Roject is a programming project manager written in Ruby.
18
- #
19
- # Author: Anshul Kharbanda
20
- # Created: 7 - 8 - 2016
21
- module Roject
22
- # Implementing objects can be loaded from and saved to files in
23
- # any of the supported data storage formats.
24
- #
25
- # Formats: json, yaml
26
- #
27
- # Note: Implementing objects must have a constructor with takes a single hash
28
- # argument and respond to the :hash method which returns a hash of the
29
- # data that needs to be saved
30
- #
31
- # Author: Anshul Kharbanda
32
- # Created: 7 - 10 - 2016
33
- module LoadSaveable
34
- # Methods that are implemented at the class level
35
- #
36
- # Author: Anshul Kharbanda
37
- # Created: 7 - 10 - 2016
38
- module ClassMethods
39
- # Opens the object from a file, evaluates the given
40
- # block in the context of the object, and saves the object.
41
- # If no block is given, returns the object (alias for load)
42
- #
43
- # Parameter: filename - the name of the file to open
44
- # Parameter: block - the block to evaluate within the
45
- # context of the object
46
- #
47
- # Return: the object loaded from the file (if no block given)
48
- def open filename, &block
49
- obj = load(filename)
50
- if block.nil?
51
- return obj
52
- else
53
- obj.instance_exec(&block)
54
- obj.save(filename)
55
- end
56
- end
57
-
58
- # Loads an object from a file of the given filename, parsed
59
- # in the appropriate format based on the extension
60
- #
61
- # Parameter: filename - the name of the file
62
- #
63
- # Return: object loaded from the file
64
- def load filename
65
- self.new Parsers.get(filename).parse IO.read filename
66
- end
67
-
68
- # Defines getter methods for the given names
69
- # each retrieve the value of name in the hash
70
- #
71
- # Parameter: names - the names to define
72
- def get *names
73
- unless names.empty?
74
- names.each do |name|
75
- #add name to attributes list
76
- @attributes ||= []
77
- @attributes << name
78
-
79
- # define method name
80
- define_method(name) { hash[name] }
81
- end
82
- end
83
- end
84
-
85
- # Returns all attributes that are
86
- # part of the LoadSaveable implementation
87
- #
88
- # Return: all attributes that are
89
- # part of the LoadSaveable
90
- # implementation
91
- def attributes
92
- @attributes or []
93
- end
94
- end
95
-
96
- # Methods that are implemented at the instance level
97
- #
98
- # Author: Anshul Kharbanda
99
- # Created: 7 - 10 - 2016
100
- module InstanceMethods
101
- # Saves the object at the given filename, formatted according
102
- # to the extension
103
- #
104
- # Parameter: filename - the name of the file to save to
105
- # (opened in w+ mode). Extension
106
- # determines format
107
- def save filename
108
- IO.write filename, Parsers.get(filename).format(hash)
109
- end
110
- end
111
-
112
- # The implementing reciever will extend ClassMethods
113
- # and include InstanceMethods
114
- #
115
- # Parameter: reciever - the object being included
116
- def self.included(receiver)
117
- receiver.extend ClassMethods
118
- receiver.send :include, InstanceMethods
119
- end
120
- end
121
- end
data/lib/parsers.rb DELETED
@@ -1,145 +0,0 @@
1
- =begin
2
-
3
- Program: Roject
4
-
5
- Roject is a programming project manager written in Ruby.
6
- With Roject, you can create and edit projects based on templates
7
- using simple commands without a heavy IDE.
8
-
9
- Author: Anshul Kharbanda
10
- Created: 7 - 8 - 2016
11
-
12
- =end
13
-
14
- # Parser libraries
15
- require "json"
16
- require "yaml"
17
-
18
- # Roject is a programming project manager written in Ruby.
19
- #
20
- # Author: Anshul Kharbanda
21
- # Created: 7 - 8 - 2016
22
- module Roject
23
- # Contains implementations of parsers for different filetypes
24
- #
25
- # Author: Anshul Kharbanda
26
- # Created: 7 - 11 - 2016
27
- module Parsers
28
- # Generic class parses files of a given type
29
- #
30
- # Subclasses must respond to :parse, :format, and :extension methods
31
- # - parse recieves a string and returns a hash
32
- # - format recieves a hash and returns a string
33
- # - extensions returns all of the supported extensions of the Parser
34
- #
35
- # Author: Anshul Kharbanda
36
- # Created: 7 - 11 - 2016
37
- class Parser
38
- # Matches parser class names
39
- PARSER_REGEX = /(Roject::)?(Parsers::)?(?<name>\w+)Parser/
40
-
41
- # Returns the descendants of Parser
42
- #
43
- # Return: the descendants of Parser
44
- def self.descendants
45
- ObjectSpace.each_object(Class).select {|c| c < self}
46
- end
47
-
48
- # Returns true if the parser is to be used for the given filename
49
- #
50
- # Return: true if the parser is to be used for the given filename
51
- def self.for_filename? filename
52
- extensions.include? File.extname(filename)
53
- end
54
- end
55
-
56
- # Returns the parser for the given filename
57
- #
58
- # Parameter: filename - the name of the file to parse
59
- #
60
- # Return: the parser for the given filename
61
- def self.get(filename)
62
- # Get parser from filename
63
- parser = Parser.descendants.find { |klass| klass.for_filename? filename }
64
-
65
- # Raise LoadError if no parser is found, else return parser
66
- if parser.nil?
67
- raise LoadError, "#{File.extname(filename)} not supported!"
68
- else
69
- return parser
70
- end
71
- end
72
-
73
- #---------------------------------------PARSERS---------------------------------------
74
-
75
- # Parses JSON files
76
- #
77
- # Author: Anshul Kharbanda
78
- # Created: 7 - 11 - 2016
79
- class JSONParser < Parser
80
- # Returns the extensions supported for JSON
81
- #
82
- # Return: the extensions supported for JSON
83
- def self.extensions; [".json"]; end
84
-
85
- # Parses the given json text into a hash
86
- #
87
- # Parameter: text - the json text to parse
88
- #
89
- # Return: the hash parsed from the text
90
- def self.parse(text); JSON.parse text, symbolize_names: true; end
91
-
92
- # Returns the given hash formatted to pretty json
93
- #
94
- # Parameter: hash - the hash to format
95
- #
96
- # Return: the given hash formatted to pretty json
97
- def self.format(hash); JSON.pretty_generate hash, indent: "\t"; end
98
- end
99
-
100
- # Parses YAML files
101
- #
102
- # Author: Anshul Kharbanda
103
- # Created: 7 - 13 - 2016
104
- class YAMLParser < Parser
105
- # Returns the extensions supported for YAML
106
- #
107
- # Return: the extensions supported for YAML
108
- def self.extensions; [".yaml", ".yml"]; end
109
-
110
- # Parses the given yaml text into a hash
111
- #
112
- # Parameter: text - the yaml text to parse
113
- #
114
- # Return: the hash parsed from the text
115
- def self.parse(text); symbolized YAML.load text; end
116
-
117
- # Returns the given hash formatted to yaml
118
- #
119
- # Parameter: hash - the hash to format
120
- #
121
- # Return: the given hash formatted to yaml
122
- def self.format(hash); YAML.dump stringified hash end
123
-
124
- private
125
-
126
- # Returns the hash with all of the keys converted to symbols
127
- #
128
- # Parameter: hash - the hash to symbolize
129
- #
130
- # Return: the hash with all of the keys converted to symbols
131
- def self.symbolized hash
132
- hash.each_pair.collect { |k, v| [k.to_sym, v.is_a?(Hash) ? symbolized(v) : v] }.to_h
133
- end
134
-
135
- # Returns the hash with all of the keys converted to strings
136
- #
137
- # Parameter: hash - the hash to stringify
138
- #
139
- # Return: the hash with all of the keys converted to strings
140
- def self.stringified hash
141
- hash.each_pair.collect { |k, v| [k.to_s, v.is_a?(Hash) ? stringified(v) : v] }.to_h
142
- end
143
- end
144
- end
145
- end
@@ -1,392 +0,0 @@
1
- =begin
2
-
3
- Program: Roject
4
-
5
- Roject is a programming project manager written in Ruby.
6
- With Roject, you can create and edit projects based on templates
7
- using simple commands without a heavy IDE.
8
-
9
- Author: Anshul Kharbanda
10
- Created: 7 - 8 - 2016
11
-
12
- =end
13
-
14
- require_relative "spec_require"
15
-
16
- # Describing LoadSaveable
17
- #
18
- # Implementing objects can be loaded from and saved to files in
19
- # any of the supported data storage formats.
20
- #
21
- # Formats: json
22
- #
23
- # Note: Implementing objects need to respond to the :hash method
24
- # which returns a hash of the data that needs to be saved
25
- #
26
- # Author: Anshul Kharbanda
27
- # Created: 7 - 11 - 2016
28
- describe Roject::LoadSaveable do
29
- #---------------------------------------BEFORE----------------------------------------
30
-
31
- before :all do
32
- # Basic LoadSaveable implementation
33
- class LoadSaveableClass
34
- include Roject::LoadSaveable
35
- def initialize(hash={}); @foo = hash; end
36
- def hash; @foo; end
37
- get :name, :author
38
- end
39
-
40
- @dir = "exp/loadsaveable"
41
- @default_hash = { name: "project", author: "Anshul Kharbanda" }
42
- @modded_hash = { name: "superproject", author: "Super Anshul Kharbanda" }
43
- @pjson_name = "#{@dir}/foo.json"
44
- @pyaml_name = "#{@dir}/foo.yaml"
45
- @pyml_name = "#{@dir}/foo.yml"
46
- @phony_name = "#{@dir}/foo.bar"
47
- end
48
-
49
- #--------------------------------------METHODS-----------------------------------------
50
-
51
- # Describing LoadSaveable::new
52
- #
53
- # Creates a LoadSaveable with the given data hash
54
- #
55
- # Parameter: hash - the data to be contained in the project
56
- #
57
- # Return: the created LoadSaveable
58
- describe "::new" do
59
- context "with no arguments" do
60
- it "creates an empty LoadSaveable" do
61
- project = LoadSaveableClass.new
62
- expect(project).to be_an_instance_of LoadSaveableClass
63
- expect(project.hash).to eql Hash.new
64
- end
65
- end
66
-
67
- context "with a given data hash" do
68
- it "creates a new LoadSaveable with the given data hash" do
69
- project = LoadSaveableClass.new @default_hash
70
- expect(project).to be_an_instance_of LoadSaveableClass
71
- expect(project.hash).to eql @default_hash
72
- end
73
- end
74
- end
75
-
76
- # Describing LoadSaveable::load
77
- #
78
- # Loads an object from a file of the given filename, parsed
79
- # in the appropriate format based on the extension
80
- #
81
- # Parameter: filename - the name of the file
82
- #
83
- # Return: object loaded from the file
84
- describe "::load" do
85
- #------------------------------FILETYPES------------------------------
86
-
87
- context "with a .json filename given" do
88
- it "returns a new LoadSaveable from the json file with the given filename" do
89
- project = LoadSaveableClass.load(@pjson_name)
90
- expect(project).to be_an_instance_of LoadSaveableClass
91
- expect(project.hash).to eql read_json(@pjson_name)
92
- end
93
- end
94
-
95
- context "with a .yaml filename given" do
96
- it "returns a new LoadSaveable from the yaml file with the given filename" do
97
- project = LoadSaveableClass.load(@pyaml_name)
98
- expect(project).to be_an_instance_of LoadSaveableClass
99
- expect(project.hash).to eql read_yaml(@pyaml_name)
100
- end
101
- end
102
-
103
- context "with a .yml filename given" do
104
- it "returns a new LoadSaveable from the yml file with the given filename" do
105
- project = LoadSaveableClass.load(@pyml_name)
106
- expect(project).to be_an_instance_of LoadSaveableClass
107
- expect(project.hash).to eql read_yaml(@pyml_name)
108
- end
109
- end
110
-
111
- #-----------------------------UNSUPPORTED-----------------------------
112
-
113
- context "with an unsupported file extension given" do
114
- it "raises LoadError" do
115
- expect { LoadSaveableClass.load(@phony_name) }.to raise_error LoadError
116
- end
117
- end
118
- end
119
-
120
- # Describing LoadSaveable#save
121
- #
122
- # Saves the object at the given filename, formatted according
123
- # to the extension
124
- #
125
- # Parameter: filename - the name of the file to save to
126
- # (opened in w+ mode). Extension
127
- # determines format
128
- describe "#save" do
129
- #-------------------------------BEFORE--------------------------------
130
-
131
- before :each do
132
- @project = LoadSaveableClass.new @modded_hash
133
- end
134
-
135
- #------------------------------FILETYPES------------------------------
136
-
137
- context "with a .json filename given" do
138
- it "saves the project to the given filename in json format" do
139
- @project.save @pjson_name
140
- expect(read_json(@pjson_name)).to eql @modded_hash
141
- end
142
- end
143
-
144
- context "with a .yaml filename given" do
145
- it "saves the project to the given filename in yaml format" do
146
- @project.save @pyaml_name
147
- expect(read_yaml(@pyaml_name)).to eql @modded_hash
148
- end
149
- end
150
-
151
- context "with a .yml filename given" do
152
- it "saves the project to the given filename in yml format" do
153
- @project.save @pyml_name
154
- expect(read_yaml(@pyml_name)).to eql @modded_hash
155
- end
156
- end
157
-
158
- #-----------------------------UNSUPPORTED-----------------------------
159
-
160
- context "with an unsupported file extension given" do
161
- it "raises LoadError" do
162
- expect { @project.save @phony_name }.to raise_error LoadError
163
- end
164
- end
165
-
166
- #-------------------------------AFTER--------------------------------
167
-
168
- after :all do
169
- write_json @pjson_name, @default_hash
170
- write_yaml @pyaml_name, @default_hash
171
- write_yaml @pyml_name, @default_hash
172
- end
173
- end
174
-
175
- # Describing LoadSaveable::open
176
- #
177
- # Opens the object from a file, evaluates the given
178
- # block in the context of the object, and saves the object.
179
- # If no block is given, returns the object (alias for load)
180
- #
181
- # Parameter: filename - the name of the file to open
182
- # Parameter: block - the block to evaluate within the
183
- # context of the object
184
- #
185
- # Return: the object loaded from the file (if no block given)
186
- describe "::open" do
187
- context "with filename and block given" do
188
- #------------------------------FILETYPES------------------------------
189
-
190
- context "when file is .json" do
191
- # Declare project local variable
192
- project = nil
193
-
194
- it "loads a LoadSaveable from the json file with the given filename (calling #load)" do
195
- # Declare modded_hash local variable
196
- mhash = @modded_hash
197
-
198
- # Open project in a block
199
- expect { LoadSaveableClass.open @pjson_name do
200
- # Set project to instance
201
- project = self
202
-
203
- # Modify project
204
- initialize mhash
205
- end }.not_to raise_error
206
- end
207
-
208
- it "evaluates the given block in the context of the loaded LoadSaveable" do
209
- # Check if project was actually self, and it was successfuly modified
210
- expect(project).to be_an_instance_of LoadSaveableClass
211
- expect(project.hash).to eql @modded_hash
212
- end
213
-
214
- it "saves the LoadSaveable when the block ends" do
215
- # Check if the modded project was saved
216
- expect(read_json(@pjson_name)).to eql @modded_hash
217
- end
218
- end
219
-
220
- context "when file is .yaml" do
221
- # Declare project local variable
222
- project = nil
223
-
224
- it "loads a LoadSaveable from the yaml file with the given filename (calling #load)" do
225
- # Declare modded_hash local variable
226
- mhash = @modded_hash
227
-
228
- # Open project in a block
229
- expect { LoadSaveableClass.open @pyaml_name do
230
- # Set project to instance
231
- project = self
232
-
233
- # Modify project
234
- initialize mhash
235
- end }.not_to raise_error
236
- end
237
-
238
- it "evaluates the given block in the context of the loaded LoadSaveable" do
239
- # Check if project was actually self, and it was successfuly modified
240
- expect(project).to be_an_instance_of LoadSaveableClass
241
- expect(project.hash).to eql @modded_hash
242
- end
243
-
244
- it "saves the LoadSaveable when the block ends" do
245
- # Check if the modded project was saved
246
- expect(read_yaml(@pyaml_name)).to eql @modded_hash
247
- end
248
- end
249
-
250
- context "when file is .yml" do
251
- # Declare project local variable
252
- project = nil
253
-
254
- it "loads a LoadSaveable from the yml file with the given filename (calling #load)" do
255
- # Declare modded_hash local variable
256
- mhash = @modded_hash
257
-
258
- # Open project in a block
259
- expect { LoadSaveableClass.open @pyml_name do
260
- # Set project to instance
261
- project = self
262
-
263
- # Modify project
264
- initialize mhash
265
- end }.not_to raise_error
266
- end
267
-
268
- it "evaluates the given block in the context of the loaded LoadSaveable" do
269
- # Check if project was actually self, and it was successfuly modified
270
- expect(project).to be_an_instance_of LoadSaveableClass
271
- expect(project.hash).to eql @modded_hash
272
- end
273
-
274
- it "saves the LoadSaveable when the block ends" do
275
- # Check if the modded project was saved
276
- expect(read_yaml(@pyml_name)).to eql @modded_hash
277
- end
278
- end
279
-
280
- #-----------------------------UNSUPPORTED-----------------------------
281
-
282
- context "when filetype is unsupported" do
283
- it "raises LoadError" do
284
- expect { LoadSaveableClass.open(@phony_name) {} }.to raise_error LoadError
285
- end
286
- end
287
-
288
- after :all do
289
- write_json @pjson_name, @default_hash
290
- write_yaml @pyaml_name, @default_hash
291
- write_yaml @pyml_name, @default_hash
292
- end
293
- end
294
-
295
- context "with filename given and no block given" do
296
- #------------------------------FILETYPES------------------------------
297
-
298
- context "when file is .json" do
299
- it "loads a LoadSaveable from the json file with the given filename (calling #load) and returns it." do
300
- project = LoadSaveableClass.open @pjson_name
301
- expect(project).to be_an_instance_of LoadSaveableClass
302
- expect(project.hash).to eql @default_hash
303
- end
304
- end
305
-
306
- context "when file is .yaml" do
307
- it "loads a LoadSaveable from the yaml file with the given filename (calling #load) and returns it." do
308
- project = LoadSaveableClass.open @pyaml_name
309
- expect(project).to be_an_instance_of LoadSaveableClass
310
- expect(project.hash).to eql @default_hash
311
- end
312
- end
313
-
314
- context "when file is .yml" do
315
- it "loads a LoadSaveable from the yml file with the given filename (calling #load) and returns it." do
316
- project = LoadSaveableClass.open @pyml_name
317
- expect(project).to be_an_instance_of LoadSaveableClass
318
- expect(project.hash).to eql @default_hash
319
- end
320
- end
321
-
322
- #-----------------------------UNSUPPORTED-----------------------------
323
-
324
- context "when filetype is unsupported" do
325
- it "raises LoadError" do
326
- expect { LoadSaveableClass.open @phony_name }.to raise_error LoadError
327
- end
328
- end
329
- end
330
- end
331
-
332
- # Describing LoadSaveable::get
333
- #
334
- # Defines a getter method for the given name
335
- # which retrieves the value of name in the data
336
- # hash
337
- #
338
- # Parameter: name - the name to define
339
- describe '::get' do
340
- before :all do
341
- @hash = { name: "foo", author: "bar", value: "baz" }
342
- end
343
-
344
- it 'defines methods with the given names' do
345
- LoadSaveableClass.get *@hash.each_key
346
-
347
- @hash.each_key do |key|
348
- expect(LoadSaveableClass.method_defined?(key)).to be true
349
- end
350
- end
351
-
352
- it 'defines methods which return the values in the hash at their corresponding names' do
353
- @instance = LoadSaveableClass.new @hash
354
-
355
- @hash.each_pair do |key, value|
356
- expect(@instance.send(key)).to eql value
357
- end
358
- end
359
- end
360
-
361
- # Describing LoadSaveable::attributes
362
- #
363
- # Returns all attributes that are
364
- # part of the LoadSaveable implementation
365
- #
366
- # Return: all attributes that are
367
- # part of the LoadSaveable
368
- # implementation
369
- describe '::attributes' do
370
- context 'with attributes set' do
371
- it 'returns all attributes that are part of the loadsaveable implementation' do
372
- hash = @default_hash
373
- instance = LoadSaveableClass.new hash
374
-
375
- LoadSaveableClass.attributes.each do |attribute|
376
- expect(instance.send(attribute)).to eql hash[attribute]
377
- end
378
- end
379
- end
380
-
381
- context 'with no attributes set' do
382
- it 'returns an empty array' do
383
- class LoadSaveableClass2
384
- include Roject::LoadSaveable
385
- def initialize(hash={}); @bar = hash; end
386
- def hash; @bar; end
387
- end
388
- expect(LoadSaveableClass2.attributes).to be_empty
389
- end
390
- end
391
- end
392
- end
data/spec/parsers_spec.rb DELETED
@@ -1,128 +0,0 @@
1
- =begin
2
-
3
- Program: Roject
4
-
5
- Roject is a programming project manager written in Ruby.
6
- With Roject, you can create and edit projects based on templates
7
- using simple commands without a heavy IDE.
8
-
9
- Author: Anshul Kharbanda
10
- Created: 7 - 8 - 2016
11
-
12
- =end
13
-
14
- # Spec require
15
- require_relative "spec_require"
16
-
17
- # Describing Roject::Parsers
18
- #
19
- # Contains implementations of parsers for different filetypes
20
- #
21
- # Author: Anshul Kharbanda
22
- # Created: 7 - 11 - 2016
23
- describe Roject::Parsers do
24
- #------------------------------------------BEFORE-------------------------------------------
25
-
26
- before :all do
27
- @hash = { foo: "bar", baz: ["Ju", "Jay", "Jaz"] }
28
- end
29
-
30
- #------------------------------------------PARSERS------------------------------------------
31
-
32
- # Describing Roject::Parsers::JSONParser
33
- #
34
- # Parses JSON files
35
- #
36
- # Author: Anshul Kharbanda
37
- # Created: 7 - 11 - 2016
38
- describe '::JSONParser' do
39
-
40
- #----------------------------------BEFORE-----------------------------------
41
-
42
- before :all do
43
- @text = JSON.pretty_generate(@hash, indent: "\t")
44
- @parser = Roject::Parsers::JSONParser
45
- end
46
-
47
- #----------------------------------METHODS----------------------------------
48
-
49
- # Describing Roject::Parsers::JSONParser::parse
50
- #
51
- # Parses the given json text into a hash
52
- #
53
- # Parameter: text - the json text to parse
54
- #
55
- # Return: the hash parsed from the text
56
- describe '::parse' do
57
- it 'parses the given JSON text into a ruby hash' do
58
- expect(@parser.parse(@text)).to eql @hash
59
- end
60
- end
61
-
62
- # Describing Roject::Parsers::JSONParser::format
63
- #
64
- # Returns the object hash formatted to pretty json
65
- #
66
- # Parameter: hash - the hash to format
67
- #
68
- # Return: the given hash formatted to pretty json
69
- describe '::format' do
70
- it 'formats the given hash into pretty json' do
71
- expect(@parser.format(@hash)).to eql @text
72
- end
73
- end
74
- end
75
-
76
- # Describing Roject::Parsers::YAMLParser
77
- #
78
- # Parses JSON files
79
- #
80
- # Author: Anshul Kharbanda
81
- # Created: 7 - 11 - 2016
82
- describe '::YAMLParser' do
83
-
84
- #----------------------------------BEFORE-----------------------------------
85
-
86
- before :all do
87
- @text = YAML.dump(stringified(@hash))
88
- @parser = Roject::Parsers::YAMLParser
89
- end
90
-
91
- #----------------------------------METHODS----------------------------------
92
-
93
- # Describing Roject::Parsers::YAMLParser::parse
94
- #
95
- # Parses the given yaml text into a hash
96
- #
97
- # Parameter: text - the yaml text to parse
98
- #
99
- # Return: the hash parsed from the text
100
- describe '::parse' do
101
- it 'parses the given YAML text into a ruby hash' do
102
- expect(@parser.parse(@text)).to eql @hash
103
- end
104
- end
105
-
106
- # Describing Roject::Parsers::YAMLParser::format
107
- #
108
- # Returns the object hash formatted to yaml
109
- #
110
- # Parameter: hash - the hash to format
111
- #
112
- # Return: the given hash formatted to yaml
113
- describe '::format' do
114
- it 'formats the given hash into yaml' do
115
- expect(@parser.format(@hash)).to eql @text
116
- end
117
- end
118
- end
119
-
120
- #--------------------------------------------GET--------------------------------------------
121
-
122
- describe '::get' do
123
- it 'returns the appropriate parser according to the extension of the given filename' do
124
- expect(Roject::Parsers.get("foo.json")).to eql Roject::Parsers::JSONParser
125
- expect(Roject::Parsers.get("foo.yaml")).to eql Roject::Parsers::YAMLParser
126
- end
127
- end
128
- end