pyqt-code-editor 0.0.1__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 (73) hide show
  1. pyqt_code_editor/__init__.py +5 -0
  2. pyqt_code_editor/_settings.py +232 -0
  3. pyqt_code_editor/app.py +438 -0
  4. pyqt_code_editor/code_editors/__init__.py +1 -0
  5. pyqt_code_editor/code_editors/code_editors.py +33 -0
  6. pyqt_code_editor/code_editors/languages/__init__.py +0 -0
  7. pyqt_code_editor/code_editors/languages/generic.py +11 -0
  8. pyqt_code_editor/code_editors/languages/markdown.py +11 -0
  9. pyqt_code_editor/code_editors/languages/python.py +13 -0
  10. pyqt_code_editor/code_editors/languages/text.py +9 -0
  11. pyqt_code_editor/components/__init__.py +0 -0
  12. pyqt_code_editor/components/editor_panel.py +399 -0
  13. pyqt_code_editor/components/find_in_files.py +199 -0
  14. pyqt_code_editor/components/jupyter_console.py +487 -0
  15. pyqt_code_editor/components/project_explorer.py +515 -0
  16. pyqt_code_editor/components/settings_panel.py +162 -0
  17. pyqt_code_editor/components/sigmund.py +75 -0
  18. pyqt_code_editor/components/workspace_explorer.py +162 -0
  19. pyqt_code_editor/mixins/__init__.py +15 -0
  20. pyqt_code_editor/mixins/auto_pair.py +201 -0
  21. pyqt_code_editor/mixins/base.py +142 -0
  22. pyqt_code_editor/mixins/check.py +94 -0
  23. pyqt_code_editor/mixins/comment.py +91 -0
  24. pyqt_code_editor/mixins/complete.py +482 -0
  25. pyqt_code_editor/mixins/execute.py +182 -0
  26. pyqt_code_editor/mixins/file_link.py +166 -0
  27. pyqt_code_editor/mixins/line_number.py +206 -0
  28. pyqt_code_editor/mixins/python_auto_indent.py +239 -0
  29. pyqt_code_editor/mixins/search_replace.py +396 -0
  30. pyqt_code_editor/mixins/shortcuts.py +228 -0
  31. pyqt_code_editor/mixins/smart_backspace_delete.py +120 -0
  32. pyqt_code_editor/mixins/symbols.py +45 -0
  33. pyqt_code_editor/mixins/theme.py +99 -0
  34. pyqt_code_editor/mixins/widgets/__init__.py +0 -0
  35. pyqt_code_editor/mixins/zoom.py +51 -0
  36. pyqt_code_editor/python_utils.py +936 -0
  37. pyqt_code_editor/signal_router.py +116 -0
  38. pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
  39. pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
  40. pyqt_code_editor/syntax_highlighters/languages/generic.py +86 -0
  41. pyqt_code_editor/syntax_highlighters/languages/python.py +62 -0
  42. pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +26 -0
  43. pyqt_code_editor/themes.py +36 -0
  44. pyqt_code_editor/utils.py +96 -0
  45. pyqt_code_editor/watchdog.py +141 -0
  46. pyqt_code_editor/widgets/__init__.py +6 -0
  47. pyqt_code_editor/widgets/calltip_widget.py +44 -0
  48. pyqt_code_editor/widgets/completion_popup.py +89 -0
  49. pyqt_code_editor/widgets/dock.py +15 -0
  50. pyqt_code_editor/widgets/quick_open_dialog.py +196 -0
  51. pyqt_code_editor/widgets/quick_open_file_dialog.py +32 -0
  52. pyqt_code_editor/widgets/quick_symbol_dialog.py +13 -0
  53. pyqt_code_editor/widgets/search_replace_frame.py +128 -0
  54. pyqt_code_editor/widgets/tab_splitter.py +22 -0
  55. pyqt_code_editor/widgets/tabbed_editor.py +351 -0
  56. pyqt_code_editor/worker/__init__.py +0 -0
  57. pyqt_code_editor/worker/languages/__init__.py +0 -0
  58. pyqt_code_editor/worker/languages/generic.py +15 -0
  59. pyqt_code_editor/worker/languages/python.py +17 -0
  60. pyqt_code_editor/worker/manager.py +113 -0
  61. pyqt_code_editor/worker/process.py +128 -0
  62. pyqt_code_editor/worker/providers/__init__.py +1 -0
  63. pyqt_code_editor/worker/providers/codestral.py +56 -0
  64. pyqt_code_editor/worker/providers/jedi.py +115 -0
  65. pyqt_code_editor/worker/providers/ruff.py +45 -0
  66. pyqt_code_editor/worker/providers/sigmund.py +29 -0
  67. pyqt_code_editor/worker/providers/symbol.py +78 -0
  68. pyqt_code_editor/worker/settings.py +1 -0
  69. pyqt_code_editor-0.0.1.dist-info/METADATA +69 -0
  70. pyqt_code_editor-0.0.1.dist-info/RECORD +73 -0
  71. pyqt_code_editor-0.0.1.dist-info/WHEEL +4 -0
  72. pyqt_code_editor-0.0.1.dist-info/entry_points.txt +4 -0
  73. pyqt_code_editor-0.0.1.dist-info/licenses/COPYING +674 -0
@@ -0,0 +1,115 @@
1
+ import re
2
+ import logging
3
+ import jedi
4
+ from .. import settings
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ def _signature_to_html(signature) -> str:
10
+ """Convert jedi.Script.get_signatures() output to nicely formatted HTML."""
11
+ param_strs = []
12
+ for param in signature.params:
13
+ param_strs.append(param.to_string())
14
+ # Build the signature line
15
+ sig_line = ",<br />&nbsp;".join(param_strs)
16
+ return_hint = ""
17
+ # If there's a known return annotation, append it
18
+ if hasattr(signature, "annotation_string") and signature.annotation_string:
19
+ return_hint = f"-> {signature.annotation_string}"
20
+ return f"({sig_line}){return_hint}"
21
+
22
+
23
+ def _prepare_jedi_script(code: str, cursor_position: int, path: str | None):
24
+ """
25
+ Prepare a Jedi Script object and calculate line_no/column_no from the
26
+ given code and cursor_position. Returns (script, line_no, column_no).
27
+ """
28
+ # Convert the flat cursor_position into line & column (1-based indexing for Jedi)
29
+ line_no = code[:cursor_position].count('\n') + 1
30
+ last_newline_idx = code.rfind('\n', 0, cursor_position)
31
+ if last_newline_idx < 0:
32
+ column_no = cursor_position
33
+ else:
34
+ column_no = cursor_position - (last_newline_idx + 1)
35
+
36
+ logger.info("Creating Jedi Script for path=%r at line=%d, column=%d",
37
+ path, line_no, column_no)
38
+
39
+ script = jedi.Script(code, path=path)
40
+ return script, line_no, column_no
41
+
42
+
43
+ def jedi_complete(code: str, cursor_position: int, path: str | None) -> list[str]:
44
+ """
45
+ Perform Python-specific completion using Jedi. Returns a list of possible completions
46
+ for the text at the given cursor position, or None if no completion is found.
47
+ """
48
+ if cursor_position == 0 or not code:
49
+ return []
50
+ # Basic sanity check for whether we want to attempt completion.
51
+ char_before = code[cursor_position - 1]
52
+ # Typically, you'd allow '.', '_' or alphanumeric as a signal for completion
53
+ if not re.match(r"[A-Za-z0-9_.]", char_before):
54
+ return []
55
+ # If the first preceding # comes before the first preceding newline, then we're inside a code comment
56
+ code_up_to_cursor = code[:cursor_position]
57
+ if code_up_to_cursor.rfind('#') > code_up_to_cursor.rfind('\n'):
58
+ return []
59
+ # Go Jedi!
60
+ script, line_no, column_no = _prepare_jedi_script(code, cursor_position, path)
61
+ completions = script.complete(line=line_no, column=column_no)
62
+ if not completions:
63
+ return []
64
+ result = [
65
+ {'completion' : c.complete, 'name': c.name}
66
+ for c in completions[:settings.max_completions] if c.complete
67
+ ]
68
+ return result or []
69
+
70
+
71
+ def jedi_signatures(code: str, cursor_position: int, path: str | None,
72
+ multiline: bool = False, max_width: int = 40,
73
+ max_lines: int = 10):
74
+ """
75
+ Retrieve function signatures (calltips) from Jedi given the current cursor position.
76
+ Returns a list of strings describing each signature, or None if none.
77
+
78
+ Enhancements:
79
+ 1) If the docstring contains a duplicate of sig_str at the beginning, it's removed.
80
+ 2) The docstring is wrapped to max_width columns and truncated to max_lines lines.
81
+ """
82
+ if cursor_position == 0 or not code:
83
+ logger.info("No code or cursor_position=0; cannot fetch calltip.")
84
+ return None
85
+
86
+ logger.info("Starting Jedi calltip request (multiline=%r).", multiline)
87
+ script, line_no, column_no = _prepare_jedi_script(code, cursor_position, path)
88
+
89
+ signatures = script.get_signatures(line=line_no, column=column_no)
90
+ if not signatures:
91
+ logger.info("No signatures returned by Jedi.")
92
+ return None
93
+
94
+ results = []
95
+ for sig in signatures:
96
+ results.append(_signature_to_html(sig))
97
+
98
+ logger.info("Got %d signature(s) from Jedi.", len(results))
99
+ return results or None
100
+
101
+
102
+ def jedi_symbols(code: str) -> list[dict]:
103
+ """Retrieve symbols from Jedi given the current code."""
104
+ script = jedi.Script(code)
105
+ symbols = script.get_names(all_scopes=True)
106
+ results = []
107
+ for symbol in symbols:
108
+ if symbol.type not in ('function', 'class'):
109
+ continue
110
+ results.append({
111
+ 'name': symbol.name,
112
+ 'type': symbol.type,
113
+ 'line': symbol.line
114
+ })
115
+ return results
@@ -0,0 +1,45 @@
1
+ import subprocess
2
+ import tempfile
3
+ import json
4
+ import os
5
+ import logging
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ def ruff_check(code: str) -> list[dict]:
10
+ """
11
+ Lints Python source code using Ruff.
12
+
13
+ Args:
14
+ code (str): The Python source code to lint.
15
+ """
16
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".py", mode="w") as tmp_file:
17
+ tmp_file.write(code)
18
+ tmp_file_path = tmp_file.name
19
+ print(tmp_file.name)
20
+ cmd = ["ruff", "check", tmp_file_path, "--output-format", "json"]
21
+ try:
22
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
23
+ stderr=subprocess.PIPE, text=True)
24
+ stdout, stderr = process.communicate()
25
+ except Exception as e:
26
+ logger.error(f'failed to invoke ruff: {e}')
27
+ return {}
28
+ finally:
29
+ if os.path.exists(tmp_file_path):
30
+ os.unlink(tmp_file_path)
31
+ try:
32
+ result = json.loads(stdout)
33
+ except Exception as e:
34
+ logger.error(f'failed to parse ruff output: {e}')
35
+ return {}
36
+ formatted_result = {}
37
+ for message in result:
38
+ row = message['location']['row']
39
+ if row not in formatted_result:
40
+ formatted_result[row] = []
41
+ formatted_result[row].append({
42
+ 'code': message['code'],
43
+ 'message': message['message'],
44
+ })
45
+ return formatted_result
@@ -0,0 +1,29 @@
1
+ import os
2
+ import sys
3
+ import json
4
+ import requests
5
+ from .. import settings
6
+
7
+
8
+ def sigmund_complete(code: str, cursor_pos: int, path: str | None,
9
+ multiline: False) -> list[str]:
10
+ if token is None:
11
+ return []
12
+ if len(code) < 10:
13
+ return []
14
+ ret_val = []
15
+ start = max(0, cursor_pos - settings.sigmund_max_context)
16
+ end = cursor_pos + settings.sigmund_max_context
17
+ prompt = code[start: cursor_pos]
18
+ suffix = code[cursor_pos: end]
19
+ data = {'prompt': prompt, 'token': token, 'suffix': suffix,
20
+ 'multiline': multiline}
21
+ try:
22
+ response = requests.post(settings.sigmund_fim_endpoint, json=data,
23
+ timeout=settings.sigmund_timeout)
24
+ response.raise_for_status()
25
+ resp_json = response.json()
26
+ completion = resp_json.get('completion', '')
27
+ return [completion]
28
+ except Exception as e:
29
+ return []
@@ -0,0 +1,78 @@
1
+ import re
2
+
3
+ def symbol_complete(code: str, cursor_pos: int, path: str | None) -> list[str]:
4
+ """
5
+ A helper function for code completion that is based on all the symbols
6
+ that are detected in the code in a language-agnostic way. The code is split
7
+ into separate words so that punctuation and separators are ignored. Then
8
+ the best fitting completion is returned. If no completion is available
9
+ (e.g., because the character before the cursor is punctuation, comma, or
10
+ whitespace), return None.
11
+
12
+ Logic to handle contradictory test #4 and #5:
13
+ 1) If the partial_word itself appears in the code, we prioritize a match
14
+ with the largest leftover length.
15
+ 2) Otherwise, if there is a symbol that differs from partial_word by exactly
16
+ 1 character, pick that first; otherwise pick the one with the largest
17
+ leftover length. Ties are broken lexicographically.
18
+ """
19
+
20
+ if cursor_pos == 0:
21
+ return [] # No space to complete if at start of code
22
+
23
+ # Check the character immediately before the cursor
24
+ char_before = code[cursor_pos - 1]
25
+ # If the character is not alphanumeric or underscore, no completion
26
+ if not re.match(r"[A-Za-z0-9_]", char_before):
27
+ return []
28
+
29
+ # Find the partial word by reading backwards from cursor_pos
30
+ start_index = cursor_pos - 1
31
+ while start_index >= 0 and re.match(r"[A-Za-z0-9_]", code[start_index]):
32
+ start_index -= 1
33
+ partial_word = code[start_index + 1:cursor_pos]
34
+ if not partial_word:
35
+ return []
36
+
37
+ # Remove the user-typed partial_word from the code where it appears near the cursor
38
+ code_without_partial = code[:start_index + 1] + code[cursor_pos:]
39
+
40
+ # Gather all words (symbols) from the updated code
41
+ all_symbols = re.findall(r"[A-Za-z0-9_]+", code_without_partial)
42
+ unique_symbols = set(all_symbols) # deduplicate
43
+
44
+ # Filter only those symbols that:
45
+ # 1) start with partial_word
46
+ # 2) are strictly longer than partial_word
47
+ matches = [sym for sym in unique_symbols
48
+ if sym.startswith(partial_word) and len(sym) > len(partial_word)]
49
+ if not matches:
50
+ return []
51
+
52
+ # Build leftover_map { leftover_length -> list_of_symbols }
53
+ leftover_map = {}
54
+ for sym in matches:
55
+ leftover_len = len(sym) - len(partial_word)
56
+ leftover_map.setdefault(leftover_len, []).append(sym)
57
+
58
+ # Check if partial_word is itself a symbol (i.e. it appears elsewhere in the code)
59
+ partial_word_is_symbol = partial_word in unique_symbols
60
+
61
+ if partial_word_is_symbol:
62
+ # Pick from the group with the maximum leftover
63
+ max_leftover_len = max(leftover_map)
64
+ candidates = leftover_map[max_leftover_len]
65
+ else:
66
+ # If there's a leftover=1 group available, pick that
67
+ if 1 in leftover_map:
68
+ candidates = leftover_map[1]
69
+ else:
70
+ # Otherwise pick from the group with the maximum leftover
71
+ max_leftover_len = max(leftover_map)
72
+ candidates = leftover_map[max_leftover_len]
73
+
74
+ # Among candidates, pick the lexicographically first
75
+ best_match = min(candidates)
76
+ # The remainder is the substring that goes beyond the partial_word
77
+ remainder = best_match[len(partial_word):]
78
+ return [{'completion' : remainder, 'name': best_match}]
@@ -0,0 +1 @@
1
+ # This is an empty module that will be filled with settings
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyqt_code_editor
3
+ Version: 0.0.1
4
+ Summary: Fully featured code-editor widgets for PyQt
5
+ Keywords: code editor,pyqt,ide
6
+ Author-email: Sebastiaan Mathôt <s.mathot@cogsci.nl>
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: COPYING
10
+ Requires-Dist: chardet
11
+ Requires-Dist: jedi
12
+ Requires-Dist: mistralai
13
+ Requires-Dist: pathspec
14
+ Requires-Dist: pygments
15
+ Requires-Dist: qtawesome
16
+ Requires-Dist: qtpy
17
+ Requires-Dist: ruff
18
+ Requires-Dist: opensesame-extension-sigmund
19
+ Requires-Dist: pyqt6
20
+ Requires-Dist: qtconsole
21
+ Project-URL: Source, https://github.com/open-cogsci/pyqt_code_editor
22
+
23
+ # PyQt Code Editor
24
+
25
+ __This code is under development and not ready for general use__
26
+
27
+ Fully featured code-editor widgets for PyQt
28
+
29
+ Copyright 2025 Sebastiaan Mathôt
30
+
31
+
32
+ ## About
33
+
34
+ This is a set of code-editor widgets for PyQt. They are inspired by PyQode, and contain much of the same functionality, but in a cleaner and more modern codebase. All functionality can be used as standalone PyQt widgets. A full Python IDE is also available. This IDE is called Sigmund Analyst, and is primarily intended for data analysis in combination with [SigmundAI](https://sigmundai.eu).
35
+
36
+ Features:
37
+
38
+ - Code-editor widgets with syntax highlighting, code completion, AI integration, and more
39
+ - Project explorer (folder view)
40
+ - Editor panel with splittable tabs
41
+ - Jupyter console
42
+ - Workspace explorer (linked to Jupyter console)
43
+ - Settings panel
44
+
45
+ ![](screenshot.png)
46
+
47
+
48
+ ## Usage
49
+
50
+ First, install all dependencies using:
51
+
52
+ ```
53
+ pip install .
54
+ ```
55
+
56
+ Next, start one of the example scripts:
57
+
58
+ ```
59
+ python examples/example_ide.py
60
+ ```
61
+
62
+ On some systems, a segmentation fault occurs with the version of PyQt from PyPi. In that case, install PyQt from some other source, such as Anaconda.
63
+
64
+
65
+ ## License
66
+
67
+ `PyQt Code Editor` is licensed under the [GNU General Public License
68
+ v3](http://www.gnu.org/licenses/gpl-3.0.en.html).
69
+
@@ -0,0 +1,73 @@
1
+ pyqt_code_editor/__init__.py,sha256=xolRrp46-3ATeGfcKWvc5bW3HfZNUbgSS19uRyL4DSY,106
2
+ pyqt_code_editor/_settings.py,sha256=u_ZjcTGS7UKcDQ0LqyvaWMu8I5_B7irxZN9QQ-Y4Asc,10250
3
+ pyqt_code_editor/app.py,sha256=YlWG2bfA5ZOSHYSKljDEMH6k_0zQzlf3KsNjO1EpIhQ,18772
4
+ pyqt_code_editor/python_utils.py,sha256=9xyk7YICT3GLB-hh_A2PDGxDf7Hg-sm9YeClEkFxzoU,26335
5
+ pyqt_code_editor/signal_router.py,sha256=7oJqEd75-CMFCFrByz42Xt1lCRwGgIj1h_FJ3euH4q8,4628
6
+ pyqt_code_editor/themes.py,sha256=jzgMzgxksF-7goILzXJm06ztgdoXwjccjEur5TRQVbQ,989
7
+ pyqt_code_editor/utils.py,sha256=2FReKyGlGbcsWflhY7fcTpoSGLScSqWGd6LJMXfhyZI,3665
8
+ pyqt_code_editor/watchdog.py,sha256=1Cbdbx6KZbWF6bBbM3vpjynXmnxQycvzsMGzeyfdS88,4450
9
+ pyqt_code_editor/code_editors/__init__.py,sha256=jY99MI7_nV8vZ4UzEuU8dvxy_c87sKpK_rzHERgxfyU,40
10
+ pyqt_code_editor/code_editors/code_editors.py,sha256=te6wYu-FciYVNL7WuDNjcsZ2ET8i2MWo8mluACZRvdI,1205
11
+ pyqt_code_editor/code_editors/languages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ pyqt_code_editor/code_editors/languages/generic.py,sha256=yT03IRSw00e-mnqljmJdVCSPwkThNiJmhMywST8fgqc,393
13
+ pyqt_code_editor/code_editors/languages/markdown.py,sha256=h9pnLFY6zr5uCLrBDs45t14PF1tVl6R1x3Lru2s3uiI,393
14
+ pyqt_code_editor/code_editors/languages/python.py,sha256=J16Rkn5OPzX2H0S2HzRip-inQhdTQVAYxreVUXxBrSY,554
15
+ pyqt_code_editor/code_editors/languages/text.py,sha256=lfdDJ15NXZka9AxrjQqfwbqVajL0-dDFo6CbDkNW6qY,340
16
+ pyqt_code_editor/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ pyqt_code_editor/components/editor_panel.py,sha256=xFDRFogW1EhM_ObRtW-zPN-rPzdoNjKKroZRa3xzrIc,17829
18
+ pyqt_code_editor/components/find_in_files.py,sha256=yqTlYJcZRbVe6_UVsjcjNE3_Xayn3jGLo4xOLvlGEw0,7498
19
+ pyqt_code_editor/components/jupyter_console.py,sha256=qWG99oZc2otlkElAislhK8HnWbfdTe36vpSWYPeF24w,20250
20
+ pyqt_code_editor/components/project_explorer.py,sha256=3JmgxQfL3O_SHwwUJ7lUgdEaPyjYp2owfK_6a4zK4DU,21552
21
+ pyqt_code_editor/components/settings_panel.py,sha256=DC5HNYtXvUsr1ZDw3bWCOivW5vVjHp8Y5SMeHuxvYN8,6399
22
+ pyqt_code_editor/components/sigmund.py,sha256=cPxVpuPYhzqDVsjQQTSngR2R75su_bKXu_Nz_9IZHeI,2562
23
+ pyqt_code_editor/components/workspace_explorer.py,sha256=-dXkMVHbSmjj75XB0AYwdAy9j4v_4gvuyXWHxyJs1fg,6420
24
+ pyqt_code_editor/mixins/__init__.py,sha256=6ZXNiJCVv0I-41_ZbO8OaywONCAoPk6BhdIHfsBgt2k,511
25
+ pyqt_code_editor/mixins/auto_pair.py,sha256=eKC-fZCJ5WXzvS4mZV69gW73jrVa7VIS_cvoFeEnR7E,8283
26
+ pyqt_code_editor/mixins/base.py,sha256=BL3cyA1zRGj07nBfq6rCq03_RWU285AcFIyHm8xcnOk,5313
27
+ pyqt_code_editor/mixins/check.py,sha256=gf1cNS1P67b4z1Qe3zX39XZuk-YzVfaBcS37T1xqT3Y,3793
28
+ pyqt_code_editor/mixins/comment.py,sha256=8_J7YwWmd5c03cbDCnPxjH5RLvy0wvabIJBywRYD5zQ,3854
29
+ pyqt_code_editor/mixins/complete.py,sha256=xFM7wNE8Z4z06LqpIMmZebk0pjfhK6cjMsqklQA7tkc,20583
30
+ pyqt_code_editor/mixins/execute.py,sha256=U1ULJHxXGGDH-chMgR42b_5zEseea34GKmGFkD4GmjY,7339
31
+ pyqt_code_editor/mixins/file_link.py,sha256=TPFG811TbYmX5SLJOCZZVf4zJKmPiTJ8MgUdvLOBrkg,6620
32
+ pyqt_code_editor/mixins/line_number.py,sha256=APmQTkJi5H1z1HZkTGf084Hc9m5t8sljyzr-7fTJZU4,8128
33
+ pyqt_code_editor/mixins/python_auto_indent.py,sha256=QKdJ0F4g0blqL_DAPQR1sIJYM7qZCRHwK5LMCfl3B8c,9684
34
+ pyqt_code_editor/mixins/search_replace.py,sha256=KtdyGUHr3ozWrZWOWL88jG_2G9t9GEkful-O1D2PtS4,15033
35
+ pyqt_code_editor/mixins/shortcuts.py,sha256=7JchKANfZulUpR_iSOQKlPT0Ns0e0ykj259lEmZbX70,9370
36
+ pyqt_code_editor/mixins/smart_backspace_delete.py,sha256=xtwWu9BCrtU-eEmynbG6Jk0-bIE-l-jw3cdwYyWBuZ4,5814
37
+ pyqt_code_editor/mixins/symbols.py,sha256=r0_g5lSfXCumbBAguPuKW1_er5g1LkIXe8xKZ8jZuxo,1739
38
+ pyqt_code_editor/mixins/theme.py,sha256=C2PVWqqaAPv4YoAn0y2ObPclXofF1SWmsUG2eGw2z94,3783
39
+ pyqt_code_editor/mixins/zoom.py,sha256=Swr_cuGmgWogp0uJVDtnwAmlip8fAKZNDm3qm5hB4UY,1537
40
+ pyqt_code_editor/mixins/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ pyqt_code_editor/syntax_highlighters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ pyqt_code_editor/syntax_highlighters/syntax_highlighter.py,sha256=vCK1DQEhpCb5ORTqzzp5Xv6uUNaw5xJMvEr0XQH3hxU,951
43
+ pyqt_code_editor/syntax_highlighters/languages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ pyqt_code_editor/syntax_highlighters/languages/generic.py,sha256=CQZYL7aDLPXcrUhQEpFpJhhpGBJJHylI6bK5OOSo2gY,3257
45
+ pyqt_code_editor/syntax_highlighters/languages/python.py,sha256=BY7BzM_9iY7Ev4HkYObbtOxG4Tx9fri3fOzEvqelDfw,2603
46
+ pyqt_code_editor/widgets/__init__.py,sha256=XeN7FD2XG-2hhwvjGhEzVTVlaeCd_hVx4jT9ydc7d5I,254
47
+ pyqt_code_editor/widgets/calltip_widget.py,sha256=c6Eq4w_PJrcGEB1xCsb6ZMuSHY2a8vToik1z0MS6jeY,1698
48
+ pyqt_code_editor/widgets/completion_popup.py,sha256=d7oS7EJOU7lFbpxdbO8x6WWUA-Q80GIXQbNuGYqGoec,3462
49
+ pyqt_code_editor/widgets/dock.py,sha256=9Kdpd7anNOD5yLeYEDR328bBlFScH0BQY6oecqkxluI,326
50
+ pyqt_code_editor/widgets/quick_open_dialog.py,sha256=_OPNOGCI9mtflTocSpk08QtCmrTOzvDxMXLTWvKwjPA,7417
51
+ pyqt_code_editor/widgets/quick_open_file_dialog.py,sha256=4Baz_D9C3XaAJ6xJJR1gBV1ABlZAHPPMFKH5mTihKx8,1165
52
+ pyqt_code_editor/widgets/quick_symbol_dialog.py,sha256=JHgmkh3RnP2fYV3iFuXbY8cCHIWmjpNR2azyIeNq5D4,418
53
+ pyqt_code_editor/widgets/search_replace_frame.py,sha256=WVN4wsZ3TK9XahPDEdYK9wWc3Z8GnxcfZI1Sil7zHnM,4517
54
+ pyqt_code_editor/widgets/tab_splitter.py,sha256=sUN6xwotvQETKJqMHa1IMswY05-xA6wSd7auIVyqnRg,704
55
+ pyqt_code_editor/widgets/tabbed_editor.py,sha256=C5Oyv7j6YBqQhyjqocP0MwrerwwnSgZFsQT4Ows32_M,14021
56
+ pyqt_code_editor/worker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ pyqt_code_editor/worker/manager.py,sha256=BjLIFG3yX7EC0dxyhWdg1qoy1S_6ZjBQeXEWTRLewHI,4054
58
+ pyqt_code_editor/worker/process.py,sha256=Gida0xdT3NtNLyJ-DU_k7rLyKEH4SzUZHnCl_8XfqqU,5157
59
+ pyqt_code_editor/worker/settings.py,sha256=rbBZbLwJalviJp7jegm_cXqYOtc19-iOjPZp2CJs24k,60
60
+ pyqt_code_editor/worker/languages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ pyqt_code_editor/worker/languages/generic.py,sha256=b9v_Ul1s6zq5FlDIjx6_bpd8Pw1GA_Gc-HGzaC-85tg,437
62
+ pyqt_code_editor/worker/languages/python.py,sha256=4qfi2Xh1PMqFEOJedfE0PfDCI2DC9GvOqkGPK81PLcw,479
63
+ pyqt_code_editor/worker/providers/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
64
+ pyqt_code_editor/worker/providers/codestral.py,sha256=pCVrS1hOdzFV6dC-rJ210mDolsMis0-4-5UDQN8_Crk,1521
65
+ pyqt_code_editor/worker/providers/jedi.py,sha256=My2I2I_-a8_el8x88ej1Kw8HP0Rpdb38AgUJKpfDP5s,4301
66
+ pyqt_code_editor/worker/providers/ruff.py,sha256=syZRyM8-n683Lc7kTf1Gq1Ns4UfPZ6sXBvHmKHTwLsA,1383
67
+ pyqt_code_editor/worker/providers/sigmund.py,sha256=Ewsd4126lK2QIjDW9KqMrnYE6ht0vCl8UOZ3kSp0h6E,928
68
+ pyqt_code_editor/worker/providers/symbol.py,sha256=iMObfsgZl6rI-WeCu9PE5uZGY6OSuST-4jcT9e0l7co,3305
69
+ pyqt_code_editor-0.0.1.dist-info/entry_points.txt,sha256=9D7XocBHMrmdKZXgFDKMpYju89bQm9u0jDB5QWABXYs,116
70
+ pyqt_code_editor-0.0.1.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
71
+ pyqt_code_editor-0.0.1.dist-info/WHEEL,sha256=_2ozNFCLWc93bK4WKHCO-eDUENDlo-dgc9cU3qokYO4,82
72
+ pyqt_code_editor-0.0.1.dist-info/METADATA,sha256=aQSLCzhfy8RmkKY_6N0CNjyguLVC9Fdl95UfCTuS6Xs,1915
73
+ pyqt_code_editor-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: flit 3.11.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ pyqt-code-editor=pyqt_code_editor.app:launch_app
3
+ sigmund-analyst=pyqt_code_editor.app:launch_app
4
+