cocos 0.4.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/Manifest.txt +1 -0
- data/lib/cocos/env.rb +22 -17
- data/lib/cocos/find_file.rb +45 -0
- data/lib/cocos/version.rb +1 -1
- data/lib/cocos.rb +62 -15
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51832aaf3ccd7164304a1c4652108b89d7651d2d7358e80c8f0d24fa46f59f69
|
|
4
|
+
data.tar.gz: 3236f78ad3ced02d1ac42a047a0ce11eaf60017063b61c2c1480786e3513ddc0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 11206d11694da8a98bf33b2c444975ec3e195e4c29348f761945fba044fe582d5ab885bb8a5d3057f3ce5589ba288bc14b9d2b456e0003fa74537ac5efa3d0a1
|
|
7
|
+
data.tar.gz: 8f9e09293599531c4fd4482295fc75e0d7aeea95ffe5de62f7c2bc4d2e84a4e8b643109682accdb98b3295e30e89265f0aa6b36dbcaf70e25adfd8488ea6ba8c
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/lib/cocos/env.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# simple read_env, load_env machinery
|
|
3
3
|
## inspired by
|
|
4
4
|
## dotenv gem -> https://github.com/bkeepers/dotenv
|
|
5
|
-
## figaro -> https://github.com/laserlemon/figaro
|
|
5
|
+
## figaro -> https://github.com/laserlemon/figaro
|
|
6
6
|
## and others
|
|
7
7
|
|
|
8
8
|
|
|
@@ -19,54 +19,59 @@ module EnvParser
|
|
|
19
19
|
parse( text )
|
|
20
20
|
end
|
|
21
21
|
def self.load( text ) parse( text ); end
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
24
|
class Error < StandardError; end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
## todo/check - what is JSON and YAML returning Parser/ParseError something else?
|
|
27
27
|
## YAML uses ParseError and JSON uses ParserError
|
|
28
28
|
class ParseError < Error; end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
|
|
31
31
|
## todo/check - if support for empty values e.g. abc= is required/possible???
|
|
32
32
|
## todo/ addd support for quoted values - why? why not?
|
|
33
33
|
## add support for "inline" end of line comments - why? why not?
|
|
34
34
|
## add support for escapes and multi-line values - why? why not?
|
|
35
|
-
|
|
35
|
+
LINE_RE = /\A
|
|
36
|
+
[ ]*
|
|
37
|
+
(?<key> [A-Za-z][A-Za-z0-9_-]*)
|
|
36
38
|
[ ]*
|
|
37
39
|
=
|
|
38
40
|
[ ]*
|
|
39
41
|
(?<value>.+?) ## non-greedy
|
|
42
|
+
[ ]*
|
|
40
43
|
\z
|
|
41
44
|
/x
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
## use a parser class - why? why not?
|
|
47
|
+
def self.parse( text )
|
|
48
|
+
h = {}
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
lineno = 0
|
|
48
51
|
text.each_line do |line|
|
|
49
52
|
lineno += 1 ## track line numbers for (parse) error reporting
|
|
50
|
-
|
|
51
53
|
line = line.strip ## check: use strip (or be more strict) - why? why not?
|
|
54
|
+
|
|
52
55
|
## skip empty and comment lines
|
|
53
|
-
next
|
|
56
|
+
next if line.empty? || line.start_with?( '#' )
|
|
57
|
+
## support __END__ marker for inline comments
|
|
58
|
+
break if line == '__END__'
|
|
54
59
|
|
|
55
|
-
if m=
|
|
60
|
+
if m=LINE_RE.match(line)
|
|
56
61
|
key = m[:key]
|
|
57
62
|
value = m[:value]
|
|
58
|
-
|
|
63
|
+
|
|
59
64
|
## todo/check - check/warn about duplicates - why? why not?
|
|
60
65
|
h[key] = value
|
|
61
|
-
|
|
66
|
+
else
|
|
62
67
|
raise ParseError, "line #{lineno} - unknown line type; cannot parse >#{line}<"
|
|
63
|
-
|
|
68
|
+
end
|
|
64
69
|
end
|
|
65
70
|
h
|
|
66
71
|
end # methdod self.parse
|
|
67
72
|
end # module EnvParser
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
|
|
70
75
|
|
|
71
76
|
__END__
|
|
72
77
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
## note - use File.file? instead of File.exist?
|
|
5
|
+
## (checks if file exists AND file is a file NOT a directory)
|
|
6
|
+
##
|
|
7
|
+
##
|
|
8
|
+
## add option - raise_on_error: false - why? why not?
|
|
9
|
+
## def find_file! - find_file( raise_on_error: false )
|
|
10
|
+
##
|
|
11
|
+
## todo/check
|
|
12
|
+
## golang lookup_path or such
|
|
13
|
+
## always return absolute (expanded) path - why? why not?
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
module Kernel
|
|
17
|
+
|
|
18
|
+
def find_file!( name, path: )
|
|
19
|
+
filepath = find_file( name, path: path )
|
|
20
|
+
raise Errorno::ENOENT, "file <#{name}> not found; looking in path #{path.inspect}" if filepath.nil?
|
|
21
|
+
filepath
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
## note - find_file will NOT find directories!!!
|
|
26
|
+
## File.file? will only check if a file (not directory) exits!!
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
## todo/check - expand path and use File.realpath too?
|
|
31
|
+
## or keep "simple" File.join ?
|
|
32
|
+
|
|
33
|
+
def find_file( name, path: )
|
|
34
|
+
return name if File.file?( name )
|
|
35
|
+
|
|
36
|
+
path.each do |dir|
|
|
37
|
+
filepath = File.join( dir, name )
|
|
38
|
+
return filepath if File.file?( filepath )
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
nil ## return nil if not found
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
end # module Kernel
|
data/lib/cocos/version.rb
CHANGED
data/lib/cocos.rb
CHANGED
|
@@ -33,6 +33,9 @@ require_relative 'cocos/version' # note: let version always go first
|
|
|
33
33
|
require_relative 'cocos/env' ## e.g. EnvParser
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
require_relative 'cocos/find_file'
|
|
37
|
+
|
|
38
|
+
|
|
36
39
|
###
|
|
37
40
|
## read/parse convenience/helper shortcuts
|
|
38
41
|
|
|
@@ -151,8 +154,8 @@ def download_ini( url )
|
|
|
151
154
|
parse_ini( download_text( url ))
|
|
152
155
|
end
|
|
153
156
|
|
|
154
|
-
alias_method :read_conf,
|
|
155
|
-
alias_method :parse_conf,
|
|
157
|
+
alias_method :read_conf, :read_ini
|
|
158
|
+
alias_method :parse_conf, :parse_ini
|
|
156
159
|
alias_method :download_conf, :download_ini
|
|
157
160
|
|
|
158
161
|
|
|
@@ -222,11 +225,17 @@ def parse_env( str )
|
|
|
222
225
|
end
|
|
223
226
|
|
|
224
227
|
|
|
228
|
+
|
|
229
|
+
|
|
225
230
|
##
|
|
226
231
|
## todo/check - change path to *paths=['./.env']
|
|
227
232
|
## and support more files - why? why not?
|
|
233
|
+
##
|
|
234
|
+
## note - use File.file? instead of File.exist?
|
|
235
|
+
## will avoid matching directories!
|
|
236
|
+
|
|
228
237
|
def load_env( path='./.env' )
|
|
229
|
-
if File.
|
|
238
|
+
if File.file?( path )
|
|
230
239
|
puts "==> loading .env settings..."
|
|
231
240
|
env = read_env( path )
|
|
232
241
|
puts " applying .env settings... (merging into ENV)"
|
|
@@ -291,7 +300,7 @@ alias_method :write_txt, :write_text
|
|
|
291
300
|
|
|
292
301
|
|
|
293
302
|
|
|
294
|
-
|
|
303
|
+
|
|
295
304
|
# note:
|
|
296
305
|
# for now write_csv expects array of string arrays
|
|
297
306
|
# does NOT support array of hashes for now
|
|
@@ -301,21 +310,16 @@ def write_csv( path, recs, headers: nil )
|
|
|
301
310
|
FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
|
|
302
311
|
|
|
303
312
|
File.open( path, 'w:utf-8' ) do |f|
|
|
304
|
-
if headers
|
|
305
|
-
f.write( headers.
|
|
313
|
+
if headers ## e.g. Date,Team 1,FT,HT,Team 2
|
|
314
|
+
f.write( headers.map do |header|
|
|
315
|
+
_escape_csv( header )
|
|
316
|
+
end.join(',') )
|
|
306
317
|
f.write( "\n" )
|
|
307
318
|
end
|
|
308
319
|
|
|
309
320
|
recs.each do |values|
|
|
310
|
-
## quote values that incl. a comma
|
|
311
|
-
## todo/fix - add more escape/quote checks - why? why not?
|
|
312
|
-
## check how other csv libs handle value generation
|
|
313
321
|
buf = values.map do |value|
|
|
314
|
-
|
|
315
|
-
%Q{"#{value}"}
|
|
316
|
-
else
|
|
317
|
-
value
|
|
318
|
-
end
|
|
322
|
+
_escape_csv( value )
|
|
319
323
|
end.join( ',' )
|
|
320
324
|
|
|
321
325
|
f.write( buf )
|
|
@@ -326,6 +330,50 @@ end
|
|
|
326
330
|
|
|
327
331
|
|
|
328
332
|
|
|
333
|
+
## quote values that incl. a comma
|
|
334
|
+
## todo/fix - add more escape/quote checks - why? why not?
|
|
335
|
+
## check how other csv libs handle value generation
|
|
336
|
+
##
|
|
337
|
+
## If a field contains
|
|
338
|
+
## - a comma (,)
|
|
339
|
+
## - a double quote (")
|
|
340
|
+
## - a newline (\r\n)
|
|
341
|
+
## then wrap the field in quotes
|
|
342
|
+
## Inside quoted fields, double every double quote (" → "")
|
|
343
|
+
|
|
344
|
+
def _escape_csv(value)
|
|
345
|
+
## auto-convert to string or let code fail on nil or such?
|
|
346
|
+
value = value.to_s
|
|
347
|
+
|
|
348
|
+
## note - double double quotes (") for now only
|
|
349
|
+
## check
|
|
350
|
+
## - escape newline (lf) as \n or keep it literal - why? why not?
|
|
351
|
+
## what about \r carriage return (cr)
|
|
352
|
+
##
|
|
353
|
+
## add value.match?(/\A\s|\s\z/) ||
|
|
354
|
+
## to preserve leading/trailing spaces in value ???
|
|
355
|
+
## e.g. _a_ becomes "_a_" written out
|
|
356
|
+
##
|
|
357
|
+
## quote empty strings or keep them empty
|
|
358
|
+
## what about nil - for now empty string too
|
|
359
|
+
## add nil_value option e.g. 'n/a' or such
|
|
360
|
+
## and quote_empty true|false - why? why not?
|
|
361
|
+
if value.include?(',') ||
|
|
362
|
+
value.include?('"') ||
|
|
363
|
+
value.include?("\n") ||
|
|
364
|
+
value.include?("\r")
|
|
365
|
+
'"' + value.gsub('"', '""') + '"'
|
|
366
|
+
else
|
|
367
|
+
value
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
329
377
|
######
|
|
330
378
|
# world wide web (www) support
|
|
331
379
|
|
|
@@ -356,4 +404,3 @@ Coco = Cocos
|
|
|
356
404
|
|
|
357
405
|
|
|
358
406
|
puts Cocos.banner ## say hello
|
|
359
|
-
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cocos
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gerald Bauer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: csvreader
|
|
@@ -92,14 +92,14 @@ dependencies:
|
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '4.
|
|
95
|
+
version: '4.2'
|
|
96
96
|
type: :development
|
|
97
97
|
prerelease: false
|
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
100
|
- - "~>"
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '4.
|
|
102
|
+
version: '4.2'
|
|
103
103
|
description: cocos (code commons) - auto-include quick-starter prelude & prolog
|
|
104
104
|
email: gerald.bauer@gmail.com
|
|
105
105
|
executables: []
|
|
@@ -117,6 +117,7 @@ files:
|
|
|
117
117
|
- Rakefile
|
|
118
118
|
- lib/cocos.rb
|
|
119
119
|
- lib/cocos/env.rb
|
|
120
|
+
- lib/cocos/find_file.rb
|
|
120
121
|
- lib/cocos/version.rb
|
|
121
122
|
homepage: https://github.com/rubycocos/cocos
|
|
122
123
|
licenses:
|
|
@@ -139,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
139
140
|
- !ruby/object:Gem::Version
|
|
140
141
|
version: '0'
|
|
141
142
|
requirements: []
|
|
142
|
-
rubygems_version: 3.
|
|
143
|
+
rubygems_version: 3.5.22
|
|
143
144
|
signing_key:
|
|
144
145
|
specification_version: 4
|
|
145
146
|
summary: cocos (code commons) - auto-include quick-starter prelude & prolog
|