cremefraiche 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of cremefraiche might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/bin/cremefraiche +25 -0
- data/bin/cremefraicheGui +26 -0
- data/cremefraiche.gemspec +24 -0
- data/lib/LANG +1 -0
- data/lib/busy_indicator/busy_function_test.rb +56 -0
- data/lib/busy_indicator/busy_indicator.rb +95 -0
- data/lib/busy_indicator/color_output.rb +51 -0
- data/lib/cfprawn.rb +394 -0
- data/lib/confcheck.rb +112 -0
- data/lib/config +192 -0
- data/lib/configuration.rb +259 -0
- data/lib/cremefraiche.rb +341 -0
- data/lib/emlfile.rb +140 -0
- data/lib/file_checking.rb +87 -0
- data/lib/gui/AboutDialog.rb +64 -0
- data/lib/gui/ButtonLabel.rb +49 -0
- data/lib/gui/ConfDialog.rb +618 -0
- data/lib/gui/HowtoDialog.rb +184 -0
- data/lib/gui/conf_option.rb +279 -0
- data/lib/gui/conf_value.rb +65 -0
- data/lib/gui/cremefraicheGui.rb +625 -0
- data/lib/gui/gtk-about.xpm +90 -0
- data/lib/gui/gtk-close.xpm +90 -0
- data/lib/gui/gtk-execute.xpm +118 -0
- data/lib/gui/gtk-open.xpm +147 -0
- data/lib/gui/gtk-properties.xpm +378 -0
- data/lib/gui/gtk-quit.xpm +352 -0
- data/lib/gui/gtk-remove.xpm +123 -0
- data/lib/gui/gtk-save.xpm +214 -0
- data/lib/gui/gtk-stop.xpm +344 -0
- data/lib/gui/help.xpm +463 -0
- data/lib/gui/icon.xpm +300 -0
- data/lib/gui/message_dialog.rb +34 -0
- data/lib/gui/okay.xpm +49 -0
- data/lib/gui/preferences-color.xpm +252 -0
- data/lib/gui/view.xpm +75 -0
- data/lib/html2text.rb +177 -0
- data/lib/icon/icon.xpm +300 -0
- data/lib/icon/icon_big.xpm +661 -0
- data/lib/license.rb +705 -0
- data/lib/log.conf +65 -0
- data/lib/logging.rb +193 -0
- data/lib/tag_munging.rb +97 -0
- data/lib/translating.rb +78 -0
- data/lib/translations +598 -0
- data/lib/version.rb +26 -0
- metadata +213 -0
data/lib/log.conf
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2013-2016 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
|
+
# PAY ATTENTION to the fact, that these settings overwrite any other
|
44
|
+
# way to configure the loggers.
|
45
|
+
|
46
|
+
# Example: naming a log-file
|
47
|
+
# :HtmlBuilder => [info, 'C:\temp\htmlbuilder.log']
|
48
|
+
# :HtmlBuilder => [debug, '/tmp/htmlbuilder.log'],
|
49
|
+
|
50
|
+
#:Configuration => info,
|
51
|
+
#:ConfDialog => info,
|
52
|
+
#:ConfOption => info,
|
53
|
+
#:EmlFile => info,
|
54
|
+
#:CremeFraiche => info,
|
55
|
+
#:CremeFraicheGui => info,
|
56
|
+
#:CFPrawn => info,
|
57
|
+
#:Html2Text => info,
|
58
|
+
#:TagMunging => info,
|
59
|
+
#:ButtonLabel => info,
|
60
|
+
#:HowtoDialog => info,
|
61
|
+
|
62
|
+
# And ignore the remainder, too.
|
63
|
+
}
|
64
|
+
|
65
|
+
#eof
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2016 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
|
+
include File_Checking
|
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
|
+
|
70
|
+
# ---> Ingeniuous code starts here
|
71
|
+
cn = (self.class == Class ? name : self.class.name)
|
72
|
+
# <--- Ingeniuous code ends here
|
73
|
+
|
74
|
+
# allow to override the set log-levels with an
|
75
|
+
# external configuration (log.conf).
|
76
|
+
log_conf(cn)
|
77
|
+
# Or use the defaults as set here or elsewhere...
|
78
|
+
|
79
|
+
@level ||= level
|
80
|
+
@target ||= target
|
81
|
+
|
82
|
+
@log = Logger.new(@target)
|
83
|
+
@log.level = @level
|
84
|
+
|
85
|
+
@log.formatter = proc do |severity, datetime, progname, msg|
|
86
|
+
t = Time.now
|
87
|
+
"#{cn}: #{severity} #{t.hour}-#{t.min}-#{t.sec}: #{msg}\n"
|
88
|
+
end
|
89
|
+
if ! @@have_log
|
90
|
+
@log.debug cn.dup << ' reading logging-configuration from ' << @@LOG_CONF
|
91
|
+
@@have_log = true
|
92
|
+
@log.debug('level is ' << level.to_s)
|
93
|
+
end
|
94
|
+
return @log
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set the log-target to an IO object.
|
98
|
+
def log_target=(target)
|
99
|
+
@target = target
|
100
|
+
@log = Logger.new(@@target)
|
101
|
+
@log.level = @level
|
102
|
+
end
|
103
|
+
|
104
|
+
# set the log-level
|
105
|
+
def log_level=(level)
|
106
|
+
@level = level
|
107
|
+
@log.level = @level
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Override or set the log-level and target-device, as set in a file 'log.conf'.
|
113
|
+
# I do not like the look of this, but it works just the way I want it to.
|
114
|
+
# "HEAVANS! Isn't there a standard way to do this in Ruby, for Christ's sake?", you say.
|
115
|
+
# Heck, I don't care. <= Read that again, I say.
|
116
|
+
def log_conf(cn = nil)
|
117
|
+
config = level = target = nil
|
118
|
+
# puts 'log-config is in ' << @@LOG_CONF
|
119
|
+
if(File::exist?(@@LOG_CONF) )
|
120
|
+
begin
|
121
|
+
conf = File.read(@@LOG_CONF)
|
122
|
+
config = instance_eval(conf)
|
123
|
+
rescue Exception => ex
|
124
|
+
STDERR.puts "WARNING! Cannot evaluate the logger-configuration!" << ' ' << ex.message
|
125
|
+
STDERR.puts "Default log-levels apply."
|
126
|
+
end
|
127
|
+
else
|
128
|
+
puts "Default log-levels apply."
|
129
|
+
end
|
130
|
+
|
131
|
+
if(config && config.respond_to?(:to_hash) )
|
132
|
+
config.default = nil
|
133
|
+
if cn
|
134
|
+
config = config[cn.to_sym]
|
135
|
+
else
|
136
|
+
config = config[self.class.name.to_sym]
|
137
|
+
end
|
138
|
+
|
139
|
+
if(config )
|
140
|
+
if(config.respond_to?(:to_ary) && config.size == 2)
|
141
|
+
@level, @target = config
|
142
|
+
@target.downcase!
|
143
|
+
logdir = File.dirname(@target)
|
144
|
+
msg = file_check(logdir, :exist?, :directory?, :writable?)
|
145
|
+
if(msg)
|
146
|
+
STDERR.puts "WARNING! A logfile for '%s' cannot be written to %s (%s)!" %[self.class.name, logdir, msg]
|
147
|
+
@target = nil
|
148
|
+
end
|
149
|
+
else
|
150
|
+
@level = config
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
######### test
|
158
|
+
if __FILE__ == $0
|
159
|
+
class TClass
|
160
|
+
# class level ---->
|
161
|
+
self.extend(Logging)
|
162
|
+
@@log = init_logger(STDOUT, Logger::INFO)
|
163
|
+
# <------
|
164
|
+
# object-level ---->
|
165
|
+
include Logging
|
166
|
+
# <---------
|
167
|
+
|
168
|
+
def test_log
|
169
|
+
@@log.info('class-level logger called from instance: ' << @@log.to_s)
|
170
|
+
#@log = @@log # works too
|
171
|
+
@log = TClass.class_eval{@log}
|
172
|
+
@log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
|
173
|
+
@log.debug("you won't see this on log-level INFO")
|
174
|
+
|
175
|
+
# object-level ---->
|
176
|
+
init_logger
|
177
|
+
# <-----------
|
178
|
+
@log.info("That's a different thing: " << @log.to_s << " - object-level logger!")
|
179
|
+
|
180
|
+
end
|
181
|
+
def self::test_log
|
182
|
+
@log.info('class-level logger called from class: ' << @log.to_s)
|
183
|
+
@@log.info('AGAIN: class-level logger called from class: ' << @log.to_s)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
TClass.new.test_log # class-logger + 1st object-logger
|
188
|
+
TClass.new.test_log # same class-logger + 2nd object-logger
|
189
|
+
|
190
|
+
TClass::test_log # same class-logger
|
191
|
+
puts 'And just say it once clearly: THIS IS COOOL!!'
|
192
|
+
end
|
193
|
+
#EOF
|
data/lib/tag_munging.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2013-2016 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 'logging'
|
24
|
+
require_relative 'translating'
|
25
|
+
require 'nokogiri'
|
26
|
+
require 'singleton'
|
27
|
+
|
28
|
+
=begin
|
29
|
+
A utility module for recurring tag-specific tasks.
|
30
|
+
=end
|
31
|
+
module TagMunging
|
32
|
+
|
33
|
+
def remove_empty_rows(table)
|
34
|
+
all_body_rows(table) do |tr|
|
35
|
+
cells = tr.xpath("./td").dup
|
36
|
+
empty = true
|
37
|
+
cells.each{|cell| empty = false if !cell.children.empty? }
|
38
|
+
tr.remove if empty
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def all_row_cells(tr, &b)
|
43
|
+
tds = tr.xpath('./td')
|
44
|
+
tds.each do |td|
|
45
|
+
yield(td, tds.index(td) )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def all_body_rows(table, &b)
|
50
|
+
trs = table.xpath("./tbody/tr")
|
51
|
+
@log.debug('table contains ' << trs.size.to_s << ' data-rows') if @log
|
52
|
+
trs.each do |tr|
|
53
|
+
yield(tr, trs.index(tr) )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def all_body_cells(table, &b)
|
58
|
+
trs = table.xpath("./tbody/tr")
|
59
|
+
@log.debug('table contains ' << trs.size.to_s << ' data-rows') if @log
|
60
|
+
trs.each do |tr|
|
61
|
+
all_row_cells(tr) do |td|
|
62
|
+
yield(td, trs.index(td) )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def remove_empty_sub_tags(parent, tag)
|
68
|
+
tags = parent.xpath(".//" << tag)
|
69
|
+
tags.each{|t| t.remove if t.content.chomp.strip.empty?}
|
70
|
+
end
|
71
|
+
|
72
|
+
def right_align_numbers(tags, symbol)
|
73
|
+
tags.each do |tag|
|
74
|
+
if(tag.content.chomp.match(/^-?[^\D]\d*(\.?\d*)?[^\D]?$/) )
|
75
|
+
tag['class'] = (tag['class'] ? tag['class'] : '') << ' ' << 'right'
|
76
|
+
cont = tag.content
|
77
|
+
tag.content = cont << symbol if cont && symbol
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def new_tag(doc, tag, options = nil)
|
83
|
+
ntag = Nokogiri::XML::Node.new(tag, doc)
|
84
|
+
if(options && options.respond_to?(:to_hash))
|
85
|
+
ntag.content = options.delete(:content) if options[:content]
|
86
|
+
ntag.parent = options.delete(:parent) if options[:parent]
|
87
|
+
options.each do |k,v|
|
88
|
+
ntag[k.to_s] = v
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return ntag
|
92
|
+
end
|
93
|
+
|
94
|
+
def tag_by_content(doc, tagname, content)
|
95
|
+
return doc.xpath("//" << tagname.to_s).detect{|tag| tag.content.strip == content}
|
96
|
+
end
|
97
|
+
end
|
data/lib/translating.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2016, Michael Uplawski *
|
5
|
+
* <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
|
25
|
+
RD = File.expand_path(File.dirname(__FILE__) ) + File::SEPARATOR if !defined?(RD)
|
26
|
+
|
27
|
+
require 'yaml'
|
28
|
+
require_relative 'file_checking'
|
29
|
+
|
30
|
+
|
31
|
+
# A way to produce translated text in a ruby-program.
|
32
|
+
# Translations are read from a file "translations" in the program folder.
|
33
|
+
module Translating
|
34
|
+
# There are better ways to extend a translated
|
35
|
+
# string, but I keep the 'wild-card' for
|
36
|
+
# historical reasons.
|
37
|
+
|
38
|
+
@@lang = nil
|
39
|
+
@@lang_file = format("%s%s", RD, 'LANG')
|
40
|
+
@@tr = YAML::load_file("#{RD}translations")
|
41
|
+
|
42
|
+
# find the current language-setting and return it.
|
43
|
+
def self.language()
|
44
|
+
if @@lang == nil
|
45
|
+
r = ENV['LANG']
|
46
|
+
if(r)
|
47
|
+
@@lang = r[0, 2]
|
48
|
+
elsif( !File_Checking::file_check(@@lang_file, [:exist?, :readable?]) && File::size(@@lang_file) >= 2)
|
49
|
+
File::open(@@lang_file, 'r') {|f| @@lang = f.readline}
|
50
|
+
@@lang.chomp!.downcase! if @@lang
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@@lang = 'en' if !@@lang
|
54
|
+
end
|
55
|
+
|
56
|
+
# Translate a string to the currently set langage. If 'warn' is true
|
57
|
+
# (default), a missing translation provokes a message on STDOUT,
|
58
|
+
# indicating the string that needs translating.
|
59
|
+
def self.trl(t, warn = true)
|
60
|
+
Translating::language()
|
61
|
+
lt = @@tr[t]
|
62
|
+
if(lt)
|
63
|
+
lt = lt[@@lang]
|
64
|
+
elsif warn
|
65
|
+
# File.open('/tmp/mtf', 'a+') {|f| f << t << "\n"}
|
66
|
+
puts "\nTRANSLATION MISSING: \"" << t << "\""
|
67
|
+
end
|
68
|
+
lt ||= t
|
69
|
+
return lt
|
70
|
+
end
|
71
|
+
|
72
|
+
# Translate a string to the currently set langage. If 'warn' is true
|
73
|
+
# (default), a missing translation provokes a message on STDOUT,
|
74
|
+
# indicating the string that needs translating.
|
75
|
+
def trl(t, warn = true )
|
76
|
+
Translating::trl(t, warn)
|
77
|
+
end
|
78
|
+
end
|