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.
- checksums.yaml +4 -4
- data/CLAUDE.md +9 -3
- data/README.md +38 -7
- data/docs/application.md +164 -0
- data/docs/getting_started.md +112 -0
- data/docs/iterators.md +294 -0
- data/docs/language_objects.md +190 -0
- data/docs/language_scripting.md +62 -0
- data/docs/language_syntax.md +307 -0
- data/docs/objects.md +77 -0
- data/docs/operators.md +62 -0
- data/docs/plugins.md +54 -0
- data/docs/verbs.md +64 -0
- data/gloo.gemspec +5 -3
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +14 -0
- data/lib/gloo/app/platform.rb +29 -2
- data/lib/gloo/app/settings.rb +1 -1
- data/lib/gloo/core/gloo_system.rb +52 -1
- data/lib/gloo/docs/doc_data.rb +160 -0
- data/lib/gloo/docs/help_shell.rb +285 -0
- data/lib/gloo/docs/markdown_renderer.rb +39 -0
- data/lib/gloo/objs/basic/alias.rb +53 -0
- data/lib/gloo/objs/basic/boolean.rb +30 -0
- data/lib/gloo/objs/basic/container.rb +38 -0
- data/lib/gloo/objs/basic/decimal.rb +30 -0
- data/lib/gloo/objs/basic/integer.rb +58 -0
- data/lib/gloo/objs/basic/script.rb +31 -0
- data/lib/gloo/objs/basic/string.rb +51 -4
- data/lib/gloo/objs/basic/string_msgs.rb +20 -0
- data/lib/gloo/objs/basic/text.rb +51 -4
- data/lib/gloo/objs/basic/untyped.rb +21 -0
- data/lib/gloo/objs/ctrl/each.rb +63 -1
- data/lib/gloo/objs/ctrl/function.rb +69 -0
- data/lib/gloo/objs/ctrl/repeat.rb +41 -0
- data/lib/gloo/objs/dt/date.rb +43 -0
- data/lib/gloo/objs/dt/datetime.rb +50 -0
- data/lib/gloo/objs/dt/time.rb +43 -0
- data/lib/gloo/objs/str_utils/cipher.rb +59 -0
- data/lib/gloo/objs/str_utils/outline.rb +65 -1
- data/lib/gloo/objs/str_utils/password.rb +56 -0
- data/lib/gloo/objs/system/erb.rb +39 -0
- data/lib/gloo/objs/system/file_handle.rb +56 -0
- data/lib/gloo/objs/system/system.rb +29 -0
- data/lib/gloo/objs/web/http_get.rb +35 -0
- data/lib/gloo/objs/web/http_post.rb +33 -0
- data/lib/gloo/objs/web/json.rb +40 -0
- data/lib/gloo/objs/web/uri.rb +40 -0
- data/lib/gloo/shell/command_node.rb +39 -0
- data/lib/gloo/shell/context.rb +93 -0
- data/lib/gloo/shell/runner.rb +315 -0
- data/lib/gloo/verbs/break.rb +32 -0
- data/lib/gloo/verbs/check.rb +49 -0
- data/lib/gloo/verbs/cls.rb +18 -0
- data/lib/gloo/verbs/context.rb +47 -0
- data/lib/gloo/verbs/create.rb +42 -0
- data/lib/gloo/verbs/eval.rb +27 -0
- data/lib/gloo/verbs/execute.rb +27 -0
- data/lib/gloo/verbs/exists.rb +54 -2
- data/lib/gloo/verbs/files.rb +22 -0
- data/lib/gloo/verbs/help.rb +43 -178
- data/lib/gloo/verbs/if.rb +52 -0
- data/lib/gloo/verbs/invoke.rb +62 -0
- data/lib/gloo/verbs/list.rb +32 -0
- data/lib/gloo/verbs/load.rb +55 -2
- data/lib/gloo/verbs/log.rb +44 -0
- data/lib/gloo/verbs/move.rb +36 -1
- data/lib/gloo/verbs/put.rb +35 -0
- data/lib/gloo/verbs/quit.rb +19 -0
- data/lib/gloo/verbs/redirect.rb +52 -2
- data/lib/gloo/verbs/reload.rb +27 -0
- data/lib/gloo/verbs/run.rb +39 -0
- data/lib/gloo/verbs/save.rb +26 -0
- data/lib/gloo/verbs/show.rb +54 -0
- data/lib/gloo/verbs/tell.rb +32 -0
- data/lib/gloo/verbs/throw.rb +29 -0
- data/lib/gloo/verbs/unless.rb +50 -0
- data/lib/gloo/verbs/unload.rb +23 -0
- data/lib/gloo/verbs/version.rb +37 -3
- data/lib/gloo/verbs/wait.rb +26 -0
- metadata +28 -20
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
|
2
|
+
# Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# A shell runner. Drives a command-tree REPL with readline
|
|
5
|
+
# tab-completion.
|
|
6
|
+
#
|
|
7
|
+
# Adapted from gloo-cli's ShellRunner: that version took a `Shell`
|
|
8
|
+
# Gloo::Core::Obj and read its config (prompt, on_error, etc) from
|
|
9
|
+
# gloo-script-declared children. There's no such object tree for an
|
|
10
|
+
# interpreter-internal shell, so this version takes plain options
|
|
11
|
+
# instead. The Command Obj / cmd_obj_action(_with_context) mechanism
|
|
12
|
+
# was gloo-cli's way of running a gloo-declared Command object's
|
|
13
|
+
# action script; it isn't ported either — command nodes here always
|
|
14
|
+
# dispatch to a named method on the Runner (or a subclass of it).
|
|
15
|
+
#
|
|
16
|
+
# One addition beyond the gloo-cli original: a :dynamic node's
|
|
17
|
+
# generated children can carry a :child_method, so each one dispatches
|
|
18
|
+
# to a handler with the source item itself as `obj` (e.g. "verb put"
|
|
19
|
+
# dispatching to a detail-lookup method with "put" as the argument).
|
|
20
|
+
# gloo-cli didn't need this since it resolved a Command Obj instead.
|
|
21
|
+
#
|
|
22
|
+
require 'readline'
|
|
23
|
+
|
|
24
|
+
module Gloo
|
|
25
|
+
module Shell
|
|
26
|
+
class Runner
|
|
27
|
+
|
|
28
|
+
DEFAULT_PROMPT = ' -> '.freeze
|
|
29
|
+
UNKNOWN_COMMAND = 'Unknown command'.freeze
|
|
30
|
+
|
|
31
|
+
QUIT_NAME = 'quit'.freeze
|
|
32
|
+
QUIT_DESCRIPTION = 'Quit the application'.freeze
|
|
33
|
+
QUIT_METHOD = 'cmd_quit'.freeze
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Initialize the shell runner.
|
|
37
|
+
#
|
|
38
|
+
# @param engine [Gloo::App::Engine] The running gloo engine.
|
|
39
|
+
# Not used directly by the base Runner, but stored for
|
|
40
|
+
# subclasses' command methods to query (dictionary, heap, etc).
|
|
41
|
+
# @param opts [Hash] :prompt, :on_error, :on_unknown_command,
|
|
42
|
+
# :on_empty_command, :before_action, :after_action - all Procs
|
|
43
|
+
# except :prompt (String) and :include_quit (Boolean).
|
|
44
|
+
#
|
|
45
|
+
def initialize( engine, opts = {} )
|
|
46
|
+
@engine = engine
|
|
47
|
+
@prompt_text = opts[ :prompt ]
|
|
48
|
+
@on_error = opts[ :on_error ]
|
|
49
|
+
@on_unknown_command = opts[ :on_unknown_command ]
|
|
50
|
+
@on_empty_command = opts[ :on_empty_command ]
|
|
51
|
+
@before_action = opts[ :before_action ]
|
|
52
|
+
@after_action = opts[ :after_action ]
|
|
53
|
+
@include_quit = opts[ :include_quit ] || false
|
|
54
|
+
|
|
55
|
+
@context = Gloo::Shell::Context.new
|
|
56
|
+
@root = Gloo::Shell::CommandNode.new( nil )
|
|
57
|
+
|
|
58
|
+
add_quit_command if @include_quit
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# ---------------------------------------------------------------------
|
|
62
|
+
# Shell control: start and stop
|
|
63
|
+
# ---------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Start the shell.
|
|
67
|
+
#
|
|
68
|
+
def start
|
|
69
|
+
repl
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Flag the shell as done. Next time through the loop it will stop.
|
|
74
|
+
#
|
|
75
|
+
def stop
|
|
76
|
+
@context.done = true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
# Get the prompt string.
|
|
81
|
+
#
|
|
82
|
+
def prompt
|
|
83
|
+
return @prompt_text ? "#{@prompt_text} " : DEFAULT_PROMPT
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#
|
|
87
|
+
# Handle an empty command - run the on_empty_command hook if given.
|
|
88
|
+
#
|
|
89
|
+
def handle_empty_command
|
|
90
|
+
@on_empty_command&.call
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# Handle an unknown command - run the on_unknown_command hook if
|
|
95
|
+
# given, otherwise show the default message.
|
|
96
|
+
#
|
|
97
|
+
def handle_unknown_command
|
|
98
|
+
return if @on_unknown_command&.call
|
|
99
|
+
|
|
100
|
+
puts UNKNOWN_COMMAND
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# Run the before_action hook, if given.
|
|
105
|
+
#
|
|
106
|
+
def run_before_action
|
|
107
|
+
@before_action&.call
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Run the after_action hook, if given.
|
|
112
|
+
#
|
|
113
|
+
def run_after_action
|
|
114
|
+
@after_action&.call
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Run the on_error hook, if given.
|
|
119
|
+
#
|
|
120
|
+
def run_on_error
|
|
121
|
+
@on_error&.call
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# Quit the shell.
|
|
126
|
+
#
|
|
127
|
+
def cmd_quit( _obj, context )
|
|
128
|
+
puts 'Quitting…'
|
|
129
|
+
context.done = true
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# ---------------------------------------------------------------------
|
|
133
|
+
# Context
|
|
134
|
+
# ---------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
#
|
|
137
|
+
# Set a context list, available to dynamic command nodes.
|
|
138
|
+
#
|
|
139
|
+
def set_context( key, value_list )
|
|
140
|
+
@context.set( key, value_list )
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# ---------------------------------------------------------------------
|
|
144
|
+
# Tree building
|
|
145
|
+
# ---------------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
#
|
|
148
|
+
# Execute a command.
|
|
149
|
+
#
|
|
150
|
+
def execute_command( command_node, _args, _parent_node = nil )
|
|
151
|
+
if command_node.method
|
|
152
|
+
send( command_node.method, command_node.obj, @context )
|
|
153
|
+
elsif command_node.name && !command_node.description.empty?
|
|
154
|
+
puts "#{command_node.description}: #{command_node.name}"
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
#
|
|
159
|
+
# Build a command node from data.
|
|
160
|
+
#
|
|
161
|
+
def build_node_from_data( data )
|
|
162
|
+
if data[ :dynamic ]
|
|
163
|
+
return Gloo::Shell::CommandNode.new(
|
|
164
|
+
data[ :name ], description: data[ :description ], obj: data[ :obj ] ) do |ctx|
|
|
165
|
+
ctx.send( data[ :source ] ).map do |item|
|
|
166
|
+
Gloo::Shell::CommandNode.new( item, method: data[ :child_method ], obj: item )
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
elsif data[ :children ]
|
|
170
|
+
return Gloo::Shell::CommandNode.new(
|
|
171
|
+
data[ :name ], description: data[ :description ],
|
|
172
|
+
method: data[ :method ], obj: data[ :obj ] ) do |_ctx|
|
|
173
|
+
data[ :children ].map { |child_data| build_node_from_data( child_data ) }
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
return Gloo::Shell::CommandNode.new(
|
|
177
|
+
data[ :name ], description: data[ :description ],
|
|
178
|
+
method: data[ :method ], obj: data[ :obj ] )
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
#
|
|
183
|
+
# Add a command node to the root, dynamically.
|
|
184
|
+
#
|
|
185
|
+
# @param command_data [Hash] The command data hash.
|
|
186
|
+
#
|
|
187
|
+
def add_command_node( command_data )
|
|
188
|
+
node = build_node_from_data( command_data )
|
|
189
|
+
|
|
190
|
+
existing_block = @root.instance_variable_get( :@children_block )
|
|
191
|
+
if existing_block
|
|
192
|
+
existing_nodes = existing_block.call( @context )
|
|
193
|
+
all_nodes = existing_nodes + [ node ]
|
|
194
|
+
@root.instance_variable_set( :@children_block, proc { |_ctx| all_nodes } )
|
|
195
|
+
else
|
|
196
|
+
@root.instance_variable_set( :@children_block, proc { |_ctx| [ node ] } )
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
return node
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# ---------------------------------------------------------------------
|
|
203
|
+
# REPL
|
|
204
|
+
# ---------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
#
|
|
207
|
+
# Execute a single command from the given tokens and return.
|
|
208
|
+
#
|
|
209
|
+
def execute_once( tokens )
|
|
210
|
+
result = traverse( @root, tokens )
|
|
211
|
+
if result[ :node ]
|
|
212
|
+
run_before_action
|
|
213
|
+
execute_command( result[ :node ], tokens, result[ :parent ] )
|
|
214
|
+
run_after_action
|
|
215
|
+
else
|
|
216
|
+
handle_unknown_command
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
#
|
|
221
|
+
# Traverse the command tree to find the matching node.
|
|
222
|
+
#
|
|
223
|
+
# @param node [CommandNode] The current node.
|
|
224
|
+
# @param tokens [Array<String>] The tokens to traverse.
|
|
225
|
+
#
|
|
226
|
+
# @return [Hash] Hash with :node and :parent keys.
|
|
227
|
+
#
|
|
228
|
+
def traverse( node, tokens )
|
|
229
|
+
current = node
|
|
230
|
+
parent = nil
|
|
231
|
+
|
|
232
|
+
tokens.each do |token|
|
|
233
|
+
children = current.children( @context )
|
|
234
|
+
match = children.find { |c| c.name == token }
|
|
235
|
+
return { node: nil, parent: nil } unless match
|
|
236
|
+
|
|
237
|
+
parent = current
|
|
238
|
+
current = match
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
return { node: current, parent: parent }
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
#
|
|
245
|
+
# Setup readline completion.
|
|
246
|
+
#
|
|
247
|
+
def setup_completion
|
|
248
|
+
Readline.completion_append_character = ' '
|
|
249
|
+
Readline.basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("
|
|
250
|
+
|
|
251
|
+
Readline.completion_proc = proc do |input|
|
|
252
|
+
buffer = Readline.line_buffer
|
|
253
|
+
tokens = buffer.split( ' ' )
|
|
254
|
+
tokens << '' if buffer.end_with?( ' ' )
|
|
255
|
+
|
|
256
|
+
result = traverse( @root, tokens[ 0..-2 ] )
|
|
257
|
+
current = result[ :node ]
|
|
258
|
+
options = current ? current.children( @context ).map( &:name ) : []
|
|
259
|
+
|
|
260
|
+
matches = options.grep( /^#{Regexp.escape( input )}/ )
|
|
261
|
+
|
|
262
|
+
if matches.length > 1
|
|
263
|
+
puts
|
|
264
|
+
current.children( @context ).each do |child|
|
|
265
|
+
puts "#{child.name.ljust( 15 )} #{child.description}" if matches.include?( child.name )
|
|
266
|
+
end
|
|
267
|
+
print "#{prompt}#{buffer}"
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
matches
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
#
|
|
275
|
+
# Run the REPL loop.
|
|
276
|
+
#
|
|
277
|
+
def repl
|
|
278
|
+
setup_completion
|
|
279
|
+
|
|
280
|
+
while !@context.done && ( line = Readline.readline( prompt, true ) )
|
|
281
|
+
tokens = line.strip.split( ' ' )
|
|
282
|
+
if tokens.empty?
|
|
283
|
+
handle_empty_command
|
|
284
|
+
next
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
result = traverse( @root, tokens )
|
|
288
|
+
|
|
289
|
+
if result[ :node ]
|
|
290
|
+
run_before_action
|
|
291
|
+
execute_command( result[ :node ], tokens, result[ :parent ] )
|
|
292
|
+
run_after_action
|
|
293
|
+
else
|
|
294
|
+
handle_unknown_command
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# ---------------------------------------------------------------------
|
|
300
|
+
# Private
|
|
301
|
+
# ---------------------------------------------------------------------
|
|
302
|
+
|
|
303
|
+
private
|
|
304
|
+
|
|
305
|
+
#
|
|
306
|
+
# Add the built-in quit command, if enabled.
|
|
307
|
+
#
|
|
308
|
+
def add_quit_command
|
|
309
|
+
add_command_node(
|
|
310
|
+
{ name: QUIT_NAME, description: QUIT_DESCRIPTION, method: QUIT_METHOD } )
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|
data/lib/gloo/verbs/break.rb
CHANGED
|
@@ -39,6 +39,38 @@ module Gloo
|
|
|
39
39
|
|
|
40
40
|
private
|
|
41
41
|
|
|
42
|
+
# ---------------------------------------------------------------------
|
|
43
|
+
# Verb Documentation
|
|
44
|
+
# ---------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Get the verb's documentation data.
|
|
48
|
+
#
|
|
49
|
+
def self.doc_data
|
|
50
|
+
{
|
|
51
|
+
:name => KEYWORD,
|
|
52
|
+
:shortcut => KEYWORD_SHORT,
|
|
53
|
+
:description => 'Break out of the current script, stop running.',
|
|
54
|
+
:syntax => [ 'break' ],
|
|
55
|
+
:result => 'No more commands are executed in the currently ' \
|
|
56
|
+
'running script. If there are other scripts in the stack, ' \
|
|
57
|
+
'they will resume normally.',
|
|
58
|
+
:examples => <<~EXAMPLES.strip
|
|
59
|
+
#
|
|
60
|
+
# Break out of a script.
|
|
61
|
+
#
|
|
62
|
+
break_out [can] :
|
|
63
|
+
x [bool] : false
|
|
64
|
+
on_load [script] :
|
|
65
|
+
if ^.x then break
|
|
66
|
+
show 'should see this'
|
|
67
|
+
put true into ^.x
|
|
68
|
+
if ^.x then break
|
|
69
|
+
show 'should not see this'
|
|
70
|
+
EXAMPLES
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
42
74
|
end
|
|
43
75
|
end
|
|
44
76
|
end
|
data/lib/gloo/verbs/check.rb
CHANGED
|
@@ -49,6 +49,55 @@ module Gloo
|
|
|
49
49
|
|
|
50
50
|
private
|
|
51
51
|
|
|
52
|
+
# ---------------------------------------------------------------------
|
|
53
|
+
# Verb Documentation
|
|
54
|
+
# ---------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Get the verb's documentation data.
|
|
58
|
+
#
|
|
59
|
+
def self.doc_data
|
|
60
|
+
{
|
|
61
|
+
:name => KEYWORD,
|
|
62
|
+
:shortcut => KEYWORD_SHORT,
|
|
63
|
+
:description => 'Send a message to an object to check for an ' \
|
|
64
|
+
'object condition. This is the same as the tell verb, but ' \
|
|
65
|
+
'gives better syntactical naming.',
|
|
66
|
+
:syntax => [ 'check {path.to.object} for {condition_message}' ],
|
|
67
|
+
:parameters => [
|
|
68
|
+
'{path.to.object} — The object that we want to send a condition_message to.',
|
|
69
|
+
'{message} — The condition_message to send.'
|
|
70
|
+
],
|
|
71
|
+
:result => 'The result depends on the message that is sent, but ' \
|
|
72
|
+
'by convention the result of the check will be in it.',
|
|
73
|
+
:errors => [
|
|
74
|
+
"#{UNKNOWN_MSG_ERR} — No message was specified, or the 'for' keyword is missing.",
|
|
75
|
+
'Object was not found — The target of the message was not found.'
|
|
76
|
+
],
|
|
77
|
+
:examples => <<~EXAMPLES.strip
|
|
78
|
+
#
|
|
79
|
+
# Base object checks.
|
|
80
|
+
#
|
|
81
|
+
obj [container] :
|
|
82
|
+
msg [string] :
|
|
83
|
+
on_load [script] :
|
|
84
|
+
show 'Does the obj container have children?'
|
|
85
|
+
check obj for contains?
|
|
86
|
+
show it
|
|
87
|
+
|
|
88
|
+
show 'Is the msg blank?'
|
|
89
|
+
check obj.msg for blank?
|
|
90
|
+
show it
|
|
91
|
+
|
|
92
|
+
put 'Hello, world!' into obj.msg
|
|
93
|
+
show obj.msg
|
|
94
|
+
show 'Is the msg still blank?'
|
|
95
|
+
check obj.msg for blank?
|
|
96
|
+
show it
|
|
97
|
+
EXAMPLES
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
52
101
|
end
|
|
53
102
|
end
|
|
54
103
|
end
|
data/lib/gloo/verbs/cls.rb
CHANGED
|
@@ -32,6 +32,24 @@ module Gloo
|
|
|
32
32
|
return KEYWORD_SHORT
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
# ---------------------------------------------------------------------
|
|
36
|
+
# Verb Documentation
|
|
37
|
+
# ---------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Get the verb's documentation data.
|
|
41
|
+
#
|
|
42
|
+
def self.doc_data
|
|
43
|
+
{
|
|
44
|
+
:name => KEYWORD,
|
|
45
|
+
:shortcut => KEYWORD_SHORT,
|
|
46
|
+
:description => 'Clear the console screen.',
|
|
47
|
+
:syntax => [ 'clear' ],
|
|
48
|
+
:result => 'The screen is cleared and cursor set to the top.',
|
|
49
|
+
:examples => '> clear'
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
35
53
|
end
|
|
36
54
|
end
|
|
37
55
|
end
|
data/lib/gloo/verbs/context.rb
CHANGED
|
@@ -57,6 +57,53 @@ module Gloo
|
|
|
57
57
|
@engine.log.debug "Context set to #{@engine.heap.context}"
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# ---------------------------------------------------------------------
|
|
61
|
+
# Verb Documentation
|
|
62
|
+
# ---------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
#
|
|
65
|
+
# Get the verb's documentation data.
|
|
66
|
+
#
|
|
67
|
+
def self.doc_data
|
|
68
|
+
{
|
|
69
|
+
:name => KEYWORD,
|
|
70
|
+
:shortcut => KEYWORD_SHORT,
|
|
71
|
+
:description => 'Get or set the current context. When no ' \
|
|
72
|
+
'parameter is provided, the context will be shown. When the ' \
|
|
73
|
+
"optional path parameter is provided, the context will be set " \
|
|
74
|
+
"to that path. Use 'context root' to set the context back to " \
|
|
75
|
+
'the root level. When context has been set, the pathname can ' \
|
|
76
|
+
'start from the context container by use of the @. prefix.',
|
|
77
|
+
:syntax => [ 'context {path.to.new.context}' ],
|
|
78
|
+
:parameters => [
|
|
79
|
+
'{path.to.new.context} — Optional. The path to the new context when setting the context.'
|
|
80
|
+
],
|
|
81
|
+
:result => 'Context is optionally set. It will be set to the ' \
|
|
82
|
+
'new context path when we are changing context. Context is ' \
|
|
83
|
+
'shown in either case.',
|
|
84
|
+
:notes => 'Providing a context that does not exist will not ' \
|
|
85
|
+
'initially be a problem — you can set the context to an ' \
|
|
86
|
+
"object before it exists. However, use of a context that " \
|
|
87
|
+
"doesn't exist will be a problem.\n\n" \
|
|
88
|
+
"CLI Example:\n" \
|
|
89
|
+
"> context\n" \
|
|
90
|
+
" Context: root\n\n" \
|
|
91
|
+
"> context my.object.path\n" \
|
|
92
|
+
" Context: my.object.path\n\n" \
|
|
93
|
+
"> context root\n" \
|
|
94
|
+
" Context: root",
|
|
95
|
+
:examples => <<~EXAMPLES.strip
|
|
96
|
+
context [container] :
|
|
97
|
+
sub [container] :
|
|
98
|
+
msg [string] : Hello Gloo World!
|
|
99
|
+
on_load [script] :
|
|
100
|
+
@ context.sub
|
|
101
|
+
show @.msg
|
|
102
|
+
@ root
|
|
103
|
+
EXAMPLES
|
|
104
|
+
}
|
|
105
|
+
end
|
|
106
|
+
|
|
60
107
|
end
|
|
61
108
|
end
|
|
62
109
|
end
|
data/lib/gloo/verbs/create.rb
CHANGED
|
@@ -69,6 +69,48 @@ module Gloo
|
|
|
69
69
|
@engine.heap.it.set_to value
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
# ---------------------------------------------------------------------
|
|
73
|
+
# Verb Documentation
|
|
74
|
+
# ---------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# Get the verb's documentation data.
|
|
78
|
+
#
|
|
79
|
+
def self.doc_data
|
|
80
|
+
{
|
|
81
|
+
:name => KEYWORD,
|
|
82
|
+
:shortcut => KEYWORD_SHORT,
|
|
83
|
+
:description => 'Create a new object of given type with given ' \
|
|
84
|
+
'value. Both type and value are optional when creating an object.',
|
|
85
|
+
:syntax => [ 'create {new.object.path} as {type} : {value}' ],
|
|
86
|
+
:parameters => [
|
|
87
|
+
'{new.object.path} — The path and name of the new object.',
|
|
88
|
+
'{type} — The type of the new object. Optional; if not provided the object will be untyped.',
|
|
89
|
+
"{value} — The initial value for the new object. Optional; if not provided the object will have the default value for the type."
|
|
90
|
+
],
|
|
91
|
+
:result => "The new object will be created and added to the " \
|
|
92
|
+
"object heap. It will be set to the new object's initial value.",
|
|
93
|
+
:errors => [
|
|
94
|
+
"#{NO_NAME_ERR} — The name of the object was not specified and the object cannot be created."
|
|
95
|
+
],
|
|
96
|
+
:examples => <<~EXAMPLES.strip
|
|
97
|
+
# Basic examples of creating an object from the gloo shell:
|
|
98
|
+
> create x as integer : 1
|
|
99
|
+
> create s : "abc"
|
|
100
|
+
> create t
|
|
101
|
+
|
|
102
|
+
# Example of creating an object with an alias:
|
|
103
|
+
a [can] :
|
|
104
|
+
ln [alias] : x
|
|
105
|
+
|
|
106
|
+
on_load [script] :
|
|
107
|
+
create a.ln* as string
|
|
108
|
+
put 'test' into x
|
|
109
|
+
show a.ln
|
|
110
|
+
EXAMPLES
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
72
114
|
end
|
|
73
115
|
end
|
|
74
116
|
end
|
data/lib/gloo/verbs/eval.rb
CHANGED
|
@@ -38,6 +38,33 @@ module Gloo
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# ---------------------------------------------------------------------
|
|
42
|
+
# Verb Documentation
|
|
43
|
+
# ---------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Get the verb's documentation data.
|
|
47
|
+
#
|
|
48
|
+
def self.doc_data
|
|
49
|
+
{
|
|
50
|
+
:name => KEYWORD,
|
|
51
|
+
:shortcut => KEYWORD_SHORT,
|
|
52
|
+
:description => 'Evaluate an expression and put the result into it.',
|
|
53
|
+
:syntax => [ 'eval {expression}' ],
|
|
54
|
+
:parameters => [
|
|
55
|
+
'{expression} — The expression that will be evaluated. The expression is optional. If not provided, eval will result in true.'
|
|
56
|
+
],
|
|
57
|
+
:result => 'The result of the expression evaluation is put ' \
|
|
58
|
+
'into it. No other action is performed.',
|
|
59
|
+
:examples => <<~EXAMPLES.strip
|
|
60
|
+
> eval "me"
|
|
61
|
+
> eval "hello " "world"
|
|
62
|
+
> eval 132 * 23
|
|
63
|
+
> eval path.to.num = 1
|
|
64
|
+
EXAMPLES
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
41
68
|
end
|
|
42
69
|
end
|
|
43
70
|
end
|
data/lib/gloo/verbs/execute.rb
CHANGED
|
@@ -49,6 +49,33 @@ module Gloo
|
|
|
49
49
|
return KEYWORD_SHORT
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
# ---------------------------------------------------------------------
|
|
53
|
+
# Verb Documentation
|
|
54
|
+
# ---------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Get the verb's documentation data.
|
|
58
|
+
#
|
|
59
|
+
def self.doc_data
|
|
60
|
+
{
|
|
61
|
+
:name => KEYWORD,
|
|
62
|
+
:shortcut => KEYWORD_SHORT,
|
|
63
|
+
:description => 'Execute a shell command. This verb is not ' \
|
|
64
|
+
'available in the Web app.',
|
|
65
|
+
:syntax => [ 'exec {expression}' ],
|
|
66
|
+
:parameters => [
|
|
67
|
+
'{expression} — Evaluate the expression and execute in the shell.'
|
|
68
|
+
],
|
|
69
|
+
:result => 'There is no result within gloo, any output is in the terminal.',
|
|
70
|
+
:errors => [
|
|
71
|
+
"#{MISSING_EXPR_ERR} — No expression is provided as parameter to the verb."
|
|
72
|
+
],
|
|
73
|
+
:examples => <<~EXAMPLES.strip
|
|
74
|
+
> exec 'rake test'
|
|
75
|
+
EXAMPLES
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
52
79
|
end
|
|
53
80
|
end
|
|
54
81
|
end
|
data/lib/gloo/verbs/exists.rb
CHANGED
|
@@ -72,9 +72,9 @@ module Gloo
|
|
|
72
72
|
return false
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
#
|
|
75
|
+
#
|
|
76
76
|
# Check to see if an instance of an object exists.
|
|
77
|
-
#
|
|
77
|
+
#
|
|
78
78
|
def instance_exists?( pn )
|
|
79
79
|
pn = Gloo::Core::Pn.new( @engine, pn )
|
|
80
80
|
o = pn.resolve
|
|
@@ -82,6 +82,58 @@ module Gloo
|
|
|
82
82
|
return true
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
+
# ---------------------------------------------------------------------
|
|
86
|
+
# Verb Documentation
|
|
87
|
+
# ---------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Get the verb's documentation data.
|
|
91
|
+
#
|
|
92
|
+
def self.doc_data
|
|
93
|
+
{
|
|
94
|
+
:name => KEYWORD,
|
|
95
|
+
:shortcut => KEYWORD_SHORT,
|
|
96
|
+
:description => 'Check to see if a verb or object type has ' \
|
|
97
|
+
'been defined (or loaded). This verb can be used to check ' \
|
|
98
|
+
'if a core library or extension has been loaded.',
|
|
99
|
+
:syntax => [ 'exists? |any,object,verb,instance| {keyword}' ],
|
|
100
|
+
:parameters => [
|
|
101
|
+
"Kind of Keyword — Check for the presence of a keyword of a kind. " \
|
|
102
|
+
"any (default, optional) checks for either an object or a verb; " \
|
|
103
|
+
"object checks for an object matching the keyword or keyword " \
|
|
104
|
+
"shortcut; verb checks for a verb matching the keyword or " \
|
|
105
|
+
"keyword shortcut; instance checks to see if an object " \
|
|
106
|
+
"instance exists at the pathname represented by keyword. " \
|
|
107
|
+
"`exists? any markdown` is identical to `exists? markdown`.",
|
|
108
|
+
'{keyword} — The verb or object keyword or keyword shortcut. ' \
|
|
109
|
+
'Must be specified. For the instance option, the keyword is ' \
|
|
110
|
+
'the pathname to an object instance.'
|
|
111
|
+
],
|
|
112
|
+
:result => 'If the object or verb has been defined, then true, ' \
|
|
113
|
+
'otherwise false. The result will be in it.',
|
|
114
|
+
:errors => [
|
|
115
|
+
"#{WRONG_NUM_ARGS_ERR} The kind of keyword is optional."
|
|
116
|
+
],
|
|
117
|
+
:examples => <<~EXAMPLES.strip
|
|
118
|
+
#
|
|
119
|
+
# Example of exists? keyword.
|
|
120
|
+
#
|
|
121
|
+
exists [container] :
|
|
122
|
+
|
|
123
|
+
\ton_load [script] :
|
|
124
|
+
\t\texists? object markdown
|
|
125
|
+
\t\tshow it # false
|
|
126
|
+
|
|
127
|
+
\t\tload lib md
|
|
128
|
+
\t\texists? object markdown
|
|
129
|
+
\t\tshow it # true
|
|
130
|
+
|
|
131
|
+
\t\texists? instance exists.on_load
|
|
132
|
+
\t\tshow it # true
|
|
133
|
+
EXAMPLES
|
|
134
|
+
}
|
|
135
|
+
end
|
|
136
|
+
|
|
85
137
|
end
|
|
86
138
|
end
|
|
87
139
|
end
|