rotuka-rutils 0.2.4

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.
@@ -0,0 +1,321 @@
1
+ module RuTils
2
+ module Gilenson
3
+ end
4
+ end
5
+
6
+ # Это - прямой порт Тыпографицы от pixelapes.
7
+ # Настройки можно регулировать через методы, т.е.
8
+ #
9
+ # typ = RuTils::Gilenson::Obsolete.new('Эти "так называемые" великие деятели')
10
+ # typ.html = false => "false"
11
+ # typ.dash = true => "true"
12
+ # typ.to_html => 'Эти «так называемые» великие деятели'
13
+ # Ни обновляться ни поддерживаться этот модуль более не будет.
14
+ class RuTils::Gilenson::Obsolete
15
+ def initialize(text, *args)
16
+ @_text = text
17
+ @skip_tags = true;
18
+ @p_prefix = "<p class=typo>";
19
+ @p_postfix = "</p>";
20
+ @a_soft = true;
21
+ @indent_a = "images/z.gif width=25 height=1 border=0 alt=\'\' align=top />" # <->
22
+ @indent_b = "images/z.gif width=50 height=1 border=0 alt=\'\' align=top />" # <-->
23
+ @fixed_size = 80 # максимальная ширина
24
+ @ignore = /notypo/ # regex, который игнорируется. Этим надо воспользоваться для обработки pre и code
25
+
26
+ @de_nobr = true;
27
+
28
+ @phonemasks = [[ /([0-9]{4})\-([0-9]{2})\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/,
29
+ /([0-9]{4})\-([0-9]{2})\-([0-9]{2})/,
30
+ /(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
31
+ /(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
32
+ /(\([0-9\+\-]+\)) ?([0-9]{3})\-([0-9]{2})/,
33
+ /(\([0-9\+\-]+\)) ?([0-9]{2})\-([0-9]{3})/,
34
+ /([0-9]{3})\-([0-9]{2})\-([0-9]{2})/,
35
+ /([0-9]{2})\-([0-9]{2})\-([0-9]{2})/,
36
+ /([0-9]{1})\-([0-9]{2})\-([0-9]{2})/,
37
+ /([0-9]{2})\-([0-9]{3})/,
38
+ /([0-9]+)\-([0-9]+)/,
39
+ ],[
40
+ '<nobr>\1&ndash;\2&ndash;\3&nbsp;\4:\5:\6</nobr>',
41
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
42
+ '<nobr>\1&nbsp;\2&ndash;\3&ndash;\4</nobr>',
43
+ '<nobr>\1&nbsp;\2&ndash;\3&ndash;\4</nobr>',
44
+ '<nobr>\1&nbsp;\2&ndash;\3</nobr>',
45
+ '<nobr>\1&nbsp;\2&ndash;\3</nobr>',
46
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
47
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
48
+ '<nobr>\1&ndash;\2&ndash;\3</nobr>',
49
+ '<nobr>\1&ndash;\2</nobr>',
50
+ '<nobr>\1&ndash;\2</nobr>'
51
+ ]]
52
+
53
+ @glueleft = ['рис.', 'табл.', 'см.', 'им.', 'ул.', 'пер.', 'кв.', 'офис', 'оф.', 'г.']
54
+ @glueright = ['руб.', 'коп.', 'у.е.', 'мин.']
55
+
56
+ @settings = {
57
+ "inches" => true, # преобразовывать дюймы в &quot;
58
+ "laquo" => true, # кавычки-ёлочки
59
+ "farlaquo" => false, # кавычки-ёлочки для фара (знаки "больше-меньше")
60
+ "quotes" => true, # кавычки-английские лапки
61
+ "dash" => true, # короткое тире (150)
62
+ "emdash" => true, # длинное тире двумя минусами (151)
63
+ "(c)" => true,
64
+ "(r)" => true,
65
+ "(tm)" => true,
66
+ "(p)" => true,
67
+ "+-" => true, # спецсимволы, какие - понятно
68
+ "degrees" => true, # знак градуса
69
+ "<-->" => true, # отступы $Indent*
70
+ "dashglue" => true, "wordglue" => true, # приклеивание предлогов и дефисов
71
+ "spacing" => true, # запятые и пробелы, перестановка
72
+ "phones" => true, # обработка телефонов
73
+ "fixed" => false, # подгон под фиксированную ширину
74
+ "html" => false # запрет тагов html
75
+ }
76
+ # irrelevant - indentation with images
77
+ @indent_a = "<!--indent-->"
78
+ @indent_b = "<!--indent-->"
79
+
80
+ @mark_tag = "\xF0\xF0\xF0\xF0" # Подстановочные маркеры тегов
81
+ @mark_ignored = "\201" # Подстановочные маркеры неизменяемых групп
82
+ end
83
+
84
+
85
+ # Proxy unknown method calls as setting switches. Methods with = will set settings, methods without - fetch them
86
+ def method_missing(meth, *args) #:nodoc:
87
+ setting = meth.to_s.gsub(/=$/, '')
88
+ super(meth, *args) unless @settings.has_key?(setting) #this will pop the exception if we have no such setting
89
+
90
+ return @settings[meth.to_s] if setting == meth.to_s
91
+ return (@settings[meth.to_s] = args[0])
92
+ end
93
+
94
+
95
+ def to_html(no_paragraph = false)
96
+
97
+ text = @_text
98
+
99
+ # -2. игнорируем ещё регексп
100
+ ignored = []
101
+
102
+
103
+ text.scan(@ignore) do |result|
104
+ ignored << result
105
+ end
106
+
107
+ text.gsub!(@ignore, @mark_ignored) # маркер игнора
108
+
109
+ # -1. запрет тагов html
110
+ text.gsub!(/&/, '&amp;') if @settings["html"]
111
+
112
+
113
+ # 0. Вырезаем таги
114
+ # проблема на самом деле в том, на что похожи таги.
115
+ # вариант 1, простой (закрывающий таг) </abcz>
116
+ # вариант 2, простой (просто таг) <abcz>
117
+ # вариант 3, посложней <abcz href="abcz">
118
+ # вариант 4, простой (просто таг) <abcz />
119
+ # вариант 5, вакка \xA2\xA2...== нафиг нафиг
120
+ # самый сложный вариант - это когда в параметре тага встречается вдруг символ ">"
121
+ # вот он: <abcz href="abcz>">
122
+ # как работает вырезание? введём спецсимвол. Да, да, спецсимвол.
123
+ # нам он ещё вопьётся =)
124
+ # заменим все таги на спец.символ, запоминая одновременно их в массив.
125
+ # и будем верить, что спец.символы в дикой природе не встречаются.
126
+
127
+ tags = []
128
+ if (@skip_tags)
129
+ # re = /<\/?[a-z0-9]+("+ # имя тага
130
+ # "\s+("+ # повторяющая конструкция: хотя бы один разделитель и тельце
131
+ # "[a-z]+("+ # атрибут из букв, за которым может стоять знак равенства и потом
132
+ # "=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+))"+ #
133
+ # ")?"+
134
+ # ")?"+
135
+ # ")*\/?>|\xA2\xA2[^\n]*?==/i;
136
+
137
+ # re = /<\/?[a-z0-9]+(\s+([a-z]+(=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+)))?)?)*\/?>|\xA2\xA2[^\n]*?==/ui
138
+
139
+ re = /(<\/?[a-z0-9]+(\s+([a-z]+(=((\'[^\']*\')|(\"[^\"]*\")|([0-9@\-_a-z:\/?&=\.]+)))?)?)*\/?>)/ui
140
+
141
+ # по-хорошему атрибуты тоже нужно типографить. Или не нужно? бугага...
142
+
143
+ tags = text.scan(re).map{|tag| tag[0] }
144
+ # match = "&lt;" + match if @settings["html"]
145
+ text.gsub!(re, @mark_tag) #маркер тега, мы используем Invalid UTF-sequence для него
146
+
147
+ # puts "matched #{tags.size} tags"
148
+ end
149
+
150
+ # 1. Запятые и пробелы
151
+ if @settings["spacing"]
152
+ text.gsub!( /(\s*)([,]*)/sui, '\2\1');
153
+ text.gsub!( /(\s*)([\.?!]*)(\s*[ЁА-ЯA-Z])/su, '\2\1\3');
154
+ end
155
+
156
+ # 2. Разбиение на строки длиной не более ХХ символов
157
+ # --- для ваки не портировано ---
158
+ # --- для ваки не портировано ---
159
+
160
+ # 3. Спецсимволы
161
+ # 0. дюймы с цифрами
162
+ text.gsub!(/\s([0-9]{1,2}([\.,][0-9]{1,2})?)\"/ui, ' \1&quot;') if @settings["inches"]
163
+
164
+ # 1. лапки
165
+ if (@settings["quotes"])
166
+ text.gsub!( /\"\"/ui, "&quot;&quot;")
167
+ text.gsub!( /\"\.\"/ui, "&quot;.&quot;")
168
+ _text = '""';
169
+ while _text != text do
170
+ _text = text
171
+ text.gsub!( /(^|\s|\201|\xF0\xF0\xF0\xF0|>)\"([0-9A-Za-z\'\!\s\.\?\,\-\&\;\:\_\xF0\xF0\xF0\xF0\201]+(\"|&#148;))/ui, '\1&#147;\2')
172
+ #this doesnt work in-place. somehow.
173
+ text = text.gsub( /(\&\#147\;([A-Za-z0-9\'\!\s\.\?\,\-\&\;\:\xF0\xF0\xF0\xF0\201\_]*).*[A-Za-z0-9][\xF0\xF0\xF0\xF0\201\?\.\!\,]*)\"/ui, '\1&#148;')
174
+ end
175
+ end
176
+
177
+ # 2. ёлочки
178
+ if @settings["laquo"]
179
+ text.gsub!( /\"\"/ui, "&quot;&quot;");
180
+ text.gsub!( /(^|\s|\201|\xF0\xF0\xF0\xF0|>|\()\"((\201|\xF0\xF0\xF0\xF0)*[~0-9ёЁA-Za-zА-Яа-я\-:\/\.])/ui, "\\1&laquo;\\2");
181
+ # nb: wacko only regexp follows:
182
+ text.gsub!( /(^|\s|\201|\xF0\xF0\xF0\xF0|>|\()\"((\201|\xF0\xF0\xF0\xF0|\/&nbsp;|\/|\!)*[~0-9ёЁA-Za-zА-Яа-я\-:\/\.])/ui, "\\1&laquo;\\2")
183
+ _text = "\"\"";
184
+ while (_text != text) do
185
+ _text = text;
186
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\201|\xF0\xF0\xF0\xF0)*)\"/sui, "\\1&raquo;")
187
+ # nb: wacko only regexps follows:
188
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\201|\xF0\xF0\xF0\xF0)*\?(\201|\xF0\xF0\xF0\xF0)*)\"/sui, "\\1&raquo;")
189
+ text.gsub!( /(\&laquo\;([^\"]*)[ёЁA-Za-zА-Яа-я0-9\.\-:\/](\201|\xF0\xF0\xF0\xF0|\/|\!)*)\"/sui, "\\1&raquo;")
190
+ end
191
+ end
192
+
193
+
194
+ # 2b. одновременно ёлочки и лапки
195
+ if (@settings["quotes"] && (@settings["laquo"] or @settings["farlaquo"]))
196
+ text.gsub!(/(\&\#147;\;(([A-Za-z0-9'!\.?,\-&;:]|\s|\xF0\xF0\xF0\xF0|\201)*)&laquo;(.*)&raquo;)&raquo;/ui,"\\1&#148;");
197
+ end
198
+
199
+
200
+ # 3. тире
201
+ if (@settings["dash"])
202
+ text.gsub!( /(\s|;)\-(\s)/ui, "\\1&ndash;\\2")
203
+ end
204
+
205
+
206
+ # 3a. тире длинное
207
+ if (@settings["emdash"])
208
+ text.gsub!( /(\s|;)\-\-(\s)/ui, "\\1&mdash;\\2")
209
+ # 4. (с)
210
+ text.gsub!(/\([сСcC]\)((?=\w)|(?=\s[0-9]+))/u, "&copy;") if @settings["(c)"]
211
+ # 4a. (r)
212
+ text.gsub!( /\(r\)/ui, "<sup>&#174;</sup>") if @settings["(r)"]
213
+
214
+ # 4b. (tm)
215
+ text.gsub!( /\(tm\)|\(тм\)/ui, "&#153;") if @settings["(tm)"]
216
+ # 4c. (p)
217
+ text.gsub!( /\(p\)/ui, "&#167;") if @settings["(p)"]
218
+ end
219
+
220
+
221
+ # 5. +/-
222
+ text.gsub!(/[^+]\+\-/ui, "&#177;") if @settings["+-"]
223
+
224
+
225
+ # 5a. 12^C
226
+ if @settings["degrees"]
227
+ text.gsub!( /-([0-9])+\^([FCС])/, "&ndash;\\1&#176;\\2")
228
+ text.gsub!( /\+([0-9])+\^([FCС])/, "+\\1&#176;\\2")
229
+ text.gsub!( /\^([FCС])/, "&#176;\\1")
230
+ end
231
+
232
+
233
+ # 6. телефоны
234
+ if @settings["phones"]
235
+ @phonemasks[0].each_with_index do |v, i|
236
+ text.gsub!(v, @phonemasks[1][i])
237
+ end
238
+ end
239
+
240
+
241
+ # 7. Короткие слова и &nbsp;
242
+ if (@settings["wordglue"])
243
+
244
+ text = " " + text + " ";
245
+ _text = " " + text + " ";
246
+ until _text == text
247
+ _text = text
248
+ text.gsub!( /(\s+)([a-zа-яА-Я]{1,2})(\s+)([^\\s$])/ui, '\1\2&nbsp;\4')
249
+ text.gsub!( /(\s+)([a-zа-яА-Я]{3})(\s+)([^\\s$])/ui, '\1\2&nbsp;\4')
250
+ end
251
+
252
+ for i in @glueleft
253
+ text.gsub!( /(\s)(#{i})(\s+)/sui, '\1\2&nbsp;')
254
+ end
255
+
256
+ for i in @glueright
257
+ text.gsub!( /(\s)(#{i})(\s+)/sui, '&nbsp;\2\3')
258
+ end
259
+ end
260
+
261
+
262
+
263
+ # 8. Склейка ласт. Тьфу! дефисов.
264
+ text.gsub!( /([a-zа-яА-Я0-9]+(\-[a-zа-яА-Я0-9]+)+)/ui, '<nobr>\1</nobr>') if @settings["dashglue"]
265
+
266
+
267
+ # 9. Макросы
268
+
269
+
270
+
271
+ # 10. Переводы строк
272
+ # --- для ваки не портировано ---
273
+ # --- для ваки не портировано ---
274
+
275
+
276
+ # БЕСКОНЕЧНОСТЬ. Вставляем таги обратно.
277
+ # if (@skip_tags)
278
+ # text = text.split("\xF0\xF0\xF0\xF0").join
279
+ #
280
+
281
+ tags.each do |tag|
282
+ text.sub!(@mark_tag, tag)
283
+ end
284
+
285
+ # i = 0
286
+ # text.gsub!(@mark_tag) {
287
+ # i + 1
288
+ # tags[i-1]
289
+ # }
290
+
291
+ # text = text.split("\xF0\xF0\xF0\xF0")
292
+ #puts "reinserted #{i} tags"
293
+ #
294
+ # end
295
+
296
+
297
+ #ext.gsub!("a", '')
298
+ # raise "Text still has tag markers!" if text.include?("a")
299
+
300
+ # БЕСКОНЕЧНОСТЬ-2. вставляем ещё сигнорированный регексп
301
+ #
302
+ # if @ignore
303
+ # ignored.each { | tag | text.sub!(@mark_ignored, tag) }
304
+ # end
305
+
306
+ # raise "Text still has ignored markers!" if text.include?("\201")
307
+
308
+ # БОНУС: прокручивание ссылок через A(...)
309
+ # --- для ваки не портировано ---
310
+ # --- для ваки не портировано ---
311
+
312
+ # фуф, закончили.
313
+ # text.gsub!(/<nobr>/, "<span class=\"nobr\">").gsub(/<\/nobr>/, "</span>") if (@de_nobr)
314
+
315
+ # text.gsub!(/<nobr>/, "<span class=\"nobr\">").gsub(/<\/nobr>/, "</span>") if (@de_nobr)
316
+
317
+ text.gsub(/(\s)+$/, "").gsub(/^(\s)+/, "")
318
+
319
+ end
320
+
321
+ end
@@ -0,0 +1,12 @@
1
+ if defined?(BlueCloth) && !BlueCloth.instance_methods.include?("to_html_without_rutils")
2
+ class Object::BlueCloth < String #:nodoc:
3
+ alias_method :to_html_without_rutils, :to_html
4
+ def to_html(*opts)
5
+ if RuTils::overrides_enabled?
6
+ RuTils::Gilenson::Formatter.new(to_html_without_rutils(*opts)).to_html
7
+ else
8
+ to_html_without_rutils(*opts)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module RuTils
2
+ @@overrides = true
3
+
4
+ # Метод позволяет проверить, включена ли перегрузка функций других модулей.
5
+ # Попутно он спрашивает модуль Locale (если таковой имеется) является ли русский
6
+ # текущим языком, и если является, включает перегрузку функций имплицитно.
7
+ # Это позволяет подчинить настройку перегруженных функций настроенной локали.
8
+ # Модуль Locale можно получить как часть Ruby-Gettext или как отдельный
9
+ # модуль ruby-locale. Мы поддерживаем оба.
10
+ def self.overrides_enabled?
11
+ if defined?(Locale) and Locale.respond_to?(:current)
12
+ return true if Locale.current.to_s.split('_').first == 'ru'
13
+ end
14
+ @@overrides ? true : false
15
+ end
16
+
17
+ # Включает или выключает перегрузки других модулей. Полезно, например, в случае когда нужно рендерить страницу
18
+ # сайта на нескольких языках и нужно отключить русское оформление текста для других языков.
19
+ def self.overrides= (new_override_flag)
20
+ @@overrides = (new_override_flag ? true : false)
21
+ end
22
+
23
+ # Вновь выполняет перегрузку. Делать это надо после того, как в программу импортированы
24
+ # другие модули.
25
+ def self.reload_integrations!
26
+ load File.dirname(__FILE__) + '/blue_cloth_override.rb'
27
+ load File.dirname(__FILE__) + '/red_cloth_override.rb'
28
+ load File.dirname(__FILE__) + '/rails_date_helper_override.rb'
29
+ end
30
+ end
31
+
32
+ RuTils::reload_integrations!
@@ -0,0 +1,113 @@
1
+ if defined?(Object::ActionView)
2
+ module Object::ActionView::Helpers::DateHelper
3
+
4
+ # Заменяет ActionView::Helpers::DateHelper::distance_of_time_in_words на русское сообщение.
5
+ #
6
+ # Целые числа интерпретируются как секунды
7
+ # <tt>distance_of_time_in_words(50)</tt> возвращает "меньше минуты".
8
+
9
+ alias :stock_distance_of_time_in_words :distance_of_time_in_words
10
+ def distance_of_time_in_words(*args)
11
+ RuTils::overrides_enabled? ? RuTils::DateTime::distance_of_time_in_words(*args) : stock_distance_of_time_in_words
12
+ end
13
+
14
+
15
+ # В Rails >= 2.1 3 аргумента у select_month
16
+ args_num = 2
17
+ begin
18
+ class TestClass
19
+ include Object::ActionView::Helpers::DateHelper
20
+ end
21
+ TestClass.new.select_month(Time.now, {}, {}, {}, {}, {}, {})
22
+ rescue ArgumentError => e
23
+ if e.message =~ /wrong number of arguments \(7 for (\d+)\)/
24
+ args_num = $1.to_i
25
+ end
26
+ end
27
+
28
+ case args_num
29
+ when 2
30
+ # Заменяет ActionView::Helpers::DateHelper::select_month меню выбора русских месяцев.
31
+ #
32
+ # select_month(Date.today) # Использует ключи "Январь", "Март"
33
+ # select_month(Date.today, :use_month_numbers => true) # Использует ключи "1", "3"
34
+ # select_month(Date.today, :add_month_numbers => true) # Использует ключи "1 - Январь", "3 - Март"
35
+ def select_month(date, options = {})
36
+ month_options = []
37
+ if RuTils::overrides_enabled?
38
+ month_names = case true
39
+ when options[:use_short_month]
40
+ Date::RU_ABBR_MONTHNAMES
41
+ # использование в контексте date_select с днями требует родительный падеж
42
+ when options[:order] && options[:order].include?(:day)
43
+ Date::RU_INFLECTED_MONTHNAMES
44
+ else
45
+ Date::RU_MONTHNAMES
46
+ end
47
+ else
48
+ month_names = options[:use_short_month] ? Date::ABBR_MONTHNAMES : Date::MONTHNAMES
49
+ end
50
+ 1.upto(12) do |month_number|
51
+ month_name = if options[:use_month_numbers]
52
+ month_number
53
+ elsif options[:add_month_numbers]
54
+ month_number.to_s + ' - ' + month_names[month_number]
55
+ else
56
+ month_names[month_number]
57
+ end
58
+
59
+ month_options << ((date && (date.kind_of?(Fixnum) ? date : date.month) == month_number) ?
60
+ %(<option value="#{month_number}" selected="selected">#{month_name}</option>\n) :
61
+ %(<option value="#{month_number}">#{month_name}</option>\n)
62
+ )
63
+ end
64
+
65
+ select_html(options[:field_name] || 'month', month_options, options)
66
+ end
67
+
68
+ # Заменяет ActionView::Helpers::DateHelper::select_date меню выбора русской даты.
69
+ def select_date(date = Date.today, options = {})
70
+ options[:order] ||= []
71
+ [:day, :month, :year].each { |o| options[:order].push(o) unless options[:order].include?(o) }
72
+
73
+ options[:order].map{ |o| self.send("select_#{o}", date, options) }.join
74
+ end
75
+
76
+ # Заменяет ActionView::Helpers::DateHelper::select_datetime меню выбора русской даты.
77
+ def select_datetime(datetime = Time.now, options = {})
78
+ select_day(datetime, options) + select_month(datetime, options) + select_year(datetime, options) +
79
+ select_hour(datetime, options) + select_minute(datetime, options)
80
+ end
81
+ when 3
82
+ # Rails 2.1
83
+
84
+ # Заменяет ActionView::Helpers::DateHelper::select_month меню выбора русских месяцев.
85
+ #
86
+ # select_month(Date.today) # Использует ключи "Январь", "Март"
87
+ # select_month(Date.today, :use_month_numbers => true) # Использует ключи "1", "3"
88
+ # select_month(Date.today, :add_month_numbers => true) # Использует ключи "1 - Январь", "3 - Март"
89
+ def select_month_with_rutils(date, options = {}, html_options = {})
90
+ if RuTils::overrides_enabled?
91
+ month_names = case true
92
+ when options[:use_short_month]
93
+ Date::RU_ABBR_MONTHNAMES
94
+ # использование в контексте date_select с днями требует родительный падеж
95
+ when options[:order] && options[:order].include?(:day)
96
+ Date::RU_INFLECTED_MONTHNAMES
97
+ else
98
+ Date::RU_MONTHNAMES
99
+ end
100
+ options = options.reverse_merge(:use_month_names => month_names)
101
+ end
102
+ select_month_without_rutils(date, options, html_options)
103
+ end
104
+ alias_method_chain :select_month, :rutils
105
+
106
+ def select_date_with_rutils(date = Date.today, options = {}, html_options = {})
107
+ options = options.reverse_merge(:order => [:day, :month, :year])
108
+ select_date_without_rutils(date, options, html_options)
109
+ end
110
+ alias_method_chain :select_date, :rutils
111
+ end
112
+ end
113
+ end #endif