pyqt-code-editor 0.0.36__tar.gz → 0.0.38__tar.gz

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 (79) hide show
  1. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/PKG-INFO +1 -1
  2. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/__init__.py +1 -1
  3. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/_settings.py +13 -1
  4. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/find_in_files.py +0 -4
  5. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/project_explorer.py +20 -6
  6. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/search_replace_frame.py +41 -19
  7. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/ruff.py +0 -1
  8. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/COPYING +0 -0
  9. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyproject.toml +0 -0
  10. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/app.py +0 -0
  11. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/__init__.py +0 -0
  12. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/code_editors.py +0 -0
  13. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/languages/__init__.py +0 -0
  14. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/languages/generic.py +0 -0
  15. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/languages/markdown.py +0 -0
  16. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/languages/python.py +0 -0
  17. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/code_editors/languages/text.py +0 -0
  18. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/__init__.py +0 -0
  19. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/editor_panel.py +0 -0
  20. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/jupyter_console.py +0 -0
  21. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/settings_panel.py +0 -0
  22. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/sigmund.py +0 -0
  23. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/components/workspace_explorer.py +0 -0
  24. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/environment_manager.py +0 -0
  25. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/__init__.py +0 -0
  26. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/auto_indent.py +0 -0
  27. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/auto_pair.py +0 -0
  28. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/base.py +0 -0
  29. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/check.py +0 -0
  30. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/comment.py +0 -0
  31. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/complete.py +0 -0
  32. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/execute.py +0 -0
  33. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/file_link.py +0 -0
  34. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/line_number.py +0 -0
  35. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/python_auto_indent.py +0 -0
  36. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/search_replace.py +0 -0
  37. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/shortcuts.py +0 -0
  38. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/smart_backspace_delete.py +0 -0
  39. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/symbols.py +0 -0
  40. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/theme.py +0 -0
  41. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/widgets/__init__.py +0 -0
  42. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/mixins/zoom.py +0 -0
  43. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/sigmund-analyst.png +0 -0
  44. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/signal_router.py +0 -0
  45. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
  46. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
  47. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/syntax_highlighters/languages/generic.py +0 -0
  48. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/syntax_highlighters/languages/python.py +0 -0
  49. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +0 -0
  50. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/themes.py +0 -0
  51. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/__init__.py +0 -0
  52. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/languages/__init__.py +0 -0
  53. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/languages/python/__init__.py +0 -0
  54. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/languages/python/_auto_indent.py +0 -0
  55. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/languages/python/_extract_cells.py +0 -0
  56. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/utils/languages/python/_mask_str_in_code.py +0 -0
  57. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/watchdog.py +0 -0
  58. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/__init__.py +0 -0
  59. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/calltip_widget.py +0 -0
  60. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/completion_popup.py +0 -0
  61. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/dock.py +0 -0
  62. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/quick_open_dialog.py +0 -0
  63. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/quick_open_file_dialog.py +0 -0
  64. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/quick_symbol_dialog.py +0 -0
  65. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/tab_splitter.py +0 -0
  66. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/widgets/tabbed_editor.py +0 -0
  67. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/__init__.py +0 -0
  68. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/languages/__init__.py +0 -0
  69. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/languages/generic.py +0 -0
  70. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/languages/python.py +0 -0
  71. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/manager.py +0 -0
  72. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/process.py +0 -0
  73. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/__init__.py +0 -0
  74. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/codestral.py +0 -0
  75. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/jedi.py +0 -0
  76. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/sigmund.py +0 -0
  77. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/providers/symbol.py +0 -0
  78. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/pyqt_code_editor/worker/settings.py +0 -0
  79. {pyqt_code_editor-0.0.36 → pyqt_code_editor-0.0.38}/readme.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqt_code_editor
3
- Version: 0.0.36
3
+ Version: 0.0.38
4
4
  Summary: Fully featured code-editor widgets for PyQt
5
5
  Keywords: code editor,pyqt,ide
6
6
  Author-email: Sebastiaan Mathôt <s.mathot@cogsci.nl>
@@ -2,4 +2,4 @@
2
2
 
3
3
  from ._settings import settings
4
4
 
5
- __version__ = '0.0.36'
5
+ __version__ = '0.0.38'
@@ -228,11 +228,23 @@ class Settings(QObject):
228
228
  if self.font_family != 'default':
229
229
  return
230
230
  from .utils import get_first_available_font
231
+
231
232
  self.font_family = get_first_available_font(
232
233
  ['Ubuntu Mono', 'Liberation Mono', 'DejaVu Sans Mono', 'Courier New',
233
234
  'monospace'])
235
+
236
+ # Fallback if no font was found
237
+ if self.font_family is None:
238
+ import platform
239
+ system = platform.system()
240
+ if system == 'Windows':
241
+ self.font_family = 'Consolas' # Available on Windows Vista+
242
+ elif system == 'Darwin': # macOS
243
+ self.font_family = 'Menlo' # Default monospace on macOS
244
+ else: # Linux and other Unix-like systems
245
+ self.font_family = 'monospace' # Generic monospace fallback
246
+
234
247
  logger.info(f'setting font family to {self.font_family}')
235
248
 
236
-
237
249
  # Create the singleton instance
238
250
  settings = Settings()
@@ -269,10 +269,6 @@ class FindInFiles(QDockWidget):
269
269
  self._open_file(path, line_no)
270
270
 
271
271
  def _open_file(self, path, line_no=0):
272
- """
273
- Dummy method: In production, integrate with your editor logic.
274
- """
275
- print(f"Opening file: {path}, line {line_no}")
276
272
  self.open_file_requested.emit(path, line_no)
277
273
 
278
274
  def closeEvent(self, event):
@@ -212,12 +212,26 @@ class ProjectExplorer(QDockWidget):
212
212
  self._setup_shortcuts()
213
213
 
214
214
  def _setup_shortcuts(self):
215
- """Set up global keyboard shortcuts for common actions."""
216
- QShortcut(QKeySequence("F2"), self, activated=lambda: self._handle_rename_shortcut())
217
- QShortcut(QKeySequence.Delete, self, activated=lambda: self._handle_delete_shortcut())
218
- QShortcut(QKeySequence.Cut, self, activated=lambda: self._handle_cut_shortcut())
219
- QShortcut(QKeySequence.Copy, self, activated=lambda: self._handle_copy_shortcut())
220
- QShortcut(QKeySequence.Paste, self, activated=lambda: self._handle_paste_shortcut())
215
+ """Set up keyboard shortcuts for common actions."""
216
+ shortcut_f2 = QShortcut(QKeySequence("F2"), self)
217
+ shortcut_f2.setContext(Qt.WidgetWithChildrenShortcut)
218
+ shortcut_f2.activated.connect(lambda: self._handle_rename_shortcut())
219
+
220
+ shortcut_delete = QShortcut(QKeySequence.Delete, self)
221
+ shortcut_delete.setContext(Qt.WidgetWithChildrenShortcut)
222
+ shortcut_delete.activated.connect(lambda: self._handle_delete_shortcut())
223
+
224
+ shortcut_cut = QShortcut(QKeySequence.Cut, self)
225
+ shortcut_cut.setContext(Qt.WidgetWithChildrenShortcut)
226
+ shortcut_cut.activated.connect(lambda: self._handle_cut_shortcut())
227
+
228
+ shortcut_copy = QShortcut(QKeySequence.Copy, self)
229
+ shortcut_copy.setContext(Qt.WidgetWithChildrenShortcut)
230
+ shortcut_copy.activated.connect(lambda: self._handle_copy_shortcut())
231
+
232
+ shortcut_paste = QShortcut(QKeySequence.Paste, self)
233
+ shortcut_paste.setContext(Qt.WidgetWithChildrenShortcut)
234
+ shortcut_paste.activated.connect(lambda: self._handle_paste_shortcut())
221
235
 
222
236
  def _handle_rename_shortcut(self):
223
237
  """Handle F2 shortcut for rename."""
@@ -3,9 +3,10 @@ from qtpy.QtWidgets import (
3
3
  QLineEdit, QPushButton, QCheckBox, QLabel
4
4
  )
5
5
  from qtpy.QtCore import Qt, Signal
6
+ from qtpy.QtGui import QKeyEvent
6
7
  from .. import settings
7
8
 
8
-
9
+
9
10
  class SearchReplaceFrame(QFrame):
10
11
  """
11
12
  A small widget containing 'Find' and optionally 'Replace' fields,
@@ -16,10 +17,10 @@ class SearchReplaceFrame(QFrame):
16
17
  findPrevRequested = Signal()
17
18
  replaceOneRequested = Signal()
18
19
  replaceAllRequested = Signal()
19
-
20
+
20
21
  def __init__(self, parent=None):
21
22
  super().__init__(parent)
22
-
23
+
23
24
  self.setFrameShape(QFrame.StyledPanel)
24
25
  self.setFrameShadow(QFrame.Raised)
25
26
  editor = parent
@@ -51,14 +52,14 @@ class SearchReplaceFrame(QFrame):
51
52
  }}
52
53
  ''')
53
54
  self.setWindowFlags(Qt.SubWindow | Qt.FramelessWindowHint)
54
-
55
+
55
56
  # Layout
56
57
  layout = QVBoxLayout(self)
57
58
  layout.setContentsMargins(5, 5, 5, 5)
58
-
59
+
59
60
  # Find row
60
61
  findRow = QHBoxLayout()
61
-
62
+
62
63
  self.findLabel = QLabel("Find:", self)
63
64
  self.matchCountLabel = QLabel("0 of 0", self)
64
65
  self.findEdit = QLineEdit(self)
@@ -68,10 +69,10 @@ class SearchReplaceFrame(QFrame):
68
69
  self.regexBox.setToolTip("Use Regular Expressions")
69
70
  self.wholeWordBox = QCheckBox("\\b", self)
70
71
  self.wholeWordBox.setToolTip("Match Whole Word")
71
-
72
+
72
73
  self.findNextBtn = QPushButton("Next", self)
73
74
  self.findPrevBtn = QPushButton("Prev", self)
74
-
75
+
75
76
  findRow.addWidget(self.findLabel)
76
77
  findRow.addWidget(self.findEdit)
77
78
  findRow.addWidget(self.matchCountLabel)
@@ -80,34 +81,56 @@ class SearchReplaceFrame(QFrame):
80
81
  findRow.addWidget(self.wholeWordBox)
81
82
  findRow.addWidget(self.findNextBtn)
82
83
  findRow.addWidget(self.findPrevBtn)
83
-
84
+
84
85
  layout.addLayout(findRow)
85
-
86
+
86
87
  # Replace row
87
88
  replaceRow = QHBoxLayout()
88
89
  self.replaceLabel = QLabel("Replace:", self)
89
90
  self.replaceEdit = QLineEdit(self)
90
91
  self.replaceBtn = QPushButton("Replace", self)
91
92
  self.replaceAllBtn = QPushButton("Replace All", self)
92
-
93
+
93
94
  replaceRow.addWidget(self.replaceLabel)
94
95
  replaceRow.addWidget(self.replaceEdit)
95
96
  replaceRow.addWidget(self.replaceBtn)
96
97
  replaceRow.addWidget(self.replaceAllBtn)
97
-
98
+
98
99
  layout.addLayout(replaceRow)
99
-
100
+
100
101
  self.replaceRowWidget = replaceRow # Keep reference to manage visibility
101
-
102
+
102
103
  # Connections
103
104
  self.findNextBtn.clicked.connect(self.findNextRequested)
104
105
  self.findPrevBtn.clicked.connect(self.findPrevRequested)
105
106
  self.replaceBtn.clicked.connect(self.replaceOneRequested)
106
107
  self.replaceAllBtn.clicked.connect(self.replaceAllRequested)
107
-
108
+
109
+ # Install event filter to handle Shift+Enter
110
+ self.findEdit.installEventFilter(self)
111
+ self.replaceEdit.installEventFilter(self)
112
+
108
113
  # Default: searching only, so hide the "replace" row
109
114
  self.showSearchOnly()
110
-
115
+
116
+ def eventFilter(self, obj, event):
117
+ """Handle key events for find and replace fields"""
118
+ if event.type() == QKeyEvent.KeyPress:
119
+ if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
120
+ if event.modifiers() & Qt.ShiftModifier:
121
+ # Shift+Enter triggers find previous
122
+ self.findPrevRequested.emit()
123
+ return True
124
+ elif obj == self.findEdit:
125
+ # Enter in find field triggers find next
126
+ self.findNextRequested.emit()
127
+ return True
128
+ elif obj == self.replaceEdit:
129
+ # Enter in replace field triggers replace
130
+ self.replaceOneRequested.emit()
131
+ return True
132
+ return super().eventFilter(obj, event)
133
+
111
134
  def showSearchOnly(self):
112
135
  # Hide replace UI
113
136
  self.replaceLabel.setVisible(False)
@@ -116,7 +139,7 @@ class SearchReplaceFrame(QFrame):
116
139
  self.replaceAllBtn.setVisible(False)
117
140
  self.adjustSize()
118
141
  self.resize(self.sizeHint())
119
-
142
+
120
143
  def showSearchReplace(self):
121
144
  # Show replace UI
122
145
  self.replaceLabel.setVisible(True)
@@ -124,5 +147,4 @@ class SearchReplaceFrame(QFrame):
124
147
  self.replaceBtn.setVisible(True)
125
148
  self.replaceAllBtn.setVisible(True)
126
149
  self.adjustSize()
127
- self.resize(self.sizeHint())
128
-
150
+ self.resize(self.sizeHint())
@@ -24,7 +24,6 @@ def ruff_check(code: str, prefix: str | None = None) -> list[dict]:
24
24
  with tempfile.NamedTemporaryFile(delete=False, suffix=".py", mode="w") as tmp_file:
25
25
  tmp_file.write(code)
26
26
  tmp_file_path = tmp_file.name
27
- print(tmp_file.name)
28
27
  cmd = ["ruff", "check", tmp_file_path, "--output-format", "json"]
29
28
 
30
29
  # Set creation flags for Windows to prevent console window from appearing