Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public class Terminal.Application : Gtk.Application {

public bool is_testing { get; set construct; }

private static Themes themes;

public Application () {
Object (
application_id: "io.elementary.terminal", /* Ensures only one instance runs */
Expand Down Expand Up @@ -238,7 +236,8 @@ public class Terminal.Application : Gtk.Application {
saved_state = new GLib.Settings ("io.elementary.terminal.saved-state");
settings = new GLib.Settings ("io.elementary.terminal.settings");
settings_sys = new GLib.Settings ("org.gnome.desktop.interface");
themes = new Themes ();

new Themes (); // Start listening to gsettings to sync headerbar dark style preference

var provider = new Gtk.CssProvider ();
provider.load_from_resource ("/io/elementary/terminal/Application.css");
Expand Down
39 changes: 15 additions & 24 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ namespace Terminal {
private Dialogs.ColorPreferences? color_preferences_dialog;
private uint focus_timeout = 0;

private const int NORMAL = 0;
private const int MAXIMIZED = 1;
private const int FULLSCREEN = 2;

public bool focus_restored_tabs { get; construct; default = true; }
public bool recreate_tabs { get; construct; default = true; }
public bool recreate_tabs { get; construct; }
public Terminal.Application app { get; construct; }
public SimpleActionGroup actions { get; construct; }

Expand All @@ -30,20 +25,19 @@ namespace Terminal {
public const string ACTION_CLOSE_TAB = "action-close-tab";
public const string ACTION_CLOSE_TABS_TO_RIGHT = "action_close_tabs_to_right";
public const string ACTION_CLOSE_OTHER_TABS = "action_close_other_tabs";
public const string ACTION_FULLSCREEN = "action-fullscreen";
private const string ACTION_FULLSCREEN = "action-fullscreen";
public const string ACTION_NEW_TAB = "action-term_widgetnew-tab";
public const string ACTION_NEW_TAB_AT = "action-new-tab-at";
public const string ACTION_TAB_ACTIVE_SHELL = "action-tab_active_shell";
public const string ACTION_TAB_RELOAD = "action-tab_reload";
public const string ACTION_RESTORE_CLOSED_TAB = "action-restore-closed-tab";
public const string ACTION_DUPLICATE_TAB = "action-duplicate-tab";
public const string ACTION_NEXT_TAB = "action-next-tab";
public const string ACTION_PREVIOUS_TAB = "action-previous-tab";
public const string ACTION_MOVE_TAB_RIGHT = "action-move-tab-right";
public const string ACTION_MOVE_TAB_LEFT = "action-move-tab-left";
private const string ACTION_NEXT_TAB = "action-next-tab";
private const string ACTION_PREVIOUS_TAB = "action-previous-tab";
private const string ACTION_MOVE_TAB_RIGHT = "action-move-tab-right";
private const string ACTION_MOVE_TAB_LEFT = "action-move-tab-left";
public const string ACTION_MOVE_TAB_TO_NEW_WINDOW = "action-move-tab-to-new-window";
public const string ACTION_SEARCH = "action-search";
public const string ACTION_SEARCH_ACCEL = "<Control><Shift>f";
private const string ACTION_SEARCH = "action-search";
public const string ACTION_SEARCH_NEXT = "action-search-next";
public const string ACTION_SEARCH_PREVIOUS = "action-search-previous";

Expand Down Expand Up @@ -89,7 +83,7 @@ namespace Terminal {
action_accelerators[ACTION_PREVIOUS_TAB] = "<Control>Page_Up";
action_accelerators[ACTION_MOVE_TAB_RIGHT] = "<Control><Alt>Right";
action_accelerators[ACTION_MOVE_TAB_LEFT] = "<Control><Alt>Left";
action_accelerators[ACTION_SEARCH] = ACTION_SEARCH_ACCEL;
action_accelerators[ACTION_SEARCH] = "<Control><Shift>f";
}

construct {
Expand Down Expand Up @@ -180,8 +174,8 @@ namespace Terminal {
notebook.add_new_tab (location, command);
}

Adw.TabPage? tab_to_close = null;
TerminalWidget? term_to_close = null;
private Adw.TabPage? tab_to_close = null;
private TerminalWidget? term_to_close = null;
private void setup_ui () {
unfullscreen_button = new Gtk.Button.from_icon_name ("view-restore-symbolic") {
action_name = ACTION_PREFIX + ACTION_FULLSCREEN,
Expand Down Expand Up @@ -454,10 +448,7 @@ namespace Terminal {
index++;
}

if (focus_restored_tabs) {
var tab = notebook.tab_view.get_nth_page (focus.clamp (0, notebook.n_pages - 1));
notebook.selected_page = tab;
}
notebook.selected_page = notebook.tab_view.get_nth_page (focus.clamp (0, notebook.n_pages - 1));
}

private void connect_terminal_signals (TerminalWidget terminal_widget) {
Expand Down Expand Up @@ -497,7 +488,7 @@ namespace Terminal {

private bool close_immediately = false;
//TODO Make TerminalWidget.confirm_kill_fg_process asynchronous and terminate all in callback
public bool on_delete_event () {
private bool on_delete_event () {
if (close_immediately) {
return Gdk.EVENT_PROPAGATE;
}
Expand Down Expand Up @@ -612,15 +603,15 @@ namespace Terminal {
notebook.cycle_tabs (BACK);
}

void action_move_tab_right () {
private void action_move_tab_right () {
notebook.tab_view.reorder_forward (notebook.selected_page);
}

void action_move_tab_left () {
private void action_move_tab_left () {
notebook.tab_view.reorder_backward (notebook.selected_page);
}

void action_move_tab_to_new_window () {
private void action_move_tab_to_new_window () {
// Do not use app action because we do not want default tab added
notebook.transfer_tab_to_window (present_new_empty_window ());
}
Expand Down
23 changes: 0 additions & 23 deletions src/Utils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -172,29 +172,6 @@ namespace Terminal.Utils {
}
}

public string? escape_uri (string uri, bool allow_utf8 = true, bool allow_single_quote = true) {
// We only want to allow '#' in appropriate position for fragment identifier, i.e. after the last directory separator.
var placeholder = "::::::";
var parts = uri.split (Path.DIR_SEPARATOR_S);
parts[parts.length - 1] = parts[parts.length - 1].replace ("#", placeholder);
var uri_to_escape = string.joinv (Path.DIR_SEPARATOR_S, parts);
string rc = ((Uri.RESERVED_CHARS_GENERIC_DELIMITERS + Uri.RESERVED_CHARS_SUBCOMPONENT_DELIMITERS))
.replace ("#", "")
.replace ("*", "")
.replace ("~", "");

if (!allow_single_quote) {
rc = rc.replace ("'", "");
}

//Escape and then replace fragment identifier
return Uri.escape_string (
(Uri.unescape_string (uri_to_escape) ?? uri_to_escape),
rc ,
allow_utf8
).replace (placeholder, "#");
}

public SimpleAction action_from_group (string action_name, SimpleActionGroup action_group) {
return ((SimpleAction) action_group.lookup_action (action_name));
}
Expand Down
5 changes: 1 addition & 4 deletions src/Widgets/TerminalView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
*/

public class Terminal.TerminalView : Granite.Bin {
const int TAB_HISTORY_MAX_ITEMS = 20;

public signal void new_tab_requested ();
public signal void tab_duplicated (Adw.TabPage page);
private const int TAB_HISTORY_MAX_ITEMS = 20;

public int n_pages {
get {
Expand Down
124 changes: 53 additions & 71 deletions src/Widgets/TerminalWidget.vala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace Terminal {
public string program_string { get; set; default = ""; }
static int terminal_id_counter = 0;
private bool init_complete;
public bool resized {get; set;}
private bool resized { get; set; }
public TabState tab_state { get; set; default = NONE; }

GLib.Pid child_pid;
Expand All @@ -38,59 +38,58 @@ namespace Terminal {
// There may be no associated tab while made restorable or when closing
public unowned Adw.TabPage? tab;

public const string ACTION_OPEN_IN_BROWSER = "term.open-in-browser";
public const string ACTION_COPY = "term.copy";
public const string ACTION_COPY_OUTPUT = "term.copy-output";
public const string ACTION_CLEAR_SCREEN = "term.clear-screen";
public const string ACTION_RESET = "term.reset";
public const string ACTION_PASTE = "term.paste";
public const string ACTION_RELOAD = "term.reload";
public const string ACTION_SCROLL_TO_COMMAND = "term.scroll-to-command";
public const string ACTION_SELECT_ALL = "term.select-all";

public const string[] ACCELS_OPEN_IN_BROWSER = { "<Control><Shift>E", null };
public const string[] ACCELS_COPY = { "<Control><Shift>C", null };
public const string[] ACCELS_COPY_OUTPUT = { "<Alt>C", null };
public const string[] ACCELS_CLEAR_SCREEN = { "<Control><Shift>L", null };
public const string[] ACCELS_RESET = { "<Control><Shift>K", null };
public const string[] ACCELS_PASTE = { "<Control><Shift>V", null };
public const string[] ACCELS_RELOAD = { "<Control><Shift>R", "<Ctrl>F5", null };
public const string[] ACCELS_SELECT_ALL = { "<Control><Shift>A", null };
private const string ACTION_OPEN_IN_BROWSER = "term.open-in-browser";
private const string ACTION_COPY = "term.copy";
private const string ACTION_COPY_OUTPUT = "term.copy-output";
private const string ACTION_CLEAR_SCREEN = "term.clear-screen";
private const string ACTION_RESET = "term.reset";
private const string ACTION_PASTE = "term.paste";
private const string ACTION_RELOAD = "term.reload";
private const string ACTION_SCROLL_TO_COMMAND = "term.scroll-to-command";
private const string ACTION_SELECT_ALL = "term.select-all";

private const string[] ACCELS_OPEN_IN_BROWSER = { "<Control><Shift>E", null };
private const string[] ACCELS_COPY = { "<Control><Shift>C", null };
private const string[] ACCELS_COPY_OUTPUT = { "<Alt>C", null };
private const string[] ACCELS_CLEAR_SCREEN = { "<Control><Shift>L", null };
private const string[] ACCELS_RESET = { "<Control><Shift>K", null };
private const string[] ACCELS_PASTE = { "<Control><Shift>V", null };
private const string[] ACCELS_RELOAD = { "<Control><Shift>R", "<Ctrl>F5", null };
private const string[] ACCELS_SELECT_ALL = { "<Control><Shift>A", null };
// Specify zooming shortcuts for use by tooltips in SettingsPopover. We don't use actions for this.
public const string[] ACCELS_ZOOM_DEFAULT = { "<control>0", "<Control>KP_0", null };
public const string[] ACCELS_ZOOM_IN = { "<Control>plus", "<Control>equal", "<Control>KP_Add", null };
public const string[] ACCELS_ZOOM_OUT = { "<Control>minus", "<Control>KP_Subtract", null };

public int default_size;
const string SEND_PROCESS_FINISHED_BASH = "dbus-send --type=method_call " +
"--session --dest=io.elementary.terminal " +
"/io/elementary/terminal " +
"io.elementary.terminal.ProcessFinished " +
"string:$PANTHEON_TERMINAL_ID " +
"string:\"$(fc -nl -1 | cut -c 3-)\" " +
"int32:\$__bp_last_ret_value >/dev/null 2>&1";
private const string SEND_PROCESS_FINISHED_BASH = "dbus-send --type=method_call " +
"--session --dest=io.elementary.terminal " +
"/io/elementary/terminal " +
"io.elementary.terminal.ProcessFinished " +
"string:$PANTHEON_TERMINAL_ID " +
"string:\"$(fc -nl -1 | cut -c 3-)\" " +
"int32:\$__bp_last_ret_value >/dev/null 2>&1";

/* Following strings are used to build RegEx for matching URIs */
const string USERCHARS = "-[:alnum:]";
const string USERCHARS_CLASS = "[" + USERCHARS + "]";
const string PASSCHARS_CLASS = "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]";
const string HOSTCHARS_CLASS = "[-[:alnum:]]";
const string HOST = HOSTCHARS_CLASS + "+(\\." + HOSTCHARS_CLASS + "+)*";
const string PORT = "(?:\\:[[:digit:]]{1,5})?";
const string PATHCHARS_CLASS = "[-[:alnum:]\\Q_$.+!*,;:@&=?/~#%\\E]";
const string PATHTERM_CLASS = "[^\\Q]'.}>) \t\r\n,\"\\E]";
const string SCHEME = "(?:news:|telnet:|nntp:|file:\\/|https?:|ftps?:|sftp:|webcal:" +
"|irc:|sftp:|ldaps?:|nfs:|smb:|rsync:|ssh:|rlogin:|telnet:|git:" +
"|git\\+ssh:|bzr:|bzr\\+ssh:|svn:|svn\\+ssh:|hg:|mailto:|magnet:)";

const string USERPASS = USERCHARS_CLASS + "+(?:" + PASSCHARS_CLASS + "+)?";
const string URLPATH = "(?:(/" + PATHCHARS_CLASS +
"+(?:[(]" + PATHCHARS_CLASS +
"*[)])*" + PATHCHARS_CLASS +
"*)*" + PATHTERM_CLASS +
")?";

const string[] REGEX_STRINGS = {
private const string USERCHARS = "-[:alnum:]";
private const string USERCHARS_CLASS = "[" + USERCHARS + "]";
private const string PASSCHARS_CLASS = "[-[:alnum:]\\Q,?;.:/!%$^*&~\"#'\\E]";
private const string HOSTCHARS_CLASS = "[-[:alnum:]]";
private const string HOST = HOSTCHARS_CLASS + "+(\\." + HOSTCHARS_CLASS + "+)*";
private const string PORT = "(?:\\:[[:digit:]]{1,5})?";
private const string PATHCHARS_CLASS = "[-[:alnum:]\\Q_$.+!*,;:@&=?/~#%\\E]";
private const string PATHTERM_CLASS = "[^\\Q]'.}>) \t\r\n,\"\\E]";
private const string SCHEME = "(?:news:|telnet:|nntp:|file:\\/|https?:|ftps?:|sftp:|webcal:" +
"|irc:|sftp:|ldaps?:|nfs:|smb:|rsync:|ssh:|rlogin:|telnet:|git:" +
"|git\\+ssh:|bzr:|bzr\\+ssh:|svn:|svn\\+ssh:|hg:|mailto:|magnet:)";

private const string USERPASS = USERCHARS_CLASS + "+(?:" + PASSCHARS_CLASS + "+)?";
private const string URLPATH = "(?:(/" + PATHCHARS_CLASS +
"+(?:[(]" + PATHCHARS_CLASS +
"*[)])*" + PATHCHARS_CLASS +
"*)*" + PATHTERM_CLASS +
")?";

private const string[] REGEX_STRINGS = {
SCHEME + "//(?:" + USERPASS + "\\@)?" + HOST + PORT + URLPATH,
"(?:www|ftp)" + HOSTCHARS_CLASS + "*\\." + HOST + PORT + URLPATH,
"(?:callto:|h323:|sip:)" + USERCHARS_CLASS + "[" + USERCHARS + ".]*(?:" + PORT + "/[a-z0-9]+)?\\@" + HOST,
Expand All @@ -101,7 +100,7 @@ namespace Terminal {
public const double MIN_SCALE = 0.25;
public const double MAX_SCALE = 4.0;

public const int SYS_PIDFD_OPEN = 434; // Same on every arch
private const int SYS_PIDFD_OPEN = 434; // Same on every arch

public bool killed { get; private set; default = false; }

Expand All @@ -118,7 +117,7 @@ namespace Terminal {
private long remembered_position; /* Only need to remember row at the moment */
private long remembered_command_start_row = 0; /* Only need to remember row at the moment */
private long remembered_command_end_row = 0; /* Only need to remember row at the moment */
public bool last_key_was_return = true;
private bool last_key_was_return = true;
private bool child_has_exited = false;
private string? link_uri = null;

Expand Down Expand Up @@ -930,7 +929,7 @@ namespace Terminal {
);
}

public bool try_get_foreground_pid (out int pid) {
private bool try_get_foreground_pid (out int pid) {
if (child_has_exited) {
pid = -1;
return false;
Expand All @@ -952,16 +951,6 @@ namespace Terminal {
return try_get_foreground_pid (null);
}

public int calculate_width (int column_count) {
int width = (int) (this.get_char_width ()) * column_count;
return width;
}

public int calculate_height (int row_count) {
int height = (int) (this.get_char_height ()) * row_count;
return height;
}

private void clickable (string[] str) {
foreach (unowned string exp in str) {
try {
Expand Down Expand Up @@ -990,7 +979,7 @@ namespace Terminal {
}
}

public string get_pid_exe_name (int pid) {
private string get_pid_exe_name (int pid) {
try {
var exe = GLib.FileUtils.read_link ("/proc/%d/exe".printf (pid));
return Path.get_basename (exe);
Expand Down Expand Up @@ -1043,13 +1032,13 @@ namespace Terminal {
return true;
}

public void remember_position () {
private void remember_position () {
long col, row;
get_cursor_position (out col, out row);
remembered_position = row;
}

public void remember_command_start_position () {
private void remember_command_start_position () {
if (!last_key_was_return || has_foreground_process ()) {
return;
}
Expand All @@ -1061,7 +1050,7 @@ namespace Terminal {
resized = false;
}

public void remember_command_end_position () {
private void remember_command_end_position () {
if (last_key_was_return && !has_foreground_process ()) {
return;
}
Expand Down Expand Up @@ -1150,13 +1139,6 @@ namespace Terminal {
);
}

public void prepare_to_close () {
if (contents_changed_timeout_id > 0) {
Source.remove (contents_changed_timeout_id);
contents_changed_timeout_id = 0;
}
}

private void open_in_browser (GLib.SimpleAction action, GLib.Variant? parameter) {
var uri = get_current_selection_link_or_pwd ();
var context = Gdk.Display.get_default ().get_app_launch_context ();
Expand Down