terse_ruby 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 +7 -0
- data/LICENCE.txt +21 -0
- data/README.txt +55 -0
- data/bin/terse_ruby.rb +59 -0
- data/lib/terse_ruby/format.rb +55 -0
- data/lib/terse_ruby/keyword.rb +108 -0
- data/lib/terse_ruby/scan.rb +147 -0
- data/lib/terse_ruby.rb +10 -0
- data/terse_ruby.gemspec +14 -0
- data/test/expected_test_file.rb +42 -0
- data/test/test_expansion.rb +63 -0
- data/test/test_file.txt +30 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 86cb4b9b2d13dd5a177f684edd7f151b4e7e24ac
|
4
|
+
data.tar.gz: d255dd24063cb2fa9e7010c6e3024dcb0adb888e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0f33d258de944a568cf348257f5c5ba1eba7c5aaaf28c19ec5ef9d550db2ccb5e214972ab805edbecf7a4c51d1d5eb1cc19f1c76cee3f4d1c92095c8903c890a
|
7
|
+
data.tar.gz: b2118518ae4f4d8e151c23a09648319111ca2003eeeceb00bd32f35cea44be2baec012229a6314d920d8dcdff8c6bcf05ae1467964044004d0cba6af6a3a8a35
|
data/LICENCE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Richard Morrisby
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.txt
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Terse Ruby
|
2
|
+
# A simple utility to allow you to write shorthand for Ruby classes; the utility will then convert this shorthand file into a genuine Ruby .rb file (either writing a new file or overwriting)
|
3
|
+
#
|
4
|
+
# E.g. terse_file.txt contains :
|
5
|
+
#
|
6
|
+
# req a_gem
|
7
|
+
# c AClass
|
8
|
+
# i AnInclude
|
9
|
+
# d method1
|
10
|
+
#
|
11
|
+
# Then Terse Ruby will write a new file terse_file.rb containing :
|
12
|
+
#
|
13
|
+
# require "a_gem"
|
14
|
+
# class AClass
|
15
|
+
# include AnInclude
|
16
|
+
# def method1
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# Rules :
|
22
|
+
# Terse Ruby will look through the supplied files and convert certain keywords at the start of lines :
|
23
|
+
# c -> class
|
24
|
+
# m -> module
|
25
|
+
# r -> require (and will wrap the required item in " " if needed)
|
26
|
+
# i -> include
|
27
|
+
# d -> def
|
28
|
+
# e -> end (method, class & module ends will be added if a subsequent method, class or module is detected, or is end-of-file)
|
29
|
+
# a -> attr_accessor (and prefixes the variable name with : to make it a symbol)
|
30
|
+
# r -> attr_reader (and prefixes the variable name with : to make it a symbol)
|
31
|
+
# w -> attr_writer (and prefixes the variable name with : to make it a symbol)
|
32
|
+
#
|
33
|
+
# All remaining text in the line is not altered, even if a matching keyword is present, because the keywords need to be at the beginning of the line (ignoring leading whitespace)
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# Flags :
|
37
|
+
# v : verbose mode
|
38
|
+
# o : overwrite - if the new file already exists, the existing file will be overwritten
|
39
|
+
#
|
40
|
+
#
|
41
|
+
# Invokation :
|
42
|
+
# terse_ruby can be directly invoked from the command-line with :
|
43
|
+
#
|
44
|
+
# ruby -e "require 'terse_ruby'; TerseRuby.scan_files ARGV" [one or more files] [flags]
|
45
|
+
#
|
46
|
+
# e.g.
|
47
|
+
#
|
48
|
+
# ruby -e "require 'terse_ruby'; TerseRuby.scan_files ARGV" terse_file1.txt terse_file2.txt -o -v
|
49
|
+
#
|
50
|
+
# Alternatively, the below two lines are all you need to run terse_ruby within your own Ruby file :
|
51
|
+
#
|
52
|
+
# require_relative "../lib/terse_ruby"
|
53
|
+
# TerseRuby.scan_files ARGV
|
54
|
+
#
|
55
|
+
# (if ARGV have not been supplied, you'll need to construct this object yourself first)
|
data/bin/terse_ruby.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Terse Ruby
|
2
|
+
# A simple utility to allow you to write shorthand for Ruby classes; the utility will then convert this shorthand file into a genuine Ruby .rb file (either writing a new file or overwriting)
|
3
|
+
#
|
4
|
+
# E.g. terse_file.txt contains :
|
5
|
+
#
|
6
|
+
# req a_gem
|
7
|
+
# c AClass
|
8
|
+
# i AnInclude
|
9
|
+
# d method1
|
10
|
+
#
|
11
|
+
# Then Terse Ruby will write a new file terse_file.rb containing :
|
12
|
+
#
|
13
|
+
# require "a_gem"
|
14
|
+
# class AClass
|
15
|
+
# include AnInclude
|
16
|
+
# def method1
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# Rules :
|
22
|
+
# Terse Ruby will look through the supplied files and convert certain keywords at the start of lines :
|
23
|
+
# c -> class
|
24
|
+
# m -> module
|
25
|
+
# r -> require (and will wrap the required item in " " if needed)
|
26
|
+
# i -> include
|
27
|
+
# d -> def
|
28
|
+
# e -> end (method, class & module ends will be added if a subsequent method, class or module is detected, or is end-of-file)
|
29
|
+
# a -> attr_accessor (and prefixes the variable name with : to make it a symbol)
|
30
|
+
# r -> attr_reader (and prefixes the variable name with : to make it a symbol)
|
31
|
+
# w -> attr_writer (and prefixes the variable name with : to make it a symbol)
|
32
|
+
#
|
33
|
+
# All remaining text in the line is not altered, even if a matching keyword is present, because the keywords need to be at the beginning of the line (ignoring leading whitespace)
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# Flags :
|
37
|
+
# v : verbose mode
|
38
|
+
# o : overwrite - if the new file already exists, the existing file will be overwritten
|
39
|
+
#
|
40
|
+
#
|
41
|
+
# Invokation :
|
42
|
+
# terse_ruby can be directly invoked from the command-line with :
|
43
|
+
#
|
44
|
+
# ruby -e "require 'terse_ruby'; TerseRuby.scan_files ARGV" [one or more files] [flags]
|
45
|
+
#
|
46
|
+
# e.g.
|
47
|
+
#
|
48
|
+
# ruby -e "require 'terse_ruby'; TerseRuby.scan_files ARGV" terse_file1.txt terse_file2.txt -o -v
|
49
|
+
#
|
50
|
+
# Alternatively, the below two lines are all you need to run terse_ruby within your own Ruby file :
|
51
|
+
#
|
52
|
+
# require_relative "../lib/terse_ruby"
|
53
|
+
# TerseRuby.scan_files ARGV
|
54
|
+
#
|
55
|
+
# (if ARGV have not been supplied, you'll need to construct this object yourself first)
|
56
|
+
|
57
|
+
|
58
|
+
require_relative "../lib/terse_ruby"
|
59
|
+
TerseRuby.scan_files ARGV
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module TerseRuby
|
2
|
+
|
3
|
+
# Simple class for formatting the list of lines
|
4
|
+
class Format
|
5
|
+
|
6
|
+
# Apply indentation
|
7
|
+
# It is easier to do this once the full list of newlines is assembled
|
8
|
+
def self.indent lines
|
9
|
+
indented_lines = []
|
10
|
+
indent_level = 0
|
11
|
+
keys = %w{ class module def if when case for }
|
12
|
+
first_word_regex = /^([a-zA-Z0-9_]+)(\s+|$)/
|
13
|
+
lines.each do |l|
|
14
|
+
l.strip!
|
15
|
+
l =~ first_word_regex # set the $ variables for inspection
|
16
|
+
# check for "end" before indenting
|
17
|
+
indent_level -= 1 if $1 == "end"
|
18
|
+
|
19
|
+
indent_level.times do
|
20
|
+
l.insert(0, "\t")
|
21
|
+
end
|
22
|
+
indented_lines << l
|
23
|
+
# puts indented_lines
|
24
|
+
|
25
|
+
# check for indent-increasing keywords after indenting
|
26
|
+
indent_level += 1 if keys.include?($1)
|
27
|
+
end
|
28
|
+
indented_lines
|
29
|
+
end
|
30
|
+
|
31
|
+
# Insert empty lines in between the end of a method and the start of the next (same for classes & modules)
|
32
|
+
def self.space_lines lines
|
33
|
+
spaced_lines = []
|
34
|
+
|
35
|
+
keys = %w{ class module def }
|
36
|
+
first_word_regex = /^\s*([a-zA-Z0-9_]+)(\s+|$)/
|
37
|
+
for i in 0 ... lines.size - 1
|
38
|
+
first_line = lines[i]
|
39
|
+
next_line = lines[i + 1]
|
40
|
+
|
41
|
+
spaced_lines << first_line
|
42
|
+
|
43
|
+
first_line =~ first_word_regex # set the $ variables for inspection
|
44
|
+
# We only care about line-pairs where the first line is an end, and the next one matches one of our keys
|
45
|
+
if $1 == "end"
|
46
|
+
next_line =~ first_word_regex
|
47
|
+
spaced_lines << "" if keys.include?($1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# Remember to add the last line!
|
51
|
+
spaced_lines << lines[-1]
|
52
|
+
spaced_lines
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module TerseRuby
|
2
|
+
|
3
|
+
# A class storing all information about a keyword & what it should be transformed into
|
4
|
+
class Keyword
|
5
|
+
attr_accessor :keyword
|
6
|
+
attr_accessor :substitute
|
7
|
+
attr_accessor :regex
|
8
|
+
attr_accessor :follow_on_regex
|
9
|
+
attr_accessor :follow_on_substitute
|
10
|
+
attr_accessor :try_follow_on_regex
|
11
|
+
attr_accessor :needs_top_level_end
|
12
|
+
attr_accessor :needs_inner_end
|
13
|
+
attr_accessor :is_end
|
14
|
+
|
15
|
+
def initialize(keyword)
|
16
|
+
@keyword = keyword
|
17
|
+
@regex = gen_regex_from_keyword keyword
|
18
|
+
@follow_on_regex = gen_regex_from_keyword_including_follow_on keyword
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO this doesn't work, needs to process the thing following the keyword, not the keyword itself
|
22
|
+
def set_substitute
|
23
|
+
case @keyword
|
24
|
+
when "a", "r", "w"
|
25
|
+
@substitute = ":" + @substitute
|
26
|
+
when "req", "reqr"
|
27
|
+
@substitute = "\"" + @substitute + "\"" unless ["\"", "'"].include? @substitute[0]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
# @substitutes = %W{ require require_relative include class method def end attr_accesor attr_reader attr_writer }
|
34
|
+
|
35
|
+
|
36
|
+
# def generate_regexes
|
37
|
+
# r = []
|
38
|
+
# for i in 0 ... @keywords.size
|
39
|
+
# r << Keyword.new(@keywords[i], @substitutes[i], gen_regex_from_keyword(@keywords[i]))
|
40
|
+
# end
|
41
|
+
# r
|
42
|
+
# end
|
43
|
+
|
44
|
+
# Simple regex to match a keyword at the start of a line
|
45
|
+
def gen_regex_from_keyword keyword
|
46
|
+
return /(^\s*)(#{keyword})(\s+|$)/
|
47
|
+
end
|
48
|
+
|
49
|
+
# Regex to match a keyword at the start of a line, and the next word on that line
|
50
|
+
# E.g. this will also catch (in $3) the item following the "require" keyword
|
51
|
+
# This enables the routine to format this follow-on word, e.g. to turn 'req a_gem' into
|
52
|
+
# 'require "a_gem"'
|
53
|
+
def gen_regex_from_keyword_including_follow_on keyword
|
54
|
+
return /(^\s*)(#{keyword})\s+([a-zA-Z0-9_]+)/
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.generate_keywords
|
58
|
+
keywords = []
|
59
|
+
keys = [:req, :reqr, :i, :c, :m, :d, :e, :a, :r, :w]
|
60
|
+
keys.each do |key|
|
61
|
+
k = Keyword.new key
|
62
|
+
# k.keyword = key
|
63
|
+
case key
|
64
|
+
when :req
|
65
|
+
k.substitute = "require"
|
66
|
+
k.try_follow_on_regex = true
|
67
|
+
k.follow_on_substitute = "\"\#{$3}\""
|
68
|
+
when :reqr
|
69
|
+
k.substitute = "require_relative"
|
70
|
+
k.try_follow_on_regex = true
|
71
|
+
k.follow_on_substitute = "\"\#{$3}\""
|
72
|
+
when :i
|
73
|
+
k.substitute = "include"
|
74
|
+
when :c
|
75
|
+
k.substitute = "class"
|
76
|
+
k.needs_top_level_end = true
|
77
|
+
when :m
|
78
|
+
k.substitute = "module"
|
79
|
+
k.needs_top_level_end = true
|
80
|
+
when :d
|
81
|
+
k.substitute = "def"
|
82
|
+
k.needs_inner_end = true
|
83
|
+
when :e
|
84
|
+
k.substitute = "end"
|
85
|
+
k.is_end = true
|
86
|
+
when :a
|
87
|
+
k.substitute = "attr_accessor"
|
88
|
+
k.try_follow_on_regex = true
|
89
|
+
k.follow_on_substitute = "$3.to_sym"#"\":\#{$3}\""
|
90
|
+
when :r
|
91
|
+
k.substitute = "attr_reader"
|
92
|
+
k.try_follow_on_regex = true
|
93
|
+
k.follow_on_substitute = "$3.to_sym"
|
94
|
+
when :w
|
95
|
+
k.substitute = "attr_writer"
|
96
|
+
k.try_follow_on_regex = true
|
97
|
+
k.follow_on_substitute = "$3.to_sym"
|
98
|
+
|
99
|
+
else
|
100
|
+
# raise "Unknown keyword #{key}"
|
101
|
+
puts "Unknown keyword #{key}"
|
102
|
+
end
|
103
|
+
keywords << k
|
104
|
+
end # end keys.each
|
105
|
+
keywords
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require "more_ruby"
|
2
|
+
require_relative "keyword"
|
3
|
+
require_relative "format"
|
4
|
+
|
5
|
+
module TerseRuby
|
6
|
+
|
7
|
+
# This Scan class does the meat of the work
|
8
|
+
# TODO generate to_s, ==, initialize
|
9
|
+
class Scan
|
10
|
+
|
11
|
+
# The main method. ARGV from the invokation are passed in to here
|
12
|
+
def self.scan_files(argv)
|
13
|
+
puts "\nTerse Ruby called"
|
14
|
+
|
15
|
+
keywords = TerseRuby::Keyword.generate_keywords
|
16
|
+
flags = argv.options
|
17
|
+
@verbose = flags.include_any?("v", "verbose")
|
18
|
+
@overwrite = flags.include_any?("o", "overwrite", "w", "write")
|
19
|
+
@no_formatting = flags.include_any?("n", "noformatting")
|
20
|
+
|
21
|
+
files = argv.values
|
22
|
+
|
23
|
+
if files.size < 1
|
24
|
+
puts "No files supplied"
|
25
|
+
else
|
26
|
+
files.each do |f|
|
27
|
+
is_file? f
|
28
|
+
end
|
29
|
+
pv "Will scan #{files.size} file#{plural_or_not files}"
|
30
|
+
files.each do |f|
|
31
|
+
is_file? f
|
32
|
+
filename = File.basename f
|
33
|
+
new_filename = gen_new_filename f
|
34
|
+
newlines = []
|
35
|
+
lines = File.readlines f
|
36
|
+
pv "File #{filename} has #{lines.size} line#{plural_or_not lines}"
|
37
|
+
# If we detect the start of a new class/method/etc. before the last one has been closed
|
38
|
+
# then insert an "end" to close it off
|
39
|
+
needs_top_level_end = false
|
40
|
+
needs_inner_end = false
|
41
|
+
insert_end = false
|
42
|
+
lines.each do |l|
|
43
|
+
line = l.chomp
|
44
|
+
newline = line # keep the orginial line unless we detect a match
|
45
|
+
keywords.each do |k|
|
46
|
+
if line =~ k.regex
|
47
|
+
pv "\nMatch found against line --> #{line}"
|
48
|
+
pv "Matched -------------------> " + $2
|
49
|
+
if k.is_end
|
50
|
+
if needs_inner_end
|
51
|
+
needs_inner_end = false
|
52
|
+
elsif needs_top_level_end
|
53
|
+
needs_top_level_end = false
|
54
|
+
end
|
55
|
+
insert_end = false
|
56
|
+
end
|
57
|
+
|
58
|
+
if k.needs_inner_end
|
59
|
+
if needs_inner_end
|
60
|
+
newlines << "end"
|
61
|
+
# keep needs_inner_end true as we need to watch for an end for this new match
|
62
|
+
else
|
63
|
+
needs_inner_end = true # set in readiness for the next match
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if k.needs_top_level_end
|
68
|
+
if needs_inner_end
|
69
|
+
newlines << "end"
|
70
|
+
needs_inner_end = false
|
71
|
+
end
|
72
|
+
if needs_top_level_end
|
73
|
+
newlines << "end"
|
74
|
+
# keep needs_top_level_end true as we need to watch for an end for this new match
|
75
|
+
else
|
76
|
+
needs_top_level_end = true # set in readiness for the next match
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if k.try_follow_on_regex && line =~ k.follow_on_regex
|
81
|
+
# puts ""
|
82
|
+
# $& is the entire match, not just the bits in ( )
|
83
|
+
remainder = line[$&.size .. -1]
|
84
|
+
follow_on = (eval k.follow_on_substitute).inspect
|
85
|
+
newline = "#{$1}#{k.substitute} #{follow_on}#{remainder}"
|
86
|
+
else
|
87
|
+
remainder = line[($1.size + $2.size) .. -1]
|
88
|
+
newline = "#{$1}#{k.substitute}#{remainder}"
|
89
|
+
end
|
90
|
+
|
91
|
+
pv "Line will become ----------> " + newline
|
92
|
+
break
|
93
|
+
end # end if regex
|
94
|
+
end # end keywords.each
|
95
|
+
newlines << newline
|
96
|
+
end # end lines.each
|
97
|
+
# Add end lines to end of file if necessary
|
98
|
+
newlines << "end" if needs_inner_end
|
99
|
+
newlines << "end" if needs_top_level_end
|
100
|
+
|
101
|
+
# Apply indentation
|
102
|
+
newlines = TerseRuby::Format.indent(newlines) unless @no_formatting
|
103
|
+
|
104
|
+
# Add newlines between the end of a method and the start of the next, if needed
|
105
|
+
newlines = TerseRuby::Format.space_lines(newlines) unless @no_formatting
|
106
|
+
|
107
|
+
# Write out the new file
|
108
|
+
File.open(new_filename, "w") do |new_f|
|
109
|
+
newlines.each do |l|
|
110
|
+
new_f.puts l
|
111
|
+
end
|
112
|
+
end
|
113
|
+
puts "\nWrote file #{new_filename}"
|
114
|
+
end # end else
|
115
|
+
end # end ARGV.size
|
116
|
+
puts "\nTerse Ruby finished"
|
117
|
+
end # end scan_files
|
118
|
+
|
119
|
+
# Returns an "s" string if the size of the item (item.size) is > 1; returns "" otherwise
|
120
|
+
def self.plural_or_not item
|
121
|
+
item.size == 1 ? "" : "s"
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.is_file? f
|
125
|
+
raise "Could not locate file at " + File.absolute_path(f) unless File.file?(f)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Rules :
|
129
|
+
# Keep base-name, change ext. to .rb, write to current working dir
|
130
|
+
def self.gen_new_filename f
|
131
|
+
path = Dir.getwd
|
132
|
+
name = File.basename_no_ext f
|
133
|
+
ext = ".rb"
|
134
|
+
new_f = File.join(path, name) + ext
|
135
|
+
|
136
|
+
if File.file?(new_f)
|
137
|
+
puts "New file wll overwrite existing file " + new_f
|
138
|
+
raise "Overwrite flag not specified; will not overwrite existing file " + new_f if !@overwrite
|
139
|
+
end
|
140
|
+
new_f
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.pv s
|
144
|
+
puts s if @verbose
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
data/lib/terse_ruby.rb
ADDED
data/terse_ruby.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'terse_ruby'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
s.licenses = ['MIT']
|
5
|
+
s.summary = "A utility to convert 'shorthand' Ruby into genuine Ruby."
|
6
|
+
s.description = "A utility to convert 'shorthand' Ruby into genuine Ruby. See README for more details."
|
7
|
+
s.authors = ["Richard Morrisby"]
|
8
|
+
s.email = 'rmorrisby@gmail.com'
|
9
|
+
s.homepage = 'https://rubygems.org/gems/terse_ruby'
|
10
|
+
s.required_ruby_version = '>=1.9'
|
11
|
+
s.files = Dir['**/**']
|
12
|
+
s.test_files = Dir["test/test*.rb"]
|
13
|
+
s.has_rdoc = true
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# test file for Terse Ruby
|
2
|
+
|
3
|
+
require "things"
|
4
|
+
|
5
|
+
class AClass
|
6
|
+
include stuff
|
7
|
+
def method1
|
8
|
+
require_relative "morethings"
|
9
|
+
puts "this is a real Ruby line"
|
10
|
+
end
|
11
|
+
|
12
|
+
def method2
|
13
|
+
end
|
14
|
+
|
15
|
+
def meth3
|
16
|
+
|
17
|
+
attr_accessor :field1
|
18
|
+
attr_reader :field2
|
19
|
+
attr_writer :field3
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module AModule
|
25
|
+
|
26
|
+
attr_writer :field4
|
27
|
+
attr_reader :field5
|
28
|
+
attr_accessor :field3 # deliberately the same name, but different accessor, as in AClass
|
29
|
+
|
30
|
+
def m3
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def method2
|
35
|
+
end
|
36
|
+
|
37
|
+
def c m r i d e a r w
|
38
|
+
end
|
39
|
+
|
40
|
+
def wraedirmc
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require_relative "../lib/terse_ruby"
|
3
|
+
|
4
|
+
class TestExpansion < Test::Unit::TestCase
|
5
|
+
|
6
|
+
@@terse_file = "test_file.txt"
|
7
|
+
@@expanded_file = "test_file.rb"
|
8
|
+
@@premade_file = "expected_test_file.rb"
|
9
|
+
@@cmd = "ruby -e \"require 'terse_ruby'; TerseRuby.scan_files ARGV\" #{@@terse_file}"
|
10
|
+
|
11
|
+
def switch_dir
|
12
|
+
# Change this so we know where the expaneded file will be created
|
13
|
+
@previous_wd ||= Dir.getwd # Preserve the old wd so we can switch back to it after the test
|
14
|
+
Dir.chdir File.expand_path(File.dirname(__FILE__))
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_cmd
|
18
|
+
system @@cmd
|
19
|
+
end
|
20
|
+
|
21
|
+
# Switch to the same directory as this unit-test file, and check that the expected file is not present
|
22
|
+
def setup
|
23
|
+
switch_dir
|
24
|
+
raise "terse_ruby unit-tests found a pre-existing #{@@expanded_file} in #{Dir.getwd}; unit-tests will clean up after themselves but will not alter pre-existing files" if File.file? @@expanded_file
|
25
|
+
raise "terse_ruby unit-tests could not locate the starting test file #{@@terse_file} in #{Dir.getwd}" unless File.file? @@terse_file
|
26
|
+
end
|
27
|
+
|
28
|
+
# Tests that the test file is expanded with the expected name
|
29
|
+
def test_expanded_name
|
30
|
+
assert_false(File.file?(@@expanded_file), "Expanded test file #{@@expanded_file} already existed before running test")
|
31
|
+
run_cmd
|
32
|
+
assert(File.exists?(@@expanded_file), "terse_ruby did not expand #{@@terse_file} into a file with name #{@@expanded_file}")
|
33
|
+
assert(File.file?(@@expanded_file), "terse_ruby did not expand #{@@terse_file} into a file with name #{@@expanded_file}")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Tests that the test file is expanded into the expected form
|
37
|
+
# Expand the file, then compare the two line-by-line
|
38
|
+
def test_expansion
|
39
|
+
run_cmd
|
40
|
+
assert(File.file?(@@expanded_file), "terse_ruby did not expand #{@@terse_file} into a file with name #{@@expanded_file}")
|
41
|
+
|
42
|
+
expected_lines = File.readlines(@@premade_file)
|
43
|
+
actual_lines = File.readlines(@@expanded_file)
|
44
|
+
|
45
|
+
assert_equal(expected_lines.size, actual_lines.size, "Expanded file did not have the expected number of lines")
|
46
|
+
|
47
|
+
# As expected_lines and actual_lines are arrays, we can just use Array#==
|
48
|
+
assert_equal(expected_lines.sort, actual_lines.sort, "Expanded file did not have the expected lines in the expected order")
|
49
|
+
assert_equal(expected_lines, actual_lines, "Expanded file did not have the expected lines")
|
50
|
+
end
|
51
|
+
|
52
|
+
# Delete the expected file from the expected dir
|
53
|
+
def teardown
|
54
|
+
if File.file?(@@expanded_file)
|
55
|
+
count = File.delete @@expanded_file
|
56
|
+
raise "Teardown failed to delete expanded file #{@@expanded_file}" unless count == 1
|
57
|
+
raise "Teardown failed to delete expanded file #{@@expanded_file}" if File.file?(@@expanded_file)
|
58
|
+
puts "Teardown deleted expanded file #{@@expanded_file}"
|
59
|
+
end
|
60
|
+
Dir.chdir @previous_wd # restore the working directory to what it was previously
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/test/test_file.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# test file for Terse Ruby
|
2
|
+
|
3
|
+
req things
|
4
|
+
|
5
|
+
c AClass
|
6
|
+
i stuff
|
7
|
+
d method1
|
8
|
+
reqr morethings
|
9
|
+
puts "this is a real Ruby line"
|
10
|
+
e
|
11
|
+
d method2
|
12
|
+
d meth3
|
13
|
+
|
14
|
+
a field1
|
15
|
+
r field2
|
16
|
+
w field3
|
17
|
+
|
18
|
+
m AModule
|
19
|
+
|
20
|
+
w field4
|
21
|
+
r field5
|
22
|
+
a field3 # deliberately the same name, but different accessor, as in AClass
|
23
|
+
|
24
|
+
d m3
|
25
|
+
|
26
|
+
d method2
|
27
|
+
e
|
28
|
+
|
29
|
+
d c m r i d e a r w
|
30
|
+
d wraedirmc
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: terse_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Richard Morrisby
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A utility to convert 'shorthand' Ruby into genuine Ruby. See README for
|
14
|
+
more details.
|
15
|
+
email: rmorrisby@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENCE.txt
|
21
|
+
- README.txt
|
22
|
+
- bin/terse_ruby.rb
|
23
|
+
- lib/terse_ruby.rb
|
24
|
+
- lib/terse_ruby/format.rb
|
25
|
+
- lib/terse_ruby/keyword.rb
|
26
|
+
- lib/terse_ruby/scan.rb
|
27
|
+
- terse_ruby.gemspec
|
28
|
+
- test/expected_test_file.rb
|
29
|
+
- test/test_expansion.rb
|
30
|
+
- test/test_file.txt
|
31
|
+
homepage: https://rubygems.org/gems/terse_ruby
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.9'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 2.5.1
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: A utility to convert 'shorthand' Ruby into genuine Ruby.
|
55
|
+
test_files:
|
56
|
+
- test/test_expansion.rb
|