dfhmdf 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b63e9ac034b94142ef123c5557fe73b860e0f853
4
+ data.tar.gz: 749a0b27b492e45c7c83fb9c3588160a6e150b9b
5
+ SHA512:
6
+ metadata.gz: 9378f25ada91fd1bc9462d9189133c51c13bbc43d33f32b41cc4a241818b730c36fe41545180109c9d5faa4e658585555313f8c3119951bc461004c2c92ca51c
7
+ data.tar.gz: aea1f18ac9970760998a21538bfc7622a03110545dbe05cf7351357aae8b88a4753e3104eacca9788da43802125140e656f586f0cde7642959a61c51868602bc
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.lock
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'rspec'
5
+
6
+ gemspec
data/Gemspec ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Dave Nicolette
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # dfhmdf
2
+
3
+ Converts DFHMDF macro specifications into ```text_field``` definitions for use with the (https://github.com/cheezy/te3270/)[TE3270 gem]. The purpose is to eliminate the need for you to count the characters across and down a 3270 screen to determine the X and Y coordinates and the length of each field you wish to define for TE3270.
4
+
5
+ ## Example
6
+
7
+ Given a BMS macro source file named ```myscreen.txt``` with the following contents:
8
+
9
+ ```
10
+ QCKSET DFHMSD TYPE=MAP,STORAGE=AUTO,MODE=OUT,LANG=COBOL,TIOAPFX=YES
11
+ QCKMAP DFHMDI SIZE=(24,80),LINE=1,COLUMN=1,CTRL=ALARM
12
+ DFHMDF POS=(1,1),LENGTH=3,ATTRB=(ASKIP,BRT),INITIAL='QCK'
13
+ DFHMDF POS=(1,26),LENGTH=28,ATTRB=(ASKIP,NORM), X
14
+ INITIAL='Quick Customer Account Check'
15
+ DFHMDF POS=(3,1),LENGTH=8,ATTRB=(ASKIP,NORM),INITIAL='Account:'
16
+ ACCTNO DFHMDF POS=(3,13),LENGTH=7,ATTRB=(ASKIP,NORM)
17
+ DFHMDF POS=(4,1),LENGTH=5,ATTRB=(ASKIP,NORM),INITIAL='Name:'
18
+ SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM)
19
+ FNAME DFHMDF POS=(4,30),LENGTH=10,ATTRB=(ASKIP,NORM)
20
+ DFHMDF POS=(5,1),LENGTH=11,ATTRB=(ASKIP,NORM),INITIAL='Max charge:'
21
+ CHG DFHMDF POS=(5,13),ATTRB=(ASKIP,NORM),PICOUT='$,$$0.00'
22
+ MSG DFHMDF LENGTH=20,POS=(7,1),ATTRB=(ASKIP,NORM)
23
+ DFHMSD TYPE=FINAL
24
+ ```
25
+
26
+ run ```dfhmdf`` as a command-line utility:
27
+
28
+ ```sh
29
+ dfhmdf macro-source > target-file
30
+ ```
31
+
32
+ to produce the following output:
33
+
34
+ ```ruby
35
+ text_field(:acctno, 4, 13, 7)
36
+ text_field(:surname, 5, 13, 15)
37
+ text_field(:fname, 5, 30, 10)
38
+ text_field(:chg, 6, 13, 8)
39
+ text_field(:msg, 8, 1, 20)
40
+ ```
41
+
42
+ From the example you may surmise:
43
+
44
+ 1. It only pays attention to DFHMDF macros.
45
+ 1. It uses the downcased label value as the TE3270 field name, or a name like 'x14y12' for unlabeled DFHMDF macros.
46
+ 1. It adjusts the X axis offset to account for the attribute byte.
47
+ 1. When PICOUT is specified instead of LENGTH, it derives the length from the PICOUT value.
48
+ 1. It generates only ```text_field``` definitions, and not a complete TE3270 screen class.
49
+
50
+ So, if you have coded a TE3270 screen class like this:
51
+
52
+ ```ruby
53
+ class MainframeScreen
54
+ include TE3270
55
+
56
+ def login(username, password)
57
+ self.userid = username
58
+ self.password = password
59
+ end
60
+ end
61
+
62
+ emulator = TE3270.emulator_for :extra do |platform|
63
+ platform.session_file = 'sessionfile.edp'
64
+ end
65
+ my_screen = MainframeScreen.new(emulator)
66
+ my_screen.userid = 'the_id'
67
+ my_screen.password = 'the_password'
68
+ ```
69
+
70
+ then you can paste in the generated ```text_field``` definitions like this:
71
+
72
+ ```ruby
73
+ class MainframeScreen
74
+ include TE3270
75
+
76
+ text_field(:acctno, 4, 13, 7)
77
+ text_field(:surname, 5, 13, 15)
78
+ text_field(:fname, 5, 30, 10)
79
+ text_field(:chg, 6, 13, 8)
80
+ text_field(:msg, 8, 1, 20)
81
+
82
+ def login(username, password)
83
+ self.userid = username
84
+ self.password = password
85
+ end
86
+ end
87
+
88
+ emulator = TE3270.emulator_for :extra do |platform|
89
+ platform.session_file = 'sessionfile.edp'
90
+ end
91
+ my_screen = MainframeScreen.new(emulator)
92
+ my_screen.userid = 'the_id'
93
+ my_screen.password = 'the_password'
94
+ ```
95
+
96
+ ## Installation
97
+
98
+ Add this line to your application's Gemfile:
99
+
100
+ ```ruby
101
+ gem 'dfhmdf'
102
+ ```
103
+
104
+ And then execute:
105
+
106
+ $ bundle
107
+
108
+ or install it yourself as:
109
+
110
+ $ gem install dfhmdf
111
+
112
+ ## Contributing
113
+
114
+ 1. Fork it ( https://github.com/[my-github-username]/dfhmdf/fork )
115
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
116
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
117
+ 4. Push to the branch (`git push origin my-new-feature`)
118
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/dfhmdf ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/convert_dfhmdf'
4
+
5
+ convert = ConvertDfhmdf.new
6
+ convert.run
data/dfhmdf.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dfhmdf/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dfhmdf"
8
+ spec.version = Dfhmdf::VERSION
9
+ spec.authors = ["Dave Nicolette"]
10
+ spec.email = ["davenicolette@gmail.com"]
11
+ spec.summary = %q{Interprets DFHMDF macros}
12
+ spec.description = %q{Generate text_field specifications for te3270 based on DFHMDF source}
13
+ spec.homepage = "http://github.com/neopragma/dfhmdf"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,66 @@
1
+ require_relative './dfhmdf'
2
+
3
+ class ConvertDfhmdf
4
+ include Dfhmdf
5
+
6
+ def run
7
+ open_file
8
+ begin
9
+ clear
10
+ ingest_macro
11
+ process_macro @macro_source
12
+ puts te3270_text_field if dfhmdf?
13
+ end while @eof == false
14
+ close_file
15
+ end
16
+
17
+ def process_macro dfhmdf_macro
18
+ parse_tokens tokenize_line dfhmdf_macro
19
+ end
20
+
21
+ def ingest_macro
22
+ macro_end = false
23
+ @macro_source = ''
24
+ current_line = read_line
25
+ begin
26
+ if current_line == nil || current_line.length < 72 || current_line[71] == ' '
27
+ macro_end = true
28
+ end
29
+ @macro_source << squish(current_line)
30
+ current_line = read_line unless macro_end
31
+ end while macro_end == false
32
+ @macro_source
33
+ end
34
+
35
+ def process_macro dfhmdf_macro
36
+ parse_tokens tokenize_line dfhmdf_macro
37
+ end
38
+
39
+ def squish str
40
+ str[71] = ' ' unless str.length < 72
41
+ str.split.join(' ')
42
+ end
43
+
44
+ def macro_source
45
+ @macro_source
46
+ end
47
+
48
+ def read_line
49
+ line = @source_file.readline
50
+ @eof = @source_file.eof?
51
+ line
52
+ end
53
+
54
+ def open_file
55
+ if ARGV[0] == nil
56
+ abort 'Usage: ruby make_fields.rb inputfilename'
57
+ end
58
+ @source_file = File.open(ARGV[0], 'r')
59
+ @eof = false
60
+ end
61
+
62
+ def close_file
63
+ @source_file.close
64
+ end
65
+
66
+ end
data/lib/dfhmdf.rb ADDED
@@ -0,0 +1,126 @@
1
+ module Dfhmdf
2
+
3
+ def te3270_text_field
4
+ "text_field(:#{field_label}, #{x_coordinate}, #{y_coordinate}, #{field_length})"
5
+ end
6
+
7
+ def clear
8
+ @field_label, @parameter_hash, @parameters, @tokens = nil
9
+ @dfhmdf = false
10
+ end
11
+
12
+ def tokenize_line input_line
13
+
14
+ # Want to split on spaces except when space occurs within single quotes.
15
+ # Should be able to do it with a regex. Unable to figure it out so far. Using brute force.
16
+ # This regex doesn't work but was as close as I was able to get.
17
+ # @tokens = [@tokens, input_line.scan(/'.*?'|".*?"|\S+/)].compact.reduce([], :|)
18
+
19
+ new_tokens = []
20
+ temp = input_line.split
21
+ for i in 0..temp.length-1 do
22
+ if temp[i] != nil
23
+ if temp[i].include? "'"
24
+ temp[i] << ' ' << temp[i+1] unless temp[i+1] == nil
25
+ temp[i + 1] = nil
26
+ if new_tokens[i] == nil
27
+ new_tokens[i] = temp[i]
28
+ else
29
+ new_tokens[i] << temp[i]
30
+ end
31
+ else
32
+ new_tokens << temp[i]
33
+ end
34
+ end
35
+ end
36
+ @tokens = [@tokens, new_tokens].compact.reduce([], :|)
37
+ end
38
+
39
+ def parse_tokens tokens
40
+ @dfhmdf = false
41
+ if tokens[0] == 'DFHMDF'
42
+ @dfhmdf = true
43
+ @field_label = nil
44
+ operands = tokens[1]
45
+ elsif tokens[1] == 'DFHMDF'
46
+ @dfhmdf = true
47
+ @field_label = tokens[0].downcase
48
+ operands = tokens[2]
49
+ end
50
+ if dfhmdf? && tokens != nil && operands != nil && operands.include?('=')
51
+ parse_operands operands
52
+ end
53
+ end
54
+
55
+
56
+ def parse_operands operands_as_string
57
+ #-----------------------------------------------------------------------------
58
+ # Parse the operands in a macro source statement:
59
+ #
60
+ # LABEL MACRO OPERAND,OPERAND,OPERAND COMMENT X
61
+ # xxxxxxxxxxxxxxxxxxxxxxx
62
+ #
63
+ # Example
64
+ # -------
65
+ # from this...
66
+ # FIELD1 DFHMDF POS=(6,18),LENGTH=14,ATTRB=(ASKIP,NORM),INITIAL='Hello there'
67
+ #
68
+ # to this...
69
+ # { :pos => [ "6", "18" ], :length => "14", :attrb => [ "ASKIP", "NORM" ],
70
+ # :initial => "Hello there" }
71
+ #-----------------------------------------------------------------------------
72
+ @operands_hash = {}
73
+
74
+ # Split on comma except when the comma appears within parentheses.
75
+ # Couldn't figure out how to make it ignore commas within single quotes,
76
+ # so it misses PICOUT='$,$$0.00' and similar. Using brute force to handle it.
77
+
78
+ item = operands_as_string.split(/,(?![^(]*\))/)
79
+ for i in 0..item.length-1
80
+ if item[i].match(/^PICOUT=/)
81
+ item[i] << ',' << item[i+1]
82
+ end
83
+
84
+ if item[i].include? '='
85
+ key_value_pair = item[i].split('=')
86
+
87
+ # handle operand values consisting of a comma-separated list within parentheses
88
+ if key_value_pair[1][0] == '('
89
+ key_value_pair[1].gsub!(/[\(\)]/, '')
90
+ key_value_pair[1] = key_value_pair[1].split(',')
91
+ end
92
+
93
+ # handle operand values in single quotes
94
+ if key_value_pair[1][0] == "'"
95
+ key_value_pair[1].gsub!(/'/, '')
96
+ end
97
+
98
+ @operands_hash[key_value_pair[0].downcase.to_sym] = key_value_pair[1]
99
+ end
100
+ end
101
+ @operands_hash
102
+ end
103
+
104
+ def x_coordinate
105
+ (@operands_hash != nil && @operands_hash[:pos] && @operands_hash[:pos][0].to_i + 1) || 0
106
+ end
107
+
108
+ def y_coordinate
109
+ (@operands_hash != nil && @operands_hash[:pos] && @operands_hash[:pos][1].to_i) || 0
110
+ end
111
+
112
+ def field_length
113
+ (@operands_hash != nil && @operands_hash[:length] && @operands_hash[:length].to_i) ||
114
+ (@operands_hash != nil && @operands_hash[:initial] && @operands_hash[:initial].length) ||
115
+ (@operands_hash != nil && @operands_hash[:picout] && @operands_hash[:picout].length) || 0
116
+ end
117
+
118
+ def field_label
119
+ (@field_label == nil && "x#{x_coordinate}y#{y_coordinate}") || @field_label
120
+ end
121
+
122
+ def dfhmdf?
123
+ @dfhmdf
124
+ end
125
+
126
+ end
@@ -0,0 +1,3 @@
1
+ module Dfhmdf
2
+ VERSION = "0.0.1"
3
+ end
data/sample-macros ADDED
@@ -0,0 +1,15 @@
1
+ QCKSET DFHMSD TYPE=MAP,STORAGE=AUTO,MODE=OUT,LANG=COBOL,TIOAPFX=YES
2
+ QCKMAP DFHMDI SIZE=(24,80),LINE=1,COLUMN=1,CTRL=ALARM
3
+ DFHMDF POS=(1,1),LENGTH=3,ATTRB=(ASKIP,BRT),INITIAL='QCK'
4
+ TITLE DFHMDF POS=(1,26),LENGTH=28,ATTRB=(ASKIP,NORM), X
5
+ INITIAL='Quick Customer Account Check'
6
+ HEAD DFHMDF POS=(3,1),LENGTH=8,ATTRB=(ASKIP,NORM),INITIAL='Account:'
7
+ ACCTNO DFHMDF POS=(3,13),LENGTH=7,ATTRB=(ASKIP,NORM)
8
+ DFHMDF POS=(4,1),LENGTH=5,ATTRB=(ASKIP,NORM),INITIAL='Name:'
9
+ SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM)
10
+ FNAME DFHMDF POS=(4,30),LENGTH=10,ATTRB=(ASKIP,NORM)
11
+ DFHMDF POS=(5,1),LENGTH=11,ATTRB=(ASKIP,NORM), X
12
+ INITIAL='Max charge:'
13
+ CHG DFHMDF POS=(5,13),ATTRB=(ASKIP,NORM),PICOUT='$,$$0.00'
14
+ MSG DFHMDF LENGTH=20,POS=(7,1),ATTRB=(ASKIP,NORM)
15
+ DFHMSD TYPE=FINAL
@@ -0,0 +1,49 @@
1
+ require 'convert_dfhmdf'
2
+
3
+ describe ConvertDfhmdf do
4
+
5
+ before(:each) do
6
+ @screen_def = ConvertDfhmdf.new
7
+ end
8
+
9
+ describe "#process_macro" do
10
+ it "handles a DFHMDF macro" do
11
+ @screen_def.process_macro 'SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM)'
12
+ expect(@screen_def.dfhmdf?).to be(true)
13
+ expect(@screen_def.field_label).to eq('surname')
14
+ expect(@screen_def.x_coordinate).to eq(5)
15
+ expect(@screen_def.y_coordinate).to eq(13)
16
+ expect(@screen_def.field_length).to eq(15)
17
+ end
18
+ it "ignores macros other than DFHMDF" do
19
+ @screen_def.process_macro 'QCKSET DFHMSD TYPE=MAP,STORAGE=AUTO,MODE=OUT,LANG=COBOL,TIOAPFX=YES'
20
+ expect(@screen_def.dfhmdf?).to be(false)
21
+ expect(@screen_def.field_label).to eq('x0y0')
22
+ expect(@screen_def.x_coordinate).to eq(0)
23
+ expect(@screen_def.y_coordinate).to eq(0)
24
+ expect(@screen_def.field_length).to eq(0)
25
+ end
26
+ end
27
+
28
+ describe "#ingest_macro" do
29
+ it "stores macro source coded on a single line" do
30
+ allow(@screen_def).to receive(:read_line).and_return('SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM)')
31
+ @screen_def.ingest_macro
32
+ expect(@screen_def.macro_source).to eq('SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM)')
33
+ end
34
+
35
+ it "stores macro source coded on multiple lines" do
36
+ allow(@screen_def).to receive(:read_line).and_return(
37
+ # 1 2 3 4 5 6 7 8
38
+ # 12345678901234567890123456789012345678901234567890123456789012345678901234567890
39
+ 'SURNAME DFHMDF POS=(4,13), X',
40
+ ' LENGTH=15, X',
41
+ ' ATTRB=(ASKIP,NORM), X',
42
+ ' INITIAL=\'Name here\'')
43
+ @screen_def.ingest_macro
44
+ expect(@screen_def.macro_source)
45
+ .to eq('SURNAME DFHMDF POS=(4,13),LENGTH=15,ATTRB=(ASKIP,NORM),INITIAL=\'Name here\'')
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,208 @@
1
+ require 'dfhmdf'
2
+
3
+ class ScreenDef
4
+ include Dfhmdf
5
+
6
+ def operands_hash value
7
+ @operands_hash = value
8
+ end
9
+
10
+ def field_label= value
11
+ @field_label = value
12
+ end
13
+
14
+ end
15
+
16
+ describe ScreenDef do
17
+
18
+ before(:each) do
19
+ @screen_def = ScreenDef.new
20
+ end
21
+
22
+ context "housekeeping" do
23
+ it "clears all temporary values relevant to processing a DFHMDF macro" do
24
+ @screen_def.clear
25
+ expect(@screen_def.dfhmdf?).to be(false)
26
+ expect(@screen_def.field_length).to eq(0)
27
+ expect(@screen_def.field_label).to eq('x0y0')
28
+ expect(@screen_def.x_coordinate).to eq(0)
29
+ expect(@screen_def.y_coordinate).to eq(0)
30
+ end
31
+ end
32
+
33
+ context "tokenizing" do
34
+ describe "#tokenize_line" do
35
+ it "collects tokens separated by spaces" do
36
+ expect(@screen_def.tokenize_line('abc de,fg,hijk lmnop'))
37
+ .to eq([ 'abc', 'de,fg,hijk', 'lmnop' ])
38
+ end
39
+
40
+ it "doesn't split on spaces that appear within quoted strings" do
41
+ expect(@screen_def.tokenize_line("abc de,'fg hi',jkl mnop"))
42
+ .to eq([ "abc", "de,'fg hi',jkl", "mnop" ])
43
+ end
44
+
45
+ it "splits properly when the last operand is a quoted string with a space" do
46
+ expect(@screen_def.tokenize_line("abc de,'fg hi',jkl"))
47
+ .to eq([ "abc", "de,'fg hi',jkl" ])
48
+ end
49
+ end
50
+ end
51
+
52
+ context "recognizing DFHMDF macros" do
53
+ describe "#parse_tokens" do
54
+ it "recognizes a DFHMDF macro with no label" do
55
+ @screen_def.parse_tokens([ 'DFHMDF', 'POS=(4,5),LENGTH=15', 'baz' ])
56
+ expect(@screen_def.dfhmdf?).to be(true)
57
+ end
58
+ end
59
+
60
+ describe "#parse_tokens" do
61
+ it "clears the previous value of field label when none is specified" do
62
+ @screen_def.field_label = 'aardvaark'
63
+ @screen_def.parse_tokens([ 'DFHMDF', 'foo', 'bar' ])
64
+ expect(@screen_def.field_label).to eql('x0y0')
65
+ end
66
+ end
67
+
68
+ describe "#parse_tokens" do
69
+ it "recognizes a DFHMDF macro with a label" do
70
+ @screen_def.parse_tokens([ 'FIELDNAME', 'DFHMDF', 'POS=(4,5),LENGTH=15', 'bar' ])
71
+ expect(@screen_def.dfhmdf?).to be(true)
72
+ end
73
+ end
74
+
75
+ describe "#parse_tokens" do
76
+ it "populates the field label when one is specified" do
77
+ @screen_def.parse_tokens([ 'FIELDNAME', 'DFHMDF', 'POS=(4,5),LENGTH=15', 'bar' ])
78
+ expect(@screen_def.field_label).to eq('fieldname')
79
+ end
80
+ end
81
+
82
+ describe "#parse_tokens" do
83
+ it "ignores source lines that do not contain a DFHMDF macro" do
84
+ @screen_def.parse_tokens [ 'foo', 'bar', 'DFHMDF', 'baz' ]
85
+ expect(@screen_def.dfhmdf?).to eq(false)
86
+ end
87
+ end
88
+ end
89
+
90
+ context "parsing macro operands" do
91
+ describe "#parse_operands" do
92
+ it "handles simple key-value pairs" do
93
+ expect(@screen_def.parse_operands("KEY1=15,KEY2=30"))
94
+ .to eq({ :key1 => "15", :key2 => "30" })
95
+ end
96
+
97
+ it "handles operands with quoted values" do
98
+ expect(@screen_def.parse_operands("KEY1='Quoted value 1',KEY2='Quoted value 2'"))
99
+ .to eq({ :key1 => "Quoted value 1", :key2 => "Quoted value 2" })
100
+ end
101
+
102
+ it "handles operands with comma-separated values in parentheses" do
103
+ expect(@screen_def.parse_operands("KEY1=(one,two),KEY2=(three,four)"))
104
+ .to eq({ :key1 => [ "one", "two" ], :key2 => [ "three", "four" ] })
105
+ end
106
+
107
+ it "handles a mix of operand formats" do
108
+ expect(@screen_def.parse_operands("POS=(6,18),LENGTH=14,ATTRB=(ASKIP,NORM),INITIAL='Hello there'"))
109
+ .to eq({ :pos => [ "6", "18" ], :length => "14", :attrb => [ "ASKIP", "NORM" ], :initial => "Hello there" })
110
+ end
111
+ end
112
+ end
113
+
114
+ context "determining field label" do
115
+ describe "#field_label" do
116
+ it "returns the field label that was specified on the DFHMDF macro" do
117
+ @screen_def.field_label = 'NAME'
118
+ expect(@screen_def.field_label).to eq('NAME')
119
+ end
120
+
121
+ it "derives a field label based on x and y coordinates when no label was specified" do
122
+ @screen_def.field_label = nil
123
+ @screen_def.operands_hash( { :pos => [ "5", "18" ] })
124
+ expect(@screen_def.field_label).to eq('x6y18')
125
+ end
126
+ end
127
+ end
128
+
129
+ context "determining field position" do
130
+ describe "#x_coordinate" do
131
+ it "returns 0 as the x coordinate if the position has not been determined" do
132
+ expect(@screen_def.x_coordinate).to eq(0)
133
+ end
134
+
135
+ it "returns 0 as the x coordinate if POS=(x,y) was not specified" do
136
+ @screen_def.operands_hash( { :foo => "bar" } )
137
+ expect(@screen_def.x_coordinate).to eq(0)
138
+ end
139
+
140
+ it "calculates the x coordinate value skipping the attribute byte" do
141
+ @screen_def.operands_hash( { :pos => ["5", "28"] } )
142
+ expect(@screen_def.x_coordinate).to eq(6)
143
+ end
144
+ end
145
+
146
+ describe "#y_coordinate" do
147
+ it "returns 0 as the y coordinate if the position has not been determined" do
148
+ expect(@screen_def.y_coordinate).to eq(0)
149
+ end
150
+
151
+ it "returns 0 as the y coordinate if POS=(x,y) was not specified" do
152
+ @screen_def.operands_hash( { :foo => "bar" } )
153
+ expect(@screen_def.y_coordinate).to eq(0)
154
+ end
155
+
156
+ it "returns the y coordinate value from the POS=(x,y) parameter" do
157
+ @screen_def.operands_hash( { :pos => ["5", "28"] } )
158
+ expect(@screen_def.y_coordinate).to eq(28)
159
+ end
160
+ end
161
+ end
162
+
163
+ describe "determining field length" do
164
+ describe "handling the LENGTH= parameter of the DFHMDF macro" do
165
+ it "returns 0 as the length if the length has not been determined" do
166
+ expect(@screen_def.field_length).to eq(0)
167
+ end
168
+
169
+ it "returns 0 as the length if the length was not specified" do
170
+ @screen_def.operands_hash( { :foo => "bar" } )
171
+ expect(@screen_def.field_length).to eq(0)
172
+ end
173
+
174
+ it "returns the length value from the LENGTH= parameter" do
175
+ @screen_def.operands_hash( { :length => "34" })
176
+ expect(@screen_def.field_length).to eq(34)
177
+ end
178
+ end
179
+
180
+ describe "handling the PICOUT= parameter of the DFHMDF macro" do
181
+ it "derives the length based on the PICOUT value" do
182
+ @screen_def.operands_hash( { :picout => "$,$$0.00" })
183
+ expect(@screen_def.field_length).to eq(8)
184
+ end
185
+ end
186
+ end
187
+
188
+ describe "generating a text_field definition" do
189
+ it "generates a text_field definition for a field with a LENGTH= specification" do
190
+ @screen_def.field_label = 'myfield'
191
+ @screen_def.operands_hash({ :pos => [ "23", "6" ], :length => "14" })
192
+ expect(@screen_def.te3270_text_field).to eql('text_field(:myfield, 24, 6, 14)')
193
+ end
194
+
195
+ it "generates a text_field definition for a field with a PICOUT= specification" do
196
+ @screen_def.field_label = 'otherfld'
197
+ @screen_def.operands_hash({ :pos => [ "8", "16" ], :picout => "$$,$$0.00" })
198
+ expect(@screen_def.te3270_text_field).to eql('text_field(:otherfld, 9, 16, 9)')
199
+ end
200
+
201
+ it "generates a text_field definition for a field with INITIAL= and no LENGTH=" do
202
+ @screen_def.field_label = 'otherfld'
203
+ @screen_def.operands_hash({ :pos => [ "8", "16" ], :initial => "Hello" })
204
+ expect(@screen_def.te3270_text_field).to eql('text_field(:otherfld, 9, 16, 5)')
205
+ end
206
+ end
207
+
208
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'dfhmdf'
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dfhmdf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dave Nicolette
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Generate text_field specifications for te3270 based on DFHMDF source
42
+ email:
43
+ - davenicolette@gmail.com
44
+ executables:
45
+ - dfhmdf
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - Gemspec
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - bin/dfhmdf
56
+ - dfhmdf.gemspec
57
+ - lib/convert_dfhmdf.rb
58
+ - lib/dfhmdf.rb
59
+ - lib/dfhmdf/version.rb
60
+ - sample-macros
61
+ - spec/lib/dfhmdf/convert_dfhmdf_spec.rb
62
+ - spec/lib/dfhmdf/dfhmdf_spec.rb
63
+ - spec/spec_helper.rb
64
+ homepage: http://github.com/neopragma/dfhmdf
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.2.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Interprets DFHMDF macros
88
+ test_files:
89
+ - spec/lib/dfhmdf/convert_dfhmdf_spec.rb
90
+ - spec/lib/dfhmdf/dfhmdf_spec.rb
91
+ - spec/spec_helper.rb