general 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +674 -0
- data/README.md +135 -0
- data/Rakefile +52 -0
- data/exp/future.general +11 -0
- data/exp/out.txt +1 -0
- data/exp/sample.general +1 -0
- data/lib/gdothash.rb +106 -0
- data/lib/general.rb +3 -3
- data/lib/goperations.rb +49 -28
- data/lib/gpartials/gpartial.rb +43 -0
- data/lib/gpartials/gplaceholder.rb +156 -0
- data/lib/gpartials/gtext.rb +93 -0
- data/lib/gpartials/gtimeformatplaceholder.rb +71 -0
- data/lib/templates/gbasetemplate.rb +55 -0
- data/lib/{gio.rb → templates/gio.rb} +1 -2
- data/lib/templates/gtemplate.rb +103 -0
- data/lib/templates/gtimeformat.rb +62 -0
- data/spec/garrayplaceholder_spec.rb +163 -0
- data/spec/gdothash_spec.rb +87 -0
- data/spec/goperations_spec.rb +246 -0
- data/spec/gpartial_spec.rb +54 -0
- data/spec/gplaceholder_spec.rb +300 -0
- data/spec/gtemplates_spec.rb +480 -0
- data/spec/gtext_spec.rb +150 -0
- data/spec/spec_require.rb +25 -3
- metadata +24 -8
- data/lib/gpartials.rb +0 -191
- data/lib/gtemplate.rb +0 -118
- data/lib/gtimeformat.rb +0 -53
- data/spec/gio_spec.rb +0 -64
- data/spec/gtemplate_spec.rb +0 -93
data/README.md
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# General
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
General is a simple templating system in ruby that allows you to create templates from both pure strings and files (with the extension .general), as well as create new strings and files with these created objects.
|
6
|
+
|
7
|
+
## General Templates
|
8
|
+
|
9
|
+
### Basic Templates
|
10
|
+
|
11
|
+
A general template consists of regular text along with placeholders, which are defined as follows: `@(-name-)`. You can also specify default text as well like so: `@(-name-: -default text-)`.
|
12
|
+
|
13
|
+
Here's an exmple of a general template text: `"Hello, I am @(name: Gordon Ramsay) and I like @(food: cat food)!"`
|
14
|
+
|
15
|
+
To import all classes in the library, type `require 'general'`. You can then create a general template from a string within your ruby code using the GTemplate object:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
template = General::GTemplate.new "Hello, I am @(name: Gordon Ramsay) and I like @(food: cat food)!"
|
19
|
+
```
|
20
|
+
|
21
|
+
To generate a string from the template, use the "apply" method and add your data as named arguments.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
string = template.apply name: "Joe", food: "Joe's Schmoes"
|
25
|
+
|
26
|
+
# string now equals "Hello, I am Joe and I like Joe's Schmoes"
|
27
|
+
```
|
28
|
+
|
29
|
+
If you don't specify a value for a particular placeholder, it will take on it's default value.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
string = template.apply food: "Joe's Schmoes"
|
33
|
+
|
34
|
+
# string now equals "Hello, I am Gordon Ramsay and I like Joe's Schmoes"
|
35
|
+
```
|
36
|
+
|
37
|
+
If you have an array of data, you can use `apply_all` to apply the template to each individual element separately.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
array = template.apply_all [{name: "Joe", food: "Joe Schmoes"}, {name: "Jane", food: "Jane's Danes"}, {name: "Denny", food: "Denny's Fennies"}]
|
41
|
+
|
42
|
+
#array now has these elements:
|
43
|
+
# - Hello, I am Joe and I like Joe's Schmoes
|
44
|
+
# - Hello, I am Jane and I like Jane's Danes
|
45
|
+
# - Hello, I am Denny and I like Denny's Fennies
|
46
|
+
```
|
47
|
+
|
48
|
+
### Placeholder Operations
|
49
|
+
|
50
|
+
You can also specify operations to be performed on values passed to placeholders, akin to AngularJS's filters. For example: `@(name -> capitalize)` will capitalize whatever name is inputted before applying it to the text.
|
51
|
+
|
52
|
+
The current placeholder operations are:
|
53
|
+
|
54
|
+
| Operation | Description |
|
55
|
+
|:-----------|:--------------------------------------------------------|
|
56
|
+
| capitalize | Capitalizes the first letter of each word in a string |
|
57
|
+
| uppercase | Makes every letter in a string uppercase |
|
58
|
+
| lowercase | Makes every letter in a string lowercase |
|
59
|
+
| dollars | Formats an integer money amount (in cents) to dollars |
|
60
|
+
| time | Formats an integer time (in seconds) to HH:MM:SS format |
|
61
|
+
|
62
|
+
### Array Templates
|
63
|
+
|
64
|
+
You can also make array templates within templates, which will format each value in an array of data according to a general template
|
65
|
+
|
66
|
+
A general array template is as follows: `@[-name-] -general template for each value- @[]`. You can also specify the delimeter, which will be appended to the end of each element. The delimeter should be added in the end tag, like so: `@[-name-] -general template for each value- @[-delimeter-]`. If no delimeter is given, the default is a space. The start and end tags are invariant with atleast 1 whitespace or newline. So you can also define the template like such:
|
67
|
+
|
68
|
+
```
|
69
|
+
@[-name-]
|
70
|
+
-general template for each value-
|
71
|
+
@[-delimeter-]
|
72
|
+
```
|
73
|
+
|
74
|
+
An example of an array template:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
template = General::GTemplate.new \
|
78
|
+
"List of Film Crew:
|
79
|
+
@[crew]
|
80
|
+
@(name): @(role)
|
81
|
+
@[\n]"
|
82
|
+
```
|
83
|
+
|
84
|
+
You can now specify an array of values for "crew" in template, and it will format the data accordingly:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
string = template.apply crew: [
|
88
|
+
{name: "Chris Nolan", role: "Director"},
|
89
|
+
{name: "Wally Pfister", role: "Director of Photography"},
|
90
|
+
{name: "Christian Bale", role: "Bruce Wayne/Batman"},
|
91
|
+
{name: "Michael Caine", role: "Alfred Pennyworth"}
|
92
|
+
]
|
93
|
+
|
94
|
+
# string now equals:
|
95
|
+
# "List of Film Crew:
|
96
|
+
# Chris Nolan: Director
|
97
|
+
# Wally Pfister: Director of Photography
|
98
|
+
# Christian Bale: Bruce Wayne/Batman
|
99
|
+
# Michael Caine: Alfred Pennyworth"
|
100
|
+
```
|
101
|
+
|
102
|
+
## General IO
|
103
|
+
|
104
|
+
You can also write to files using io GIO, a general template capable of writing to files. You can create a GIO like a GTemplate:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
gio = General::GIO.new "Hello, I am @(name: Gordon Ramsay) and I like @(food: cat food)!"
|
108
|
+
```
|
109
|
+
|
110
|
+
You can also load a GIO from a file. For example, here's how you create a template file from the file "example.txt.general"
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
gio = General::GFile.load "example.txt.general"
|
114
|
+
```
|
115
|
+
|
116
|
+
To write to a file, simply call the write method, pass in the file and the data to apply (like in GTemplate#apply):
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
gio.write file, name: "Joe", food: "Joe's Schmoes"
|
120
|
+
```
|
121
|
+
|
122
|
+
Where `file` is the file you are writing to. You can also pass the name of the file to write to as well:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
gio.write "example.txt", name: "Joe", food: "Joe's Schmoes"
|
126
|
+
```
|
127
|
+
|
128
|
+
To get the original source filename of the GIO, just call `source`
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
gio.source # == "example.txt.general"
|
132
|
+
```
|
133
|
+
|
134
|
+
-------------------------------------------------------------------------------------------------------------------------------------
|
135
|
+
Anshul Kharbanda
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
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
|
+
# Required libraries
|
15
|
+
require "rspec/core/rake_task"
|
16
|
+
require "rubygems/tasks"
|
17
|
+
require "fileutils"
|
18
|
+
|
19
|
+
# Directories
|
20
|
+
SPECDIR = "spec"
|
21
|
+
|
22
|
+
# Default Task
|
23
|
+
task :default => :spec
|
24
|
+
|
25
|
+
# RSpec Tasks
|
26
|
+
RSpec::Core::RakeTask.new do |task|
|
27
|
+
task.pattern = "#{SPECDIR}/*_spec.rb"
|
28
|
+
task.rspec_opts = "--format documentation --color"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Gem Tasks
|
32
|
+
Gem::Tasks.new
|
33
|
+
|
34
|
+
# Git Tasks
|
35
|
+
namespace :git do
|
36
|
+
desc "Push changes to remote"
|
37
|
+
task :push, [:message] => :commit do
|
38
|
+
sh "git push origin master"
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Commit changes"
|
42
|
+
task :commit, [:message] do |task, args|
|
43
|
+
sh "git add --all"
|
44
|
+
sh "git commit -m #{args[:message].inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Soft git reset"
|
48
|
+
task :reset do sh "git reset" end
|
49
|
+
|
50
|
+
desc "Hard git reset"
|
51
|
+
task :reset_hard do sh "git reset --hard HEAD" end
|
52
|
+
end
|
data/exp/future.general
ADDED
data/exp/out.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
There once was a chef name Joe, and he loved eating Joe's Schmoes. He went to Kentucky.
|
data/exp/sample.general
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
There once was a chef name @(name: gordon ramsay -> capitalize all), and he loved eating @(food: carrots). He went to @(place -> capitalize).
|
data/lib/gdothash.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# General is a templating system in ruby
|
2
|
+
# Copyright (C) 2016 Anshul Kharbanda
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# General is a templating system in ruby
|
18
|
+
#
|
19
|
+
# Author: Anshul Kharbanda
|
20
|
+
# Created: 3 - 4 - 2016
|
21
|
+
module General
|
22
|
+
# Wrapper for hash objects which implements dot notation
|
23
|
+
#
|
24
|
+
# Author: Anshul Kharbanda
|
25
|
+
# Created: 9 - 27 - 2016
|
26
|
+
class GDotHash
|
27
|
+
# Initializes the given GDotHash with the given hash
|
28
|
+
#
|
29
|
+
# Parameter: hash - the hash being manipulated
|
30
|
+
def initialize(hash={}); @hash = hash; end
|
31
|
+
|
32
|
+
# Returns the string representation of the hash
|
33
|
+
#
|
34
|
+
# Return: the string representation of the hash
|
35
|
+
def to_s; @hash.to_s; end
|
36
|
+
|
37
|
+
# Returns true if the GDotHash contains the given key
|
38
|
+
#
|
39
|
+
# Parameter: key - the key to check
|
40
|
+
#
|
41
|
+
# Return: true if the GDotHash contains the given key
|
42
|
+
def has_key? key
|
43
|
+
# Split keys
|
44
|
+
subkeys = key.to_s.split(".").collect(&:to_sym)
|
45
|
+
|
46
|
+
# Check each subkey
|
47
|
+
sub = @hash
|
48
|
+
subkeys.each do |subkey|
|
49
|
+
# Return false if subhash doesn't contain key
|
50
|
+
# Else continue
|
51
|
+
if sub.is_a?(Hash) && sub.has_key?(subkey)
|
52
|
+
sub = sub[subkey]
|
53
|
+
else
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return true if passed
|
59
|
+
return true
|
60
|
+
end
|
61
|
+
|
62
|
+
# Gets the value at the given key
|
63
|
+
#
|
64
|
+
# Parameter: key - the key to return
|
65
|
+
#
|
66
|
+
# Return: the value at the given key
|
67
|
+
def [] key
|
68
|
+
# Split keys
|
69
|
+
subkeys = key.to_s.split(".").collect(&:to_sym)
|
70
|
+
|
71
|
+
# Travel down to value
|
72
|
+
get = @hash
|
73
|
+
subkeys.each do |subkey|
|
74
|
+
if get.is_a?(Hash) && get.has_key?(subkey)
|
75
|
+
get = get[subkey]
|
76
|
+
else
|
77
|
+
raise ArgumentError, "key is not defined in hash: #{key}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return value
|
82
|
+
return get
|
83
|
+
end
|
84
|
+
|
85
|
+
# Sets the given key to the given value
|
86
|
+
#
|
87
|
+
# Parameter: key - the key to set
|
88
|
+
# Parameter: value - the value to set
|
89
|
+
def []= key, value
|
90
|
+
# Split subkeys
|
91
|
+
subkeys = key.to_s.split(".").collect(&:to_sym)
|
92
|
+
|
93
|
+
# Generate structure of new data
|
94
|
+
new_data = Hash.new
|
95
|
+
sub = new_data
|
96
|
+
subkeys[0...-1].each do |subkey|
|
97
|
+
sub[subkey] = Hash.new
|
98
|
+
sub = sub[subkey]
|
99
|
+
end
|
100
|
+
sub[subkeys[-1]] = value
|
101
|
+
|
102
|
+
# Merge hash with new data
|
103
|
+
@hash.merge! new_data
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/general.rb
CHANGED
@@ -14,6 +14,6 @@
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
|
-
require_relative "gtemplate"
|
18
|
-
require_relative "gtimeformat"
|
19
|
-
require_relative "gio"
|
17
|
+
require_relative "template/gtemplate"
|
18
|
+
require_relative "template/gtimeformat"
|
19
|
+
require_relative "template/gio"
|
data/lib/goperations.rb
CHANGED
@@ -14,6 +14,8 @@
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
|
+
require_relative "templates/gtimeformat"
|
18
|
+
|
17
19
|
# General is a templating system in ruby
|
18
20
|
#
|
19
21
|
# Author: Anshul Kharbanda
|
@@ -24,6 +26,15 @@ module General
|
|
24
26
|
# Author: Anshul Kharbanda
|
25
27
|
# Created: 6 - 3 - 2016
|
26
28
|
module GOperations
|
29
|
+
# The money types used by the money operation
|
30
|
+
MONEY_TYPES = {
|
31
|
+
"USD" => "$",
|
32
|
+
"EUR" => "€"
|
33
|
+
}
|
34
|
+
|
35
|
+
# The default time format
|
36
|
+
DEFAULT_TIME = "@I:@MM:@SS @A"
|
37
|
+
|
27
38
|
#-----------------------------------STRING OPERATIONS------------------------------------
|
28
39
|
|
29
40
|
# Capitalizes every word in the string
|
@@ -31,8 +42,13 @@ module General
|
|
31
42
|
# Parameter: string - the string being capitalized
|
32
43
|
#
|
33
44
|
# Return: the capitalized string
|
34
|
-
def self.capitalize string
|
35
|
-
|
45
|
+
def self.capitalize string, what="first"
|
46
|
+
assert_type string, String
|
47
|
+
case what
|
48
|
+
when "all" then string.split(' ').collect(&:capitalize).join(' ')
|
49
|
+
when "first" then string.capitalize
|
50
|
+
else raise TypeError.new "Undefined second argument for operation capitalize: #{what}"
|
51
|
+
end
|
36
52
|
end
|
37
53
|
|
38
54
|
# Converts every letter in the string to uppercase
|
@@ -40,8 +56,9 @@ module General
|
|
40
56
|
# Parameter: string - the string being uppercased
|
41
57
|
#
|
42
58
|
# Return: the uppercased string
|
43
|
-
def self.uppercase
|
44
|
-
|
59
|
+
def self.uppercase(string)
|
60
|
+
assert_type string, String
|
61
|
+
string.upcase
|
45
62
|
end
|
46
63
|
|
47
64
|
# Converts every letter in the string to lowercase
|
@@ -49,47 +66,51 @@ module General
|
|
49
66
|
# Parameter: string - the string being lowercased
|
50
67
|
#
|
51
68
|
# Return: the lowercased string
|
52
|
-
def self.lowercase
|
53
|
-
|
69
|
+
def self.lowercase(string)
|
70
|
+
assert_type string, String
|
71
|
+
string.downcase
|
54
72
|
end
|
55
73
|
|
56
74
|
#-----------------------------------INTEGER OPERATIONS------------------------------------
|
57
75
|
|
58
|
-
# Returns the integer monetary value
|
76
|
+
# Returns the integer monetary value formatted to the given money type
|
59
77
|
#
|
60
|
-
# Parameter: integer - the
|
78
|
+
# Parameter: integer - the monetary amount being formatted
|
79
|
+
# Parameter: type - the type of money (defaults to USD)
|
61
80
|
#
|
62
|
-
# Return: the formatted
|
63
|
-
def self.
|
64
|
-
|
65
|
-
|
81
|
+
# Return: the formatted money amount
|
82
|
+
def self.money integer, type="USD"
|
83
|
+
assert_type integer, Integer
|
84
|
+
if MONEY_TYPES[type]
|
85
|
+
(integer < 0 ? "-" : "") + MONEY_TYPES[type] + (integer * 0.01).abs.to_s
|
66
86
|
else
|
67
|
-
|
87
|
+
raise TypeError.new("Money type: #{type} is not supported!")
|
68
88
|
end
|
69
89
|
end
|
70
90
|
|
71
|
-
# Returns the integer time value (in seconds) formatted
|
91
|
+
# Returns the integer time value (in seconds) formatted with the given formatter
|
72
92
|
#
|
73
93
|
# Parameter: integer - the integer being formatted (representing the time in seconds)
|
94
|
+
# Parameter: format - the format being used (defaults to DEFAULT_TIME)
|
74
95
|
#
|
75
|
-
# Return: the formatted
|
76
|
-
def self.time integer
|
77
|
-
|
96
|
+
# Return: the time formatted with the given formatter
|
97
|
+
def self.time integer, format=DEFAULT_TIME
|
98
|
+
assert_type integer, Integer
|
99
|
+
General::GTimeFormat.new(format).apply(integer)
|
78
100
|
end
|
79
101
|
|
80
102
|
private
|
81
103
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
.
|
91
|
-
|
92
|
-
.sub(/A/, value / 3600 > 12 ? 'PM' : 'AM')
|
104
|
+
# Raises TypeError if the given value is not one of the given types
|
105
|
+
#
|
106
|
+
# Parameter: value - the value to check
|
107
|
+
# Parameter: types - the types to check for
|
108
|
+
#
|
109
|
+
# Raises: TypeError - if the given value is not one of the given types
|
110
|
+
def self.assert_type value, *types
|
111
|
+
unless types.any? {|type| value.is_a? type}
|
112
|
+
raise TypeError.new "Unexpected value type #{value.class.name}. Expected #{types.collect(&:name).join(",")}"
|
113
|
+
end
|
93
114
|
end
|
94
115
|
end
|
95
116
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# General is a templating system in ruby
|
2
|
+
# Copyright (C) 2016 Anshul Kharbanda
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# General is a templating system in ruby
|
18
|
+
#
|
19
|
+
# Author: Anshul Kharbanda
|
20
|
+
# Created: 3 - 4 - 2016
|
21
|
+
module General
|
22
|
+
# A unit of the GTemplate. Returns a string based on an argument hash
|
23
|
+
# When GTemplate is applied
|
24
|
+
#
|
25
|
+
# Author: Anshul Kharbanda
|
26
|
+
# Created: 7 - 29 - 2016
|
27
|
+
class GPartial
|
28
|
+
protected
|
29
|
+
|
30
|
+
# Regular expression that matches placeholder names
|
31
|
+
NAME = /(?<name>[a-zA-Z]\w*(\.[a-zA-Z]\w*)*)/
|
32
|
+
|
33
|
+
public
|
34
|
+
|
35
|
+
# Get name
|
36
|
+
attr :name
|
37
|
+
|
38
|
+
# Initializes the GPartial with the given object
|
39
|
+
#
|
40
|
+
# Parameter: obj - the object containing information for the partial
|
41
|
+
def initialize(obj); @name = obj[:name].to_sym; end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# General is a templating system in ruby
|
2
|
+
# Copyright (C) 2016 Anshul Kharbanda
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require_relative "gpartial"
|
18
|
+
require_relative "../goperations"
|
19
|
+
|
20
|
+
# General is a templating system in ruby
|
21
|
+
#
|
22
|
+
# Author: Anshul Kharbanda
|
23
|
+
# Created: 3 - 4 - 2016
|
24
|
+
module General
|
25
|
+
# Represents a placeholder partial in a GTemplate
|
26
|
+
#
|
27
|
+
# Author: Anshul Kharbanda
|
28
|
+
# Created: 7 - 1 - 2016
|
29
|
+
class GPlaceholder < GPartial
|
30
|
+
private
|
31
|
+
|
32
|
+
# Regular expression that matches a single placeholder
|
33
|
+
ARGUMENT = /(?<text>\w+)|((?<qtat>'|")(?<text>.*)\k<qtat>)/
|
34
|
+
|
35
|
+
# Regular expression that matches placeholder arguments
|
36
|
+
ARGUMENTS = /(?<arguments>(#{ARGUMENT}\s*)*)/
|
37
|
+
|
38
|
+
# Regular expression that matches placeholder operations
|
39
|
+
OPERATION = /(->\s*(?<operation>\w+))/
|
40
|
+
|
41
|
+
# Regular expression that matches placeholder defaults
|
42
|
+
DEFAULT = /(\:\s*(?<default>[^(\-\>)]+))/
|
43
|
+
|
44
|
+
public
|
45
|
+
|
46
|
+
# Regular expression that matches placeholders
|
47
|
+
REGEX = /@\(\s*#{NAME}\s*#{DEFAULT}?\s*(#{OPERATION}\s*#{ARGUMENTS}?)?\s*\)/
|
48
|
+
|
49
|
+
# Initializes the GPlaceholder with the given match
|
50
|
+
#
|
51
|
+
# Parameter: match - the match data from the string being parsed
|
52
|
+
# Parameter: defaults - the hash of default data from the GTemplate
|
53
|
+
def initialize match, defaults
|
54
|
+
super match
|
55
|
+
@operation = match[:operation]
|
56
|
+
if match[:arguments]
|
57
|
+
@arguments = match[:arguments].gsub(ARGUMENT).collect { |arg|
|
58
|
+
ARGUMENT.match(arg)[:text]
|
59
|
+
}
|
60
|
+
else
|
61
|
+
@arguments = []
|
62
|
+
end
|
63
|
+
@defaults = defaults
|
64
|
+
@defaults[@name] = match[:default] unless @defaults.has_key? @name
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the value of the placeholder in the given data
|
68
|
+
# with the given operation performed on it
|
69
|
+
#
|
70
|
+
# Parameter: data - the data being applied
|
71
|
+
#
|
72
|
+
# Return: the value of the placeholder in the given data
|
73
|
+
# with the given operation performed on it
|
74
|
+
def apply data
|
75
|
+
# Get value from either data or defaults
|
76
|
+
if data.has_key? @name
|
77
|
+
value = data[@name]
|
78
|
+
else
|
79
|
+
value = @defaults[@name]
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return value (operation performed if one is defined)
|
83
|
+
return (@operation ? General::GOperations.send(@operation, value, *@arguments) : value).to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the string as a regex
|
87
|
+
#
|
88
|
+
# Parameter: first - true if the placeholder is the first of its kind in the GTemplate
|
89
|
+
#
|
90
|
+
# Returns: the string as a regex
|
91
|
+
def regex(first=true); first ? "(?<#{@name.to_s}>.*)" : "\\k<#{@name.to_s}>"; end
|
92
|
+
|
93
|
+
# Returns the string representation of the placeholder
|
94
|
+
#
|
95
|
+
# Parameter: first - true if the placeholder is the first of its kind in the GTemplate
|
96
|
+
#
|
97
|
+
# Return: the string representation of the placeholder
|
98
|
+
def string first=true
|
99
|
+
str = "@(#{@name}"
|
100
|
+
if first
|
101
|
+
if @defaults[@name]
|
102
|
+
str += ": #{@defaults[@name]}"
|
103
|
+
end
|
104
|
+
if @operation
|
105
|
+
str += " -> #{@operation}"
|
106
|
+
unless @arguments.empty?
|
107
|
+
str += @arguments.collect {|s| " \"#{s}\""}.join
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
return str + ")"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Represents an array placeholder partial in a GTemplate
|
116
|
+
#
|
117
|
+
# Author: Anshul Kharbanda
|
118
|
+
# Created: 7 - 1 - 2016
|
119
|
+
class GArrayPlaceholder < GPartial
|
120
|
+
# Regular expression that matches array placeholders
|
121
|
+
REGEX = /\A@\[#{NAME}\]( +|\n+)?(?<text>.*?)( +|\n+)?@\[(?<delimeter>.+)?\]/m
|
122
|
+
|
123
|
+
# Default delimeter
|
124
|
+
DEFAULT_DELIMETER = " "
|
125
|
+
|
126
|
+
# Initializes the GPlaceholder with the given match
|
127
|
+
#
|
128
|
+
# Parameter: match - the match data from the string being parsed
|
129
|
+
def initialize match
|
130
|
+
super
|
131
|
+
@delimeter = match[:delimeter] || DEFAULT_DELIMETER
|
132
|
+
@template = General::GTemplate.new match[:text]
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the value of the array placeholder in the given data
|
136
|
+
# formatted by the given GTemplate and joined by the given delimeter
|
137
|
+
#
|
138
|
+
# Parameter: data - the data being applied
|
139
|
+
#
|
140
|
+
# Return: the value of the array placeholder in the given data
|
141
|
+
# formatted by the given GTemplate and joined by the given delimeter
|
142
|
+
def apply(data); @template.apply_all(data[@name]).join(@delimeter); end
|
143
|
+
|
144
|
+
# Throws TypeError
|
145
|
+
#
|
146
|
+
# Parameter: first - true if the placeholder is the first of it's kind
|
147
|
+
def regex(first=true); raise TypeError.new("Array Templates cannot be matched."); end
|
148
|
+
|
149
|
+
# Returns the string representation of the array placeholder
|
150
|
+
#
|
151
|
+
# Parameter: first - true if the placeholder is the first of it's kind
|
152
|
+
#
|
153
|
+
# Return: the string representation of the array placeholder
|
154
|
+
def string(first=true); "@[#{@name}] #{@template.to_s} @[#{@delimeter.inspect[1...-1]}]"; end
|
155
|
+
end
|
156
|
+
end
|