topinambour 1.0.11 → 1.0.12
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/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/preferences.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2016 Cedric LE MOIGNE, cedlemo@gmx.com
|
1
|
+
# Copyright 2016-2017 Cedric LE MOIGNE, cedlemo@gmx.com
|
2
2
|
# This file is part of Topinambour.
|
3
3
|
#
|
4
4
|
# Topinambour is free software: you can redistribute it and/or modify
|
@@ -13,151 +13,196 @@
|
|
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
|
-
require "gtksourceview3"
|
17
|
-
|
18
|
-
module TopinambourPreferences
|
19
|
-
def self.generate_dialog(parent)
|
20
|
-
resource_file = "/com/github/cedlemo/topinambour/prefs-dialog.ui"
|
21
|
-
builder = Gtk::Builder.new(:resource => resource_file)
|
22
|
-
dialog = builder["Preferences_dialog"]
|
23
|
-
dialog.transient_for = parent
|
24
|
-
add_actions(builder, parent)
|
25
|
-
connect_response(dialog, builder)
|
26
|
-
dialog
|
27
|
-
end
|
28
16
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
17
|
+
class TopinambourPreferences < Gtk::Window
|
18
|
+
type_register
|
19
|
+
class << self
|
20
|
+
def init
|
21
|
+
resource_file = "/com/github/cedlemo/topinambour/prefs-dialog.ui"
|
22
|
+
set_template(:resource => resource_file)
|
23
|
+
|
24
|
+
%w(width_spin height_spin shell_entry audible_bell_switch
|
25
|
+
allow_bold_switch scroll_on_output_switch scroll_on_keystroke_switch
|
26
|
+
rewrap_on_resize_switch mouse_autohide_switch cursor_shape_sel
|
27
|
+
cursor_blink_mode_sel backspace_binding_sel delete_binding_sel
|
28
|
+
css_chooser_button use_custom_css_switch).each do |widget|
|
29
|
+
bind_template_child(widget)
|
36
30
|
end
|
31
|
+
|
32
|
+
set_connect_func { |name| method(name) }
|
37
33
|
end
|
38
|
-
end
|
39
34
|
|
40
|
-
|
41
|
-
props = get_all_properties(widget, builder)
|
42
|
-
toplevel = widget.transient_for
|
43
|
-
toplevel.application.update_css(props)
|
44
|
-
widget.destroy
|
45
|
-
end
|
35
|
+
private
|
46
36
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
props.merge!(get_combo_values(builder))
|
53
|
-
end
|
37
|
+
def on_width_spin_value_changed_cb(spin)
|
38
|
+
parent = spin.toplevel.transient_for
|
39
|
+
height = parent.application.settings["height"]
|
40
|
+
parent.resize(spin.value, height)
|
41
|
+
end
|
54
42
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
43
|
+
def on_height_spin_value_changed_cb(spin)
|
44
|
+
parent = spin.toplevel.transient_for
|
45
|
+
width = parent.application.settings["width"]
|
46
|
+
parent.resize(width, spin.value)
|
59
47
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
48
|
+
|
49
|
+
def on_shell_entry_activate_cb(entry)
|
50
|
+
style_context = entry.style_context
|
51
|
+
|
52
|
+
if File.exist?(entry.text)
|
53
|
+
settings = entry.toplevel.settings
|
54
|
+
entry.set_icon_from_icon_name(:secondary, nil)
|
55
|
+
style_context.remove_class("error")
|
56
|
+
settings["default-shell"] = entry.text if settings
|
57
|
+
else
|
58
|
+
style_context.add_class("error")
|
59
|
+
entry.set_icon_from_icon_name(:secondary, "dialog-warning-symbolic")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def on_shell_entry_focus_out_event_cb(entry, _)
|
64
|
+
style_context = entry.style_context
|
65
|
+
|
66
|
+
if File.exist?(entry.text)
|
67
|
+
settings = entry.toplevel.settings
|
68
|
+
entry.set_icon_from_icon_name(:secondary, nil)
|
69
|
+
style_context.remove_class("error")
|
70
|
+
settings["default-shell"] = entry.text if settings
|
71
|
+
else
|
72
|
+
style_context.add_class("error")
|
73
|
+
entry.set_icon_from_icon_name(:secondary, "dialog-warning-symbolic")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_css_file_selected_cb(filechooser)
|
78
|
+
parent = filechooser.toplevel.transient_for
|
79
|
+
parent.application.settings["css-file"] = filechooser.filename
|
80
|
+
parent.application.reload_css_config
|
64
81
|
end
|
65
|
-
gen_spinbuttons_actions(builder, parent)
|
66
|
-
end
|
67
82
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
def on_custom_css_switch_state_set(switch, _state)
|
84
|
+
parent = switch.toplevel.transient_for
|
85
|
+
setting = "custom-css"
|
86
|
+
settings = parent.application.settings
|
87
|
+
settings[setting] = switch.active?
|
88
|
+
switch.toplevel.css_chooser_button.sensitive = settings[setting]
|
89
|
+
parent.application.reload_css_config
|
73
90
|
false
|
74
91
|
end
|
75
92
|
end
|
76
93
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
94
|
+
attr_reader :settings
|
95
|
+
def initialize(parent)
|
96
|
+
super(:type => :toplevel)
|
97
|
+
set_transient_for(parent)
|
98
|
+
@parent = parent
|
82
99
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
100
|
+
configure_headerbar
|
101
|
+
|
102
|
+
signal_connect "delete-event" do |widget|
|
103
|
+
widget.destroy
|
104
|
+
@parent.notebook.current.term.grab_focus
|
87
105
|
end
|
106
|
+
|
107
|
+
@settings = @parent.application.settings
|
108
|
+
|
109
|
+
initialize_widgets
|
88
110
|
end
|
89
111
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
112
|
+
private
|
113
|
+
|
114
|
+
def initialize_widgets
|
115
|
+
initialize_use_custom_css_settings
|
116
|
+
bind_spin_buttons_with_settings
|
117
|
+
bind_switches_with_settings
|
118
|
+
bind_combo_boxes_with_settings
|
119
|
+
|
120
|
+
shell_entry.text = @settings["default-shell"]
|
121
|
+
|
122
|
+
css_chooser_button.current_folder = "#{ENV['HOME']}/.config/topinambour/"
|
123
|
+
css_chooser_button.filename = @parent.application.check_css_file_path || ""
|
98
124
|
end
|
99
125
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
126
|
+
def bind_switches_with_settings
|
127
|
+
bind_switch_state_with_setting(allow_bold_switch, "allow-bold")
|
128
|
+
bind_switch_state_with_setting(audible_bell_switch, "audible-bell")
|
129
|
+
bind_switch_state_with_setting(scroll_on_output_switch, "scroll-on-output")
|
130
|
+
bind_switch_state_with_setting(scroll_on_keystroke_switch,
|
131
|
+
"scroll-on-keystroke")
|
132
|
+
bind_switch_state_with_setting(rewrap_on_resize_switch, "rewrap-on-resize")
|
133
|
+
bind_switch_state_with_setting(mouse_autohide_switch, "mouse-autohide")
|
108
134
|
end
|
109
135
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
widget.value = w if widget.value + 1 < w
|
116
|
-
end
|
136
|
+
def bind_combo_boxes_with_settings
|
137
|
+
bind_combo_box_with_setting(cursor_shape_sel, "cursor-shape")
|
138
|
+
bind_combo_box_with_setting(cursor_blink_mode_sel, "cursor-blink-mode")
|
139
|
+
bind_combo_box_with_setting(backspace_binding_sel, "backspace-binding")
|
140
|
+
bind_combo_box_with_setting(delete_binding_sel, "delete-binding")
|
117
141
|
end
|
118
142
|
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
parent.resize(w, widget.value)
|
123
|
-
_, h = parent.size
|
124
|
-
widget.value = h if widget.value + 1 < h
|
125
|
-
end
|
143
|
+
def bind_spin_buttons_with_settings
|
144
|
+
bind_spin_button_with_setting(width_spin, "width")
|
145
|
+
bind_spin_button_with_setting(height_spin, "height")
|
126
146
|
end
|
127
147
|
|
128
|
-
def
|
129
|
-
|
130
|
-
|
148
|
+
def configure_headerbar
|
149
|
+
headerbar = Gtk::HeaderBar.new
|
150
|
+
headerbar.title = "Topinambour Preferences"
|
151
|
+
headerbar.show_close_button = true
|
152
|
+
set_titlebar(headerbar)
|
131
153
|
end
|
132
154
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
155
|
+
def initialize_use_custom_css_settings
|
156
|
+
setting = "custom-css"
|
157
|
+
switch = use_custom_css_switch
|
158
|
+
switch.active = @settings[setting]
|
159
|
+
css_chooser_button.sensitive = @settings[setting]
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_switch_to_initial_state(_switch, setting)
|
163
|
+
state = @settings[setting]
|
164
|
+
m = "#{setting.tr('-', '_')}="
|
165
|
+
@parent.notebook.each do |tab|
|
166
|
+
tab.term.send(m, state)
|
140
167
|
end
|
141
|
-
props
|
142
168
|
end
|
143
169
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
170
|
+
def bind_switch_state_with_setting(switch, setting)
|
171
|
+
set_switch_to_initial_state(switch, setting)
|
172
|
+
@settings.bind(setting,
|
173
|
+
switch,
|
174
|
+
"active",
|
175
|
+
Gio::SettingsBindFlags::DEFAULT)
|
176
|
+
switch.signal_connect "state-set" do |_switch, state|
|
177
|
+
m = "#{setting.tr('-', '_')}="
|
178
|
+
@parent.notebook.each { |tab| tab.term.send(m, state) }
|
179
|
+
false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def set_combo_to_initial_state(_combo_box, setting)
|
184
|
+
active = @settings[setting]
|
185
|
+
m = "#{setting.tr('-', '_')}="
|
186
|
+
@parent.notebook.each { |tab| tab.term.send(m, active) }
|
187
|
+
end
|
188
|
+
|
189
|
+
def bind_combo_box_with_setting(combo_box, setting)
|
190
|
+
set_combo_to_initial_state(combo_box, setting)
|
191
|
+
@settings.bind(setting,
|
192
|
+
combo_box,
|
193
|
+
"active",
|
194
|
+
Gio::SettingsBindFlags::DEFAULT)
|
195
|
+
combo_box.signal_connect "changed" do
|
196
|
+
m = "#{setting.tr('-', '_')}="
|
197
|
+
@parent.notebook.each { |tab| tab.term.send(m, combo_box.active) }
|
198
|
+
false
|
152
199
|
end
|
153
|
-
props
|
154
200
|
end
|
155
201
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
props
|
202
|
+
def bind_spin_button_with_setting(spin_button, setting)
|
203
|
+
@settings.bind(setting,
|
204
|
+
spin_button,
|
205
|
+
"value",
|
206
|
+
Gio::SettingsBindFlags::DEFAULT)
|
162
207
|
end
|
163
208
|
end
|
data/lib/shortcuts.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2016 Cedric LE MOIGNE, cedlemo@gmx.com
|
1
|
+
# Copyright 2016-2017 Cedric LE MOIGNE, cedlemo@gmx.com
|
2
2
|
# This file is part of Topinambour.
|
3
3
|
#
|
4
4
|
# Topinambour is free software: you can redistribute it and/or modify
|
@@ -22,7 +22,6 @@ module TopinambourShortcuts
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.handle_simple(event, window)
|
25
|
-
overlay_mode = window.in_overlay_mode?
|
26
25
|
case event.keyval
|
27
26
|
when Gdk::Keyval::KEY_Escape # escape from overlay mode
|
28
27
|
if window.in_overlay_mode?
|
@@ -62,31 +61,20 @@ module TopinambourShortcuts
|
|
62
61
|
when Gdk::Keyval::KEY_slash
|
63
62
|
window.show_searchbar
|
64
63
|
true
|
65
|
-
when Gdk::Keyval::
|
66
|
-
window.
|
64
|
+
when Gdk::Keyval::KEY_Page_Up
|
65
|
+
window.opacity = window.opacity + 0.05
|
66
|
+
true
|
67
|
+
when Gdk::Keyval::KEY_Page_Down
|
68
|
+
window.opacity = window.opacity - 0.05
|
67
69
|
true
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
71
73
|
def self.handle_key_press(window, event)
|
72
|
-
keyval = event.keyval
|
73
74
|
if ctrl_shift?(event)
|
74
75
|
handle_ctrl_shift(event, window)
|
75
76
|
else
|
76
77
|
handle_simple(event, window)
|
77
78
|
end
|
78
79
|
end
|
79
|
-
|
80
|
-
def self.handle_scroll(window, event)
|
81
|
-
if ctrl_shift?(event)
|
82
|
-
case event.direction
|
83
|
-
when Gdk::ScrollDirection::UP
|
84
|
-
window.opacity = window.opacity + 0.05
|
85
|
-
true
|
86
|
-
when Gdk::ScrollDirection::DOWN
|
87
|
-
window.opacity = window.opacity - 0.05
|
88
|
-
true
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
80
|
end
|
data/lib/terminal.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2015-
|
1
|
+
# Copyright 2015-2017 Cedric LE MOIGNE, cedlemo@gmx.com
|
2
2
|
# This file is part of Topinambour.
|
3
3
|
#
|
4
4
|
# Topinambour is free software: you can redistribute it and/or modify
|
@@ -19,7 +19,7 @@
|
|
19
19
|
|
20
20
|
class TopinambourTabTerm < Gtk::Box
|
21
21
|
attr_reader :term
|
22
|
-
def initialize(command_string, working_dir=nil)
|
22
|
+
def initialize(command_string, working_dir = nil)
|
23
23
|
super(:horizontal, 0)
|
24
24
|
set_name("topinambour-tab-term")
|
25
25
|
@term = TopinambourTerminal.new(command_string, working_dir)
|
@@ -31,26 +31,24 @@ class TopinambourTabTerm < Gtk::Box
|
|
31
31
|
end
|
32
32
|
##
|
33
33
|
# The default vte terminal customized
|
34
|
-
class TopinambourTerminal
|
34
|
+
class TopinambourTerminal < Vte::Terminal
|
35
35
|
attr_reader :pid, :menu, :regexes, :last_match
|
36
|
-
attr_accessor :preview, :
|
36
|
+
attr_accessor :preview, :custom_title
|
37
37
|
|
38
38
|
##
|
39
39
|
# Create a new TopinambourTerminal instance that runs command_string
|
40
40
|
def initialize(command_string, working_dir = nil)
|
41
41
|
super()
|
42
|
-
|
43
|
-
command_array =
|
44
|
-
|
45
|
-
:working_directory => working_dir,
|
46
|
-
:spawn_flags => GLib::Spawn::SEARCH_PATH)
|
42
|
+
|
43
|
+
command_array = parse_command(command_string)
|
44
|
+
rescued_spawn(command_array, working_dir)
|
47
45
|
|
48
46
|
signal_connect "child-exited" do |widget|
|
49
47
|
tabterm = widget.parent
|
50
48
|
notebook = tabterm.parent
|
51
49
|
current_page = notebook.page_num(tabterm)
|
52
50
|
notebook.remove_page(current_page)
|
53
|
-
|
51
|
+
@application.quit unless notebook.n_pages >= 1
|
54
52
|
end
|
55
53
|
|
56
54
|
signal_connect "window-title-changed" do |widget|
|
@@ -59,8 +57,71 @@ class TopinambourTerminal
|
|
59
57
|
when_terminal_title_change if notebook && notebook.current.term == self
|
60
58
|
end
|
61
59
|
|
62
|
-
|
63
|
-
|
60
|
+
add_popup_menu
|
61
|
+
configure
|
62
|
+
end
|
63
|
+
|
64
|
+
def pid_dir
|
65
|
+
File.readlink("/proc/#{@pid}/cwd")
|
66
|
+
end
|
67
|
+
|
68
|
+
def terminal_title
|
69
|
+
@custom_title.class == String ? @custom_title : window_title.to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_settings
|
73
|
+
colors
|
74
|
+
set_colors(@colors[0], @colors[1], @colors[2..-1])
|
75
|
+
set_font(font)
|
76
|
+
end
|
77
|
+
|
78
|
+
def colors
|
79
|
+
colors_strings = application.settings["colorscheme"]
|
80
|
+
@colors = colors_strings.map { |c| Gdk::RGBA.parse(c) }
|
81
|
+
@colors
|
82
|
+
end
|
83
|
+
|
84
|
+
def font
|
85
|
+
font_str = application.settings["font"]
|
86
|
+
@font = Pango::FontDescription.new(font_str)
|
87
|
+
end
|
88
|
+
|
89
|
+
def colors=(colors)
|
90
|
+
set_colors(colors[0], colors[1], colors[2..-1])
|
91
|
+
end
|
92
|
+
|
93
|
+
def font=(font_str)
|
94
|
+
application.settings["font"] = Pango::FontDescription.new(font_str)
|
95
|
+
set_font(font)
|
96
|
+
@font = font
|
97
|
+
end
|
98
|
+
|
99
|
+
def application
|
100
|
+
@application = self.parent.toplevel.application unless @application
|
101
|
+
@application
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def parse_command(command_string)
|
107
|
+
GLib::Shell.parse(command_string)
|
108
|
+
rescue GLib::ShellError => e
|
109
|
+
STDERR.puts "domain = #{e.domain}"
|
110
|
+
STDERR.puts "code = #{e.code}"
|
111
|
+
STDERR.puts "message = #{e.message}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def rescued_spawn(command_array, working_dir)
|
115
|
+
@pid = spawn(:argv => command_array,
|
116
|
+
:working_directory => working_dir,
|
117
|
+
:spawn_flags => GLib::Spawn::SEARCH_PATH)
|
118
|
+
rescue => e
|
119
|
+
STDERR.puts e.message
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_popup_menu
|
123
|
+
ui = "/com/github/cedlemo/topinambour/terminal-menu.ui"
|
124
|
+
builder = Gtk::Builder.new(:resource => ui)
|
64
125
|
@menu = Gtk::Popover.new(self, builder["termmenu"])
|
65
126
|
|
66
127
|
signal_connect "button-press-event" do |widget, event|
|
@@ -76,28 +137,12 @@ class TopinambourTerminal
|
|
76
137
|
false
|
77
138
|
end
|
78
139
|
end
|
79
|
-
|
80
|
-
configure
|
81
|
-
end
|
82
|
-
|
83
|
-
def pid_dir
|
84
|
-
File.readlink("/proc/#{@pid}/cwd")
|
85
|
-
end
|
86
|
-
|
87
|
-
def terminal_title
|
88
|
-
@custom_title.class == String ? @custom_title : window_title.to_s
|
89
140
|
end
|
90
141
|
|
91
|
-
private
|
92
|
-
|
93
142
|
def configure
|
94
143
|
set_rewrap_on_resize(true)
|
95
144
|
set_scrollback_lines(-1)
|
96
145
|
search_set_wrap_around(true)
|
97
|
-
@colors = css_colors
|
98
|
-
set_font(css_font)
|
99
|
-
apply_colors
|
100
|
-
load_properties
|
101
146
|
add_matches
|
102
147
|
end
|
103
148
|
|
@@ -149,11 +194,9 @@ class TopinambourTerminal
|
|
149
194
|
end
|
150
195
|
|
151
196
|
def launch_default_for_regex_match(match, regex_type)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
puts "error : #{e.message}\n\tfor match: #{match} of type :#{regex_type}"
|
156
|
-
end
|
197
|
+
Gio::AppInfo.launch_default_for_uri(match)
|
198
|
+
rescue => e
|
199
|
+
puts "error : #{e.message}\n\tfor match: #{match} of type :#{regex_type}"
|
157
200
|
end
|
158
201
|
|
159
202
|
def launch_color_visualizer(color_name)
|