Skip to content

Commit a0917ed

Browse files
committed
initial support for tabs
1 parent 5c4579a commit a0917ed

32 files changed

+825
-566
lines changed

LICENSE

+3-3
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ terms of section 4, provided that you also meet all of these conditions:
220220
"keep intact all notices".
221221

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

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

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,19 @@ Terms uses GTK4 and is written in Rust. The latter has no added value aside from
3232

3333
## Status
3434

35-
- [x] Single terminal mode. No tiling, no tabs.
35+
Terms is still very much in development. The following features are present but may still need some work to stabilize.
36+
3637
- [x] Multiple windows
3738
- [x] Drag/drop support
3839
- [x] href/mailto regex matching
3940
- [x] Settings
4041
- [x] Theming. Compatible with Gogh
4142
- [x] Flatpak support
4243
- [x] Shortcuts
43-
- [ ] Tabs
44+
- [x] Tabs
4445
- [ ] Tiling
4546
- [ ] Profiles
46-
- [ ] Store and load sessions like Tilix does
47+
- [ ] Store and load session like Tilix and Prompt do
4748
- [ ] iTerm2-like support for tmux
4849

4950

data/io.github.vhdirk.Terms.gschema.xml.in

+119-114
Large diffs are not rendered by default.

data/resources/resources.gresource.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
<file compressed="true" preprocess="xml-stripblanks" alias="shortcut_row.ui">../../src/components/shortcut_row/shortcut_row.ui</file>
1515
<file compressed="true" preprocess="xml-stripblanks" alias="shortcut_dialog.ui">../../src/components/shortcut_dialog/shortcut_dialog.ui</file>
1616
<file compressed="true" preprocess="xml-stripblanks" alias="terminal.ui">../../src/components/terminal/terminal.ui</file>
17-
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_frame.ui">../../src/components/terminal_frame/terminal_frame.ui</file>
17+
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_panel.ui">../../src/components/terminal_panel/terminal_panel.ui</file>
18+
<file compressed="true" preprocess="xml-stripblanks" alias="terminal_tab.ui">../../src/components/terminal_tab/terminal_tab.ui</file>
1819
<file compressed="true" preprocess="xml-stripblanks" alias="search_toolbar.ui">../../src/components/search_toolbar/search_toolbar.ui</file>
19-
<file compressed="true" preprocess="xml-stripblanks" alias="session.ui">../../src/components/session/session.ui</file>
2020
<file compressed="true" preprocess="xml-stripblanks" alias="style_switcher.ui">../../src/components/style_switcher/style_switcher.ui</file>
2121
</gresource>
2222
<gresource prefix="/io/github/vhdirk/Terms/svg">

data/resources/style.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ window:not(.about) headerbar,
1717
background-color: @window_bg_color;
1818
}
1919

20-
#terms_main_window.context-root .custom-headerbar {
20+
/* #terms_main_window.context-root .custom-headerbar {
2121
background-color: @root_context_color;
2222
}
2323
2424
#terms_main_window.context-ssh .custom-headerbar {
2525
background-color: @ssh_context_color;
26-
}
26+
} */
2727

2828
/* .custom-headerbar windowhandle>box {
2929
padding-top: 0;

data/resources/ui/help_overlay.ui

+29-29
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@
1616
</child>
1717
<child>
1818
<object class="GtkShortcutsShortcut">
19-
<property name="title" translatable="yes" context="shortcut window">New session</property>
20-
<property name="action-name">win.new-session</property>
19+
<property name="title" translatable="yes" context="shortcut window">New tab</property>
20+
<property name="action-name">win.new-tab</property>
2121
</object>
2222
</child>
2323
<child>
2424
<object class="GtkShortcutsShortcut">
25-
<property name="title" translatable="yes" context="shortcut window">Close session</property>
26-
<property name="action-name">win.close-session</property>
25+
<property name="title" translatable="yes" context="shortcut window">Close tab</property>
26+
<property name="action-name">win.close-tab</property>
2727
</object>
2828
</child>
2929
<child>
3030
<object class="GtkShortcutsShortcut">
31-
<property name="title" translatable="yes" context="shortcut window">Rename session</property>
32-
<property name="action-name">win.rename-session</property>
31+
<property name="title" translatable="yes" context="shortcut window">Rename tab</property>
32+
<property name="action-name">win.rename-tab</property>
3333
</object>
3434
</child>
3535
<child>
@@ -92,75 +92,75 @@
9292
<property name="title" translatable="yes" context="shortcut window">Navigation</property>
9393
<child>
9494
<object class="GtkShortcutsShortcut">
95-
<property name="title" translatable="yes" context="shortcut window">Focus next session</property>
96-
<property name="action-name">app.focus-session-next</property>
95+
<property name="title" translatable="yes" context="shortcut window">Focus next tab</property>
96+
<property name="action-name">app.focus-tab-next</property>
9797
</object>
9898
</child>
9999
<child>
100100
<object class="GtkShortcutsShortcut">
101-
<property name="title" translatable="yes" context="shortcut window">Focus previous session</property>
102-
<property name="action-name">app.focus-session-previous</property>
101+
<property name="title" translatable="yes" context="shortcut window">Focus previous tab</property>
102+
<property name="action-name">app.focus-tab-previous</property>
103103
</object>
104104
</child>
105105
<child>
106106
<object class="GtkShortcutsShortcut">
107-
<property name="title" translatable="yes" context="shortcut window">Focus Session 1</property>
108-
<property name="action-name">win.focus-session-1</property>
107+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 1</property>
108+
<property name="action-name">win.focus-tab-1</property>
109109
</object>
110110
</child>
111111
<child>
112112
<object class="GtkShortcutsShortcut">
113-
<property name="title" translatable="yes" context="shortcut window">Focus Session 2</property>
114-
<property name="action-name">win.focus-session-2</property>
113+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 2</property>
114+
<property name="action-name">win.focus-tab-2</property>
115115
</object>
116116
</child>
117117
<child>
118118
<object class="GtkShortcutsShortcut">
119-
<property name="title" translatable="yes" context="shortcut window">Focus Session 3</property>
120-
<property name="action-name">win.focus-session-3</property>
119+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 3</property>
120+
<property name="action-name">win.focus-tab-3</property>
121121
</object>
122122
</child>
123123
<child>
124124
<object class="GtkShortcutsShortcut">
125-
<property name="title" translatable="yes" context="shortcut window">Focus Session 4</property>
126-
<property name="action-name">win.focus-session-4</property>
125+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 4</property>
126+
<property name="action-name">win.focus-tab-4</property>
127127
</object>
128128
</child>
129129
<child>
130130
<object class="GtkShortcutsShortcut">
131-
<property name="title" translatable="yes" context="shortcut window">Focus Session 5</property>
132-
<property name="action-name">win.focus-session-5</property>
131+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 5</property>
132+
<property name="action-name">win.focus-tab-5</property>
133133
</object>
134134
</child>
135135
<child>
136136
<object class="GtkShortcutsShortcut">
137-
<property name="title" translatable="yes" context="shortcut window">Focus Session 6</property>
138-
<property name="action-name">win.focus-session-6</property>
137+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 6</property>
138+
<property name="action-name">win.focus-tab-6</property>
139139
</object>
140140
</child>
141141
<child>
142142
<object class="GtkShortcutsShortcut">
143-
<property name="title" translatable="yes" context="shortcut window">Focus Session 7</property>
144-
<property name="action-name">win.focus-session-7</property>
143+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 7</property>
144+
<property name="action-name">win.focus-tab-7</property>
145145
</object>
146146
</child>
147147
<child>
148148
<object class="GtkShortcutsShortcut">
149-
<property name="title" translatable="yes" context="shortcut window">Focus Session 8</property>
150-
<property name="action-name">win.focus-session-8</property>
149+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 8</property>
150+
<property name="action-name">win.focus-tab-8</property>
151151
</object>
152152
</child>
153153
<child>
154154
<object class="GtkShortcutsShortcut">
155-
<property name="title" translatable="yes" context="shortcut window">Focus Session 9</property>
156-
<property name="action-name">win.focus-session-9</property>
155+
<property name="title" translatable="yes" context="shortcut window">Focus Tab 9</property>
156+
<property name="action-name">win.focus-tab-9</property>
157157
</object>
158158
</child>
159159
<child>
160160
<object class="GtkShortcutsShortcut">
161161
<property name="title" translatable="yes" context="shortcut window">Switch to last
162162
Tab</property>
163-
<property name="action-name">win.focus-session-last</property>
163+
<property name="action-name">win.focus-tab-last</property>
164164
</object>
165165
</child>
166166
</object>

src/application.rs

+27-64
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
use std::{borrow::Cow, fmt, rc::Rc};
2-
3-
use crate::{
4-
components::{TerminalInitArgs, Window},
5-
config::{self, APP_ID, APP_NAME, VERSION},
6-
settings::Settings,
7-
};
81
use adw;
92
use gettextrs::gettext;
103
use gio::ApplicationFlags;
114
use glib::ExitCode;
12-
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
13-
use serde::{Deserialize, Serialize};
5+
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
146
use std::{cell::RefCell, path::PathBuf};
7+
use std::{fmt, rc::Rc};
158
use tracing::*;
169

17-
// use crate::{config, session_list::SessionList, spawn, system_settings::SystemSettings, Window};
10+
use crate::{
11+
components::Window,
12+
config::{self, APP_ID, APP_NAME, VERSION},
13+
settings::Settings,
14+
};
1815

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

5552
mod imp {
5653

57-
use std::{collections::HashMap, env};
58-
5954
use adw::subclass::prelude::AdwApplicationImpl;
6055
// use panel::{prelude::WorkbenchExt, subclass::prelude::PanelApplicationImpl};
6156

62-
use crate::{
63-
components::{TerminalInitArgs, Window},
64-
config::APP_ID,
65-
theme_provider::ThemeProvider,
66-
};
57+
use crate::{components::Window, config::APP_ID, theme_provider::ThemeProvider, util::EnvMap};
6758

6859
use super::*;
6960

70-
#[derive(Debug)]
61+
#[derive(Debug, Default)]
7162
pub struct Application {
72-
/// The application settings.
7363
pub settings: Settings,
74-
// pub theme_provider: ThemeProvider,
75-
// /// The system settings.
76-
// pub system_settings: SystemSettings,
77-
// /// The list of logged-in sessions.
78-
// pub session_list: SessionList,
79-
pub init_args: RefCell<TerminalInitArgs>,
80-
}
8164

82-
impl Default for Application {
83-
fn default() -> Self {
84-
Self {
85-
settings: Settings::default(),
86-
// system_settings: Default::default(),
87-
// session_list: Default::default(),
88-
init_args: RefCell::default(),
89-
}
90-
}
65+
pub command: RefCell<Option<String>>,
66+
pub directory: RefCell<Option<PathBuf>>,
67+
pub env: RefCell<Option<EnvMap>>,
9168
}
9269

9370
#[glib::object_subclass]
@@ -110,15 +87,11 @@ mod imp {
11087
}
11188

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

121-
self.new_window(Some(self.init_args.borrow().clone()));
94+
self.new_window(self.command.borrow().clone(), self.directory.borrow().clone(), self.env.borrow().clone());
12295
}
12396

12497
fn startup(&self) {
@@ -147,18 +120,12 @@ mod imp {
147120
return ExitCode::SUCCESS;
148121
}
149122

150-
let working_dir = options
151-
.lookup_value("working-directory", None)
152-
.and_then(|w| w.get::<PathBuf>())
153-
.or(env::current_dir().ok());
123+
let working_dir = options.lookup_value("working-directory", None).and_then(|w| w.get::<PathBuf>());
154124

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

157-
self.set_init_args(TerminalInitArgs {
158-
working_dir,
159-
command,
160-
env: HashMap::new(),
161-
});
127+
*self.command.borrow_mut() = command;
128+
*self.directory.borrow_mut() = working_dir;
162129

163130
self.parent_handle_local_options(options)
164131
}
@@ -200,20 +167,12 @@ mod imp {
200167
);
201168
}
202169

203-
fn set_init_args(&self, init_args: TerminalInitArgs) {
204-
let mut args = self.init_args.borrow_mut();
205-
*args = init_args;
206-
}
207-
208-
pub fn new_window(&self, init_args: Option<TerminalInitArgs>) {
209-
// Get the current window or create one if necessary
170+
pub fn new_window(&self, command: Option<String>, directory: Option<PathBuf>, env: Option<EnvMap>) {
210171
let app = self.obj();
211172

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

216-
// Ask the window manager/compositor to present the window
217176
info!("Add window");
218177
app.add_window(&window);
219178
window.present();
@@ -264,15 +223,19 @@ impl Application {
264223
}
265224

266225
fn setup_shortcuts(&self) {
267-
// TODO: watch for changes
226+
// TODO: watch for changes in shortcuts
268227
let shortcut_settings = self.imp().settings.shortcuts();
269228
for (action, accels) in shortcut_settings.actionmap() {
270229
self.set_accels_for_action(&action, &accels.iter().map(|a| a.as_str()).collect::<Vec<_>>())
271230
}
272231
}
273232

274233
fn new_window(&self) {
275-
self.imp().new_window(None);
234+
// TODO: this fails if the last active window was not a 'Window' but perhaps preferences
235+
let directory = self.active_window().and_downcast::<Window>().and_then(|window| window.directory());
236+
237+
// TODO: respect working_directory_mode setting
238+
self.imp().new_window(None, directory, None);
276239
}
277240

278241
fn show_about(&self) {
@@ -285,7 +248,7 @@ impl Application {
285248
.application_name(APP_NAME)
286249
.license_type(gtk::License::Gpl30)
287250
.developer_name("Dirk Van Haerenborgh")
288-
.copyright(2022 Dirk Van Haerenborgh")
251+
.copyright(2023 Dirk Van Haerenborgh")
289252
.website("https://github.com/vhdirk/terms/")
290253
.issue_url("https://github.com/vhdirk/terms/issues")
291254
// .translator_credits(gettext("translator-credits").replace("\\n", "\n"))

0 commit comments

Comments
 (0)