gloo 6.0 → 6.1.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +9 -3
  3. data/README.md +38 -7
  4. data/docs/application.md +164 -0
  5. data/docs/getting_started.md +112 -0
  6. data/docs/iterators.md +294 -0
  7. data/docs/language_objects.md +190 -0
  8. data/docs/language_scripting.md +62 -0
  9. data/docs/language_syntax.md +307 -0
  10. data/docs/objects.md +77 -0
  11. data/docs/operators.md +62 -0
  12. data/docs/plugins.md +54 -0
  13. data/docs/verbs.md +64 -0
  14. data/gloo.gemspec +5 -3
  15. data/lib/VERSION +1 -1
  16. data/lib/VERSION_NOTES +14 -0
  17. data/lib/gloo/app/platform.rb +29 -2
  18. data/lib/gloo/app/settings.rb +1 -1
  19. data/lib/gloo/core/gloo_system.rb +52 -1
  20. data/lib/gloo/docs/doc_data.rb +160 -0
  21. data/lib/gloo/docs/help_shell.rb +285 -0
  22. data/lib/gloo/docs/markdown_renderer.rb +39 -0
  23. data/lib/gloo/objs/basic/alias.rb +53 -0
  24. data/lib/gloo/objs/basic/boolean.rb +30 -0
  25. data/lib/gloo/objs/basic/container.rb +38 -0
  26. data/lib/gloo/objs/basic/decimal.rb +30 -0
  27. data/lib/gloo/objs/basic/integer.rb +58 -0
  28. data/lib/gloo/objs/basic/script.rb +31 -0
  29. data/lib/gloo/objs/basic/string.rb +51 -4
  30. data/lib/gloo/objs/basic/string_msgs.rb +20 -0
  31. data/lib/gloo/objs/basic/text.rb +51 -4
  32. data/lib/gloo/objs/basic/untyped.rb +21 -0
  33. data/lib/gloo/objs/ctrl/each.rb +63 -1
  34. data/lib/gloo/objs/ctrl/function.rb +69 -0
  35. data/lib/gloo/objs/ctrl/repeat.rb +41 -0
  36. data/lib/gloo/objs/dt/date.rb +43 -0
  37. data/lib/gloo/objs/dt/datetime.rb +50 -0
  38. data/lib/gloo/objs/dt/time.rb +43 -0
  39. data/lib/gloo/objs/str_utils/cipher.rb +59 -0
  40. data/lib/gloo/objs/str_utils/outline.rb +65 -1
  41. data/lib/gloo/objs/str_utils/password.rb +56 -0
  42. data/lib/gloo/objs/system/erb.rb +39 -0
  43. data/lib/gloo/objs/system/file_handle.rb +56 -0
  44. data/lib/gloo/objs/system/system.rb +29 -0
  45. data/lib/gloo/objs/web/http_get.rb +35 -0
  46. data/lib/gloo/objs/web/http_post.rb +33 -0
  47. data/lib/gloo/objs/web/json.rb +40 -0
  48. data/lib/gloo/objs/web/uri.rb +40 -0
  49. data/lib/gloo/shell/command_node.rb +39 -0
  50. data/lib/gloo/shell/context.rb +93 -0
  51. data/lib/gloo/shell/runner.rb +315 -0
  52. data/lib/gloo/verbs/break.rb +32 -0
  53. data/lib/gloo/verbs/check.rb +49 -0
  54. data/lib/gloo/verbs/cls.rb +18 -0
  55. data/lib/gloo/verbs/context.rb +47 -0
  56. data/lib/gloo/verbs/create.rb +42 -0
  57. data/lib/gloo/verbs/eval.rb +27 -0
  58. data/lib/gloo/verbs/execute.rb +27 -0
  59. data/lib/gloo/verbs/exists.rb +54 -2
  60. data/lib/gloo/verbs/files.rb +22 -0
  61. data/lib/gloo/verbs/help.rb +43 -178
  62. data/lib/gloo/verbs/if.rb +52 -0
  63. data/lib/gloo/verbs/invoke.rb +62 -0
  64. data/lib/gloo/verbs/list.rb +32 -0
  65. data/lib/gloo/verbs/load.rb +55 -2
  66. data/lib/gloo/verbs/log.rb +44 -0
  67. data/lib/gloo/verbs/move.rb +36 -1
  68. data/lib/gloo/verbs/put.rb +35 -0
  69. data/lib/gloo/verbs/quit.rb +19 -0
  70. data/lib/gloo/verbs/redirect.rb +52 -2
  71. data/lib/gloo/verbs/reload.rb +27 -0
  72. data/lib/gloo/verbs/run.rb +39 -0
  73. data/lib/gloo/verbs/save.rb +26 -0
  74. data/lib/gloo/verbs/show.rb +54 -0
  75. data/lib/gloo/verbs/tell.rb +32 -0
  76. data/lib/gloo/verbs/throw.rb +29 -0
  77. data/lib/gloo/verbs/unless.rb +50 -0
  78. data/lib/gloo/verbs/unload.rb +23 -0
  79. data/lib/gloo/verbs/version.rb +37 -3
  80. data/lib/gloo/verbs/wait.rb +26 -0
  81. metadata +28 -20
@@ -159,6 +159,62 @@ module Gloo
159
159
  @engine.heap.it.set_to result
160
160
  end
161
161
 
162
+ # ---------------------------------------------------------------------
163
+ # Object Documentation
164
+ # ---------------------------------------------------------------------
165
+
166
+ #
167
+ # Get the object's documentation data.
168
+ #
169
+ def self.doc_data
170
+ {
171
+ :name => KEYWORD,
172
+ :shortcut => KEYWORD_SHORT,
173
+ :description => 'A password object that can be generated, hashed, and compared.',
174
+ :children => [
175
+ 'salt (string) — Optional salt to use when hashing and checking passwords.',
176
+ 'password (string) — The password. generate puts a new random password here. Used in the hash and check messages.',
177
+ 'hash (string) — The hashed value of the password. Created when the hash message is called, and compared when the check message is called.'
178
+ ],
179
+ :messages => [
180
+ 'generate ({len}) — Generate a new password, put in the password child object. The {len} parameter is optional; the length is 7 if not specified.',
181
+ 'hash — Hash the password in the child object. Put it in the hash child object.',
182
+ 'check — Check the password in the child object. Is it the same as the hash?'
183
+ ],
184
+ :examples => <<~EXAMPLES.strip
185
+ #
186
+ # Password Hashing and checking.
187
+ #
188
+ password [can] :
189
+
190
+ pwd [password] :
191
+ salt [string] : MySalt
192
+ password [string] :
193
+ hash [string] :
194
+
195
+ on_load [script] :
196
+ show
197
+ show 'Generating a new password' (white)
198
+ tell ^.pwd to generate
199
+ show 'Password: ' + ^.pwd.password
200
+ show
201
+ show 'hashing the password' (white)
202
+ tell ^.pwd to hash
203
+ show ^.pwd.hash (red)
204
+ show
205
+ show 'checking with the correct password' (white)
206
+ tell ^.pwd to check
207
+ show 'Result of check: ' + it (green)
208
+ show
209
+ show 'checking with the wrong password' (white)
210
+ tell ^.pwd to generate(23)
211
+ tell ^.pwd to check
212
+ show 'Result of check: ' + it (red)
213
+ show
214
+ EXAMPLES
215
+ }
216
+ end
217
+
162
218
  end
163
219
  end
164
220
  end
@@ -110,6 +110,45 @@ module Gloo
110
110
  set_result render.result_with_hash( param_hash )
111
111
  end
112
112
 
113
+ # ---------------------------------------------------------------------
114
+ # Object Documentation
115
+ # ---------------------------------------------------------------------
116
+
117
+ #
118
+ # Get the object's documentation data.
119
+ #
120
+ def self.doc_data
121
+ {
122
+ :name => KEYWORD,
123
+ :shortcut => KEYWORD_SHORT,
124
+ :description => 'Use the ERB templating system to generate ' \
125
+ 'content. For example, you can use the ERB object for ' \
126
+ 'string interpolation.',
127
+ :children => [
128
+ 'template (text) — The template that will be used when the ERB object is run.',
129
+ 'params (container) — The collection of children values used when the template is rendered.',
130
+ 'result (text) — The result of the template rendering.'
131
+ ],
132
+ :messages => [
133
+ 'run — Render the result based on the template and the parameter values.'
134
+ ],
135
+ :examples => <<~EXAMPLES.strip
136
+ e [can] :
137
+ erb [erb] :
138
+ template [text] : BEGIN
139
+ Hello <%= first %> <%= last %>!
140
+ END
141
+ params [container] :
142
+ first [string] : Eric
143
+ last [string] : Crane
144
+ result [text] :
145
+ on_load [script] :
146
+ run e.erb
147
+ show e.erb.result
148
+ EXAMPLES
149
+ }
150
+ end
151
+
113
152
  end
114
153
  end
115
154
  end
@@ -239,6 +239,62 @@ module Gloo
239
239
  return true
240
240
  end
241
241
 
242
+ # ---------------------------------------------------------------------
243
+ # Object Documentation
244
+ # ---------------------------------------------------------------------
245
+
246
+ #
247
+ # Get the object's documentation data.
248
+ #
249
+ def self.doc_data
250
+ {
251
+ :name => KEYWORD,
252
+ :shortcut => KEYWORD_SHORT,
253
+ :description => 'Reference to a file or folder (directory) ' \
254
+ 'on disk. The string value of the file object is the path ' \
255
+ 'and name of the file.',
256
+ :messages => [
257
+ 'read ({into.obj}) — Read the file and put the data in the specified object. If {into.obj} is not specified, the data will be in it.',
258
+ 'write ({from.obj}) — Write the data in {from.obj} into the file.',
259
+ 'append ({data}) — Append the given data to the file as a new line. Adds a leading newline first if the file doesn\'t already end with one.',
260
+ 'delete — Delete the file.',
261
+ 'get_name — Get the name of the file without path or extension. Put the name into it.',
262
+ 'get_ext — Get the file extension. Put the extension into it.',
263
+ 'get_parent — Get the file or folder path parent. Put the parent into it.',
264
+ 'get_sha256 — Get the SHA256 hash of the contents of the file. Put the hash value into it.',
265
+ 'show — Show the contents of the file.',
266
+ 'page — Show the contents of the file, paginated.',
267
+ 'open — Open the file with the default application for the type.',
268
+ 'exists? — Check to see if the file exists. It will be true or false.',
269
+ 'is_file? — Check to see if the file specified is a regular file. It will be true or false.',
270
+ 'is_dir? — Check to see if the file specified is a directory. It will be true or false.',
271
+ 'find_match — Look for the existence of a file matching the file\'s pattern. It will be true or false.',
272
+ 'mkdir — Create the file\'s path as a directory, if it doesn\'t already exist.'
273
+ ],
274
+ :examples => <<~EXAMPLES.strip
275
+ #
276
+ # Get elements of a file name.
277
+ #
278
+ file_name [can] :
279
+
280
+ # The full file path, name and extension.
281
+ f [file] : /Users/me/dev/gloo/gloo.gemspec
282
+
283
+ on_load [script] :
284
+ show "Full file name: " + ^.f
285
+
286
+ check ^.f for get_name
287
+ show "The file name alone: " and it
288
+
289
+ check ^.f for get_ext
290
+ show "The file extension: " and it
291
+
292
+ check ^.f for get_parent
293
+ show "The file path: " and it
294
+ EXAMPLES
295
+ }
296
+ end
297
+
242
298
  end
243
299
  end
244
300
  end
@@ -125,6 +125,35 @@ module Gloo
125
125
  set_result result
126
126
  end
127
127
 
128
+ # ---------------------------------------------------------------------
129
+ # Object Documentation
130
+ # ---------------------------------------------------------------------
131
+
132
+ #
133
+ # Get the object's documentation data.
134
+ #
135
+ def self.doc_data
136
+ {
137
+ :name => KEYWORD,
138
+ :shortcut => KEYWORD_SHORT,
139
+ :description => 'Execute a system command.',
140
+ :children => [
141
+ "command (string) — Default: '#{DEFAULT_CMD}'. The command that will be sent to the system.",
142
+ 'get_output (boolean) — Default: true. Should executing the command get the output and put it in the result object?',
143
+ 'result (string) — The result of running the command. Only set if get_output is true.'
144
+ ],
145
+ :messages => [
146
+ 'run — Run the system level command. Sets the result value to the output of the command if get_output is true.'
147
+ ],
148
+ :examples => <<~EXAMPLES.strip
149
+ date [system] :
150
+ command [string] : date
151
+ get_output [bool] : true
152
+ result [string] :
153
+ EXAMPLES
154
+ }
155
+ end
156
+
128
157
  end
129
158
  end
130
159
  end
@@ -148,6 +148,41 @@ module Gloo
148
148
  return "#{uri_value}#{p}"
149
149
  end
150
150
 
151
+ # ---------------------------------------------------------------------
152
+ # Object Documentation
153
+ # ---------------------------------------------------------------------
154
+
155
+ #
156
+ # Get the object's documentation data.
157
+ #
158
+ def self.doc_data
159
+ {
160
+ :name => KEYWORD,
161
+ :shortcut => KEYWORD_SHORT,
162
+ :description => 'Perform an HTTP Get.',
163
+ :children => [
164
+ "uri (string) — Example: 'https://web.site/'. The URI for the HTTP Get request.",
165
+ 'params (container) — Collection of parameters for the HTTP Get.',
166
+ 'result (string) — The result of the request. Whatever was returned from the HTTP Get call.',
167
+ 'skip_ssl_verify (boolean) — Optional. Skip the SSL verification as part of the request.'
168
+ ],
169
+ :messages => [
170
+ 'run — Run the HTTP Get and update the result.'
171
+ ],
172
+ :examples => <<~EXAMPLES.strip
173
+ g [http_get] :
174
+ uri [string] : http://api.sunrise-sunset.org/json
175
+ params [container] :
176
+ lat [string] : 36.7201600
177
+ lng [string] : -4.4203400
178
+ date [string] : today
179
+ result [string] :
180
+
181
+ > run g
182
+ EXAMPLES
183
+ }
184
+ end
185
+
151
186
  end
152
187
  end
153
188
  end
@@ -152,6 +152,39 @@ module Gloo
152
152
  return find_child_value( SKIP_SSL_VERIFY ) || false
153
153
  end
154
154
 
155
+ # ---------------------------------------------------------------------
156
+ # Object Documentation
157
+ # ---------------------------------------------------------------------
158
+
159
+ #
160
+ # Get the object's documentation data.
161
+ #
162
+ def self.doc_data
163
+ {
164
+ :name => KEYWORD,
165
+ :shortcut => KEYWORD_SHORT,
166
+ :description => 'Perform an HTTP Post.',
167
+ :children => [
168
+ "uri (string) — Example: 'https://web.site/'. The URI for the HTTP Post.",
169
+ 'body (container) — Collection of parameters for the HTTP Post.',
170
+ 'result (string) — The result of the request. Whatever was returned in the body of the HTTP POST.',
171
+ 'skip_ssl_verify (boolean) — Optional. Skip the SSL verification as part of the request.'
172
+ ],
173
+ :messages => [
174
+ 'run — Run the HTTP Post, sending the body data to the endpoint specified in the URI.'
175
+ ],
176
+ :examples => <<~EXAMPLES.strip
177
+ post [post] :
178
+ txt [str] : Message from gloo!
179
+ uri [str] : https://my.service.com/my-long-token
180
+ body [can] :
181
+ text [alias] : post.txt
182
+ username [str] : me
183
+ on_load [script] : run post
184
+ EXAMPLES
185
+ }
186
+ end
187
+
155
188
  end
156
189
  end
157
190
  end
@@ -202,6 +202,46 @@ module Gloo
202
202
  return data
203
203
  end
204
204
 
205
+ # ---------------------------------------------------------------------
206
+ # Object Documentation
207
+ # ---------------------------------------------------------------------
208
+
209
+ #
210
+ # Get the object's documentation data.
211
+ #
212
+ def self.doc_data
213
+ {
214
+ :name => KEYWORD,
215
+ :shortcut => KEYWORD_SHORT,
216
+ :description => 'JSON data in a text string.',
217
+ :messages => [
218
+ 'get ({path}) — Get a value from the JSON data. Example: tell myjson to get (\'title\'). The parameter is the path in JSON to the value we want. The value is put into it.',
219
+ 'set ({obj.path}) — Convert an object to an approximate JSON value. Example: tell myjson to set (my.object). The parameter is the path to the object used as the source. Note this is an approximate conversion — a gloo object can have both a simple value and be a container for child objects, which JSON can\'t represent the same way.',
220
+ 'parse ({dst.path}) — Parse the JSON data and put values in the object specified by the parameter. Example: tell myjson to parse (path.to.dst).',
221
+ 'pretty — Make the JSON format pretty.'
222
+ ],
223
+ :examples => <<~EXAMPLES.strip
224
+ #
225
+ # Get values from within a JSON object.
226
+ #
227
+
228
+ json_get [can] :
229
+ on_load [script] :
230
+ tell json_get.payload to get ('msg')
231
+ show it
232
+ tell json_get.payload to get ('sub.data')
233
+ show it
234
+ tell json_get.payload to get ('sub.child.msg')
235
+ show it
236
+ payload [json] : BEGIN
237
+ { "msg":"The message from inside a JSON block",
238
+ "sub":{"data":"in sub-object",
239
+ "child":{"msg":"third level"}} }
240
+ END
241
+ EXAMPLES
242
+ }
243
+ end
244
+
205
245
  end
206
246
  end
207
247
  end
@@ -169,6 +169,46 @@ module Gloo
169
169
  end
170
170
  end
171
171
 
172
+ # ---------------------------------------------------------------------
173
+ # Object Documentation
174
+ # ---------------------------------------------------------------------
175
+
176
+ #
177
+ # Get the object's documentation data.
178
+ #
179
+ def self.doc_data
180
+ {
181
+ :name => KEYWORD,
182
+ :shortcut => KEYWORD_SHORT,
183
+ :description => 'A URI or URL.',
184
+ :messages => [
185
+ 'open — Open the URL in the default browser.',
186
+ 'get_scheme — Get the URI scheme; example: http.',
187
+ 'get_host — Get the URI host; example: google.com.',
188
+ 'get_path — Get the URI resource path; example: /post.',
189
+ 'get_query — Get the URI query parameters; example: id=121.',
190
+ 'get_fragment — Get the URI fragment.',
191
+ 'get_cert_expires — Get the web site\'s certificate expiration date.'
192
+ ],
193
+ :examples => <<~EXAMPLES.strip
194
+ url [can] :
195
+ on_load [script] :
196
+ tell url.u to get_scheme
197
+ show "scheme: " + it
198
+
199
+ tell url.u to get_host
200
+ show "host: " + it
201
+
202
+ tell url.u to get_path
203
+ show "path: " + it
204
+
205
+ show "opening URL: " + url.u
206
+ tell url.u to open
207
+ u [uri] : https://my.url/path/1234
208
+ EXAMPLES
209
+ }
210
+ end
211
+
172
212
  end
173
213
  end
174
214
  end
@@ -0,0 +1,39 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
3
+ #
4
+ # A node in a shell's command tree.
5
+ # Ported from gloo-cli's CommandNode, namespace only.
6
+ #
7
+
8
+ module Gloo
9
+ module Shell
10
+ class CommandNode
11
+
12
+ attr_reader :name, :description, :method, :obj
13
+
14
+ #
15
+ # Initialize a command node.
16
+ # Children are supplied lazily via a block, evaluated
17
+ # with the shell's Context whenever they're needed.
18
+ #
19
+ def initialize( name, description: '', method: nil, obj: nil, &children_block )
20
+ @name = name
21
+ @description = description
22
+ @method = method
23
+ @obj = obj
24
+ @children_block = children_block
25
+ end
26
+
27
+ #
28
+ # Get this node's children, given the current shell context.
29
+ # Returns an empty array for leaf nodes.
30
+ #
31
+ def children( context )
32
+ return [] unless @children_block
33
+
34
+ @children_block.call( context )
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,93 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
3
+ #
4
+ # A shell context. Data associated with a running shell session.
5
+ # Ported from gloo-cli's ShellContext, namespace only.
6
+ #
7
+
8
+ module Gloo
9
+ module Shell
10
+ class Context
11
+
12
+ attr_accessor :done
13
+
14
+ #
15
+ # Initialize the shell context.
16
+ #
17
+ def initialize
18
+ @done = false
19
+ @properties = {}
20
+ end
21
+
22
+ #
23
+ # Get a property value.
24
+ # Returns an empty array if the property doesn't exist.
25
+ #
26
+ def get( key )
27
+ key = key.to_sym
28
+ return @properties[ key ] if @properties.key?( key )
29
+
30
+ return []
31
+ end
32
+
33
+ #
34
+ # Set a property value.
35
+ #
36
+ def set( key, value )
37
+ @properties[ key.to_sym ] = value
38
+ end
39
+
40
+ #
41
+ # Add an item to a property list.
42
+ #
43
+ def add_to_list( key, item )
44
+ key = key.to_sym
45
+ list = get( key )
46
+ list = [] unless list.is_a?( Array )
47
+
48
+ list << item
49
+ set( key, list )
50
+
51
+ return list
52
+ end
53
+
54
+ #
55
+ # Check if a property exists.
56
+ #
57
+ def has?( key )
58
+ return @properties.key?( key.to_sym )
59
+ end
60
+
61
+ #
62
+ # Get all property keys.
63
+ #
64
+ def keys
65
+ return @properties.keys
66
+ end
67
+
68
+ #
69
+ # Dynamic method access to properties.
70
+ # e.g. context.verbs is the same as context.get(:verbs),
71
+ # context.verbs = [...] is the same as context.set(:verbs, [...]).
72
+ #
73
+ def method_missing( method_name, *args, &block )
74
+ if method_name.to_s.end_with?( '=' )
75
+ key = method_name.to_s.chomp( '=' ).to_sym
76
+ set( key, args.first )
77
+ else
78
+ key = method_name.to_sym
79
+ get( key )
80
+ end
81
+ end
82
+
83
+ #
84
+ # Respond to missing methods for property access.
85
+ #
86
+ def respond_to_missing?( method_name, include_private = false )
87
+ key = method_name.to_s.chomp( '=' ).to_sym
88
+ return has?( key ) || super
89
+ end
90
+
91
+ end
92
+ end
93
+ end