livetext 0.9.59 → 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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/lib/livetext/core.rb +4 -3
  3. data/lib/livetext/function_caller.rb +32 -0
  4. data/lib/livetext/function_registry.rb +2 -2
  5. data/lib/livetext/helpers.rb +1 -0
  6. data/lib/livetext/userapi.rb +19 -3
  7. data/lib/livetext/version.rb +1 -1
  8. data/test/snapshots/basic_formatting/expected-output.txt +6 -2
  9. data/test/snapshots/block_comment/expected-output.txt +2 -0
  10. data/test/snapshots/comments_ignored_1/expected-output.txt +2 -0
  11. data/test/snapshots/complex_body/expected-output.txt +4 -1
  12. data/test/snapshots/copy_is_raw/expected-output.txt +2 -0
  13. data/test/snapshots/def_method/expected-output.txt +4 -1
  14. data/test/snapshots/def_parameters/expected-output.txt +6 -2
  15. data/test/snapshots/error_inc_line_num/expected-output.txt +1 -0
  16. data/test/snapshots/error_invalid_name/expected-output.txt +3 -1
  17. data/test/snapshots/error_line_num/expected-output.txt +1 -0
  18. data/test/snapshots/error_mismatched_end/expected-output.txt +3 -1
  19. data/test/snapshots/error_missing_end/expected-output.txt +3 -1
  20. data/test/snapshots/error_name_not_permitted/expected-output.txt +3 -1
  21. data/test/snapshots/error_no_such_copy/expected-output.txt +3 -1
  22. data/test/snapshots/error_no_such_inc/expected-output.txt +3 -1
  23. data/test/snapshots/error_no_such_mixin/expected-output.txt +3 -1
  24. data/test/snapshots/example_alpha/expected-output.txt +6 -2
  25. data/test/snapshots/example_alpha2/expected-output.txt +4 -1
  26. data/test/snapshots/functions/expected-output.txt +12 -5
  27. data/test/snapshots/functions_reflection/expected-output.txt +1 -0
  28. data/test/snapshots/hello_world/expected-output.txt +2 -0
  29. data/test/snapshots/import/expected-output.txt +3 -1
  30. data/test/snapshots/import2/expected-output.txt +6 -2
  31. data/test/snapshots/import_bookish/expected-output.txt +1 -0
  32. data/test/snapshots/mixin_booktool/expected-output.txt +1 -0
  33. data/test/snapshots/mixin_functions/expected-output.txt +12 -5
  34. data/test/snapshots/mixin_functions_class/expected-output.txt +12 -5
  35. data/test/snapshots/more_complex_vars/expected-output.txt +2 -0
  36. data/test/snapshots/more_functions/expected-output.txt +23 -10
  37. data/test/snapshots/multiple_functions/expected-output.txt +4 -1
  38. data/test/snapshots/nested_includes/expected-output.txt +26 -11
  39. data/test/snapshots/parameter_handling/expected-output.txt +4 -1
  40. data/test/snapshots/predef_vars/match-output.txt +8 -6
  41. data/test/snapshots/raw_lines/expected-output.txt +4 -1
  42. data/test/snapshots/raw_text_block/expected-output.txt +2 -0
  43. data/test/snapshots/simple_copy/expected-output.txt +2 -0
  44. data/test/snapshots/simple_func_api/match-output.txt +18 -0
  45. data/test/snapshots/simple_func_api/source.lt3 +31 -0
  46. data/test/snapshots/simple_func_api/stderr.txt +0 -0
  47. data/test/snapshots/simple_import/expected-output.txt +6 -2
  48. data/test/snapshots/simple_include/expected-output.txt +3 -0
  49. data/test/snapshots/simple_mixin/expected-output.txt +2 -0
  50. data/test/snapshots/simple_vars/expected-output.txt +2 -0
  51. data/test/snapshots/single_raw_line/expected-output.txt +4 -1
  52. data/test/snapshots/system_info/match-output.txt +22 -18
  53. data/test/snapshots/table_with_heredocs/expected-output.txt +4 -1
  54. data/test/snapshots/var_into_func/expected-output.txt +12 -5
  55. data/test/unit/all.rb +1 -0
  56. data/test/unit/function_caller.rb +101 -0
  57. metadata +8 -6
  58. data/test/snapshots/system_info/actual-output.txt +0 -20
  59. data/test/snapshots/system_info/err-sdiff.txt +0 -1
  60. data/test/snapshots/system_info/expected-output.txt +0 -20
  61. /data/test/snapshots/{system_info/actual-error.txt → simple_func_api/expected-error.txt} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa6586e6dd32101565ed6f27e471db94eecd120927242debc0f7155c37810b19
4
- data.tar.gz: f51a1aabb1ef4c17236903165c3791b11b72b665793b50def1bdb172d735c749
3
+ metadata.gz: 0d0ba9b287008c8827a9a1d30881507700dceffae0edd52e4dd5274b5fb4f004
4
+ data.tar.gz: eb988c908dcdbbbff10710a4a62bd51cdd13b832a9121814150a484448d9c5f7
5
5
  SHA512:
6
- metadata.gz: db5c47791d907813a31d31c603ddc3d8ff807d14b47a9ca8c480faba66d5f0685897e5a97541b470953a10cf1a7cc8092f6270713012877ff5cbc723c81a7a19
7
- data.tar.gz: 342c91272464b87292314d0e819d94e63dd2d0ccf4e68c14628bd4909d5f462a3e012545f1b7f39987d4a90c66c5d5dda332d566685af6eb99113ac0be7207d4
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
@@ -188,6 +188,7 @@ class Livetext
188
188
  break if line.nil?
189
189
  process_line(line)
190
190
  end
191
+ api.close_paragraph # Close any open paragraph
191
192
  result = @body
192
193
  # @body = ""
193
194
  result
@@ -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
@@ -89,6 +89,7 @@ module Livetext::Helpers
89
89
  success = process_line(line)
90
90
  break unless success
91
91
  end
92
+ api.close_paragraph # Close any open paragraph
92
93
  val = finalize rescue nil
93
94
  @body # FIXME? @body.join("\n") # array
94
95
  return true
@@ -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
@@ -188,15 +190,25 @@ class Livetext::UserAPI
188
190
  return if @live.nopass
189
191
  if line == "\n"
190
192
  unless @live.nopara
191
- out "<p>"
192
- out
193
+ out "</p>\n\n<p>"
193
194
  end
194
195
  else
196
+ # Start first paragraph if needed
197
+ if @live.body.empty? && !@live.nopara
198
+ out "<p>"
199
+ end
195
200
  text = @expander.format(line.chomp)
196
201
  out text
197
202
  end
198
203
  end
199
204
 
205
+ def close_paragraph
206
+ return if @live.nopara
207
+ return if @live.body.empty?
208
+ return if @live.body.end_with?("</p>")
209
+ out "</p>"
210
+ end
211
+
200
212
  def out(str = "", file = nil)
201
213
  return if str.nil?
202
214
  return file.puts str unless file.nil?
@@ -234,5 +246,9 @@ class Livetext::UserAPI
234
246
  def debug(*args)
235
247
  TTY.puts *args if @live.debug
236
248
  end
249
+
250
+ def funcs
251
+ @funcs
252
+ end
237
253
  end
238
254
 
@@ -2,5 +2,5 @@
2
2
  # Defining VERSION
3
3
 
4
4
  class Livetext
5
- VERSION = "0.9.59"
5
+ VERSION = "0.9.61"
6
6
  end
@@ -1,13 +1,17 @@
1
+ <p>
1
2
  Here are examples of <b>boldface</b>
2
3
  and <i>italics</i>
3
4
  and <tt>code</tt>
4
5
  as well as <b>more complex</b> examples
5
6
  of <i>italicized text</i>
6
7
  and <tt>code font</tt>.
7
- <p>
8
+ </p>
8
9
 
10
+ <p>
9
11
  Here are some random punctuation marks:
10
12
  ; # . * _ ` : @ % ^ & $
11
- <p>
13
+ </p>
12
14
 
15
+ <p>
13
16
  No need to escape these: * _ `
17
+ </p>
@@ -1,5 +1,7 @@
1
+ <p>
1
2
  abc 123
2
3
  xyz
3
4
  one
4
5
  more
5
6
  time
7
+ </p>
@@ -1,4 +1,6 @@
1
+ <p>
1
2
  abc 123
2
3
  this is a test
3
4
  more stuff
4
5
  still more stuff
6
+ </p>
@@ -1,8 +1,11 @@
1
- Testing complex function body logic...
2
1
  <p>
2
+ Testing complex function body logic...
3
+ </p>
3
4
 
5
+ <p>
4
6
  Testing with nil: nil
5
7
  Testing with empty: nil
6
8
  Testing with number: number
7
9
  Testing with string: HELLO
8
10
  Testing explicit empty: empty
11
+ </p>
@@ -1,3 +1,4 @@
1
+ <p>
1
2
  A copy command
2
3
  does not interpret its input:
3
4
  This is not a comment:
@@ -5,3 +6,4 @@ This is not a comment:
5
6
  This is not a method:
6
7
  .no_such_method
7
8
  That's all.
9
+ </p>
@@ -1,7 +1,10 @@
1
+ <p>
1
2
  abc
2
3
  123
3
4
  xyz
4
- <p>
5
+ </p>
5
6
 
7
+ <p>
6
8
  xyzzy
7
9
  123
10
+ </p>
@@ -1,12 +1,15 @@
1
+ <p>
1
2
  Testing no parameters:
2
3
  No parameters method called
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
5
7
  Testing with args and data:
6
8
  Args: ["arg1", "arg2"], Data: "arg1 arg2"
7
9
  This is the data line
8
- <p>
10
+ </p>
9
11
 
12
+ <p>
10
13
  Testing with body:
11
14
  Args: ["arg1", "arg2"], Data: "arg1 arg2"
12
15
  Body has 3 lines:
@@ -19,3 +22,4 @@ Raw body has 3 lines:
19
22
  1: This is line 1 of the raw body
20
23
  2: This is line 2 of the raw body
21
24
  3: This is line 3 of the raw body
25
+ </p>
@@ -1,3 +1,4 @@
1
+ <p>
1
2
  This is my
2
3
  source file
3
4
  which includes file2 here:
@@ -1,5 +1,7 @@
1
+ <p>
1
2
  This file has
2
3
  a defined method
3
4
  that is invalid:
4
- <p>
5
+ </p>
5
6
 
7
+ <p>
@@ -1,3 +1,4 @@
1
+ <p>
1
2
  This file
2
3
  will have an error
3
4
  on line 4
@@ -1,6 +1,8 @@
1
+ <p>
1
2
  It is an error
2
3
  to specify .end
3
4
  without something
4
5
  beginning a block:
5
- <p>
6
+ </p>
6
7
 
8
+ <p>
@@ -1,4 +1,6 @@
1
+ <p>
1
2
  Blah
2
3
  blah
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
@@ -1,4 +1,6 @@
1
+ <p>
1
2
  Names such as 'class'
2
3
  are not permitted here...
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
@@ -1,5 +1,7 @@
1
+ <p>
1
2
  Make sure a
2
3
  nonexistent file with .copy
3
4
  gives an error.
4
- <p>
5
+ </p>
5
6
 
7
+ <p>
@@ -1,5 +1,7 @@
1
+ <p>
1
2
  Make sure
2
3
  a nonexistent include
3
4
  will give an error.
4
- <p>
5
+ </p>
5
6
 
7
+ <p>
@@ -1,6 +1,8 @@
1
+ <p>
1
2
  Test that
2
3
  we give an error
3
4
  when a mixin does not
4
5
  exist:
5
- <p>
6
+ </p>
6
7
 
8
+ <p>
@@ -1,6 +1,8 @@
1
- Here is an alphabetized list:
2
1
  <p>
2
+ Here is an alphabetized list:
3
+ </p>
3
4
 
5
+ <p>
4
6
  aardvark
5
7
  anamorphic
6
8
  anarchist
@@ -18,6 +20,8 @@ Here is an alphabetized list:
18
20
  quark
19
21
  zootrope
20
22
  zymurgy
21
- <p>
23
+ </p>
22
24
 
25
+ <p>
23
26
  That's all.
27
+ </p>
@@ -1,6 +1,8 @@
1
- Here is an alphabetized list:
2
1
  <p>
2
+ Here is an alphabetized list:
3
+ </p>
3
4
 
5
+ <p>
4
6
  aardvark anamorphic anarchist
5
7
  bellicose cytology ectomorph
6
8
  fishmonger fusillade glyph
@@ -8,3 +10,4 @@ gryphon halcyon manicotti
8
10
  mataeotechny pareidolia quark
9
11
  zootrope zymurgy
10
12
  And that is all.
13
+ </p>
@@ -1,20 +1,27 @@
1
+ <p>
1
2
  Testing out
2
3
  some functions
3
4
  here...
4
- <p>
5
+ </p>
5
6
 
7
+ <p>
6
8
  I am calling Eureka! here...
7
9
  Let's see
8
10
  what happens.
9
- <p>
11
+ </p>
10
12
 
13
+ <p>
11
14
  Functions can take a parameter in brackets
12
15
  (which it can parse itself as needed):
13
- <p>
16
+ </p>
14
17
 
15
- The result is 4.0 as I see it.
16
18
  <p>
19
+ The result is 4.0 as I see it.
20
+ </p>
17
21
 
18
- Some functions like date and time are predefined.
19
22
  <p>
23
+ Some functions like date and time are predefined.
24
+ </p>
20
25
 
26
+ <p>
27
+ </p>
@@ -25,3 +25,4 @@
25
25
  <li><strong>$$weekday</strong> - builtin</li>
26
26
  <li><strong>$$year</strong> - builtin</li>
27
27
  </ul>
28
+ </p>
@@ -1,2 +1,4 @@
1
+ <p>
1
2
  Hello,
2
3
  world!
4
+ </p>
@@ -1,6 +1,8 @@
1
+ <p>
1
2
  Test .import:
2
3
  we give an error
3
4
  when a .rb does not
4
5
  exist:
5
- <p>
6
+ </p>
6
7
 
8
+ <p>
@@ -1,8 +1,12 @@
1
- Testing .import:
2
1
  <p>
2
+ Testing .import:
3
+ </p>
3
4
 
5
+ <p>
4
6
  Now call a method:
5
7
  Hello, world.
6
- <p>
8
+ </p>
7
9
 
10
+ <p>
8
11
  That's all.
12
+ </p>
@@ -8,3 +8,4 @@
8
8
  <td width=0% valign=top>bar</td>
9
9
  </tr>
10
10
  </table>
11
+ </p>
@@ -8,3 +8,4 @@
8
8
  <td width=[0, 0]% valign=top>bar</td>
9
9
  </tr>
10
10
  </table>
11
+ </p>
@@ -1,18 +1,25 @@
1
- Testing functions defined in external .rb files
2
1
  <p>
2
+ Testing functions defined in external .rb files
3
+ </p>
3
4
 
5
+ <p>
4
6
  Now calling a function defined in the .rb file:
5
7
  External function called with: test_parameter
6
- <p>
8
+ </p>
7
9
 
10
+ <p>
8
11
  And another one with brackets:
9
12
  Another function called with: with brackets
10
- <p>
13
+ </p>
11
14
 
15
+ <p>
12
16
  And a function with no parameters:
13
17
  Simple function with no parameters
14
- <p>
18
+ </p>
15
19
 
16
- That's all.
17
20
  <p>
21
+ That's all.
22
+ </p>
18
23
 
24
+ <p>
25
+ </p>
@@ -1,20 +1,27 @@
1
- Testing functions defined in Livetext::Functions class
2
1
  <p>
2
+ Testing functions defined in Livetext::Functions class
3
+ </p>
3
4
 
5
+ <p>
4
6
  Now calling functions defined in Livetext::Functions class:
5
7
  Class function called with: test_parameter
6
- <p>
8
+ </p>
7
9
 
10
+ <p>
8
11
  And another one with brackets:
9
12
  Another class function called with: with brackets
10
- <p>
13
+ </p>
11
14
 
15
+ <p>
12
16
  And a function with no parameters:
13
17
  Simple class function with no parameters
14
- <p>
18
+ </p>
15
19
 
20
+ <p>
16
21
  Testing that the functions have access to Livetext::Vars:
17
22
  Vars test: param=some_value, View=[View is undefined]
18
- <p>
23
+ </p>
19
24
 
25
+ <p>
20
26
  That's all.
27
+ </p>
@@ -1,4 +1,6 @@
1
+ <p>
1
2
  Just some more text.
2
3
  My birthday is May 31, so they tell me.
3
4
  That's 5/31 if you're American.
4
5
  That's all.
6
+ </p>
@@ -1,37 +1,50 @@
1
- Testing some more functions here...
2
1
  <p>
2
+ Testing some more functions here...
3
+ </p>
3
4
 
5
+ <p>
4
6
  Here I am calling a function with
5
7
  a colon parameter...
6
- <p>
8
+ </p>
7
9
 
8
10
  <p>
11
+ </p>
9
12
 
10
- Next let's <b>do</b> something with our parameter:
11
13
  <p>
14
+ Next let's <b>do</b> something with our parameter:
15
+ </p>
12
16
 
13
- I'll call these variants...
14
17
  <p>
18
+ I'll call these variants...
19
+ </p>
15
20
 
16
- "Motel" spelled backwards is letom :)
17
21
  <p>
22
+ "Motel" spelled backwards is letom :)
23
+ </p>
18
24
 
19
- "lamina" reversed is animal
20
25
  <p>
26
+ "lamina" reversed is animal
27
+ </p>
21
28
 
22
- I can also use the erutaef tekcarb here.
23
29
  <p>
30
+ I can also use the erutaef tekcarb here.
31
+ </p>
24
32
 
33
+ <p>
25
34
  If I don't use a parameter for [Error evaluating $$reverse()] - it gives
26
35
  me an error. (Bug or feature??)
27
- <p>
36
+ </p>
28
37
 
38
+ <p>
29
39
  What if a function doesn't use parameters at all, but
30
40
  we pass them? Hmm...
31
- <p>
41
+ </p>
32
42
 
43
+ <p>
33
44
  Now we succeed and succeed some more
34
45
  and finally we succeed in life.
35
- <p>
46
+ </p>
36
47
 
48
+ <p>
37
49
  But can we succeed, when our beds are burning?
50
+ </p>
@@ -1,5 +1,8 @@
1
- Testing multiple user functions in the same document...
2
1
  <p>
2
+ Testing multiple user functions in the same document...
3
+ </p>
3
4
 
5
+ <p>
4
6
  Calling all functions:
5
7
  one
8
+ </p>
@@ -1,68 +1,83 @@
1
+ <p>
1
2
  # Main file - Level 1
2
3
  # This file includes level2 and tests all variables and functions from all levels
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
5
7
  # Include level2 (which includes level3)
6
8
  # Level 2 - Middle level
7
9
  # This file includes level3 and defines its own variables and functions
8
- <p>
10
+ </p>
9
11
 
12
+ <p>
10
13
  # Level 3 - Deepest level
11
14
  # This file defines variables and functions that should be accessible to all higher levels
12
- <p>
15
+ </p>
13
16
 
17
+ <p>
14
18
  This is content from level 3.
15
19
  The deep variable is: I am from level 3
16
20
  The deep number is: 42
21
+ </p>
17
22
  This is content from level 2.
18
23
  The middle variable is: I am from level 2
19
24
  The middle number is: 100
20
- <p>
25
+ </p>
21
26
 
27
+ <p>
22
28
  # Test using deep level variables and functions
23
29
  Deep variable from level 2: I am from level 3
24
30
  Deep function call: Deep function called with: from level 2
25
31
  Deep math: 42 = 42
26
- <p>
32
+ </p>
27
33
 
34
+ <p>
28
35
  # Test our own variables and functions
29
36
  Middle function call: Middle function called with: from level 2
30
37
  Combined variables: Deep: I am from level 3, Middle: I am from level 2
31
- <p>
38
+ </p>
32
39
 
40
+ <p>
33
41
  # Test deep method from level 3
34
42
  Deep method called from level 3
43
+ </p>
35
44
  # Test all variables from all levels
36
45
  Main variable: I am from main level
37
46
  Middle variable: I am from level 2
38
47
  Deep variable: I am from level 3
39
- <p>
48
+ </p>
40
49
 
50
+ <p>
41
51
  # Test all functions from all levels
42
52
  Main function: Main function called with: from main
43
53
  Middle function: Middle function called with: from main
44
54
  Deep function: Deep function called with: from main
45
- <p>
55
+ </p>
46
56
 
57
+ <p>
47
58
  # Test math functions
48
59
  Deep math: 20 = 20
49
60
  Main number: 999
50
61
  Middle number: 100
51
62
  Deep number: 42
52
- <p>
63
+ </p>
53
64
 
65
+ <p>
54
66
  # Test combined functions
55
67
  Combine vars: Deep: I am from level 3, Middle: I am from level 2
56
68
  Test all levels: Main: I am from main level, Middle: I am from level 2, Deep: I am from level 3
57
- <p>
69
+ </p>
58
70
 
71
+ <p>
59
72
  # Test methods from all levels
60
73
  Main method called from main level
61
74
  Middle method called from level 2
62
75
  Deep method called from level 3
63
- <p>
76
+ </p>
64
77
 
78
+ <p>
65
79
  # Test that we can still access everything after the include
66
80
  Final test - deep function: Deep function called with: final call
67
81
  Final test - middle function: Middle function called with: final call
68
82
  Final test - main function: Main function called with: final call
83
+ </p>
@@ -1,7 +1,10 @@
1
- Testing function parameter handling...
2
1
  <p>
2
+ Testing function parameter handling...
3
+ </p>
3
4
 
5
+ <p>
4
6
  Testing with no parameter: nil
5
7
  Testing with empty parameter: nil
6
8
  Testing with string parameter: hello
7
9
  Testing with number parameter: 42
10
+ </p>
@@ -1,6 +1,8 @@
1
- 1 Here we go...
2
- 2 File = source.lt3
3
- 3 /FileDir = .*.test.snapshots.predef_vars/
4
- 4 /User = [A-Za-z][A-Za-z0-9]*/
5
- 5 /Version = 0\.\d{1,2}\.\d{1,2}/
6
- 6 NoSuchVar = [NoSuchVar is undefined]
1
+ 1 <p>
2
+ 2 Here we go...
3
+ 3 File = source.lt3
4
+ 4 /FileDir = .*.test.snapshots.predef_vars/
5
+ 5 /User = [A-Za-z][A-Za-z0-9]*/
6
+ 6 /Version = 0\.\d{1,2}\.\d{1,2}/
7
+ 7 NoSuchVar = [NoSuchVar is undefined]
8
+ 8 </p>
@@ -1,7 +1,9 @@
1
+ <p>
1
2
  The .r can be used to output single lines
2
3
  without interpretation:
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
5
7
  Ordinary line... plus two blank lines:
6
8
 
7
9
 
@@ -9,3 +11,4 @@ No formatting: *foo `foo _foo ~foo
9
11
  No variables: $alpha $beta
10
12
  No functions: $$this $$that
11
13
  That's all.
14
+ </p>
@@ -1,3 +1,4 @@
1
+ <p>
1
2
  This text block will be passed thru
2
3
  with no interpretation or processing:
3
4
  .comment
@@ -14,3 +15,4 @@ Or these:
14
15
  `(alpha male)
15
16
  _(beta max)
16
17
  *(gamma rays)
18
+ </p>
@@ -1,3 +1,4 @@
1
+ <p>
1
2
  The copy command
2
3
  copies any file
3
4
  without interpretation,
@@ -5,3 +6,4 @@ such as:
5
6
  a simple
6
7
  include file.
7
8
  That is all.
9
+ </p>
@@ -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
@@ -1,9 +1,13 @@
1
+ <p>
1
2
  Here I am
2
3
  testing a simple import
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
5
7
  Now call a method:
6
8
  Hello, world.
7
- <p>
9
+ </p>
8
10
 
11
+ <p>
9
12
  That's all.
13
+ </p>
@@ -1,7 +1,10 @@
1
+ <p>
1
2
  Here I am
2
3
  trying to
3
4
  include
4
5
  a simple
5
6
  include file.
7
+ </p>
6
8
  I hope that
7
9
  worked.
10
+ </p>
@@ -1,5 +1,7 @@
1
+ <p>
1
2
  Here I am
2
3
  testing a simple mixin
3
4
  Now call a method:
4
5
  Hello, world.
5
6
  That's all.
7
+ </p>
@@ -1,6 +1,8 @@
1
+ <p>
1
2
  Just
2
3
  some text.
3
4
  Hi, there.
4
5
  GulliverFoyle is my name, and Terra is my nation.
5
6
  I'm GulliverFoyle, from Terra.
6
7
  That's all.
8
+ </p>
@@ -1,8 +1,11 @@
1
+ <p>
1
2
  The .r can be used to output single lines
2
3
  without interpretation:
3
- <p>
4
+ </p>
4
5
 
6
+ <p>
5
7
  .comment This is not a real comment.
6
8
  This is not _italics or *boldface
7
9
  This is not a $variable reference
8
10
  That's all.
11
+ </p>
@@ -1,18 +1,22 @@
1
- 1 System Info Variables:
2
- 2 Hostname: HAL9000
3
- 3 /Platform: .*x86_64-darwin\d+/
4
- 4 /Ruby Version: \d+\.\d+\.\d+/
5
- 5 Livetext Version: 0.9.58
6
- 6 <p>
7
- 7
8
- 8 System Info Functions:
9
- 9 Hostname: HAL9000
10
- 10 /Platform: .*x86_64-darwin\d+/
11
- 11 /Ruby Version: \d+\.\d+\.\d+/
12
- 12 Livetext Version: \d+\.\d+\.\d+/
13
- 13 <p>
14
- 14
15
- 15 Date Formatting Functions:
16
- 16 /Default: \d{4}-\d{2}-\d{2}/
17
- 17 /Days ago: \d{4}-\d{2}-\d{2}/
18
- 18 /Days from now: \d{4}-\d{2}-\d{2}/
1
+ 1 <p>
2
+ 2 System Info Variables:
3
+ 3 Hostname: HAL9000
4
+ 4 /Platform: .*x86_64-darwin\d+/
5
+ 5 /Ruby Version: \d+\.\d+\.\d+/
6
+ 6 Livetext Version: 0.9.60
7
+ 7 </p>
8
+ 8
9
+ 9 <p>
10
+ 10 System Info Functions:
11
+ 11 Hostname: HAL9000
12
+ 12 /Platform: .*x86_64-darwin\d+/
13
+ 13 /Ruby Version: \d+\.\d+\.\d+/
14
+ 14 /Livetext Version: \d+\.\d+\.\d+/
15
+ 15 </p>
16
+ 16
17
+ 17 <p>
18
+ 18 Date Formatting Functions:
19
+ 19 /Default: \d{4}-\d{2}-\d{2}/
20
+ 20 /Days ago: \d{4}-\d{2}-\d{2}/
21
+ 21 /Days from now: \d{4}-\d{2}-\d{2}/
22
+ 22 </p>
@@ -1,6 +1,8 @@
1
- Testing heredocs (used in a table)
2
1
  <p>
2
+ Testing heredocs (used in a table)
3
+ </p>
3
4
 
5
+ <p>
4
6
  <br>
5
7
 
6
8
  <center><table width=90% cellpadding=5>
@@ -21,3 +23,4 @@ row 2<br><br>
21
23
  col 2<br></td>
22
24
  </tr>
23
25
  </table></center>
26
+ </p>
@@ -1,16 +1,23 @@
1
- <p>
1
+ </p>
2
2
 
3
- Testing STILL more functions here...
4
3
  <p>
4
+ Testing STILL more functions here...
5
+ </p>
5
6
 
6
7
  <p>
8
+ </p>
7
9
 
8
- Now... let's try passing a variable to a function. Will this work??
9
10
  <p>
11
+ Now... let's try passing a variable to a function. Will this work??
12
+ </p>
10
13
 
11
- Variable $alpha is regal, which reversed is lager
12
14
  <p>
15
+ Variable $alpha is regal, which reversed is lager
16
+ </p>
13
17
 
14
- That's all.
15
18
  <p>
19
+ That's all.
20
+ </p>
16
21
 
22
+ <p>
23
+ </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.59
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
@@ -216,11 +221,7 @@ files:
216
221
  - test/snapshots/single_raw_line/expected-output.txt
217
222
  - test/snapshots/single_raw_line/source.lt3
218
223
  - test/snapshots/subset.txt
219
- - test/snapshots/system_info/actual-error.txt
220
- - test/snapshots/system_info/actual-output.txt
221
- - test/snapshots/system_info/err-sdiff.txt
222
224
  - test/snapshots/system_info/expected-error.txt
223
- - test/snapshots/system_info/expected-output.txt
224
225
  - test/snapshots/system_info/match-output.txt
225
226
  - test/snapshots/system_info/source.lt3
226
227
  - test/snapshots/table_with_heredocs/expected-error.txt
@@ -240,6 +241,7 @@ files:
240
241
  - test/unit/double.rb
241
242
  - test/unit/formatter.rb
242
243
  - test/unit/formatter_component.rb
244
+ - test/unit/function_caller.rb
243
245
  - test/unit/function_registry.rb
244
246
  - test/unit/functions.rb
245
247
  - test/unit/html.rb
@@ -1,20 +0,0 @@
1
- System Info Variables:
2
- Hostname: HAL9000
3
- Platform: x86_64-darwin22
4
- Ruby Version: 3.2.3
5
- Livetext Version: 0.9.58
6
- </p>
7
-
8
- <p>
9
- System Info Functions:
10
- Hostname: HAL9000
11
- Platform: x86_64-darwin22
12
- Ruby Version: 3.2.3
13
- Livetext Version: 0.9.58
14
- </p>
15
-
16
- <p>
17
- Date Formatting Functions:
18
- Default: 2025-09-06
19
- Days ago: 2025-08-30
20
- Days from now: 2025-09-13
@@ -1 +0,0 @@
1
- ACTUAL | EXPECTED
@@ -1,20 +0,0 @@
1
- System Info Variables:
2
- Hostname: HAL9000
3
- Platform: x86_64-darwin22
4
- Ruby Version: 3.2.3
5
- Livetext Version: 0.9.58
6
- </p>
7
-
8
- <p>
9
- System Info Functions:
10
- Hostname: HAL9000
11
- Platform: x86_64-darwin22
12
- Ruby Version: 3.2.3
13
- Livetext Version: 0.9.58
14
- </p>
15
-
16
- <p>
17
- Date Formatting Functions:
18
- Default: 2025-09-06
19
- Days ago: 2025-08-30
20
- Days from now: 2025-09-13