fto 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.
- data/CONTRIBUTORS.txt +5 -0
- data/LICENCE.txt +202 -0
- data/README.txt +75 -0
- data/doc/classes/FormatText.html +120 -0
- data/doc/classes/FormatText/Context.html +240 -0
- data/doc/classes/FormatText/Context.src/M000001.html +26 -0
- data/doc/classes/FormatText/Context.src/M000004.html +26 -0
- data/doc/classes/FormatText/Context.src/M000007.html +26 -0
- data/doc/classes/FormatText/Context.src/M000008.html +26 -0
- data/doc/classes/FormatText/Context.src/M000009.html +26 -0
- data/doc/classes/FormatText/Effector.html +411 -0
- data/doc/classes/FormatText/Effector.src/M000004.html +38 -0
- data/doc/classes/FormatText/Effector.src/M000005.html +39 -0
- data/doc/classes/FormatText/Effector.src/M000007.html +38 -0
- data/doc/classes/FormatText/Effector.src/M000008.html +42 -0
- data/doc/classes/FormatText/Effector.src/M000009.html +43 -0
- data/doc/classes/FormatText/Effector.src/M000010.html +19 -0
- data/doc/classes/FormatText/Effector.src/M000011.html +18 -0
- data/doc/classes/FormatText/Effector.src/M000012.html +19 -0
- data/doc/classes/FormatText/Effector.src/M000013.html +18 -0
- data/doc/classes/FormatText/Effector.src/M000014.html +18 -0
- data/doc/classes/FormatText/FTO.html +305 -0
- data/doc/classes/FormatText/FTO.src/M000001.html +19 -0
- data/doc/classes/FormatText/FTO.src/M000002.html +34 -0
- data/doc/classes/FormatText/FTO.src/M000003.html +22 -0
- data/doc/classes/FormatText/FTO.src/M000004.html +19 -0
- data/doc/classes/FormatText/FTO.src/M000005.html +22 -0
- data/doc/classes/FormatText/FTO.src/M000006.html +20 -0
- data/doc/classes/FormatText/FTO.src/M000007.html +63 -0
- data/doc/classes/FormatText/FTO.src/M000008.html +63 -0
- data/doc/created.rid +1 -0
- data/doc/files/fto_rb.html +141 -0
- data/doc/files/lib/fto_rb.html +150 -0
- data/doc/fr_class_index.html +30 -0
- data/doc/fr_file_index.html +27 -0
- data/doc/fr_method_index.html +39 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/fto.rb +1349 -0
- data/test/test_fto_api.rb +143 -0
- data/test/test_fto_effectors.rb +440 -0
- data/test/test_helper.rb +3 -0
- metadata +115 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Classes
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Classes</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Classes</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/FormatText.html">FormatText</a><br />
|
24
|
+
<a href="classes/FormatText/Context.html">FormatText::Context</a><br />
|
25
|
+
<a href="classes/FormatText/Effector.html">FormatText::Effector</a><br />
|
26
|
+
<a href="classes/FormatText/FTO.html">FormatText::FTO</a><br />
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
</body>
|
30
|
+
</html>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Files
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Files</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Files</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="files/lib/fto_rb.html">lib/fto.rb</a><br />
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</body>
|
27
|
+
</html>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/FormatText/FTO.html#M000004">destroyEffector (FormatText::FTO)</a><br />
|
24
|
+
<a href="classes/FormatText/Effector.html#M000010">disable (FormatText::Effector)</a><br />
|
25
|
+
<a href="classes/FormatText/FTO.html#M000005">disableEffector (FormatText::FTO)</a><br />
|
26
|
+
<a href="classes/FormatText/Effector.html#M000011">disabled? (FormatText::Effector)</a><br />
|
27
|
+
<a href="classes/FormatText/Effector.html#M000012">enable (FormatText::Effector)</a><br />
|
28
|
+
<a href="classes/FormatText/FTO.html#M000003">enableEffector (FormatText::FTO)</a><br />
|
29
|
+
<a href="classes/FormatText/Effector.html#M000013">enabled? (FormatText::Effector)</a><br />
|
30
|
+
<a href="classes/FormatText/FTO.html#M000006">findEffectors (FormatText::FTO)</a><br />
|
31
|
+
<a href="classes/FormatText/FTO.html#M000007">format (FormatText::FTO)</a><br />
|
32
|
+
<a href="classes/FormatText/Effector.html#M000009">new (FormatText::Effector)</a><br />
|
33
|
+
<a href="classes/FormatText/Context.html#M000008">new (FormatText::Context)</a><br />
|
34
|
+
<a href="classes/FormatText/FTO.html#M000001">new (FormatText::FTO)</a><br />
|
35
|
+
<a href="classes/FormatText/FTO.html#M000002">registerEffector (FormatText::FTO)</a><br />
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</body>
|
39
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
RDoc Documentation
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>RDoc Documentation</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="files/lib/fto_rb.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
data/doc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
data/lib/fto.rb
ADDED
@@ -0,0 +1,1349 @@
|
|
1
|
+
#
|
2
|
+
# = fto.rb - Formatted Text Output
|
3
|
+
#
|
4
|
+
# Author:: Ken Coar
|
5
|
+
# Copyright:: Copyright © 2009 Ken Coar
|
6
|
+
# License:: Apache Licence 2.0
|
7
|
+
#
|
8
|
+
# == Synopsis
|
9
|
+
#
|
10
|
+
# require 'fto'
|
11
|
+
# include FormatText
|
12
|
+
# formatString = FTO.new("This will include a string: !AS", "string1")
|
13
|
+
# puts formatString.format
|
14
|
+
# puts formatString.format("string2")
|
15
|
+
#
|
16
|
+
# == Description
|
17
|
+
#
|
18
|
+
# FTO is a Ruby library for formatting text strings. In function it
|
19
|
+
# is similar to <tt>printf(3)</tt>; however, the syntax of the format
|
20
|
+
# effectors (sometimes called 'format descriptors') and the selection
|
21
|
+
# of effectors bundled with the package are based on the SYS$FAO
|
22
|
+
# user-mode system service found on OpenVMS.
|
23
|
+
#
|
24
|
+
# The FTO class is an extension of String, enhancing the constructor,
|
25
|
+
# adding the <i>format()</i> instance method, and the
|
26
|
+
# <i>registerEffector()</i> class method.
|
27
|
+
#
|
28
|
+
# In addition to the included list of effectors, FTO provides easy
|
29
|
+
# extensibility by allowing the developer to write her own effector
|
30
|
+
# handlers and registering them with <i>FTO.registerEffector()</i>.
|
31
|
+
#
|
32
|
+
#--
|
33
|
+
# Copyright 2009 Ken Coar
|
34
|
+
#
|
35
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
36
|
+
# may not use this file except in compliance with the License. You may
|
37
|
+
# obtain a copy of the License at
|
38
|
+
#
|
39
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
40
|
+
#
|
41
|
+
# Unless required by applicable law or agreed to in writing, software
|
42
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
43
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
44
|
+
# implied. See the License for the specific language governing
|
45
|
+
# permissions and limitations under the License.
|
46
|
+
#++
|
47
|
+
|
48
|
+
|
49
|
+
#--
|
50
|
+
# Notes about markup (docco being hard to find). This will be deleted
|
51
|
+
# ere long.
|
52
|
+
#
|
53
|
+
# \:arg:, \:args:
|
54
|
+
#
|
55
|
+
# \:call-seq:
|
56
|
+
# Alternative(s) to default invocation built by rdoc
|
57
|
+
#
|
58
|
+
# \:doc:
|
59
|
+
#
|
60
|
+
# \:enddoc:
|
61
|
+
# Stop documenting the current tree of items
|
62
|
+
#
|
63
|
+
# \:include:
|
64
|
+
# Pull in another file.
|
65
|
+
#
|
66
|
+
# \:main:
|
67
|
+
#
|
68
|
+
# \:nodoc: all
|
69
|
+
#
|
70
|
+
# \:nodoc:
|
71
|
+
# Temporarily turn off rdoc interpretation
|
72
|
+
#
|
73
|
+
# \:notnew:, \:not_new:, \:not-new:
|
74
|
+
# Document constructor as 'initialize' rather than as 'new'
|
75
|
+
#
|
76
|
+
# \:section:
|
77
|
+
#
|
78
|
+
# \:title:
|
79
|
+
# Duh.
|
80
|
+
#
|
81
|
+
# \:yield:, \:yields:
|
82
|
+
# Display an alternative to the automatic 'yields' rdoc makes up
|
83
|
+
#
|
84
|
+
# Stuff from SYS$FAO that isn't yet implemented (and may not be
|
85
|
+
# reasonable outside of OpenVMS).
|
86
|
+
#
|
87
|
+
# @TODO: !%T Inserts the system time. It takes one parameter: the
|
88
|
+
# address of a quadword time value to be converted to
|
89
|
+
# ASCII. If you specify 0, the current system time is
|
90
|
+
# inserted.
|
91
|
+
# @TODO: !%D Inserts the system date and time. It takes one
|
92
|
+
# parameter: the address of a quadword time value to be
|
93
|
+
# converted to ASCII. If you specify 0, the current system
|
94
|
+
# date and time is inserted.
|
95
|
+
# @TODO: !n%C Inserts a character string when the most recently
|
96
|
+
# evaluated argument has the value n. (Recommended for use
|
97
|
+
# with multilingual products.)
|
98
|
+
# @TODO: !%E Inserts a character string when the value of the most
|
99
|
+
# recently evaluated argument does not match any preceding
|
100
|
+
# !n%C directives. (Recommended for use with multilingual
|
101
|
+
# products.)
|
102
|
+
# @TODO: !%F Makes the end of a plurals statement.
|
103
|
+
#
|
104
|
+
#++
|
105
|
+
|
106
|
+
require 'rubygems'
|
107
|
+
require 'gettext'
|
108
|
+
|
109
|
+
module FormatText
|
110
|
+
|
111
|
+
include GetText
|
112
|
+
|
113
|
+
#
|
114
|
+
# Each time an effector's pattern is matched, its _code_ attribute
|
115
|
+
# is called with this structure, which is used to communicate
|
116
|
+
# details to the code block, and by the code block to pass back some
|
117
|
+
# behaviour modification notes. Most of the attributes should be
|
118
|
+
# treated as read-only, with exceptions noted below in the attribute
|
119
|
+
# descriptions.
|
120
|
+
#
|
121
|
+
# This class is used internally by the +fto+ library and isn't
|
122
|
+
# really intended for external consumption.
|
123
|
+
#
|
124
|
+
class Context
|
125
|
+
|
126
|
+
#
|
127
|
+
# <i>FormatText::Effector object</i>. The _Effector_ object
|
128
|
+
# involved. Read-only.
|
129
|
+
#
|
130
|
+
attr_accessor :effectorObj
|
131
|
+
|
132
|
+
#
|
133
|
+
# <i>FTO object</i>. The _FTO_ object being processed.
|
134
|
+
# Read-only.
|
135
|
+
#
|
136
|
+
attr_accessor :ftoObj
|
137
|
+
|
138
|
+
#
|
139
|
+
# _String_. The string that matched the effector and triggered
|
140
|
+
# its processing. Read-only.
|
141
|
+
#
|
142
|
+
attr_accessor :sMatched
|
143
|
+
|
144
|
+
#
|
145
|
+
# _Array_. Arguments remaining to be processed. Usually
|
146
|
+
# read-only, but see the description of the _usedArgs_ attribute
|
147
|
+
# for exceptions.
|
148
|
+
#
|
149
|
+
attr_accessor :usedArgs
|
150
|
+
|
151
|
+
#
|
152
|
+
# _Array_. List of arguments already processed. Usually
|
153
|
+
# read-only. The effector function is responsible for using the
|
154
|
+
# values in this array to perform its task.
|
155
|
+
#
|
156
|
+
# The only time this should be considered read/write is when the
|
157
|
+
# effector is intended to modify the list of arguments being used
|
158
|
+
# to build the final string. The _argList_ attribute should be
|
159
|
+
# modified in conjunction with _usedArgs_ to maintain continuity.
|
160
|
+
# By default, after the effector function returns, the caller (the
|
161
|
+
# <i>FTO#format</i> method) will take the element from the front
|
162
|
+
# of the _argList_ array and push it onto the end of the
|
163
|
+
# _usedArgs_ array.
|
164
|
+
#
|
165
|
+
attr_accessor :argList
|
166
|
+
|
167
|
+
#
|
168
|
+
# _Boolean_. The effector function sets this to +true+ to inhibit
|
169
|
+
# the <i>FTO#format()</i> method from modifying the argument list
|
170
|
+
# after the function returns. See the descriptions under the
|
171
|
+
# _argList_ and _usedArgs_ attributes.
|
172
|
+
#
|
173
|
+
attr_accessor :reuseArg
|
174
|
+
|
175
|
+
#
|
176
|
+
# Create a new <i>FormatText::Context</i> object. There may only
|
177
|
+
# be a single argument to the constructor, and it must be a hash,
|
178
|
+
# using symbols for the names of the attributes to set:
|
179
|
+
#
|
180
|
+
# x = FormatText::Context.new({ :sMatched => 'string', :reuseArg => false })
|
181
|
+
#
|
182
|
+
# This class is used internally by the +fto+ library and isn't
|
183
|
+
# really intended for external consumption.
|
184
|
+
#
|
185
|
+
# :call-seq:
|
186
|
+
# new<i>(Hash)</i> => <i>FormatText::Context object</i>
|
187
|
+
#
|
188
|
+
def initialize(*argsp)
|
189
|
+
(@effectorObj, @ftoObj) = nil
|
190
|
+
@sMatched = ''
|
191
|
+
@usedArgs = []
|
192
|
+
@argList = []
|
193
|
+
@reuseArg = false
|
194
|
+
if (argsp[0].class != Hash)
|
195
|
+
raise RuntimeError, self.class.name + _(' requires a Hash to create')
|
196
|
+
end
|
197
|
+
argsp[0].each { |key,val| eval("self.#{key.to_s} = val") }
|
198
|
+
end # def initialize
|
199
|
+
|
200
|
+
end # class Context
|
201
|
+
|
202
|
+
#
|
203
|
+
# = Description
|
204
|
+
#
|
205
|
+
# The _FTO_ class is the user interface; all others are for
|
206
|
+
# developers modifying or extending the +fto+ library.
|
207
|
+
#
|
208
|
+
# _FTO_ is a subclass of _String_, so all _String_ methods work on
|
209
|
+
# an _FTO_ object. _FTO_ provides the additional <i>format()</i>
|
210
|
+
# method.
|
211
|
+
#
|
212
|
+
# In addition to string text, the constructor (<i>FTO.new</i>) can
|
213
|
+
# take more than a single argument. Additional arguments will be
|
214
|
+
# stored as part of the object and will be available to the
|
215
|
+
# <i>FTO#format()</i> method at runtime.
|
216
|
+
#
|
217
|
+
# An _FTO_ object can be created as just a formatting string, or the
|
218
|
+
# constructor invocation can also include values to be applied by
|
219
|
+
# the <i>FTO#format()</i> method. At runtime the <i>format()</i> method
|
220
|
+
# can override any argument list provided at instantiation, but the
|
221
|
+
# latter is not lost.
|
222
|
+
#
|
223
|
+
class FTO < String
|
224
|
+
|
225
|
+
#
|
226
|
+
# Class variables
|
227
|
+
#
|
228
|
+
|
229
|
+
#
|
230
|
+
# Hash of all registered effector objects, keyed by their IDs.
|
231
|
+
#
|
232
|
+
@@RegisteredEffectors = {} unless (defined?(@@RegisteredEffectors))
|
233
|
+
|
234
|
+
#
|
235
|
+
# Hash of all currently enabled effectors, keyed by their sort
|
236
|
+
# key.
|
237
|
+
#
|
238
|
+
@@EnabledEffectors = {} unless (defined?(@@EnabledEffectors))
|
239
|
+
|
240
|
+
#
|
241
|
+
# Ordered array of effector keys (used to index
|
242
|
+
# @@EnabledEffectors)
|
243
|
+
#
|
244
|
+
@@EffectorKeys = [] unless (defined?(@@EffectorKeys))
|
245
|
+
|
246
|
+
# :stopdoc:
|
247
|
+
#
|
248
|
+
# We do this in order to call super on String, but since our
|
249
|
+
# argument list is different, we need to finesse it a little.
|
250
|
+
# Nobody's business but ours.
|
251
|
+
#
|
252
|
+
alias_method(:String_initialize, :initialize) # :nodoc:
|
253
|
+
# :startdoc:
|
254
|
+
|
255
|
+
#
|
256
|
+
# Debugging class method to access list of registered effectors
|
257
|
+
#
|
258
|
+
def self.effectors() # :nodoc:
|
259
|
+
@@RegisteredEffectors
|
260
|
+
end # def self.effectors()
|
261
|
+
|
262
|
+
#
|
263
|
+
# Debugging class method to access list of effector keys.
|
264
|
+
#
|
265
|
+
def self.eKeys() # :nodoc:
|
266
|
+
@@EffectorKeys
|
267
|
+
end # def self.eKeys()
|
268
|
+
|
269
|
+
#
|
270
|
+
# Debugging class method to access regular expression used to find
|
271
|
+
# effectors.
|
272
|
+
#
|
273
|
+
def self.regex() # :nodoc:
|
274
|
+
@@regex
|
275
|
+
end # def self.regex()
|
276
|
+
|
277
|
+
#
|
278
|
+
# Any argument list is supplied at object instantiation can be
|
279
|
+
# temporarily overridden when the <i>FTO#format()</i> method is
|
280
|
+
# invoked.
|
281
|
+
#
|
282
|
+
# :call-seq:
|
283
|
+
# new<i>()</i> => <i>FTO object</i>
|
284
|
+
# new<i>(String)</i> => <i>FTO object</i>
|
285
|
+
# new<i>(String, arg [, ...])</i> => <i>FTO object</i>
|
286
|
+
#
|
287
|
+
def initialize(text=nil, *args)
|
288
|
+
String_initialize(text)
|
289
|
+
@args = args
|
290
|
+
end # def initialize
|
291
|
+
|
292
|
+
#
|
293
|
+
# Add an effector description to the list of those which will be
|
294
|
+
# processed by the <i>FTO#format()</i> method.
|
295
|
+
#
|
296
|
+
# :call-seq:
|
297
|
+
# FTO.registerEffector<i>(FormatText::Effector)</i> => <i>nil</i>
|
298
|
+
# FTO.registerEffector<i>({ :symattr => value [, ...] })</i> => <i>nil</i>
|
299
|
+
#
|
300
|
+
def self.registerEffector(*args)
|
301
|
+
if ((args.length == 1) && (args[0].class.name.match(/Effector$/))
|
302
|
+
newE = args[0]
|
303
|
+
else
|
304
|
+
newE = Effector.new('placeholder')
|
305
|
+
if ((args.length == 1) && (args[0].class == Hash))
|
306
|
+
args[0].each do |key,val|
|
307
|
+
eval("newE.#{key.to_s} = val")
|
308
|
+
end
|
309
|
+
else
|
310
|
+
newE = Effector.new(args)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
@@RegisteredEffectors[newE.id] = newE
|
314
|
+
key = sprintf('%06d-%s', newE.priority, newE.name)
|
315
|
+
newE.sortKey = key
|
316
|
+
self.rebuildEffectorList()
|
317
|
+
nil
|
318
|
+
end # def self.registerEffector()
|
319
|
+
|
320
|
+
# :stopdoc:
|
321
|
+
#
|
322
|
+
# This class method rebuilds the regular expression and the hash
|
323
|
+
# of enabled effectors. It needs to be invoked any time an
|
324
|
+
# effector is added, destroyed, enabled, or disabled. It's for
|
325
|
+
# internal use only.
|
326
|
+
#
|
327
|
+
def self.rebuildEffectorList()
|
328
|
+
enabled = @@RegisteredEffectors.select { |id,e| e.enabled? }
|
329
|
+
@@EffectorKeys = enabled.collect { |k,e| e.sortKey }.sort
|
330
|
+
@@EnabledEffectors = {}
|
331
|
+
enabled.each { |k,e| @@EnabledEffectors[e.sortKey] = e }
|
332
|
+
@@regex = Regexp.new("(#{@@EffectorKeys.collect {|k| @@EnabledEffectors[k].reMatch}.join(')|(')})")
|
333
|
+
nil
|
334
|
+
end # def self.rebuildEffectorList()
|
335
|
+
# :startdoc:
|
336
|
+
|
337
|
+
#
|
338
|
+
# Enables the effector with the specified ID (found in the
|
339
|
+
# effector's _id_ attribute). This is a no-op if the effector is
|
340
|
+
# already enabled.
|
341
|
+
#
|
342
|
+
# :call-seq:
|
343
|
+
# FTO.enableEffector<i>(Fixnum)</i> => <i>nil</i>
|
344
|
+
#
|
345
|
+
def self.enableEffector(id)
|
346
|
+
if ((e = @@RegisteredEffectors[id]).nil?)
|
347
|
+
raise RuntimeError, _('No such effector ') + "ID\##{id}"
|
348
|
+
end
|
349
|
+
e.enabled = true
|
350
|
+
self.rebuildEffectorList()
|
351
|
+
end # def self.enableEffector()
|
352
|
+
|
353
|
+
#
|
354
|
+
# Completely removes the effector with the specified ID from the
|
355
|
+
# FTO system. <strong>THIS IS NOT REVERSIBLE!</strong>
|
356
|
+
#
|
357
|
+
# :call-seq:
|
358
|
+
# FTO.destroyEffector<i>(Fixnum)</i> => <i>nil</i>
|
359
|
+
#
|
360
|
+
def self.destroyEffector(id)
|
361
|
+
@@RegisteredEffectors.delete(id)
|
362
|
+
self.rebuildEffectorList()
|
363
|
+
end # def self.destroyEffector()
|
364
|
+
|
365
|
+
#
|
366
|
+
# Disables the effector with the specified ID (such as from
|
367
|
+
# <i>FTO.findEffectors()</i>). This is a no-op if the effector is
|
368
|
+
# already disabled.
|
369
|
+
#
|
370
|
+
# :call-seq:
|
371
|
+
# FTO.disableEffector<i>(Fixnum)</i> => <i>nil</i>
|
372
|
+
#
|
373
|
+
def self.disableEffector(id)
|
374
|
+
if ((e = @@RegisteredEffectors[id]).nil?)
|
375
|
+
raise RuntimeError, _('No such effector ') + "ID\##{id}"
|
376
|
+
end
|
377
|
+
e.disable
|
378
|
+
nil
|
379
|
+
end # def self.disableEffector()
|
380
|
+
|
381
|
+
#
|
382
|
+
# Returns an array of registered effectors whose names (_name_
|
383
|
+
# attribute) match the specified pattern.
|
384
|
+
#
|
385
|
+
# :call-seq:
|
386
|
+
# FTO.findEffectors<i>(String)</i> => <i>Array</i>
|
387
|
+
# FTO.findEffectors<i>(Regexp)</i> => <i>Array</i>
|
388
|
+
#
|
389
|
+
def self.findEffectors(pattern)
|
390
|
+
pattern = Regexp.new(pattern) unless (pattern.class == Regexp)
|
391
|
+
matches = @@RegisteredEffectors.select { |id,e| e.name.match(pattern) }
|
392
|
+
matches.collect { |id,e| e }
|
393
|
+
end # def self.findEffector()
|
394
|
+
|
395
|
+
#
|
396
|
+
# Process the formatting string, optionally with a runtime
|
397
|
+
# argument list. The argument list can either be a list of
|
398
|
+
# values, an array of values, or an <i>FormatText::Context</i>
|
399
|
+
# object. (The latter is intended only for internal use with
|
400
|
+
# recursion.)
|
401
|
+
#
|
402
|
+
# :call-seq:
|
403
|
+
# format<i>()</i> => <i>String</i>
|
404
|
+
# format<i>(arg [, ...])</i> => <i>String</i>
|
405
|
+
# format<i>(Array)</i> => <i>String</i>
|
406
|
+
# format<i>(FormatText::Context)</i> => <i>String</i> (<u>internal use only</u>)
|
407
|
+
#
|
408
|
+
def format(*argListp)
|
409
|
+
argList = argListp.empty? ? @args.clone : argListp
|
410
|
+
if ((argList.length == 1) && (argList[0].class == Array)) &&
|
411
|
+
argList = argList[0]
|
412
|
+
end
|
413
|
+
#
|
414
|
+
# It's possible we were passed a Context object so we can
|
415
|
+
# recurse. If so, use its values for some of these.
|
416
|
+
#
|
417
|
+
if ((argList.length == 1) && (argList[0].class == FormatText::Context))
|
418
|
+
eContext = argList[0]
|
419
|
+
usedArgs = eContext.usedArgs
|
420
|
+
argList = eContext.argList
|
421
|
+
else
|
422
|
+
usedArgs = []
|
423
|
+
eContext = Context.new({
|
424
|
+
:ftoObj => self,
|
425
|
+
:usedArgs => usedArgs,
|
426
|
+
:argList => argList
|
427
|
+
})
|
428
|
+
end
|
429
|
+
result = self.to_s
|
430
|
+
effector = sMatched = nil
|
431
|
+
while (m = result.match(@@regex))
|
432
|
+
#
|
433
|
+
# Find out which effector was matched. The index in .captures
|
434
|
+
# will be the same as the index in @effectors.
|
435
|
+
#
|
436
|
+
m.captures.length.times do |i|
|
437
|
+
next if (m.captures[i].nil?)
|
438
|
+
eContext.effectorObj = effector = @@EnabledEffectors[@@EffectorKeys[i]]
|
439
|
+
eContext.sMatched = sMatched = m.captures[i]
|
440
|
+
eContext.reuseArg = false
|
441
|
+
break
|
442
|
+
end
|
443
|
+
#
|
444
|
+
# Call the workhorse for this descriptor
|
445
|
+
#
|
446
|
+
replacement = effector.code.call(eContext)
|
447
|
+
result.sub!(sMatched, replacement)
|
448
|
+
#
|
449
|
+
# Mark the item at the front of the argument list as having
|
450
|
+
# been used, if the effector agrees.
|
451
|
+
#
|
452
|
+
usedArgs.push(argList.shift) unless (eContext.reuseArg)
|
453
|
+
end
|
454
|
+
result
|
455
|
+
end # def format()
|
456
|
+
|
457
|
+
end # class FTO
|
458
|
+
|
459
|
+
#
|
460
|
+
# Class used to describe a format effector. The
|
461
|
+
# <i>FormatText::Effector</i> class is basically a container rather
|
462
|
+
# than an active class. It holds information about how an effector
|
463
|
+
# operates and what it needs.
|
464
|
+
#
|
465
|
+
# Typically <i>FormatText::Effector</i> objects aren't created
|
466
|
+
# directly, but by calling <i>FTO.registerEffector()</i>.
|
467
|
+
#
|
468
|
+
class Effector
|
469
|
+
|
470
|
+
@@NEXTID = 1 unless (defined?(@@NEXTID))
|
471
|
+
|
472
|
+
#
|
473
|
+
# _Fixnum_. ID number assigned to the effector, unique within a
|
474
|
+
# usage environment. Used by <i>FTO.enableEffector()</i>,
|
475
|
+
# <i>FTO.disableEffector()</i>, and <i>FTO.destroyEffector()</i>.
|
476
|
+
#
|
477
|
+
attr_reader :id
|
478
|
+
|
479
|
+
#
|
480
|
+
# _Boolean_. Whether this effector should be processed or
|
481
|
+
# ignored.
|
482
|
+
#
|
483
|
+
attr_accessor :enabled
|
484
|
+
|
485
|
+
#
|
486
|
+
# _String_. Human-readable name for what the effector does. Used
|
487
|
+
# for sorting.
|
488
|
+
#
|
489
|
+
attr_accessor :name
|
490
|
+
|
491
|
+
#
|
492
|
+
# _String_. Human-readable brief description.
|
493
|
+
#
|
494
|
+
attr_accessor :description
|
495
|
+
|
496
|
+
#
|
497
|
+
# _Fixnum_. Numeric priority value for sorting purposes.
|
498
|
+
#
|
499
|
+
attr_accessor :priority
|
500
|
+
|
501
|
+
#
|
502
|
+
# _String_. Key used to sort effectors, built from the name and
|
503
|
+
# priority.
|
504
|
+
#
|
505
|
+
attr_accessor :sortKey
|
506
|
+
|
507
|
+
#
|
508
|
+
# _String_. Regular expression used to recognise the effector in
|
509
|
+
# the format string.
|
510
|
+
#
|
511
|
+
attr_accessor :reMatch
|
512
|
+
|
513
|
+
#
|
514
|
+
# _String_. Optional regex pattern used to extract additional info
|
515
|
+
# (such as a field width).
|
516
|
+
#
|
517
|
+
attr_accessor :reExtra
|
518
|
+
|
519
|
+
#
|
520
|
+
# _Integer_. [<i>Numeric conversion effectors only</i>] If the
|
521
|
+
# effector is used to represent a number, this is a mask of the
|
522
|
+
# bits to be included. For instance, if the effector only
|
523
|
+
# displays 8-bit values, this value would be <tt>0xFF</tt>.
|
524
|
+
#
|
525
|
+
attr_accessor :mask
|
526
|
+
|
527
|
+
#
|
528
|
+
# _Integer_. [<i>Numeric conversion effectors only</i>] If the
|
529
|
+
# value is to be interpreted as signed, this is a mask for the
|
530
|
+
# sign bit. (For a byte, <tt>:mask</tt> would be <tt>0xFF</tt>
|
531
|
+
# and <tt>:signbit</tt> would be <tt>0x80</tt>.)
|
532
|
+
#
|
533
|
+
attr_accessor :signbit
|
534
|
+
|
535
|
+
#
|
536
|
+
# _Fixnum_. Default width for the effector result (used when
|
537
|
+
# filling).
|
538
|
+
#
|
539
|
+
attr_accessor :dWidth
|
540
|
+
|
541
|
+
#
|
542
|
+
# _Any_. Default value (used if _argList_ has been exhausted).
|
543
|
+
#
|
544
|
+
attr_accessor :dValue
|
545
|
+
|
546
|
+
#
|
547
|
+
# _String_. Character used to fill values shorter than the field
|
548
|
+
# widths.
|
549
|
+
#
|
550
|
+
attr_accessor :fill
|
551
|
+
|
552
|
+
#
|
553
|
+
# _Symbol_. Symbol value <tt>:left</tt> or <tt>:right</tt>,
|
554
|
+
# indicating against which edge of a too-wide field the value
|
555
|
+
# should abut.
|
556
|
+
#
|
557
|
+
attr_accessor :justify
|
558
|
+
|
559
|
+
#
|
560
|
+
# _Symbol_. Symbol value <tt>:left</tt> or <tt>:right</tt>
|
561
|
+
# indicating on which side too-wide results should be truncated to
|
562
|
+
# fit within the field width.
|
563
|
+
#
|
564
|
+
attr_accessor :truncate
|
565
|
+
|
566
|
+
#
|
567
|
+
# _Array_. Array of additional info for the function
|
568
|
+
# (effector-specific).
|
569
|
+
#
|
570
|
+
attr_accessor :data
|
571
|
+
|
572
|
+
#
|
573
|
+
# _Proc_. Code block (<i>e.g.</i>, a +lambda+ function) that
|
574
|
+
# actually interprets the effector. (See the
|
575
|
+
# <i>FormatText::Context</i> class for a description, or the
|
576
|
+
# various +Convert+ constants in the source.)
|
577
|
+
#
|
578
|
+
attr_accessor :code
|
579
|
+
|
580
|
+
#
|
581
|
+
# Creates a new <i>FormatText::Effector</i> object. The argument
|
582
|
+
# list can be either an order-dependent list of attribute values,
|
583
|
+
# or a hash using the symbolised attribute names as the keys.
|
584
|
+
#
|
585
|
+
# call-seq:
|
586
|
+
# new<i>(Hash)</i> => <i>FormatText::Effector object</i>
|
587
|
+
# new<i>(name, description, enabled, priority, code, reMatch, reExtra, mask, signbit, dWidth, fill, justify, truncate, data)</i> => <i>FormatText::Effector object</i>
|
588
|
+
#
|
589
|
+
def initialize(*argsp)
|
590
|
+
@id = @@NEXTID
|
591
|
+
@@NEXTID += 1
|
592
|
+
#
|
593
|
+
# Set up defaults
|
594
|
+
#
|
595
|
+
(@name, @description, @code, @reMatch, @reExtra, @mask,
|
596
|
+
@signbit, @dWidth, @dValue, @truncate) = nil
|
597
|
+
@enabled = true
|
598
|
+
@priority = 1000
|
599
|
+
@data = []
|
600
|
+
@fill = ' '
|
601
|
+
@justify = :left
|
602
|
+
#
|
603
|
+
# We can either handle an order-dependent list of arguments, or
|
604
|
+
# a hash representing keyword arguments.
|
605
|
+
#
|
606
|
+
args = (argsp.length == 1) ? argsp[0] : argsp
|
607
|
+
case args.class
|
608
|
+
when Array
|
609
|
+
(@name, @description, @enabled, @priority, @code, @reMatch,
|
610
|
+
@reExtra, @mask, @signbit, @dWidth, @fill, @justify,
|
611
|
+
@truncate, @data) = args
|
612
|
+
when Hash
|
613
|
+
args.each { |key,val| eval("@{key.to_s} = val") }
|
614
|
+
end
|
615
|
+
@data = [@data] unless (@data.nil? || (@data.class == Array))
|
616
|
+
end # def initialize
|
617
|
+
|
618
|
+
#
|
619
|
+
# Disables the effector, removing it from consideration when the
|
620
|
+
# format string is being scanned. It can be subsequently
|
621
|
+
# re-enabled with the <i>Effector#enable()</i> method. This is a
|
622
|
+
# no-op if the effector is already disabled.
|
623
|
+
#
|
624
|
+
# :call-seq:
|
625
|
+
# disable<i>()</i> => <i>nil</i>
|
626
|
+
#
|
627
|
+
def disable()
|
628
|
+
@enabled = false
|
629
|
+
FTO.rebuildEffectorList()
|
630
|
+
end # def disable()
|
631
|
+
|
632
|
+
#
|
633
|
+
# Returns +true+ if the effector is disabled (<i>i.e.</i>,
|
634
|
+
# inactive and not considered when scanning the format string);
|
635
|
+
# otherwise returns +false+.
|
636
|
+
#
|
637
|
+
# :call-seq:
|
638
|
+
# disabled? => <i>Boolean</i>
|
639
|
+
#
|
640
|
+
def disabled?()
|
641
|
+
! @enabled
|
642
|
+
end # def disabled?()
|
643
|
+
|
644
|
+
#
|
645
|
+
# Enables the effector, making certain that it is considered when
|
646
|
+
# the format string is being scanned. This is a no-op if the
|
647
|
+
# effector is already active.
|
648
|
+
#
|
649
|
+
# :call-seq:
|
650
|
+
# enable<i>()</i> => <i>nil</i>
|
651
|
+
#
|
652
|
+
def enable()
|
653
|
+
@enabled = true
|
654
|
+
FTO.rebuildEffectorList()
|
655
|
+
end # def enable()
|
656
|
+
|
657
|
+
#
|
658
|
+
# Returns +true+ if the effector is enabled (<i>i.e.</i>,
|
659
|
+
# active and considered when scanning the format string);
|
660
|
+
# otherwise returns +false+.
|
661
|
+
#
|
662
|
+
# :call-seq:
|
663
|
+
# enabled? => <i>Boolean</i>
|
664
|
+
#
|
665
|
+
def enabled?()
|
666
|
+
@enabled
|
667
|
+
end # def enabled?()
|
668
|
+
|
669
|
+
end # class Effector
|
670
|
+
|
671
|
+
# :stopdoc:
|
672
|
+
#
|
673
|
+
# Lambda functions (for no particular reason) used by effectors.
|
674
|
+
#
|
675
|
+
|
676
|
+
#
|
677
|
+
# Handle filling, justifying, and truncating.
|
678
|
+
#
|
679
|
+
FillAndJustify = lambda {
|
680
|
+
| eObj, rText, width, overflowChar |
|
681
|
+
overflowChar = '*' if (overflowChar.nil?)
|
682
|
+
if ((! width.nil?) && (width.to_s.length != 0))
|
683
|
+
width = width.to_i
|
684
|
+
else
|
685
|
+
width = eObj.dWidth
|
686
|
+
end
|
687
|
+
return rText if (width.nil?)
|
688
|
+
width = width.to_i
|
689
|
+
if (rText.length > width)
|
690
|
+
case eObj.truncate
|
691
|
+
when :right
|
692
|
+
rText = rText[0,width]
|
693
|
+
when :left
|
694
|
+
rText = rText[rText.length - width,width]
|
695
|
+
else
|
696
|
+
rText = overflowChar * width
|
697
|
+
end
|
698
|
+
else
|
699
|
+
#
|
700
|
+
# The result is shorter than the width. How do we make up the
|
701
|
+
# difference?
|
702
|
+
#
|
703
|
+
fill = eObj.fill * (width - rText.length)
|
704
|
+
case eObj.justify
|
705
|
+
when :left then rText += fill
|
706
|
+
when :right then rText = fill + rText
|
707
|
+
end
|
708
|
+
end
|
709
|
+
rText
|
710
|
+
}
|
711
|
+
|
712
|
+
#
|
713
|
+
# Get the next argument, use the default, or raise an exception.
|
714
|
+
#
|
715
|
+
GetArgument = lambda {
|
716
|
+
| eContext |
|
717
|
+
if (! eContext.argList.empty?)
|
718
|
+
arg = eContext.argList.first
|
719
|
+
elsif ((arg = eContext.effectorObj.dValue).nil?)
|
720
|
+
raise RuntimeError,
|
721
|
+
_('Insufficient arguments to format ') + "'#{eContext.ftoObj}'"
|
722
|
+
end
|
723
|
+
arg
|
724
|
+
}
|
725
|
+
|
726
|
+
#
|
727
|
+
# Predefined conversion functions. The function is passed a Context
|
728
|
+
# object (defined above).
|
729
|
+
#
|
730
|
+
# The function is responsible for getting its argument from
|
731
|
+
# argList.first. It can modify usedArgs, argList, and reuseArg, but
|
732
|
+
# this should be done with caution.
|
733
|
+
#
|
734
|
+
# The function's return value is the formatted quantity.
|
735
|
+
#
|
736
|
+
|
737
|
+
#
|
738
|
+
# Placeholder effector function.
|
739
|
+
#
|
740
|
+
ConvertTBD = lambda {
|
741
|
+
| eContext |
|
742
|
+
eContext.reuseArg = true
|
743
|
+
return 'TBD'
|
744
|
+
}
|
745
|
+
|
746
|
+
ConvertFixedWindow = lambda {
|
747
|
+
| eContext |
|
748
|
+
eObj = eContext.effectorObj
|
749
|
+
parcels = eContext.sMatched.match(Regexp.new(eObj.reExtra))
|
750
|
+
width = parcels.captures[0].sub(/</, '').to_i
|
751
|
+
#
|
752
|
+
# Clone the Context because we want to retain the arglist array
|
753
|
+
# identities, but don't want to mess up any of the other aspects
|
754
|
+
# needed by our caller.
|
755
|
+
#
|
756
|
+
f = FTO.new(parcels.captures[1], eContext.clone)
|
757
|
+
sNext = f.format
|
758
|
+
if ((diff = width - sNext.length) <= 0)
|
759
|
+
sNext = sNext[diff.abs,width]
|
760
|
+
else
|
761
|
+
sNext = (' ' * diff) + sNext
|
762
|
+
end
|
763
|
+
eContext.reuseArg = true
|
764
|
+
sNext
|
765
|
+
}
|
766
|
+
|
767
|
+
#
|
768
|
+
# Convert a numeric argument of some sort.
|
769
|
+
#
|
770
|
+
ConvertNumeric = lambda {
|
771
|
+
| eContext |
|
772
|
+
eObj = eContext.effectorObj
|
773
|
+
#
|
774
|
+
# This bit of funk is so we can correctly handle a string like
|
775
|
+
# '0xABC'.
|
776
|
+
#
|
777
|
+
thisArg = eval("#{GetArgument.call(eContext)}").to_i & eObj.mask
|
778
|
+
#
|
779
|
+
# Sign-extend the value if appropriate.
|
780
|
+
#
|
781
|
+
if ((! eObj.signbit.nil?) && ((thisArg & eObj.signbit) != 0))
|
782
|
+
thisArg |= ~ eObj.mask
|
783
|
+
end
|
784
|
+
#
|
785
|
+
# See if we need to convert to a non-decimal base.
|
786
|
+
#
|
787
|
+
case true
|
788
|
+
when eObj.data.include?(:octal) then replacement = thisArg.to_s(8)
|
789
|
+
when eObj.data.include?(:hex) then replacement = thisArg.to_s(16).upcase
|
790
|
+
else replacement = thisArg.to_s
|
791
|
+
end
|
792
|
+
width = eContext.sMatched.match(Regexp.new(eObj.reExtra)).captures[0]
|
793
|
+
FillAndJustify.call(eObj, replacement, width, '*')
|
794
|
+
}
|
795
|
+
|
796
|
+
#
|
797
|
+
# Insert a string
|
798
|
+
#
|
799
|
+
ConvertString = lambda {
|
800
|
+
| eContext |
|
801
|
+
eObj = eContext.effectorObj
|
802
|
+
if (eObj.data.include?(:lengthAsArg))
|
803
|
+
strLen = GetArgument.call(eContext)
|
804
|
+
eContext.usedArgs.push(eContext.argList.shift)
|
805
|
+
end
|
806
|
+
replacement = GetArgument.call(eContext)
|
807
|
+
unless (strLen.nil?)
|
808
|
+
if (strLen <= replacement.length)
|
809
|
+
replacement = replacement[0,strLen]
|
810
|
+
else
|
811
|
+
replacement += "\000" * (strLen - replacement.length)
|
812
|
+
end
|
813
|
+
end
|
814
|
+
replacement.gsub!(/[^[:print:]]/, '.') if (eObj.data.include?(:printable))
|
815
|
+
eObj = eContext.effectorObj
|
816
|
+
width = eContext.sMatched.match(Regexp.new(eObj.reExtra)).captures[0]
|
817
|
+
FillAndJustify.call(eObj, replacement, width, '*')
|
818
|
+
}
|
819
|
+
|
820
|
+
#
|
821
|
+
# Insert a repeating character.
|
822
|
+
#
|
823
|
+
ConvertRepeatChar = lambda {
|
824
|
+
| eContext |
|
825
|
+
eContext.reuseArg = true
|
826
|
+
eObj = eContext.effectorObj
|
827
|
+
exInfo = eContext.sMatched.match(Regexp.new(eObj.reExtra))
|
828
|
+
width = exInfo.captures[0].to_i
|
829
|
+
replacement = exInfo.captures[1] * width
|
830
|
+
return replacement
|
831
|
+
}
|
832
|
+
|
833
|
+
ConvertIsAre = lambda {
|
834
|
+
| eContext |
|
835
|
+
#
|
836
|
+
# We don't actually use the argument list, so we need to make sure
|
837
|
+
# the argument pointer doesn't get advanced.
|
838
|
+
#
|
839
|
+
eContext.reuseArg = true
|
840
|
+
result = (eContext.usedArgs.last == 1) ? _('is') : _('are')
|
841
|
+
result.upcase! if (eContext.sMatched == '!%IS')
|
842
|
+
return result
|
843
|
+
}
|
844
|
+
|
845
|
+
ConvertPlural = lambda {
|
846
|
+
| eContext |
|
847
|
+
#
|
848
|
+
# We don't actually use the argument list, so we need to make sure
|
849
|
+
# the argument pointer doesn't get advanced.
|
850
|
+
#
|
851
|
+
eContext.reuseArg = true
|
852
|
+
m2 = eContext.sMatched.match(Regexp.new(eContext.effectorObj.reExtra))
|
853
|
+
return '' if (m2.captures[0].nil?)
|
854
|
+
return m2.captures[0] if (eContext.usedArgs.last == 1)
|
855
|
+
result = (m2.captures[0].upcase == 'S') ? 'es' : 's'
|
856
|
+
result.upcase! if (m2.captures[0].match(/[A-Z]/))
|
857
|
+
return m2.captures[0] + result
|
858
|
+
}
|
859
|
+
|
860
|
+
# :startdoc:
|
861
|
+
|
862
|
+
#
|
863
|
+
# Start registering the standard effectors.
|
864
|
+
#
|
865
|
+
|
866
|
+
#
|
867
|
+
# The simple replacements ('insert a TAB', etc.)
|
868
|
+
#
|
869
|
+
FTO.registerEffector({
|
870
|
+
:name => 'TAB',
|
871
|
+
:description => _('Insert a TAB character'),
|
872
|
+
:reMatch => '!_',
|
873
|
+
:code => lambda {
|
874
|
+
| eContext |
|
875
|
+
eContext.reuseArg = true
|
876
|
+
return "\011"
|
877
|
+
}
|
878
|
+
})
|
879
|
+
FTO.registerEffector({
|
880
|
+
:name => 'Bang',
|
881
|
+
:description => _('Insert an exclamation mark ' +
|
882
|
+
'(!) character'),
|
883
|
+
:reMatch => '!!',
|
884
|
+
:code => lambda {
|
885
|
+
| eContext |
|
886
|
+
eContext.reuseArg = true
|
887
|
+
return '!'
|
888
|
+
}
|
889
|
+
})
|
890
|
+
FTO.registerEffector({
|
891
|
+
:name => 'Formfeed',
|
892
|
+
:description => _('Insert a form-feed control ' +
|
893
|
+
'character'),
|
894
|
+
:reMatch => '!\^',
|
895
|
+
:code => lambda {
|
896
|
+
| eContext |
|
897
|
+
eContext.reuseArg = true
|
898
|
+
return "\014"
|
899
|
+
}
|
900
|
+
})
|
901
|
+
FTO.registerEffector({
|
902
|
+
:name => 'CR',
|
903
|
+
:description => _('Insert a carriage-return ' +
|
904
|
+
'character'),
|
905
|
+
:reMatch => '!=',
|
906
|
+
:code => lambda {
|
907
|
+
| eContext |
|
908
|
+
eContext.reuseArg = true
|
909
|
+
return "\015"
|
910
|
+
}
|
911
|
+
})
|
912
|
+
FTO.registerEffector({
|
913
|
+
:name => 'LF',
|
914
|
+
:description => _('Insert a line-feed control ' +
|
915
|
+
'character'),
|
916
|
+
:reMatch => '!,',
|
917
|
+
:code => lambda {
|
918
|
+
| eContext |
|
919
|
+
eContext.reuseArg = true
|
920
|
+
return "\012"
|
921
|
+
}
|
922
|
+
})
|
923
|
+
FTO.registerEffector({
|
924
|
+
:name => 'CRLF',
|
925
|
+
:description => _('Insert a carriage-return and ' +
|
926
|
+
'a line-feed'),
|
927
|
+
:reMatch => '!/',
|
928
|
+
:code => lambda {
|
929
|
+
| eContext |
|
930
|
+
eContext.reuseArg = true
|
931
|
+
return "\015\012"
|
932
|
+
}
|
933
|
+
})
|
934
|
+
|
935
|
+
#
|
936
|
+
# Effectors that frob the argument list.
|
937
|
+
#
|
938
|
+
FTO.registerEffector({
|
939
|
+
:name => 'Reuse',
|
940
|
+
:description => _('Back the argument list up ' +
|
941
|
+
'so the last argument gets re-used'),
|
942
|
+
:reMatch => '!-',
|
943
|
+
:code => lambda {
|
944
|
+
| eContext |
|
945
|
+
eContext.reuseArg = true
|
946
|
+
eContext.argList.unshift(eContext.usedArgs.pop) unless (eContext.usedArgs.empty?)
|
947
|
+
return ''
|
948
|
+
}
|
949
|
+
})
|
950
|
+
FTO.registerEffector({
|
951
|
+
:name => 'Skip',
|
952
|
+
:description => _('Skip over the next item in ' +
|
953
|
+
'the argument list'),
|
954
|
+
:reMatch => '!\+',
|
955
|
+
:code => lambda {
|
956
|
+
| eContext |
|
957
|
+
eContext.usedArgs.push(eContext.argList.unshift) unless (eContext.argList.empty?)
|
958
|
+
return ''
|
959
|
+
}
|
960
|
+
})
|
961
|
+
FTO.registerEffector({
|
962
|
+
:name => 'ArgWidth',
|
963
|
+
:description => _('Specify a field width using ' +
|
964
|
+
'an argument rather than a ' +
|
965
|
+
'hard-coded value'),
|
966
|
+
:reMatch => '!#',
|
967
|
+
:code => lambda {
|
968
|
+
| eContext |
|
969
|
+
n = GetArgument.call(eContext)
|
970
|
+
return "!#{n.to_i.to_s}"
|
971
|
+
}
|
972
|
+
})
|
973
|
+
FTO.registerEffector({
|
974
|
+
:name => 'RepeatingChar',
|
975
|
+
:description => _('Insert n occurrences of ' +
|
976
|
+
'a character'),
|
977
|
+
:reMatch => '!\d+\*.',
|
978
|
+
:reExtra => '!(\d+)\*(.)',
|
979
|
+
:code => ConvertRepeatChar,
|
980
|
+
})
|
981
|
+
FTO.registerEffector({
|
982
|
+
:name => 'Pluralise-English',
|
983
|
+
:description => _('Add an "s" or "es" suffix if ' +
|
984
|
+
'the last argument used was not 1'),
|
985
|
+
:reMatch => '.?!%S',
|
986
|
+
:reExtra => '(.)?!%S',
|
987
|
+
:code => ConvertPlural,
|
988
|
+
})
|
989
|
+
FTO.registerEffector({
|
990
|
+
:name => 'is/are-English',
|
991
|
+
:description => _('Insert "is" or "are" depending ' +
|
992
|
+
'on whether the last argument ' +
|
993
|
+
'used was 1'),
|
994
|
+
:reMatch => '!%is',
|
995
|
+
:code => ConvertIsAre,
|
996
|
+
})
|
997
|
+
FTO.registerEffector({
|
998
|
+
:name => 'IS/ARE-English',
|
999
|
+
:description => _('Insert n occurrences of a ' +
|
1000
|
+
'character'),
|
1001
|
+
:reMatch => '!%IS',
|
1002
|
+
:code => ConvertIsAre,
|
1003
|
+
})
|
1004
|
+
|
1005
|
+
FTO.registerEffector({
|
1006
|
+
:name => 'Fixed Window',
|
1007
|
+
:description => _('Force a right-justified field ' +
|
1008
|
+
'width on the contents between ' +
|
1009
|
+
'the effector delimiters'),
|
1010
|
+
:priority => 10,
|
1011
|
+
:reMatch => '!\d+<.*!>',
|
1012
|
+
:reExtra => '!(\d+<)(.*)(!>)',
|
1013
|
+
:fill => ' ',
|
1014
|
+
:truncate => :right,
|
1015
|
+
:justify => :right,
|
1016
|
+
:code => ConvertFixedWindow,
|
1017
|
+
})
|
1018
|
+
#
|
1019
|
+
# Strings
|
1020
|
+
#
|
1021
|
+
FTO.registerEffector({
|
1022
|
+
:name => 'String AS',
|
1023
|
+
:description => _('Insert a simple string'),
|
1024
|
+
:reMatch => '!\d*AS',
|
1025
|
+
:reExtra => '!(\d*)AS',
|
1026
|
+
:fill => ' ',
|
1027
|
+
:truncate => :right,
|
1028
|
+
:data => [:AS],
|
1029
|
+
:code => ConvertString,
|
1030
|
+
})
|
1031
|
+
FTO.registerEffector({
|
1032
|
+
:name => 'String AN',
|
1033
|
+
:description => _('Insert a simple string, ' +
|
1034
|
+
'replacing non-printing ' +
|
1035
|
+
'characters with "."'),
|
1036
|
+
:reMatch => '!\d*AN',
|
1037
|
+
:reExtra => '!(\d*)AN',
|
1038
|
+
:fill => ' ',
|
1039
|
+
:truncate => :right,
|
1040
|
+
:data => [:AS, :printable],
|
1041
|
+
:code => ConvertString,
|
1042
|
+
})
|
1043
|
+
FTO.registerEffector({
|
1044
|
+
:name => 'String AD',
|
1045
|
+
:description => _('Insert the first n characters ' +
|
1046
|
+
'of a string, drawing n from the ' +
|
1047
|
+
'argument list'),
|
1048
|
+
:reMatch => '!\d*AD',
|
1049
|
+
:reExtra => '!(\d*)AD',
|
1050
|
+
:fill => ' ',
|
1051
|
+
:truncate => :right,
|
1052
|
+
:data => [:lengthAsArg],
|
1053
|
+
:code => ConvertString,
|
1054
|
+
})
|
1055
|
+
FTO.registerEffector({
|
1056
|
+
:name => 'String AF',
|
1057
|
+
:description => _('Insert the first n characters ' +
|
1058
|
+
'of a string, drawing n from the ' +
|
1059
|
+
'argument list and replacing ' +
|
1060
|
+
'non-printing characters with "."'),
|
1061
|
+
:reMatch => '!\d*AF',
|
1062
|
+
:reExtra => '!(\d*)AF',
|
1063
|
+
:fill => ' ',
|
1064
|
+
:truncate => :right,
|
1065
|
+
:data => [:lengthAsArg, :printable],
|
1066
|
+
:code => ConvertString,
|
1067
|
+
})
|
1068
|
+
FTO.registerEffector({
|
1069
|
+
:name => 'Byte: unsigned',
|
1070
|
+
:description => _('Insert the decimal ' +
|
1071
|
+
'representation of an unsigned ' +
|
1072
|
+
'8-bit value, left space-filled ' +
|
1073
|
+
'to the field width'),
|
1074
|
+
:reMatch => '!\d*UB',
|
1075
|
+
:reExtra => '!(\d*)UB',
|
1076
|
+
:mask => 0xFF,
|
1077
|
+
:code => ConvertNumeric,
|
1078
|
+
})
|
1079
|
+
FTO.registerEffector({
|
1080
|
+
:name => 'Byte: unsigned, zero-filled',
|
1081
|
+
:description => _('Insert the decimal ' +
|
1082
|
+
'representation of an unsigned ' +
|
1083
|
+
'8-bit value, left zero-filled ' +
|
1084
|
+
'to the field width'),
|
1085
|
+
:reMatch => '!\d*ZB',
|
1086
|
+
:reExtra => '!(\d*)ZB',
|
1087
|
+
:mask => 0xFF,
|
1088
|
+
:fill => '0',
|
1089
|
+
:justify => :right,
|
1090
|
+
:code => ConvertNumeric,
|
1091
|
+
})
|
1092
|
+
FTO.registerEffector({
|
1093
|
+
:name => 'Byte: signed',
|
1094
|
+
:description => _('Insert the decimal ' +
|
1095
|
+
'representation of a signed ' +
|
1096
|
+
'8-bit value, left space-filled ' +
|
1097
|
+
'to the field width'),
|
1098
|
+
:reMatch => '!\d*SB',
|
1099
|
+
:reExtra => '!(\d*)SB',
|
1100
|
+
:mask => 0xFF,
|
1101
|
+
:signbit => 0x80,
|
1102
|
+
:code => ConvertNumeric,
|
1103
|
+
})
|
1104
|
+
FTO.registerEffector({
|
1105
|
+
:name => 'Byte: octal',
|
1106
|
+
:description => _('Insert the octal ' +
|
1107
|
+
'representation of an unsigned ' +
|
1108
|
+
'8-bit value, left zero-filled ' +
|
1109
|
+
'to the field width (default ' +
|
1110
|
+
'3)'),
|
1111
|
+
:reMatch => '!\d*OB',
|
1112
|
+
:reExtra => '!(\d*)OB',
|
1113
|
+
:mask => 0xFF,
|
1114
|
+
:dWidth => 3,
|
1115
|
+
:fill => '0',
|
1116
|
+
:justify => :right,
|
1117
|
+
:truncate => :left,
|
1118
|
+
:data => [:octal],
|
1119
|
+
:code => ConvertNumeric,
|
1120
|
+
})
|
1121
|
+
FTO.registerEffector({
|
1122
|
+
:name => 'Byte: hex',
|
1123
|
+
:description => _('Insert the hexadecimal ' +
|
1124
|
+
'representation of an unsigned ' +
|
1125
|
+
'8-bit value, left zero-filled ' +
|
1126
|
+
'to the field width (default ' +
|
1127
|
+
'2)'),
|
1128
|
+
:reMatch => '!\d*XB',
|
1129
|
+
:reExtra => '!(\d*)XB',
|
1130
|
+
:mask => 0xFF,
|
1131
|
+
:dWidth => 2,
|
1132
|
+
:fill => '0',
|
1133
|
+
:justify => :right,
|
1134
|
+
:truncate => :left,
|
1135
|
+
:data => [:hex],
|
1136
|
+
:code => ConvertNumeric,
|
1137
|
+
})
|
1138
|
+
FTO.registerEffector({
|
1139
|
+
:name => 'Word: unsigned',
|
1140
|
+
:description => _('Insert the decimal ' +
|
1141
|
+
'representation of an unsigned ' +
|
1142
|
+
'8-bit value, left space-filled ' +
|
1143
|
+
'to the field width'),
|
1144
|
+
:reMatch => '!\d*UW',
|
1145
|
+
:reExtra => '!(\d*)UW',
|
1146
|
+
:mask => 0xFFFF,
|
1147
|
+
:code => ConvertNumeric,
|
1148
|
+
})
|
1149
|
+
FTO.registerEffector({
|
1150
|
+
:name => 'Word: unsigned, zero-filled',
|
1151
|
+
:description => _('Insert the decimal ' +
|
1152
|
+
'representation of an unsigned ' +
|
1153
|
+
'8-bit value, left zero-filled ' +
|
1154
|
+
'to the field width'),
|
1155
|
+
:reMatch => '!\d*ZW',
|
1156
|
+
:reExtra => '!(\d*)ZW',
|
1157
|
+
:mask => 0xFFFF,
|
1158
|
+
:fill => '0',
|
1159
|
+
:justify => :right,
|
1160
|
+
:code => ConvertNumeric,
|
1161
|
+
})
|
1162
|
+
FTO.registerEffector({
|
1163
|
+
:name => 'Word: signed',
|
1164
|
+
:description => _('Insert the decimal ' +
|
1165
|
+
'representation of a signed ' +
|
1166
|
+
'16-bit value, left space-filled ' +
|
1167
|
+
'to the field width'),
|
1168
|
+
:reMatch => '!\d*SW',
|
1169
|
+
:reExtra => '!(\d*)SW',
|
1170
|
+
:mask => 0xFFFF,
|
1171
|
+
:signbit => 0x8000,
|
1172
|
+
:code => ConvertNumeric,
|
1173
|
+
})
|
1174
|
+
FTO.registerEffector({
|
1175
|
+
:name => 'Word: octal',
|
1176
|
+
:description => _('Insert the octal ' +
|
1177
|
+
'representation of an unsigned ' +
|
1178
|
+
'16-bit value, left zero-filled ' +
|
1179
|
+
'to the field width (default ' +
|
1180
|
+
'6)'),
|
1181
|
+
:reMatch => '!\d*OW',
|
1182
|
+
:reExtra => '!(\d*)OW',
|
1183
|
+
:mask => 0xFFFF,
|
1184
|
+
:dWidth => 6,
|
1185
|
+
:fill => '0',
|
1186
|
+
:justify => :right,
|
1187
|
+
:truncate => :left,
|
1188
|
+
:data => [:octal],
|
1189
|
+
:code => ConvertNumeric,
|
1190
|
+
})
|
1191
|
+
FTO.registerEffector({
|
1192
|
+
:name => 'Word: hex',
|
1193
|
+
:description => _('Insert the hexadecimal ' +
|
1194
|
+
'representation of an unsigned ' +
|
1195
|
+
'16-bit value, left zero-filled ' +
|
1196
|
+
'to the field width (default ' +
|
1197
|
+
'4)'),
|
1198
|
+
:reMatch => '!\d*XW',
|
1199
|
+
:reExtra => '!(\d*)XW',
|
1200
|
+
:mask => 0xFFFF,
|
1201
|
+
:dWidth => 4,
|
1202
|
+
:fill => '0',
|
1203
|
+
:justify => :right,
|
1204
|
+
:truncate => :left,
|
1205
|
+
:data => [:hex],
|
1206
|
+
:code => ConvertNumeric,
|
1207
|
+
})
|
1208
|
+
FTO.registerEffector({
|
1209
|
+
:name => 'Long: unsigned',
|
1210
|
+
:description => _('Insert the decimal ' +
|
1211
|
+
'representation of an unsigned ' +
|
1212
|
+
'8-bit value, left space-filled ' +
|
1213
|
+
'to the field width'),
|
1214
|
+
:reMatch => '!\d*UL',
|
1215
|
+
:reExtra => '!(\d*)UL',
|
1216
|
+
:mask => 0xFFFFFFFF,
|
1217
|
+
:code => ConvertNumeric,
|
1218
|
+
})
|
1219
|
+
FTO.registerEffector({
|
1220
|
+
:name => 'Long: unsigned, zero-filled',
|
1221
|
+
:description => _('Insert the decimal ' +
|
1222
|
+
'representation of an unsigned ' +
|
1223
|
+
'8-bit value, left zero-filled ' +
|
1224
|
+
'to the field width'),
|
1225
|
+
:reMatch => '!\d*ZL',
|
1226
|
+
:reExtra => '!(\d*)ZL',
|
1227
|
+
:mask => 0xFFFFFFFF,
|
1228
|
+
:fill => '0',
|
1229
|
+
:justify => :right,
|
1230
|
+
:code => ConvertNumeric,
|
1231
|
+
})
|
1232
|
+
FTO.registerEffector({
|
1233
|
+
:name => 'Long: signed',
|
1234
|
+
:description => _('Insert the decimal ' +
|
1235
|
+
'representation of a signed ' +
|
1236
|
+
'32-bit value, left space-filled ' +
|
1237
|
+
'to the field width'),
|
1238
|
+
:reMatch => '!\d*SL',
|
1239
|
+
:reExtra => '!(\d*)SL',
|
1240
|
+
:mask => 0xFFFFFFFF,
|
1241
|
+
:signbit => 0x80000000,
|
1242
|
+
:code => ConvertNumeric,
|
1243
|
+
})
|
1244
|
+
FTO.registerEffector({
|
1245
|
+
:name => 'Long: octal',
|
1246
|
+
:description => _('Insert the octal ' +
|
1247
|
+
'representation of an unsigned ' +
|
1248
|
+
'32-bit value, left zero-filled ' +
|
1249
|
+
'to the field width (default ' +
|
1250
|
+
'11)'),
|
1251
|
+
:reMatch => '!\d*OL',
|
1252
|
+
:reExtra => '!(\d*)OL',
|
1253
|
+
:mask => 0xFFFFFFFF,
|
1254
|
+
:dWidth => 11,
|
1255
|
+
:fill => '0',
|
1256
|
+
:justify => :right,
|
1257
|
+
:truncate => :left,
|
1258
|
+
:data => [:octal],
|
1259
|
+
:code => ConvertNumeric,
|
1260
|
+
})
|
1261
|
+
FTO.registerEffector({
|
1262
|
+
:name => 'Long: hex',
|
1263
|
+
:description => _('Insert the hexadecimal ' +
|
1264
|
+
'representation of an unsigned ' +
|
1265
|
+
'32-bit value, left zero-filled ' +
|
1266
|
+
'to the field width (default ' +
|
1267
|
+
'8)'),
|
1268
|
+
:reMatch => '!\d*XL',
|
1269
|
+
:reExtra => '!(\d*)XL',
|
1270
|
+
:mask => 0xFFFFFFFF,
|
1271
|
+
:dWidth => 8,
|
1272
|
+
:fill => '0',
|
1273
|
+
:justify => :right,
|
1274
|
+
:truncate => :left,
|
1275
|
+
:data => [:hex],
|
1276
|
+
:code => ConvertNumeric,
|
1277
|
+
})
|
1278
|
+
FTO.registerEffector({
|
1279
|
+
:name => 'Quadword: unsigned',
|
1280
|
+
:description => _('Insert the decimal ' +
|
1281
|
+
'representation of an unsigned ' +
|
1282
|
+
'8-bit value, left space-filled ' +
|
1283
|
+
'to the field width'),
|
1284
|
+
:reMatch => '!\d*UQ',
|
1285
|
+
:reExtra => '!(\d*)UQ',
|
1286
|
+
:mask => 0xFFFFFFFFFFFFFFFF,
|
1287
|
+
:code => ConvertNumeric,
|
1288
|
+
})
|
1289
|
+
FTO.registerEffector({
|
1290
|
+
:name => 'Quadword: unsigned, zero-filled',
|
1291
|
+
:description => _('Insert the decimal ' +
|
1292
|
+
'representation of an unsigned ' +
|
1293
|
+
'8-bit value, left zero-filled ' +
|
1294
|
+
'to the field width'),
|
1295
|
+
:reMatch => '!\d*ZQ',
|
1296
|
+
:reExtra => '!(\d*)ZQ',
|
1297
|
+
:mask => 0xFFFFFFFFFFFFFFFF,
|
1298
|
+
:fill => '0',
|
1299
|
+
:justify => :right,
|
1300
|
+
:code => ConvertNumeric,
|
1301
|
+
})
|
1302
|
+
FTO.registerEffector({
|
1303
|
+
:name => 'Quadword: signed',
|
1304
|
+
:description => _('Insert the decimal ' +
|
1305
|
+
'representation of a signed ' +
|
1306
|
+
'64-bit value, left space-filled ' +
|
1307
|
+
'to the field width'),
|
1308
|
+
:reMatch => '!\d*SQ',
|
1309
|
+
:reExtra => '!(\d*)SQ',
|
1310
|
+
:mask => 0xFFFFFFFFFFFFFFFF,
|
1311
|
+
:signbit => 0x8000000000000000,
|
1312
|
+
:code => ConvertNumeric,
|
1313
|
+
})
|
1314
|
+
FTO.registerEffector({
|
1315
|
+
:name => 'Quadword: octal',
|
1316
|
+
:description => _('Insert the octal ' +
|
1317
|
+
'representation of an unsigned ' +
|
1318
|
+
'64-bit value, left zero-filled ' +
|
1319
|
+
'to the field width (default ' +
|
1320
|
+
'22)'),
|
1321
|
+
:reMatch => '!\d*OQ',
|
1322
|
+
:reExtra => '!(\d*)OQ',
|
1323
|
+
:mask => 0xFFFFFFFFFFFFFFFF,
|
1324
|
+
:dWidth => 22,
|
1325
|
+
:fill => '0',
|
1326
|
+
:justify => :right,
|
1327
|
+
:truncate => :left,
|
1328
|
+
:data => [:octal],
|
1329
|
+
:code => ConvertNumeric,
|
1330
|
+
})
|
1331
|
+
FTO.registerEffector({
|
1332
|
+
:name => 'Quadword: hex',
|
1333
|
+
:description => _('Insert the hexadecimal ' +
|
1334
|
+
'representation of an unsigned ' +
|
1335
|
+
'64-bit value, left zero-filled ' +
|
1336
|
+
'to the field width (default ' +
|
1337
|
+
'16)'),
|
1338
|
+
:reMatch => '!\d*XQ',
|
1339
|
+
:reExtra => '!(\d*)XQ',
|
1340
|
+
:mask => 0xFFFFFFFFFFFFFFFF,
|
1341
|
+
:dWidth => 16,
|
1342
|
+
:fill => '0',
|
1343
|
+
:justify => :right,
|
1344
|
+
:truncate => :left,
|
1345
|
+
:data => [:hex],
|
1346
|
+
:code => ConvertNumeric,
|
1347
|
+
})
|
1348
|
+
|
1349
|
+
end # module FTO
|