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.
Files changed (52) hide show
  1. nterm/__init__.py +54 -0
  2. nterm/__main__.py +619 -0
  3. nterm/askpass/__init__.py +22 -0
  4. nterm/askpass/server.py +393 -0
  5. nterm/config.py +158 -0
  6. nterm/connection/__init__.py +17 -0
  7. nterm/connection/profile.py +296 -0
  8. nterm/manager/__init__.py +29 -0
  9. nterm/manager/connect_dialog.py +322 -0
  10. nterm/manager/editor.py +262 -0
  11. nterm/manager/io.py +678 -0
  12. nterm/manager/models.py +346 -0
  13. nterm/manager/settings.py +264 -0
  14. nterm/manager/tree.py +493 -0
  15. nterm/resources.py +48 -0
  16. nterm/session/__init__.py +60 -0
  17. nterm/session/askpass_ssh.py +399 -0
  18. nterm/session/base.py +110 -0
  19. nterm/session/interactive_ssh.py +522 -0
  20. nterm/session/pty_transport.py +571 -0
  21. nterm/session/ssh.py +610 -0
  22. nterm/terminal/__init__.py +11 -0
  23. nterm/terminal/bridge.py +83 -0
  24. nterm/terminal/resources/terminal.html +253 -0
  25. nterm/terminal/resources/terminal.js +414 -0
  26. nterm/terminal/resources/xterm-addon-fit.min.js +8 -0
  27. nterm/terminal/resources/xterm-addon-unicode11.min.js +8 -0
  28. nterm/terminal/resources/xterm-addon-web-links.min.js +8 -0
  29. nterm/terminal/resources/xterm.css +209 -0
  30. nterm/terminal/resources/xterm.min.js +8 -0
  31. nterm/terminal/widget.py +380 -0
  32. nterm/theme/__init__.py +10 -0
  33. nterm/theme/engine.py +456 -0
  34. nterm/theme/stylesheet.py +377 -0
  35. nterm/theme/themes/clean.yaml +0 -0
  36. nterm/theme/themes/default.yaml +36 -0
  37. nterm/theme/themes/dracula.yaml +36 -0
  38. nterm/theme/themes/gruvbox_dark.yaml +36 -0
  39. nterm/theme/themes/gruvbox_hybrid.yaml +38 -0
  40. nterm/theme/themes/gruvbox_light.yaml +36 -0
  41. nterm/vault/__init__.py +32 -0
  42. nterm/vault/credential_manager.py +163 -0
  43. nterm/vault/keychain.py +135 -0
  44. nterm/vault/manager_ui.py +962 -0
  45. nterm/vault/profile.py +219 -0
  46. nterm/vault/resolver.py +250 -0
  47. nterm/vault/store.py +642 -0
  48. ntermqt-0.1.0.dist-info/METADATA +327 -0
  49. ntermqt-0.1.0.dist-info/RECORD +52 -0
  50. ntermqt-0.1.0.dist-info/WHEEL +5 -0
  51. ntermqt-0.1.0.dist-info/entry_points.txt +5 -0
  52. 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