profanity_fe 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/profanity +1692 -0
- data/lib/profanity_fe/countdown_window.rb +72 -0
- data/lib/profanity_fe/indicator_window.rb +48 -0
- data/lib/profanity_fe/progress_window.rb +67 -0
- data/lib/profanity_fe/text_window.rb +174 -0
- metadata +49 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
class CountdownWindow < Curses::Window
|
2
|
+
attr_accessor :label, :fg, :bg, :end_time, :secondary_end_time, :active, :layout
|
3
|
+
attr_reader :value, :secondary_value
|
4
|
+
|
5
|
+
@@list = Array.new
|
6
|
+
|
7
|
+
def CountdownWindow.list
|
8
|
+
@@list
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
@label = String.new
|
13
|
+
@fg = [ ]
|
14
|
+
@bg = [ nil, 'ff0000', '0000ff' ]
|
15
|
+
@active = nil
|
16
|
+
@end_time = 0
|
17
|
+
@secondary_end_time = 0
|
18
|
+
@@list.push(self)
|
19
|
+
super(*args)
|
20
|
+
end
|
21
|
+
def update
|
22
|
+
old_value, old_secondary_value = @value, @secondary_value
|
23
|
+
@value = [(@end_time.to_f - Time.now.to_f + $server_time_offset.to_f - 0.2).ceil, 0].max
|
24
|
+
@secondary_value = [(@secondary_end_time.to_f - Time.now.to_f + $server_time_offset.to_f - 0.2).ceil, 0].max
|
25
|
+
if (old_value != @value) or (old_secondary_value != @secondary_value) or (@old_active != @active)
|
26
|
+
str = "#{@label}#{[ @value, @secondary_value ].max.to_s.rjust(self.maxx - @label.length)}"
|
27
|
+
setpos(0, 0)
|
28
|
+
if ((@value == 0) and (@secondary_value == 0)) or (@active == false)
|
29
|
+
if @active
|
30
|
+
str = "#{@label}#{'?'.rjust(self.maxx - @label.length)}"
|
31
|
+
left_background_str = str[0,1].to_s
|
32
|
+
right_background_str = str[(left_background_str.length),(@label.length + (self.maxx - @label.length))].to_s
|
33
|
+
attron(color_pair(get_color_pair_id(@fg[1], @bg[1]))|Curses::A_NORMAL) {
|
34
|
+
addstr left_background_str
|
35
|
+
}
|
36
|
+
attron(color_pair(get_color_pair_id(@fg[2], @bg[2]))|Curses::A_NORMAL) {
|
37
|
+
addstr right_background_str
|
38
|
+
}
|
39
|
+
else
|
40
|
+
attron(color_pair(get_color_pair_id(@fg[0], @bg[0]))|Curses::A_NORMAL) {
|
41
|
+
addstr str
|
42
|
+
}
|
43
|
+
end
|
44
|
+
else
|
45
|
+
left_background_str = str[0,@value].to_s
|
46
|
+
secondary_background_str = str[left_background_str.length,(@secondary_value - @value)].to_s
|
47
|
+
right_background_str = str[(left_background_str.length + secondary_background_str.length),(@label.length + (self.maxx - @label.length))].to_s
|
48
|
+
if left_background_str.length > 0
|
49
|
+
attron(color_pair(get_color_pair_id(@fg[1], @bg[1]))|Curses::A_NORMAL) {
|
50
|
+
addstr left_background_str
|
51
|
+
}
|
52
|
+
end
|
53
|
+
if secondary_background_str.length > 0
|
54
|
+
attron(color_pair(get_color_pair_id(@fg[2], @bg[2]))|Curses::A_NORMAL) {
|
55
|
+
addstr secondary_background_str
|
56
|
+
}
|
57
|
+
end
|
58
|
+
if right_background_str.length > 0
|
59
|
+
attron(color_pair(get_color_pair_id(@fg[3], @bg[3]))|Curses::A_NORMAL) {
|
60
|
+
addstr right_background_str
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@old_active = @active
|
65
|
+
noutrefresh
|
66
|
+
true
|
67
|
+
else
|
68
|
+
false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class IndicatorWindow < Curses::Window
|
2
|
+
@@list = Array.new
|
3
|
+
|
4
|
+
def IndicatorWindow.list
|
5
|
+
@@list
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :fg, :bg, :layout
|
9
|
+
attr_reader :label, :value
|
10
|
+
|
11
|
+
def label=(str)
|
12
|
+
@label = str
|
13
|
+
redraw
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
@fg = [ '444444', 'ffff00' ]
|
18
|
+
@bg = [ nil, nil ]
|
19
|
+
@label = '*'
|
20
|
+
@value = nil
|
21
|
+
@@list.push(self)
|
22
|
+
super(*args)
|
23
|
+
end
|
24
|
+
def update(new_value)
|
25
|
+
if new_value == @value
|
26
|
+
false
|
27
|
+
else
|
28
|
+
@value = new_value
|
29
|
+
redraw
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def redraw
|
34
|
+
setpos(0,0)
|
35
|
+
if @value
|
36
|
+
if @value.is_a?(Integer)
|
37
|
+
attron(color_pair(get_color_pair_id(@fg[@value], @bg[@value]))|Curses::A_NORMAL) { addstr @label }
|
38
|
+
else
|
39
|
+
attron(color_pair(get_color_pair_id(@fg[1], @bg[1]))|Curses::A_NORMAL) { addstr @label }
|
40
|
+
end
|
41
|
+
else
|
42
|
+
attron(color_pair(get_color_pair_id(@fg[0], @bg[0]))|Curses::A_NORMAL) { addstr @label }
|
43
|
+
end
|
44
|
+
noutrefresh
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class ProgressWindow < Curses::Window
|
2
|
+
attr_accessor :fg, :bg, :label, :layout
|
3
|
+
attr_reader :value, :max_value
|
4
|
+
|
5
|
+
@@list = Array.new
|
6
|
+
|
7
|
+
def ProgressWindow.list
|
8
|
+
@@list
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
@label = String.new
|
13
|
+
@fg = [ ]
|
14
|
+
@bg = [ '0000aa', '000055' ]
|
15
|
+
@value = 0
|
16
|
+
@max_value = 100
|
17
|
+
@@list.push(self)
|
18
|
+
super(*args)
|
19
|
+
end
|
20
|
+
def update(new_value, new_max_value=nil)
|
21
|
+
new_max_value ||= @max_value
|
22
|
+
if (new_value == @value) and (new_max_value == @max_value)
|
23
|
+
false
|
24
|
+
else
|
25
|
+
@value = new_value
|
26
|
+
@max_value = [new_max_value, 1].max
|
27
|
+
redraw
|
28
|
+
end
|
29
|
+
end
|
30
|
+
def redraw
|
31
|
+
str = "#{@label}#{@value.to_s.rjust(self.maxx - @label.length)}"
|
32
|
+
percent = [[(@value/@max_value.to_f), 0.to_f].max, 1].min
|
33
|
+
if (@value == 0) and (fg[3] or bg[3])
|
34
|
+
setpos(0, 0)
|
35
|
+
attron(color_pair(get_color_pair_id(@fg[3], @bg[3]))|Curses::A_NORMAL) {
|
36
|
+
addstr str
|
37
|
+
}
|
38
|
+
else
|
39
|
+
left_str = str[0,(str.length*percent).floor].to_s
|
40
|
+
if (@fg[1] or @bg[1]) and (left_str.length < str.length) and (((left_str.length+0.5)*(1/str.length.to_f)) < percent)
|
41
|
+
middle_str = str[left_str.length,1].to_s
|
42
|
+
else
|
43
|
+
middle_str = ''
|
44
|
+
end
|
45
|
+
right_str = str[(left_str.length + middle_str.length),(@label.length + (self.maxx - @label.length))].to_s
|
46
|
+
setpos(0, 0)
|
47
|
+
if left_str.length > 0
|
48
|
+
attron(color_pair(get_color_pair_id(@fg[0], @bg[0]))|Curses::A_NORMAL) {
|
49
|
+
addstr left_str
|
50
|
+
}
|
51
|
+
end
|
52
|
+
if middle_str.length > 0
|
53
|
+
attron(color_pair(get_color_pair_id(@fg[1], @bg[1]))|Curses::A_NORMAL) {
|
54
|
+
addstr middle_str
|
55
|
+
}
|
56
|
+
end
|
57
|
+
if right_str.length > 0
|
58
|
+
attron(color_pair(get_color_pair_id(@fg[2], @bg[2]))|Curses::A_NORMAL) {
|
59
|
+
addstr right_str
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
noutrefresh
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,174 @@
|
|
1
|
+
class TextWindow < Curses::Window
|
2
|
+
attr_reader :color_stack, :buffer
|
3
|
+
attr_accessor :scrollbar, :indent_word_wrap, :layout
|
4
|
+
@@list = Array.new
|
5
|
+
|
6
|
+
def TextWindow.list
|
7
|
+
@@list
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
@buffer = Array.new
|
12
|
+
@buffer_pos = 0
|
13
|
+
@max_buffer_size = 250
|
14
|
+
@indent_word_wrap = true
|
15
|
+
@@list.push(self)
|
16
|
+
super(*args)
|
17
|
+
end
|
18
|
+
def max_buffer_size
|
19
|
+
@max_buffer_size
|
20
|
+
end
|
21
|
+
def max_buffer_size=(val)
|
22
|
+
# fixme: minimum size? Curses.lines?
|
23
|
+
@max_buffer_size = val.to_i
|
24
|
+
end
|
25
|
+
def add_line(line, line_colors=Array.new)
|
26
|
+
part = [ 0, line.length ]
|
27
|
+
line_colors.each { |h| part.push(h[:start]); part.push(h[:end]) }
|
28
|
+
part.uniq!
|
29
|
+
part.sort!
|
30
|
+
for i in 0...(part.length-1)
|
31
|
+
str = line[part[i]...part[i+1]]
|
32
|
+
color_list = line_colors.find_all { |h| (h[:start] <= part[i]) and (h[:end] >= part[i+1]) }
|
33
|
+
if color_list.empty?
|
34
|
+
addstr str
|
35
|
+
else
|
36
|
+
# shortest length highlight takes precedence when multiple highlights cover the same substring
|
37
|
+
# fixme: allow multiple highlights on a substring when one specifies fg and the other specifies bg
|
38
|
+
color_list = color_list.sort_by { |h| h[:end] - h[:start] }
|
39
|
+
#log("line: #{line}, list: #{color_list}")
|
40
|
+
fg = color_list.map { |h| h[:fg] }.find { |fg| !fg.nil? }
|
41
|
+
bg = color_list.map { |h| h[:bg] }.find { |bg| !bg.nil? }
|
42
|
+
ul = color_list.map { |h| h[:ul] == "true" }.find { |ul| ul }
|
43
|
+
attron(color_pair(get_color_pair_id(fg, bg))|(ul ? Curses::A_UNDERLINE : Curses::A_NORMAL)) {
|
44
|
+
addstr str
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def add_string(string, string_colors=Array.new)
|
50
|
+
#
|
51
|
+
# word wrap string, split highlights if needed so each wrapped line is independent, update buffer, update window if needed
|
52
|
+
#
|
53
|
+
while (line = string.slice!(/^.{2,#{maxx-1}}(?=\s|$)/)) or (line = string.slice!(0,(maxx-1)))
|
54
|
+
line_colors = Array.new
|
55
|
+
for h in string_colors
|
56
|
+
line_colors.push(h.dup) if (h[:start] < line.length)
|
57
|
+
h[:end] -= line.length
|
58
|
+
h[:start] = [(h[:start] - line.length), 0].max
|
59
|
+
end
|
60
|
+
string_colors.delete_if { |h| h[:end] < 0 }
|
61
|
+
line_colors.each { |h| h[:end] = [h[:end], line.length].min }
|
62
|
+
@buffer.unshift([line,line_colors])
|
63
|
+
@buffer.pop if @buffer.length > @max_buffer_size
|
64
|
+
if @buffer_pos == 0
|
65
|
+
addstr "\n"
|
66
|
+
add_line(line, line_colors)
|
67
|
+
else
|
68
|
+
@buffer_pos += 1
|
69
|
+
scroll(1) if @buffer_pos > (@max_buffer_size - maxy)
|
70
|
+
update_scrollbar
|
71
|
+
end
|
72
|
+
break if string.chomp.empty?
|
73
|
+
if @indent_word_wrap
|
74
|
+
if string[0,1] == ' '
|
75
|
+
string = " #{string}"
|
76
|
+
string_colors.each { |h|
|
77
|
+
h[:end] += 1;
|
78
|
+
# Never let the highlighting hang off the edge -- it looks weird
|
79
|
+
h[:start] += h[:start] == 0 ? 2 : 1
|
80
|
+
}
|
81
|
+
else
|
82
|
+
string = " #{string}"
|
83
|
+
string_colors.each { |h| h[:end] += 2; h[:start] += 2 }
|
84
|
+
end
|
85
|
+
else
|
86
|
+
if string[0,1] == ' '
|
87
|
+
string = string[1,string.length]
|
88
|
+
string_colors.each { |h| h[:end] -= 1; h[:start] -= 1 }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
if @buffer_pos == 0
|
93
|
+
noutrefresh
|
94
|
+
end
|
95
|
+
end
|
96
|
+
def scroll(scroll_num)
|
97
|
+
if scroll_num < 0
|
98
|
+
if (@buffer_pos + maxy + scroll_num.abs) >= @buffer.length
|
99
|
+
scroll_num = 0 - (@buffer.length - @buffer_pos - maxy)
|
100
|
+
end
|
101
|
+
if scroll_num < 0
|
102
|
+
@buffer_pos += scroll_num.abs
|
103
|
+
scrl(scroll_num)
|
104
|
+
setpos(0,0)
|
105
|
+
pos = @buffer_pos + maxy - 1
|
106
|
+
scroll_num.abs.times {
|
107
|
+
add_line(@buffer[pos][0], @buffer[pos][1])
|
108
|
+
addstr "\n"
|
109
|
+
pos -=1
|
110
|
+
}
|
111
|
+
noutrefresh
|
112
|
+
end
|
113
|
+
update_scrollbar
|
114
|
+
elsif scroll_num > 0
|
115
|
+
if @buffer_pos == 0
|
116
|
+
nil
|
117
|
+
else
|
118
|
+
if (@buffer_pos - scroll_num) < 0
|
119
|
+
scroll_num = @buffer_pos
|
120
|
+
end
|
121
|
+
@buffer_pos -= scroll_num
|
122
|
+
scrl(scroll_num)
|
123
|
+
setpos(maxy - scroll_num, 0)
|
124
|
+
pos = @buffer_pos + scroll_num - 1
|
125
|
+
(scroll_num - 1).times {
|
126
|
+
add_line(@buffer[pos][0], @buffer[pos][1])
|
127
|
+
addstr "\n"
|
128
|
+
pos -= 1
|
129
|
+
}
|
130
|
+
add_line(@buffer[pos][0], @buffer[pos][1])
|
131
|
+
noutrefresh
|
132
|
+
end
|
133
|
+
end
|
134
|
+
update_scrollbar
|
135
|
+
end
|
136
|
+
def update_scrollbar
|
137
|
+
if @scrollbar
|
138
|
+
last_scrollbar_pos = @scrollbar_pos
|
139
|
+
@scrollbar_pos = maxy - ((@buffer_pos/[(@buffer.length - maxy), 1].max.to_f) * (maxy - 1)).round - 1
|
140
|
+
if last_scrollbar_pos
|
141
|
+
unless last_scrollbar_pos == @scrollbar_pos
|
142
|
+
@scrollbar.setpos(last_scrollbar_pos, 0)
|
143
|
+
@scrollbar.addch '|'
|
144
|
+
@scrollbar.setpos(@scrollbar_pos, 0)
|
145
|
+
@scrollbar.attron(Curses::A_REVERSE) {
|
146
|
+
@scrollbar.addch ' '
|
147
|
+
}
|
148
|
+
@scrollbar.noutrefresh
|
149
|
+
end
|
150
|
+
else
|
151
|
+
for num in 0...maxy
|
152
|
+
@scrollbar.setpos(num, 0)
|
153
|
+
if num == @scrollbar_pos
|
154
|
+
@scrollbar.attron(Curses::A_REVERSE) {
|
155
|
+
@scrollbar.addch ' '
|
156
|
+
}
|
157
|
+
else
|
158
|
+
@scrollbar.addch '|'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
@scrollbar.noutrefresh
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
def clear_scrollbar
|
166
|
+
@scrollbar_pos = nil
|
167
|
+
@scrollbar.clear
|
168
|
+
@scrollbar.noutrefresh
|
169
|
+
end
|
170
|
+
def resize_buffer
|
171
|
+
# fixme
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: profanity_fe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Lowe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-02-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: ProfanityFE is a third party frontend for Simutronics MUD games.
|
14
|
+
email: matt@io4.us
|
15
|
+
executables:
|
16
|
+
- profanity
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/profanity
|
21
|
+
- lib/profanity_fe/countdown_window.rb
|
22
|
+
- lib/profanity_fe/indicator_window.rb
|
23
|
+
- lib/profanity_fe/progress_window.rb
|
24
|
+
- lib/profanity_fe/text_window.rb
|
25
|
+
homepage: https://github.com/matt-lowe/ProfanityFE
|
26
|
+
licenses:
|
27
|
+
- GPL-2.0+
|
28
|
+
metadata: {}
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '2.0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 2.7.6
|
46
|
+
signing_key:
|
47
|
+
specification_version: 4
|
48
|
+
summary: ProfanityFE is a third party frontend for Simutronics games.
|
49
|
+
test_files: []
|