ntermqt 0.1.0__py3-none-any.whl
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.
- nterm/__init__.py +54 -0
- nterm/__main__.py +619 -0
- nterm/askpass/__init__.py +22 -0
- nterm/askpass/server.py +393 -0
- nterm/config.py +158 -0
- nterm/connection/__init__.py +17 -0
- nterm/connection/profile.py +296 -0
- nterm/manager/__init__.py +29 -0
- nterm/manager/connect_dialog.py +322 -0
- nterm/manager/editor.py +262 -0
- nterm/manager/io.py +678 -0
- nterm/manager/models.py +346 -0
- nterm/manager/settings.py +264 -0
- nterm/manager/tree.py +493 -0
- nterm/resources.py +48 -0
- nterm/session/__init__.py +60 -0
- nterm/session/askpass_ssh.py +399 -0
- nterm/session/base.py +110 -0
- nterm/session/interactive_ssh.py +522 -0
- nterm/session/pty_transport.py +571 -0
- nterm/session/ssh.py +610 -0
- nterm/terminal/__init__.py +11 -0
- nterm/terminal/bridge.py +83 -0
- nterm/terminal/resources/terminal.html +253 -0
- nterm/terminal/resources/terminal.js +414 -0
- nterm/terminal/resources/xterm-addon-fit.min.js +8 -0
- nterm/terminal/resources/xterm-addon-unicode11.min.js +8 -0
- nterm/terminal/resources/xterm-addon-web-links.min.js +8 -0
- nterm/terminal/resources/xterm.css +209 -0
- nterm/terminal/resources/xterm.min.js +8 -0
- nterm/terminal/widget.py +380 -0
- nterm/theme/__init__.py +10 -0
- nterm/theme/engine.py +456 -0
- nterm/theme/stylesheet.py +377 -0
- nterm/theme/themes/clean.yaml +0 -0
- nterm/theme/themes/default.yaml +36 -0
- nterm/theme/themes/dracula.yaml +36 -0
- nterm/theme/themes/gruvbox_dark.yaml +36 -0
- nterm/theme/themes/gruvbox_hybrid.yaml +38 -0
- nterm/theme/themes/gruvbox_light.yaml +36 -0
- nterm/vault/__init__.py +32 -0
- nterm/vault/credential_manager.py +163 -0
- nterm/vault/keychain.py +135 -0
- nterm/vault/manager_ui.py +962 -0
- nterm/vault/profile.py +219 -0
- nterm/vault/resolver.py +250 -0
- nterm/vault/store.py +642 -0
- ntermqt-0.1.0.dist-info/METADATA +327 -0
- ntermqt-0.1.0.dist-info/RECORD +52 -0
- ntermqt-0.1.0.dist-info/WHEEL +5 -0
- ntermqt-0.1.0.dist-info/entry_points.txt +5 -0
- ntermqt-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>nterm</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
html, body {
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
background: var(--bg-color, #1e1e2e);
|
|
18
|
+
}
|
|
19
|
+
#terminal {
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
}
|
|
23
|
+
#terminal .xterm-viewport {
|
|
24
|
+
overflow-y: auto !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Status Overlay */
|
|
28
|
+
#overlay {
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
right: 0;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
background: var(--overlay-bg, rgba(30, 30, 46, 0.9));
|
|
35
|
+
display: none;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
z-index: 1000;
|
|
39
|
+
}
|
|
40
|
+
#overlay.visible {
|
|
41
|
+
display: flex;
|
|
42
|
+
}
|
|
43
|
+
#overlay-content {
|
|
44
|
+
text-align: center;
|
|
45
|
+
}
|
|
46
|
+
#overlay-text {
|
|
47
|
+
color: var(--overlay-text, #cdd6f4);
|
|
48
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
49
|
+
font-size: 16px;
|
|
50
|
+
padding: 20px 40px;
|
|
51
|
+
border-radius: 8px;
|
|
52
|
+
background: var(--overlay-box-bg, #313244);
|
|
53
|
+
}
|
|
54
|
+
#overlay-spinner {
|
|
55
|
+
width: 24px;
|
|
56
|
+
height: 24px;
|
|
57
|
+
border: 3px solid var(--overlay-text, #cdd6f4);
|
|
58
|
+
border-top-color: transparent;
|
|
59
|
+
border-radius: 50%;
|
|
60
|
+
animation: spin 1s linear infinite;
|
|
61
|
+
margin: 0 auto 16px;
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
64
|
+
#overlay-spinner.visible {
|
|
65
|
+
display: block;
|
|
66
|
+
}
|
|
67
|
+
@keyframes spin {
|
|
68
|
+
to { transform: rotate(360deg); }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Paste Confirmation Dialog */
|
|
72
|
+
#paste-confirm {
|
|
73
|
+
position: absolute;
|
|
74
|
+
top: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
right: 0;
|
|
77
|
+
bottom: 0;
|
|
78
|
+
background: var(--overlay-bg, rgba(30, 30, 46, 0.95));
|
|
79
|
+
display: none;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
z-index: 1001;
|
|
83
|
+
}
|
|
84
|
+
#paste-confirm.visible {
|
|
85
|
+
display: flex;
|
|
86
|
+
}
|
|
87
|
+
#paste-confirm-dialog {
|
|
88
|
+
background: var(--overlay-box-bg, #313244);
|
|
89
|
+
border-radius: 12px;
|
|
90
|
+
padding: 24px;
|
|
91
|
+
max-width: 600px;
|
|
92
|
+
width: 90%;
|
|
93
|
+
max-height: 80vh;
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
97
|
+
}
|
|
98
|
+
#paste-confirm-title {
|
|
99
|
+
color: var(--overlay-text, #cdd6f4);
|
|
100
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
101
|
+
font-size: 18px;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
margin-bottom: 8px;
|
|
104
|
+
}
|
|
105
|
+
#paste-confirm-subtitle {
|
|
106
|
+
color: var(--overlay-text, #a6adc8);
|
|
107
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
108
|
+
font-size: 14px;
|
|
109
|
+
margin-bottom: 16px;
|
|
110
|
+
}
|
|
111
|
+
#paste-confirm-preview {
|
|
112
|
+
background: var(--bg-color, #1e1e2e);
|
|
113
|
+
border: 1px solid #45475a;
|
|
114
|
+
border-radius: 8px;
|
|
115
|
+
padding: 12px;
|
|
116
|
+
font-family: 'JetBrains Mono', 'Cascadia Code', Consolas, monospace;
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
color: var(--overlay-text, #cdd6f4);
|
|
119
|
+
white-space: pre-wrap;
|
|
120
|
+
word-break: break-all;
|
|
121
|
+
overflow-y: auto;
|
|
122
|
+
max-height: 300px;
|
|
123
|
+
flex: 1;
|
|
124
|
+
margin-bottom: 20px;
|
|
125
|
+
}
|
|
126
|
+
#paste-confirm-buttons {
|
|
127
|
+
display: flex;
|
|
128
|
+
justify-content: flex-end;
|
|
129
|
+
gap: 12px;
|
|
130
|
+
}
|
|
131
|
+
.paste-btn {
|
|
132
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
133
|
+
font-size: 14px;
|
|
134
|
+
font-weight: 500;
|
|
135
|
+
padding: 10px 20px;
|
|
136
|
+
border-radius: 6px;
|
|
137
|
+
border: none;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
transition: background-color 0.15s ease;
|
|
140
|
+
}
|
|
141
|
+
.paste-btn-cancel {
|
|
142
|
+
background: #45475a;
|
|
143
|
+
color: #cdd6f4;
|
|
144
|
+
}
|
|
145
|
+
.paste-btn-cancel:hover {
|
|
146
|
+
background: #585b70;
|
|
147
|
+
}
|
|
148
|
+
.paste-btn-confirm {
|
|
149
|
+
background: #a6e3a1;
|
|
150
|
+
color: #1e1e2e;
|
|
151
|
+
}
|
|
152
|
+
.paste-btn-confirm:hover {
|
|
153
|
+
background: #94e2d5;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Context Menu */
|
|
157
|
+
#context-menu {
|
|
158
|
+
position: absolute;
|
|
159
|
+
background: var(--overlay-box-bg, #313244);
|
|
160
|
+
border: 1px solid #45475a;
|
|
161
|
+
border-radius: 8px;
|
|
162
|
+
padding: 4px 0;
|
|
163
|
+
min-width: 160px;
|
|
164
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
|
165
|
+
z-index: 1002;
|
|
166
|
+
display: none;
|
|
167
|
+
}
|
|
168
|
+
#context-menu.visible {
|
|
169
|
+
display: block;
|
|
170
|
+
}
|
|
171
|
+
.context-menu-item {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: space-between;
|
|
175
|
+
padding: 8px 16px;
|
|
176
|
+
color: var(--overlay-text, #cdd6f4);
|
|
177
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
178
|
+
font-size: 13px;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
transition: background-color 0.1s ease;
|
|
181
|
+
}
|
|
182
|
+
.context-menu-item:hover {
|
|
183
|
+
background: #45475a;
|
|
184
|
+
}
|
|
185
|
+
.context-menu-item.disabled {
|
|
186
|
+
color: #6c7086;
|
|
187
|
+
cursor: default;
|
|
188
|
+
}
|
|
189
|
+
.context-menu-item.disabled:hover {
|
|
190
|
+
background: transparent;
|
|
191
|
+
}
|
|
192
|
+
.context-menu-shortcut {
|
|
193
|
+
color: #6c7086;
|
|
194
|
+
font-size: 12px;
|
|
195
|
+
margin-left: 24px;
|
|
196
|
+
}
|
|
197
|
+
.context-menu-separator {
|
|
198
|
+
height: 1px;
|
|
199
|
+
background: #45475a;
|
|
200
|
+
margin: 4px 0;
|
|
201
|
+
}
|
|
202
|
+
</style>
|
|
203
|
+
<link rel="stylesheet" href="xterm.css">
|
|
204
|
+
</head>
|
|
205
|
+
<body>
|
|
206
|
+
<div id="terminal"></div>
|
|
207
|
+
|
|
208
|
+
<!-- Status Overlay -->
|
|
209
|
+
<div id="overlay">
|
|
210
|
+
<div id="overlay-content">
|
|
211
|
+
<div id="overlay-spinner"></div>
|
|
212
|
+
<span id="overlay-text"></span>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<!-- Paste Confirmation Dialog -->
|
|
217
|
+
<div id="paste-confirm">
|
|
218
|
+
<div id="paste-confirm-dialog">
|
|
219
|
+
<div id="paste-confirm-title">Confirm Multi-line Paste</div>
|
|
220
|
+
<div id="paste-confirm-subtitle">You are about to paste <span id="paste-line-count">0</span> lines:</div>
|
|
221
|
+
<pre id="paste-confirm-preview"></pre>
|
|
222
|
+
<div id="paste-confirm-buttons">
|
|
223
|
+
<button class="paste-btn paste-btn-cancel" id="paste-cancel">Cancel</button>
|
|
224
|
+
<button class="paste-btn paste-btn-confirm" id="paste-ok">Paste</button>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
<!-- Context Menu -->
|
|
230
|
+
<div id="context-menu">
|
|
231
|
+
<div class="context-menu-item" id="ctx-copy">
|
|
232
|
+
<span>Copy</span>
|
|
233
|
+
<span class="context-menu-shortcut">Ctrl+Shift+C</span>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="context-menu-item" id="ctx-paste">
|
|
236
|
+
<span>Paste</span>
|
|
237
|
+
<span class="context-menu-shortcut">Ctrl+Shift+V</span>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="context-menu-separator"></div>
|
|
240
|
+
<div class="context-menu-item" id="ctx-clear">
|
|
241
|
+
<span>Clear Terminal</span>
|
|
242
|
+
<span class="context-menu-shortcut"></span>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<script src="xterm.min.js"></script>
|
|
247
|
+
<script src="xterm-addon-fit.min.js"></script>
|
|
248
|
+
<script src="xterm-addon-web-links.min.js"></script>
|
|
249
|
+
<script src="xterm-addon-unicode11.min.js"></script>
|
|
250
|
+
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
|
251
|
+
<script src="terminal.js"></script>
|
|
252
|
+
</body>
|
|
253
|
+
</html>
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
let term = null;
|
|
5
|
+
let fitAddon = null;
|
|
6
|
+
let bridge = null;
|
|
7
|
+
let initialized = false;
|
|
8
|
+
|
|
9
|
+
// DOM elements
|
|
10
|
+
let contextMenu = null;
|
|
11
|
+
let pasteConfirmDialog = null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize xterm.js terminal
|
|
15
|
+
*/
|
|
16
|
+
function initTerminal() {
|
|
17
|
+
// Default theme (Catppuccin Mocha)
|
|
18
|
+
const defaultTheme = {
|
|
19
|
+
background: '#1e1e2e',
|
|
20
|
+
foreground: '#cdd6f4',
|
|
21
|
+
cursor: '#f5e0dc',
|
|
22
|
+
cursorAccent: '#1e1e2e',
|
|
23
|
+
selectionBackground: '#585b70',
|
|
24
|
+
selectionForeground: '#cdd6f4',
|
|
25
|
+
black: '#45475a',
|
|
26
|
+
red: '#f38ba8',
|
|
27
|
+
green: '#a6e3a1',
|
|
28
|
+
yellow: '#f9e2af',
|
|
29
|
+
blue: '#89b4fa',
|
|
30
|
+
magenta: '#f5c2e7',
|
|
31
|
+
cyan: '#94e2d5',
|
|
32
|
+
white: '#bac2de',
|
|
33
|
+
brightBlack: '#585b70',
|
|
34
|
+
brightRed: '#f38ba8',
|
|
35
|
+
brightGreen: '#a6e3a1',
|
|
36
|
+
brightYellow: '#f9e2af',
|
|
37
|
+
brightBlue: '#89b4fa',
|
|
38
|
+
brightMagenta: '#f5c2e7',
|
|
39
|
+
brightCyan: '#94e2d5',
|
|
40
|
+
brightWhite: '#a6adc8',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Create terminal
|
|
44
|
+
term = new Terminal({
|
|
45
|
+
cursorBlink: true,
|
|
46
|
+
cursorStyle: 'block',
|
|
47
|
+
fontSize: 14,
|
|
48
|
+
fontFamily: 'JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace',
|
|
49
|
+
fontWeight: 'normal',
|
|
50
|
+
fontWeightBold: 'bold',
|
|
51
|
+
lineHeight: 1.1,
|
|
52
|
+
letterSpacing: 0,
|
|
53
|
+
theme: defaultTheme,
|
|
54
|
+
allowProposedApi: true,
|
|
55
|
+
scrollback: 10000,
|
|
56
|
+
tabStopWidth: 8,
|
|
57
|
+
bellStyle: 'none',
|
|
58
|
+
macOptionIsMeta: true,
|
|
59
|
+
macOptionClickForcesSelection: true,
|
|
60
|
+
rightClickSelectsWord: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Load addons
|
|
64
|
+
fitAddon = new FitAddon.FitAddon();
|
|
65
|
+
term.loadAddon(fitAddon);
|
|
66
|
+
|
|
67
|
+
const webLinksAddon = new WebLinksAddon.WebLinksAddon();
|
|
68
|
+
term.loadAddon(webLinksAddon);
|
|
69
|
+
|
|
70
|
+
const unicode11Addon = new Unicode11Addon.Unicode11Addon();
|
|
71
|
+
term.loadAddon(unicode11Addon);
|
|
72
|
+
term.unicode.activeVersion = '11';
|
|
73
|
+
|
|
74
|
+
// Open terminal in container
|
|
75
|
+
const container = document.getElementById('terminal');
|
|
76
|
+
term.open(container);
|
|
77
|
+
|
|
78
|
+
// Initial fit
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
fitAddon.fit();
|
|
81
|
+
}, 0);
|
|
82
|
+
|
|
83
|
+
// Handle user input - properly encode UTF-8 to base64
|
|
84
|
+
term.onData(data => {
|
|
85
|
+
if (bridge) {
|
|
86
|
+
// Encode UTF-8 string to base64
|
|
87
|
+
bridge.onData(btoa(unescape(encodeURIComponent(data))));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Handle title changes
|
|
92
|
+
term.onTitleChange(title => {
|
|
93
|
+
if (bridge) {
|
|
94
|
+
bridge.onTitleChange(title);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Handle resize
|
|
99
|
+
const resizeObserver = new ResizeObserver(entries => {
|
|
100
|
+
if (!initialized) return;
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
fitAddon.fit();
|
|
104
|
+
if (bridge) {
|
|
105
|
+
bridge.onResize(term.cols, term.rows);
|
|
106
|
+
}
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.error('Resize error:', e);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
resizeObserver.observe(container);
|
|
112
|
+
|
|
113
|
+
// Focus terminal on click
|
|
114
|
+
container.addEventListener('click', () => {
|
|
115
|
+
term.focus();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
initialized = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Set up context menu
|
|
123
|
+
*/
|
|
124
|
+
function setupContextMenu() {
|
|
125
|
+
contextMenu = document.getElementById('context-menu');
|
|
126
|
+
const container = document.getElementById('terminal');
|
|
127
|
+
|
|
128
|
+
// Show context menu on right-click
|
|
129
|
+
container.addEventListener('contextmenu', (e) => {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
|
|
132
|
+
// Update copy item state based on selection
|
|
133
|
+
const copyItem = document.getElementById('ctx-copy');
|
|
134
|
+
const hasSelection = term.hasSelection();
|
|
135
|
+
|
|
136
|
+
if (hasSelection) {
|
|
137
|
+
copyItem.classList.remove('disabled');
|
|
138
|
+
} else {
|
|
139
|
+
copyItem.classList.add('disabled');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Position menu
|
|
143
|
+
const x = Math.min(e.clientX, window.innerWidth - 180);
|
|
144
|
+
const y = Math.min(e.clientY, window.innerHeight - 120);
|
|
145
|
+
|
|
146
|
+
contextMenu.style.left = x + 'px';
|
|
147
|
+
contextMenu.style.top = y + 'px';
|
|
148
|
+
contextMenu.classList.add('visible');
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Hide context menu on click elsewhere
|
|
152
|
+
document.addEventListener('click', (e) => {
|
|
153
|
+
if (!contextMenu.contains(e.target)) {
|
|
154
|
+
contextMenu.classList.remove('visible');
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Hide on escape
|
|
159
|
+
document.addEventListener('keydown', (e) => {
|
|
160
|
+
if (e.key === 'Escape') {
|
|
161
|
+
contextMenu.classList.remove('visible');
|
|
162
|
+
pasteConfirmDialog.classList.remove('visible');
|
|
163
|
+
if (bridge) {
|
|
164
|
+
bridge.onPasteCancelled();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Context menu actions
|
|
170
|
+
document.getElementById('ctx-copy').addEventListener('click', () => {
|
|
171
|
+
contextMenu.classList.remove('visible');
|
|
172
|
+
doCopy();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
document.getElementById('ctx-paste').addEventListener('click', () => {
|
|
176
|
+
contextMenu.classList.remove('visible');
|
|
177
|
+
doPaste();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
document.getElementById('ctx-clear').addEventListener('click', () => {
|
|
181
|
+
contextMenu.classList.remove('visible');
|
|
182
|
+
term.clear();
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Set up paste confirmation dialog
|
|
188
|
+
*/
|
|
189
|
+
function setupPasteConfirm() {
|
|
190
|
+
pasteConfirmDialog = document.getElementById('paste-confirm');
|
|
191
|
+
|
|
192
|
+
document.getElementById('paste-cancel').addEventListener('click', () => {
|
|
193
|
+
pasteConfirmDialog.classList.remove('visible');
|
|
194
|
+
if (bridge) {
|
|
195
|
+
bridge.onPasteCancelled();
|
|
196
|
+
}
|
|
197
|
+
term.focus();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
document.getElementById('paste-ok').addEventListener('click', () => {
|
|
201
|
+
pasteConfirmDialog.classList.remove('visible');
|
|
202
|
+
if (bridge) {
|
|
203
|
+
bridge.onPasteConfirmed();
|
|
204
|
+
}
|
|
205
|
+
term.focus();
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Set up keyboard shortcuts
|
|
211
|
+
*/
|
|
212
|
+
function setupKeyboardShortcuts() {
|
|
213
|
+
// Attach to terminal's custom key handler
|
|
214
|
+
term.attachCustomKeyEventHandler((e) => {
|
|
215
|
+
// Detect platform for modifier key
|
|
216
|
+
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
|
217
|
+
const modifier = isMac ? e.metaKey : e.ctrlKey;
|
|
218
|
+
|
|
219
|
+
// Ctrl+Shift+C or Cmd+C (Mac) - Copy
|
|
220
|
+
if (modifier && e.shiftKey && e.key === 'C') {
|
|
221
|
+
doCopy();
|
|
222
|
+
return false; // Prevent default
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Ctrl+Shift+V or Cmd+V (Mac) - Paste
|
|
226
|
+
if (modifier && e.shiftKey && e.key === 'V') {
|
|
227
|
+
doPaste();
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Also support Ctrl+C for copy when there's a selection (non-Mac)
|
|
232
|
+
// On Mac, Cmd+C already works natively
|
|
233
|
+
if (!isMac && e.ctrlKey && !e.shiftKey && e.key === 'c' && term.hasSelection()) {
|
|
234
|
+
doCopy();
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Ctrl+V for paste (non-Mac)
|
|
239
|
+
if (!isMac && e.ctrlKey && !e.shiftKey && e.key === 'v') {
|
|
240
|
+
doPaste();
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return true; // Allow default handling
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Copy terminal selection to clipboard
|
|
250
|
+
*/
|
|
251
|
+
function doCopy() {
|
|
252
|
+
if (!term.hasSelection()) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const selection = term.getSelection();
|
|
256
|
+
// Let Python handle clipboard - more reliable in QWebEngineView
|
|
257
|
+
if (bridge) {
|
|
258
|
+
bridge.onSelectionCopied(selection);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Paste from clipboard (routes through Python for multiline check)
|
|
263
|
+
*/
|
|
264
|
+
function doPaste() {
|
|
265
|
+
// Let Python handle clipboard read - more reliable in QWebEngineView
|
|
266
|
+
if (bridge) {
|
|
267
|
+
bridge.onPasteRequested('');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Set up bridge to Python via QWebChannel
|
|
273
|
+
*/
|
|
274
|
+
function setupBridge() {
|
|
275
|
+
new QWebChannel(qt.webChannelTransport, function(channel) {
|
|
276
|
+
bridge = channel.objects.bridge;
|
|
277
|
+
|
|
278
|
+
// Data from Python to terminal - properly decode UTF-8
|
|
279
|
+
bridge.write_data.connect(function(dataB64) {
|
|
280
|
+
try {
|
|
281
|
+
// Decode base64 to binary string, then to UTF-8
|
|
282
|
+
const binaryString = atob(dataB64);
|
|
283
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
284
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
285
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
286
|
+
}
|
|
287
|
+
const data = new TextDecoder('utf-8').decode(bytes);
|
|
288
|
+
term.write(data);
|
|
289
|
+
} catch (e) {
|
|
290
|
+
console.error('Write error:', e);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Theme changes
|
|
295
|
+
bridge.apply_theme.connect(function(themeJson) {
|
|
296
|
+
try {
|
|
297
|
+
const theme = JSON.parse(themeJson);
|
|
298
|
+
term.options.theme = theme;
|
|
299
|
+
|
|
300
|
+
// Update CSS variables
|
|
301
|
+
document.documentElement.style.setProperty(
|
|
302
|
+
'--bg-color',
|
|
303
|
+
theme.background || '#1e1e2e'
|
|
304
|
+
);
|
|
305
|
+
document.body.style.background = theme.background || '#1e1e2e';
|
|
306
|
+
} catch (e) {
|
|
307
|
+
console.error('Theme error:', e);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Font changes
|
|
312
|
+
bridge.set_font.connect(function(family, size) {
|
|
313
|
+
term.options.fontFamily = family;
|
|
314
|
+
term.options.fontSize = size;
|
|
315
|
+
setTimeout(() => fitAddon.fit(), 0);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Resize command
|
|
319
|
+
bridge.do_resize.connect(function(cols, rows) {
|
|
320
|
+
term.resize(cols, rows);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Overlay control - now with spinner visibility
|
|
324
|
+
bridge.show_overlay.connect(function(message, showSpinner) {
|
|
325
|
+
const overlay = document.getElementById('overlay');
|
|
326
|
+
const text = document.getElementById('overlay-text');
|
|
327
|
+
const spinner = document.getElementById('overlay-spinner');
|
|
328
|
+
|
|
329
|
+
text.textContent = message;
|
|
330
|
+
|
|
331
|
+
if (showSpinner) {
|
|
332
|
+
spinner.classList.add('visible');
|
|
333
|
+
} else {
|
|
334
|
+
spinner.classList.remove('visible');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
overlay.classList.add('visible');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
bridge.hide_overlay.connect(function() {
|
|
341
|
+
const overlay = document.getElementById('overlay');
|
|
342
|
+
overlay.classList.remove('visible');
|
|
343
|
+
term.focus();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Focus command
|
|
347
|
+
bridge.focus_terminal.connect(function() {
|
|
348
|
+
term.focus();
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Clear command
|
|
352
|
+
bridge.clear_terminal.connect(function() {
|
|
353
|
+
term.clear();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Copy command (triggered from Python)
|
|
357
|
+
bridge.do_copy.connect(function() {
|
|
358
|
+
doCopy();
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Direct paste (already confirmed, skip check)
|
|
362
|
+
bridge.do_paste.connect(function(dataB64) {
|
|
363
|
+
try {
|
|
364
|
+
const data = decodeURIComponent(escape(atob(dataB64)));
|
|
365
|
+
// Write directly to terminal as if user typed it
|
|
366
|
+
// This will be picked up by onData handler
|
|
367
|
+
term.paste(data);
|
|
368
|
+
} catch (e) {
|
|
369
|
+
console.error('Direct paste error:', e);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Show paste confirmation dialog
|
|
374
|
+
bridge.show_paste_confirm.connect(function(preview, lineCount) {
|
|
375
|
+
document.getElementById('paste-line-count').textContent = lineCount;
|
|
376
|
+
document.getElementById('paste-confirm-preview').textContent = preview;
|
|
377
|
+
pasteConfirmDialog.classList.add('visible');
|
|
378
|
+
|
|
379
|
+
// Focus the confirm button
|
|
380
|
+
document.getElementById('paste-ok').focus();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Hide paste confirmation dialog
|
|
384
|
+
bridge.hide_paste_confirm.connect(function() {
|
|
385
|
+
pasteConfirmDialog.classList.remove('visible');
|
|
386
|
+
term.focus();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// Notify Python that terminal is ready
|
|
390
|
+
fitAddon.fit();
|
|
391
|
+
bridge.onResize(term.cols, term.rows);
|
|
392
|
+
bridge.onReady();
|
|
393
|
+
term.focus();
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Initialize everything when DOM is ready
|
|
399
|
+
*/
|
|
400
|
+
function init() {
|
|
401
|
+
initTerminal();
|
|
402
|
+
setupContextMenu();
|
|
403
|
+
setupPasteConfirm();
|
|
404
|
+
setupKeyboardShortcuts();
|
|
405
|
+
setupBridge();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Start when DOM ready
|
|
409
|
+
if (document.readyState === 'loading') {
|
|
410
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
411
|
+
} else {
|
|
412
|
+
init();
|
|
413
|
+
}
|
|
414
|
+
})();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skipped minification because the original files appears to be already minified.
|
|
3
|
+
* Original file: /npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js
|
|
4
|
+
*
|
|
5
|
+
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
|
6
|
+
*/
|
|
7
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
|
|
8
|
+
//# sourceMappingURL=xterm-addon-fit.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skipped minification because the original files appears to be already minified.
|
|
3
|
+
* Original file: /npm/xterm-addon-unicode11@0.6.0/lib/xterm-addon-unicode11.js
|
|
4
|
+
*
|
|
5
|
+
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
|
6
|
+
*/
|
|
7
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(this,(()=>(()=>{"use strict";var e={433:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void 0;const o=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648],[1750,1757],[1759,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2045,2045],[2070,2073],[2075,2083],[2085,2087],[2089,2093],[2137,2139],[2259,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2558,2558],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2641,2641],[2672,2673],[2677,2677],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2810,2815],[2817,2817],[2876,2876],[2879,2879],[2881,2884],[2893,2893],[2902,2902],[2914,2915],[2946,2946],[3008,3008],[3021,3021],[3072,3072],[3076,3076],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3170,3171],[3201,3201],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3328,3329],[3387,3388],[3393,3396],[3405,3405],[3426,3427],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3981,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4151],[4153,4154],[4157,4158],[4184,4185],[4190,4192],[4209,4212],[4226,4226],[4229,4230],[4237,4237],[4253,4253],[4448,4607],[4957,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6158],[6277,6278],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6683,6683],[6742,6742],[6744,6750],[6752,6752],[6754,6754],[6757,6764],[6771,6780],[6783,6783],[6832,6846],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7040,7041],[7074,7077],[7080,7081],[7083,7085],[7142,7142],[7144,7145],[7149,7149],[7151,7153],[7212,7219],[7222,7223],[7376,7378],[7380,7392],[7394,7400],[7405,7405],[7412,7412],[7416,7417],[7616,7673],[7675,7679],[8203,8207],[8234,8238],[8288,8292],[8294,8303],[8400,8432],[11503,11505],[11647,11647],[11744,11775],[12330,12333],[12441,12442],[42607,42610],[42612,42621],[42654,42655],[42736,42737],[43010,43010],[43014,43014],[43019,43019],[43045,43046],[43204,43205],[43232,43249],[43263,43263],[43302,43309],[43335,43345],[43392,43394],[43443,43443],[43446,43449],[43452,43453],[43493,43493],[43561,43566],[43569,43570],[43573,43574],[43587,43587],[43596,43596],[43644,43644],[43696,43696],[43698,43700],[43703,43704],[43710,43711],[43713,43713],[43756,43757],[43766,43766],[44005,44005],[44008,44008],[44013,44013],[64286,64286],[65024,65039],[65056,65071],[65279,65279],[65529,65531]],n=[[66045,66045],[66272,66272],[66422,66426],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[68325,68326],[68900,68903],[69446,69456],[69633,69633],[69688,69702],[69759,69761],[69811,69814],[69817,69818],[69821,69821],[69837,69837],[69888,69890],[69927,69931],[69933,69940],[70003,70003],[70016,70017],[70070,70078],[70089,70092],[70191,70193],[70196,70196],[70198,70199],[70206,70206],[70367,70367],[70371,70378],[70400,70401],[70459,70460],[70464,70464],[70502,70508],[70512,70516],[70712,70719],[70722,70724],[70726,70726],[70750,70750],[70835,70840],[70842,70842],[70847,70848],[70850,70851],[71090,71093],[71100,71101],[71103,71104],[71132,71133],[71219,71226],[71229,71229],[71231,71232],[71339,71339],[71341,71341],[71344,71349],[71351,71351],[71453,71455],[71458,71461],[71463,71467],[71727,71735],[71737,71738],[72148,72151],[72154,72155],[72160,72160],[72193,72202],[72243,72248],[72251,72254],[72263,72263],[72273,72278],[72281,72283],[72330,72342],[72344,72345],[72752,72758],[72760,72765],[72767,72767],[72850,72871],[72874,72880],[72882,72883],[72885,72886],[73009,73014],[73018,73018],[73020,73021],[73023,73029],[73031,73031],[73104,73105],[73109,73109],[73111,73111],[73459,73460],[78896,78904],[92912,92916],[92976,92982],[94031,94031],[94095,94098],[113821,113822],[113824,113827],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[121344,121398],[121403,121452],[121461,121461],[121476,121476],[121499,121503],[121505,121519],[122880,122886],[122888,122904],[122907,122913],[122915,122916],[122918,122922],[123184,123190],[123628,123631],[125136,125142],[125252,125258],[917505,917505],[917536,917631],[917760,917999]],r=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,11929],[11931,12019],[12032,12245],[12272,12283],[12288,12329],[12334,12350],[12353,12438],[12443,12543],[12549,12591],[12593,12686],[12688,12730],[12736,12771],[12784,12830],[12832,12871],[12880,19903],[19968,42124],[42128,42182],[43360,43388],[44032,55203],[63744,64255],[65040,65049],[65072,65106],[65108,65126],[65128,65131],[65281,65376],[65504,65510]],i=[[94176,94179],[94208,100343],[100352,101106],[110592,110878],[110928,110930],[110948,110951],[110960,111355],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127490],[127504,127547],[127552,127560],[127568,127569],[127584,127589],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128725],[128747,128748],[128756,128762],[128992,129003],[129293,129393],[129395,129398],[129402,129442],[129445,129450],[129454,129482],[129485,129535],[129648,129651],[129656,129658],[129664,129666],[129680,129685],[131072,196605],[196608,262141]];let d;function c(e,t){let o,n=0,r=t.length-1;if(e<t[0][0]||e>t[r][1])return!1;for(;r>=n;)if(o=n+r>>1,e>t[o][1])n=o+1;else{if(!(e<t[o][0]))return!0;r=o-1}return!1}t.UnicodeV11=class{constructor(){if(this.version="11",!d){d=new Uint8Array(65536),d.fill(1),d[0]=0,d.fill(0,1,32),d.fill(0,127,160);for(let e=0;e<o.length;++e)d.fill(0,o[e][0],o[e][1]+1);for(let e=0;e<r.length;++e)d.fill(2,r[e][0],r[e][1]+1)}}wcwidth(e){return e<32?0:e<127?1:e<65536?d[e]:c(e,n)?0:c(e,i)?2:1}}}},t={};function o(n){var r=t[n];if(void 0!==r)return r.exports;var i=t[n]={exports:{}};return e[n](i,i.exports,o),i.exports}var n={};return(()=>{var e=n;Object.defineProperty(e,"__esModule",{value:!0}),e.Unicode11Addon=void 0;const t=o(433);e.Unicode11Addon=class{activate(e){e.unicode.register(new t.UnicodeV11)}dispose(){}}})(),n})()));
|
|
8
|
+
//# sourceMappingURL=xterm-addon-unicode11.js.map
|