topinambour 2.0.4 → 2.0.6
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 +4 -4
- data/bin/topinambour +22 -24
- data/data/gschemas.compiled +0 -0
- data/data/prefs-dialog.ui +6 -6
- data/data/topinambour.css +7 -46
- data/data/topinambour.gresource +0 -0
- data/data/topinambour.gresource.xml +0 -1
- data/data/topinambour.gschema.xml +4 -4
- data/lib/about.rb +46 -0
- data/lib/actions.rb +2 -0
- data/lib/application.rb +80 -83
- data/lib/color_selector.rb +148 -22
- data/lib/font_selector.rb +43 -21
- data/lib/preferences.rb +6 -2
- data/lib/profile.rb +62 -0
- data/lib/shortcuts.rb +2 -5
- data/lib/terminal.rb +87 -70
- data/lib/terminal_regex.rb +9 -0
- data/lib/version.rb +25 -0
- data/lib/window.rb +67 -95
- metadata +28 -8
- data/data/window.ui +0 -58
data/lib/color_selector.rb
CHANGED
@@ -14,26 +14,29 @@
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
15
15
|
# along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
|
-
TERMINAL_COLOR_NAMES = [:
|
18
|
-
:blue, :magenta, :cyan, :white
|
19
|
-
:brightred, :brightgreen, :brightyellow, :brightblue,
|
20
|
-
:brightmagenta, :brightcyan, :brightwhite
|
21
|
-
]
|
17
|
+
TERMINAL_COLOR_NAMES = [:black, :red, :green, :yellow,
|
18
|
+
:blue, :magenta, :cyan, :white]
|
22
19
|
|
23
|
-
class TopinambourColorSelector < Gtk::
|
20
|
+
class TopinambourColorSelector < Gtk::Grid
|
24
21
|
attr_reader :colors
|
25
22
|
def initialize(window)
|
26
23
|
@window = window
|
27
|
-
super(
|
24
|
+
super()
|
28
25
|
|
29
26
|
reset_button = generate_reset_button
|
30
|
-
|
27
|
+
attach(reset_button, 0, 0, 1, 1)
|
31
28
|
|
32
29
|
initialize_default_colors
|
33
30
|
add_color_selectors
|
34
31
|
|
35
32
|
save_button = generate_save_button
|
36
|
-
|
33
|
+
attach(save_button, 0, 1, 1, 1)
|
34
|
+
|
35
|
+
import_button = generate_import_button
|
36
|
+
attach(import_button, 10, 0, 1, 1)
|
37
|
+
|
38
|
+
export_button = generate_export_button
|
39
|
+
attach(export_button, 10, 1, 1, 1)
|
37
40
|
|
38
41
|
show_all
|
39
42
|
set_halign(:center)
|
@@ -43,6 +46,83 @@ class TopinambourColorSelector < Gtk::Box
|
|
43
46
|
|
44
47
|
private
|
45
48
|
|
49
|
+
def generate_import_export_button(name, save_in=nil)
|
50
|
+
button = ColorSchemeSelector.new(name, @window, save_in)
|
51
|
+
button.signal_connect "clicked" do |widget|
|
52
|
+
filename = widget.run_chooser_dialog
|
53
|
+
if filename then
|
54
|
+
yield filename if block_given?
|
55
|
+
end
|
56
|
+
widget.chooser_destroy
|
57
|
+
end
|
58
|
+
button
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_import_button
|
62
|
+
generate_import_export_button("Import") do |filename|
|
63
|
+
file = File.read(filename)
|
64
|
+
|
65
|
+
foreground = file[/\*\.?foreground:\s*(.*)/, 1]
|
66
|
+
child = get_child_at(1, 0)
|
67
|
+
child.rgba = Gdk::RGBA.parse(foreground) unless foreground.nil?
|
68
|
+
@colors[0] = child.rgba
|
69
|
+
|
70
|
+
background = file[/\*\.?background:\s*(.*)/, 1]
|
71
|
+
child = get_child_at(1, 1)
|
72
|
+
child.rgba = Gdk::RGBA.parse(background) unless background.nil?
|
73
|
+
@colors[1] = child.rgba
|
74
|
+
#
|
75
|
+
# Normal colors top row
|
76
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
77
|
+
color = file[/\*\.?color#{i}:\s*(.*)/, 1]
|
78
|
+
child = get_child_at(2 + i, 0)
|
79
|
+
child.rgba = Gdk::RGBA.parse(color) unless color.nil?
|
80
|
+
@colors[2 + i] = child.rgba
|
81
|
+
end
|
82
|
+
|
83
|
+
# Bright colors bottom row
|
84
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
85
|
+
color = file[/\*\.?color#{i + 8}:\s*(.*)/, 1]
|
86
|
+
child = get_child_at(2 + i, 1)
|
87
|
+
child.rgba = Gdk::RGBA.parse(color) unless color.nil?
|
88
|
+
@colors[10 + i] = child.rgba
|
89
|
+
end
|
90
|
+
apply_new_colors
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def double_to_hex(d)
|
95
|
+
(d * 255).to_i.to_s(16)
|
96
|
+
end
|
97
|
+
|
98
|
+
def rgba_to_hex_string(rgba)
|
99
|
+
"##{double_to_hex(rgba.red)}#{double_to_hex(rgba.green)}#{double_to_hex(rgba.blue)}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def generate_export_button
|
103
|
+
generate_import_export_button("Export", "untitled") do |filename|
|
104
|
+
File.open(filename, 'a') do |file|
|
105
|
+
child = get_child_at(1, 0)
|
106
|
+
file.puts "*.foreground: #{rgba_to_hex_string(child.rgba)}"
|
107
|
+
|
108
|
+
child = get_child_at(1, 1)
|
109
|
+
file.puts "*.background: #{rgba_to_hex_string(child.rgba)}"
|
110
|
+
|
111
|
+
# Normal colors top row
|
112
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
113
|
+
child = get_child_at(2 + i, 0)
|
114
|
+
file.puts "*.color#{i}: #{rgba_to_hex_string(child.rgba)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# Bright colors bottom row
|
118
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
119
|
+
child = get_child_at(2 + i, 1)
|
120
|
+
file.puts "*.color#{i + 8}: #{rgba_to_hex_string(child.rgba)}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
46
126
|
def initialize_default_colors
|
47
127
|
colors_strings = @window.application.settings["colorscheme"]
|
48
128
|
@default_colors = colors_strings.map {|c| Gdk::RGBA.parse(c) }
|
@@ -53,8 +133,19 @@ class TopinambourColorSelector < Gtk::Box
|
|
53
133
|
button = Gtk::Button.new(:label => "Reset")
|
54
134
|
button.signal_connect "clicked" do
|
55
135
|
initialize_default_colors
|
56
|
-
|
57
|
-
|
136
|
+
# foreground
|
137
|
+
get_child_at(1, 0).rgba = @default_colors[0]
|
138
|
+
# background
|
139
|
+
get_child_at(1, 1).rgba = @default_colors[1]
|
140
|
+
|
141
|
+
# Normal colors top row
|
142
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
143
|
+
get_child_at(2 + i, 0).rgba = @default_colors[2 + i]
|
144
|
+
end
|
145
|
+
|
146
|
+
# Bright colors bottom row
|
147
|
+
TERMINAL_COLOR_NAMES.each_with_index do |_, i|
|
148
|
+
get_child_at(2 + i, 1).rgba = @default_colors[10 + i]
|
58
149
|
end
|
59
150
|
apply_new_colors
|
60
151
|
end
|
@@ -64,7 +155,7 @@ class TopinambourColorSelector < Gtk::Box
|
|
64
155
|
def apply_new_properties
|
65
156
|
colors_strings = @colors.map { |c| c.to_s }
|
66
157
|
@window.application.settings["colorscheme"] = colors_strings
|
67
|
-
@window.terminal.
|
158
|
+
@window.terminal.load_colors
|
68
159
|
@window.terminal.load_settings
|
69
160
|
end
|
70
161
|
|
@@ -72,22 +163,32 @@ class TopinambourColorSelector < Gtk::Box
|
|
72
163
|
button = Gtk::Button.new(:label => "Save")
|
73
164
|
button.signal_connect "clicked" do |widget|
|
74
165
|
apply_new_properties
|
75
|
-
|
166
|
+
@window.exit_overlay_mode
|
76
167
|
end
|
77
168
|
button
|
78
169
|
end
|
79
170
|
|
171
|
+
def add_color_selector(name, i, position=nil)
|
172
|
+
color_sel = Gtk::ColorButton.new(@default_colors[i])
|
173
|
+
color_sel.title = name.to_s
|
174
|
+
color_sel.name = "topinambour-button-#{name}"
|
175
|
+
color_sel.tooltip_text = name.to_s
|
176
|
+
color_sel.signal_connect "color-set" do
|
177
|
+
@colors[i] = color_sel.rgba
|
178
|
+
apply_new_colors
|
179
|
+
end
|
180
|
+
attach(color_sel, position[0], position[1], 1, 1)
|
181
|
+
end
|
182
|
+
|
80
183
|
def add_color_selectors
|
184
|
+
add_color_selector("foreground", 0, [1, 0])
|
185
|
+
add_color_selector("background", 1, [1, 1])
|
81
186
|
TERMINAL_COLOR_NAMES.each_with_index do |name, i|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
@colors[i] = color_sel.rgba
|
88
|
-
apply_new_colors
|
89
|
-
end
|
90
|
-
pack_start(color_sel, :expand => false, :fill => false, :padding => 0)
|
187
|
+
add_color_selector(name, i + 2, [2 + i, 0])
|
188
|
+
end
|
189
|
+
|
190
|
+
TERMINAL_COLOR_NAMES.each_with_index do |name, i|
|
191
|
+
add_color_selector("bright#{name}", i + 10, [2 + i, 1])
|
91
192
|
end
|
92
193
|
end
|
93
194
|
|
@@ -95,3 +196,28 @@ class TopinambourColorSelector < Gtk::Box
|
|
95
196
|
@window.terminal.colors = @colors
|
96
197
|
end
|
97
198
|
end
|
199
|
+
|
200
|
+
class ColorSchemeSelector < Gtk::Button
|
201
|
+
def initialize(label, parent, save_in)
|
202
|
+
@parent = parent
|
203
|
+
@save_in = save_in
|
204
|
+
@action = @save_in.nil? ? :open : :save
|
205
|
+
super(:label => label)
|
206
|
+
end
|
207
|
+
|
208
|
+
def run_chooser_dialog
|
209
|
+
@dialog = Gtk::FileChooserDialog.new(:title => label,
|
210
|
+
:parent => @parent,
|
211
|
+
:action => @action,
|
212
|
+
:buttons => [[label, :ok],
|
213
|
+
["Cancel", :cancel]])
|
214
|
+
@dialog.current_name = @save_in unless @save_in.nil?
|
215
|
+
if @dialog.run == :ok then
|
216
|
+
@dialog.filename
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def chooser_destroy
|
221
|
+
@dialog.destroy
|
222
|
+
end
|
223
|
+
end
|
data/lib/font_selector.rb
CHANGED
@@ -13,38 +13,60 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU General Public License
|
15
15
|
# along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
## Widget used to choose the font at runtime in a Gtk::Layout
|
18
|
+
#
|
16
19
|
class TopinambourFontSelector < Gtk::Box
|
17
20
|
attr_reader :font
|
18
21
|
def initialize(window)
|
22
|
+
super(:horizontal, 0)
|
23
|
+
configure
|
19
24
|
@window = window
|
20
25
|
@font = @window.terminal.font
|
21
|
-
|
26
|
+
add_buttons
|
27
|
+
show_all
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def configure
|
33
|
+
set_name('topinambour-font-selector')
|
34
|
+
set_halign(:center)
|
35
|
+
set_valign(:end)
|
36
|
+
end
|
22
37
|
|
23
|
-
|
24
|
-
reset_button.
|
38
|
+
def generate_reset_button
|
39
|
+
@reset_button = Gtk::Button.new(label: 'Reset')
|
40
|
+
@reset_button.signal_connect 'clicked' do
|
25
41
|
@window.terminal.font = @font.to_s
|
26
42
|
end
|
27
|
-
|
43
|
+
end
|
28
44
|
|
29
|
-
|
30
|
-
font_button
|
31
|
-
font_button.
|
32
|
-
font_button.
|
33
|
-
font_button.
|
34
|
-
font_button.
|
35
|
-
font_button.
|
36
|
-
|
45
|
+
def generate_font_button
|
46
|
+
@font_button = Gtk::FontButton.new
|
47
|
+
@font_button.font = @font.to_s
|
48
|
+
@font_button.show_style = true
|
49
|
+
@font_button.show_size = true
|
50
|
+
@font_button.use_font = true
|
51
|
+
@font_button.use_size = false
|
52
|
+
@font_button.signal_connect 'font-set' do
|
53
|
+
@window.terminal.font = @font_button.font_name
|
37
54
|
end
|
38
|
-
|
55
|
+
end
|
39
56
|
|
40
|
-
|
41
|
-
save_button.
|
42
|
-
|
57
|
+
def generate_save_button
|
58
|
+
@save_button = Gtk::Button.new(label: 'Quit')
|
59
|
+
@save_button.signal_connect 'clicked' do
|
60
|
+
@window.overlay.exit_overlay_mode
|
43
61
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_buttons
|
65
|
+
generate_reset_button
|
66
|
+
pack_start(@reset_button, expand: false, fill: false, padding: 0)
|
67
|
+
generate_font_button
|
68
|
+
pack_start(@font_button, expand: false, fill: false, padding: 0)
|
69
|
+
generate_save_button
|
70
|
+
pack_start(@save_button, expand: false, fill: false, padding: 0)
|
49
71
|
end
|
50
72
|
end
|
data/lib/preferences.rb
CHANGED
@@ -37,13 +37,17 @@ class TopinambourPreferences < Gtk::Window
|
|
37
37
|
def on_width_spin_value_changed_cb(spin)
|
38
38
|
parent = spin.toplevel.transient_for
|
39
39
|
height = parent.application.settings["height"]
|
40
|
-
parent.
|
40
|
+
terminal = parent.terminal
|
41
|
+
terminal.set_size(spin.value, height)
|
42
|
+
parent.resize(*terminal.size)
|
41
43
|
end
|
42
44
|
|
43
45
|
def on_height_spin_value_changed_cb(spin)
|
44
46
|
parent = spin.toplevel.transient_for
|
45
47
|
width = parent.application.settings["width"]
|
46
|
-
parent.
|
48
|
+
terminal = parent.terminal
|
49
|
+
terminal.set_size(width, spin.value)
|
50
|
+
parent.resize(*terminal.size)
|
47
51
|
end
|
48
52
|
|
49
53
|
def on_shell_entry_activate_cb(entry)
|
data/lib/profile.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright 2018 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
|
+
# Session or Profile class
|
19
|
+
# Allow to switch easily between different configurations.
|
20
|
+
class Profile
|
21
|
+
attr_accessor :name,
|
22
|
+
:terminal_options,
|
23
|
+
:vte_options
|
24
|
+
def initialize(terminal_options, vte_options)
|
25
|
+
@terminal_options = terminal_options
|
26
|
+
@vte_options = vte_options
|
27
|
+
end
|
28
|
+
|
29
|
+
## TODO : use json
|
30
|
+
def save
|
31
|
+
# File.open("#{DATA_HOME_DIR}/#{@name}", 'w+') do |f|
|
32
|
+
# Marshal.dump(self, f)
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
|
36
|
+
def load
|
37
|
+
# File.open("#{DATA_HOME_DIR}/#{@name}") do |f|
|
38
|
+
# session = Marshal.load(f)
|
39
|
+
# @terminal_options = session.terminal_options
|
40
|
+
# @vte_options = session.vte_options
|
41
|
+
# end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
TerminalOptions = Struct.new(:colorscheme,
|
46
|
+
:default_scheme,
|
47
|
+
:font,
|
48
|
+
:width,
|
49
|
+
:height,
|
50
|
+
:custom_css,
|
51
|
+
:css_file)
|
52
|
+
|
53
|
+
VteOptions = Struct.new(:allow_bold,
|
54
|
+
:audible_bell,
|
55
|
+
:scroll_on_output,
|
56
|
+
:scroll_on_keystroke,
|
57
|
+
:rewrap_on_resize,
|
58
|
+
:mouse_autohide,
|
59
|
+
:cursor_shape,
|
60
|
+
:cursor_blink_mode,
|
61
|
+
:backspace_binding,
|
62
|
+
:delete_binding)
|
data/lib/shortcuts.rb
CHANGED
@@ -24,8 +24,8 @@ module TopinambourShortcuts
|
|
24
24
|
def self.handle_simple(event, window)
|
25
25
|
case event.keyval
|
26
26
|
when Gdk::Keyval::KEY_Escape # escape from overlay mode
|
27
|
-
if window.in_overlay_mode?
|
28
|
-
window.exit_overlay_mode
|
27
|
+
if window.overlay.in_overlay_mode?
|
28
|
+
window.overlay.exit_overlay_mode
|
29
29
|
window.terminal.grab_focus
|
30
30
|
true
|
31
31
|
end
|
@@ -34,9 +34,6 @@ module TopinambourShortcuts
|
|
34
34
|
|
35
35
|
def self.handle_ctrl_shift(event, window)
|
36
36
|
case event.keyval
|
37
|
-
when Gdk::Keyval::KEY_W # close the current tab
|
38
|
-
window.close_current_tab
|
39
|
-
true
|
40
37
|
when Gdk::Keyval::KEY_Q # Quit
|
41
38
|
window.quit_gracefully
|
42
39
|
true
|
data/lib/terminal.rb
CHANGED
@@ -19,13 +19,13 @@
|
|
19
19
|
|
20
20
|
class TopinambourTermBox < Gtk::Box
|
21
21
|
attr_reader :term
|
22
|
-
def initialize(command_string, working_dir = nil)
|
22
|
+
def initialize(command_string, working_dir = nil, parent)
|
23
23
|
super(:horizontal, 0)
|
24
|
-
set_name(
|
25
|
-
@term = TopinambourTerminal.new(command_string, working_dir)
|
24
|
+
set_name('topinambour-term-box')
|
25
|
+
@term = TopinambourTerminal.new(command_string, parent, working_dir)
|
26
26
|
@scrollbar = Gtk::Scrollbar.new(:vertical, @term.vadjustment)
|
27
|
-
@scrollbar.name =
|
28
|
-
pack_start(@term, :
|
27
|
+
@scrollbar.name = 'topinambour-scrollbar'
|
28
|
+
pack_start(@term, expand: true, fill: true, padding: 0)
|
29
29
|
pack_start(@scrollbar)
|
30
30
|
show_all
|
31
31
|
end
|
@@ -34,22 +34,26 @@ end
|
|
34
34
|
##
|
35
35
|
# The default vte terminal customized
|
36
36
|
class TopinambourTerminal < Vte::Terminal
|
37
|
-
attr_reader :pid, :menu, :
|
37
|
+
attr_reader :pid, :menu, :last_match
|
38
|
+
REGEXES = [:REGEX_URL_AS_IS, :REGEX_URL_FILE, :REGEX_URL_HTTP,
|
39
|
+
:REGEX_URL_VOIP, :REGEX_EMAIL, :REGEX_NEWS_MAN, :CSS_COLORS]
|
38
40
|
|
39
41
|
##
|
40
42
|
# Create a new TopinambourTerminal instance that runs command_string
|
41
|
-
def initialize(command_string, working_dir = nil)
|
43
|
+
def initialize(command_string, toplevel, working_dir = nil)
|
42
44
|
super()
|
43
|
-
|
45
|
+
@toplevel = toplevel
|
46
|
+
@settings = toplevel.application.settings
|
47
|
+
set_name('topinambour-terminal')
|
44
48
|
command_array = parse_command(command_string)
|
45
49
|
rescued_spawn(command_array, working_dir)
|
46
50
|
|
47
|
-
signal_connect
|
48
|
-
toplevel.application.quit
|
49
|
-
end
|
51
|
+
signal_connect('child-exited') {@toplevel.quit_gracefully}
|
50
52
|
|
53
|
+
load_settings
|
54
|
+
add_matches
|
51
55
|
add_popup_menu
|
52
|
-
|
56
|
+
handle_mouse_clic
|
53
57
|
end
|
54
58
|
|
55
59
|
def pid_dir
|
@@ -60,20 +64,39 @@ class TopinambourTerminal < Vte::Terminal
|
|
60
64
|
@custom_title.class == String ? @custom_title : window_title.to_s
|
61
65
|
end
|
62
66
|
|
67
|
+
def size
|
68
|
+
col = column_count
|
69
|
+
char_w = char_width
|
70
|
+
row = row_count
|
71
|
+
char_h = char_height
|
72
|
+
[col * char_w, row * char_h]
|
73
|
+
end
|
74
|
+
|
75
|
+
######################################
|
76
|
+
# Methods used to load Gio::Settings #
|
77
|
+
######################################
|
78
|
+
|
63
79
|
def load_settings
|
64
|
-
|
80
|
+
load_colors
|
65
81
|
set_colors(@colors[0], @colors[1], @colors[2..-1])
|
66
|
-
set_font(
|
82
|
+
set_font(load_font)
|
83
|
+
set_size(*load_size_settings)
|
84
|
+
end
|
85
|
+
|
86
|
+
def load_size_settings
|
87
|
+
h = @settings['height']
|
88
|
+
w = @settings['width']
|
89
|
+
[w, h]
|
67
90
|
end
|
68
91
|
|
69
|
-
def
|
70
|
-
colors_strings =
|
92
|
+
def load_colors
|
93
|
+
colors_strings = @settings['colorscheme']
|
71
94
|
@colors = colors_strings.map { |c| Gdk::RGBA.parse(c) }
|
72
95
|
@colors
|
73
96
|
end
|
74
97
|
|
75
|
-
def
|
76
|
-
font_str =
|
98
|
+
def load_font
|
99
|
+
font_str = @settings['font']
|
77
100
|
@font = Pango::FontDescription.new(font_str)
|
78
101
|
end
|
79
102
|
|
@@ -82,7 +105,7 @@ class TopinambourTerminal < Vte::Terminal
|
|
82
105
|
end
|
83
106
|
|
84
107
|
def font=(font_str)
|
85
|
-
|
108
|
+
@settings['font'] = font_str
|
86
109
|
font = Pango::FontDescription.new(font_str)
|
87
110
|
set_font(font)
|
88
111
|
@font = font
|
@@ -90,6 +113,10 @@ class TopinambourTerminal < Vte::Terminal
|
|
90
113
|
|
91
114
|
private
|
92
115
|
|
116
|
+
##############################
|
117
|
+
# Terminal command functions #
|
118
|
+
##############################
|
119
|
+
|
93
120
|
def parse_command(command_string)
|
94
121
|
GLib::Shell.parse(command_string)
|
95
122
|
rescue GLib::ShellError => e
|
@@ -99,26 +126,45 @@ class TopinambourTerminal < Vte::Terminal
|
|
99
126
|
end
|
100
127
|
|
101
128
|
def rescued_spawn(command_array, working_dir)
|
102
|
-
@pid = spawn(:
|
103
|
-
:
|
104
|
-
:
|
129
|
+
@pid = spawn(argv: command_array,
|
130
|
+
working_directory: working_dir,
|
131
|
+
spawn_flags: GLib::Spawn::SEARCH_PATH)
|
105
132
|
rescue => e
|
106
133
|
STDERR.puts e.message
|
107
134
|
end
|
108
135
|
|
136
|
+
###########################
|
137
|
+
# Regexes related methods #
|
138
|
+
###########################
|
139
|
+
|
140
|
+
def add_matches
|
141
|
+
REGEXES.each do |name|
|
142
|
+
regex_name = TopinambourRegex.const_get(name)
|
143
|
+
regex = if Vte::Regex
|
144
|
+
Vte::Regex.new(regex_name, Pcre2::ALL_FLAGS, for_match: true)
|
145
|
+
else
|
146
|
+
compile_options = %i[optimize multiline]
|
147
|
+
GLib::Regex.new(regex_name, compile_options: compile_options)
|
148
|
+
end
|
149
|
+
match_add_regex(regex, 0)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
109
153
|
def add_popup_menu
|
110
|
-
ui =
|
111
|
-
builder = Gtk::Builder.new(:
|
112
|
-
@menu = Gtk::Popover.new(self, builder[
|
154
|
+
ui = '/com/github/cedlemo/topinambour/terminal-menu.ui'
|
155
|
+
builder = Gtk::Builder.new(resource: ui)
|
156
|
+
@menu = Gtk::Popover.new(self, builder['termmenu'])
|
157
|
+
end
|
113
158
|
|
114
|
-
|
159
|
+
def handle_mouse_clic
|
160
|
+
signal_connect 'button-press-event' do |widget, event|
|
115
161
|
if event.type == Gdk::EventType::BUTTON_PRESS &&
|
116
162
|
event.button == Gdk::BUTTON_SECONDARY
|
117
163
|
manage_regex_on_right_click(widget, event)
|
118
|
-
display_copy_past_menu(
|
164
|
+
display_copy_past_menu(event)
|
119
165
|
true
|
120
166
|
elsif event.button == Gdk::BUTTON_PRIMARY
|
121
|
-
|
167
|
+
manage_regex_on_left_click(widget, event)
|
122
168
|
false # let false so that it doesn't block the event
|
123
169
|
else
|
124
170
|
false
|
@@ -126,66 +172,37 @@ class TopinambourTerminal < Vte::Terminal
|
|
126
172
|
end
|
127
173
|
end
|
128
174
|
|
129
|
-
def
|
130
|
-
|
131
|
-
set_scrollback_lines(-1)
|
132
|
-
search_set_wrap_around(true)
|
133
|
-
add_matches
|
134
|
-
end
|
135
|
-
|
136
|
-
def add_matches
|
137
|
-
@regexes = [:REGEX_URL_AS_IS, :REGEX_URL_FILE, :REGEX_URL_HTTP,
|
138
|
-
:REGEX_URL_VOIP, :REGEX_EMAIL, :REGEX_NEWS_MAN,
|
139
|
-
:CSS_COLORS]
|
140
|
-
@regexes.each do |name|
|
141
|
-
regex_name = TopinambourRegex.const_get(name)
|
142
|
-
flags = [:optimize,
|
143
|
-
:multiline]
|
144
|
-
if Vte::Regex
|
145
|
-
# PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_MULTILINE
|
146
|
-
pcre2_utf = "0x00080000".to_i(16)
|
147
|
-
pcre2_no_utf_check = "0x40000000".to_i(16)
|
148
|
-
pcre2_multiline = "0x00000400".to_i(16)
|
149
|
-
flags = pcre2_utf | pcre2_no_utf_check | pcre2_multiline
|
150
|
-
regex = Vte::Regex.new(regex_name, flags, :for_match => true)
|
151
|
-
match_add_regex(regex, 0)
|
152
|
-
else
|
153
|
-
regex = GLib::Regex.new(regex_name, :compile_options => flags)
|
154
|
-
match_add_gregex(regex, 0)
|
155
|
-
end
|
156
|
-
end
|
175
|
+
def manage_regex_on_right_click(_widget, event)
|
176
|
+
@last_match, _regex_type = match_check_event(event)
|
157
177
|
end
|
158
178
|
|
159
|
-
def display_copy_past_menu(
|
179
|
+
def display_copy_past_menu(event)
|
160
180
|
x, y = event.window.coords_to_parent(event.x,
|
161
181
|
event.y)
|
162
182
|
rect = Gdk::Rectangle.new(x - allocation.x,
|
163
183
|
y - allocation.y,
|
164
184
|
1,
|
165
185
|
1)
|
166
|
-
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
def manage_regex_on_right_click(_widget, event)
|
171
|
-
@last_match, _regex_type = match_check_event(event)
|
186
|
+
@menu.set_pointing_to(rect)
|
187
|
+
@menu.show
|
172
188
|
end
|
173
189
|
|
174
|
-
def
|
190
|
+
def manage_regex_on_left_click(widget, event)
|
175
191
|
match, regex_type = match_check_event(event)
|
176
192
|
return nil if regex_type == -1
|
177
|
-
case
|
193
|
+
case REGEXES[regex_type]
|
178
194
|
when :REGEX_EMAIL
|
179
|
-
launch_default_for_regex_match(
|
195
|
+
launch_default_for_regex_match('mailto:' + match, REGEXES[regex_type])
|
180
196
|
when :REGEX_URL_HTTP
|
181
|
-
launch_default_for_regex_match(
|
197
|
+
launch_default_for_regex_match('http://' + match, REGEXES[regex_type])
|
182
198
|
when :CSS_COLORS
|
183
199
|
launch_color_visualizer(match)
|
184
200
|
else
|
185
|
-
launch_default_for_regex_match(match,
|
201
|
+
launch_default_for_regex_match(match, REGEXES[regex_type])
|
186
202
|
end
|
187
203
|
end
|
188
204
|
|
205
|
+
# Open default application on a left click.
|
189
206
|
def launch_default_for_regex_match(match, regex_type)
|
190
207
|
Gio::AppInfo.launch_default_for_uri(match)
|
191
208
|
rescue => e
|
@@ -193,8 +210,8 @@ class TopinambourTerminal < Vte::Terminal
|
|
193
210
|
end
|
194
211
|
|
195
212
|
def launch_color_visualizer(color_name)
|
196
|
-
dialog = Gtk::ColorChooserDialog.new(:
|
197
|
-
:
|
213
|
+
dialog = Gtk::ColorChooserDialog.new(title: color_name,
|
214
|
+
parent: parent.toplevel)
|
198
215
|
dialog.show_editor = true
|
199
216
|
dialog.use_alpha = true
|
200
217
|
dialog.rgba = Gdk::RGBA.parse(color_name)
|