viewworkbook 0.1.3

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,43 @@
1
+ #encoding 'UTF-8'
2
+
3
+ # functions to apply colors to terminal output
4
+
5
+ COLORS = {:default => 9, :black => 0, :red => 1, :green => 2, :yellow => 3, :blue => 4, :purple => 5, :cyan => 6, :white => 7 }
6
+
7
+ BG = 4
8
+ FG = 3
9
+ REGULAR = 0
10
+ BOLD = 1
11
+ UNDERLINE = 4
12
+ BLINK = 5
13
+ SWAP = 7
14
+ NEUTRAL = 0
15
+
16
+ STYLES = {:regular => REGULAR, :bold => BOLD, :underline => UNDERLINE, :blink => BLINK, :swap => SWAP, :neutral => NEUTRAL}
17
+
18
+ def colorize(text, color_code)
19
+ "#{color_code}#{text}\033[0m"
20
+ end
21
+
22
+ def style(text, style_code)
23
+ "#{style_code}#{text}\033[0m"
24
+ end
25
+
26
+ def colored_output(output_text, fg_color = :default, bg_color = :default, style = :regular , mode = :neutral )
27
+ "\033[%i;%i;%i%i;%i%im%s\033[0m" %[STYLES[mode.to_sym], STYLES[style.to_sym], FG, COLORS[fg_color.to_sym], BG, COLORS[bg_color.to_sym], output_text]
28
+ end
29
+
30
+ def red(text); colorize(text, "\033[31m"); end
31
+ def green(text); colorize(text, "\033[32m"); end
32
+ def yellow(text); colorize(text, "\033[33m"); end
33
+ def purple(text); colorize(text, "\033[35m"); end
34
+ def cyan(text); colorize(text, "\033[36m"); end
35
+ def blue(text); colorize(text, "\033[34m"); end
36
+ def white(text); colorize(text, "\033[37m"); end
37
+
38
+ def black_on_white(text); colorize(colorize(text, "\033[30m"), "\033[47m");end
39
+ def white_on_black(text); colorize(colorize(text, "\033[37m"), "\033[40m");end
40
+
41
+ def bold(text); style(text, "\033[01m");end
42
+ def underline(text); style(text, "\033[04m");end
43
+
@@ -0,0 +1,97 @@
1
+ #encoding: UTF-8
2
+
3
+ =begin
4
+ /***************************************************************************
5
+ * Copyright ©2016-2016, Michael Uplawski <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
+ require_relative 'logging'
26
+
27
+ # Objects of this class represent columns in a spreadsheet table
28
+
29
+ class Column
30
+ self.extend(Logging)
31
+ @@log = self.init_logger
32
+ @@DEF_WIDTH=15
33
+ @@col_width=@@DEF_WIDTH
34
+ @@columns = Array.new
35
+ def initialize(number = nil)
36
+ @log = @@log
37
+ @number = number
38
+ @cells = Array.new
39
+ @width = @@col_width
40
+ @@columns << self
41
+ end
42
+
43
+ def add(cell)
44
+ n_cell = nil
45
+ if cell.respond_to?(:to_cell)
46
+ n_cell = cell
47
+ elsif cell.respond_to?(:to_i)
48
+ n_cell = Cell.new( cell, @number)
49
+ else
50
+ msg = 'For a new cell, a row-number must be specified'
51
+ @log.error(yellow(msg))
52
+ raise StandardError(msg)
53
+ end
54
+ @cells.insert(n_cell.row, n_cell)
55
+ @cells.compact!
56
+ set_limits
57
+ end
58
+
59
+ def each(&b)
60
+ @cells.each do |c|
61
+ yield(c)
62
+ end
63
+ end
64
+
65
+ def self::col_width
66
+ @@col_width
67
+ end
68
+
69
+ def self::col_width=(w)
70
+ @@col_width = w
71
+ @log.debug("self::col_width=(#{w}), calling resize")
72
+
73
+ @@columns.each {|col| col.resize(w)}
74
+ end
75
+
76
+ def resize(width)
77
+ @width = width
78
+ @log.debug('calling resize')
79
+ @cells.each {|cell| cell.resize}
80
+ end
81
+
82
+ def to_s
83
+ '<' << self.class.name.dup << ':' << object_id.to_s << "{number=%s width=%s cells.length=}>" %[@number, @cells.length]
84
+ end
85
+
86
+ attr_reader :number, :width
87
+ alias :<< :add
88
+
89
+ private
90
+
91
+ def set_limits
92
+ @ideal_width = @cells.max{|c1, c2| c1.ideal_width <=> c2.ideal_width}.ideal_width
93
+ @ideal_width ||= @@DEF_WIDTH
94
+ # @width ||= @ideal_width
95
+ end
96
+
97
+ end
@@ -0,0 +1,87 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2011-2013 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
+ =begin
24
+ A module to facilitate frequently occuring checks on
25
+ file-system objects
26
+ =end
27
+ module File_Checking
28
+
29
+ @@text_messages = {
30
+ :exist? => "does not exist!",
31
+ :exist => "does not exist!",
32
+ :readable? => "is not readable!",
33
+ :readable => "is not readable!",
34
+ :executable? => "is not executable!",
35
+ :executable => "is not executable!",
36
+ :writable? => "is not writable!",
37
+ :writable => "is not writable!",
38
+ :directory? => "is not a directory!",
39
+ :directory => "is not a directory!",
40
+ :file? => "is not a file!",
41
+ :file => "is not a file!",
42
+ }
43
+
44
+ # Checks if the file with the name from the first
45
+ # parameter has the properties, listed in the second.
46
+ # The messages parameter is an array of one or several
47
+ # of :exist?, :readable?, :writable?, :directory? or
48
+ # their string-representations, respectively.
49
+ # Returns nil in case of success, otherwise an
50
+ # informative message, describing the first negative
51
+ # test-result.
52
+ def file_check(file, *messages)
53
+ File_Checking.file_check(file, *messages)
54
+ end
55
+
56
+ # Checks if the file with the name from the first
57
+ # parameter has the properties, listed in the second.
58
+ # The messages parameter is an array of one or all
59
+ # of :exist?, :readable?, :writable?, :directory? or
60
+ # their string-representations, respectively.
61
+ # Returns nil in case of success, otherwise an
62
+ # informative message, describing the first negative
63
+ # test-result.
64
+ def self.file_check(file, *messages)
65
+ msg = nil
66
+ if(file && messages.respond_to?(:to_ary) && !messages.empty?)
67
+ messages.each do |k|
68
+ if(! k.to_s.end_with?('?'))
69
+ k = (k.to_s << '?').to_sym
70
+ end
71
+ @log.debug ('checking ' << k.to_s) if @log
72
+ if(msg == nil && File.respond_to?(k) && ! File.send(k, file.to_s))
73
+ msg = "#{file} #{@@text_messages[k.to_sym]}"
74
+ end
75
+ end
76
+ end
77
+ msg
78
+ end
79
+ end
80
+
81
+ =begin
82
+ # example
83
+
84
+ include File_Checking
85
+ msg = file_check('some_file.txt', [:exist?, :readable?, 'writable'])
86
+ puts msg if msg
87
+ =end
@@ -0,0 +1,62 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2013 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
+ :ViewWorkBook => debug,
49
+ :SheetInterface => debug,
50
+ :Action => info,
51
+ :Menu => info,
52
+ :SheetData => info,
53
+ :Row => info,
54
+ :Cell => info,
55
+ :Column => info,
56
+ :Scrollable => debug,
57
+ :AnsiEscapedText => debug,
58
+
59
+ # And ignore the remainder, too.
60
+ }
61
+
62
+ #eof
@@ -0,0 +1,195 @@
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
+ $DEBUG = :DEBUG
26
+
27
+ =begin Creates a member @log and precede its output with the name of the class
28
+ of the object.
29
+ Example for a class-level logger:
30
+ # --------------------
31
+ class TClass
32
+ self.extend(Logging)
33
+ @@log = init_logger(STDOUT)
34
+ def test_log
35
+ @@log.info('class-level logger called from instance: ' << @@log.to_s)
36
+ @log = @@log
37
+ @log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
38
+ end
39
+ def self::test_log
40
+ @log.info('class-level logger called from class: ' << @log.to_s)
41
+ @@log.info('AGAIN: class-level logger called from class: ' << @@log.to_s)
42
+ end
43
+ end
44
+ #---------------------
45
+ Example for a object-level logger:
46
+ ATTN! This means 1 logger per object.
47
+ # --------------------
48
+ class TClass
49
+ include Logging
50
+ def initialize
51
+ init_logger(STDOUT, Logger::DEBUG)
52
+ end
53
+ def test_log
54
+ @log.debug('called test_log() ')
55
+ end
56
+ end
57
+ =end
58
+ module Logging
59
+ include File_Checking
60
+
61
+ @@have_log = false
62
+ @@LOG_CONF = File.dirname(File.absolute_path(__FILE__)) << File::Separator << 'log.conf'
63
+
64
+ # Call this method in an instance-method (e.g. initialize() ) to define the
65
+ # object-level logger; i.e. an object-specific member @log.
66
+ # Call this method within the class-definition for a class-level logger; i.e.
67
+ # a member @log for class-level acces.
68
+ # The method returns the logger, so you can actually do what you want with it.
69
+ def init_logger(target = STDOUT, level = Logger::INFO)
70
+ # Prepare for a class-level logger. This is actually quite cool.
71
+
72
+ # ---> Ingeniuous code starts here
73
+ cn = (self.class == Class ? name : self.class.name)
74
+ # <--- Ingeniuous code ends here
75
+
76
+ # allow to override the set log-levels with an
77
+ # external configuration (log.conf).
78
+ log_conf(cn)
79
+ # Or use the defaults as set here or elsewhere...
80
+
81
+ @level ||= level
82
+ @target ||= target
83
+
84
+ @log = Logger.new(@target)
85
+ @log.level = @level
86
+
87
+ @log.formatter = proc do |severity, datetime, progname, msg|
88
+ t = Time.now
89
+ "#{cn}: #{severity} #{t.hour}-#{t.min}-#{t.sec}: #{msg}\n"
90
+ end
91
+ if ! @@have_log
92
+ @log.debug cn.dup << ' reading logging-configuration from ' << @@LOG_CONF
93
+ @@have_log = true
94
+ @log.debug('level is ' << level.to_s)
95
+ end
96
+ return @log
97
+ end
98
+
99
+ # Set the log-target to an IO object.
100
+ def log_target=(target)
101
+ @target = target
102
+ @log = Logger.new(@@target)
103
+ @log.level = @level
104
+ end
105
+
106
+ # set the log-level
107
+ def log_level=(level)
108
+ @level = level
109
+ @log.level = @level
110
+ end
111
+
112
+ private
113
+
114
+ # Override or set the log-level and target-device, as set in a file 'log.conf'.
115
+ # I do not like the look of this, but it works just the way I want it to.
116
+ # "HEAVANS! Isn't there a standard way to do this in Ruby, for Christ's sake?", you say.
117
+ # Heck, I don't care. <= Read that again, I say.
118
+ def log_conf(cn = nil)
119
+ config = level = target = nil
120
+ # puts 'log-config is in ' << @@LOG_CONF
121
+ if(File::exist?(@@LOG_CONF) )
122
+ begin
123
+ conf = File.read(@@LOG_CONF)
124
+ config = instance_eval(conf)
125
+ rescue Exception => ex
126
+ STDERR.puts "WARNING! Cannot evaluate the logger-configuration!" << ' ' << ex.message
127
+ STDERR.puts "Default log-levels apply."
128
+ end
129
+ else
130
+ puts "Default log-levels apply."
131
+ end
132
+
133
+ if(config && config.respond_to?(:to_hash) )
134
+ config.default = nil
135
+ if cn
136
+ config = config[cn.to_sym]
137
+ else
138
+ config = config[self.class.name.to_sym]
139
+ end
140
+
141
+ if(config )
142
+ if(config.respond_to?(:to_ary) && config.size == 2)
143
+ @level, @target = config
144
+ @target.downcase!
145
+ logdir = File.dirname(@target)
146
+ msg = file_check(logdir, :exist?, :directory?, :writable?)
147
+ if(msg)
148
+ STDERR.puts "WARNING! A logfile for '%s' cannot be written to %s (%s)!" %[self.class.name, logdir, msg]
149
+ @target = nil
150
+ end
151
+ else
152
+ @level = config
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ ######### test
160
+ if __FILE__ == $0
161
+ class TClass
162
+ # class level ---->
163
+ self.extend(Logging)
164
+ @@log = init_logger(STDOUT, Logger::INFO)
165
+ # <------
166
+ # object-level ---->
167
+ include Logging
168
+ # <---------
169
+
170
+ def test_log
171
+ @@log.info('class-level logger called from instance: ' << @@log.to_s)
172
+ #@log = @@log # works too
173
+ @log = TClass.class_eval{@log}
174
+ @log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
175
+ @log.debug("you won't see this on log-level INFO")
176
+
177
+ # object-level ---->
178
+ init_logger
179
+ # <-----------
180
+ @log.info("That's a different thing: " << @log.to_s << " - object-level logger!")
181
+
182
+ end
183
+ def self::test_log
184
+ @log.info('class-level logger called from class: ' << @log.to_s)
185
+ @@log.info('AGAIN: class-level logger called from class: ' << @log.to_s)
186
+ end
187
+ end
188
+
189
+ TClass.new.test_log # class-logger + 1st object-logger
190
+ TClass.new.test_log # same class-logger + 2nd object-logger
191
+
192
+ TClass::test_log # same class-logger
193
+ puts 'And just say it once clearly: THIS IS COOOL!!'
194
+ end
195
+ #EOF