util 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSES.md ADDED
@@ -0,0 +1,21 @@
1
+ Code principal / Main code / Code principau
2
+ ===========================================
3
+
4
+ Distribué sous license [CeCIll-C](https://cecill.info/licences.fr.html) (plus ou moins équivalent à une LGPL, mais conforme au droit français). Texte complet dans `CECILL-C.FR`.
5
+
6
+ Distributed under [CeCIll-C](https://cecill.info/licences.fr.html) license (more or less a compliant with French law version of LGPL). See full text in `CECILL-C.EN`.
7
+
8
+ Espargi amé la licènci [CeCIll-C](https://cecill.info/licences.fr.html) (mai o mens coume uno LGPL, mai counforme au dre francés). Tèste entié dins `CECILL-C.FR`.
9
+
10
+ ISO 639-3 Code Tables
11
+ =====================
12
+
13
+ The ISO 639-3 code set may be downloaded and incorporated into software products, web-based systems, digital devices, etc., either commercial or non-commercial, provided that:
14
+
15
+ - attribution is given [www.iso639-3.sil.org](https://iso639-3.sil.org) as the source of the codes;
16
+ - the identifiers of the code set are not modified or extended except as may be privately agreed using the Private Use Area (range qaa to qtz), and then such extensions shall not be distributed publicly;
17
+ - the product, system, or device does not provide a means to redistribute the code set.
18
+
19
+ Expansions to the information provided by the standard (e.g., population data, names in other languages, geographic coordinates, etc.) may be made and distributed as long as such added information is clearly identified as not being part of the standard itself. The ISO 639-3 website is the only authorized distribution site for the ISO 639-3 code tables.
20
+
21
+ For any questions about whether a particular use is covered by these guidelines, contact the Registration Authority at [ISO639-3@sil.org](mailto:iso639-3@sil.org).
data/README.md ADDED
@@ -0,0 +1,325 @@
1
+ Gemme `Util`
2
+ ============
3
+
4
+ **English explanations [below](#util-gem). ⇓ Esplicacioun en prouvènçau [dessouto](#gèmo-util).**
5
+
6
+ Cette gemme regroupe un certain nombre de petits utilitaires visant à simplifier l’écriture de code en Ruby. Il n'y a pas de logique particulière dans ce qui y est réuni, si ce n’est que chaque classe correspond à une fonctionnalité répétitive à écrire, mais utile dans de nombreux codes plus spécialisés. Pour l’heure, les classes sont les suivantes (par ordre alphabétique).
7
+
8
+ Sauf mention contraire, toutes les classes sont contenues dans le module principal `Util`. Se reporter à la documentation (en anglais) pour une explication plus détaillée du fonctionnement de chaque classe.
9
+
10
+ ### → `Arg` (classe indépendante)
11
+
12
+ **Attention ! Cette classe va très certainement changer dans une version postérieure.**
13
+
14
+ Cette classe sert à vérifier le type des arguments passés à une fonction et, au besoin, à remplacer un argument invalide par une valeur par défaut.
15
+
16
+ ```ruby
17
+ def creer_dict_entier cle, valeur
18
+ cle = Arg.check cle, Symbol, :def # Nil ne répond pas à #to_sym
19
+ valeur = Arg.check valeur, Integer, nil, true
20
+ # Si nil est passé comme valeur, il doit rester tel quel et non
21
+ # être transformé en 0 par #to_i
22
+ { cle => valeur }
23
+ end
24
+ ```
25
+
26
+ ### → `ConsoleLogger`
27
+
28
+ Cette classe offre une interface simple pour écrire différents types de messages sur le terminal, mis en forme et avec des couleurs. Fortement configurable.
29
+
30
+ ```ruby
31
+ cl = ConsoleLogger.new e: { :stderr => true }
32
+ cl.warning 'Les erreurs seront affichées sur STDERR.'
33
+ # Message écrit en jaune
34
+ begin
35
+ texte = File.read 'secret.msg'
36
+ rescue Exception => e
37
+ msg = 'Impossible d’aller plus loin à cause de %E%, abandon.'
38
+ cl.error msg, 'E': e.message
39
+ # Message écrit en rouge
40
+ end
41
+ ```
42
+
43
+ ### → `I18n`
44
+
45
+ Une classe permettant de faire de l’internationalisation basique. Ce n’est *en rien* un système complet prenant en charge le sens de lecture des langues ou les différentes manières de gérer le pluriel. Un code d’identification et une langue donnent une chaîne de caractères, rien de plus. Si vous avez besoin de quelque chose de plus complexe, il vaudra mieux vous tourner vers la gemme [`i18n`](https://rubygems.org/gems/i18n) de Rails, voire vers `gettext`.
46
+
47
+ ```ruby
48
+ Util::I18n << __FILE__
49
+ Util::I18n.set_default_language :prv
50
+ Util::I18n.message 'bonjour' # 'Adiéu'
51
+ Util::I18n.message 'bonjour', lang: :fra # 'Bonjour'
52
+ ```
53
+
54
+ ### → `Lists`
55
+
56
+ Un module qui regroupe des sous-modules représentant des listes utiles.
57
+
58
+ #### ⇒ `Lists::ISO639`
59
+
60
+ Un module contenant les codes [ISO 639](https://fr.wikipedia.org/wiki/ISO_639). Pour l’instant, seule la classe `P3` contenant les codes ISO 639-3 est disponible.
61
+
62
+ ```ruby
63
+ codes = Util::Lists::ISO639
64
+ puts codes::P3.from1 'fr' # :fre
65
+ puts codes::P3.exist? :prv # true
66
+ puts codes::P3.valid? :prv # false
67
+ ```
68
+
69
+ ### → `Testing`
70
+
71
+ Une classe pour simplifier l’écriture de tests unitaires. Là encore, on reste sur du basique. Pour quelque chose de plus complexe, on se tournera vers des environnements de test dédiés.
72
+
73
+ ```ruby
74
+ class MaClasse
75
+ def self.fonction arg
76
+ raise ArgumentError, 'Ce n’est pas un entier non signé.' unless arg.to_i >= 0
77
+ -arg.to_i
78
+ end
79
+ end
80
+
81
+ test = Util::Testing.new
82
+
83
+ test.register 'succes', [-12, -42] do ||
84
+ [MaClasse.fonction('12'), MaClasse.fonction(42.0)]
85
+ end
86
+
87
+ test.register 'succes-avec-resultat-implicite' do ||
88
+ MaClasse.fonction '12'
89
+ true
90
+ end
91
+
92
+ test.register 'echec-attendu', ArgumentError, 'signé' do ||
93
+ MaClasse.fonction -1
94
+ end
95
+
96
+ test.register 'mauvaise-raison', ArgumentError, 'signé' do ||
97
+ MaClasse.fonction
98
+ end
99
+
100
+ test.register 'mauvaise-exception', ArgumentError, 'signé' do ||
101
+ MonAutreClasse.fonction
102
+ end
103
+
104
+ test.run
105
+ ```
106
+
107
+ ### → `YAML` (module indépendant)
108
+
109
+ Une extension du module `YAML` de la bibliothèque standard, qui se contente d’ajouter une fonction `from_file` permettant de lire un fichier YAML tout en vérifiant qu’aucune erreur ne s’est produite.
110
+
111
+ `Util` gem
112
+ ==========
113
+
114
+ This gem groups together a number of small utilities that aim to make writing code in Ruby easier. There is no specific logic behind the collection, except that each class corresponds to a functionality that is repetitive to write, but useful in many more specialized codes. For now, the following classes are extant (in alphabetical order).
115
+
116
+ Unless specified otherwise, all classes are contained inside the `Util` main module. See the documentation for a more detailed explanation of how each class works.
117
+
118
+ ### → `Arg` (independent class)
119
+
120
+ **Warning! This class will most certainly change in a later version.**
121
+
122
+ This class is used to typecheck the arguments provided to a function and, if needed, replace an invalid argument by a default value.
123
+
124
+ ```ruby
125
+ def create_integer_hash key, value
126
+ key = Arg.check key, Symbol, :def # Nil does not respond to #to_sym
127
+ value = Arg.check value, Integer, nil, true
128
+ # If nil is provided as value, it shall remain as such and not
129
+ # be converted to 0 by #to_i
130
+ { key => value }
131
+ end
132
+ ```
133
+
134
+ ### → `ConsoleLogger`
135
+
136
+ This class offers a simple interface to write different kinds of messages on the console, formatted and colored. Highly configurable.
137
+
138
+ ```ruby
139
+ cl = ConsoleLogger.new e: { :stderr => true }
140
+ cl.warning 'Errors will be logged on STDERR.'
141
+ # Message written in yellow
142
+ begin
143
+ text = File.read 'secret.msg'
144
+ rescue Exception => e
145
+ msg = 'Cannot go any further because of %E%, aborting.'
146
+ cl.error msg, 'E': e.message
147
+ # Message written in red
148
+ end
149
+ ```
150
+
151
+ ### → `I18n`
152
+
153
+ A class to do some basic internationalization. It is *in no way* a full-fledged system that would take into account reading directions or different ways of pluralizing. An token and a language give a string, nothing more. If you need something more complex, you should rather use Rails [`i18n`](https://rubygems.org/gems/i18n) gem, or even `gettext`.
154
+
155
+ ```ruby
156
+ Util::I18n << __FILE__
157
+ Util::I18n.set_default_language :prv
158
+ Util::I18n.message 'bonjour' # 'Adiéu'
159
+ Util::I18n.message 'bonjour', lang: :fra # 'Bonjour'
160
+ ```
161
+
162
+ ### → `Lists`
163
+
164
+ A collection of submodules respresenting useful lists.
165
+
166
+ #### ⇒ `Lists::ISO639`
167
+
168
+ A module containing [ISO 639](https://en.wikipedia.org/wiki/ISO_639) codes. For now, the class `P3` containing ISO 639-3 codes is the only one available.
169
+
170
+ ```ruby
171
+ codes = Util::Lists::ISO639
172
+ puts codes::P3.from1 'fr' # :fre
173
+ puts codes::P3.exist? :prv # true
174
+ puts codes::P3.valid? :prv # false
175
+ ```
176
+
177
+ ### → `Testing`
178
+
179
+ A class to make writing unit tests easier. There again, it remains basic. For something more complex, better go with a dedicated testing framework.
180
+
181
+ ```ruby
182
+ class MyClass
183
+ def self.function arg
184
+ raise ArgumentError, 'Not an unsigned int.' unless arg.to_i >= 0
185
+ -arg.to_i
186
+ end
187
+ end
188
+
189
+ test = Util::Testing.new
190
+
191
+ test.register 'success', [-12, -42] do ||
192
+ [MyClass.function('12'), MyClass.function(42.0)]
193
+ end
194
+
195
+ test.register 'success-with-implicit-result' do ||
196
+ MyClass.function '12'
197
+ true
198
+ end
199
+
200
+ test.register 'expected-fail', ArgumentError, 'unsigned' do ||
201
+ MyClass.function -1
202
+ end
203
+
204
+ test.register 'wrong-reason', ArgumentError, 'unsigned' do ||
205
+ MyClass.function
206
+ end
207
+
208
+ test.register 'wrong-exception', ArgumentError, 'unsigned' do ||
209
+ MyOtherClass.function
210
+ end
211
+
212
+ test.run
213
+ ```
214
+
215
+ ### → `YAML` (module indépendant)
216
+
217
+ An extension to the standard library module `YAML`, that just adds a `from_file` function allowing to read a YAML file while checking that no error happened.
218
+
219
+ Gèmo `Util`
220
+ ===========
221
+
222
+ Aquesto gèmo recampo quauqui pichòtis utilita servènt à escriéure dóu code Ruby mai simplamen. I a pas gaire de lougico dins ço qu’i es reüni, à despart de que cado classo courrespond à quicon de repetitéu à escriéure, mai utile dins un mouloun de code mai especialisa. Aro, li classo soun li seguènto (alfabeticamen).
223
+
224
+ Sènso mencioun countràri, tòuti li classo soun countengudo dins lou moudule principau `Util`. Vèire la doucumentacioun pèr d’esclargimen sus coume marcho cado classo.
225
+
226
+ ### → `Arg` (classo independento)
227
+
228
+ **Mèfi ! Aquesto classo va à cop segur chanja dins uno versioun venento.**
229
+
230
+ Aquesto classo sèr à s’assegura dóu tipe dis argumen passa à-n-uno founcioun e, au besoun, à ramplaça un argumen invalide amé ’no valour pèr defaut.
231
+
232
+ ```ruby
233
+ def crea_dic_entie clau, valour
234
+ clau = Arg.check clau, Symbol, :def # Nil respond pas à #to_sym
235
+ valour = Arg.check valour, Integer, nil, true
236
+ # Se nil es baia coume valour, dèu demoura coume acò e pas èstre
237
+ # vira en 0 pèr #to_i
238
+ { clau => valour }
239
+ end
240
+ ```
241
+
242
+ ### → `ConsoleLogger`
243
+
244
+ Aquesto classo óufris uno interfàci simplo pèr escriéure divèrsi message sus lou terminau, mes en fourmo e acoulouri. Se pòu mai counfigura.
245
+
246
+ ```ruby
247
+ cl = ConsoleLogger.new e: { :stderr => true }
248
+ cl.warning 'Lis errour saran escricho sus STDERR.'
249
+ # Message escri en jaune
250
+ begin
251
+ text = File.read 'secret.msg'
252
+ rescue Exception => e
253
+ msg = 'Impoussible d’ana mai liuen à cause de %E%, abandoun.'
254
+ cl.error msg, 'E': e.message
255
+ # Message escri en rouge
256
+ end
257
+ ```
258
+
259
+ ### → `I18n`
260
+
261
+ Uno classo pèr faire de l’internaciounalisacioun elementàri. Es *pas ges* de sistèmo entié que tèn comte dóu sèns de leituro di lengo vo di biais diferènt de mena lou plurau. Un code d’identificacioun e uno lengo baion uno cadeno d’emprèsso, ges de mai. Se vous fai mestié d’agué quicon de mai coumplèisse, vaudra miés chausi la gèmo [`i18n`](https://rubygems.org/gems/i18n) de Rails, emai bessai `gettext`.
262
+
263
+ ```ruby
264
+ Util::I18n << __FILE__
265
+ Util::I18n.set_default_language :prv
266
+ Util::I18n.message 'bonjour' # 'Adiéu'
267
+ Util::I18n.message 'bonjour', lang: :fra # 'Bonjour'
268
+ ```
269
+
270
+ ### → `Lists`
271
+
272
+ Uno couleicioun de souto-moudule que represènton de tiero utile.
273
+
274
+ #### ⇒ `Lists::ISO639`
275
+
276
+ Un moudule countenènt li code [ISO 639](https://fr.wikipedia.org/wiki/ISO_639). Aro, i a que la classo `P3`, que countèn li code ISO 639-3.
277
+
278
+ ```ruby
279
+ codes = Util::Lists::ISO639
280
+ puts codes::P3.from1 'fr' # :fre
281
+ puts codes::P3.exist? :prv # true
282
+ puts codes::P3.valid? :prv # false
283
+ ```
284
+
285
+ ### → `Testing`
286
+
287
+ Uno classo pèr assimpli l’escrituro d’assai unitàri. Aqui tambèn, demouro elementàri. Pèr quicon de mai coumplèisse, fau chausi un vertadier envirounamen d’assai.
288
+
289
+ ```ruby
290
+ class MaClasso
291
+ def self.founcioun arg
292
+ raise ArgumentError, 'Pas ges d’entié noun signa.' unless arg.to_i >= 0
293
+ -arg.to_i
294
+ end
295
+ end
296
+
297
+ assai = Util::Testing.new
298
+
299
+ assai.register 'reussido', [-12, -42] do ||
300
+ [MaClasso.founcioun('12'), MaClasso.founcioun(42.0)]
301
+ end
302
+
303
+ assai.register 'reussido-senso-resultat-espres' do ||
304
+ MaClasso.founcioun '12'
305
+ true
306
+ end
307
+
308
+ assai.register 'revirado-esperado', ArgumentError, 'signa' do ||
309
+ MaClasso.founcioun -1
310
+ end
311
+
312
+ assai.register 'marrido-encauso', ArgumentError, 'signa' do ||
313
+ MaClasso.founcioun
314
+ end
315
+
316
+ assai.register 'marrido-eicecioun', ArgumentError, 'signa' do ||
317
+ MounAutroClasso.founcioun
318
+ end
319
+
320
+ assai.run
321
+ ```
322
+
323
+ ### → `YAML` (moudule independènt)
324
+
325
+ Vèn espandi lou moudule `YAML` de la biblioutèco ourdinàrio, e fai ren de mai qu’apoundre uno founcioun `from_file`, que permet de legi un fiquié YAML en s’assegurant que i a pas agu d’errour.
data/lib/util.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'util/communia'
2
+ require 'util/console_logger'
3
+ require 'util/i18n'
4
+ require 'util/lists'
5
+ require 'util/yaml'
6
+
7
+ # A collection of simple utilities to reduce boilerplate.
8
+ module Util; end
data/lib/util/arg.rb ADDED
@@ -0,0 +1,90 @@
1
+ # Functions to typecheck the arguments of a function.
2
+ # @note WARNING!! The API of the module will most probably change
3
+ # in future versions of the gem. For now consider it for internal
4
+ # use only.
5
+ class Arg
6
+ private_class_method :new
7
+
8
+ # Verify whether a given argument belongs to a class or can be converted
9
+ # into that class.
10
+ # @param [Object] value argument to check
11
+ # @param [Class, String] klass class to which it must belong; Boolean is a synonym
12
+ # for TrueClass; all standard classes who have #to_X will try to convert
13
+ # the value if it responds to the given conversion method
14
+ # @param [Object] alt value to use if the argument does not belong to the
15
+ # wanted class
16
+ # @param [Boolean] disallow_nil if true and +value+ is +nil+, then +alt+
17
+ # will be returned instead of trying to convert +nil+ to the right type
18
+ # @return [Object]
19
+ # @example
20
+ # def create_integer_hash key, value
21
+ # key = Arg.check key, Symbol, :def # Nil does not respond to #to_sym
22
+ # value = Arg.check value, Integer, nil, true
23
+ # # If nil is provided as value, it shall remain as such and not
24
+ # # be converted to 0 by #to_i
25
+ # { key => value }
26
+ # end
27
+ #
28
+ # hash1 = create_integer_hash 'hello', 13.4 # { :hello => 13 }
29
+ # hash2 = create_integer_hash nil, nil # { :def => nil }
30
+ def self.check value, klass, alt, disallow_nil = false
31
+ return alt if disallow_nil and value.nil?
32
+ case klass.to_s
33
+ when 'Array' then return value.respond_to?(:to_a) ? value.to_a : alt
34
+ when 'Boolean' then return value === true ? true : alt
35
+ when 'Complex' then return value.respond_to?(:to_c) ? value.to_c : alt
36
+ when 'FalseClass' then return value === false ? false : alt
37
+ when 'Float' then return value.respond_to?(:to_f) ? value.to_f : alt
38
+ when 'Hash' then return value.respond_to?(:to_h) ? value.to_h : alt
39
+ when 'Integer' then return value.respond_to?(:to_i) ? value.to_i : alt
40
+ when 'Rational' then return value.respond_to?(:to_r) ? value.to_r : alt
41
+ when 'String' then return value.respond_to?(:to_s) ? value.to_s : alt
42
+ when 'Symbol' then return value.respond_to?(:to_sym) ? value.to_sym : alt
43
+ when 'TrueClass' then return value === true ? true : alt
44
+ else return value.is_a?(klass) ? value : alt
45
+ end
46
+ end
47
+
48
+ # Easier way to typecheck a whole list of argument than individually
49
+ # calling Arg.check on each of them. Takes an array of arrays containing
50
+ # the three or four argument of Arg.check, performs said method on each
51
+ # of them, and returns an array of the results.
52
+ # @param [Array<Array<Object, Class, Object, Boolean>>] array arguments to check
53
+ # @return [Array<Object>]
54
+ # @example
55
+ # def create_integer_hash key, value
56
+ # key, value = Arg.check_a [ [key, Symbol, :def],
57
+ # [value, Integer, nil, true] ]
58
+ # { key => value }
59
+ # end
60
+ def self.check_a array
61
+ result = []
62
+ array.each do |elem|
63
+ value, klass, alt, dis = elem
64
+ result << check(value, klass, alt, (dis.nil? ? false : dis))
65
+ end
66
+ result
67
+ end
68
+
69
+ # Typecheck the content of an options hash, while ignoring undefined
70
+ # options. Calls Arg.check on the values associated with a given key,
71
+ # according to the rest of the informations given.
72
+ # @param [Hash] hash hash whose content to check
73
+ # @param [Array<Array<Object, Class, Object, Boolean>>] array options to check
74
+ # @return [Array<Object>]
75
+ # @example
76
+ # def initialize opts={}
77
+ # opts = Arg.check opts, Hash, {}
78
+ # @encoding, @font_size, @line_height = Arg.check_h opts,
79
+ # [ [:enc, String, 'UTF-8', true], [:size, Integer, 12, true ],
80
+ # [:height, Float, 1.0, true] ]
81
+ # end
82
+ def self.check_h hash, array
83
+ result = []
84
+ array.each do |elem|
85
+ idx, klass, alt, dis = elem
86
+ result << check(hash[idx], klass, alt, (dis.nil? ? false : dis))
87
+ end
88
+ result
89
+ end
90
+ end
@@ -0,0 +1,8 @@
1
+ module Util
2
+ # @no_doc
3
+ # Path to source code of the Ruby part of the gem.
4
+ LIB_PATH = File.dirname(File.dirname(File.expand_path(__FILE__)))
5
+ # @no_doc
6
+ # Path to the data files of the gem.
7
+ SHARE_PATH = File.join File.dirname(LIB_PATH), 'share'
8
+ end