terse_ruby 0.1.0 → 0.1.1

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: 86cb4b9b2d13dd5a177f684edd7f151b4e7e24ac
4
- data.tar.gz: d255dd24063cb2fa9e7010c6e3024dcb0adb888e
3
+ metadata.gz: 79aecaa694ade661bca00b2cd64fdf3704212b7f
4
+ data.tar.gz: 1dff71c71f0a27f982394d3d30cfc6949bd17000
5
5
  SHA512:
6
- metadata.gz: 0f33d258de944a568cf348257f5c5ba1eba7c5aaaf28c19ec5ef9d550db2ccb5e214972ab805edbecf7a4c51d1d5eb1cc19f1c76cee3f4d1c92095c8903c890a
7
- data.tar.gz: b2118518ae4f4d8e151c23a09648319111ca2003eeeceb00bd32f35cea44be2baec012229a6314d920d8dcdff8c6bcf05ae1467964044004d0cba6af6a3a8a35
6
+ metadata.gz: 0e8abe0b27382b2aac3a15aba0a12c6c901e9c78b2c7dea75d80888e7066417ec763f3459261a8d04ee4194ea78b3306d86db62d07bed40c4fadfd83ef1d6da4
7
+ data.tar.gz: 064b6152d319c606beaad32edeaa616e9a6a561f331c7ca104a968963fb3811b2ab2ff5cb78cce68f5fa33097866fba1995ac045c201c06bbb94108a4dac7d85
data/README.txt CHANGED
@@ -18,7 +18,7 @@
18
18
  # end
19
19
  #
20
20
  #
21
- # Rules :
21
+ # Keywords :
22
22
  # Terse Ruby will look through the supplied files and convert certain keywords at the start of lines :
23
23
  # c -> class
24
24
  # m -> module
@@ -49,7 +49,59 @@
49
49
  #
50
50
  # Alternatively, the below two lines are all you need to run terse_ruby within your own Ruby file :
51
51
  #
52
- # require_relative "../lib/terse_ruby"
52
+ # require "terse_ruby"
53
+ #
54
+ # # (optionally add to ARGV here)
53
55
  # TerseRuby.scan_files ARGV
54
56
  #
55
- # (if ARGV have not been supplied, you'll need to construct this object yourself first)
57
+ # If ARGV have not been supplied, you'll need to add your args to ARGV, e.g. ARGV << "-v"; ARGV << "terse_file.txt"
58
+ # Note that ARGV is not any ordinary array; terse_ruby uses the 'argv' gem which adds methods to the ARGV object;
59
+ # therefore we must supply the ARGV object to TerseRuby.scan_files
60
+
61
+
62
+ # Terse Java
63
+ #
64
+ # Invoke in the same way as TerseRuby, but instead using the module name TerseJava; e.g.
65
+ # ruby -e "require 'terse_ruby'; TerseRuby.scan_files ARGV" [one or more files] [flags]
66
+ # or
67
+ # TerseJava.scan_files ARGV
68
+ #
69
+ # Keywords :
70
+ #
71
+ # imp -> import
72
+ # pk -> package
73
+ # c -> class
74
+ # impl -> implements
75
+ # ex -> extends
76
+ # int -> interface
77
+ # ab -> abstract
78
+ # e -> enum
79
+ # st -> static
80
+ # v -> void
81
+ # m -> main
82
+ # p -> public
83
+ # pt -> protected
84
+ # pv -> private
85
+ # r -> return
86
+ # s -> String
87
+ # i -> Integer
88
+ # b -> Boolean
89
+ # f -> Float
90
+ # fn -> final
91
+ #
92
+ #
93
+ # Flags :
94
+ #
95
+ # The same flags may be used as with Terse Ruby
96
+ #
97
+ # Notes :
98
+ #
99
+ # Constructors will not be made, as it is impossble to 100% accurately distinguish between a variable and a method in terse form.
100
+ # Getters and setters will not be made, as it is impossble to 100% accurately distinguish between a variable and a method in terse form.
101
+ # This is acceptable, as most IDEs are able to generate constructors and getters-and-setters.
102
+ #
103
+ # Primitive types (int, float, etc.) will never be used; i -> Integer, f -> Float, etc.
104
+ #
105
+ # Obvious class-beginnings will be given { (and } at the end of the file); obvious method endings (i.e. the 'return' keyword) will be given }
106
+ # Because in terse form, there is ambiguity between methods and variables, some method starts will not gain { and some regular code lines will not gain ;
107
+ # You should expect Java expanded from terse-form to contain compilation errors of this kind.
@@ -0,0 +1,50 @@
1
+ # Simple build script
2
+ # Deletes the existing gem file (if present)
3
+ # Uninstalls the gem
4
+ # Builds the gem
5
+ # Installs the new gem
6
+
7
+ # Note : when calling system (or backticks, etc.) th enew process starts at the system default, not the current working directory.
8
+ # Therefore we need to use a syntax of : system "cd #{gem_dir} && #{i_cmd}"
9
+
10
+ # Run from this directory!
11
+ gem_dir = Dir.getwd
12
+
13
+ # Delete existing .gem files in the dir
14
+
15
+ gemfiles = Dir.entries(gem_dir).collect {|q| q if q =~ /.gem$/}.compact
16
+
17
+ gemfiles.each do |q|
18
+ File.delete q
19
+ puts "Deleted #{q}"
20
+ end
21
+
22
+ gemfiles = Dir.entries(gem_dir).collect {|q| q if q =~ /.gem$/}.compact
23
+ raise "Gem has not been deleted" unless gemfiles.size == 0
24
+
25
+ # Uninstall, build, install
26
+ gemspecs = Dir.entries(gem_dir).collect {|q| q if q =~ /.gemspec$/}.compact
27
+
28
+ raise "Did not find a .gemspec in #{gem_dir}" if gemspecs.size < 1
29
+ raise "Found more than one .gemspec in #{gem_dir}" if gemspecs.size > 1
30
+
31
+ gemspec = gemspecs[0]
32
+
33
+ gemname = File.basename(gemspec, File.extname(gemspec))
34
+
35
+ u_cmd = "gem uninstall #{gemname}"
36
+ system u_cmd
37
+
38
+ b_cmd = "gem build #{gemspec}"
39
+ system "cd #{gem_dir} && #{b_cmd}"
40
+
41
+ gemfiles = Dir.entries(gem_dir).collect {|q| q if q =~ /.gem$/}.compact
42
+ raise "Gem was not built" unless gemfiles.size == 1
43
+
44
+ gemfile = gemfiles[0]
45
+ raise "Gem file is not for the expected gem, expected a #{gemname} gem but found #{gemfile}" unless gemfile =~ /^#{gemname}/
46
+
47
+ i_cmd = "gem install #{gemfile}"
48
+ system "cd #{gem_dir} && #{i_cmd}"
49
+
50
+ puts "Gem #{gemname} built & installed"
@@ -1,38 +1,39 @@
1
- module TerseRuby
1
+ module Terse
2
2
 
3
3
  # Simple class for formatting the list of lines
4
4
  class Format
5
5
 
6
6
  # Apply indentation
7
7
  # It is easier to do this once the full list of newlines is assembled
8
- def self.indent lines
8
+ def self.indent lines, settings
9
9
  indented_lines = []
10
10
  indent_level = 0
11
- keys = %w{ class module def if when case for }
12
- first_word_regex = /^([a-zA-Z0-9_]+)(\s+|$)/
13
11
  lines.each do |l|
14
12
  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
-
13
+ l =~ settings.indent_out_regex
14
+
15
+ # check for a loop-ending before indenting
16
+ indent_level -= 1 if settings.indent_out.include?($1.to_s.strip) # must to_s in case $1 is nil
19
17
  indent_level.times do
20
18
  l.insert(0, "\t")
21
19
  end
22
- indented_lines << l
23
- # puts indented_lines
20
+ indented_lines << l.dup # need to call .dup ; it will otherwise mess up indentation of loop-ending lines
24
21
 
25
22
  # check for indent-increasing keywords after indenting
26
- indent_level += 1 if keys.include?($1)
23
+ l =~ settings.indent_in_regex
24
+ indent_level += 1 if settings.indent_in.include?($1.to_s.strip) # must to_s in case $1 is nil
27
25
  end
28
26
  indented_lines
29
27
  end
30
28
 
31
29
  # 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
30
+ def self.space_lines lines, keywords, settings
33
31
  spaced_lines = []
34
32
 
35
- keys = %w{ class module def }
33
+ # Filter out keywords that do not trigger some sort of indent-change
34
+ keys = keywords.dup
35
+ keys = keys.delete_if {|k| !(k.needs_top_level_end || k.needs_inner_end)}
36
+ keys.collect! {|k| k.substitute}
36
37
  first_word_regex = /^\s*([a-zA-Z0-9_]+)(\s+|$)/
37
38
  for i in 0 ... lines.size - 1
38
39
  first_line = lines[i]
@@ -42,9 +43,9 @@ module TerseRuby
42
43
 
43
44
  first_line =~ first_word_regex # set the $ variables for inspection
44
45
  # 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
+ if $1.to_s.strip == settings.loop_ending.strip
46
47
  next_line =~ first_word_regex
47
- spaced_lines << "" if keys.include?($1)
48
+ spaced_lines << "" if keys.include?($1.to_s.strip)
48
49
  end
49
50
  end
50
51
  # Remember to add the last line!
@@ -0,0 +1,166 @@
1
+ module Terse
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_start
12
+ attr_accessor :needs_inner_start
13
+ attr_accessor :needs_top_level_end
14
+ attr_accessor :needs_inner_end
15
+ attr_accessor :is_end
16
+
17
+ # some keywords naturally imply that the line should have a line-ending, e.g. ; for Java
18
+ # line-endings should not be applied if the keyword indicates the start/end of a class/method/block, etc.
19
+ # Internally, :needs_top_level_end and :needs_inner_end take priority over :needs_line_ending
20
+ attr_accessor :needs_line_ending
21
+
22
+ def initialize(keyword)
23
+ @keyword = keyword
24
+ @regex = gen_regex_from_keyword keyword
25
+ @follow_on_regex = gen_regex_from_keyword_including_follow_on keyword
26
+ end
27
+
28
+ # # TODO this doesn't work, needs to process the thing following the keyword, not the keyword itself
29
+ # def set_substitute
30
+ # case @keyword
31
+ # when "a", "r", "w"
32
+ # @substitute = ":" + @substitute
33
+ # when "req", "reqr"
34
+ # @substitute = "\"" + @substitute + "\"" unless ["\"", "'"].include? @substitute[0]
35
+ # end
36
+ # end
37
+
38
+
39
+
40
+ # # @substitutes = %W{ require require_relative include class method def end attr_accesor attr_reader attr_writer }
41
+
42
+
43
+ # # def generate_regexes
44
+ # # r = []
45
+ # # for i in 0 ... @keywords.size
46
+ # # r << Keyword.new(@keywords[i], @substitutes[i], gen_regex_from_keyword(@keywords[i]))
47
+ # # end
48
+ # # r
49
+ # # end
50
+
51
+ # # Simple regex to match a keyword at the start of a line
52
+ # def gen_regex_from_keyword keyword
53
+ # return /(^\s*)(#{keyword})(\s+|$)/
54
+ # end
55
+
56
+ # # Regex to match a keyword at the start of a line, and the next word on that line
57
+ # # E.g. this will also catch (in $3) the item following the "require" keyword
58
+ # # This enables the routine to format this follow-on word, e.g. to turn 'req a_gem' into
59
+ # # 'require "a_gem"'
60
+ # def gen_regex_from_keyword_including_follow_on keyword
61
+ # return /(^\s*)(#{keyword})\s+([a-zA-Z0-9_]+)/
62
+ # end
63
+
64
+ # def self.generate_ruby_keywords
65
+ # keywords = []
66
+ # keys = [:req, :reqr, :i, :c, :m, :d, :e, :a, :r, :w]
67
+ # keys.each do |key|
68
+ # k = Keyword.new key
69
+ # # k.keyword = key
70
+ # case key
71
+ # when :req
72
+ # k.substitute = "require"
73
+ # k.try_follow_on_regex = true
74
+ # k.follow_on_substitute = "\"\#{$3}\""
75
+ # when :reqr
76
+ # k.substitute = "require_relative"
77
+ # k.try_follow_on_regex = true
78
+ # k.follow_on_substitute = "\"\#{$3}\""
79
+ # when :i
80
+ # k.substitute = "include"
81
+ # when :c
82
+ # k.substitute = "class"
83
+ # k.needs_top_level_end = true
84
+ # when :m
85
+ # k.substitute = "module"
86
+ # k.needs_top_level_end = true
87
+ # when :d
88
+ # k.substitute = "def"
89
+ # k.needs_inner_end = true
90
+ # when :e
91
+ # k.substitute = "end"
92
+ # k.is_end = true
93
+ # when :a
94
+ # k.substitute = "attr_accessor"
95
+ # k.try_follow_on_regex = true
96
+ # k.follow_on_substitute = "$3.to_sym"#"\":\#{$3}\""
97
+ # when :r
98
+ # k.substitute = "attr_reader"
99
+ # k.try_follow_on_regex = true
100
+ # k.follow_on_substitute = "$3.to_sym"
101
+ # when :w
102
+ # k.substitute = "attr_writer"
103
+ # k.try_follow_on_regex = true
104
+ # k.follow_on_substitute = "$3.to_sym"
105
+
106
+ # else
107
+ # # raise "Unknown keyword #{key}"
108
+ # puts "Unknown keyword #{key}"
109
+ # end
110
+ # keywords << k
111
+ # end # end keys.each
112
+ # keywords
113
+ # end
114
+
115
+ # def self.generate_java_keywords
116
+ # keywords = []
117
+ # keys = [:imp, :c, :ex, :inc, :ab, :e, :st, :v, :m, :p, :pt, :pv, :r, :s, :i, :b, :f, :fn]
118
+ # keys.each do |key|
119
+ # k = Keyword.new key
120
+ # # k.keyword = key
121
+ # case key
122
+ # when :imp
123
+ # k.substitute = "import"
124
+ # k.try_follow_on_regex = true
125
+ # k.follow_on_substitute = "\"\#{$3}\""
126
+ # when :reqr
127
+ # k.substitute = "require_relative"
128
+ # k.try_follow_on_regex = true
129
+ # k.follow_on_substitute = "\"\#{$3}\""
130
+ # when :i
131
+ # k.substitute = "include"
132
+ # when :c
133
+ # k.substitute = "class"
134
+ # k.needs_top_level_end = true
135
+ # when :m
136
+ # k.substitute = "module"
137
+ # k.needs_top_level_end = true
138
+ # when :d
139
+ # k.substitute = "def"
140
+ # k.needs_inner_end = true
141
+ # when :e
142
+ # k.substitute = "end"
143
+ # k.is_end = true
144
+ # when :a
145
+ # k.substitute = "attr_accessor"
146
+ # k.try_follow_on_regex = true
147
+ # k.follow_on_substitute = "$3.to_sym"#"\":\#{$3}\""
148
+ # when :r
149
+ # k.substitute = "attr_reader"
150
+ # k.try_follow_on_regex = true
151
+ # k.follow_on_substitute = "$3.to_sym"
152
+ # when :w
153
+ # k.substitute = "attr_writer"
154
+ # k.try_follow_on_regex = true
155
+ # k.follow_on_substitute = "$3.to_sym"
156
+
157
+ # else
158
+ # # raise "Unknown keyword #{key}"
159
+ # puts "Unknown keyword #{key}"
160
+ # end
161
+ # keywords << k
162
+ # end # end keys.each
163
+ # keywords
164
+ # end
165
+ end
166
+ end
@@ -0,0 +1,103 @@
1
+ require_relative "keyword"
2
+
3
+ module Terse
4
+
5
+ # A class storing all information about a keyword & what it should be transformed into
6
+ class KeywordJava < Keyword
7
+
8
+ def initialize(keyword)
9
+ super(keyword)
10
+ @loop_ending = "}"
11
+ @line_ending = ";"
12
+ end
13
+
14
+ # Simple regex to match a keyword
15
+ def gen_regex_from_keyword keyword
16
+ # return /(^|\s+)(#{keyword})(\s+|$)/
17
+ return /(^|\s+|\w*\()(#{keyword})(\s+|$)/
18
+ end
19
+
20
+ # Regex to match a keyword at the start of a line, and the next word on that line
21
+ # E.g. this will also catch (in $3) the item following the "require" keyword
22
+ # This enables the routine to format this follow-on word, e.g. to turn 'req a_gem' into
23
+ # 'require "a_gem"'
24
+ def gen_regex_from_keyword_including_follow_on keyword
25
+ return /(^|\s+)(#{keyword})\s+([a-zA-Z0-9_]+)/
26
+ end
27
+
28
+ def self.generate_keywords
29
+ keywords = []
30
+ keys = [:imp, :pk, :c, :ex, :impl, :int, :ab, :e, :st, :v, :m, :p, :pt, :pv, :r, :s, :i, :b, :f, :fn]
31
+ keys.each do |key|
32
+ k = KeywordJava.new key
33
+ # k.keyword = key
34
+ case key
35
+ when :imp
36
+ k.substitute = "import"
37
+ k.needs_line_ending = true
38
+ when :pk
39
+ k.substitute = "package"
40
+ k.needs_line_ending = true
41
+ when :c
42
+ k.substitute = "class"
43
+ k.needs_top_level_start = true
44
+ k.needs_top_level_end = true
45
+ when :ex
46
+ k.substitute = "extends"
47
+ when :impl
48
+ k.substitute = "implements"
49
+ when :int
50
+ k.substitute = "interface"
51
+ when :ab
52
+ k.substitute = "abstract"
53
+ when :e
54
+ k.substitute = "enum"
55
+ k.needs_top_level_start = true
56
+ k.needs_top_level_end = true
57
+ when :st
58
+ k.substitute = "static"
59
+ k.needs_line_ending = true
60
+ when :v
61
+ k.substitute = "void"
62
+ k.needs_inner_start = true
63
+ k.needs_inner_end = true
64
+ when :m
65
+ k.substitute = "main"
66
+ when :p
67
+ k.substitute = "public"
68
+ k.needs_line_ending = true
69
+ when :pt
70
+ k.substitute = "protected"
71
+ k.needs_line_ending = true
72
+ when :pv
73
+ k.substitute = "private"
74
+ k.needs_line_ending = true
75
+ when :r
76
+ k.substitute = "return"
77
+ k.needs_inner_end = true
78
+ k.needs_line_ending = true
79
+ when :s
80
+ k.substitute = "String"
81
+ k.needs_line_ending = true
82
+ when :i
83
+ k.substitute = "Integer"
84
+ k.needs_line_ending = true
85
+ when :b
86
+ k.substitute = "Boolean"
87
+ k.needs_line_ending = true
88
+ when :f
89
+ k.substitute = "Float"
90
+ k.needs_line_ending = true
91
+ when :fn
92
+ k.substitute = "final"
93
+ k.needs_line_ending = true
94
+ else
95
+ # raise "Unknown keyword #{key}"
96
+ puts "Unknown keyword #{key}"
97
+ end
98
+ keywords << k
99
+ end # end keys.each
100
+ keywords
101
+ end
102
+ end
103
+ end