gloo 6.3.1 → 6.5.0
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/CLAUDE.md +13 -0
- data/docs/application.md +9 -0
- data/docs/language_objects.md +78 -0
- data/docs/language_scripting.md +41 -0
- data/docs/objects.md +1 -1
- data/docs/verbs.md +36 -2
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +13 -0
- data/lib/gloo/app/engine.rb +5 -1
- data/lib/gloo/app/log.rb +5 -5
- data/lib/gloo/app/settings.rb +4 -1
- data/lib/gloo/core/obj.rb +60 -1
- data/lib/gloo/core/parser.rb +30 -1
- data/lib/gloo/core/tokens.rb +44 -18
- data/lib/gloo/expr/l_string.rb +8 -4
- data/lib/gloo/objs/basic/script.rb +28 -2
- data/lib/gloo/objs/web/json.rb +4 -1
- data/lib/gloo/persist/comment_buffer.rb +58 -0
- data/lib/gloo/persist/declaration_ledger.rb +61 -0
- data/lib/gloo/persist/disc_mech.rb +15 -2
- data/lib/gloo/persist/file_loader.rb +208 -102
- data/lib/gloo/persist/file_saver.rb +251 -6
- data/lib/gloo/persist/file_storage.rb +10 -4
- data/lib/gloo/persist/indent_stack.rb +90 -0
- data/lib/gloo/persist/line_splitter.rb +18 -3
- data/lib/gloo/persist/persist_man.rb +193 -26
- data/lib/gloo/persist/script_body_collector.rb +102 -0
- data/lib/gloo/persist/shorthand_expander.rb +51 -0
- data/lib/gloo/persist/source/blank_node.rb +27 -0
- data/lib/gloo/persist/source/comment_node.rb +27 -0
- data/lib/gloo/persist/source/directive_node.rb +26 -0
- data/lib/gloo/persist/source/obj_node.rb +91 -0
- data/lib/gloo/persist/source/source_doc.rb +41 -0
- data/lib/gloo/verbs/list.rb +24 -2
- data/lib/gloo/verbs/load.rb +9 -1
- data/lib/gloo/verbs/reload.rb +3 -0
- data/lib/gloo/verbs/save.rb +57 -10
- data/test.gloo/ctrl/each.test.gloo +28 -30
- data/test.gloo/dt/date.test.gloo +69 -71
- data/test.gloo/dt/datetime.test.gloo +55 -57
- data/test.gloo/dt/time.test.gloo +70 -72
- data/test.gloo/lang/continuation.test.gloo +25 -27
- data/test.gloo/lang/convert.test.gloo +50 -52
- data/test.gloo/lang/dt_comparisons.test.gloo +87 -89
- data/test.gloo/lang/exceptions.test.gloo +42 -44
- data/test.gloo/lang/gloo_sys.test.gloo +100 -102
- data/test.gloo/lang/here.test.gloo +32 -34
- data/test.gloo/lang/it.test.gloo +27 -29
- data/test.gloo/lang/literal.test.gloo +55 -57
- data/test.gloo/lang/load_lib_directive.test.gloo +18 -20
- data/test.gloo/lang/naming.test.gloo +28 -30
- data/test.gloo/lang/ops.test.gloo +53 -55
- data/test.gloo/lang/shorthand.test.gloo +27 -0
- data/test.gloo/math/add.test.gloo +40 -42
- data/test.gloo/math/div.test.gloo +23 -25
- data/test.gloo/math/mult.test.gloo +23 -25
- data/test.gloo/math/sub.test.gloo +23 -25
- data/test.gloo/objs/alias.test.gloo +15 -17
- data/test.gloo/objs/bool.test.gloo +54 -56
- data/test.gloo/objs/can.test.gloo +33 -35
- data/test.gloo/objs/cipher.test.gloo +39 -41
- data/test.gloo/objs/decimal.test.gloo +27 -29
- data/test.gloo/objs/erb.test.gloo +47 -49
- data/test.gloo/objs/file.test.gloo +68 -70
- data/test.gloo/objs/function.test.gloo +37 -39
- data/test.gloo/objs/int.test.gloo +54 -56
- data/test.gloo/objs/json.test.gloo +57 -50
- data/test.gloo/objs/obj.test.gloo +68 -48
- data/test.gloo/objs/outline.test.gloo +48 -50
- data/test.gloo/objs/password.test.gloo +34 -36
- data/test.gloo/objs/repeat.test.gloo +42 -44
- data/test.gloo/objs/script.test.gloo +13 -15
- data/test.gloo/objs/string.test.gloo +82 -84
- data/test.gloo/objs/text.test.gloo +90 -92
- data/test.gloo/objs/untyped.test.gloo +36 -38
- data/test.gloo/objs/uri.test.gloo +37 -39
- data/test.gloo/string/str.test.gloo +15 -0
- data/test.gloo/verbs/break.test.gloo +12 -14
- data/test.gloo/verbs/check.test.gloo +22 -24
- data/test.gloo/verbs/context.test.gloo +11 -13
- data/test.gloo/verbs/create.test.gloo +7 -9
- data/test.gloo/verbs/eval.test.gloo +10 -12
- data/test.gloo/verbs/exists.test.gloo +43 -45
- data/test.gloo/verbs/if.test.gloo +8 -10
- data/test.gloo/verbs/invoke.test.gloo +73 -75
- data/test.gloo/verbs/list.test.gloo +21 -23
- data/test.gloo/verbs/load.test.gloo +27 -21
- data/test.gloo/verbs/log.test.gloo +7 -9
- data/test.gloo/verbs/move.test.gloo +12 -14
- data/test.gloo/verbs/put.test.gloo +10 -12
- data/test.gloo/verbs/reload.test.gloo +55 -0
- data/test.gloo/verbs/run.test.gloo +8 -10
- data/test.gloo/verbs/save.test.gloo +111 -0
- data/test.gloo/verbs/show.test.gloo +26 -28
- data/test.gloo/verbs/tell.test.gloo +8 -10
- data/test.gloo/verbs/throw.test.gloo +31 -33
- data/test.gloo/verbs/unless.test.gloo +13 -15
- data/test.gloo/verbs/unload.test.gloo +10 -12
- metadata +14 -1
data/lib/gloo/verbs/list.rb
CHANGED
|
@@ -74,6 +74,7 @@ module Gloo
|
|
|
74
74
|
#
|
|
75
75
|
def show_obj( obj, indent = ' ' )
|
|
76
76
|
theme = @engine.theme
|
|
77
|
+
show_doc( obj, indent ) if @engine.settings.list_docs
|
|
77
78
|
if obj.multiline_value? && obj.value_is_array?
|
|
78
79
|
str = theme.emphasis( "#{indent}#{obj.name}" )
|
|
79
80
|
str << theme.accent( " [#{obj.type_display}] : " )
|
|
@@ -89,6 +90,23 @@ module Gloo
|
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
|
|
93
|
+
#
|
|
94
|
+
# Show the object's doc (its leading comment, cleaned up) above
|
|
95
|
+
# its listing line, one '#'-prefixed line per line of doc.
|
|
96
|
+
# Silent when the object has none.
|
|
97
|
+
#
|
|
98
|
+
def show_doc( obj, indent )
|
|
99
|
+
return if obj.doc.to_s.strip.empty?
|
|
100
|
+
|
|
101
|
+
theme = @engine.theme
|
|
102
|
+
# split( -1 ), not each_line -- a doc ending in a blank '#' line
|
|
103
|
+
# ends with "\n", and each_line silently drops that trailing
|
|
104
|
+
# empty line rather than yielding it.
|
|
105
|
+
obj.doc.split( "\n", -1 ).each do |line|
|
|
106
|
+
@engine.log.show theme.muted( "#{indent}# #{line}".rstrip )
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
92
110
|
#
|
|
93
111
|
# Determine how many levels to show.
|
|
94
112
|
#
|
|
@@ -130,12 +148,16 @@ module Gloo
|
|
|
130
148
|
'current context. When a path is provided, it will be ' \
|
|
131
149
|
'listed instead of the current context. When using context, ' \
|
|
132
150
|
'the current context will be shown, but when context has ' \
|
|
133
|
-
'not been set, the root will be shown.'
|
|
151
|
+
'not been set, the root will be shown. When the list_docs ' \
|
|
152
|
+
'setting is on, any listed object that has a doc (the ' \
|
|
153
|
+
'comment block declared immediately above it in its source ' \
|
|
154
|
+
'file) shows it too.',
|
|
134
155
|
:syntax => [ 'list {path.to.object}' ],
|
|
135
156
|
:parameters => [
|
|
136
157
|
'{path.to.object} — Optional path to object that will be listed. When no path is provided, the current context is used.'
|
|
137
158
|
],
|
|
138
|
-
:result => 'Object and children are listed out in the CLI.'
|
|
159
|
+
:result => 'Object and children are listed out in the CLI. ' \
|
|
160
|
+
'Doc lines are included when the list_docs setting is on.',
|
|
139
161
|
:errors => [
|
|
140
162
|
"#{TARGET_MISSING_ERR}{path.to.object} — The object specified that is to be listed could not be found."
|
|
141
163
|
],
|
data/lib/gloo/verbs/load.rb
CHANGED
|
@@ -122,8 +122,16 @@ module Gloo
|
|
|
122
122
|
:errors => [
|
|
123
123
|
"#{MISSING_EXPR_ERR} — No expression is provided as parameter to the verb.",
|
|
124
124
|
"#{UNKNOWN_OPT_ERR} — The reference type given isn't file, ext, or lib.",
|
|
125
|
-
"#{WRONG_NUM_ARGS_ERR} — load expects 2 or 3 arguments (the verb, an optional reference type, and the file/ext/lib name)."
|
|
125
|
+
"#{WRONG_NUM_ARGS_ERR} — load expects 2 or 3 arguments (the verb, an optional reference type, and the file/ext/lib name).",
|
|
126
|
+
'File not found: {name} — The file name given could not be ' \
|
|
127
|
+
'resolved to a gloo file (checked as a full path, and ' \
|
|
128
|
+
'relative to the project and gloo root folders).'
|
|
126
129
|
],
|
|
130
|
+
:notes => 'Several files can contribute to one container: ' \
|
|
131
|
+
'declare it in each file and add different children, and ' \
|
|
132
|
+
'they merge in the heap. If two loaded files declare the ' \
|
|
133
|
+
'same object with different values, the first one loaded ' \
|
|
134
|
+
'wins and a warning is logged.',
|
|
127
135
|
:examples => <<~EXAMPLES.strip
|
|
128
136
|
> load my/project/file
|
|
129
137
|
> load my/app/*
|
data/lib/gloo/verbs/reload.rb
CHANGED
|
@@ -61,6 +61,9 @@ module Gloo
|
|
|
61
61
|
'loaded again. Note that re-load does not trigger the ' \
|
|
62
62
|
'on_load script to run. There is an on_reload message sent ' \
|
|
63
63
|
'to all open files.',
|
|
64
|
+
:notes => 'If a file has changes that have not been saved, ' \
|
|
65
|
+
'reloading discards them (a warning is logged, but the ' \
|
|
66
|
+
'reload still proceeds).',
|
|
64
67
|
:examples => <<~EXAMPLES.strip
|
|
65
68
|
> reload
|
|
66
69
|
EXAMPLES
|
data/lib/gloo/verbs/save.rb
CHANGED
|
@@ -10,14 +10,16 @@ module Gloo
|
|
|
10
10
|
|
|
11
11
|
KEYWORD = 'save'.freeze
|
|
12
12
|
KEYWORD_SHORT = 'sv'.freeze
|
|
13
|
+
TO = 'to'.freeze
|
|
14
|
+
MISSING_PATH_ERR = "'Save ... to' must include a path!".freeze
|
|
13
15
|
|
|
14
16
|
#
|
|
15
17
|
# Run the verb.
|
|
16
18
|
#
|
|
17
19
|
def run
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
return @engine.persist_man.save @tokens.second unless @tokens.index_of( TO )
|
|
21
|
+
|
|
22
|
+
run_save_to
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
#
|
|
@@ -34,6 +36,26 @@ module Gloo
|
|
|
34
36
|
return KEYWORD_SHORT
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
# ---------------------------------------------------------------------
|
|
40
|
+
# Private functions
|
|
41
|
+
# ---------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Run 'save {obj} to {path}'.
|
|
47
|
+
#
|
|
48
|
+
def run_save_to
|
|
49
|
+
name = @tokens.before_token( TO )[ 1 ]
|
|
50
|
+
path = @tokens.after_token( TO )
|
|
51
|
+
unless path
|
|
52
|
+
@engine.err MISSING_PATH_ERR
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@engine.persist_man.save_to( name, path )
|
|
57
|
+
end
|
|
58
|
+
|
|
37
59
|
# ---------------------------------------------------------------------
|
|
38
60
|
# Verb Documentation
|
|
39
61
|
# ---------------------------------------------------------------------
|
|
@@ -45,17 +67,42 @@ module Gloo
|
|
|
45
67
|
{
|
|
46
68
|
:name => KEYWORD,
|
|
47
69
|
:shortcut => KEYWORD_SHORT,
|
|
48
|
-
:description => 'Save
|
|
49
|
-
'
|
|
50
|
-
'
|
|
51
|
-
|
|
70
|
+
:description => 'Save an object to a .gloo file. With no ' \
|
|
71
|
+
'path, saves every file that owns a declaration in the ' \
|
|
72
|
+
"object's root (its file, or every contributing file for " \
|
|
73
|
+
'a namespace shared across several files); with no object ' \
|
|
74
|
+
'at all, saves every open file. An object not yet mapped ' \
|
|
75
|
+
'to a file is saved fresh, either to a given path or to a ' \
|
|
76
|
+
"default path built from the object's own name.",
|
|
77
|
+
:syntax => [
|
|
78
|
+
'save',
|
|
79
|
+
'save {path.to.object}',
|
|
80
|
+
'save {path.to.object} to {path}'
|
|
81
|
+
],
|
|
52
82
|
:parameters => [
|
|
53
|
-
'{path.to.object} — Name of the object
|
|
83
|
+
'{path.to.object} — Name of the object to save.',
|
|
84
|
+
'{path} — Where to save it, relative to the project root ' \
|
|
85
|
+
'(.gloo appended if omitted). Registers the mapping, so ' \
|
|
86
|
+
'a later bare save includes it.'
|
|
87
|
+
],
|
|
88
|
+
:result => 'The file(s) are updated with the latest object ' \
|
|
89
|
+
'state. This is a rewrite, not a regeneration: comments, ' \
|
|
90
|
+
'blank lines, and the original formatting are preserved, ' \
|
|
91
|
+
'and only values that actually changed are re-written.',
|
|
92
|
+
:errors => [
|
|
93
|
+
"#{MISSING_PATH_ERR} — 'to' was given with nothing after it.",
|
|
94
|
+
'Could not resolve object to save — the object was not found.',
|
|
95
|
+
'Will not overwrite a file not already saved there — the ' \
|
|
96
|
+
'target path exists but is not mapped to this object.'
|
|
54
97
|
],
|
|
55
|
-
:
|
|
56
|
-
|
|
98
|
+
:notes => 'An object can also be told to save itself: ' \
|
|
99
|
+
'`tell my_obj to save`. When several files contribute to ' \
|
|
100
|
+
'one container (the namespace pattern), each file save only ' \
|
|
101
|
+
"rewrites that file's own declarations.",
|
|
57
102
|
:examples => <<~EXAMPLES.strip
|
|
103
|
+
> save
|
|
58
104
|
> save my_obj
|
|
105
|
+
> save my_obj to sub/my_obj
|
|
59
106
|
EXAMPLES
|
|
60
107
|
}
|
|
61
108
|
end
|
|
@@ -2,38 +2,36 @@
|
|
|
2
2
|
# Each and repeat control object tests
|
|
3
3
|
#
|
|
4
4
|
|
|
5
|
-
tests [can] :
|
|
6
|
-
ctrl [can] :
|
|
7
|
-
each [can] :
|
|
5
|
+
tests.ctrl.each [can] :
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
count [int] : 0
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
wrd [each] :
|
|
10
|
+
word [string] :
|
|
11
|
+
IN [string] : one two three
|
|
12
|
+
do [script] :
|
|
13
|
+
eval ^^.count + 1
|
|
14
|
+
put it into ^^.count
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
rpt [repeat] :
|
|
17
|
+
times [int] : 3
|
|
18
|
+
index [int] : 0
|
|
19
|
+
do [script] :
|
|
20
|
+
eval ^^.count + 1
|
|
21
|
+
put it into ^^.count
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
each_word [test] :
|
|
24
|
+
description [string] : Count words with each word
|
|
25
|
+
on_test [script] :
|
|
26
|
+
put 0 into ^^.count
|
|
27
|
+
tell ^^.wrd to run
|
|
28
|
+
eval ^^.count = 3
|
|
29
|
+
assert "expected 3 words counted"
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
repeat_n_times [test] :
|
|
32
|
+
description [string] : Repeat a script n times
|
|
33
|
+
on_test [script] :
|
|
34
|
+
put 0 into ^^.count
|
|
35
|
+
tell ^^.rpt to run
|
|
36
|
+
eval ^^.count = 3
|
|
37
|
+
assert "expected repeat to run 3 times"
|
data/test.gloo/dt/date.test.gloo
CHANGED
|
@@ -2,87 +2,85 @@
|
|
|
2
2
|
# Date tests
|
|
3
3
|
#
|
|
4
4
|
|
|
5
|
-
tests [can] :
|
|
6
|
-
dt [can] :
|
|
7
|
-
date [can] :
|
|
5
|
+
tests.dt.date [can] :
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
d [date] :
|
|
8
|
+
x [date] :
|
|
9
|
+
future [date] :
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
now [test] :
|
|
12
|
+
description [string] : Get the current date
|
|
13
|
+
on_test [script] :
|
|
14
|
+
check ^^.x for blank?
|
|
15
|
+
assert "expected new date to be blank"
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
tell ^^.x to now
|
|
18
|
+
check ^^.x for blank?
|
|
19
|
+
refute "expected date to not be blank"
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
tell ^^.d to now
|
|
22
|
+
eval ^^.d = ^^.x
|
|
23
|
+
assert "expected dates to be equal"
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
add [test] :
|
|
26
|
+
description [string] : Add days to a date
|
|
27
|
+
on_test [script] :
|
|
28
|
+
tell ^^.d to now
|
|
29
|
+
tell ^^.future to now
|
|
30
|
+
tell ^^.future to add
|
|
31
|
+
eval ^^.future = ^^.d
|
|
32
|
+
refute "expected future date to be after current date"
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
subtract [test] :
|
|
35
|
+
description [string] : Subtract days from a date
|
|
36
|
+
on_test [script] :
|
|
37
|
+
tell ^^.d to now
|
|
38
|
+
tell ^^.future to now
|
|
39
|
+
tell ^^.future to sub
|
|
40
|
+
eval ^^.future = ^^.d
|
|
41
|
+
refute "expected past date to be before current date"
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
dd [test] :
|
|
44
|
+
description [string] : Get the day portion of a date
|
|
45
|
+
on_test [script] :
|
|
46
|
+
tell ^^.d to now
|
|
47
|
+
tell ^^.d to dd
|
|
48
|
+
eval it = ^^.d
|
|
49
|
+
refute "expected day to not be the same as the date"
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
mm [test] :
|
|
52
|
+
description [string] : Get the month portion of a date
|
|
53
|
+
on_test [script] :
|
|
54
|
+
tell ^^.d to now
|
|
55
|
+
tell ^^.d to mm
|
|
56
|
+
eval it = ^^.d
|
|
57
|
+
refute "expected month to not be the same as the date"
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
yy [test] :
|
|
60
|
+
description [string] : Get the year portion of a date
|
|
61
|
+
on_test [script] :
|
|
62
|
+
tell ^^.d to now
|
|
63
|
+
tell ^^.d to yy
|
|
64
|
+
eval it = ^^.d
|
|
65
|
+
refute "expected year to not be the same as the date"
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
yyyy [test] :
|
|
68
|
+
description [string] : Get the 4 digit year portion of a date
|
|
69
|
+
on_test [script] :
|
|
70
|
+
tell ^^.d to now
|
|
71
|
+
tell ^^.d to yyyy
|
|
72
|
+
eval ^^.d = it
|
|
73
|
+
refute "expected yyyy to not be the same as the date"
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
format [test] :
|
|
76
|
+
description [string] : Format a date
|
|
77
|
+
on_test [script] :
|
|
78
|
+
put '2025.10.15' into ^^.d
|
|
79
|
+
tell ^^.d to format
|
|
80
|
+
eval it = '2025-10-15'
|
|
81
|
+
assert "expected formatted date to match"
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
tell ^^.d to format ('%m/%d')
|
|
84
|
+
eval it = '10/15'
|
|
85
|
+
assert "expected formatted date to match"
|
|
88
86
|
|
|
@@ -2,60 +2,58 @@
|
|
|
2
2
|
# Datetime tests
|
|
3
3
|
#
|
|
4
4
|
|
|
5
|
-
tests [can] :
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
eval it = '10/15/2025'
|
|
61
|
-
assert "expected formatted datetime to match"
|
|
5
|
+
tests.dt.datetime [can] :
|
|
6
|
+
|
|
7
|
+
d [dt] :
|
|
8
|
+
|
|
9
|
+
now [test] :
|
|
10
|
+
description [string] : Get the current datetime
|
|
11
|
+
on_test [script] :
|
|
12
|
+
check ^^.d for blank?
|
|
13
|
+
assert "expected new datetime to be blank"
|
|
14
|
+
|
|
15
|
+
tell ^^.d to now
|
|
16
|
+
check ^^.d for blank?
|
|
17
|
+
refute "expected datetime to not be blank after now"
|
|
18
|
+
|
|
19
|
+
is_today [test] :
|
|
20
|
+
description [string] : Check if datetime is today
|
|
21
|
+
on_test [script] :
|
|
22
|
+
tell ^^.d to now
|
|
23
|
+
tell ^^.d to is_today
|
|
24
|
+
assert "expected current datetime to be today"
|
|
25
|
+
|
|
26
|
+
is_past [test] :
|
|
27
|
+
description [string] : Check if datetime is in the past
|
|
28
|
+
on_test [script] :
|
|
29
|
+
tell ^^.d to now
|
|
30
|
+
tell ^^.d to is_past
|
|
31
|
+
refute "expected current datetime to not be in the past"
|
|
32
|
+
|
|
33
|
+
put 'yesterday' into ^^.d
|
|
34
|
+
tell ^^.d to is_past
|
|
35
|
+
assert "expected yesterday to be in the past"
|
|
36
|
+
|
|
37
|
+
is_future [test] :
|
|
38
|
+
description [string] : Check if datetime is in the future
|
|
39
|
+
on_test [script] :
|
|
40
|
+
tell ^^.d to now
|
|
41
|
+
tell ^^.d to is_future
|
|
42
|
+
refute "expected current datetime to not be in the future"
|
|
43
|
+
|
|
44
|
+
put 'tomorrow' into ^^.d
|
|
45
|
+
tell ^^.d to is_future
|
|
46
|
+
assert "expected tomorrow to be in the future"
|
|
47
|
+
|
|
48
|
+
format [test] :
|
|
49
|
+
description [string] : Format a datetime
|
|
50
|
+
f [dt] :
|
|
51
|
+
on_test [script] :
|
|
52
|
+
put '2025.10.15 2:30:00 PM' into ^.f
|
|
53
|
+
tell ^.f to format
|
|
54
|
+
eval it = '2025-10-15 14:30:00'
|
|
55
|
+
assert "expected formatted datetime to match"
|
|
56
|
+
|
|
57
|
+
tell ^.f to format ('%m/%d/%Y')
|
|
58
|
+
eval it = '10/15/2025'
|
|
59
|
+
assert "expected formatted datetime to match"
|