fxri 0.3.4 → 0.3.5
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.
- data/fxri +4 -344
- data/fxri.gemspec +24 -24
- data/fxri.rb +351 -0
- data/lib/Empty_Text_Field_Handler.rb +63 -63
- data/lib/FoxDisplayer.rb +148 -148
- data/lib/FoxTextFormatter.rb +274 -274
- data/lib/Icon_Loader.rb +35 -35
- data/lib/Packet_Item.rb +178 -178
- data/lib/Packet_List.rb +192 -192
- data/lib/Recursive_Open_Struct.rb +233 -238
- data/lib/Search_Engine.rb +165 -165
- data/lib/fxirb.rb +401 -400
- metadata +13 -22
- data/bugs/fxri bug `concat' can't convert nil into Array (TypeError).eml +0 -50
- data/bugs/fxri with Ruby v1.8.5 via OneClickInstaller v1.8.5-21.eml +0 -167
- data/fxri-0.3.4.gem +0 -0
- data/lib/fxirb-0.2.1/CHANGELOG +0 -31
- data/lib/fxirb-0.2.1/fxirb.rb +0 -395
@@ -1,63 +1,63 @@
|
|
1
|
-
# Copyright (c) 2004, 2005 Martin Ankerl
|
2
|
-
# Shows a grey text in an FXTextField if the user did not enter any input. This is a nice way to
|
3
|
-
# give the user more information about what to enter into a text field, without the need of additional
|
4
|
-
# space in the GUI.
|
5
|
-
class Empty_Text_Field_Handler
|
6
|
-
|
7
|
-
# Create a new handler for the specified textfield, with the given text. From now on you have to use the
|
8
|
-
# created object to get and set text, not the textfield or this handler would come out of sync
|
9
|
-
def initialize(textField, myText)
|
10
|
-
@textField = textField
|
11
|
-
@myText = myText
|
12
|
-
@isEmpty = true
|
13
|
-
onTextFieldFocusOut
|
14
|
-
# create connections
|
15
|
-
@textField.connect(SEL_FOCUSIN, method(:onTextFieldFocusIn))
|
16
|
-
@textField.connect(SEL_FOCUSOUT, method(:onTextFieldFocusOut))
|
17
|
-
end
|
18
|
-
|
19
|
-
# Check if textfield is empty (no user input).
|
20
|
-
def empty?
|
21
|
-
@isEmpty
|
22
|
-
end
|
23
|
-
|
24
|
-
# Set new text for the textfield
|
25
|
-
def text=(newText)
|
26
|
-
onTextFieldFocusIn
|
27
|
-
@textField.text = newText.to_s
|
28
|
-
onTextFieldFocusOut
|
29
|
-
end
|
30
|
-
|
31
|
-
# Get the textfield's text, if the user has entered something.
|
32
|
-
def text
|
33
|
-
if empty? && !@inside
|
34
|
-
""
|
35
|
-
else
|
36
|
-
@textField.text
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Set focus to the textfield.
|
41
|
-
def setFocus
|
42
|
-
@textField.setFocus
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def onTextFieldFocusIn(*args)
|
48
|
-
@inside = true
|
49
|
-
return if !@isEmpty
|
50
|
-
@textField.textColor = FXColor::Black
|
51
|
-
@textField.text = ""
|
52
|
-
end
|
53
|
-
|
54
|
-
def onTextFieldFocusOut(*args)
|
55
|
-
@inside = false
|
56
|
-
@textField.killSelection
|
57
|
-
@isEmpty = @textField.text == ""
|
58
|
-
return if !@isEmpty
|
59
|
-
@textField.textColor = FXColor::DarkGrey
|
60
|
-
@textField.text = @myText
|
61
|
-
@isEmpty = true
|
62
|
-
end
|
63
|
-
end
|
1
|
+
# Copyright (c) 2004, 2005 Martin Ankerl
|
2
|
+
# Shows a grey text in an FXTextField if the user did not enter any input. This is a nice way to
|
3
|
+
# give the user more information about what to enter into a text field, without the need of additional
|
4
|
+
# space in the GUI.
|
5
|
+
class Empty_Text_Field_Handler
|
6
|
+
|
7
|
+
# Create a new handler for the specified textfield, with the given text. From now on you have to use the
|
8
|
+
# created object to get and set text, not the textfield or this handler would come out of sync
|
9
|
+
def initialize(textField, myText)
|
10
|
+
@textField = textField
|
11
|
+
@myText = myText
|
12
|
+
@isEmpty = true
|
13
|
+
onTextFieldFocusOut
|
14
|
+
# create connections
|
15
|
+
@textField.connect(SEL_FOCUSIN, method(:onTextFieldFocusIn))
|
16
|
+
@textField.connect(SEL_FOCUSOUT, method(:onTextFieldFocusOut))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check if textfield is empty (no user input).
|
20
|
+
def empty?
|
21
|
+
@isEmpty
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set new text for the textfield
|
25
|
+
def text=(newText)
|
26
|
+
onTextFieldFocusIn
|
27
|
+
@textField.text = newText.to_s
|
28
|
+
onTextFieldFocusOut
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the textfield's text, if the user has entered something.
|
32
|
+
def text
|
33
|
+
if empty? && !@inside
|
34
|
+
""
|
35
|
+
else
|
36
|
+
@textField.text
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set focus to the textfield.
|
41
|
+
def setFocus
|
42
|
+
@textField.setFocus
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def onTextFieldFocusIn(*args)
|
48
|
+
@inside = true
|
49
|
+
return if !@isEmpty
|
50
|
+
@textField.textColor = FXColor::Black
|
51
|
+
@textField.text = ""
|
52
|
+
end
|
53
|
+
|
54
|
+
def onTextFieldFocusOut(*args)
|
55
|
+
@inside = false
|
56
|
+
@textField.killSelection
|
57
|
+
@isEmpty = @textField.text == ""
|
58
|
+
return if !@isEmpty
|
59
|
+
@textField.textColor = FXColor::DarkGrey
|
60
|
+
@textField.text = @myText
|
61
|
+
@isEmpty = true
|
62
|
+
end
|
63
|
+
end
|
data/lib/FoxDisplayer.rb
CHANGED
@@ -1,148 +1,148 @@
|
|
1
|
-
class FoxDisplayer
|
2
|
-
attr_accessor :reader
|
3
|
-
|
4
|
-
def initialize(text_field)
|
5
|
-
@text_field = text_field
|
6
|
-
@formatter = FoxTextFormatter.new(70, "") do |arg, style|
|
7
|
-
startpos = @str.size
|
8
|
-
@str << arg
|
9
|
-
@formats.push [startpos, arg.size, style]
|
10
|
-
end
|
11
|
-
@reader = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
def width=(newWidth)
|
15
|
-
@formatter.width = newWidth
|
16
|
-
end
|
17
|
-
|
18
|
-
def no_info_available
|
19
|
-
@text_field.text="nothing here, move on!"
|
20
|
-
end
|
21
|
-
|
22
|
-
def init_text
|
23
|
-
@str = ""
|
24
|
-
@formats = Array.new
|
25
|
-
end
|
26
|
-
|
27
|
-
# Sets a new text, and all styles
|
28
|
-
def set_text
|
29
|
-
@text_field.text = @str
|
30
|
-
@formats.each do |start, n, style|
|
31
|
-
case style
|
32
|
-
when FoxTextFormatter::STYLE_BOLD
|
33
|
-
@text_field.changeStyle(start, n, 2)
|
34
|
-
when FoxTextFormatter::STYLE_H1
|
35
|
-
@text_field.changeStyle(start, n, 3)
|
36
|
-
when FoxTextFormatter::STYLE_H2
|
37
|
-
@text_field.changeStyle(start, n, 4)
|
38
|
-
when FoxTextFormatter::STYLE_H3
|
39
|
-
@text_field.changeStyle(start, n, 5)
|
40
|
-
when FoxTextFormatter::STYLE_TELETYPE
|
41
|
-
@text_field.changeStyle(start, n, 6)
|
42
|
-
when FoxTextFormatter::STYLE_CODE
|
43
|
-
@text_field.changeStyle(start, n, 7)
|
44
|
-
when FoxTextFormatter::STYLE_EMPHASIS
|
45
|
-
@text_field.changeStyle(start, n, 8)
|
46
|
-
when FoxTextFormatter::STYLE_CLASS
|
47
|
-
@text_field.changeStyle(start, n, 9)
|
48
|
-
else
|
49
|
-
@text_field.changeStyle(start, n, 1)
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Display method information
|
56
|
-
def display_method_info(method)
|
57
|
-
init_text
|
58
|
-
@formatter.draw_line(method.full_name)
|
59
|
-
@formatter.display_params(method)
|
60
|
-
@formatter.draw_line
|
61
|
-
display_flow(method.comment)
|
62
|
-
|
63
|
-
if method.aliases && !method.aliases.empty?
|
64
|
-
@formatter.blankline
|
65
|
-
aka = "(also known as "
|
66
|
-
aka << method.aliases.map {|a| a.name }.join(", ")
|
67
|
-
aka << ")"
|
68
|
-
@formatter.wrap(aka)
|
69
|
-
end
|
70
|
-
set_text
|
71
|
-
end
|
72
|
-
|
73
|
-
def display_information(message)
|
74
|
-
init_text
|
75
|
-
display_flow(message)
|
76
|
-
set_text
|
77
|
-
end
|
78
|
-
|
79
|
-
def display_class_info(klass)
|
80
|
-
init_text
|
81
|
-
superclass = klass.superclass_string
|
82
|
-
if superclass
|
83
|
-
superclass = " < " + superclass
|
84
|
-
else
|
85
|
-
superclass = ""
|
86
|
-
end
|
87
|
-
@formatter.draw_line(klass.display_name + ": " + klass.full_name + superclass)
|
88
|
-
display_flow(klass.comment)
|
89
|
-
@formatter.draw_line
|
90
|
-
|
91
|
-
unless klass.includes.empty?
|
92
|
-
@formatter.blankline
|
93
|
-
@formatter.display_heading("Includes:", 2, "")
|
94
|
-
incs = []
|
95
|
-
klass.includes.each do |inc|
|
96
|
-
inc_desc = @reader.find_class_by_name(inc.name)
|
97
|
-
if inc_desc
|
98
|
-
str = inc.name + "("
|
99
|
-
str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
|
100
|
-
str << ")"
|
101
|
-
incs << str
|
102
|
-
else
|
103
|
-
incs << inc.name
|
104
|
-
end
|
105
|
-
end
|
106
|
-
@formatter.wrap(incs.sort.join(', '))
|
107
|
-
end
|
108
|
-
|
109
|
-
unless klass.constants.empty?
|
110
|
-
@formatter.blankline
|
111
|
-
@formatter.display_heading("Constants:", 2, "")
|
112
|
-
len = 0
|
113
|
-
klass.constants.each { |c| len = c.name.length if c.name.length > len }
|
114
|
-
len += 2
|
115
|
-
klass.constants.each do |c|
|
116
|
-
@formatter.wrap(c.value, @formatter.indent+((c.name+":").ljust(len)))
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
unless klass.class_methods.empty?
|
121
|
-
@formatter.blankline
|
122
|
-
@formatter.display_heading("Class methods:", 2, "")
|
123
|
-
@formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
|
124
|
-
end
|
125
|
-
|
126
|
-
unless klass.instance_methods.empty?
|
127
|
-
@formatter.blankline
|
128
|
-
@formatter.display_heading("Instance methods:", 2, "")
|
129
|
-
@formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
|
130
|
-
end
|
131
|
-
|
132
|
-
unless klass.attributes.empty?
|
133
|
-
@formatter.blankline
|
134
|
-
@formatter.wrap("Attributes:", "")
|
135
|
-
@formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
|
136
|
-
end
|
137
|
-
|
138
|
-
set_text
|
139
|
-
end
|
140
|
-
|
141
|
-
def display_flow(flow)
|
142
|
-
if !flow || flow.empty?
|
143
|
-
@formatter.wrap("(no description...)\n")
|
144
|
-
else
|
145
|
-
@formatter.display_flow(flow)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
1
|
+
class FoxDisplayer
|
2
|
+
attr_accessor :reader
|
3
|
+
|
4
|
+
def initialize(text_field)
|
5
|
+
@text_field = text_field
|
6
|
+
@formatter = FoxTextFormatter.new(70, "") do |arg, style|
|
7
|
+
startpos = @str.size
|
8
|
+
@str << arg
|
9
|
+
@formats.push [startpos, arg.size, style]
|
10
|
+
end
|
11
|
+
@reader = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def width=(newWidth)
|
15
|
+
@formatter.width = newWidth
|
16
|
+
end
|
17
|
+
|
18
|
+
def no_info_available
|
19
|
+
@text_field.text="nothing here, move on!"
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_text
|
23
|
+
@str = ""
|
24
|
+
@formats = Array.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sets a new text, and all styles
|
28
|
+
def set_text
|
29
|
+
@text_field.text = @str
|
30
|
+
@formats.each do |start, n, style|
|
31
|
+
case style
|
32
|
+
when FoxTextFormatter::STYLE_BOLD
|
33
|
+
@text_field.changeStyle(start, n, 2)
|
34
|
+
when FoxTextFormatter::STYLE_H1
|
35
|
+
@text_field.changeStyle(start, n, 3)
|
36
|
+
when FoxTextFormatter::STYLE_H2
|
37
|
+
@text_field.changeStyle(start, n, 4)
|
38
|
+
when FoxTextFormatter::STYLE_H3
|
39
|
+
@text_field.changeStyle(start, n, 5)
|
40
|
+
when FoxTextFormatter::STYLE_TELETYPE
|
41
|
+
@text_field.changeStyle(start, n, 6)
|
42
|
+
when FoxTextFormatter::STYLE_CODE
|
43
|
+
@text_field.changeStyle(start, n, 7)
|
44
|
+
when FoxTextFormatter::STYLE_EMPHASIS
|
45
|
+
@text_field.changeStyle(start, n, 8)
|
46
|
+
when FoxTextFormatter::STYLE_CLASS
|
47
|
+
@text_field.changeStyle(start, n, 9)
|
48
|
+
else
|
49
|
+
@text_field.changeStyle(start, n, 1)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Display method information
|
56
|
+
def display_method_info(method)
|
57
|
+
init_text
|
58
|
+
@formatter.draw_line(method.full_name)
|
59
|
+
@formatter.display_params(method)
|
60
|
+
@formatter.draw_line
|
61
|
+
display_flow(method.comment)
|
62
|
+
|
63
|
+
if method.aliases && !method.aliases.empty?
|
64
|
+
@formatter.blankline
|
65
|
+
aka = "(also known as "
|
66
|
+
aka << method.aliases.map {|a| a.name }.join(", ")
|
67
|
+
aka << ")"
|
68
|
+
@formatter.wrap(aka)
|
69
|
+
end
|
70
|
+
set_text
|
71
|
+
end
|
72
|
+
|
73
|
+
def display_information(message)
|
74
|
+
init_text
|
75
|
+
display_flow(message)
|
76
|
+
set_text
|
77
|
+
end
|
78
|
+
|
79
|
+
def display_class_info(klass)
|
80
|
+
init_text
|
81
|
+
superclass = klass.superclass_string
|
82
|
+
if superclass
|
83
|
+
superclass = " < " + superclass
|
84
|
+
else
|
85
|
+
superclass = ""
|
86
|
+
end
|
87
|
+
@formatter.draw_line(klass.display_name + ": " + klass.full_name + superclass)
|
88
|
+
display_flow(klass.comment)
|
89
|
+
@formatter.draw_line
|
90
|
+
|
91
|
+
unless klass.includes.empty?
|
92
|
+
@formatter.blankline
|
93
|
+
@formatter.display_heading("Includes:", 2, "")
|
94
|
+
incs = []
|
95
|
+
klass.includes.each do |inc|
|
96
|
+
inc_desc = @reader.find_class_by_name(inc.name)
|
97
|
+
if inc_desc
|
98
|
+
str = inc.name + "("
|
99
|
+
str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
|
100
|
+
str << ")"
|
101
|
+
incs << str
|
102
|
+
else
|
103
|
+
incs << inc.name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
@formatter.wrap(incs.sort.join(', '))
|
107
|
+
end
|
108
|
+
|
109
|
+
unless klass.constants.empty?
|
110
|
+
@formatter.blankline
|
111
|
+
@formatter.display_heading("Constants:", 2, "")
|
112
|
+
len = 0
|
113
|
+
klass.constants.each { |c| len = c.name.length if c.name.length > len }
|
114
|
+
len += 2
|
115
|
+
klass.constants.each do |c|
|
116
|
+
@formatter.wrap(c.value, @formatter.indent+((c.name+":").ljust(len)))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
unless klass.class_methods.empty?
|
121
|
+
@formatter.blankline
|
122
|
+
@formatter.display_heading("Class methods:", 2, "")
|
123
|
+
@formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
|
124
|
+
end
|
125
|
+
|
126
|
+
unless klass.instance_methods.empty?
|
127
|
+
@formatter.blankline
|
128
|
+
@formatter.display_heading("Instance methods:", 2, "")
|
129
|
+
@formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
|
130
|
+
end
|
131
|
+
|
132
|
+
unless klass.attributes.empty?
|
133
|
+
@formatter.blankline
|
134
|
+
@formatter.wrap("Attributes:", "")
|
135
|
+
@formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
|
136
|
+
end
|
137
|
+
|
138
|
+
set_text
|
139
|
+
end
|
140
|
+
|
141
|
+
def display_flow(flow)
|
142
|
+
if !flow || flow.empty?
|
143
|
+
@formatter.wrap("(no description...)\n")
|
144
|
+
else
|
145
|
+
@formatter.display_flow(flow)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/lib/FoxTextFormatter.rb
CHANGED
@@ -1,275 +1,275 @@
|
|
1
|
-
# This class is mostly copy & paste from ri_formatter.rb.
|
2
|
-
# except that it always returns a string and does not print anything.
|
3
|
-
class FoxTextFormatter
|
4
|
-
# define all possible styles
|
5
|
-
STYLE_NORMAL = :STYLE_NORMAL
|
6
|
-
STYLE_BOLD = :STYLE_BOLD
|
7
|
-
STYLE_CLASS = :STYLE_CLASS
|
8
|
-
STYLE_H1 = :STYLE_H1
|
9
|
-
STYLE_H2 = :STYLE_H2
|
10
|
-
STYLE_H3 = :STYLE_H3
|
11
|
-
STYLE_TELETYPE = :STYLE_TELETYPE
|
12
|
-
STYLE_CODE = :STYLE_CODE
|
13
|
-
STYLE_EMPHASIS = :STYLE_EMPHASIS
|
14
|
-
|
15
|
-
attr_reader :indent
|
16
|
-
attr_accessor :width
|
17
|
-
|
18
|
-
# whenever text should be printed/added/shown, proc is called with the text as the argument.
|
19
|
-
def initialize(width, indent, &proc)
|
20
|
-
@width = width
|
21
|
-
@indent = indent
|
22
|
-
@proc = proc
|
23
|
-
end
|
24
|
-
|
25
|
-
######################################################################
|
26
|
-
|
27
|
-
def draw_line(label=nil)
|
28
|
-
len = @width
|
29
|
-
len -= (label.size+1) if label
|
30
|
-
len = [0, len].max
|
31
|
-
@proc.call("-"*len)
|
32
|
-
if label
|
33
|
-
@proc.call(" ")
|
34
|
-
@proc.call(label, STYLE_CLASS)
|
35
|
-
end
|
36
|
-
@proc.call("\n")
|
37
|
-
end
|
38
|
-
|
39
|
-
def display_params(method)
|
40
|
-
params = method.params
|
41
|
-
|
42
|
-
if params[0] == ?(
|
43
|
-
if method.is_singleton
|
44
|
-
params = method.full_name + params
|
45
|
-
else
|
46
|
-
params = method.name + params
|
47
|
-
end
|
48
|
-
end
|
49
|
-
params.split(/\n/).each do |param|
|
50
|
-
@proc.call(param+"\n", STYLE_BOLD)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def wrap(txt, prefix=@indent, linelen=@width)
|
55
|
-
return if !txt || txt.empty?
|
56
|
-
@proc.call(prefix, STYLE_EMPHASIS)
|
57
|
-
conv_markup(txt, prefix, linelen)
|
58
|
-
=begin
|
59
|
-
textLen = linelen - prefix.length
|
60
|
-
patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
|
61
|
-
next_prefix = prefix.tr("^ ", " ")
|
62
|
-
|
63
|
-
res = []
|
64
|
-
|
65
|
-
while work.length > textLen
|
66
|
-
if work =~ patt
|
67
|
-
res << $1
|
68
|
-
work.slice!(0, $&.length)
|
69
|
-
else
|
70
|
-
res << work.slice!(0, textLen)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
res << work if work.length.nonzero?
|
74
|
-
@proc.call(prefix + res.join("\n" + next_prefix) + "\n")
|
75
|
-
=end
|
76
|
-
end
|
77
|
-
|
78
|
-
######################################################################
|
79
|
-
|
80
|
-
def blankline
|
81
|
-
@proc.call("\n")
|
82
|
-
end
|
83
|
-
|
84
|
-
######################################################################
|
85
|
-
|
86
|
-
# called when we want to ensure a nbew 'wrap' starts on a newline
|
87
|
-
# Only needed for HtmlFormatter, because the rest do their
|
88
|
-
# own line breaking
|
89
|
-
|
90
|
-
def break_to_newline
|
91
|
-
end
|
92
|
-
|
93
|
-
######################################################################
|
94
|
-
|
95
|
-
def bold_print(txt)
|
96
|
-
@proc.call(txt, STYLE_BOLD)
|
97
|
-
end
|
98
|
-
|
99
|
-
######################################################################
|
100
|
-
|
101
|
-
def raw_print_line(txt)
|
102
|
-
@proc.call(txt)
|
103
|
-
end
|
104
|
-
|
105
|
-
######################################################################
|
106
|
-
|
107
|
-
# convert HTML entities back to ASCII
|
108
|
-
def conv_html(txt)
|
109
|
-
case txt
|
110
|
-
when Array
|
111
|
-
txt.join.
|
112
|
-
gsub(/>/, '>').
|
113
|
-
gsub(/</, '<').
|
114
|
-
gsub(/"/, '"').
|
115
|
-
gsub(/&/, '&')
|
116
|
-
else # it's a String
|
117
|
-
txt.
|
118
|
-
gsub(/>/, '>').
|
119
|
-
gsub(/</, '<').
|
120
|
-
gsub(/"/, '"').
|
121
|
-
gsub(/&/, '&')
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# convert markup into display form
|
126
|
-
def conv_markup(txt, prefix, linelen)
|
127
|
-
|
128
|
-
# this code assumes that tags are not used inside tags
|
129
|
-
pos = 0
|
130
|
-
old_pos = 0
|
131
|
-
style = STYLE_NORMAL
|
132
|
-
current_indent = prefix.size
|
133
|
-
while pos = txt.index(%r{(<tt>|<code>|<b>|<em>|</tt>|</code>|</b>|</em>)}, old_pos)
|
134
|
-
new_part = txt[old_pos...pos]
|
135
|
-
@proc.call(new_part, style)
|
136
|
-
|
137
|
-
# get tag name
|
138
|
-
old_pos = txt.index(">", pos) + 1
|
139
|
-
style = case txt[(pos+1)...(old_pos-1)]
|
140
|
-
when "tt"
|
141
|
-
STYLE_TELETYPE
|
142
|
-
when "code"
|
143
|
-
STYLE_CODE
|
144
|
-
when "b"
|
145
|
-
STYLE_BOLD
|
146
|
-
when "em"
|
147
|
-
STYLE_EMPHASIS
|
148
|
-
else
|
149
|
-
# closing or unknown tags
|
150
|
-
STYLE_NORMAL
|
151
|
-
end
|
152
|
-
end
|
153
|
-
@proc.call(txt[old_pos...txt.size], style)
|
154
|
-
@proc.call("\n")
|
155
|
-
end
|
156
|
-
|
157
|
-
######################################################################
|
158
|
-
|
159
|
-
def display_list(list)
|
160
|
-
case list.type
|
161
|
-
when SM::ListBase::BULLET
|
162
|
-
prefixer = proc { |ignored| @indent + "* " }
|
163
|
-
|
164
|
-
when SM::ListBase::NUMBER,
|
165
|
-
SM::ListBase::UPPERALPHA,
|
166
|
-
SM::ListBase::LOWERALPHA
|
167
|
-
|
168
|
-
start = case list.type
|
169
|
-
when SM::ListBase::NUMBER then 1
|
170
|
-
when SM::ListBase::UPPERALPHA then 'A'
|
171
|
-
when SM::ListBase::LOWERALPHA then 'a'
|
172
|
-
end
|
173
|
-
prefixer = proc do |ignored|
|
174
|
-
res = @indent + "#{start}.".ljust(4)
|
175
|
-
start = start.succ
|
176
|
-
res
|
177
|
-
end
|
178
|
-
|
179
|
-
when SM::ListBase::LABELED
|
180
|
-
prefixer = proc do |li|
|
181
|
-
li.label
|
182
|
-
end
|
183
|
-
|
184
|
-
when SM::ListBase::NOTE
|
185
|
-
longest = 0
|
186
|
-
list.contents.each do |item|
|
187
|
-
if item.kind_of?(SM::Flow::LI) && item.label.length > longest
|
188
|
-
longest = item.label.length
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
prefixer = proc do |li|
|
193
|
-
@indent + li.label.ljust(longest+1)
|
194
|
-
end
|
195
|
-
|
196
|
-
else
|
197
|
-
fail "unknown list type"
|
198
|
-
end
|
199
|
-
|
200
|
-
list.contents.each do |item|
|
201
|
-
if item.kind_of? SM::Flow::LI
|
202
|
-
prefix = prefixer.call(item)
|
203
|
-
display_flow_item(item, prefix)
|
204
|
-
else
|
205
|
-
display_flow_item(item)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
######################################################################
|
211
|
-
|
212
|
-
def display_flow_item(item, prefix=@indent)
|
213
|
-
|
214
|
-
case item
|
215
|
-
when SM::Flow::P, SM::Flow::LI
|
216
|
-
wrap(conv_html(item.body), prefix)
|
217
|
-
blankline
|
218
|
-
|
219
|
-
when SM::Flow::LIST
|
220
|
-
display_list(item)
|
221
|
-
|
222
|
-
when SM::Flow::VERB
|
223
|
-
display_verbatim_flow_item(item, @indent)
|
224
|
-
|
225
|
-
when SM::Flow::H
|
226
|
-
display_heading(conv_html(item.text), item.level, @indent)
|
227
|
-
|
228
|
-
when SM::Flow::RULE
|
229
|
-
draw_line
|
230
|
-
|
231
|
-
when String
|
232
|
-
wrap(conv_html(item), prefix)
|
233
|
-
|
234
|
-
else
|
235
|
-
fail "Unknown flow element: #{item.class}"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
######################################################################
|
240
|
-
|
241
|
-
def display_verbatim_flow_item(item, prefix=@indent)
|
242
|
-
item.body.split(/\n/).each do |line|
|
243
|
-
@proc.call(@indent)
|
244
|
-
@proc.call(conv_html(line))
|
245
|
-
@proc.call("\n")
|
246
|
-
end
|
247
|
-
blankline
|
248
|
-
end
|
249
|
-
|
250
|
-
######################################################################
|
251
|
-
|
252
|
-
def display_heading(text, level, indent)
|
253
|
-
case level
|
254
|
-
when 1
|
255
|
-
@proc.call(text, STYLE_H1)
|
256
|
-
@proc.call("\n")
|
257
|
-
|
258
|
-
when 2
|
259
|
-
@proc.call(text, STYLE_H2)
|
260
|
-
@proc.call("\n")
|
261
|
-
|
262
|
-
else
|
263
|
-
@proc.call(indent)
|
264
|
-
@proc.call(text, STYLE_H3)
|
265
|
-
@proc.call("\n")
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
|
270
|
-
def display_flow(flow)
|
271
|
-
flow.each do |f|
|
272
|
-
display_flow_item(f)
|
273
|
-
end
|
274
|
-
end
|
1
|
+
# This class is mostly copy & paste from ri_formatter.rb.
|
2
|
+
# except that it always returns a string and does not print anything.
|
3
|
+
class FoxTextFormatter
|
4
|
+
# define all possible styles
|
5
|
+
STYLE_NORMAL = :STYLE_NORMAL
|
6
|
+
STYLE_BOLD = :STYLE_BOLD
|
7
|
+
STYLE_CLASS = :STYLE_CLASS
|
8
|
+
STYLE_H1 = :STYLE_H1
|
9
|
+
STYLE_H2 = :STYLE_H2
|
10
|
+
STYLE_H3 = :STYLE_H3
|
11
|
+
STYLE_TELETYPE = :STYLE_TELETYPE
|
12
|
+
STYLE_CODE = :STYLE_CODE
|
13
|
+
STYLE_EMPHASIS = :STYLE_EMPHASIS
|
14
|
+
|
15
|
+
attr_reader :indent
|
16
|
+
attr_accessor :width
|
17
|
+
|
18
|
+
# whenever text should be printed/added/shown, proc is called with the text as the argument.
|
19
|
+
def initialize(width, indent, &proc)
|
20
|
+
@width = width
|
21
|
+
@indent = indent
|
22
|
+
@proc = proc
|
23
|
+
end
|
24
|
+
|
25
|
+
######################################################################
|
26
|
+
|
27
|
+
def draw_line(label=nil)
|
28
|
+
len = @width
|
29
|
+
len -= (label.size+1) if label
|
30
|
+
len = [0, len].max
|
31
|
+
@proc.call("-"*len)
|
32
|
+
if label
|
33
|
+
@proc.call(" ")
|
34
|
+
@proc.call(label, STYLE_CLASS)
|
35
|
+
end
|
36
|
+
@proc.call("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def display_params(method)
|
40
|
+
params = method.params
|
41
|
+
|
42
|
+
if params[0] == ?(
|
43
|
+
if method.is_singleton
|
44
|
+
params = method.full_name + params
|
45
|
+
else
|
46
|
+
params = method.name + params
|
47
|
+
end
|
48
|
+
end
|
49
|
+
params.split(/\n/).each do |param|
|
50
|
+
@proc.call(param+"\n", STYLE_BOLD)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def wrap(txt, prefix=@indent, linelen=@width)
|
55
|
+
return if !txt || txt.empty?
|
56
|
+
@proc.call(prefix, STYLE_EMPHASIS)
|
57
|
+
conv_markup(txt, prefix, linelen)
|
58
|
+
=begin
|
59
|
+
textLen = linelen - prefix.length
|
60
|
+
patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
|
61
|
+
next_prefix = prefix.tr("^ ", " ")
|
62
|
+
|
63
|
+
res = []
|
64
|
+
|
65
|
+
while work.length > textLen
|
66
|
+
if work =~ patt
|
67
|
+
res << $1
|
68
|
+
work.slice!(0, $&.length)
|
69
|
+
else
|
70
|
+
res << work.slice!(0, textLen)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
res << work if work.length.nonzero?
|
74
|
+
@proc.call(prefix + res.join("\n" + next_prefix) + "\n")
|
75
|
+
=end
|
76
|
+
end
|
77
|
+
|
78
|
+
######################################################################
|
79
|
+
|
80
|
+
def blankline
|
81
|
+
@proc.call("\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
######################################################################
|
85
|
+
|
86
|
+
# called when we want to ensure a nbew 'wrap' starts on a newline
|
87
|
+
# Only needed for HtmlFormatter, because the rest do their
|
88
|
+
# own line breaking
|
89
|
+
|
90
|
+
def break_to_newline
|
91
|
+
end
|
92
|
+
|
93
|
+
######################################################################
|
94
|
+
|
95
|
+
def bold_print(txt)
|
96
|
+
@proc.call(txt, STYLE_BOLD)
|
97
|
+
end
|
98
|
+
|
99
|
+
######################################################################
|
100
|
+
|
101
|
+
def raw_print_line(txt)
|
102
|
+
@proc.call(txt)
|
103
|
+
end
|
104
|
+
|
105
|
+
######################################################################
|
106
|
+
|
107
|
+
# convert HTML entities back to ASCII
|
108
|
+
def conv_html(txt)
|
109
|
+
case txt
|
110
|
+
when Array
|
111
|
+
txt.join.
|
112
|
+
gsub(/>/, '>').
|
113
|
+
gsub(/</, '<').
|
114
|
+
gsub(/"/, '"').
|
115
|
+
gsub(/&/, '&')
|
116
|
+
else # it's a String
|
117
|
+
txt.
|
118
|
+
gsub(/>/, '>').
|
119
|
+
gsub(/</, '<').
|
120
|
+
gsub(/"/, '"').
|
121
|
+
gsub(/&/, '&')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# convert markup into display form
|
126
|
+
def conv_markup(txt, prefix, linelen)
|
127
|
+
|
128
|
+
# this code assumes that tags are not used inside tags
|
129
|
+
pos = 0
|
130
|
+
old_pos = 0
|
131
|
+
style = STYLE_NORMAL
|
132
|
+
current_indent = prefix.size
|
133
|
+
while pos = txt.index(%r{(<tt>|<code>|<b>|<em>|</tt>|</code>|</b>|</em>)}, old_pos)
|
134
|
+
new_part = txt[old_pos...pos]
|
135
|
+
@proc.call(new_part, style)
|
136
|
+
|
137
|
+
# get tag name
|
138
|
+
old_pos = txt.index(">", pos) + 1
|
139
|
+
style = case txt[(pos+1)...(old_pos-1)]
|
140
|
+
when "tt"
|
141
|
+
STYLE_TELETYPE
|
142
|
+
when "code"
|
143
|
+
STYLE_CODE
|
144
|
+
when "b"
|
145
|
+
STYLE_BOLD
|
146
|
+
when "em"
|
147
|
+
STYLE_EMPHASIS
|
148
|
+
else
|
149
|
+
# closing or unknown tags
|
150
|
+
STYLE_NORMAL
|
151
|
+
end
|
152
|
+
end
|
153
|
+
@proc.call(txt[old_pos...txt.size], style)
|
154
|
+
@proc.call("\n")
|
155
|
+
end
|
156
|
+
|
157
|
+
######################################################################
|
158
|
+
|
159
|
+
def display_list(list)
|
160
|
+
case list.type
|
161
|
+
when SM::ListBase::BULLET
|
162
|
+
prefixer = proc { |ignored| @indent + "* " }
|
163
|
+
|
164
|
+
when SM::ListBase::NUMBER,
|
165
|
+
SM::ListBase::UPPERALPHA,
|
166
|
+
SM::ListBase::LOWERALPHA
|
167
|
+
|
168
|
+
start = case list.type
|
169
|
+
when SM::ListBase::NUMBER then 1
|
170
|
+
when SM::ListBase::UPPERALPHA then 'A'
|
171
|
+
when SM::ListBase::LOWERALPHA then 'a'
|
172
|
+
end
|
173
|
+
prefixer = proc do |ignored|
|
174
|
+
res = @indent + "#{start}.".ljust(4)
|
175
|
+
start = start.succ
|
176
|
+
res
|
177
|
+
end
|
178
|
+
|
179
|
+
when SM::ListBase::LABELED
|
180
|
+
prefixer = proc do |li|
|
181
|
+
li.label
|
182
|
+
end
|
183
|
+
|
184
|
+
when SM::ListBase::NOTE
|
185
|
+
longest = 0
|
186
|
+
list.contents.each do |item|
|
187
|
+
if item.kind_of?(SM::Flow::LI) && item.label.length > longest
|
188
|
+
longest = item.label.length
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
prefixer = proc do |li|
|
193
|
+
@indent + li.label.ljust(longest+1)
|
194
|
+
end
|
195
|
+
|
196
|
+
else
|
197
|
+
fail "unknown list type"
|
198
|
+
end
|
199
|
+
|
200
|
+
list.contents.each do |item|
|
201
|
+
if item.kind_of? SM::Flow::LI
|
202
|
+
prefix = prefixer.call(item)
|
203
|
+
display_flow_item(item, prefix)
|
204
|
+
else
|
205
|
+
display_flow_item(item)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
######################################################################
|
211
|
+
|
212
|
+
def display_flow_item(item, prefix=@indent)
|
213
|
+
|
214
|
+
case item
|
215
|
+
when SM::Flow::P, SM::Flow::LI
|
216
|
+
wrap(conv_html(item.body), prefix)
|
217
|
+
blankline
|
218
|
+
|
219
|
+
when SM::Flow::LIST
|
220
|
+
display_list(item)
|
221
|
+
|
222
|
+
when SM::Flow::VERB
|
223
|
+
display_verbatim_flow_item(item, @indent)
|
224
|
+
|
225
|
+
when SM::Flow::H
|
226
|
+
display_heading(conv_html(item.text), item.level, @indent)
|
227
|
+
|
228
|
+
when SM::Flow::RULE
|
229
|
+
draw_line
|
230
|
+
|
231
|
+
when String
|
232
|
+
wrap(conv_html(item), prefix)
|
233
|
+
|
234
|
+
else
|
235
|
+
fail "Unknown flow element: #{item.class}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
######################################################################
|
240
|
+
|
241
|
+
def display_verbatim_flow_item(item, prefix=@indent)
|
242
|
+
item.body.split(/\n/).each do |line|
|
243
|
+
@proc.call(@indent)
|
244
|
+
@proc.call(conv_html(line))
|
245
|
+
@proc.call("\n")
|
246
|
+
end
|
247
|
+
blankline
|
248
|
+
end
|
249
|
+
|
250
|
+
######################################################################
|
251
|
+
|
252
|
+
def display_heading(text, level, indent)
|
253
|
+
case level
|
254
|
+
when 1
|
255
|
+
@proc.call(text, STYLE_H1)
|
256
|
+
@proc.call("\n")
|
257
|
+
|
258
|
+
when 2
|
259
|
+
@proc.call(text, STYLE_H2)
|
260
|
+
@proc.call("\n")
|
261
|
+
|
262
|
+
else
|
263
|
+
@proc.call(indent)
|
264
|
+
@proc.call(text, STYLE_H3)
|
265
|
+
@proc.call("\n")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
def display_flow(flow)
|
271
|
+
flow.each do |f|
|
272
|
+
display_flow_item(f)
|
273
|
+
end
|
274
|
+
end
|
275
275
|
end
|