gloo 6.5.1 → 6.6.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/docs/application.md +2 -0
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +6 -0
- data/lib/gloo/app/engine.rb +17 -1
- data/lib/gloo/app/settings.rb +40 -0
- data/lib/gloo/docs/help_shell.rb +46 -1
- data/lib/gloo/objs/basic/string_msgs.rb +20 -0
- data/lib/gloo/objs/basic/word_wrap.rb +58 -0
- data/lib/gloo/verbs/list.rb +36 -4
- data/test.gloo/objs/string.test.gloo +17 -0
- data/test.gloo/objs/text.test.gloo +9 -0
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 24b089e57c145daea09ee59a1967bc38ec4482d0a9a137f9e3a32e8b71fb4ece
|
|
4
|
+
data.tar.gz: 625b347a0ff732f2fe81008c9e7e6d56de92f84ef846ccd37ebeda10948117ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3080060d8fea38b00cc1870d9ae07d8149db13395834d72a20c9f18f7b9c43d97b6af97177d653b7eaeeffa49b04f9005a8318f7aaaa56edf65619645dde8016
|
|
7
|
+
data.tar.gz: f137b40bf30a08e7af993fdd67041084a7f6aefbaf461934f1b4b8bd370e399cf3044537388d1a09be6dd954d73c3487ceddf6c977493287e3aa5ec6894f2b13
|
data/docs/application.md
CHANGED
|
@@ -88,6 +88,8 @@ gloo:
|
|
|
88
88
|
#
|
|
89
89
|
# Run this script when starting up gloo.
|
|
90
90
|
# (Only if a script file is not specified.)
|
|
91
|
+
# A bare filename (no path) is looked up in the config directory
|
|
92
|
+
# above. Either way, the .gloo extension is assumed if left off.
|
|
91
93
|
#
|
|
92
94
|
start_with:
|
|
93
95
|
|
data/lib/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
1
|
+
6.6.0
|
data/lib/VERSION_NOTES
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
6.6.0 - 2026.09.12
|
|
2
|
+
- Allow shortcut reference for start file in configuration directory.
|
|
3
|
+
- Adds word wrap message for strings and text.
|
|
4
|
+
- Adds line wrapping for object comments and help documentation.
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
6.5.1 - 2026.09.11
|
|
2
8
|
- Adds doc to the load verb for recent changes.
|
|
3
9
|
|
data/lib/gloo/app/engine.rb
CHANGED
|
@@ -207,7 +207,9 @@ module Gloo
|
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
name = @settings.start_with
|
|
210
|
-
|
|
210
|
+
return if name.blank?
|
|
211
|
+
|
|
212
|
+
@persist_man.load( resolve_start_with( name ) )
|
|
211
213
|
end
|
|
212
214
|
|
|
213
215
|
#
|
|
@@ -382,6 +384,20 @@ module Gloo
|
|
|
382
384
|
|
|
383
385
|
private
|
|
384
386
|
|
|
387
|
+
#
|
|
388
|
+
# Resolve the start_with setting to a loadable name/path.
|
|
389
|
+
# A bare filename (no directory separator) is resolved against
|
|
390
|
+
# the config directory rather than the project path, and the
|
|
391
|
+
# .gloo extension is assumed when not given.
|
|
392
|
+
#
|
|
393
|
+
def resolve_start_with( name )
|
|
394
|
+
ext = @persist_man.file_ext
|
|
395
|
+
name = "#{name}#{ext}" unless name.end_with?( ext )
|
|
396
|
+
return name if name.include?( File::SEPARATOR )
|
|
397
|
+
|
|
398
|
+
return File.join( @settings.config_path, name )
|
|
399
|
+
end
|
|
400
|
+
|
|
385
401
|
#
|
|
386
402
|
# Get the stack trace as a string, truncating the middle if it's long.
|
|
387
403
|
#
|
data/lib/gloo/app/settings.rb
CHANGED
|
@@ -189,13 +189,53 @@ module Gloo
|
|
|
189
189
|
def get_default_settings
|
|
190
190
|
projects = File.join( @user_root, 'projects' )
|
|
191
191
|
str = <<~TEXT
|
|
192
|
+
#
|
|
193
|
+
# Gloo configuration
|
|
194
|
+
#
|
|
192
195
|
gloo:
|
|
196
|
+
|
|
197
|
+
#
|
|
198
|
+
# Root directory for projects.
|
|
199
|
+
# Update this with the directory with your gloo projects.
|
|
200
|
+
#
|
|
193
201
|
project_path: #{projects}
|
|
202
|
+
|
|
203
|
+
#
|
|
204
|
+
# Run this script when starting up gloo.
|
|
205
|
+
# (Only if a script file is not specified.)
|
|
206
|
+
# A bare filename (no path) is looked up in the config directory
|
|
207
|
+
# above. Either way, the .gloo extension is assumed if left off.
|
|
208
|
+
#
|
|
194
209
|
start_with:
|
|
210
|
+
|
|
211
|
+
#
|
|
212
|
+
# Indentation (spaces) when showing an object outline.
|
|
213
|
+
#
|
|
195
214
|
list_indent: 2
|
|
215
|
+
|
|
216
|
+
#
|
|
217
|
+
# Show listing the object tree,
|
|
218
|
+
# how many levels of children will be shown?
|
|
219
|
+
# Children at deeper levels will be hidden.
|
|
220
|
+
#
|
|
196
221
|
list_levels: 3
|
|
222
|
+
|
|
223
|
+
#
|
|
224
|
+
# When listing the object tree, also show each object's doc (the
|
|
225
|
+
# comment declared immediately above it in its source file), if it
|
|
226
|
+
# has one.
|
|
227
|
+
#
|
|
197
228
|
list_docs: false
|
|
229
|
+
|
|
230
|
+
#
|
|
231
|
+
# Show debug statements in the log?
|
|
232
|
+
#
|
|
198
233
|
debug: false
|
|
234
|
+
|
|
235
|
+
#
|
|
236
|
+
# Color theme for console output: dark or light.
|
|
237
|
+
# Match this to your terminal's background.
|
|
238
|
+
#
|
|
199
239
|
theme: #{DEFAULT_THEME}
|
|
200
240
|
TEXT
|
|
201
241
|
return str
|
data/lib/gloo/docs/help_shell.rb
CHANGED
|
@@ -24,6 +24,10 @@ module Gloo
|
|
|
24
24
|
README_GLOB = 'README*'.freeze
|
|
25
25
|
NO_README_YET = 'No README found for library'.freeze
|
|
26
26
|
|
|
27
|
+
# Matches a (possibly indented) markdown bullet line, capturing
|
|
28
|
+
# its leading whitespace and the text after '- '.
|
|
29
|
+
BULLET_RE = /\A(\s*)-\s+(.*)\z/.freeze
|
|
30
|
+
|
|
27
31
|
#
|
|
28
32
|
# Initialize the help shell for the given engine.
|
|
29
33
|
#
|
|
@@ -249,10 +253,51 @@ module Gloo
|
|
|
249
253
|
#
|
|
250
254
|
def page_markdown( md )
|
|
251
255
|
rule = '-' * @engine.platform.cols
|
|
252
|
-
|
|
256
|
+
wrapped = wrap_markdown_for_terminal( md.strip )
|
|
257
|
+
bracketed = "#{rule}\n#{wrapped}\n#{rule}\n"
|
|
253
258
|
@engine.platform.page( Gloo::Docs::MarkdownRenderer.colorize( bracketed, @engine.theme ) )
|
|
254
259
|
end
|
|
255
260
|
|
|
261
|
+
#
|
|
262
|
+
# Word-wrap plain (pre-color) markdown to the terminal width.
|
|
263
|
+
# Headings and fenced code blocks are left untouched (code is
|
|
264
|
+
# never rewrapped); a bullet line's continuation lines are
|
|
265
|
+
# indented to line up under its text, not under the '-' itself
|
|
266
|
+
# -- same convention as List#show_doc's doc-line wrapping.
|
|
267
|
+
#
|
|
268
|
+
def wrap_markdown_for_terminal( md )
|
|
269
|
+
width = Gloo::App::Settings.cols( @engine )
|
|
270
|
+
in_code_fence = false
|
|
271
|
+
lines = md.split( "\n", -1 ).flat_map do |line|
|
|
272
|
+
if line.strip.start_with?( '```' )
|
|
273
|
+
in_code_fence = !in_code_fence
|
|
274
|
+
next [ line ]
|
|
275
|
+
end
|
|
276
|
+
next [ line ] if in_code_fence || line.start_with?( '#' ) || line.strip.empty?
|
|
277
|
+
|
|
278
|
+
wrap_markdown_line( line, width )
|
|
279
|
+
end
|
|
280
|
+
return lines.join( "\n" )
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
#
|
|
284
|
+
# Wrap one prose or bullet markdown line to width. A bullet's
|
|
285
|
+
# continuation lines get a blank-space prefix the same length as
|
|
286
|
+
# its '{indent}- ', so wrapped text lines up under the bullet's
|
|
287
|
+
# own text.
|
|
288
|
+
#
|
|
289
|
+
def wrap_markdown_line( line, width )
|
|
290
|
+
match = BULLET_RE.match( line )
|
|
291
|
+
prefix = match ? "#{match[1]}- " : ''
|
|
292
|
+
text = match ? match[2] : line
|
|
293
|
+
cont_indent = ' ' * prefix.length
|
|
294
|
+
|
|
295
|
+
wrapped = Gloo::Objs::WordWrap.wrap( text, width - prefix.length )
|
|
296
|
+
# "".split( "\n", -1 ) is [], not [ '' ] -- keep a blank line as one piece.
|
|
297
|
+
pieces = wrapped.empty? ? [ '' ] : wrapped.split( "\n", -1 )
|
|
298
|
+
return pieces.each_with_index.map { |piece, i| "#{i.zero? ? prefix : cont_indent}#{piece}" }
|
|
299
|
+
end
|
|
300
|
+
|
|
256
301
|
#
|
|
257
302
|
# Snapshot the verb, object type, doc page, and loaded library
|
|
258
303
|
# names for tab-completion.
|
|
@@ -55,6 +55,7 @@ module Gloo
|
|
|
55
55
|
'splitl ({index}) — Get the substring to the left of index {index} (same as split (0, {index})). A parameter is required. Does not change the value of the string. It will have the substring.',
|
|
56
56
|
'splitr ({index}) — Get the substring from index {index} to the end of the string (same as split ({index}, size)). A parameter is required. Does not change the value of the string. It will have the substring.',
|
|
57
57
|
'split_list ({delim} {dst.path}) — Split the string by {delim} and put the parts into children of the container at {dst.path} (or an alias that points to one), one part per child, in order. Existing children are matched by position and have their values set; extra parts get new (untyped) children, numbered from 1; extra existing children are left alone. Both parameters are required. Does not change the value of the string. It will have the number of parts.',
|
|
58
|
+
'word_wrap ({width}) — Word-wrap the string to {width} columns, breaking on whitespace (never mid-word; an overlong word is left on its own line rather than broken). The {width} parameter is optional; it defaults to the terminal\'s current width. This message changes the value of the string. It will have the wrapped string.',
|
|
58
59
|
'page — Show the value in a pager (less), for viewing long content a screen at a time.'
|
|
59
60
|
]
|
|
60
61
|
end
|
|
@@ -481,6 +482,25 @@ module Gloo
|
|
|
481
482
|
return s
|
|
482
483
|
end
|
|
483
484
|
|
|
485
|
+
#
|
|
486
|
+
# Word-wrap the string to the given column width, breaking on
|
|
487
|
+
# whitespace. Defaults to the terminal's current width when no
|
|
488
|
+
# width parameter is given.
|
|
489
|
+
#
|
|
490
|
+
def msg_word_wrap
|
|
491
|
+
width = Gloo::App::Settings.cols( @engine )
|
|
492
|
+
if @params&.token_count&.positive?
|
|
493
|
+
expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
|
|
494
|
+
data = expr.evaluate
|
|
495
|
+
width = data.to_i
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
s = Gloo::Objs::WordWrap.wrap( value, width )
|
|
499
|
+
set_value s
|
|
500
|
+
@engine.heap.it.set_to s
|
|
501
|
+
return s
|
|
502
|
+
end
|
|
503
|
+
|
|
484
504
|
#
|
|
485
505
|
# Show the value in a pager, for long content.
|
|
486
506
|
#
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
|
2
|
+
# Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Word-wrapping utility.
|
|
5
|
+
# This is a static class.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
module Gloo
|
|
9
|
+
module Objs
|
|
10
|
+
class WordWrap
|
|
11
|
+
|
|
12
|
+
# ---------------------------------------------------------------------
|
|
13
|
+
# Wrapping
|
|
14
|
+
# ---------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# Wrap the given text to the given column width.
|
|
18
|
+
# Greedy word-wrap: breaks on whitespace, never mid-word. A single
|
|
19
|
+
# word longer than the width is left on its own line rather than
|
|
20
|
+
# being hard-broken (e.g. a URL stays intact, just overflows).
|
|
21
|
+
# Existing line breaks in the text are preserved -- each line is
|
|
22
|
+
# wrapped independently, so blank lines and paragraph breaks survive.
|
|
23
|
+
#
|
|
24
|
+
def self.wrap( text, width )
|
|
25
|
+
return text.to_s if width.to_i <= 0
|
|
26
|
+
|
|
27
|
+
text.to_s.split( "\n", -1 ).map { |line| wrap_line( line, width ) }.join( "\n" )
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------
|
|
31
|
+
# Private
|
|
32
|
+
# ---------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Wrap a single line (no embedded newlines) to the given width.
|
|
36
|
+
#
|
|
37
|
+
def self.wrap_line( line, width )
|
|
38
|
+
words = line.split( ' ' )
|
|
39
|
+
return line if words.empty?
|
|
40
|
+
|
|
41
|
+
lines = []
|
|
42
|
+
current = words.shift
|
|
43
|
+
words.each do |word|
|
|
44
|
+
if "#{current} #{word}".length > width
|
|
45
|
+
lines << current
|
|
46
|
+
current = word
|
|
47
|
+
else
|
|
48
|
+
current = "#{current} #{word}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
lines << current
|
|
52
|
+
return lines.join( "\n" )
|
|
53
|
+
end
|
|
54
|
+
private_class_method :wrap_line
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/gloo/verbs/list.rb
CHANGED
|
@@ -92,21 +92,53 @@ module Gloo
|
|
|
92
92
|
|
|
93
93
|
#
|
|
94
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.
|
|
95
|
+
# its listing line, one '#'-prefixed line per line of doc, word-
|
|
96
|
+
# wrapped to fit the terminal. Silent when the object has none.
|
|
97
97
|
#
|
|
98
98
|
def show_doc( obj, indent )
|
|
99
99
|
return if obj.doc.to_s.strip.empty?
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
prefix = "#{indent}# "
|
|
102
|
+
cont_indent = "#{indent} " # lines up under the text after '# '
|
|
103
|
+
width = doc_wrap_width( prefix.length )
|
|
104
|
+
|
|
102
105
|
# split( -1 ), not each_line -- a doc ending in a blank '#' line
|
|
103
106
|
# ends with "\n", and each_line silently drops that trailing
|
|
104
107
|
# empty line rather than yielding it.
|
|
105
108
|
obj.doc.split( "\n", -1 ).each do |line|
|
|
106
|
-
|
|
109
|
+
show_doc_line( line, prefix, cont_indent, width )
|
|
107
110
|
end
|
|
108
111
|
end
|
|
109
112
|
|
|
113
|
+
#
|
|
114
|
+
# Word-wrap a single doc line to width, then show each wrapped
|
|
115
|
+
# piece: the '#' prefix on the first, the aligned continuation
|
|
116
|
+
# indent on the rest.
|
|
117
|
+
#
|
|
118
|
+
def show_doc_line( line, prefix, cont_indent, width )
|
|
119
|
+
theme = @engine.theme
|
|
120
|
+
wrapped = Gloo::Objs::WordWrap.wrap( line, width )
|
|
121
|
+
# "".split( "\n", -1 ) is [], not [ '' ] -- a blank line still
|
|
122
|
+
# needs one piece so it renders as a bare '#', not nothing.
|
|
123
|
+
pieces = wrapped.empty? ? [ '' ] : wrapped.split( "\n", -1 )
|
|
124
|
+
pieces.each_with_index do |piece, i|
|
|
125
|
+
p = i.zero? ? prefix : cont_indent
|
|
126
|
+
@engine.log.show theme.muted( "#{p}#{piece}".rstrip )
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
#
|
|
131
|
+
# How many columns of text fit after the doc-line prefix. Falls
|
|
132
|
+
# back to a small minimum rather than a zero/negative width when
|
|
133
|
+
# the terminal is very narrow or the indent is very deep.
|
|
134
|
+
#
|
|
135
|
+
def doc_wrap_width( prefix_length )
|
|
136
|
+
width = Gloo::App::Settings.cols( @engine ) - prefix_length
|
|
137
|
+
return width if width.positive?
|
|
138
|
+
|
|
139
|
+
return 20
|
|
140
|
+
end
|
|
141
|
+
|
|
110
142
|
#
|
|
111
143
|
# Determine how many levels to show.
|
|
112
144
|
#
|
|
@@ -79,6 +79,23 @@ tests.objs.string [can] :
|
|
|
79
79
|
eval it = 'three'
|
|
80
80
|
assert "expected split (8 100) to clamp to 'three'"
|
|
81
81
|
|
|
82
|
+
word_wrap [test] :
|
|
83
|
+
description [string] : Word-wrap a string to an explicit width
|
|
84
|
+
on_test [script] :
|
|
85
|
+
put 'one two three four five' into ^^.s
|
|
86
|
+
tell ^^.s to word_wrap (10)
|
|
87
|
+
tell ^^.s to count_lines
|
|
88
|
+
eval it = 3
|
|
89
|
+
assert "expected word_wrap (10) to produce 3 lines"
|
|
90
|
+
|
|
91
|
+
word_wrap_keeps_long_word_intact [test] :
|
|
92
|
+
description [string] : word_wrap never breaks a word, even one wider than the width
|
|
93
|
+
on_test [script] :
|
|
94
|
+
put 'http://example.com/a-really-long-url short' into ^^.s
|
|
95
|
+
tell ^^.s to word_wrap (10)
|
|
96
|
+
check ^^.s for substring? ('http://example.com/a-really-long-url')
|
|
97
|
+
assert "expected the long word to remain intact on its own line"
|
|
98
|
+
|
|
82
99
|
split_list [test] :
|
|
83
100
|
description [string] : Split a string into children of a target container
|
|
84
101
|
on_test [script] :
|
|
@@ -101,3 +101,12 @@ tests.objs.text [can] :
|
|
|
101
101
|
put 'hello world' into ^^.b
|
|
102
102
|
tell ^^.b to substring? ('lo w')
|
|
103
103
|
assert "expected it to be true that it contains 'lo w'"
|
|
104
|
+
|
|
105
|
+
word_wrap [test] :
|
|
106
|
+
description [string] : Word-wrap text to an explicit width
|
|
107
|
+
on_test [script] :
|
|
108
|
+
put 'one two three four five' into ^^.b
|
|
109
|
+
tell ^^.b to word_wrap (10)
|
|
110
|
+
tell ^^.b to count_lines
|
|
111
|
+
eval it = 3
|
|
112
|
+
assert "expected word_wrap (10) to produce 3 lines"
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gloo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Crane
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-09-12 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: bundler
|
|
@@ -361,6 +362,7 @@ files:
|
|
|
361
362
|
- lib/gloo/objs/basic/string_msgs.rb
|
|
362
363
|
- lib/gloo/objs/basic/text.rb
|
|
363
364
|
- lib/gloo/objs/basic/untyped.rb
|
|
365
|
+
- lib/gloo/objs/basic/word_wrap.rb
|
|
364
366
|
- lib/gloo/objs/ctrl/each.rb
|
|
365
367
|
- lib/gloo/objs/ctrl/each_child.rb
|
|
366
368
|
- lib/gloo/objs/ctrl/each_dir.rb
|
|
@@ -505,6 +507,7 @@ licenses:
|
|
|
505
507
|
- MIT
|
|
506
508
|
metadata:
|
|
507
509
|
documentation_uri: https://github.com/ecrane/gloo
|
|
510
|
+
post_install_message:
|
|
508
511
|
rdoc_options: []
|
|
509
512
|
require_paths:
|
|
510
513
|
- lib
|
|
@@ -519,7 +522,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
519
522
|
- !ruby/object:Gem::Version
|
|
520
523
|
version: '0'
|
|
521
524
|
requirements: []
|
|
522
|
-
rubygems_version:
|
|
525
|
+
rubygems_version: 3.5.16
|
|
526
|
+
signing_key:
|
|
523
527
|
specification_version: 4
|
|
524
528
|
summary: Gloo scripting language. A scripting language built on ruby.
|
|
525
529
|
test_files: []
|