rsyntaxtree 1.0.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,179 +1,167 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
-
4
- #==========================
5
- # element.rb
6
- #==========================
7
- #
8
- # Aa class that represents a basic tree element, either node or leaf.
9
- # Copyright (c) 2007-2021 Yoichiro Hasebe <yohasebe@gmail.com>
10
-
11
- require "markup_parser"
12
- require 'utils'
13
-
14
- module RSyntaxTree
15
- class Element
16
-
17
- attr_accessor :id,
18
- :parent, :type, :level,
19
- :width, :height,
20
- :content, :content_width, :content_height,
21
- :horizontal_indent, :vertical_indent,
22
- :triangle, :enclosure, :children, :parent,
23
- :font, :fontsize, :contains_phrase,
24
- :path
25
-
26
- def initialize(id, parent, content, level, fontset, fontsize)
27
- @type = ETYPE_LEAF
28
- @id = id # Unique element id
29
- @parent = parent # Parent element id
30
- @children = [] # Child element ids
31
- @type = type # Element type
32
- @level = level # Element level in the tree (0=top etc...)
33
- @width = 0 # Width of the part of the tree including itself and it governs
34
- @content_width = 0 # Width of the content
35
- @horizontal_indent = 0 # Drawing offset
36
- @vertical_indent = 0 # Drawing offset
37
- content = content.strip
38
-
39
- if /.+?\^?((?:\+\>?\d+)+)\^?\z/m =~ content
40
- @path = $1.sub(/\A\+/, "").split("+")
41
- else
42
- @path = []
43
- end
44
-
45
- @fontset = fontset
46
- @fontsize = fontsize
47
-
48
- parsed = Markup.parse(content)
49
-
50
- if parsed[:status] == :success
51
- results = parsed[:results]
52
- else
53
- error_text = "Error: input text contains an invalid string"
54
- error_text += "\n > " + content
55
- raise RSTError, error_text
56
- end
57
- @content = results[:contents]
58
- @paths = results[:paths]
59
- @enclosure = results[:enclosure]
60
- @triangle = results[:triangle]
61
-
62
- @contains_phrase = false
63
- setup
64
- end
65
-
66
- def setup
67
- total_width = 0
68
- total_height = 0
69
- @content.each_with_index do |content, idx|
70
- content_width = 0
71
- case content[:type]
72
- when :border, :bborder
73
- height = $single_line_height / 2
74
- content[:height] = height
75
- total_height += height
76
- when :text
77
- row_width = 0
78
- elements_height = []
79
- content[:elements].each do |e|
80
- text = e[:text]
81
- e[:text] = text.gsub(" ", WHITESPACE_BLOCK).gsub(">", '&#62;').gsub("<", '&#60;')
82
-
83
-
84
- @contains_phrase = true if text.include?(" ")
85
- decoration = e[:decoration]
86
- fontsize = decoration.include?(:small) || decoration.include?(:small) ? @fontsize * SUBSCRIPT_CONST : @fontsize
87
- fontsize = decoration.include?(:subscript) || decoration.include?(:superscript) ? fontsize * SUBSCRIPT_CONST : fontsize
88
- style = decoration.include?(:italic) || decoration.include?(:bolditalic) ? :italic : :normal
89
- weight = decoration.include?(:bold) || decoration.include?(:bolditalic) ? :bold : :normal
90
-
91
- # e[:cjk] = false
92
- # if e[:decoration].include?(:math)
93
- # font = @fontset[:math]
94
- # elsif text.contains_cjk?
95
- # font = @fontset[:cjk]
96
- # e[:cjk] = true
97
- # elsif decoration.include? :bolditalic
98
- if decoration.include? :bolditalic
99
- font = @fontset[:bolditalic]
100
- elsif decoration.include? :bold
101
- font = @fontset[:bold]
102
- elsif decoration.include? :italic
103
- font = @fontset[:italic]
104
- else
105
- font = @fontset[:normal]
106
- end
107
-
108
- standard_metrics = FontMetrics.get_metrics('X', @fontset[:normal], fontsize, :normal, :normal)
109
- height = standard_metrics.height
110
- if /\A[\<\>]+\z/ =~ text
111
- width = standard_metrics.width * text.size / 2
112
- elsif text.contains_emoji?
113
- segments = text.split_by_emoji
114
- width = 0
115
- segments.each do |seg|
116
- if /\s/ =~ seg[:char]
117
- ch = 't'
118
- else
119
- ch = seg[:char]
120
- end
121
- if seg[:type] == :emoji
122
- this_font = @fontset[:emoji]
123
- metrics = FontMetrics.get_metrics(ch, this_font, fontsize, style, weight)
124
- width += metrics.width
125
- else
126
- this_font = font
127
- metrics = FontMetrics.get_metrics(ch, this_font, fontsize, style, weight)
128
- width += metrics.width
129
- end
130
- end
131
- else
132
- text.gsub!("\\\\", 'i')
133
- text.gsub!("\\", "")
134
- text.gsub!(" ", "x")
135
- text.gsub!("%", "X")
136
- metrics = FontMetrics.get_metrics(text, font, fontsize, style, weight)
137
- width = metrics.width
138
- end
139
-
140
- if e[:decoration].include?(:box) || e[:decoration].include?(:circle) || e[:decoration].include?(:bar)
141
- if e[:text].size == 1
142
- e[:content_width] = width
143
- width += (height - width)
144
- else
145
- e[:content_width] = width
146
- width += $width_half_X
147
- end
148
- end
149
-
150
- if e[:decoration].include?(:whitespace)
151
- width = $width_half_X / 2 * e[:text].size / 4
152
- e[:text] = ""
153
- end
154
-
155
- e[:height] = height
156
- elements_height << height + $box_vertical_margin / 2
157
-
158
- e[:width] = width
159
- row_width += width
160
- end
161
-
162
- if @enclosure != :none
163
- total_height += (elements_height.max + $height_connector_to_text)
164
- else
165
- total_height += elements_height.max
166
- end
167
- content_width += row_width
168
- end
169
- total_width = content_width if total_width < content_width
170
- end
171
- @content_width = total_width
172
- @content_height = total_height
173
- end
174
-
175
- def add_child(child_id)
176
- @children << child_id
177
- end
178
- end
179
- end
1
+ # frozen_string_literal: true
2
+
3
+ #==========================
4
+ # element.rb
5
+ #==========================
6
+ #
7
+ # Aa class that represents a basic tree element, either node or leaf.
8
+ # Copyright (c) 2007-2023 Yoichiro Hasebe <yohasebe@gmail.com>
9
+
10
+ require_relative "markup_parser"
11
+ require_relative "utils"
12
+
13
+ module RSyntaxTree
14
+ class Element
15
+ attr_accessor :id, :parent, :type, :level, :width, :height, :content, :content_width, :content_height, :horizontal_indent, :vertical_indent, :triangle, :enclosure, :children, :font, :fontsize, :contains_phrase, :path
16
+
17
+ def initialize(id, parent, content, level, fontset, fontsize, global)
18
+ @global = global
19
+ @type = ETYPE_LEAF
20
+ @id = id # Unique element id
21
+ @parent = parent # Parent element id
22
+ @children = [] # Child element ids
23
+ @type = type # Element type
24
+ @level = level # Element level in the tree (0=top etc...)
25
+ @width = 0 # Width of the part of the tree including itself and it governs
26
+ @content_width = 0 # Width of the content
27
+ @horizontal_indent = 0 # Drawing offset
28
+ @vertical_indent = 0 # Drawing offset
29
+ content = content.strip
30
+
31
+ @path = if /.+?\^?((?:\+>?\d+)+)\^?\z/m =~ content
32
+ $1.sub(/\A\+/, "").split("+")
33
+ else
34
+ []
35
+ end
36
+
37
+ @fontset = fontset
38
+ @fontsize = fontsize
39
+
40
+ parsed = Markup.parse(content)
41
+
42
+ if parsed[:status] == :success
43
+ results = parsed[:results]
44
+ else
45
+ error_text = "Error: input text contains an invalid string"
46
+ error_text += "\n > " + content
47
+ raise RSTError, error_text
48
+ end
49
+ @content = results[:contents]
50
+ @paths = results[:paths]
51
+ @enclosure = results[:enclosure]
52
+ @triangle = results[:triangle]
53
+
54
+ @contains_phrase = false
55
+ setup
56
+ end
57
+
58
+ def setup
59
+ total_width = 0
60
+ total_height = 0
61
+ @content.each do |content|
62
+ content_width = 0
63
+ case content[:type]
64
+ when :border, :bborder
65
+ height = @global[:single_line_height] / 2
66
+ content[:height] = height
67
+ total_height += height
68
+ when :text
69
+ row_width = 0
70
+ elements_height = []
71
+ content[:elements].each do |e|
72
+ text = e[:text]
73
+ e[:text] = text.gsub(" ", WHITESPACE_BLOCK).gsub(">", '&#62;').gsub("<", '&#60;')
74
+
75
+ @contains_phrase = true if text.include?(" ")
76
+ decoration = e[:decoration]
77
+ fontsize = decoration.include?(:small) ? @fontsize * SUBSCRIPT_CONST : @fontsize
78
+ fontsize = decoration.include?(:subscript) || decoration.include?(:superscript) ? fontsize * SUBSCRIPT_CONST : fontsize
79
+ style = decoration.include?(:italic) || decoration.include?(:bolditalic) ? :italic : :normal
80
+ weight = decoration.include?(:bold) || decoration.include?(:bolditalic) ? :bold : :normal
81
+
82
+ # e[:cjk] = false
83
+ # if e[:decoration].include?(:math)
84
+ # font = @fontset[:math]
85
+ # elsif text.contains_cjk?
86
+ # font = @fontset[:cjk]
87
+ # e[:cjk] = true
88
+ # elsif decoration.include? :bolditalic
89
+ font = if decoration.include? :bolditalic
90
+ @fontset[:bolditalic]
91
+ elsif decoration.include? :bold
92
+ @fontset[:bold]
93
+ elsif decoration.include? :italic
94
+ @fontset[:italic]
95
+ else
96
+ @fontset[:normal]
97
+ end
98
+
99
+ standard_metrics = FontMetrics.get_metrics('X', @fontset[:normal], fontsize, :normal, :normal)
100
+ height = standard_metrics.height
101
+ if /\A[<>]+\z/ =~ text
102
+ width = standard_metrics.width * text.size / 2
103
+ elsif text.contains_emoji?
104
+ segments = text.split_by_emoji
105
+ width = 0
106
+ segments.each do |seg|
107
+ ch = if /\s/ =~ seg[:char]
108
+ 't'
109
+ else
110
+ seg[:char]
111
+ end
112
+ this_font = if seg[:type] == :emoji
113
+ @fontset[:emoji]
114
+ else
115
+ font
116
+ end
117
+ metrics = FontMetrics.get_metrics(ch, this_font, fontsize, style, weight)
118
+ width += metrics.width
119
+ end
120
+ else
121
+ text.gsub!("\\\\", 'i')
122
+ text.gsub!("\\", "")
123
+ text.gsub!(" ", "x")
124
+ text.gsub!("%", "X")
125
+ metrics = FontMetrics.get_metrics(text, font, fontsize, style, weight)
126
+ width = metrics.width
127
+ end
128
+
129
+ if e[:decoration].include?(:box) || e[:decoration].include?(:circle) || e[:decoration].include?(:bar)
130
+ e[:content_width] = width
131
+ width += if e[:text].size == 1
132
+ height - width
133
+ else
134
+ @global[:width_half_x]
135
+ end
136
+ end
137
+
138
+ if e[:decoration].include?(:whitespace)
139
+ width = @global[:width_half_x] / 2 * e[:text].size / 4
140
+ e[:text] = ""
141
+ end
142
+
143
+ e[:height] = height
144
+ elements_height << height + @global[:box_vertical_margin] / 2
145
+
146
+ e[:width] = width
147
+ row_width += width
148
+ end
149
+
150
+ total_height += if @enclosure != :none
151
+ elements_height.max + @global[:height_connector_to_text]
152
+ else
153
+ elements_height.max
154
+ end
155
+ content_width += row_width
156
+ end
157
+ total_width = content_width if total_width < content_width
158
+ end
159
+ @content_width = total_width
160
+ @content_height = total_height
161
+ end
162
+
163
+ def add_child(child_id)
164
+ @children << child_id
165
+ end
166
+ end
167
+ end
@@ -1,124 +1,105 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
-
4
- #==========================
5
- # elementlist.rb
6
- #==========================
7
- #
8
- # Contains a list of unordered tree elements with a defined parent
9
- # Copyright (c) 2007-2021 Yoichiro Hasebe <yohasebe@gmail.com>
10
-
11
- require 'element'
12
-
13
- module RSyntaxTree
14
- class ElementList
15
-
16
- attr_accessor :elements, :iterator
17
- def initialize
18
- @elements = Array.new # The element array
19
- @iterator = -1 # Iterator index (used for get_first / get_next)
20
- end
21
-
22
- def set_hierarchy
23
- @elements.each do |e|
24
- get_id(e.parent).add_child(e.id) unless e.parent == 0
25
- end
26
- end
27
-
28
- def add(element)
29
- @elements << element
30
- if(element.parent != 0)
31
- parent = get_id(element.parent)
32
- parent.type = ETYPE_NODE
33
- end
34
- end
35
-
36
- def get_first
37
- if(@elements.length == 0)
38
- return nil
39
- else
40
- @iterator = 0
41
- return @elements[@iterator]
42
- end
43
- end
44
-
45
- def get_next
46
- @iterator += 1
47
- if @elements[@iterator]
48
- return @elements[@iterator]
49
- else
50
- return nil
51
- end
52
- end
53
-
54
- def get_id(id)
55
- @elements.each do |element|
56
- if(element.id == id)
57
- return element
58
- end
59
- end
60
- return nil;
61
- end
62
-
63
- def get_elements
64
- @elements
65
- end
66
-
67
- def get_child_count(id)
68
- get_children(id).length
69
- end
70
-
71
- def get_children(id)
72
- children = Array.new
73
- @elements.each do |element|
74
- if(element.parent == id)
75
- children << element.id
76
- end
77
- end
78
- children
79
- end
80
-
81
- def get_element_width(id)
82
- element = get_id(id)
83
- if element
84
- return element.width
85
- else
86
- return -1;
87
- end
88
- end
89
-
90
- def set_element_width(id, width)
91
- element = get_id(id)
92
- if element
93
- element.width = width
94
- end
95
- end
96
-
97
- def get_indent(id)
98
- element = get_id(id)
99
- if element
100
- return element.indent
101
- else
102
- return -1
103
- end
104
- end
105
-
106
- def set_indent(id, indent)
107
- element = get_id(id)
108
- if element
109
- element.indent = indent
110
- end
111
- end
112
-
113
- def get_level_height
114
- maxlevel = 0
115
- @elements.each do |element|
116
- level = element.level
117
- if(level > maxlevel)
118
- maxlevel = level
119
- end
120
- end
121
- return maxlevel + 1;
122
- end
123
- end
124
- end
1
+ # frozen_string_literal: true
2
+
3
+ #==========================
4
+ # elementlist.rb
5
+ #==========================
6
+ #
7
+ # Contains a list of unordered tree elements with a defined parent
8
+ # Copyright (c) 2007-2023 Yoichiro Hasebe <yohasebe@gmail.com>
9
+
10
+ require_relative "element"
11
+
12
+ module RSyntaxTree
13
+ class ElementList
14
+ attr_accessor :elements, :iterator
15
+
16
+ def initialize
17
+ @elements = []
18
+ @iterator = -1 # Iterator index (used for get_first / get_next)
19
+ end
20
+
21
+ def set_hierarchy
22
+ @elements.each do |e|
23
+ get_id(e.parent).add_child(e.id) unless e.parent.zero?
24
+ end
25
+ end
26
+
27
+ def add(element)
28
+ @elements << element
29
+ return if element.parent.zero?
30
+
31
+ parent = get_id(element.parent)
32
+ parent.type = ETYPE_NODE
33
+ end
34
+
35
+ def get_first
36
+ return nil if @elements.length.empty?
37
+
38
+ @iterator = 0
39
+ @elements[@iterator]
40
+ end
41
+
42
+ def get_next
43
+ @iterator += 1
44
+ return @elements[@iterator] if @elements[@iterator]
45
+
46
+ nil
47
+ end
48
+
49
+ def get_id(id)
50
+ @elements.each do |element|
51
+ return element if element.id == id
52
+ end
53
+ nil
54
+ end
55
+
56
+ def get_elements
57
+ @elements
58
+ end
59
+
60
+ def get_child_count(id)
61
+ get_children(id).length
62
+ end
63
+
64
+ def get_children(id)
65
+ children = []
66
+ @elements.each do |element|
67
+ children << element.id if element.parent == id
68
+ end
69
+ children
70
+ end
71
+
72
+ def get_element_width(id)
73
+ element = get_id(id)
74
+ return element.width if element
75
+
76
+ -1;
77
+ end
78
+
79
+ def set_element_width(id, width)
80
+ element = get_id(id)
81
+ element.width = width if element
82
+ end
83
+
84
+ def get_indent(id)
85
+ element = get_id(id)
86
+ return element.indent if element
87
+
88
+ -1
89
+ end
90
+
91
+ def set_indent(id, indent)
92
+ element = get_id(id)
93
+ element.indent = indent if element
94
+ end
95
+
96
+ def get_level_height
97
+ maxlevel = 0
98
+ @elements.each do |element|
99
+ level = element.level
100
+ maxlevel = level if level > maxlevel
101
+ end
102
+ maxlevel + 1
103
+ end
104
+ end
105
+ end