PrEditor 2.7.0__tar.gz → 2.9.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.
- {preditor-2.7.0 → preditor-2.9.0}/.github/workflows/static-analysis-and-test.yml +5 -1
- {preditor-2.7.0 → preditor-2.9.0}/PKG-INFO +8 -1
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/PKG-INFO +8 -1
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/scm_file_list.json +1 -0
- preditor-2.9.0/PrEditor.egg-info/scm_version.json +8 -0
- {preditor-2.7.0 → preditor-2.9.0}/README.md +7 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/debug.py +70 -5
- {preditor-2.7.0 → preditor-2.9.0}/preditor/excepthooks.py +11 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/__init__.py +1 -21
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/codehighlighter.py +52 -66
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/completer.py +44 -16
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/console.py +14 -13
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/console_base.py +177 -21
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/drag_tab_bar.py +2 -3
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/level_buttons.py +3 -3
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/loggerwindow.py +41 -9
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/loggerwindow.ui +24 -18
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/workboxwidget.py +1 -1
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/documenteditor.py +3 -3
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/finddialog.py +4 -4
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/ui/finddialog.ui +5 -5
- {preditor-2.7.0 → preditor-2.9.0}/preditor/stream/director.py +48 -11
- {preditor-2.7.0 → preditor-2.9.0}/preditor/version.py +3 -3
- preditor-2.7.0/PrEditor.egg-info/scm_version.json +0 -8
- {preditor-2.7.0 → preditor-2.9.0}/.coveragerc +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.github/ISSUE_TEMPLATE/BUG_REPORT.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.github/workflows/release.yml +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.gitignore +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/.pre-commit-config.yaml +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/CODE_OF_CONDUCT.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/CONTRIBUTING.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/LICENSE +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/MANIFEST.in +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/SOURCES.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/dependency_links.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/entry_points.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/requires.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/PrEditor.egg-info/top_level.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/examples/add_to_app.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/examples/output_capture_and_show.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/examples/output_console.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/examples/output_console.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/__main__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/about_module.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/cli.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/config.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/constants.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/contexts.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/cores/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/cores/core.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/.hab.json +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/maya/PrEditor_maya.mod +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/maya/README.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/maya/plug-ins/PrEditor_maya.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/studiomax/PackageContents.xml +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/studiomax/README.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/studiomax/preditor.ms +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/dccs/studiomax/preditor_menu.mnx +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/delayable_engine/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/delayable_engine/delayables.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/enum.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/app.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/dialog.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/editor_chooser.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/errordialog.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/find_files.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/fuzzy_search/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/fuzzy_search/fuzzy_search.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/group_tab_widget.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/grouped_tab_menu.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/grouped_tab_models.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/grouped_tab_widget.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/group_tab_widget/one_tab_widget.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/logger_window_handler.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/logger_window_plugin.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/newtabwidget.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/output_console.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/qtdesigner/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/qtdesigner/_log_plugin.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/qtdesigner/console_base_plugin.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/qtdesigner/console_predit_plugin.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/set_text_editor_path_dialog.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/status_label.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/suggest_path_quotes_dialog.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/editor_chooser.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/errordialog.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/find_files.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/set_text_editor_path_dialog.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/ui/suggest_path_quotes_dialog.ui +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/window.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/workbox_mixin.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/gui/workbox_text_edit.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/logging_config.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/osystem.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/plugins.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/prefs.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/error_mail.html +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/error_mail_inline.html +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/README.md +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/arrow_forward.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/check-bold.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/chevron-down.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/chevron-up.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/close-thick.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/comment-edit.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/content-copy.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/content-cut.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/content-duplicate.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/content-paste.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/content-save.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/debug_disabled.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/eye-check.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/file-plus.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/file-remove.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/format-align-left.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/format-letter-case-lower.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/format-letter-case-upper.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/format-letter-case.svg +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/information.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_critical.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_custom.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_debug.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_error.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_info.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_not_set.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/logging_warning.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/marker.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/play.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/playlist-play.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/plus-minus-variant.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/preditor.ico +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/preditor.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/preditor.psd +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/preditor.svg +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/regex.svg +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/restart.svg +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/skip-forward-outline.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/skip-next-outline.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/skip-next.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/skip-previous.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/subdirectory-arrow-right.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/text-search-variant.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/img/warning-big.png +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/lang/python.json +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/pref_updates/pref_updates.json +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/settings.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/stylesheet/Bright.css +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/resource/stylesheet/Dark.css +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/delayables/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/delayables/smart_highlight.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/delayables/spell_check.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/bash.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/batch.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/cpp.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/css.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/eyeonscript.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/html.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/javascript.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/lua.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/maxscript.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/mel.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/mu.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/nsi.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/perl.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/puppet.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/python.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/ruby.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/sql.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/xml.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/config/yaml.ini +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lang/language.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/cpplexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/javascriptlexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/maxscriptlexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/mellexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/mulexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/scintilla/lexers/pythonlexer.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/settings.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/stream/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/stream/console_handler.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/stream/manager.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/streamhandler_helper.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/utils/__init__.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/utils/call_stack.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/utils/cute.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/utils/stylesheets.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/utils/text_search.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/preditor/weakref.py +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/pyproject.toml +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements-cli.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements-dev.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements-qsci5.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements-qsci6.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements-shortcut.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/requirements.txt +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/setup.cfg +0 -0
- {preditor-2.7.0 → preditor-2.9.0}/tox.ini +0 -0
|
@@ -49,10 +49,14 @@ jobs:
|
|
|
49
49
|
strategy:
|
|
50
50
|
matrix:
|
|
51
51
|
os: ['ubuntu-latest', 'windows-latest']
|
|
52
|
-
python: ['3.
|
|
52
|
+
python: ['3.10', '3.11', '3.12', '3.13']
|
|
53
53
|
# Works around the depreciation of python 3.7 for ubuntu
|
|
54
54
|
# https://github.com/actions/setup-python/issues/544
|
|
55
55
|
include:
|
|
56
|
+
- os: 'ubuntu-24.04'
|
|
57
|
+
python: '3.9'
|
|
58
|
+
- os: 'ubuntu-24.04'
|
|
59
|
+
python: '3.8'
|
|
56
60
|
- os: 'ubuntu-22.04'
|
|
57
61
|
python: '3.7'
|
|
58
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PrEditor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: A python REPL and Editor and console based on Qt.
|
|
5
5
|
Author-email: Blur Studio <opensource@blur.com>
|
|
6
6
|
License: LGPL-3.0
|
|
@@ -84,6 +84,13 @@ blocks([...](https://docs.python.org/3/glossary.html#term-...)), use the workbox
|
|
|
84
84
|
loggers, and tracebacks(not using stderr). This can be used in various widgets to
|
|
85
85
|
show selected output. See [examples/output_console.py](examples/output_console.py)
|
|
86
86
|
for an example of the various modes.
|
|
87
|
+
* **Traceback markers:** Set the `PREDITOR_WRAP_TB` environment variable to
|
|
88
|
+
`prefix,suffix` to print those lines to stderr before and after every traceback
|
|
89
|
+
handled by PrEditor's excepthook. The traceback is still raised normally. This
|
|
90
|
+
makes tracebacks easy to find or parse in log files, for example:
|
|
91
|
+
```
|
|
92
|
+
PREDITOR_WRAP_TB=--- TRACEBACK START ---,--- TRACEBACK END ---
|
|
93
|
+
```
|
|
87
94
|
* All code is run in `__main__`. In code you can add objects to it for inspection in PrEditor.
|
|
88
95
|
* `Ctrl + Shift + PgUp/PgDown` changes focus between the console and workbox.
|
|
89
96
|
* `Ctrl + Alt + Shift + PgUp/PgDown` changes focus and copies the current prompt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PrEditor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: A python REPL and Editor and console based on Qt.
|
|
5
5
|
Author-email: Blur Studio <opensource@blur.com>
|
|
6
6
|
License: LGPL-3.0
|
|
@@ -84,6 +84,13 @@ blocks([...](https://docs.python.org/3/glossary.html#term-...)), use the workbox
|
|
|
84
84
|
loggers, and tracebacks(not using stderr). This can be used in various widgets to
|
|
85
85
|
show selected output. See [examples/output_console.py](examples/output_console.py)
|
|
86
86
|
for an example of the various modes.
|
|
87
|
+
* **Traceback markers:** Set the `PREDITOR_WRAP_TB` environment variable to
|
|
88
|
+
`prefix,suffix` to print those lines to stderr before and after every traceback
|
|
89
|
+
handled by PrEditor's excepthook. The traceback is still raised normally. This
|
|
90
|
+
makes tracebacks easy to find or parse in log files, for example:
|
|
91
|
+
```
|
|
92
|
+
PREDITOR_WRAP_TB=--- TRACEBACK START ---,--- TRACEBACK END ---
|
|
93
|
+
```
|
|
87
94
|
* All code is run in `__main__`. In code you can add objects to it for inspection in PrEditor.
|
|
88
95
|
* `Ctrl + Shift + PgUp/PgDown` changes focus between the console and workbox.
|
|
89
96
|
* `Ctrl + Alt + Shift + PgUp/PgDown` changes focus and copies the current prompt
|
|
@@ -38,6 +38,13 @@ blocks([...](https://docs.python.org/3/glossary.html#term-...)), use the workbox
|
|
|
38
38
|
loggers, and tracebacks(not using stderr). This can be used in various widgets to
|
|
39
39
|
show selected output. See [examples/output_console.py](examples/output_console.py)
|
|
40
40
|
for an example of the various modes.
|
|
41
|
+
* **Traceback markers:** Set the `PREDITOR_WRAP_TB` environment variable to
|
|
42
|
+
`prefix,suffix` to print those lines to stderr before and after every traceback
|
|
43
|
+
handled by PrEditor's excepthook. The traceback is still raised normally. This
|
|
44
|
+
makes tracebacks easy to find or parse in log files, for example:
|
|
45
|
+
```
|
|
46
|
+
PREDITOR_WRAP_TB=--- TRACEBACK START ---,--- TRACEBACK END ---
|
|
47
|
+
```
|
|
41
48
|
* All code is run in `__main__`. In code you can add objects to it for inspection in PrEditor.
|
|
42
49
|
* `Ctrl + Shift + PgUp/PgDown` changes focus between the console and workbox.
|
|
43
50
|
* `Ctrl + Alt + Shift + PgUp/PgDown` changes focus and copies the current prompt
|
|
@@ -3,15 +3,20 @@ from __future__ import absolute_import, print_function
|
|
|
3
3
|
import datetime
|
|
4
4
|
import inspect
|
|
5
5
|
import logging
|
|
6
|
+
import os
|
|
6
7
|
import sys
|
|
7
8
|
|
|
8
9
|
logger = logging.getLogger(__name__)
|
|
9
10
|
|
|
11
|
+
# Keeps the file `faulthandlerToFile` installed open for the life of the process
|
|
12
|
+
_faulthandlerFile = None
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
class FileLogger:
|
|
12
16
|
def __init__(self, stdhandle, logfile, _print=True, clearLog=True):
|
|
13
17
|
self.old_stream = stdhandle
|
|
14
|
-
|
|
18
|
+
# Accept pathlib objects but store the path as a string
|
|
19
|
+
self._logfile = os.fspath(logfile)
|
|
15
20
|
self._print = _print
|
|
16
21
|
if clearLog:
|
|
17
22
|
# clear the log file
|
|
@@ -48,18 +53,21 @@ def logToFile(path, stdout=True, stderr=True, useOldStd=True, clearLog=True):
|
|
|
48
53
|
sys.version info when stdout is True.
|
|
49
54
|
|
|
50
55
|
Args:
|
|
51
|
-
path (str): File path to log output to.
|
|
52
|
-
|
|
56
|
+
path (str or os.PathLike): File path to log output to. If None is explicitly
|
|
57
|
+
passed the path returned by `preditor.osystem.defaultLogFile()` is used.
|
|
53
58
|
stdout (bool): If True(default) override sys.stdout.
|
|
54
|
-
|
|
55
59
|
stderr (bool): If True(default) override sys.stderr.
|
|
56
|
-
|
|
57
60
|
useOldStd (bool): If True, messages will be written to the FileLogger
|
|
58
61
|
and the previous sys.stdout/sys.stderr.
|
|
59
62
|
|
|
60
63
|
clearLog (bool): If True(default) clear the log file when this command is
|
|
61
64
|
called.
|
|
62
65
|
"""
|
|
66
|
+
if path is None:
|
|
67
|
+
from . import osystem
|
|
68
|
+
|
|
69
|
+
path = osystem.defaultLogFile()
|
|
70
|
+
|
|
63
71
|
if stderr:
|
|
64
72
|
sys.stderr = FileLogger(sys.stderr, path, useOldStd, clearLog=clearLog)
|
|
65
73
|
if stdout:
|
|
@@ -76,6 +84,63 @@ def logToFile(path, stdout=True, stderr=True, useOldStd=True, clearLog=True):
|
|
|
76
84
|
StreamHandlerHelper.replace_stream(sys.stderr.old_stream, sys.stderr)
|
|
77
85
|
|
|
78
86
|
|
|
87
|
+
def faulthandlerToFile(path, allThreads=True, clearLog=True, force=False):
|
|
88
|
+
"""Install faulthandler so hard crashes are written to a log file.
|
|
89
|
+
|
|
90
|
+
Python normally can't report fatal errors like segfaults, they simply kill
|
|
91
|
+
the process without any output. Enabling faulthandler makes python dump the
|
|
92
|
+
traceback of each thread to a file when one of those errors happens, which
|
|
93
|
+
is often the only record of what a host application was doing when it died.
|
|
94
|
+
|
|
95
|
+
Unlike `logToFile` this doesn't touch sys.stdout/sys.stderr. faulthandler
|
|
96
|
+
writes to the file descriptor directly, so it needs a real file on disk, not
|
|
97
|
+
a `FileLogger`. The file is left open for the life of the process, closing
|
|
98
|
+
it would leave faulthandler writing to an invalid file descriptor.
|
|
99
|
+
|
|
100
|
+
If faulthandler is already enabled it's left alone unless force is used.
|
|
101
|
+
This includes it being enabled outside of this function, for example by the
|
|
102
|
+
`PYTHONFAULTHANDLER` env var or `python -X faulthandler`.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
path (str or os.PathLike): File path to write faulthandler output to. If
|
|
106
|
+
None is explicitly passed the path returned by
|
|
107
|
+
`preditor.osystem.defaultLogFile('preditorFaulthandler.log')` is used.
|
|
108
|
+
allThreads (bool): If True(default) dump the traceback of all threads,
|
|
109
|
+
otherwise only the thread that crashed.
|
|
110
|
+
clearLog (bool): If True(default) clear the log file when this command
|
|
111
|
+
is called, otherwise append to the existing contents.
|
|
112
|
+
force (bool): If True, install faulthandler even if it was already
|
|
113
|
+
enabled. Any file opened by a previous call is closed.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
bool: If faulthandler was installed by this call. False is returned if
|
|
117
|
+
it was already enabled and force was not used.
|
|
118
|
+
"""
|
|
119
|
+
global _faulthandlerFile
|
|
120
|
+
import faulthandler
|
|
121
|
+
|
|
122
|
+
if faulthandler.is_enabled() and not force:
|
|
123
|
+
logger.debug('faulthandler is already enabled, not logging to: %s', path)
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
if path is None:
|
|
127
|
+
from . import osystem
|
|
128
|
+
|
|
129
|
+
path = osystem.defaultLogFile('preditorFaulthandler.log')
|
|
130
|
+
|
|
131
|
+
# Newline forces windows to write unix style newlines
|
|
132
|
+
output = open(path, 'w' if clearLog else 'a', newline="\n", encoding="utf-8")
|
|
133
|
+
faulthandler.enable(file=output, all_threads=allThreads)
|
|
134
|
+
|
|
135
|
+
# Only close the file used by a previous call once the new one is installed
|
|
136
|
+
previous = _faulthandlerFile
|
|
137
|
+
_faulthandlerFile = output
|
|
138
|
+
if previous is not None:
|
|
139
|
+
previous.close()
|
|
140
|
+
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
|
|
79
144
|
def printCallingFunction(compact=False):
|
|
80
145
|
"""Prints and returns info about the calling function
|
|
81
146
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import absolute_import, print_function
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
import sys
|
|
4
5
|
import traceback
|
|
5
6
|
|
|
@@ -73,14 +74,24 @@ class PreditorExceptHook(object):
|
|
|
73
74
|
A newline is printed pre-traceback to ensure the first line of output
|
|
74
75
|
is not printed in-line with the prompt. This also provides visual
|
|
75
76
|
separation between tracebacks, when received consecutively.
|
|
77
|
+
|
|
78
|
+
Checks the env var `PREDITOR_WRAP_TB`, if set it will split on commas and
|
|
79
|
+
print the first item to stderr before the traceback and the second item after
|
|
80
|
+
the traceback is handled on newlines.
|
|
76
81
|
"""
|
|
77
82
|
# Print the newline to stderr so it will show up in the same stream as
|
|
78
83
|
# the traceback will be printed to.
|
|
79
84
|
print("", file=sys.stderr)
|
|
85
|
+
fixes = os.getenv("PREDITOR_WRAP_TB", "").split(",", 2)
|
|
86
|
+
if len(fixes):
|
|
87
|
+
print(fixes[0], file=sys.stderr)
|
|
80
88
|
try:
|
|
81
89
|
self.base_excepthook(*exc_info)
|
|
82
90
|
except (TypeError, NameError):
|
|
83
91
|
sys.__excepthook__(*exc_info)
|
|
92
|
+
finally:
|
|
93
|
+
if len(fixes) > 1:
|
|
94
|
+
print(fixes[1], file=sys.stderr)
|
|
84
95
|
|
|
85
96
|
@classmethod
|
|
86
97
|
def call_callbacks(cls, *exc_info):
|
|
@@ -1,29 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from Qt.QtGui import QCursor
|
|
4
|
-
from Qt.QtWidgets import QStackedWidget, QToolTip
|
|
1
|
+
from Qt.QtWidgets import QStackedWidget
|
|
5
2
|
|
|
6
3
|
from .dialog import Dialog # noqa: F401
|
|
7
4
|
from .window import Window # noqa: F401
|
|
8
5
|
|
|
9
6
|
|
|
10
|
-
def handleMenuHovered(action):
|
|
11
|
-
"""Actions in QMenus which are not descendants of a QToolBar will not show
|
|
12
|
-
their toolTips, because... Reasons?
|
|
13
|
-
"""
|
|
14
|
-
# Don't show if it's just the text of the action
|
|
15
|
-
text = re.sub(r"(?<!&)&(?!&)", "", action.text())
|
|
16
|
-
text = text.replace('...', '')
|
|
17
|
-
|
|
18
|
-
if text == action.toolTip():
|
|
19
|
-
text = ''
|
|
20
|
-
else:
|
|
21
|
-
text = action.toolTip()
|
|
22
|
-
|
|
23
|
-
menu = action.parent()
|
|
24
|
-
QToolTip.showText(QCursor.pos(), text, menu)
|
|
25
|
-
|
|
26
|
-
|
|
27
7
|
def loadUi(filename, widget, uiname=''):
|
|
28
8
|
"""use's Qt's uic loader to load dynamic interafces onto the inputed widget
|
|
29
9
|
|
|
@@ -101,72 +101,28 @@ class CodeHighlighter(QSyntaxHighlighter):
|
|
|
101
101
|
if not self.enabled():
|
|
102
102
|
return
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
self.spans = []
|
|
106
|
-
|
|
107
|
-
if not self.isConsoleMode() or str(text).startswith('>>>'):
|
|
108
|
-
|
|
109
|
-
# We only have a result pattern if the parent has an attr "outputPrompt", so
|
|
110
|
-
# only proceed if we have been able to define self._resultPattern.
|
|
111
|
-
if self._resultPattern:
|
|
112
|
-
self.highlightText(
|
|
113
|
-
text,
|
|
114
|
-
self._resultPattern,
|
|
115
|
-
self._resultFormat,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
# Format the strings
|
|
119
|
-
self.highlightText(
|
|
120
|
-
text,
|
|
121
|
-
self._stringPattern,
|
|
122
|
-
self._stringFormat,
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
# format the comments
|
|
126
|
-
self.highlightText(
|
|
127
|
-
text,
|
|
128
|
-
self._commentPattern,
|
|
129
|
-
self._commentFormat,
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
# Format the keywords
|
|
133
|
-
self.highlightText(
|
|
134
|
-
text,
|
|
135
|
-
self._keywordPattern,
|
|
136
|
-
self._keywordFormat,
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
def highlightText(self, text, expr, format):
|
|
140
|
-
"""Highlights a text group with an expression and format
|
|
141
|
-
|
|
142
|
-
Args:
|
|
143
|
-
text (str): text to highlight
|
|
144
|
-
expr (re.compile): search parameter
|
|
145
|
-
format (QTextCharFormat): formatting rule
|
|
146
|
-
"""
|
|
147
|
-
if expr is None or not text:
|
|
104
|
+
if self.isConsoleMode() and not text.startswith('>>>'):
|
|
148
105
|
return
|
|
149
106
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
self.spans.append(match_span)
|
|
107
|
+
pattern = self._highlightPattern
|
|
108
|
+
if pattern is None:
|
|
109
|
+
pattern = self.defineHighlightPattern()
|
|
110
|
+
|
|
111
|
+
# Map the named groups of the combined pattern to their formats
|
|
112
|
+
formats = {
|
|
113
|
+
"result": self._resultFormat,
|
|
114
|
+
"string": self._stringFormat,
|
|
115
|
+
"comment": self._commentFormat,
|
|
116
|
+
"keyword": self._keywordFormat,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# The combined pattern finds the leftmost highlight first and continues
|
|
120
|
+
# searching after it. This prevents highlighting text inside of an
|
|
121
|
+
# existing highlight, for example a keyword inside a string or comment.
|
|
122
|
+
setFormat = self.setFormat
|
|
123
|
+
for match in pattern.finditer(text):
|
|
124
|
+
start, end = match.span()
|
|
125
|
+
setFormat(start, end - start, formats[match.lastgroup])
|
|
170
126
|
|
|
171
127
|
def isConsoleMode(self):
|
|
172
128
|
"""checks to see if this highlighter is in console mode"""
|
|
@@ -267,12 +223,40 @@ class CodeHighlighter(QSyntaxHighlighter):
|
|
|
267
223
|
"""Define the regex pattern to use for comment"""
|
|
268
224
|
pattern = "|".join(self._comments)
|
|
269
225
|
self._commentPattern = re.compile(pattern)
|
|
226
|
+
self._highlightPattern = None
|
|
227
|
+
|
|
228
|
+
def defineHighlightPattern(self):
|
|
229
|
+
"""Combine the result, string, comment and keyword patterns into a
|
|
230
|
+
single regex pattern with a named group for each. Searching once with
|
|
231
|
+
this pattern is much faster than searching for each pattern separately.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
re.Pattern: The combined pattern, also stored on this instance.
|
|
235
|
+
"""
|
|
236
|
+
parts = []
|
|
237
|
+
for name, expr in (
|
|
238
|
+
("result", self._resultPattern),
|
|
239
|
+
("string", self._stringPattern),
|
|
240
|
+
("comment", self._commentPattern),
|
|
241
|
+
("keyword", self._keywordPattern),
|
|
242
|
+
):
|
|
243
|
+
# Patterns that match empty text would prevent the other patterns
|
|
244
|
+
# from matching so skip them, they wouldn't highlight anything.
|
|
245
|
+
if expr is not None and expr.pattern:
|
|
246
|
+
parts.append(f"(?P<{name}>{expr.pattern})")
|
|
247
|
+
|
|
248
|
+
# If there is nothing to highlight, use a pattern that never matches.
|
|
249
|
+
self._highlightPattern = re.compile("|".join(parts) or "(?!)")
|
|
250
|
+
return self._highlightPattern
|
|
270
251
|
|
|
271
252
|
def defineKeywordPattern(self):
|
|
272
253
|
"""Define the regex pattern to use for keyword"""
|
|
273
|
-
|
|
274
|
-
|
|
254
|
+
pattern = ""
|
|
255
|
+
if self._keywords:
|
|
256
|
+
keywords = "|".join(self._keywords)
|
|
257
|
+
pattern = rf"\b(?:{keywords})\b"
|
|
275
258
|
self._keywordPattern = re.compile(pattern)
|
|
259
|
+
self._highlightPattern = None
|
|
276
260
|
|
|
277
261
|
def defineResultPattern(self):
|
|
278
262
|
"""Define the regex pattern to use for results"""
|
|
@@ -281,9 +265,11 @@ class CodeHighlighter(QSyntaxHighlighter):
|
|
|
281
265
|
prompt = parent.outputPrompt()
|
|
282
266
|
pattern = '{}[^\n]*'.format(prompt)
|
|
283
267
|
self._resultPattern = re.compile(pattern)
|
|
268
|
+
self._highlightPattern = None
|
|
284
269
|
|
|
285
270
|
def defineStringPattern(self):
|
|
286
271
|
"""Define the regex pattern to use for strings."""
|
|
287
272
|
lst = ["""{0}[^{0}\n]*{0}""".format(st) for st in self._strings]
|
|
288
273
|
pattern = "|".join(lst)
|
|
289
274
|
self._stringPattern = re.compile(pattern)
|
|
275
|
+
self._highlightPattern = None
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from __future__ import absolute_import
|
|
2
2
|
|
|
3
|
+
import heapq
|
|
3
4
|
import inspect
|
|
4
5
|
import re
|
|
5
6
|
import sys
|
|
6
7
|
from enum import Enum
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
from Qt.
|
|
10
|
-
from Qt.
|
|
11
|
-
from Qt.QtWidgets import QCompleter, QToolTip
|
|
9
|
+
from Qt.QtCore import QRegularExpression, QSortFilterProxyModel, QStringListModel, Qt
|
|
10
|
+
from Qt.QtGui import QCursor, QFontMetrics, QTextCursor
|
|
11
|
+
from Qt.QtWidgets import QCompleter, QStyle, QToolTip
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class CompleterMode(Enum):
|
|
@@ -53,6 +53,9 @@ class PythonCompleter(QCompleter):
|
|
|
53
53
|
|
|
54
54
|
# update this completer
|
|
55
55
|
self.setWidget(widget)
|
|
56
|
+
# All items use the same font, so let the popup skip measuring every row
|
|
57
|
+
# when laying out large lists.
|
|
58
|
+
self.popup().setUniformItemSizes(True)
|
|
56
59
|
|
|
57
60
|
self.setCaseSensitive()
|
|
58
61
|
self.setCompleterMode()
|
|
@@ -136,6 +139,27 @@ class PythonCompleter(QCompleter):
|
|
|
136
139
|
def hideDocumentation(self):
|
|
137
140
|
QToolTip.hideText()
|
|
138
141
|
|
|
142
|
+
def popupWidth(self, sampleCount=20):
|
|
143
|
+
"""Returns the width needed to show the longest completions in the popup.
|
|
144
|
+
|
|
145
|
+
This is much faster than `popup().sizeHintForColumn(0)` for large lists
|
|
146
|
+
as that measures every row using the item delegate. Instead only the
|
|
147
|
+
`sampleCount` longest completions are measured.
|
|
148
|
+
"""
|
|
149
|
+
popup = self.popup()
|
|
150
|
+
model = self.completionModel()
|
|
151
|
+
completions = (model.index(row, 0).data() for row in range(model.rowCount()))
|
|
152
|
+
longest = heapq.nlargest(sampleCount, completions, key=len)
|
|
153
|
+
|
|
154
|
+
metrics = QFontMetrics(popup.font())
|
|
155
|
+
textWidth = max((metrics.horizontalAdvance(t) for t in longest), default=0)
|
|
156
|
+
# Match the text margins QStyledItemDelegate adds on each side of the text.
|
|
157
|
+
margin = popup.style().pixelMetric(
|
|
158
|
+
QStyle.PixelMetric.PM_FocusFrameHMargin, None, popup
|
|
159
|
+
)
|
|
160
|
+
scrollBarWidth = popup.verticalScrollBar().sizeHint().width()
|
|
161
|
+
return textWidth + (margin + 1) * 2 + scrollBarWidth
|
|
162
|
+
|
|
139
163
|
def refreshList(self, scope=None):
|
|
140
164
|
"""refreshes the string list based on the cursor word"""
|
|
141
165
|
object, prefix = self.currentObject(scope)
|
|
@@ -150,24 +174,28 @@ class PythonCompleter(QCompleter):
|
|
|
150
174
|
except AttributeError:
|
|
151
175
|
keys = []
|
|
152
176
|
keys.sort()
|
|
153
|
-
|
|
177
|
+
# Resetting the model can get expensive for large lists, this is called
|
|
178
|
+
# on every key press while the popup is visible, but the keys only change
|
|
179
|
+
# when the object being completed changes.
|
|
180
|
+
sourceModel = self.model().sourceModel()
|
|
181
|
+
if keys != sourceModel.stringList():
|
|
182
|
+
sourceModel.setStringList(keys)
|
|
154
183
|
|
|
155
184
|
regExStr = ""
|
|
156
185
|
if self._completerMode == CompleterMode.STARTS_WITH:
|
|
157
|
-
regExStr = "^{
|
|
186
|
+
regExStr = f"^{QRegularExpression.escape(prefix)}"
|
|
158
187
|
if self._completerMode == CompleterMode.OUTER_FUZZY:
|
|
159
|
-
regExStr =
|
|
188
|
+
regExStr = QRegularExpression.escape(prefix)
|
|
160
189
|
if self._completerMode == CompleterMode.FULL_FUZZY:
|
|
161
|
-
regExStr = ".*".join(prefix)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
190
|
+
regExStr = ".*".join(QRegularExpression.escape(c) for c in prefix)
|
|
191
|
+
|
|
192
|
+
regexp = QRegularExpression(regExStr)
|
|
193
|
+
if self._sensitivity == Qt.CaseSensitivity.CaseInsensitive:
|
|
194
|
+
regexp.setPatternOptions(
|
|
195
|
+
QRegularExpression.PatternOption.CaseInsensitiveOption
|
|
196
|
+
)
|
|
197
|
+
if regexp != self.filterModel.filterRegularExpression():
|
|
167
198
|
self.filterModel.setFilterRegularExpression(regexp)
|
|
168
|
-
else:
|
|
169
|
-
regexp = QRegExp(regExStr, self._sensitivity)
|
|
170
|
-
self.filterModel.setFilterRegExp(regexp)
|
|
171
199
|
|
|
172
200
|
def clear(self):
|
|
173
201
|
self.popup().hide()
|
|
@@ -135,6 +135,7 @@ class ConsolePrEdit(ConsoleBase):
|
|
|
135
135
|
|
|
136
136
|
def clear(self):
|
|
137
137
|
"""clears the text in the editor"""
|
|
138
|
+
self._pending_writes = []
|
|
138
139
|
super(ConsoleBase, self).clear()
|
|
139
140
|
self.startInputLine()
|
|
140
141
|
# Note: Don't use the regular `super()` call here as it would result
|
|
@@ -483,15 +484,18 @@ class ConsolePrEdit(ConsoleBase):
|
|
|
483
484
|
self.controller
|
|
484
485
|
and self.controller.uiHighlightExactCompletionCHK.isChecked()
|
|
485
486
|
):
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
487
|
+
# Find the first completion that equals prefix. Let Qt
|
|
488
|
+
# search the model, as checking each row from python is
|
|
489
|
+
# slow for large lists.
|
|
490
|
+
flags = Qt.MatchFlag.MatchFixedString
|
|
491
|
+
if prefix != prefix.lower():
|
|
492
|
+
# Handle lowercase options
|
|
493
|
+
flags |= Qt.MatchFlag.MatchCaseSensitive
|
|
494
|
+
matches = model.match(
|
|
495
|
+
index, Qt.ItemDataRole.DisplayRole, prefix, 1, flags
|
|
496
|
+
)
|
|
497
|
+
if matches:
|
|
498
|
+
index = matches[0]
|
|
495
499
|
|
|
496
500
|
# Set completer current Row, so finishing the completer will use
|
|
497
501
|
# correct text
|
|
@@ -504,10 +508,7 @@ class ConsolePrEdit(ConsoleBase):
|
|
|
504
508
|
|
|
505
509
|
# show the completer for the rect
|
|
506
510
|
rect = self.cursorRect()
|
|
507
|
-
rect.setWidth(
|
|
508
|
-
completer.popup().sizeHintForColumn(0)
|
|
509
|
-
+ completer.popup().verticalScrollBar().sizeHint().width()
|
|
510
|
-
)
|
|
511
|
+
rect.setWidth(completer.popupWidth())
|
|
511
512
|
completer.complete(rect)
|
|
512
513
|
|
|
513
514
|
if completer.popup().isVisible():
|