topinambour 1.0.11 → 1.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +121 -30
- data/bin/topinambour +12 -11
- data/data/app-menu.ui +8 -4
- data/data/gschemas.compiled +0 -0
- data/data/headerbar.ui +6 -64
- data/data/main-menu-popover.ui +131 -0
- data/data/prefs-dialog.ui +405 -505
- data/data/shortcuts.ui +130 -0
- data/data/topinambour.gresource +0 -0
- data/data/topinambour.gresource.xml +2 -19
- data/data/topinambour.gschema.xml +72 -0
- data/lib/actions.rb +12 -13
- data/lib/application.rb +73 -60
- data/lib/color_selector.rb +16 -14
- data/lib/font_selector.rb +8 -14
- data/lib/notebook.rb +22 -11
- data/lib/preferences.rb +159 -114
- data/lib/shortcuts.rb +6 -18
- data/lib/terminal.rb +76 -33
- data/lib/terminal_chooser.rb +247 -110
- data/lib/window.rb +48 -47
- metadata +7 -34
- data/data/#app-menu.ui# +0 -11
- data/data/application-exit-symbolic.svg +0 -32
- data/data/color-select-symbolic.svg +0 -34
- data/data/emblem-photos-symbolic.svg +0 -33
- data/data/font-select-symbolic.svg +0 -33
- data/data/pan-end-symbolic.svg +0 -31
- data/data/pan-start-symbolic.svg +0 -31
- data/data/tab-new-symbolic.svg +0 -34
- data/data/window-close-symbolic.svg +0 -28
- data/lib/css_handler.rb +0 -241
- data/lib/style_properties.rb +0 -171
data/lib/css_handler.rb
DELETED
@@ -1,241 +0,0 @@
|
|
1
|
-
# Copyright 2016 Cedric LE MOIGNE, cedlemo@gmx.com
|
2
|
-
# This file is part of Topinambour.
|
3
|
-
#
|
4
|
-
# Topinambour is free software: you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation, either version 3 of the License, or
|
7
|
-
# any later version.
|
8
|
-
#
|
9
|
-
# Topinambour is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
|
16
|
-
|
17
|
-
##
|
18
|
-
# This module contains all the methods needed to read, parse
|
19
|
-
# and modify css file.
|
20
|
-
# Sass is used to read, parse and get informations about
|
21
|
-
# css selectors or properties
|
22
|
-
# The modifying or addition of css properties are done
|
23
|
-
# with ruby strings facilities
|
24
|
-
module CssHandler
|
25
|
-
def self.css_file?(filename)
|
26
|
-
filename =~ /^.*\.css$/ ? true : false
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.scss_file?(filename)
|
30
|
-
filename =~ /^.*\.scss$/ ? true : false
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.sass_file?(filename)
|
34
|
-
filename =~ /^.*\.sass$/ ? true : false
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.to_css(filename)
|
38
|
-
content = File.open(filename, "r").read
|
39
|
-
if css_file?(filename) || scss_file?(filename)
|
40
|
-
Sass::Engine.new(content, :syntax => :scss).render
|
41
|
-
elsif sass_file?(filename)
|
42
|
-
Sass::Engine.new(content, :syntax => :sass).render
|
43
|
-
else
|
44
|
-
puts "Your theme file must be a css, scss or sass file"
|
45
|
-
exit 1
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.to_engine(filename)
|
50
|
-
content = File.open(filename, "r").read
|
51
|
-
if css_file?(filename) || scss_file?(filename)
|
52
|
-
Sass::Engine.new(content, :syntax => :scss)
|
53
|
-
elsif sass_file?(filename)
|
54
|
-
Sass::Engine.new(content, :syntax => :sass)
|
55
|
-
else
|
56
|
-
puts "Your theme file must be a css, scss or sass file"
|
57
|
-
exit 1
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.reload_engine(engine, css_content)
|
62
|
-
Sass::Engine.new(css_content, :syntax => engine.options[:syntax])
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.color_property?(value)
|
66
|
-
parsed_color = nil
|
67
|
-
begin
|
68
|
-
parsed_color = Gdk::RGBA.parse(value)
|
69
|
-
rescue
|
70
|
-
parsed_color = nil
|
71
|
-
end
|
72
|
-
parsed_color ? true : false
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.value_to_css_value(value)
|
76
|
-
if value.class == String && color_property?(value)
|
77
|
-
"#{value}"
|
78
|
-
elsif value.class == String
|
79
|
-
%("#{value}")
|
80
|
-
else
|
81
|
-
"#{value}"
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.property_to_css_instructions(name, value)
|
87
|
-
"#{name}: #{value_to_css_value(value)}"
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.props_with_name(tree, prop_name)
|
91
|
-
props = []
|
92
|
-
tree.children.each do |node|
|
93
|
-
node.each do |prop|
|
94
|
-
next if prop.class != Sass::Tree::PropNode
|
95
|
-
name = prop.name[0]
|
96
|
-
props << prop if name == prop_name
|
97
|
-
end
|
98
|
-
end
|
99
|
-
props
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.prop_position(prop)
|
103
|
-
source_range = prop.source_range
|
104
|
-
[source_range.start_pos, source_range.end_pos]
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.property_defined?(tree, name)
|
108
|
-
tree.children.each do |node|
|
109
|
-
node.each do |prop|
|
110
|
-
next if prop.class != Sass::Tree::PropNode
|
111
|
-
next if prop.class == Sass::Tree::CommentNode
|
112
|
-
return true if prop.name[0] == name
|
113
|
-
end
|
114
|
-
end
|
115
|
-
false
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.modify_in_ranges(line, line_number, start_range, end_range, value)
|
119
|
-
if line_number < start_range.line || line_number > end_range.line
|
120
|
-
line
|
121
|
-
else
|
122
|
-
tmp = ""
|
123
|
-
if line_number == start_range.line
|
124
|
-
tmp += line[0..(start_range.offset - 2)] + value_to_css_value(value)
|
125
|
-
end
|
126
|
-
tmp += line[(end_range.offset - 1)..-1] if line_number == end_range.line
|
127
|
-
tmp
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def self.modify_property_value(file_content, property, value)
|
132
|
-
start_range = property.value_source_range.start_pos
|
133
|
-
end_range = property.value_source_range.end_pos
|
134
|
-
tmp = ""
|
135
|
-
line_number = 1
|
136
|
-
file_content.each_line do |line|
|
137
|
-
tmp += modify_in_ranges(line, line_number, start_range, end_range, value)
|
138
|
-
line_number += 1
|
139
|
-
end
|
140
|
-
tmp
|
141
|
-
end
|
142
|
-
|
143
|
-
def self.modify_each_property_values(css_content, engine, prop)
|
144
|
-
engine = engine
|
145
|
-
tree = engine.to_tree
|
146
|
-
props = props_with_name(tree, prop[:name])
|
147
|
-
new_css = css_content
|
148
|
-
(0..(props.size - 1)).each do |i|
|
149
|
-
new_css = modify_property_value(new_css, props[i], prop[:value])
|
150
|
-
engine = reload_engine(engine, new_css)
|
151
|
-
tree = engine.to_tree
|
152
|
-
props = props_with_name(tree, prop[:name])
|
153
|
-
end
|
154
|
-
new_css
|
155
|
-
end
|
156
|
-
|
157
|
-
def self.append_new_property_after_line(line, prop, indent)
|
158
|
-
tmp = line.gsub(/\;[^\;]*$/, ";\n")
|
159
|
-
new_prop = property_to_css_instructions(prop[:name], prop[:value])
|
160
|
-
tmp += (indent + new_prop + (Regexp.last_match(0) || ";\n"))
|
161
|
-
tmp
|
162
|
-
end
|
163
|
-
|
164
|
-
def self.last_child_which_is_not_comment(selector)
|
165
|
-
son = nil
|
166
|
-
selector.children.each do |child|
|
167
|
-
son = child unless child.class == Sass::Tree::CommentNode
|
168
|
-
end
|
169
|
-
son
|
170
|
-
end
|
171
|
-
|
172
|
-
def self.compute_position_to_append(selector, element)
|
173
|
-
indent = last_line = nil
|
174
|
-
if element
|
175
|
-
indent = " " * (element.name_source_range.start_pos.offset - 1) || ""
|
176
|
-
last_line = element.value_source_range.end_pos.line
|
177
|
-
else # If we don 't have any property in selector, use sel offset
|
178
|
-
indent = " " * (selector.source_range.start_pos.offset - 1) || ""
|
179
|
-
last_line = selector.source_range.start_pos.line
|
180
|
-
end
|
181
|
-
[indent, last_line]
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.append_property_in_universal_selector(css_content, engine, prop)
|
185
|
-
last_selector = selectors_with_name(engine.to_tree, "*").last
|
186
|
-
last_prop = last_child_which_is_not_comment(last_selector)
|
187
|
-
indent, last_line = compute_position_to_append(last_selector, last_prop)
|
188
|
-
tmp = ""
|
189
|
-
line_number = 1
|
190
|
-
css_content.each_line do |line|
|
191
|
-
if last_line == line_number
|
192
|
-
tmp += append_new_property_after_line(line, prop, indent)
|
193
|
-
else
|
194
|
-
tmp += line
|
195
|
-
end
|
196
|
-
line_number += 1
|
197
|
-
end
|
198
|
-
tmp
|
199
|
-
end
|
200
|
-
|
201
|
-
def self.rule_node_name_is?(node, name)
|
202
|
-
if node.rule.include?(name)
|
203
|
-
true
|
204
|
-
elsif node.parsed_rules.to_s == name
|
205
|
-
true
|
206
|
-
elsif node.resolved_rules == name
|
207
|
-
true
|
208
|
-
else
|
209
|
-
false
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def self.selectors_with_name(tree, sel_name)
|
214
|
-
selectors = []
|
215
|
-
tree.children.each do |node|
|
216
|
-
next unless node.class == Sass::Tree::RuleNode
|
217
|
-
selectors << node if rule_node_name_is?(node, sel_name)
|
218
|
-
end
|
219
|
-
selectors
|
220
|
-
end
|
221
|
-
|
222
|
-
def self.update_css_with_new_property(content, engine, prop)
|
223
|
-
if property_defined?(engine.to_tree, prop[:name])
|
224
|
-
modify_each_property_values(content, engine, prop)
|
225
|
-
else
|
226
|
-
append_property_in_universal_selector(content, engine, prop)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def self.update_css(filename, properties)
|
231
|
-
engine = to_engine(filename)
|
232
|
-
new_css = nil
|
233
|
-
content = File.open(filename, "r").read
|
234
|
-
properties.each do |prop|
|
235
|
-
new_css = update_css_with_new_property(content, engine, prop)
|
236
|
-
engine = reload_engine(engine, new_css)
|
237
|
-
content = new_css
|
238
|
-
end
|
239
|
-
new_css
|
240
|
-
end
|
241
|
-
end
|
data/lib/style_properties.rb
DELETED
@@ -1,171 +0,0 @@
|
|
1
|
-
# Copyright 2016 Cedric LE MOIGNE, cedlemo@gmx.com
|
2
|
-
# This file is part of Topinambour.
|
3
|
-
#
|
4
|
-
# Topinambour is free software: you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation, either version 3 of the License, or
|
7
|
-
# any later version.
|
8
|
-
#
|
9
|
-
# Topinambour is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
|
16
|
-
|
17
|
-
module TopinambourStyleProperties
|
18
|
-
def generate_string_rw_property(name, args)
|
19
|
-
GLib::Param::String.new(name.downcase,
|
20
|
-
name.capitalize,
|
21
|
-
name.upcase,
|
22
|
-
args,
|
23
|
-
GLib::Param::READABLE |
|
24
|
-
GLib::Param::WRITABLE)
|
25
|
-
end
|
26
|
-
|
27
|
-
def generate_boolean_rw_property(name, args)
|
28
|
-
GLib::Param::Boolean.new(name.downcase,
|
29
|
-
name.capitalize,
|
30
|
-
name.upcase,
|
31
|
-
args,
|
32
|
-
GLib::Param::READABLE |
|
33
|
-
GLib::Param::WRITABLE)
|
34
|
-
end
|
35
|
-
|
36
|
-
def generate_int_rw_property(name, args)
|
37
|
-
GLib::Param::Int.new(name.downcase,
|
38
|
-
name.capitalize,
|
39
|
-
name.upcase,
|
40
|
-
*args,
|
41
|
-
GLib::Param::READABLE |
|
42
|
-
GLib::Param::WRITABLE)
|
43
|
-
end
|
44
|
-
|
45
|
-
def generate_enum_rw_property(name, args)
|
46
|
-
GLib::Param::Enum.new(name.downcase,
|
47
|
-
name.capitalize,
|
48
|
-
name.upcase,
|
49
|
-
*args,
|
50
|
-
GLib::Param::READABLE |
|
51
|
-
GLib::Param::WRITABLE)
|
52
|
-
end
|
53
|
-
|
54
|
-
def generate_boxed_rw_property(name, args)
|
55
|
-
GLib::Param::Boxed.new(name.downcase,
|
56
|
-
name.capitalize,
|
57
|
-
name.upcase,
|
58
|
-
args,
|
59
|
-
GLib::Param::READABLE |
|
60
|
-
GLib::Param::WRITABLE)
|
61
|
-
end
|
62
|
-
|
63
|
-
def generate_rw_property(type, name, args)
|
64
|
-
type = type.to_s.downcase
|
65
|
-
method_name = "generate_#{type}_rw_property"
|
66
|
-
return false unless methods.include?(method_name.to_sym)
|
67
|
-
method(method_name.to_sym).call(name, args)
|
68
|
-
end
|
69
|
-
|
70
|
-
def install_style(type, name, args)
|
71
|
-
property = generate_rw_property(type, name, args)
|
72
|
-
install_style_property(property) if property
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
TERMINAL_COLOR_NAMES = [:foreground, :background, :black, :red, :green, :yellow,
|
77
|
-
:blue, :magenta, :cyan, :white, :brightblack,
|
78
|
-
:brightred, :brightgreen, :brightyellow, :brightblue,
|
79
|
-
:brightmagenta, :brightcyan, :brightwhite
|
80
|
-
]
|
81
|
-
DEFAULT_TERMINAL_COLORS = %w(#aeafad #323232 #000000 #b9214f #A6E22E #ff9800
|
82
|
-
#3399ff #8e33ff #06a2dc #B0B0B0 #5D5D5D #ff5c8d
|
83
|
-
#CDEE69 #ffff00 #9CD9F0 #FBB1F9 #77DFD8 #F7F7F7)
|
84
|
-
DEFAULT_TERMINAL_FONT = "Monospace 11"
|
85
|
-
|
86
|
-
class TopinambourTerminal < Vte::Terminal
|
87
|
-
extend TopinambourStyleProperties
|
88
|
-
type_register
|
89
|
-
TERMINAL_COLOR_NAMES.each_with_index do |c|
|
90
|
-
name = c.to_s
|
91
|
-
install_style("boxed",
|
92
|
-
name,
|
93
|
-
GLib::Type["GdkRGBA"])
|
94
|
-
end
|
95
|
-
install_style("boxed", "font",
|
96
|
-
GLib::Type["PangoFontDescription"])
|
97
|
-
install_style("boolean", "audible-bell", false)
|
98
|
-
install_style("boolean", "allow-bold", true)
|
99
|
-
install_style("boolean", "scroll-on-output", true)
|
100
|
-
install_style("boolean", "scroll-on-keystroke", true)
|
101
|
-
install_style("boolean", "rewrap-on-resize", true)
|
102
|
-
install_style("boolean", "mouse-autohide", true)
|
103
|
-
install_style("enum", "cursor-shape", [GLib::Type["VteCursorShape"],
|
104
|
-
Vte::CursorShape::BLOCK])
|
105
|
-
install_style("enum", "cursor-blink-mode", [GLib::Type["VteCursorBlinkMode"],
|
106
|
-
Vte::CursorBlinkMode::SYSTEM])
|
107
|
-
install_style("enum", "backspace-binding", [GLib::Type["VteEraseBinding"],
|
108
|
-
Vte::EraseBinding::AUTO])
|
109
|
-
install_style("enum", "delete-binding", [GLib::Type["VteEraseBinding"],
|
110
|
-
Vte::EraseBinding::AUTO])
|
111
|
-
def load_properties
|
112
|
-
%w(audible_bell allow_bold scroll_on_output scroll_on_keystroke
|
113
|
-
rewrap_on_resize mouse_autohide).each do |prop|
|
114
|
-
send("#{prop}=", style_get_property(prop.gsub(/_/,"-")))
|
115
|
-
end
|
116
|
-
%w(cursor_shape cursor_blink_mode backspace_binding delete_binding).each do |prop|
|
117
|
-
send("#{prop}=", style_get_property(prop.gsub(/_/,"-")))
|
118
|
-
end
|
119
|
-
@colors = css_colors
|
120
|
-
apply_colors
|
121
|
-
set_font(css_font)
|
122
|
-
end
|
123
|
-
|
124
|
-
def parse_css_color(color_name)
|
125
|
-
color_index = TERMINAL_COLOR_NAMES.index(color_name.to_sym)
|
126
|
-
color_value = DEFAULT_TERMINAL_COLORS[color_index]
|
127
|
-
default_color = Gdk::RGBA.parse(color_value)
|
128
|
-
color_from_css = style_get_property(color_name)
|
129
|
-
color = color_from_css ? color_from_css : default_color
|
130
|
-
color
|
131
|
-
end
|
132
|
-
|
133
|
-
def css_colors
|
134
|
-
colors = []
|
135
|
-
background = parse_css_color(TERMINAL_COLOR_NAMES[0].to_s)
|
136
|
-
foreground = parse_css_color(TERMINAL_COLOR_NAMES[1].to_s)
|
137
|
-
TERMINAL_COLOR_NAMES[2..-1].each do |c|
|
138
|
-
colors << parse_css_color(c.to_s)
|
139
|
-
end
|
140
|
-
[background, foreground] + colors
|
141
|
-
end
|
142
|
-
|
143
|
-
def css_font
|
144
|
-
font = style_get_property("font")
|
145
|
-
font = Pango::FontDescription.new(DEFAULT_TERMINAL_FONT) unless font
|
146
|
-
font
|
147
|
-
end
|
148
|
-
|
149
|
-
def apply_colors
|
150
|
-
set_colors(@colors[0], @colors[1], @colors[2..-1])
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
class TopinambourWindow < Gtk::ApplicationWindow
|
155
|
-
extend TopinambourStyleProperties
|
156
|
-
type_register
|
157
|
-
install_style("string", "shell", "/usr/bin/fish")
|
158
|
-
install_style("int", "width", [-1, 2000, 1000])
|
159
|
-
install_style("int", "height", [-1, 2000, 500])
|
160
|
-
|
161
|
-
def load_properties
|
162
|
-
_w, _h = self.size
|
163
|
-
w = style_get_property("width")
|
164
|
-
h = style_get_property("height")
|
165
|
-
w = _w if w == -1
|
166
|
-
h = _h if h == -1
|
167
|
-
self.resize(w, h)
|
168
|
-
self.set_default_size(w, h)
|
169
|
-
@shell = style_get_property("shell")
|
170
|
-
end
|
171
|
-
end
|