html2index 1.2.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.
data/lib/dictionary.rb ADDED
@@ -0,0 +1,46 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2015-2017 Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+ =end
22
+ require 'constants'
23
+ require_relative 'translating'
24
+
25
+ class Dictionary
26
+
27
+ attr_reader :url, :name, :xpath
28
+ attr_accessor :color
29
+ def initialize(name, url, xpath, color = nil)
30
+ @name = name
31
+ @url = url
32
+ @xpath = xpath
33
+ @color = color
34
+ end
35
+ end
36
+
37
+ ##### TEST
38
+ if __FILE__ == $0
39
+ d1 = Dictionary.new('my_dict1','www.1.html', '../nix[@nix=nil]')
40
+ d2 = Dictionary.new('my_dict2','www.2.html', '../nil[@nix=nix]')
41
+ d1.color='#000090'
42
+ d2.color='#200010'
43
+
44
+ puts 'dict 1 is ' << d1.inspect << ", color: " << d1.color
45
+ puts 'dict 2 is ' << d2.inspect << ", color: " << d2.color
46
+ end
@@ -0,0 +1,103 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2011-2017 Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+ =end
22
+ require 'filemagic'
23
+
24
+ =begin
25
+ A module to facilitate frequently occuring checks on
26
+ file-system objects
27
+ =end
28
+ module File_Checking
29
+
30
+ @@text_messages = {
31
+ :exist? => "does not exist!",
32
+ :exist => "does not exist!",
33
+ :readable? => "is not readable!",
34
+ :readable => "is not readable!",
35
+ :executable? => "is not executable!",
36
+ :executable => "is not executable!",
37
+ :writable? => "is not writable!",
38
+ :writable => "is not writable!",
39
+ :directory? => "is not a directory!",
40
+ :directory => "is not a directory!",
41
+ :file? => "is not a file!",
42
+ :file => "is not a file!",
43
+ :type => "is not of the right file-type!",
44
+ :mime => "does not have the right mime-type!",
45
+ }
46
+
47
+ # find the file-type for a given file name
48
+ def self::file_type(file, mime = false)
49
+ fm = FileMagic.fm
50
+ file_magic = fm.file(file)
51
+ file_mime = nil
52
+ if mime
53
+ fm.flags = [:mime_type]
54
+ file_mime = fm.file(file)
55
+ end
56
+ return file_magic, file_mime
57
+ end
58
+
59
+
60
+ # Checks if the file with the name from the first
61
+ # parameter has the properties, listed in the second.
62
+ # The messages parameter is an array of one or several
63
+ # of :exist?, :readable?, :writable?, :directory? or
64
+ # their string-representations, respectively.
65
+ # Returns nil in case of success, otherwise an
66
+ # informative message, describing the first negative
67
+ # test-result.
68
+ def file_check(file, *messages)
69
+ File_Checking.file_check(file, *messages)
70
+ end
71
+
72
+ # Checks if the file with the name from the first
73
+ # parameter has the properties, listed in the second.
74
+ # The messages parameter is an array of one or all
75
+ # of :exist?, :readable?, :writable?, :directory? or
76
+ # their string-representations, respectively.
77
+ # Returns nil in case of success, otherwise an
78
+ # informative message, describing the first negative
79
+ # test-result.
80
+ def self.file_check(file, *messages)
81
+ msg = nil
82
+ if(file && messages.respond_to?(:to_ary) && !messages.empty?)
83
+ messages.each do |k|
84
+ if(! k.to_s.end_with?('?'))
85
+ k = (k.to_s << '?').to_sym
86
+ end
87
+ @log.debug ('checking ' << k.to_s) if @log
88
+ if(msg == nil && File.respond_to?(k) && ! File.send(k, file.to_s))
89
+ msg = "#{file} #{@@text_messages[k.to_sym]}"
90
+ end
91
+ end
92
+ end
93
+ msg
94
+ end
95
+ end
96
+
97
+ =begin
98
+ # example
99
+
100
+ include File_Checking
101
+ msg = file_check('some_file.txt', [:exist?, :readable?, 'writable'])
102
+ puts msg if msg
103
+ =end
data/lib/html2index.rb ADDED
@@ -0,0 +1,277 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2015-201/ Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+ =end
22
+
23
+ require_relative 'argparser'
24
+ require_relative 'logging'
25
+ require_relative 'translating'
26
+ require_relative 'user_input'
27
+ require_relative 'constants'
28
+ require_relative 'version'
29
+ require_relative 'definition'
30
+ require_relative 'dictionary'
31
+ require_relative 'template'
32
+ require 'open-uri'
33
+ require 'nokogiri'
34
+ require 'filemagic'
35
+ require_relative 'file_checking'
36
+ require_relative 'configuration'
37
+
38
+ class HTML2Index
39
+ include Logging
40
+ include Nokogiri
41
+
42
+ =begin
43
+ initialize the HTML2Index-object
44
+ =end
45
+
46
+ def initialize(*argv)
47
+ init_logger()
48
+ # ensure the configuration-file exist.
49
+ options = ArgParser.parse(argv)
50
+ $configuration = Configuration.new(options)
51
+ $configuration.user_conf
52
+ @log.level = $log_level
53
+ @file = $configuration.source
54
+
55
+ @log.debug("read #{@file}, write #{$configuration.target}")
56
+ msg = File_Checking::file_check(@file, :exist?, :readable?, :file?)
57
+ if(msg)
58
+ @log.error("Error: unsuitable file " <<@file << ": " << msg)
59
+ exit false
60
+ end
61
+
62
+ ftype = File_Checking::file_type(@file)
63
+ @log.debug('ftype for ' << @file << ' is ' << ftype.to_s)
64
+ if(ftype && !ftype.empty? && !ftype[0].downcase.match("(html|xml) .*document") )
65
+ @log.error(@file.dup << ' does not look like a valid file to scan: ' << ftype)
66
+ exit false
67
+ end
68
+
69
+ @problem_log = File.join(temp_dir, PROBLEM_LOG)
70
+ @log.debug('calling generate() ')
71
+ generate()
72
+ end
73
+
74
+ # create an unnumbered list of the consulted dictionaries.
75
+ def dict_list
76
+ list = '<ul>'
77
+ $configuration.dicts.each do |d|
78
+ list << '<li>' << d.name << ' : ' << '<a href="' << d.url << '">' << d.url << '</a></li>' << "\n"
79
+ end
80
+ @log.debug('list is ' << list.to_s)
81
+ list << "</ul>\n"
82
+ end
83
+
84
+ =begin
85
+ Parses the html-file and generates the glossary.
86
+ =end
87
+ def generate()
88
+ @log.info('Generating... PSE wait')
89
+ begin
90
+ @doc = HTML::Document.parse(File.open(@file ) )
91
+ write_html()
92
+ rescue SystemExit => ir
93
+ @log.info "Bye"
94
+ exit true
95
+ rescue Exception => ex
96
+ @log.error "line #{__LINE__}: " << ex.message
97
+ exit false
98
+ end
99
+ if(File.exist?(@problem_log ))
100
+ @log.info "Some expressions caused problems and are listed in " << @problem_log
101
+ end
102
+ end
103
+ private
104
+ =begin
105
+ Searches the expression in online-dictionaries and
106
+ creates a Definition-object for each definition, found.
107
+ Returns an array of all Definition-objects for the
108
+ expression.
109
+ =end
110
+ def dict_definition(expression)
111
+ definitions = Array.new
112
+ $configuration.dicts.each do |d|
113
+ text_array = Array.new
114
+ page = nil
115
+ begin
116
+ url = d.url.dup << URI.encode_www_form_component(expression.gsub(/\s/,'_').gsub("'", ''))
117
+ page = Nokogiri::HTML(URI.open(url))
118
+ rescue Exception => ex
119
+ url_b = d.url.dup << URI.encode_www_form_component(expression.gsub(/\s/,'_'))
120
+ @log.warn('WARNING, accessing ' << url << ': ' << ex.message)
121
+ if(url_b != url)
122
+ @log.warn("\twill try " << url_b)
123
+ begin
124
+ page = Nokogiri::HTML(URI.open(url_b, "User-Agent"=>"#{APPNAME} #{VERSION}", "From"=>"Function Test <bat.guano@don.blech.e4ward.com>"))
125
+ rescue Exception => ex
126
+ @log.warn("\tWARNING, accessing " << url_b << ': ' << ex.message)
127
+ end
128
+ end
129
+ end
130
+ if(page)
131
+ nodes = page.xpath(d.xpath)
132
+ if(nodes)
133
+ text_array = nodes.collect {|n| n.inner_text.to_s.strip}
134
+ if(!text_array.empty?)
135
+ definition = Definition.new(d.name, expression.gsub('_', ' '), text_array)
136
+ definition.color = d.color
137
+ definitions.push(definition)
138
+ end
139
+ end
140
+ else
141
+ File.open(@problem_log, 'a'){|f| f.write(expression + "\n") }
142
+ end
143
+ end
144
+ return definitions
145
+ end
146
+
147
+ =begin
148
+ Creates and returns an Array of Definitions.
149
+ =end
150
+ def index()
151
+ begin
152
+ #TODO: Hash
153
+ list = Array.new
154
+ def_list = Array.new
155
+ tag = $configuration.html_tag
156
+ attr = $configuration.html_attribute
157
+ value = $configuration.attr_value
158
+ xpath = ".//#{tag}[contains(@#{attr}, '#{value}')]"
159
+ # xpath = './/' << value << '[@' << attr << '="' << value << '"]'
160
+ @log.debug('xpath is ' << xpath)
161
+ tags = @doc.xpath(xpath)
162
+ tags.each do |t|
163
+ expression = t.attribute('title').to_s
164
+ unless (expression && !expression.strip.empty? )
165
+ expression = t.text.to_s
166
+ end
167
+ if(expression)
168
+ expression.gsub!(/\s+/, " ")
169
+ expression.strip!
170
+ if(!expression.empty? && !def_list.include?(expression) )
171
+ if(!list.include?expression.downcase)
172
+ list.push expression.downcase
173
+ definition = dict_definition(expression)
174
+ if(definition && !definition.empty?)
175
+ # @log.debug('definition is ' << definition.to_s)
176
+ def_list.push(format_index(definition) )
177
+ def_list.sort!
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ =begin
184
+ if(@log.level == Logger::DEBUG)
185
+ @log.debug('def_list is ')
186
+ def_list.each_with_index{|t, i| @log.debug( "%i %s"%[i, t]) }
187
+ end
188
+ =end
189
+ rescue Interrupt => ex
190
+ @log.warn "--------------\n\tIndex generation interrupted by user\n---------------"
191
+ end
192
+ return def_list
193
+ end
194
+
195
+ =begin
196
+ Formats the definition text.
197
+ =end
198
+ def format_index(ndef)
199
+ item = "\n<dt>"
200
+ if(ndef.respond_to?(:to_ary))
201
+ item << ndef[0].expression.dup
202
+ item << "</dt>"
203
+ ndef.each_with_index do |dn, i|
204
+ item << "\n\t<dd>(<i style='color:#" << dn.color << ";'>" << dn.origin << "</i>): " << dn.definition.join("<br/>") << "</dd>"
205
+ end
206
+ else
207
+ item << ndef.expression.dup << "</dt>"
208
+ item << "\n\t<dd>(<i><u>" << dn.origin << "</i<): " << dn.definition << "</dd>"
209
+ end
210
+ return item
211
+ end
212
+ # def temp_dir options = {:remove => true}
213
+ def temp_dir
214
+ @temp_dir ||= begin
215
+ @log.debug('creating temp_dir')
216
+ require 'tmpdir'
217
+ require 'fileutils'
218
+ path = File.join(Dir::tmpdir, "HTML2Index_#{Time.now.to_i}_#{rand(1000)}")
219
+ @log.debug('temp-dir path is ' << path)
220
+ Dir.mkdir(path)
221
+ # at_exit {FileUtils.rm_rf(path) if File.exists?(path)} if options[:remove]
222
+ File.new path
223
+ end
224
+ end
225
+
226
+ def write_html()
227
+ tempfile = nil
228
+ out = nil
229
+ out_file = $configuration.target
230
+ template = Template.new
231
+ if out_file
232
+ if(File.exist?(out_file))
233
+ if(File.writable?(out_file))
234
+ puts "\nWARNING! File " << out_file << " exists!"
235
+ print "Do you want to overwrite it? (Y/n) "
236
+ res = wait_for_user
237
+ puts
238
+ unless(['y', 'Y'].include?(res.chr) )
239
+ puts "Okay, doing nothing."
240
+ exit false
241
+ end
242
+ else
243
+ puts "ERROR! File " << out_file << " is not writable! Aborting, bye."
244
+ exit false
245
+ end
246
+ end
247
+ else
248
+ @log.debug('out_file is STDOUT')
249
+ end
250
+ begin
251
+ html = template.to_s
252
+
253
+ # create the definitions in index()
254
+ def_list = "<dl>\n" << index().join("\n") << "\n</dl\n>"
255
+ # associate content with fields
256
+ data = {:dict_list => dict_list(), :glossary => def_list }
257
+ placeholders = $configuration.placeholders
258
+ fdelim = $configuration.fdelim
259
+ placeholders.each_pair do |k, v|
260
+ repl = fdelim.dup << v << fdelim.reverse
261
+ @log.debug('try to replace ' << repl)
262
+ html.gsub!(repl, data[k])
263
+ end
264
+ @log.debug('html is now ' << html)
265
+ html.gsub!(/\<head\>/, "<head>\n\t#{GeneratorMeta}")
266
+ File.write(out_file, html) if out_file
267
+ puts html if !out_file
268
+ rescue Exception => ex
269
+ @log.error( "line #{__LINE__} " << ex.message << ' (' << ex.class.name << ')')
270
+ ensure
271
+ out.close if out && !out.closed?
272
+ File.unlink(out) if out
273
+ end
274
+ end
275
+ end
276
+
277
+
data/lib/log.conf ADDED
@@ -0,0 +1,56 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2013-2015 Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+
22
+ A simplified logger configuration. Set the level for each individual logger
23
+ below. Choose a different log-device or log-file if you like. Keep the
24
+ formatting intact. Do not change other sections of this file.
25
+ =end
26
+
27
+ # Do not touch from here ----->
28
+ require 'logger'
29
+
30
+ debug = Logger::DEBUG
31
+ info = Logger::INFO
32
+ error = Logger::ERROR
33
+ fatal = Logger::FATAL
34
+ warn = Logger::WARN
35
+ unknown = Logger::UNKNOWN
36
+ {
37
+ # <---------------- to here !
38
+
39
+ # Enter your settings here, but take into consideration that not all
40
+ # the named classes will really produce readable output. Well, you can
41
+ # always try... Either name just the log-level or make the log-level
42
+ # precede the output-device or output-file like in the examples.
43
+
44
+ # Example: naming a log-file
45
+ # :HtmlBuilder => [info, 'C:\temp\htmlbuilder.log']
46
+ # :HtmlBuilder => [debug, '/tmp/htmlbuilder.log'],
47
+
48
+ :HTML2Index => debug,
49
+ :Template => info,
50
+ :Configuration => info,
51
+ :ArgParser => info,
52
+
53
+ # And ignore the remainder, too.
54
+ }
55
+
56
+ #eof
data/lib/logging.rb ADDED
@@ -0,0 +1,206 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2011-2017 Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+ =end
22
+ require 'logger'
23
+ require_relative 'file_checking'
24
+
25
+ =begin Creates a member @log and precede its output with the name of the class
26
+ of the object.
27
+ Example for a class-level logger:
28
+ # --------------------
29
+ class TClass
30
+ self.extend(Logging)
31
+ @@log = init_logger(STDOUT)
32
+ def test_log
33
+ @@log.info('class-level logger called from instance: ' << @@log.to_s)
34
+ @log = @@log
35
+ @log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
36
+ end
37
+ def self::test_log
38
+ @log.info('class-level logger called from class: ' << @log.to_s)
39
+ @@log.info('AGAIN: class-level logger called from class: ' << @@log.to_s)
40
+ end
41
+ end
42
+ #---------------------
43
+ Example for a object-level logger:
44
+ ATTN! This means 1 logger per object.
45
+ # --------------------
46
+ class TClass
47
+ include Logging
48
+ def initialize
49
+ init_logger(STDOUT, Logger::DEBUG)
50
+ end
51
+ def test_log
52
+ @log.debug('called test_log() ')
53
+ end
54
+ end
55
+ =end
56
+ module Logging
57
+ @@LEVELS = {:debug => Logger::DEBUG, :info => Logger::INFO, :error => Logger::ERROR, :warn => Logger::WARN, :unknown => Logger::UNKNOWN, :fatal => Logger::FATAL}
58
+
59
+ @@have_log = false
60
+ @@LOG_CONF = File.dirname(File.absolute_path(__FILE__)) << File::Separator << 'log.conf'
61
+
62
+ # Call this method in an instance-method (e.g. initialize() ) to define the
63
+ # object-level logger; i.e. an object-specific member @log.
64
+ # Call this method within the class-definition for a class-level logger; i.e.
65
+ # a member @log for class-level acces.
66
+ # The method returns the logger, so you can actually do what you want with it.
67
+ def init_logger(target = STDOUT, level = Logger::INFO)
68
+ # Prepare for a class-level logger. This is actually quite cool.
69
+ # ---> Ingeniuous code starts here
70
+ cn = (self.class == Class ? name : self.class.name)
71
+ # <--- Ingeniuous code ends here
72
+
73
+ # allow to override the set log-levels with an
74
+ # external configuration (log.conf).
75
+ log_conf(cn)
76
+ # Or use the defaults as set here or elsewhere...
77
+
78
+ @level ||= level
79
+ @target ||= target
80
+ @log = Logger.new(@target)
81
+ @log.level = @level
82
+ @log.formatter = formatter(cn)
83
+ if ! @@have_log
84
+ @log.debug cn.dup << ' reading logging-configuration from ' << @@LOG_CONF
85
+ @@have_log = true
86
+ @log.debug('level is ' << level.to_s)
87
+ end
88
+ return @log
89
+ end
90
+
91
+ def formatter(classname)
92
+ proc do |severity, datetime, progname, msg|
93
+ t = Time.now
94
+ "#{classname} (#{__LINE__}): #{severity} #{t.hour}-#{t.min}-#{t.sec}: #{msg}\n"
95
+ end
96
+ end
97
+
98
+ # Set the log-target to an IO object.
99
+ def log_target=(target)
100
+ @target = target
101
+ @log = Logger.new(@target)
102
+ @log.level = @level
103
+ end
104
+
105
+ # set the log-level
106
+
107
+ def log_level=(level)
108
+ @level = level
109
+ @log.level = @level
110
+ end
111
+
112
+ # verify log level
113
+ def log_level?(level)
114
+ return @log.level == level
115
+ end
116
+
117
+ # brutal log-function: print message, than exit.
118
+ def debout(str)
119
+ puts self.class.name.dup << " DEBOUT: " << str
120
+ exit true
121
+ end
122
+
123
+ private
124
+
125
+ # Override or set the log-level and target-device, as set in a file 'log.conf'.
126
+ # I do not like the look of this, but it works just the way I want it to.
127
+ # "HEAVANS! Isn't there a standard way to do this in Ruby, for Christ's sake?", you say.
128
+ # Heck, I don't care. <= Read that again, I say.
129
+ def log_conf(cn = nil)
130
+ config = level = target = nil
131
+ if(File::exist?(@@LOG_CONF) )
132
+ begin
133
+ conf = File.read(@@LOG_CONF)
134
+ config = instance_eval(conf)
135
+ rescue Exception => ex
136
+ STDERR.puts "WARNING! Cannot evaluate the logger-configuration!" << ' ' << ex.message
137
+ STDERR.puts "Default log-levels apply."
138
+ end
139
+ else
140
+ puts "Default log-levels apply."
141
+ end
142
+
143
+ if(config && config.respond_to?(:to_hash) )
144
+ config.default = nil
145
+ if cn
146
+ config = config[cn.to_sym]
147
+ else
148
+ config = config[self.class.name.to_sym]
149
+ end
150
+
151
+ if(config )
152
+ if(config.respond_to?(:to_ary) && config.size == 2)
153
+ @level, @target = config
154
+ @target.downcase!
155
+ logdir = File.dirname(@target)
156
+ msg = File_Checking::file_check(logdir, :exist?, :directory?, :writable?)
157
+ if(msg)
158
+ STDERR.puts "WARNING! A logfile for '%s' cannot be written to %s (%s)!" %[self.class.name, logdir, msg]
159
+ @target = nil
160
+ end
161
+ else
162
+ @level = config
163
+ end
164
+ end
165
+ end
166
+ end
167
+ attr_reader :level
168
+ end
169
+
170
+ ######### test
171
+ if __FILE__ == $0
172
+ class TClass
173
+ # class level ---->
174
+ self.extend(Logging)
175
+ @@log = init_logger(STDOUT, Logger::INFO)
176
+ # <------
177
+ # object-level ---->
178
+ include Logging
179
+ # <---------
180
+
181
+ def test_log
182
+ @@log.info('class-level logger called from instance: ' << @@log.to_s)
183
+ #@log = @@log # works too
184
+ @log = TClass.class_eval{@log}
185
+ @log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
186
+ @log.debug("you won't see this on log-level INFO")
187
+
188
+ # object-level ---->
189
+ init_logger
190
+ # <-----------
191
+ @log.info("That's a different thing: " << @log.to_s << " - object-level logger!")
192
+
193
+ end
194
+ def self::test_log
195
+ @log.info('class-level logger called from class: ' << @log.to_s)
196
+ @@log.info('AGAIN: class-level logger called from class: ' << @log.to_s)
197
+ end
198
+ end
199
+
200
+ TClass.new.test_log # class-logger + 1st object-logger
201
+ TClass.new.test_log # same class-logger + 2nd object-logger
202
+
203
+ TClass::test_log # same class-logger
204
+ puts 'And just say it once clearly: THIS IS COOOL!!'
205
+ end
206
+ #EOF