pyqt-code-editor 0.0.65__tar.gz → 1.0.0__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 (91) hide show
  1. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/PKG-INFO +6 -4
  2. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/__init__.py +1 -1
  3. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/_settings.py +1 -0
  4. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/app.py +0 -19
  5. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/editor_panel.py +3 -0
  6. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/project_explorer.py +1 -0
  7. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/editor_workspace.py +8 -5
  8. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/sigmund.py +4 -2
  9. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/sigmund_analyst_chat_widget.py +19 -0
  10. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/sigmund_analyst_widget.py +14 -22
  11. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/codestral.py +1 -1
  12. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/readme.md +5 -3
  13. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/COPYING +0 -0
  14. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyproject.toml +0 -0
  15. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/__init__.py +0 -0
  16. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/code_editors.py +0 -0
  17. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/__init__.py +0 -0
  18. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/generic.py +0 -0
  19. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/javascript.py +0 -0
  20. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/markdown.py +0 -0
  21. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/python.py +0 -0
  22. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/code_editors/languages/text.py +0 -0
  23. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/__init__.py +0 -0
  24. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/find_in_files.py +0 -0
  25. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/jupyter_console/__init__.py +0 -0
  26. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/jupyter_console/jupyter_console.py +0 -0
  27. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/jupyter_console/jupyter_console_tab.py +0 -0
  28. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/jupyter_console/kernel_spec_manager.py +0 -0
  29. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/settings_panel.py +0 -0
  30. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/__init__.py +0 -0
  31. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/sigmund/confirm_run_code_dialog.py +0 -0
  32. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/components/workspace_explorer.py +0 -0
  33. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/environment_manager.py +0 -0
  34. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/__init__.py +0 -0
  35. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/auto_indent.py +0 -0
  36. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/auto_pair.py +0 -0
  37. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/base.py +0 -0
  38. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/check.py +0 -0
  39. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/comment.py +0 -0
  40. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/complete.py +0 -0
  41. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/execute.py +0 -0
  42. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/file_link.py +0 -0
  43. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/highlight_matching_brackets.py +0 -0
  44. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/line_number.py +0 -0
  45. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/merge_undo_actions.py +0 -0
  46. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/python_auto_indent.py +0 -0
  47. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/search_replace.py +0 -0
  48. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/shortcuts.py +0 -0
  49. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/smart_backspace_delete.py +0 -0
  50. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/symbols.py +0 -0
  51. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/theme.py +0 -0
  52. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/widgets/__init__.py +0 -0
  53. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/mixins/zoom.py +0 -0
  54. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/sigmund-analyst.png +0 -0
  55. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/signal_router.py +0 -0
  56. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
  57. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
  58. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/syntax_highlighters/languages/generic.py +0 -0
  59. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/syntax_highlighters/languages/python.py +0 -0
  60. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +0 -0
  61. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/themes.py +0 -0
  62. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/__init__.py +0 -0
  63. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/languages/__init__.py +0 -0
  64. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/languages/python/__init__.py +0 -0
  65. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/languages/python/_auto_indent.py +0 -0
  66. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/languages/python/_extract_cells.py +0 -0
  67. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/utils/languages/python/_mask_str_in_code.py +0 -0
  68. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/watchdog.py +0 -0
  69. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/__init__.py +0 -0
  70. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/calltip_widget.py +0 -0
  71. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/completion_popup.py +0 -0
  72. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/dock.py +0 -0
  73. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/quick_open_dialog.py +0 -0
  74. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/quick_open_file_dialog.py +0 -0
  75. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/quick_symbol_dialog.py +0 -0
  76. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/search_replace_frame.py +0 -0
  77. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/tab_splitter.py +0 -0
  78. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/widgets/tabbed_editor.py +0 -0
  79. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/__init__.py +0 -0
  80. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/languages/__init__.py +0 -0
  81. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/languages/generic.py +0 -0
  82. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/languages/python.py +0 -0
  83. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/manager.py +0 -0
  84. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/process.py +0 -0
  85. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/__init__.py +0 -0
  86. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/jedi.py +0 -0
  87. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/ruff.py +0 -0
  88. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/sigmund.py +0 -0
  89. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/symbol.py +0 -0
  90. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/providers/tree_sitter.py +0 -0
  91. {pyqt_code_editor-0.0.65 → pyqt_code_editor-1.0.0}/pyqt_code_editor/worker/settings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqt_code_editor
3
- Version: 0.0.65
3
+ Version: 1.0.0
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>
@@ -63,7 +63,7 @@ Features:
63
63
 
64
64
  ### SigmundAI for collaborative code editing
65
65
 
66
- You can work together with SigmundAI on the currently active document or selected text. To activate SigmundAI integration, simply log into <https://sigmundai.eu> (subscription required). Sigmund Analyst will then automatically connect to SigmundAI when you enable the Sigmund panel in the toolbar.
66
+ You can code together with SigmundAI. This works similarly to (and is an alternative to) apps such as Claude Code, Codex, and Mistral Vibe. To activate SigmundAI integration, simply log into <https://sigmundai.eu> (subscription required). Sigmund Analyst will then automatically connect to SigmundAI when you enable the Sigmund panel in the toolbar.
67
67
 
68
68
 
69
69
  ### Mistral Codestral for as-you-type suggestions
@@ -83,10 +83,12 @@ The easiest way to install Sigmund Analys on Windows is to install OpenSesame, w
83
83
 
84
84
  ### Linux/ Ubuntu
85
85
 
86
- The easiest way to install Sigmund Analyst on Linux is to download and run the installer script. This will create a Virtual Environment, pip install Sigmund Analyst and all dependencies into this environment, and add a Desktop file to your system to easily start Sigmund Analyst. To upgrade, simply run the script again.
86
+ The easiest way to install Sigmund Analyst on Linux is to download and run the installer script. This will create a Virtual Environment, pip install Sigmund Analyst and all dependencies into this environment, and add a Desktop file to your system to easily start Sigmund Analyst. To upgrade, simply run the script again. (This is actually the OpenSesame installation script, which is bundled with Sigmund Analyst.)
87
+
88
+ Currently, the Linux installer is tested on Ubuntu 26.04.
87
89
 
88
90
  ```
89
- bash <(curl -L https://raw.githubusercontent.com/open-cogsci/pyqt_code_editor/refs/heads/master/install_sigmund_analyst.sh)
91
+ bash <(curl -L https://github.com/open-cogsci/OpenSesame/raw/refs/heads/4.1/linux-installer.sh) --install
90
92
  ```
91
93
 
92
94
 
@@ -2,4 +2,4 @@
2
2
 
3
3
  from ._settings import settings
4
4
 
5
- __version__ = '0.0.65'
5
+ __version__ = '1.0.0'
@@ -121,6 +121,7 @@ class Settings(QObject):
121
121
 
122
122
  # Sigmund provider
123
123
  sigmund_review_actions = SettingProperty(True, "Sigmund")
124
+ sigmund_link_to_workspace = SettingProperty(True, "Sigmund")
124
125
  sigmund_max_context = SettingProperty(2000, "Sigmund")
125
126
  sigmund_fim_endpoint = SettingProperty('http://localhost:5000/code_completion/fim', "Sigmund")
126
127
  sigmund_token = SettingProperty(None, "Sigmund")
@@ -457,29 +457,10 @@ class SigmundAnalyst(QMainWindow):
457
457
  dlg.exec_()
458
458
 
459
459
 
460
- def handle_output(text, content):
461
- print('***')
462
- print(text)
463
- # print('---')
464
- # for part in content['parts']:
465
- # print(part)
466
- # print(content)
467
- print('***')
468
-
469
-
470
460
  def launch_app():
471
461
  app = QApplication(sys.argv)
472
462
  settings.set_font_family()
473
463
  window = SigmundAnalyst()
474
464
  window.show()
475
- window._jupyter_console.execution_complete.connect(handle_output)
476
465
  window._toggle_dock_widget(window._jupyter_console)
477
- # window._jupyter_console.execute_code('''
478
- # from matplotlib import pyplot as plt
479
- # plt.plot([1,2,3,4])
480
- # plt.show()
481
- # print(10)
482
- # # int('x')
483
- # 11
484
- # ''')
485
466
  sys.exit(app.exec_())
@@ -98,6 +98,9 @@ class EditorPanel(QWidget):
98
98
  logger.info(f"active editor = {editor}")
99
99
  self._active_editor = editor
100
100
  self._active_tab_widget = self._active_editor.parent().parent()
101
+ current_file = editor.code_editor_file_path
102
+ if current_file is not None:
103
+ settings.current_folder = os.path.dirname(current_file)
101
104
 
102
105
  def open_file(self, path=None, line_number=None):
103
106
  if path is not None:
@@ -169,6 +169,7 @@ class ProjectExplorer(QDockWidget):
169
169
  self._filter_proxy.setSourceModel(self._model)
170
170
 
171
171
  self._display_root = root_path or QDir.currentPath()
172
+ settings.current_folder = self._display_root
172
173
 
173
174
  # Create a container widget and layout, so we can have the treeview + an optional checkbox
174
175
  container_widget = QWidget(self)
@@ -89,12 +89,15 @@ class EditorWorkspace:
89
89
  editor_content = self._normalize_line_breaks(text_cursor.selectedText())
90
90
  else:
91
91
  editor_content = self._editor.toPlainText()
92
-
93
- if content in (editor_content, self.strip_content(editor_content)):
94
- return False
95
- return True
92
+ # Treat None content as empty
93
+ if content is None:
94
+ content = ''
95
+ # Compare line-by-line, ignoring trailing whitespace on each line
96
+ content_lines = [line.rstrip() for line in content.splitlines()]
97
+ editor_lines = [line.rstrip() for line in editor_content.splitlines()]
98
+ return content_lines != editor_lines
96
99
 
97
100
  def strip_content(self, content):
98
101
  if content is None:
99
102
  return ''
100
- return content
103
+ return content.strip()
@@ -10,11 +10,13 @@ class Sigmund(Dock):
10
10
  def __init__(self, parent, editor_panel):
11
11
  super().__init__('Sigmund', parent)
12
12
  self.setObjectName("sigmund")
13
- workspace = EditorWorkspace(editor_panel)
14
13
  self.sigmund_widget = SigmundAnalystWidget(
15
14
  self, editor_panel)
16
15
  self.sigmund_widget.setStyleSheet(f'font-size: {settings.font_size}pt')
17
- self.sigmund_widget.set_workspace_manager(workspace)
16
+ self.sigmund_widget._workspace_manager = EditorWorkspace(editor_panel)
17
+ if settings.sigmund_link_to_workspace:
18
+ self.sigmund_widget.set_workspace_manager(
19
+ self.sigmund_widget._workspace_manager)
18
20
  self.setWidget(self.sigmund_widget)
19
21
 
20
22
  def setVisible(self, visible):
@@ -34,6 +34,14 @@ class SigmundAnalystChatWidget(ChatWidget):
34
34
  self._review_actions_checkbox.stateChanged.connect(
35
35
  self._on_review_actions_changed)
36
36
  options_layout.addWidget(self._review_actions_checkbox)
37
+ # 'Link editor (or selected text) to workspace' checkbox
38
+ self._link_to_workspace_checkbox = QCheckBox(
39
+ "Link active editor (or selected text) to workspace")
40
+ self._link_to_workspace_checkbox.setChecked(
41
+ settings.sigmund_link_to_workspace)
42
+ self._link_to_workspace_checkbox.stateChanged.connect(
43
+ self._on_link_to_workspace_changed)
44
+ options_layout.addWidget(self._link_to_workspace_checkbox)
37
45
  # Insert the options container before the input container
38
46
  main_layout.insertWidget(main_layout.count(), options_container)
39
47
 
@@ -58,3 +66,14 @@ class SigmundAnalystChatWidget(ChatWidget):
58
66
  return
59
67
  self._review_warning_label.setVisible(not review)
60
68
  settings.sigmund_review_actions = review
69
+
70
+ def _on_link_to_workspace_changed(self, state):
71
+ link_to_workspace = bool(state)
72
+ sigmund_widget = self.parent()
73
+ if link_to_workspace:
74
+ sigmund_widget.set_workspace_manager(
75
+ sigmund_widget._workspace_manager)
76
+ else:
77
+ sigmund_widget.set_workspace_manager(None)
78
+ settings.sigmund_link_to_workspace = link_to_workspace
79
+
@@ -43,15 +43,22 @@ class SigmundAnalystWidget(SigmundWidget):
43
43
  # Store execution results
44
44
  self._execution_result = None
45
45
  self._execution_loop = None
46
- self._working_directory = None
46
+
47
+ @property
48
+ def _working_directory(self):
49
+ """The current working directory, based on the most recently active
50
+ editor. Falls back to os.getcwd() if no folder is set.
51
+ """
52
+ folder = settings.current_folder
53
+ return folder if folder is not None else os.getcwd()
47
54
 
48
55
  def _resolve_path(self, path):
49
56
  """Resolve a path relative to the current working directory.
50
57
  Absolute paths are returned unchanged.
51
58
  """
52
- if self._working_directory is not None and not os.path.isabs(path):
53
- return os.path.join(self._working_directory, path)
54
- return path
59
+ if os.path.isabs(path):
60
+ return path
61
+ return os.path.join(self._working_directory, path)
55
62
 
56
63
  def _confirm_action(self, action_type, details):
57
64
  """Show a confirmation dialog for the proposed action.
@@ -171,9 +178,8 @@ class SigmundAnalystWidget(SigmundWidget):
171
178
  if self._jupyter_console is None:
172
179
  return 'Code execution not supported.'
173
180
  self._app._toggle_dock_widget(self._jupyter_console, show=True)
174
- if self._working_directory is not None:
175
- self._jupyter_console.change_directory(self._working_directory)
176
- time.sleep(.5)
181
+ self._jupyter_console.change_directory(self._working_directory)
182
+ time.sleep(.5)
177
183
  self._execution_result = None
178
184
  self._execution_loop = QEventLoop()
179
185
  QTimer.singleShot(30000, self._execution_loop.quit) # 30 second timeout
@@ -267,43 +273,31 @@ class SigmundAnalystWidget(SigmundWidget):
267
273
 
268
274
  def send_user_message(self, text, *args, **kwargs):
269
275
  current_path = self._editor.code_editor_file_path
270
- # If the editor is not linked to a file, simply use the working
271
- # directory.
272
276
  if current_path is None:
273
277
  current_path = '[unsaved file]'
274
- working_directory = os.getcwd()
275
- else:
276
- working_directory = os.path.dirname(current_path)
277
278
 
278
- # Initialize with default value
279
- working_directory_contents = "(No directory contents available)"
279
+ working_directory = self._working_directory
280
280
 
281
281
  # Get directory contents with priority to top-level items
282
282
  top_level = []
283
283
  all_items = []
284
284
 
285
- # Only wrap file system operations in try-except
286
285
  try:
287
- # Get top-level items (depth=1)
288
286
  top_level = [f for f in os.listdir(working_directory)
289
287
  if os.path.isfile(os.path.join(working_directory, f))
290
288
  or os.path.isdir(os.path.join(working_directory, f))]
291
289
 
292
- # Then get deeper items if we haven't reached our limit
293
290
  remaining_slots = max(0, 20 - len(top_level))
294
291
  if remaining_slots > 0:
295
292
  for root, dirs, files in os.walk(working_directory):
296
- # Skip the top level since we already have it
297
293
  if root == working_directory:
298
294
  continue
299
- # Add files first
300
295
  for file in files:
301
296
  if remaining_slots <= 0:
302
297
  break
303
298
  rel_path = os.path.relpath(os.path.join(root, file), working_directory)
304
299
  all_items.append(f".\\{rel_path}")
305
300
  remaining_slots -= 1
306
- # Then add directories if we still have space
307
301
  for dir in dirs:
308
302
  if remaining_slots <= 0:
309
303
  break
@@ -311,7 +305,6 @@ class SigmundAnalystWidget(SigmundWidget):
311
305
  all_items.append(f".\\{rel_path}\\")
312
306
  remaining_slots -= 1
313
307
 
314
- # Combine top level and deeper items
315
308
  working_directory_contents = "\n".join(
316
309
  sorted([f".\\{item}" if os.path.isfile(os.path.join(working_directory, item))
317
310
  else f".\\{item}\\" for item in top_level] +
@@ -340,6 +333,5 @@ Overview of working directory:
340
333
  ```
341
334
  '''
342
335
  self._transient_system_prompt = system_prompt
343
- self._working_directory = working_directory
344
336
  super().send_user_message(text, *args, **kwargs)
345
337
  self._attachments = None
@@ -14,7 +14,7 @@ def codestral_complete(code: str, cursor_pos: int,
14
14
  return []
15
15
 
16
16
  if client is None:
17
- from mistralai import Mistral
17
+ from mistralai.client import Mistral
18
18
  client = Mistral(api_key=settings.codestral_api_key)
19
19
 
20
20
  if len(code) < settings.codestral_min_context:
@@ -31,7 +31,7 @@ Features:
31
31
 
32
32
  ### SigmundAI for collaborative code editing
33
33
 
34
- You can work together with SigmundAI on the currently active document or selected text. To activate SigmundAI integration, simply log into <https://sigmundai.eu> (subscription required). Sigmund Analyst will then automatically connect to SigmundAI when you enable the Sigmund panel in the toolbar.
34
+ You can code together with SigmundAI. This works similarly to (and is an alternative to) apps such as Claude Code, Codex, and Mistral Vibe. To activate SigmundAI integration, simply log into <https://sigmundai.eu> (subscription required). Sigmund Analyst will then automatically connect to SigmundAI when you enable the Sigmund panel in the toolbar.
35
35
 
36
36
 
37
37
  ### Mistral Codestral for as-you-type suggestions
@@ -51,10 +51,12 @@ The easiest way to install Sigmund Analys on Windows is to install OpenSesame, w
51
51
 
52
52
  ### Linux/ Ubuntu
53
53
 
54
- The easiest way to install Sigmund Analyst on Linux is to download and run the installer script. This will create a Virtual Environment, pip install Sigmund Analyst and all dependencies into this environment, and add a Desktop file to your system to easily start Sigmund Analyst. To upgrade, simply run the script again.
54
+ The easiest way to install Sigmund Analyst on Linux is to download and run the installer script. This will create a Virtual Environment, pip install Sigmund Analyst and all dependencies into this environment, and add a Desktop file to your system to easily start Sigmund Analyst. To upgrade, simply run the script again. (This is actually the OpenSesame installation script, which is bundled with Sigmund Analyst.)
55
+
56
+ Currently, the Linux installer is tested on Ubuntu 26.04.
55
57
 
56
58
  ```
57
- bash <(curl -L https://raw.githubusercontent.com/open-cogsci/pyqt_code_editor/refs/heads/master/install_sigmund_analyst.sh)
59
+ bash <(curl -L https://github.com/open-cogsci/OpenSesame/raw/refs/heads/4.1/linux-installer.sh) --install
58
60
  ```
59
61
 
60
62