livetext 0.9.60 → 0.9.61

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63cd6b938fdb29f4b900ffb1ded5d378a9ae5d9c6274ec593f8593c2bd47e718
4
- data.tar.gz: d62dcbfc69af01c7dc3d15608e2b95c6c3abc0347769fac24b8b600727608f35
3
+ metadata.gz: 0d0ba9b287008c8827a9a1d30881507700dceffae0edd52e4dd5274b5fb4f004
4
+ data.tar.gz: eb988c908dcdbbbff10710a4a62bd51cdd13b832a9121814150a484448d9c5f7
5
5
  SHA512:
6
- metadata.gz: fb08277e4f424959940ba49f8dee3edc65347038a046b46235b618f70a11dfd92932316f325f83f2930938dd97bee26eae172e17951918638137055fc92599c6
7
- data.tar.gz: 9834c220e9775071b4e2d5769e5aa0b518e0de760940db1d10a837024f879eb449b98da8eff90f9a2696277f780b6e8baa7595439815411c70795ef865328c12
6
+ metadata.gz: 1fcc995144794c8fac0b87c42a4cd8913d57bc31c6f26cc1bd564871366c1c3d260eda87966301d81776f1322fd2c22d453b807ffc06a90e4e1f4ceca3184598
7
+ data.tar.gz: 40fe697a385ba6684df3746558674793766801933fcbd8b42766a9c2ff1121aebb75942898f32fe6184de3fb96ad2d6c9ecef980df2cf2bd8697c9f377123f08
data/lib/livetext/core.rb CHANGED
@@ -60,13 +60,13 @@ class Livetext
60
60
  def initialize(output = ::STDOUT) # Livetext
61
61
  @body = ""
62
62
  @indentation = [0]
63
+ @function_registry = Livetext::FunctionRegistry.new
64
+ @variables = Livetext::VariableManager.new(self)
65
+ @formatter = Livetext::Formatter.new(self)
63
66
  @api = UserAPI.new(self)
64
67
  @output = ::Livetext.output = output
65
68
  @html = Livetext::HTML.new(@api)
66
69
  @sources = []
67
- @function_registry = Livetext::FunctionRegistry.new
68
- @variables = Livetext::VariableManager.new(self)
69
- @formatter = Livetext::Formatter.new(self)
70
70
  # puts "------ init: self = "
71
71
  # p self
72
72
  end
@@ -0,0 +1,32 @@
1
+ # FunctionCaller - Provides simple method-style access to Livetext functions
2
+ class Livetext::FunctionCaller
3
+ def initialize(function_registry)
4
+ @registry = function_registry
5
+ end
6
+
7
+ # Dynamically handle method calls to function names
8
+ def method_missing(name, *args)
9
+ # Convert method name to string and call the function registry
10
+ function_name = name.to_s
11
+ param = args.first || ""
12
+
13
+ @registry.call(function_name, param)
14
+ rescue => e
15
+ "[Error calling function #{function_name}: #{e.message}]"
16
+ end
17
+
18
+ # Check if a function exists
19
+ def respond_to_missing?(name, include_private = false)
20
+ @registry.function_exists?(name.to_s) || super
21
+ end
22
+
23
+ # List all available functions
24
+ def list
25
+ @registry.list_functions.map { |f| f[:name] }
26
+ end
27
+
28
+ # Check if a specific function exists
29
+ def exists?(name)
30
+ @registry.function_exists?(name.to_s)
31
+ end
32
+ end
@@ -5,7 +5,7 @@ class Livetext::FunctionRegistry
5
5
  @builtin_functions = {}
6
6
  @metadata = {}
7
7
  register_builtin_functions
8
- puts "DEBUG: Registered #{@builtin_functions.size} builtin functions" if ENV['DEBUG']
8
+ # puts "DEBUG: Registered #{@builtin_functions.size} builtin functions" if ENV['DEBUG']
9
9
  end
10
10
 
11
11
  def register_user(name, function, source: :inline, filename: nil)
@@ -98,7 +98,7 @@ class Livetext::FunctionRegistry
98
98
  end
99
99
  end)
100
100
  register_builtin(:br, ->(param) do
101
- n = (param || "1").to_i
101
+ n = (param && !param.empty?) ? param.to_i : 1
102
102
  "<br>" * n
103
103
  end)
104
104
  register_builtin(:reverse, ->(param) do
@@ -1,5 +1,6 @@
1
1
  require_relative 'expansion'
2
2
  require_relative 'html'
3
+ require_relative 'function_caller'
3
4
 
4
5
  # Encapsulate the UserAPI as a class
5
6
 
@@ -19,6 +20,7 @@ class Livetext::UserAPI
19
20
  @vars = live.vars
20
21
  @html = Livetext::HTML.new(self)
21
22
  @expander = Livetext::Expansion.new(live)
23
+ @funcs = Livetext::FunctionCaller.new(live.function_registry)
22
24
  end
23
25
 
24
26
  def api
@@ -53,7 +55,7 @@ class Livetext::UserAPI
53
55
  end
54
56
 
55
57
  def expand_functions(str)
56
- @expander.expand_functions(str)
58
+ @expander.expand_function_calls(str)
57
59
  end
58
60
 
59
61
  def setvar(var, val) # FIXME
@@ -244,5 +246,9 @@ class Livetext::UserAPI
244
246
  def debug(*args)
245
247
  TTY.puts *args if @live.debug
246
248
  end
249
+
250
+ def funcs
251
+ @funcs
252
+ end
247
253
  end
248
254
 
@@ -2,5 +2,5 @@
2
2
  # Defining VERSION
3
3
 
4
4
  class Livetext
5
- VERSION = "0.9.60"
5
+ VERSION = "0.9.61"
6
6
  end
File without changes
@@ -0,0 +1,18 @@
1
+ 1 <h3>Testing Simple Function API</h3>
2
+ 2 <p>Date: 2025-09-09</p>
3
+ 3 /<p>Time: \d{2}:\d{2}:\d{2}</p>/
4
+ 4 /<p>Directory: .*livetext.*</p>/
5
+ 5 <p>Platform: universal.x86_64-darwin22</p>
6
+ 6 <p>Ruby version: 2.6.10</p>
7
+ 7 <p>Livetext version: 0.9.60</p>
8
+ 8 <p>Reverse of 'hello': olleh</p>
9
+ 9 <p>Square root of 16: 4</p>
10
+ 10 /<p>Random \(1-10\): \d+</p>/
11
+ 11 /<p>Link: <a style='text-decoration: none' href='https://google\.com'>Google</a></p>/
12
+ 12 <p>Line breaks: <br><br></p>
13
+ 13 <p>Date exists: true</p>
14
+ 14 <p>Nonexistent exists: false</p>
15
+ 15 <p>Total functions: 23</p>
16
+ 16 /<p>First 5 functions: br, date, day, days_ago, days_from_now</p>/
17
+ 17 <p><strong>Simple API works!</strong></p>
18
+ 18 </p>
@@ -0,0 +1,31 @@
1
+ .dot_def test_simple_func_api args
2
+ api.out "<h3>Testing Simple Function API</h3>"
3
+
4
+ # Test basic function calls
5
+ api.out "<p>Date: #{api.funcs.date()}</p>"
6
+ api.out "<p>Time: #{api.funcs.time()}</p>"
7
+ api.out "<p>Directory: #{api.funcs.pwd()}</p>"
8
+ api.out "<p>Platform: #{api.funcs.platform()}</p>"
9
+ api.out "<p>Ruby version: #{api.funcs.ruby_version()}</p>"
10
+ api.out "<p>Livetext version: #{api.funcs.livetext_version()}</p>"
11
+
12
+ # Test functions with parameters
13
+ api.out "<p>Reverse of 'hello': #{api.funcs.reverse('hello')}</p>"
14
+ api.out "<p>Square root of 16: #{api.funcs.isqrt('16')}</p>"
15
+ api.out "<p>Random (1-10): #{api.funcs.rand('1 10')}</p>"
16
+ api.out "<p>Link: #{api.funcs.link('Google|https://google.com')}</p>"
17
+ api.out "<p>Line breaks: #{api.funcs.br('2')}</p>"
18
+
19
+ # Test function existence
20
+ api.out "<p>Date exists: #{api.funcs.exists?('date')}</p>"
21
+ api.out "<p>Nonexistent exists: #{api.funcs.exists?('nonexistent')}</p>"
22
+
23
+ # Test function listing
24
+ functions = api.funcs.list
25
+ api.out "<p>Total functions: #{functions.length}</p>"
26
+ api.out "<p>First 5 functions: #{functions.first(5).join(', ')}</p>"
27
+
28
+ api.out "<p><strong>Simple API works!</strong></p>"
29
+ .end
30
+
31
+ .test_simple_func_api
File without changes
@@ -3,7 +3,7 @@
3
3
  3 Hostname: HAL9000
4
4
  4 /Platform: .*x86_64-darwin\d+/
5
5
  5 /Ruby Version: \d+\.\d+\.\d+/
6
- 6 Livetext Version: 0.9.59
6
+ 6 Livetext Version: 0.9.60
7
7
  7 </p>
8
8
  8
9
9
  9 <p>
data/test/unit/all.rb CHANGED
@@ -10,6 +10,7 @@ require_relative 'variables'
10
10
  require_relative 'variable_manager'
11
11
  require_relative 'functions'
12
12
  require_relative 'function_registry'
13
+ require_relative 'function_caller'
13
14
  require_relative 'mixin_functions_class'
14
15
  require_relative 'formatter'
15
16
  require_relative 'formatter_component'
@@ -0,0 +1,101 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/livetext'
3
+ require_relative '../../lib/livetext/function_caller'
4
+
5
+ class TestFunctionCaller < Minitest::Test
6
+ def setup
7
+ @registry = Livetext::FunctionRegistry.new
8
+ @caller = Livetext::FunctionCaller.new(@registry)
9
+ end
10
+
11
+ def test_calls_builtin_functions
12
+ # Test date function
13
+ result = @caller.date
14
+ assert_match(/\d{4}-\d{2}-\d{2}/, result)
15
+
16
+ # Test time function
17
+ result = @caller.time
18
+ assert_match(/\d{2}:\d{2}:\d{2}/, result)
19
+
20
+ # Test pwd function
21
+ result = @caller.pwd
22
+ assert_equal(Dir.pwd, result)
23
+ end
24
+
25
+ def test_calls_functions_with_parameters
26
+ # Test reverse function
27
+ result = @caller.reverse("hello")
28
+ assert_equal("olleh", result)
29
+
30
+ # Test isqrt function
31
+ result = @caller.isqrt("16")
32
+ assert_equal("4", result)
33
+
34
+ # Test rand function
35
+ result = @caller.rand("1 10")
36
+ num = result.to_i
37
+ assert(num >= 1 && num <= 10, "Random number should be between 1 and 10, got #{result}")
38
+ end
39
+
40
+ def test_calls_functions_with_no_parameters
41
+ # Test platform function
42
+ result = @caller.platform
43
+ assert_equal(RUBY_PLATFORM, result)
44
+
45
+ # Test ruby_version function
46
+ result = @caller.ruby_version
47
+ assert_equal(RUBY_VERSION, result)
48
+
49
+ # Test livetext_version function
50
+ result = @caller.livetext_version
51
+ assert_equal(Livetext::VERSION, result)
52
+ end
53
+
54
+ def test_handles_nonexistent_functions
55
+ result = @caller.nonexistent_function("param")
56
+ assert_match(/Error evaluating \$\$nonexistent_function/, result)
57
+ end
58
+
59
+ def test_function_existence_check
60
+ assert(@caller.exists?("date"))
61
+ assert(@caller.exists?("time"))
62
+ assert(@caller.exists?("pwd"))
63
+ refute(@caller.exists?("nonexistent"))
64
+ end
65
+
66
+ def test_list_functions
67
+ functions = @caller.list
68
+ assert_instance_of(Array, functions)
69
+ assert(functions.include?("date"))
70
+ assert(functions.include?("time"))
71
+ assert(functions.include?("pwd"))
72
+ assert(functions.include?("reverse"))
73
+ assert(functions.include?("isqrt"))
74
+ end
75
+
76
+ def test_respond_to_missing
77
+ assert(@caller.respond_to?(:date))
78
+ assert(@caller.respond_to?(:time))
79
+ assert(@caller.respond_to?(:pwd))
80
+ refute(@caller.respond_to?(:nonexistent))
81
+ end
82
+
83
+ def test_link_function
84
+ result = @caller.link("Google|https://google.com")
85
+ expected = "<a style='text-decoration: none' href='https://google.com'>Google</a>"
86
+ assert_equal(expected, result)
87
+ end
88
+
89
+ def test_br_function
90
+ result = @caller.br("3")
91
+ assert_equal("<br><br><br>", result)
92
+
93
+ # Test with empty parameter (default to 1)
94
+ result = @caller.br("")
95
+ assert_equal("<br>", result)
96
+
97
+ # Test with nil parameter (default to 1)
98
+ result = @caller.br(nil)
99
+ assert_equal("<br>", result)
100
+ end
101
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: livetext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.60
4
+ version: 0.9.61
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hal Fulton
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-09-06 00:00:00.000000000 Z
10
+ date: 2025-09-09 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: A smart text processor extensible in Ruby
13
13
  email: rubyhacker@gmail.com
@@ -35,6 +35,7 @@ files:
35
35
  - lib/livetext/expansion.rb
36
36
  - lib/livetext/formatter.rb
37
37
  - lib/livetext/formatter_component.rb
38
+ - lib/livetext/function_caller.rb
38
39
  - lib/livetext/function_registry.rb
39
40
  - lib/livetext/functions.rb
40
41
  - lib/livetext/global_helpers.rb
@@ -197,6 +198,10 @@ files:
197
198
  - test/snapshots/simple_copy/expected-output.txt
198
199
  - test/snapshots/simple_copy/simplefile.inc
199
200
  - test/snapshots/simple_copy/source.lt3
201
+ - test/snapshots/simple_func_api/expected-error.txt
202
+ - test/snapshots/simple_func_api/match-output.txt
203
+ - test/snapshots/simple_func_api/source.lt3
204
+ - test/snapshots/simple_func_api/stderr.txt
200
205
  - test/snapshots/simple_import/expected-error.txt
201
206
  - test/snapshots/simple_import/expected-output.txt
202
207
  - test/snapshots/simple_import/simple_import.rb
@@ -236,6 +241,7 @@ files:
236
241
  - test/unit/double.rb
237
242
  - test/unit/formatter.rb
238
243
  - test/unit/formatter_component.rb
244
+ - test/unit/function_caller.rb
239
245
  - test/unit/function_registry.rb
240
246
  - test/unit/functions.rb
241
247
  - test/unit/html.rb