livetext 0.9.55 → 0.9.56

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/livetext/ast/show_ast_clean.rb +10 -0
  3. data/lib/livetext/ast/show_ast_result.rb +60 -0
  4. data/lib/livetext/ast/show_raw_arrays.rb +13 -0
  5. data/lib/livetext/ast.rb +464 -0
  6. data/lib/livetext/ast_to_html.rb +32 -0
  7. data/lib/livetext/core.rb +6 -4
  8. data/lib/livetext/errors.rb +1 -0
  9. data/lib/livetext/functions.rb +26 -0
  10. data/lib/livetext/handler/mixin.rb +28 -0
  11. data/lib/livetext/helpers.rb +19 -20
  12. data/lib/livetext/standard.rb +2 -2
  13. data/lib/livetext/userapi.rb +20 -1
  14. data/lib/livetext/variable_manager.rb +14 -1
  15. data/lib/livetext/variables.rb +5 -1
  16. data/lib/livetext/version.rb +1 -1
  17. data/plugin/booktool.rb +6 -6
  18. data/plugin/lt3scriptor.rb +914 -0
  19. data/plugin/mixin_functions_class.rb +33 -0
  20. data/test/snapshots/error_missing_end/match-error.txt +1 -1
  21. data/test/snapshots/mixin_functions_class/expected-error.txt +0 -0
  22. data/test/snapshots/mixin_functions_class/expected-output.txt +20 -0
  23. data/test/snapshots/mixin_functions_class/mixin_functions_class.rb +33 -0
  24. data/test/snapshots/mixin_functions_class/source.lt3 +17 -0
  25. data/test/snapshots/system_info/match-output.txt +18 -0
  26. data/test/unit/all.rb +3 -0
  27. data/test/unit/ast.rb +90 -0
  28. data/test/unit/ast_directives.rb +104 -0
  29. data/test/unit/ast_variables.rb +71 -0
  30. data/test/unit/core_methods.rb +180 -0
  31. data/test/unit/formatter_component.rb +1 -1
  32. data/test/unit/mixin_functions_class.rb +131 -0
  33. data/test/unit/stringparser.rb +14 -32
  34. metadata +18 -5
  35. data/imports/markdown.rb +0 -44
  36. data/plugin/markdown.rb +0 -43
  37. data/test/snapshots/system_info/expected-output.txt +0 -18
@@ -0,0 +1,131 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/livetext'
3
+
4
+ class TestingMixinFunctionsClass < Minitest::Test
5
+ def setup
6
+ @live = Livetext.new
7
+ end
8
+
9
+ def test_mixin_registers_functions_from_class
10
+ # Test that the mixin handler properly registers functions from Livetext::Functions class
11
+
12
+ # First, verify that our test functions don't exist yet
13
+ registry = @live.function_registry
14
+ assert_nil(registry.get_function_info('class_func'))
15
+ assert_nil(registry.get_function_info('another_class_func'))
16
+ assert_nil(registry.get_function_info('simple_class_func'))
17
+
18
+ # Load the mixin by calling the method directly
19
+ @live.mixin(['mixin_functions_class'], '')
20
+
21
+ # Now verify that the functions are registered
22
+ info = registry.get_function_info('class_func')
23
+ assert_equal('class_func', info[:name])
24
+ assert_equal('mixin (/Users/Hal/Dropbox/topx/git/livetext/plugin/mixin_functions_class.rb)', info[:source])
25
+ assert_equal(:user, info[:type])
26
+
27
+ info = registry.get_function_info('another_class_func')
28
+ assert_equal('another_class_func', info[:name])
29
+ assert_equal('mixin (/Users/Hal/Dropbox/topx/git/livetext/plugin/mixin_functions_class.rb)', info[:source])
30
+
31
+ info = registry.get_function_info('simple_class_func')
32
+ assert_equal('simple_class_func', info[:name])
33
+ assert_equal('mixin (/Users/Hal/Dropbox/topx/git/livetext/plugin/mixin_functions_class.rb)', info[:source])
34
+ end
35
+
36
+ def test_mixin_functions_work_properly
37
+ # Test that the registered functions actually work
38
+
39
+ # Load the mixin
40
+ @live.mixin(['mixin_functions_class'], '')
41
+
42
+ # Test function calls
43
+ result = @live.api.format("$$class_func:test_param")
44
+ assert_equal("Class function called with: test_param", result)
45
+
46
+ result = @live.api.format("$$another_class_func[with brackets]")
47
+ assert_equal("Another class function called with: with brackets", result)
48
+
49
+ result = @live.api.format("$$simple_class_func")
50
+ assert_equal("Simple class function with no parameters", result)
51
+ end
52
+
53
+ def test_mixin_functions_have_vars_access
54
+ # Test that functions in Livetext::Functions class have access to Livetext::Vars
55
+
56
+ # Set a variable using the better instance-based approach
57
+ @live.vars.set(:View, "test_view")
58
+
59
+ # Load the mixin
60
+ @live.mixin(['mixin_functions_class'], '')
61
+
62
+ # Test function that accesses vars
63
+ result = @live.api.format("$$vars_test:some_value")
64
+ assert_equal("Vars test: param=some_value, View=test_view", result)
65
+ end
66
+
67
+ def test_mixin_does_not_register_builtin_functions
68
+ # Test that the mixin handler doesn't re-register builtin functions
69
+
70
+ # Load the mixin
71
+ @live.mixin(['mixin_functions_class'], '')
72
+
73
+ # Check that builtin functions still have correct source
74
+ registry = @live.function_registry
75
+ info = registry.get_function_info('date')
76
+ assert_equal('builtin', info[:source]) # Should still be builtin, not mixin
77
+
78
+ info = registry.get_function_info('reverse')
79
+ assert_equal('builtin', info[:source]) # Should still be builtin, not mixin
80
+ end
81
+
82
+ def test_mixin_registers_both_module_and_class_functions
83
+ # Test that mixin handler registers both module methods and Livetext::Functions methods
84
+
85
+ # Create a test mixin file with both types
86
+ test_mixin_content = <<~RUBY
87
+ def module_func(param)
88
+ "Module function: \#{param}"
89
+ end
90
+
91
+ class Livetext::Functions
92
+ def class_func(param)
93
+ "Class function: \#{param}"
94
+ end
95
+ end
96
+ RUBY
97
+
98
+ # Write temporary test file in current directory
99
+ test_file = File.join(Dir.pwd, "temp_mixin_test.rb")
100
+ File.write(test_file, test_mixin_content)
101
+
102
+ begin
103
+ # Load the mixin
104
+ @live.mixin(['temp_mixin_test'], '')
105
+
106
+ # Test that both types of functions are registered
107
+ registry = @live.function_registry
108
+
109
+ # Module function should be registered
110
+ info = registry.get_function_info('module_func')
111
+ assert_equal('module_func', info[:name])
112
+ assert_equal("mixin (./temp_mixin_test.rb)", info[:source])
113
+
114
+ # Class function should be registered
115
+ info = registry.get_function_info('class_func')
116
+ assert_equal('class_func', info[:name])
117
+ assert_equal("mixin (./temp_mixin_test.rb)", info[:source])
118
+
119
+ # Both should work
120
+ result = @live.api.format("$$module_func:test")
121
+ assert_equal("Module function: test", result)
122
+
123
+ result = @live.api.format("$$class_func:test")
124
+ assert_equal("Class function: test", result)
125
+
126
+ ensure
127
+ # Clean up
128
+ File.delete(test_file) if File.exist?(test_file)
129
+ end
130
+ end
131
+ end
@@ -1,8 +1,6 @@
1
1
  require 'minitest/autorun'
2
2
 
3
-
4
-
5
- require_relative '../../lib/stringparser'
3
+ require_relative '../../lib/livetext/parser/string'
6
4
 
7
5
  class TestStringParser < Minitest::Test
8
6
 
@@ -38,13 +36,13 @@ class TestStringParser < Minitest::Test
38
36
  end
39
37
 
40
38
  def test_next
41
- assert_nil @zero.next
39
+ assert_nil @zero.grab
42
40
  assert_equal @zero.i, 0 # nothing happens
43
41
 
44
- assert_equal @one.next, "x"
42
+ assert_equal @one.grab, "x"
45
43
  assert_equal @one.i, 1
46
44
 
47
- assert_equal @many.next, "T"
45
+ assert_equal @many.grab, "T"
48
46
  refute @many.eos, "EOS was true for #{@many.inspect}"
49
47
  assert_equal @many.i, 1
50
48
  end
@@ -56,20 +54,20 @@ class TestStringParser < Minitest::Test
56
54
  end
57
55
 
58
56
  def test_next_eos
59
- @zero.next
57
+ @zero.grab
60
58
  assert @zero.eos?
61
59
 
62
60
  @one.eos?
63
61
  refute @one.eos?
64
- @one.next
62
+ @one.grab
65
63
  assert @one.eos?
66
- @one.next # One beyond the actual end
64
+ @one.grab # One beyond the actual end
67
65
  assert @one.eos? # Still the end
68
66
 
69
- @many.next
67
+ @many.grab
70
68
  refute @many.eos?
71
69
  count = @many.len # doesn't make sense??
72
- count.times { @many.next }
70
+ count.times { @many.grab }
73
71
  assert @many.eos?
74
72
  end
75
73
 
@@ -80,36 +78,20 @@ class TestStringParser < Minitest::Test
80
78
  end
81
79
 
82
80
  def test_next_peek
83
- char1 = @zero.next
81
+ char1 = @zero.grab
84
82
  char2 = @zero.peek
85
83
  assert_nil char1
86
84
  assert_nil char2
87
85
  assert @zero.i == 0
88
- assert @zero.last?
89
86
  assert @zero.eos?
90
87
 
91
- refute @one.last?
92
88
  char1 = @one.peek
93
- refute @one.last?
94
- char2 = @one.next
95
- assert @one.last? # One beyond the last
89
+ char2 = @one.grab
96
90
  char3 = @one.peek
97
91
  assert char1
98
92
  assert char2 == char1
99
93
  assert char3 == @str1[1]
100
94
  assert @one.i == 1
101
- assert @one.last?
102
- assert @one.eos?
103
-
104
- char1 = @many.peek
105
- char2 = @many.next
106
- char3 = @many.peek
107
- assert char1
108
- assert char2 == char1
109
- assert char3 == @strN[1]
110
- assert @many.i == 1
111
- refute @many.last?
112
- refute @many.eos?
113
95
  end
114
96
 
115
97
  def test_skip_spaces
@@ -135,8 +117,8 @@ class TestStringParser < Minitest::Test
135
117
 
136
118
  def test_for_parse_set
137
119
  str = StringParser.new('gamma = "oh, well"')
138
- count = str.len # doesn't make sense??
139
- count.times { print str.next; }
140
-
120
+ count = str.len
121
+ count.times { str.grab }
122
+ assert str.eos?
141
123
  end
142
124
  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.55
4
+ version: 0.9.56
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hal Fulton
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-08-07 00:00:00.000000000 Z
10
+ date: 2025-08-08 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: A smart text processor extensible in Ruby
13
13
  email: rubyhacker@gmail.com
@@ -22,10 +22,14 @@ files:
22
22
  - imports/bookish.rb
23
23
  - imports/calibre.rb
24
24
  - imports/livemagick.rb
25
- - imports/markdown.rb
26
25
  - imports/pyggish.rb
27
26
  - imports/tutorial.rb
28
27
  - lib/livetext.rb
28
+ - lib/livetext/ast.rb
29
+ - lib/livetext/ast/show_ast_clean.rb
30
+ - lib/livetext/ast/show_ast_result.rb
31
+ - lib/livetext/ast/show_raw_arrays.rb
32
+ - lib/livetext/ast_to_html.rb
29
33
  - lib/livetext/core.rb
30
34
  - lib/livetext/errors.rb
31
35
  - lib/livetext/expansion.rb
@@ -57,8 +61,9 @@ files:
57
61
  - plugin/bootstrap_menu.rb
58
62
  - plugin/codetool.rb
59
63
  - plugin/livemagick.rb
60
- - plugin/markdown.rb
64
+ - plugin/lt3scriptor.rb
61
65
  - plugin/misc/navbar.rb
66
+ - plugin/mixin_functions_class.rb
62
67
  - plugin/tutorial.rb
63
68
  - test/all.rb
64
69
  - test/extra/README.txt
@@ -157,6 +162,10 @@ files:
157
162
  - test/snapshots/mixin_functions/expected-output.txt
158
163
  - test/snapshots/mixin_functions/mixin_functions.rb
159
164
  - test/snapshots/mixin_functions/source.lt3
165
+ - test/snapshots/mixin_functions_class/expected-error.txt
166
+ - test/snapshots/mixin_functions_class/expected-output.txt
167
+ - test/snapshots/mixin_functions_class/mixin_functions_class.rb
168
+ - test/snapshots/mixin_functions_class/source.lt3
160
169
  - test/snapshots/more_complex_vars/expected-error.txt
161
170
  - test/snapshots/more_complex_vars/expected-output.txt
162
171
  - test/snapshots/more_complex_vars/source.lt3
@@ -208,7 +217,7 @@ files:
208
217
  - test/snapshots/single_raw_line/source.lt3
209
218
  - test/snapshots/subset.txt
210
219
  - test/snapshots/system_info/expected-error.txt
211
- - test/snapshots/system_info/expected-output.txt
220
+ - test/snapshots/system_info/match-output.txt
212
221
  - test/snapshots/system_info/source.lt3
213
222
  - test/snapshots/table_with_heredocs/expected-error.txt
214
223
  - test/snapshots/table_with_heredocs/expected-output.txt
@@ -219,6 +228,9 @@ files:
219
228
  - test/snapshots/var_into_func/source.lt3
220
229
  - test/test_escape.lt3
221
230
  - test/unit/all.rb
231
+ - test/unit/ast.rb
232
+ - test/unit/ast_directives.rb
233
+ - test/unit/ast_variables.rb
222
234
  - test/unit/bracketed.rb
223
235
  - test/unit/core_methods.rb
224
236
  - test/unit/double.rb
@@ -227,6 +239,7 @@ files:
227
239
  - test/unit/function_registry.rb
228
240
  - test/unit/functions.rb
229
241
  - test/unit/html.rb
242
+ - test/unit/mixin_functions_class.rb
230
243
  - test/unit/parser.rb
231
244
  - test/unit/parser/all.rb
232
245
  - test/unit/parser/general.rb
data/imports/markdown.rb DELETED
@@ -1,44 +0,0 @@
1
- # This file is intended to be used via a Livetext .mixin
2
- # or the equivalent.
3
-
4
- module Markdown
5
- SimpleFormats = {}
6
- SimpleFormats[:b] = %w[* *]
7
- SimpleFormats[:i] = %w[_ _]
8
- SimpleFormats[:t] = %w[` `]
9
- SimpleFormats[:s] = %w[<strike> </strike>]
10
-
11
-
12
- def h1(args = nil, body = nil); api.out "# #{Livetext.interpolate(api.data)}"; api.optional_blank_line end # atx style for now
13
- def h2(args = nil, body = nil); api.out "## #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
14
- def h3(args = nil, body = nil); api.out "### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
15
- def h4(args = nil, body = nil); api.out "#### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
16
- def h5(args = nil, body = nil); api.out "##### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
17
- def h6(args = nil, body = nil); api.out "###### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
18
-
19
- def title(args = nil, body = nil)
20
- h1
21
- end
22
-
23
- def section(args = nil, body = nil)
24
- h3
25
- end
26
-
27
- def bq(args = nil, body = nil) # block quote
28
- api.body {|line| api.out "> #{line}" }
29
- end
30
-
31
- def list(args = nil, body = nil)
32
- api.body {|line| api.out " * #{line}" }
33
- end
34
-
35
- def olist(args = nil, body = nil) # Doesn't handle paragraphs yet
36
- n = 0
37
- api.body do |line|
38
- n += 1
39
- api.out "#{n}. #{_format(line)}"
40
- end
41
- end
42
-
43
- alias nlist olist
44
- end
data/plugin/markdown.rb DELETED
@@ -1,43 +0,0 @@
1
- # This file is intended to be used via a Livetext .mixin
2
- # or the equivalent.
3
-
4
- SimpleFormats = {}
5
- SimpleFormats[:b] = %w[* *]
6
- SimpleFormats[:i] = %w[_ _]
7
- SimpleFormats[:t] = %w[` `]
8
- SimpleFormats[:s] = %w[<strike> </strike>]
9
-
10
-
11
- def h1(args = nil, body = nil); api.out "# #{Livetext.interpolate(api.data)}"; api.optional_blank_line end # atx style for now
12
- def h2(args = nil, body = nil); api.out "## #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
13
- def h3(args = nil, body = nil); api.out "### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
14
- def h4(args = nil, body = nil); api.out "#### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
15
- def h5(args = nil, body = nil); api.out "##### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
16
- def h6(args = nil, body = nil); api.out "###### #{Livetext.interpolate(api.data)}"; api.optional_blank_line end
17
-
18
- def title(args = nil, body = nil)
19
- h1
20
- end
21
-
22
- def section(args = nil, body = nil)
23
- h3
24
- end
25
-
26
- def bq(args = nil, body = nil) # block quote
27
- api.body {|line| api.out "> #{line}" }
28
- end
29
-
30
- def list(args = nil, body = nil)
31
- api.body {|line| api.out " * #{line}" }
32
- end
33
-
34
- def olist(args = nil, body = nil) # Doesn't handle paragraphs yet
35
- n = 0
36
- api.body do |line|
37
- n += 1
38
- api.out "#{n}. #{_format(line)}"
39
- end
40
- end
41
-
42
- alias nlist olist
43
-
@@ -1,18 +0,0 @@
1
- System Info Variables:
2
- Hostname: HAL9000
3
- Platform: universal.x86_64-darwin22
4
- Ruby Version: 2.6.10
5
- Livetext Version: 0.9.53
6
- <p>
7
-
8
- System Info Functions:
9
- Hostname: HAL9000
10
- Platform: universal.x86_64-darwin22
11
- Ruby Version: 2.6.10
12
- Livetext Version: 0.9.53
13
- <p>
14
-
15
- Date Formatting Functions:
16
- Default: 2025-08-07
17
- Days ago: 2025-07-31
18
- Days from now: 2025-08-14