Skip to content

Commit

Permalink
initial support for tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
vhdirk committed Jan 28, 2024
1 parent 5c4579a commit a0917ed
Show file tree
Hide file tree
Showing 32 changed files with 825 additions and 566 deletions.
6 changes: 3 additions & 3 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ terms of section 4, provided that you also meet all of these conditions:
"keep intact all notices".

c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License to anyone who comes into postab of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
Expand Down Expand Up @@ -317,7 +317,7 @@ modification has been made.

If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
part of a transaction in which the right of postab and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
Expand Down Expand Up @@ -456,7 +456,7 @@ organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
give under the previous paragraph, plus a right to postab of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ Terms uses GTK4 and is written in Rust. The latter has no added value aside from

## Status

- [x] Single terminal mode. No tiling, no tabs.
Terms is still very much in development. The following features are present but may still need some work to stabilize.

- [x] Multiple windows
- [x] Drag/drop support
- [x] href/mailto regex matching
- [x] Settings
- [x] Theming. Compatible with Gogh
- [x] Flatpak support
- [x] Shortcuts
- [ ] Tabs
- [x] Tabs
- [ ] Tiling
- [ ] Profiles
- [ ] Store and load sessions like Tilix does
- [ ] Store and load session like Tilix and Prompt do
- [ ] iTerm2-like support for tmux


Expand Down
233 changes: 119 additions & 114 deletions data/io.github.vhdirk.Terms.gschema.xml.in

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions data/resources/resources.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
<file compressed="true" preprocess="xml-stripblanks" alias="shortcut_row.ui">../../src/components/shortcut_row/shortcut_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="shortcut_dialog.ui">../../src/components/shortcut_dialog/shortcut_dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="terminal.ui">../../src/components/terminal/terminal.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_frame.ui">../../src/components/terminal_frame/terminal_frame.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_panel.ui">../../src/components/terminal_panel/terminal_panel.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_tab.ui">../../src/components/terminal_tab/terminal_tab.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="search_toolbar.ui">../../src/components/search_toolbar/search_toolbar.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="session.ui">../../src/components/session/session.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="style_switcher.ui">../../src/components/style_switcher/style_switcher.ui</file>
</gresource>
<gresource prefix="/io/github/vhdirk/Terms/svg">
Expand Down
4 changes: 2 additions & 2 deletions data/resources/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ window:not(.about) headerbar,
background-color: @window_bg_color;
}

#terms_main_window.context-root .custom-headerbar {
/* #terms_main_window.context-root .custom-headerbar {
background-color: @root_context_color;
}
#terms_main_window.context-ssh .custom-headerbar {
background-color: @ssh_context_color;
}
} */

/* .custom-headerbar windowhandle>box {
padding-top: 0;
Expand Down
58 changes: 29 additions & 29 deletions data/resources/ui/help_overlay.ui
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">New session</property>
<property name="action-name">win.new-session</property>
<property name="title" translatable="yes" context="shortcut window">New tab</property>
<property name="action-name">win.new-tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Close session</property>
<property name="action-name">win.close-session</property>
<property name="title" translatable="yes" context="shortcut window">Close tab</property>
<property name="action-name">win.close-tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Rename session</property>
<property name="action-name">win.rename-session</property>
<property name="title" translatable="yes" context="shortcut window">Rename tab</property>
<property name="action-name">win.rename-tab</property>
</object>
</child>
<child>
Expand Down Expand Up @@ -92,75 +92,75 @@
<property name="title" translatable="yes" context="shortcut window">Navigation</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus next session</property>
<property name="action-name">app.focus-session-next</property>
<property name="title" translatable="yes" context="shortcut window">Focus next tab</property>
<property name="action-name">app.focus-tab-next</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus previous session</property>
<property name="action-name">app.focus-session-previous</property>
<property name="title" translatable="yes" context="shortcut window">Focus previous tab</property>
<property name="action-name">app.focus-tab-previous</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 1</property>
<property name="action-name">win.focus-session-1</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 1</property>
<property name="action-name">win.focus-tab-1</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 2</property>
<property name="action-name">win.focus-session-2</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 2</property>
<property name="action-name">win.focus-tab-2</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 3</property>
<property name="action-name">win.focus-session-3</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 3</property>
<property name="action-name">win.focus-tab-3</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 4</property>
<property name="action-name">win.focus-session-4</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 4</property>
<property name="action-name">win.focus-tab-4</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 5</property>
<property name="action-name">win.focus-session-5</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 5</property>
<property name="action-name">win.focus-tab-5</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 6</property>
<property name="action-name">win.focus-session-6</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 6</property>
<property name="action-name">win.focus-tab-6</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 7</property>
<property name="action-name">win.focus-session-7</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 7</property>
<property name="action-name">win.focus-tab-7</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 8</property>
<property name="action-name">win.focus-session-8</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 8</property>
<property name="action-name">win.focus-tab-8</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Focus Session 9</property>
<property name="action-name">win.focus-session-9</property>
<property name="title" translatable="yes" context="shortcut window">Focus Tab 9</property>
<property name="action-name">win.focus-tab-9</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Switch to last
Tab</property>
<property name="action-name">win.focus-session-last</property>
<property name="action-name">win.focus-tab-last</property>
</object>
</child>
</object>
Expand Down
91 changes: 27 additions & 64 deletions src/application.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use std::{borrow::Cow, fmt, rc::Rc};

use crate::{
components::{TerminalInitArgs, Window},
config::{self, APP_ID, APP_NAME, VERSION},
settings::Settings,
};
use adw;
use gettextrs::gettext;
use gio::ApplicationFlags;
use glib::ExitCode;
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use serde::{Deserialize, Serialize};
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use std::{cell::RefCell, path::PathBuf};
use std::{fmt, rc::Rc};
use tracing::*;

// use crate::{config, session_list::SessionList, spawn, system_settings::SystemSettings, Window};
use crate::{
components::Window,
config::{self, APP_ID, APP_NAME, VERSION},
settings::Settings,
};

/// The profile that was built.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -54,40 +51,20 @@ impl fmt::Display for AppProfile {

mod imp {

use std::{collections::HashMap, env};

use adw::subclass::prelude::AdwApplicationImpl;
// use panel::{prelude::WorkbenchExt, subclass::prelude::PanelApplicationImpl};

use crate::{
components::{TerminalInitArgs, Window},
config::APP_ID,
theme_provider::ThemeProvider,
};
use crate::{components::Window, config::APP_ID, theme_provider::ThemeProvider, util::EnvMap};

use super::*;

#[derive(Debug)]
#[derive(Debug, Default)]
pub struct Application {
/// The application settings.
pub settings: Settings,
// pub theme_provider: ThemeProvider,
// /// The system settings.
// pub system_settings: SystemSettings,
// /// The list of logged-in sessions.
// pub session_list: SessionList,
pub init_args: RefCell<TerminalInitArgs>,
}

impl Default for Application {
fn default() -> Self {
Self {
settings: Settings::default(),
// system_settings: Default::default(),
// session_list: Default::default(),
init_args: RefCell::default(),
}
}
pub command: RefCell<Option<String>>,
pub directory: RefCell<Option<PathBuf>>,
pub env: RefCell<Option<EnvMap>>,
}

#[glib::object_subclass]
Expand All @@ -110,15 +87,11 @@ mod imp {
}

impl ApplicationImpl for Application {
// We connect to the activate callback to create a window when the application
// has been launched. Additionally, this callback notifies us when the user
// tries to launch a "second instance" of the application. When they try
// to do that, we'll just present any existing window.
fn activate(&self) {
// init the theme provider
// late-init the theme provider
ThemeProvider::default();

self.new_window(Some(self.init_args.borrow().clone()));
self.new_window(self.command.borrow().clone(), self.directory.borrow().clone(), self.env.borrow().clone());
}

fn startup(&self) {
Expand Down Expand Up @@ -147,18 +120,12 @@ mod imp {
return ExitCode::SUCCESS;
}

let working_dir = options
.lookup_value("working-directory", None)
.and_then(|w| w.get::<PathBuf>())
.or(env::current_dir().ok());
let working_dir = options.lookup_value("working-directory", None).and_then(|w| w.get::<PathBuf>());

let command = options.lookup_value("command", None).and_then(|w| w.get::<String>());

self.set_init_args(TerminalInitArgs {
working_dir,
command,
env: HashMap::new(),
});
*self.command.borrow_mut() = command;
*self.directory.borrow_mut() = working_dir;

self.parent_handle_local_options(options)
}
Expand Down Expand Up @@ -200,20 +167,12 @@ mod imp {
);
}

fn set_init_args(&self, init_args: TerminalInitArgs) {
let mut args = self.init_args.borrow_mut();
*args = init_args;
}

pub fn new_window(&self, init_args: Option<TerminalInitArgs>) {
// Get the current window or create one if necessary
pub fn new_window(&self, command: Option<String>, directory: Option<PathBuf>, env: Option<EnvMap>) {
let app = self.obj();

// TODO: if init_args is none, we have to get them from the last terminal?
info!("Window init args: {:?}", init_args);
let window = Window::new(&*app, init_args.unwrap());
info!("Window init args: {:?} {:?} {:?}", command, directory, env);
let window = Window::new(&*app, command, directory, env);

// Ask the window manager/compositor to present the window
info!("Add window");
app.add_window(&window);
window.present();
Expand Down Expand Up @@ -264,15 +223,19 @@ impl Application {
}

fn setup_shortcuts(&self) {
// TODO: watch for changes
// TODO: watch for changes in shortcuts
let shortcut_settings = self.imp().settings.shortcuts();
for (action, accels) in shortcut_settings.actionmap() {
self.set_accels_for_action(&action, &accels.iter().map(|a| a.as_str()).collect::<Vec<_>>())
}
}

fn new_window(&self) {
self.imp().new_window(None);
// TODO: this fails if the last active window was not a 'Window' but perhaps preferences
let directory = self.active_window().and_downcast::<Window>().and_then(|window| window.directory());

// TODO: respect working_directory_mode setting
self.imp().new_window(None, directory, None);
}

fn show_about(&self) {
Expand All @@ -285,7 +248,7 @@ impl Application {
.application_name(APP_NAME)
.license_type(gtk::License::Gpl30)
.developer_name("Dirk Van Haerenborgh")
.copyright(2022 Dirk Van Haerenborgh")
.copyright(2023 Dirk Van Haerenborgh")
.website("https://github.com/vhdirk/terms/")
.issue_url("https://github.com/vhdirk/terms/issues")
// .translator_credits(gettext("translator-credits").replace("\\n", "\n"))
Expand Down
Loading

0 comments on commit a0917ed

Please sign in to comment.