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,377 @@
1
+ """
2
+ Qt stylesheet generation from themes.
3
+ """
4
+
5
+ from nterm.theme.engine import Theme
6
+
7
+
8
+ def generate_stylesheet(theme: Theme) -> str:
9
+ """
10
+ Generate Qt stylesheet from theme.
11
+
12
+ Args:
13
+ theme: Theme to generate stylesheet from
14
+
15
+ Returns:
16
+ Qt stylesheet string
17
+ """
18
+ bg = theme.background_color
19
+ fg = theme.foreground_color
20
+ border = theme.border_color
21
+ accent = theme.accent_color
22
+
23
+ # Derive additional colors
24
+ bg_lighter = _lighten(bg, 0.1)
25
+ bg_darker = _darken(bg, 0.1)
26
+ accent_hover = _lighten(accent, 0.1)
27
+ accent_pressed = _darken(accent, 0.1)
28
+
29
+ # Get terminal colors for additional UI elements
30
+ tc = theme.terminal_colors
31
+ red = tc.get("red", "#f38ba8")
32
+ green = tc.get("green", "#a6e3a1")
33
+ yellow = tc.get("yellow", "#f9e2af")
34
+
35
+ return f"""
36
+ /* Main window and containers */
37
+ QMainWindow, QDialog, QWidget {{
38
+ background-color: {bg};
39
+ color: {fg};
40
+ }}
41
+
42
+ /* Splitter */
43
+ QSplitter::handle {{
44
+ background-color: {border};
45
+ }}
46
+ QSplitter::handle:horizontal {{
47
+ width: 2px;
48
+ }}
49
+ QSplitter::handle:vertical {{
50
+ height: 2px;
51
+ }}
52
+
53
+ /* Menu bar */
54
+ QMenuBar {{
55
+ background-color: {bg};
56
+ color: {fg};
57
+ border-bottom: 1px solid {border};
58
+ padding: 2px;
59
+ }}
60
+ QMenuBar::item {{
61
+ padding: 4px 8px;
62
+ background-color: transparent;
63
+ }}
64
+ QMenuBar::item:selected {{
65
+ background-color: {bg_lighter};
66
+ border-radius: 4px;
67
+ }}
68
+
69
+ /* Menus */
70
+ QMenu {{
71
+ background-color: {bg};
72
+ color: {fg};
73
+ border: 1px solid {border};
74
+ border-radius: 4px;
75
+ padding: 4px;
76
+ }}
77
+ QMenu::item {{
78
+ padding: 6px 24px 6px 8px;
79
+ border-radius: 4px;
80
+ }}
81
+ QMenu::item:selected {{
82
+ background-color: {accent};
83
+ color: {bg};
84
+ }}
85
+ QMenu::separator {{
86
+ height: 1px;
87
+ background-color: {border};
88
+ margin: 4px 8px;
89
+ }}
90
+
91
+ /* Tab widget */
92
+ QTabWidget::pane {{
93
+ border: 1px solid {border};
94
+ border-radius: 4px;
95
+ background-color: {bg};
96
+ }}
97
+ QTabBar::tab {{
98
+ background-color: {bg_darker};
99
+ color: {fg};
100
+ border: 1px solid {border};
101
+ border-bottom: none;
102
+ padding: 6px 12px;
103
+ margin-right: 2px;
104
+ border-top-left-radius: 4px;
105
+ border-top-right-radius: 4px;
106
+ }}
107
+ QTabBar::tab:selected {{
108
+ background-color: {bg};
109
+ border-bottom: 1px solid {bg};
110
+ }}
111
+ QTabBar::tab:hover:!selected {{
112
+ background-color: {bg_lighter};
113
+ }}
114
+ QTabBar::close-button {{
115
+ image: none;
116
+ subcontrol-position: right;
117
+ }}
118
+ QTabBar::close-button:hover {{
119
+ background-color: {red};
120
+ border-radius: 2px;
121
+ }}
122
+
123
+ /* Tree widget */
124
+ QTreeWidget, QTreeView {{
125
+ background-color: {bg};
126
+ color: {fg};
127
+ border: 1px solid {border};
128
+ border-radius: 4px;
129
+ outline: none;
130
+ }}
131
+ QTreeWidget::item, QTreeView::item {{
132
+ padding: 4px;
133
+ border-radius: 4px;
134
+ }}
135
+ QTreeWidget::item:hover, QTreeView::item:hover {{
136
+ background-color: {bg_lighter};
137
+ }}
138
+ QTreeWidget::item:selected, QTreeView::item:selected {{
139
+ background-color: {accent};
140
+ color: {bg};
141
+ }}
142
+ QTreeWidget::branch {{
143
+ background-color: {bg};
144
+ }}
145
+
146
+ /* Line edit */
147
+ QLineEdit {{
148
+ background-color: {bg_darker};
149
+ color: {fg};
150
+ border: 1px solid {border};
151
+ border-radius: 4px;
152
+ padding: 6px 8px;
153
+ selection-background-color: {accent};
154
+ selection-color: {bg};
155
+ }}
156
+ QLineEdit:focus {{
157
+ border-color: {accent};
158
+ }}
159
+ QLineEdit:disabled {{
160
+ background-color: {bg};
161
+ color: {border};
162
+ }}
163
+
164
+ /* Spin box */
165
+ QSpinBox {{
166
+ background-color: {bg_darker};
167
+ color: {fg};
168
+ border: 1px solid {border};
169
+ border-radius: 4px;
170
+ padding: 4px 8px;
171
+ }}
172
+ QSpinBox:focus {{
173
+ border-color: {accent};
174
+ }}
175
+ QSpinBox::up-button, QSpinBox::down-button {{
176
+ background-color: {bg_lighter};
177
+ border: none;
178
+ width: 16px;
179
+ }}
180
+ QSpinBox::up-button:hover, QSpinBox::down-button:hover {{
181
+ background-color: {accent};
182
+ }}
183
+
184
+ /* Combo box */
185
+ QComboBox {{
186
+ background-color: {bg_darker};
187
+ color: {fg};
188
+ border: 1px solid {border};
189
+ border-radius: 4px;
190
+ padding: 6px 8px;
191
+ min-width: 100px;
192
+ }}
193
+ QComboBox:focus {{
194
+ border-color: {accent};
195
+ }}
196
+ QComboBox::drop-down {{
197
+ border: none;
198
+ width: 20px;
199
+ }}
200
+ QComboBox::down-arrow {{
201
+ width: 12px;
202
+ height: 12px;
203
+ }}
204
+ QComboBox QAbstractItemView {{
205
+ background-color: {bg};
206
+ color: {fg};
207
+ border: 1px solid {border};
208
+ selection-background-color: {accent};
209
+ selection-color: {bg};
210
+ }}
211
+
212
+ /* Push button */
213
+ QPushButton {{
214
+ background-color: {bg_lighter};
215
+ color: {fg};
216
+ border: 1px solid {border};
217
+ border-radius: 4px;
218
+ padding: 6px 16px;
219
+ min-width: 60px;
220
+ }}
221
+ QPushButton:hover {{
222
+ background-color: {accent};
223
+ color: {bg};
224
+ border-color: {accent};
225
+ }}
226
+ QPushButton:pressed {{
227
+ background-color: {accent_pressed};
228
+ }}
229
+ QPushButton:disabled {{
230
+ background-color: {bg_darker};
231
+ color: {border};
232
+ border-color: {bg_darker};
233
+ }}
234
+ QPushButton:default {{
235
+ border-color: {accent};
236
+ }}
237
+
238
+ /* Group box */
239
+ QGroupBox {{
240
+ color: {fg};
241
+ border: 1px solid {border};
242
+ border-radius: 4px;
243
+ margin-top: 8px;
244
+ padding-top: 8px;
245
+ }}
246
+ QGroupBox::title {{
247
+ subcontrol-origin: margin;
248
+ subcontrol-position: top left;
249
+ padding: 0 4px;
250
+ color: {fg};
251
+ }}
252
+
253
+ /* Labels */
254
+ QLabel {{
255
+ color: {fg};
256
+ background-color: transparent;
257
+ }}
258
+
259
+ /* Scroll bars */
260
+ QScrollBar:vertical {{
261
+ background-color: {bg};
262
+ width: 12px;
263
+ border-radius: 6px;
264
+ }}
265
+ QScrollBar::handle:vertical {{
266
+ background-color: {border};
267
+ border-radius: 6px;
268
+ min-height: 20px;
269
+ }}
270
+ QScrollBar::handle:vertical:hover {{
271
+ background-color: {accent};
272
+ }}
273
+ QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
274
+ height: 0;
275
+ }}
276
+ QScrollBar:horizontal {{
277
+ background-color: {bg};
278
+ height: 12px;
279
+ border-radius: 6px;
280
+ }}
281
+ QScrollBar::handle:horizontal {{
282
+ background-color: {border};
283
+ border-radius: 6px;
284
+ min-width: 20px;
285
+ }}
286
+ QScrollBar::handle:horizontal:hover {{
287
+ background-color: {accent};
288
+ }}
289
+ QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{
290
+ width: 0;
291
+ }}
292
+
293
+ /* Check box */
294
+ QCheckBox {{
295
+ color: {fg};
296
+ spacing: 8px;
297
+ }}
298
+ QCheckBox::indicator {{
299
+ width: 16px;
300
+ height: 16px;
301
+ border: 1px solid {border};
302
+ border-radius: 4px;
303
+ background-color: {bg_darker};
304
+ }}
305
+ QCheckBox::indicator:checked {{
306
+ background-color: {accent};
307
+ border-color: {accent};
308
+ }}
309
+ QCheckBox::indicator:hover {{
310
+ border-color: {accent};
311
+ }}
312
+
313
+ /* Tool tip */
314
+ QToolTip {{
315
+ background-color: {bg_lighter};
316
+ color: {fg};
317
+ border: 1px solid {border};
318
+ border-radius: 4px;
319
+ padding: 4px 8px;
320
+ }}
321
+
322
+ /* Message box */
323
+ QMessageBox {{
324
+ background-color: {bg};
325
+ }}
326
+ QMessageBox QLabel {{
327
+ color: {fg};
328
+ }}
329
+
330
+ /* Dialog button box */
331
+ QDialogButtonBox {{
332
+ button-layout: 3;
333
+ }}
334
+
335
+ /* Frame */
336
+ QFrame {{
337
+ background-color: transparent;
338
+ }}
339
+
340
+ /* Header view (for tree/table) */
341
+ QHeaderView::section {{
342
+ background-color: {bg_darker};
343
+ color: {fg};
344
+ border: none;
345
+ border-right: 1px solid {border};
346
+ padding: 4px 8px;
347
+ }}
348
+ """
349
+
350
+
351
+ def _hex_to_rgb(hex_color: str) -> tuple[int, int, int]:
352
+ """Convert hex color to RGB tuple."""
353
+ hex_color = hex_color.lstrip('#')
354
+ return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4))
355
+
356
+
357
+ def _rgb_to_hex(r: int, g: int, b: int) -> str:
358
+ """Convert RGB to hex color."""
359
+ return f"#{r:02x}{g:02x}{b:02x}"
360
+
361
+
362
+ def _lighten(hex_color: str, amount: float) -> str:
363
+ """Lighten a hex color by amount (0-1)."""
364
+ r, g, b = _hex_to_rgb(hex_color)
365
+ r = min(255, int(r + (255 - r) * amount))
366
+ g = min(255, int(g + (255 - g) * amount))
367
+ b = min(255, int(b + (255 - b) * amount))
368
+ return _rgb_to_hex(r, g, b)
369
+
370
+
371
+ def _darken(hex_color: str, amount: float) -> str:
372
+ """Darken a hex color by amount (0-1)."""
373
+ r, g, b = _hex_to_rgb(hex_color)
374
+ r = max(0, int(r * (1 - amount)))
375
+ g = max(0, int(g * (1 - amount)))
376
+ b = max(0, int(b * (1 - amount)))
377
+ return _rgb_to_hex(r, g, b)
File without changes
@@ -0,0 +1,36 @@
1
+ name: default
2
+
3
+ terminal_colors:
4
+ background: "#1e1e2e"
5
+ foreground: "#cdd6f4"
6
+ cursor: "#f5e0dc"
7
+ cursorAccent: "#1e1e2e"
8
+ selectionBackground: "#585b70"
9
+ selectionForeground: "#cdd6f4"
10
+ black: "#45475a"
11
+ red: "#f38ba8"
12
+ green: "#a6e3a1"
13
+ yellow: "#f9e2af"
14
+ blue: "#89b4fa"
15
+ magenta: "#f5c2e7"
16
+ cyan: "#94e2d5"
17
+ white: "#bac2de"
18
+ brightBlack: "#585b70"
19
+ brightRed: "#f38ba8"
20
+ brightGreen: "#a6e3a1"
21
+ brightYellow: "#f9e2af"
22
+ brightBlue: "#89b4fa"
23
+ brightMagenta: "#f5c2e7"
24
+ brightCyan: "#94e2d5"
25
+ brightWhite: "#a6adc8"
26
+
27
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace"
28
+ font_size: 14
29
+
30
+ background_color: "#1e1e2e"
31
+ foreground_color: "#cdd6f4"
32
+ border_color: "#313244"
33
+ accent_color: "#89b4fa"
34
+
35
+ overlay_background: "rgba(30, 30, 46, 0.9)"
36
+ overlay_text_color: "#cdd6f4"
@@ -0,0 +1,36 @@
1
+ name: dracula
2
+
3
+ terminal_colors:
4
+ background: "#282a36"
5
+ foreground: "#f8f8f2"
6
+ cursor: "#f8f8f2"
7
+ cursorAccent: "#282a36"
8
+ selectionBackground: "#44475a"
9
+ selectionForeground: "#f8f8f2"
10
+ black: "#21222c"
11
+ red: "#ff5555"
12
+ green: "#50fa7b"
13
+ yellow: "#f1fa8c"
14
+ blue: "#bd93f9"
15
+ magenta: "#ff79c6"
16
+ cyan: "#8be9fd"
17
+ white: "#f8f8f2"
18
+ brightBlack: "#6272a4"
19
+ brightRed: "#ff6e6e"
20
+ brightGreen: "#69ff94"
21
+ brightYellow: "#ffffa5"
22
+ brightBlue: "#d6acff"
23
+ brightMagenta: "#ff92df"
24
+ brightCyan: "#a4ffff"
25
+ brightWhite: "#ffffff"
26
+
27
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace"
28
+ font_size: 14
29
+
30
+ background_color: "#282a36"
31
+ foreground_color: "#f8f8f2"
32
+ border_color: "#44475a"
33
+ accent_color: "#bd93f9"
34
+
35
+ overlay_background: "rgba(40, 42, 54, 0.9)"
36
+ overlay_text_color: "#f8f8f2"
@@ -0,0 +1,36 @@
1
+ name: gruvbox_dark
2
+
3
+ terminal_colors:
4
+ background: "#282828"
5
+ foreground: "#ebdbb2"
6
+ cursor: "#ebdbb2"
7
+ cursorAccent: "#282828"
8
+ selectionBackground: "#504945"
9
+ selectionForeground: "#ebdbb2"
10
+ black: "#282828"
11
+ red: "#cc241d"
12
+ green: "#98971a"
13
+ yellow: "#d79921"
14
+ blue: "#458588"
15
+ magenta: "#b16286"
16
+ cyan: "#689d6a"
17
+ white: "#a89984"
18
+ brightBlack: "#928374"
19
+ brightRed: "#fb4934"
20
+ brightGreen: "#b8bb26"
21
+ brightYellow: "#fabd2f"
22
+ brightBlue: "#83a598"
23
+ brightMagenta: "#d3869b"
24
+ brightCyan: "#8ec07c"
25
+ brightWhite: "#ebdbb2"
26
+
27
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace"
28
+ font_size: 14
29
+
30
+ background_color: "#282828"
31
+ foreground_color: "#ebdbb2"
32
+ border_color: "#3c3836"
33
+ accent_color: "#d79921"
34
+
35
+ overlay_background: "rgba(40, 40, 40, 0.9)"
36
+ overlay_text_color: "#ebdbb2"
@@ -0,0 +1,38 @@
1
+ name: gruvbox_hybrid
2
+
3
+ # Terminal colors - Gruvbox LIGHT for high-contrast terminal
4
+ terminal_colors:
5
+ background: "#fbf1c7"
6
+ foreground: "#3c3836"
7
+ cursor: "#3c3836"
8
+ cursorAccent: "#fbf1c7"
9
+ selectionBackground: "#d5c4a1"
10
+ selectionForeground: "#3c3836"
11
+ black: "#fbf1c7"
12
+ red: "#cc241d"
13
+ green: "#98971a"
14
+ yellow: "#d79921"
15
+ blue: "#458588"
16
+ magenta: "#b16286"
17
+ cyan: "#689d6a"
18
+ white: "#7c6f64"
19
+ brightBlack: "#928374"
20
+ brightRed: "#9d0006"
21
+ brightGreen: "#79740e"
22
+ brightYellow: "#b57614"
23
+ brightBlue: "#076678"
24
+ brightMagenta: "#8f3f71"
25
+ brightCyan: "#427b58"
26
+ brightWhite: "#3c3836"
27
+
28
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace"
29
+ font_size: 14
30
+
31
+ # Widget styling - Gruvbox DARK for comfortable UI chrome
32
+ background_color: "#282828"
33
+ foreground_color: "#ebdbb2"
34
+ border_color: "#3c3836"
35
+ accent_color: "#d79921"
36
+
37
+ overlay_background: "rgba(40, 40, 40, 0.9)"
38
+ overlay_text_color: "#ebdbb2"
@@ -0,0 +1,36 @@
1
+ name: gruvbox_light
2
+
3
+ terminal_colors:
4
+ background: "#fbf1c7"
5
+ foreground: "#3c3836"
6
+ cursor: "#3c3836"
7
+ cursorAccent: "#fbf1c7"
8
+ selectionBackground: "#d5c4a1"
9
+ selectionForeground: "#3c3836"
10
+ black: "#fbf1c7"
11
+ red: "#cc241d"
12
+ green: "#98971a"
13
+ yellow: "#d79921"
14
+ blue: "#458588"
15
+ magenta: "#b16286"
16
+ cyan: "#689d6a"
17
+ white: "#7c6f64"
18
+ brightBlack: "#928374"
19
+ brightRed: "#9d0006"
20
+ brightGreen: "#79740e"
21
+ brightYellow: "#b57614"
22
+ brightBlue: "#076678"
23
+ brightMagenta: "#8f3f71"
24
+ brightCyan: "#427b58"
25
+ brightWhite: "#3c3836"
26
+
27
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace"
28
+ font_size: 14
29
+
30
+ background_color: "#fbf1c7"
31
+ foreground_color: "#3c3836"
32
+ border_color: "#d5c4a1"
33
+ accent_color: "#b57614"
34
+
35
+ overlay_background: "rgba(251, 241, 199, 0.95)"
36
+ overlay_text_color: "#3c3836"
@@ -0,0 +1,32 @@
1
+ """
2
+ Credential vault - encrypted credential storage with UI.
3
+ """
4
+
5
+ from .store import CredentialStore, StoredCredential
6
+ from .resolver import CredentialResolver, NoCredentialError
7
+ from .keychain import KeychainIntegration, KEYRING_AVAILABLE
8
+ from .manager_ui import (
9
+ CredentialManagerWidget,
10
+ CredentialDialog,
11
+ UnlockDialog,
12
+ ManagerTheme,
13
+ run_standalone,
14
+ )
15
+
16
+ __all__ = [
17
+ # Store
18
+ "CredentialStore",
19
+ "StoredCredential",
20
+ # Resolver
21
+ "CredentialResolver",
22
+ "NoCredentialError",
23
+ # Keychain
24
+ "KeychainIntegration",
25
+ "KEYRING_AVAILABLE",
26
+ # UI
27
+ "CredentialManagerWidget",
28
+ "CredentialDialog",
29
+ "UnlockDialog",
30
+ "ManagerTheme",
31
+ "run_standalone",
32
+ ]