diff --git a/dev/pyRevitLabs.PyRevit.Runtime/ScriptConsole.cs b/dev/pyRevitLabs.PyRevit.Runtime/ScriptConsole.cs index 8e71bde5d..9068ee6c5 100644 --- a/dev/pyRevitLabs.PyRevit.Runtime/ScriptConsole.cs +++ b/dev/pyRevitLabs.PyRevit.Runtime/ScriptConsole.cs @@ -14,6 +14,7 @@ using pyRevitLabs.Common; using pyRevitLabs.CommonWPF.Controls; using pyRevitLabs.Emojis; +using pyRevitLabs.PyRevit; namespace PyRevitLabs.PyRevit.Runtime { public struct ScriptConsoleDebugger { @@ -171,7 +172,7 @@ public partial class ScriptConsole : ScriptConsoleTemplate, IComponentConnector, private System.Windows.Forms.HtmlElement _lastDocumentBody = null; private UIApplication _uiApp; - private List _supportedDebuggers = + private List _supportedDebuggers = new List { new ScriptConsoleDebugger() { Name = "Pdb (IronPython|CPython)", @@ -376,6 +377,27 @@ public string GetFullHtml() { return ScriptConsoleConfigs.DOCTYPE + head.OuterHtml + ActiveDocument.Body.OuterHtml; } + private void ApplyCloseOthersConfig() + { + if (PyRevitConfigs.GetCloseOtherOutputs()) + { + var mode = PyRevitConfigs.GetCloseOutputMode(); + this.Dispatcher.BeginInvoke(new Action(() => + { + CloseOtherOutputs(filterByCommandId: mode == OutputCloseMode.CurrentCommand); + })); + } + } + + public void CloseOtherOutputs(bool filterByCommandId = true) { + try { + var filterId = filterByCommandId ? this.OutputId : null; + ScriptConsoleManager.CloseActiveOutputWindows(excludeOutputWindow: this, filterOutputWindowId: filterId); + } + catch { + } + } + private void SetupDefaultPage(string styleSheetFilePath = null) { string cssFilePath; if (styleSheetFilePath != null) @@ -448,7 +470,7 @@ public void FocusOutput() { public System.Windows.Forms.HtmlElement ComposeEntry(string contents, string HtmlElementType) { WaitReadyBrowser(); - + // order is important // "<" ---> < contents = ScriptConsoleConfigs.EscapeForHtml(contents); @@ -552,7 +574,7 @@ public string GetInput() { dbgMode = true; } } - + // if no debugger, find other patterns if (!dbgMode && new string[] { "select", "file" }.All(x => lastLine.Contains(x))) @@ -782,6 +804,7 @@ public void SelfDestructTimer(int seconds) { private void Window_Loaded(object sender, System.EventArgs e) { var outputWindow = (ScriptConsole)sender; ScriptConsoleManager.AppendToOutputWindowList(this); + ApplyCloseOthersConfig(); } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { diff --git a/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConfigs.cs b/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConfigs.cs index 281f3c0f6..3b13eed9e 100644 --- a/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConfigs.cs +++ b/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConfigs.cs @@ -35,6 +35,12 @@ public enum PyRevitLogLevels Debug } + public enum OutputCloseMode + { + CurrentCommand, + CloseAll + } + public static class PyRevitConfigs { private static readonly Logger logger = LogManager.GetCurrentClassLogger(); @@ -505,6 +511,45 @@ public static void SetLoadBetaTools(bool state) cfg.SetValue(PyRevitConsts.ConfigsCoreSection, PyRevitConsts.ConfigsLoadBetaKey, state); } + // close other outputs config + public static bool GetCloseOtherOutputs() + { + var cfg = GetConfigFile(); + var status = cfg.GetValue(PyRevitConsts.ConfigsCoreSection, PyRevitConsts.ConfigsCloseOtherOutputsKey); + return status != null ? bool.Parse(status) : PyRevitConsts.ConfigsCloseOtherOutputsDefault; + } + + public static void SetCloseOtherOutputs(bool state) + { + var cfg = GetConfigFile(); + cfg.SetValue(PyRevitConsts.ConfigsCoreSection, PyRevitConsts.ConfigsCloseOtherOutputsKey, state); + } + + public static OutputCloseMode GetCloseOutputMode() + { + var cfg = GetConfigFile(); + var raw = cfg.GetValue(PyRevitConsts.ConfigsCoreSection, PyRevitConsts.ConfigsCloseOutputModeKey); + + var s = (raw ?? PyRevitConsts.ConfigsCloseOutputModeDefault).Trim().Trim('"', '\''); + + if (s.Equals(PyRevitConsts.ConfigsCloseOutputModeCloseAll, StringComparison.InvariantCultureIgnoreCase)) + { + return OutputCloseMode.CloseAll; + } + + return OutputCloseMode.CurrentCommand; + } + + public static void SetCloseOutputMode(OutputCloseMode mode) + { + var cfg = GetConfigFile(); + var value = (mode == OutputCloseMode.CloseAll) + ? PyRevitConsts.ConfigsCloseOutputModeCloseAll + : PyRevitConsts.ConfigsCloseOutputModeCurrentCommand; + + cfg.SetValue(PyRevitConsts.ConfigsCoreSection, PyRevitConsts.ConfigsCloseOutputModeKey, value); + } + // cpythonengine public static int GetCpythonEngineVersion() { diff --git a/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs b/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs index 7a9379536..2952412b6 100644 --- a/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs +++ b/dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs @@ -42,7 +42,7 @@ public static class PyRevitConsts { public const string ReleaseDirName = "release"; public const string SitePackagesDirName = "site-packages"; public const string PyRevitfileFilename = "PyRevitfile"; - + public const string NetFxFolder = "netfx"; public const string NetCoreFolder = "netcore"; @@ -85,6 +85,12 @@ public static class PyRevitConsts { public const int ConfigsMinDriveSpaceDefault = 0; public const string ConfigsLoadBetaKey = "loadbeta"; public const bool ConfigsLoadBetaDefault = false; + public const string ConfigsCloseOtherOutputsKey = "closeotheroutputs"; + public const bool ConfigsCloseOtherOutputsDefault = false; + public const string ConfigsCloseOutputModeKey = "closeoutputmode"; + public const string ConfigsCloseOutputModeDefault = "currentcommand"; + public const string ConfigsCloseOutputModeCurrentCommand = "currentcommand"; + public const string ConfigsCloseOutputModeCloseAll = "closeall"; public const string ConfigsCPythonEngineKey = "cpyengine"; public const int ConfigsCPythonEngineDefault = 0; public const string ConfigsLocaleKey = "user_locale"; @@ -179,7 +185,7 @@ public static class PyRevitConsts { public static string FindConfigFileInDirectory(string sourcePath) { var configMatcher = new Regex(ConfigsFileRegexPattern, RegexOptions.IgnoreCase); // capture exceptions that might occur getting the files under sourcePath - // + // try { if (CommonUtils.VerifyPath(sourcePath)) foreach (string subFile in Directory.GetFiles(sourcePath)) diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.en_us.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.en_us.xaml index 295cf6646..e27fcb3e4 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.en_us.xaml +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.en_us.xaml @@ -57,6 +57,23 @@ Misc options for pyRevit development Load Beta Tools (Scripts with __beta__ = True, Reload is required) + Close other open consoles + + If enabled, pyRevit will close other output consoles when a new script is run. + This helps to reduce the number of open output windows. Activate this option, unless you want to compare + multiple output data. + + + Current command consoles + + Close all console windows associated with the current running command. + + + All consoles + + Close all currently open console windows, even those that are not associated with the running command. + + Caching Reset Caching to default 200 diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.fr_fr.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.fr_fr.xaml index 338cf6e85..281d8e5de 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.fr_fr.xaml +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.fr_fr.xaml @@ -57,6 +57,23 @@ Options diverses pour le développement de pyRevit Charger les outils bêta (Scripts avec __beta__ = True, le rechargement est requis) + Fermer les consoles ouvertes + + Si activé, pyRevit fermera les autres consoles de sortie lors de l'exécution d'un nouveau script. + Cela permet de réduire le nombre de fenêtres de sortie ouvertes. Activez cette option, sauf si vous + voulez comparer les sorties de plusieurs scripts. + + + Consoles de la commande actuelle + + Fermer toutes les fenêtres de console associées à la commande en cours d'exécution. + + + Toutes les consoles + + Fermer toutes les fenêtres de console actuellement ouvertes, même celles qui ne sont pas associées à la commande en cours. + + Mise en cache Reset la mise en cache par défaut 200 diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ru.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ru.xaml index 6080cde86..dc1f57968 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ru.xaml +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ru.xaml @@ -58,6 +58,23 @@ Разные настройки разработки pyRevit Загружать бета-инструменты (Скрипты с __beta__ = True, требуется перезапуск) + Закрывать другие открытые консоли + + Если включено, pyRevit будет закрывать другие консоли вывода при запуске нового скрипта. + Это помогает уменьшить количество открытых окон вывода. Активируйте эту опцию, если вам + не требуется сравнивать данные из нескольких окон вывода. + + + Консоли текущей команды + + Закрыть все окна консоли, связанные с текущей выполняемой командой. + + + Все консоли + + Закрыть все открытые в данный момент окна консоли, даже те, которые не связаны с выполняемой командой. + + Кеширование Сбросить настройки кеширования 220 diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml index d208f7d4c..3ddf230fe 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml @@ -205,6 +205,23 @@ + + + + + + + + + + + + + + + + + diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/bundle.yaml b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/bundle.yaml index 37a2fc2e5..c8ac032b6 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/bundle.yaml +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/bundle.yaml @@ -38,3 +38,5 @@ tooltip: Zeigt die Konfigurationsdatei im Explorer an. context: zero-doc +engine: + clean: true diff --git a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py index 553d553ea..6477d9524 100644 --- a/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py +++ b/extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py @@ -157,6 +157,16 @@ def _setup_core_options(self): self.loadbetatools_cb.IsChecked = user_config.load_beta + self.minimize_consoles_cb.IsChecked = user_config.output_close_others + + mode = user_config.output_close_mode_enum + if mode == PyRevit.OutputCloseMode.CurrentCommand: + self.closewindows_current_rb.IsChecked = True + self.closewindows_close_all_rb.IsChecked = False + else: + self.closewindows_current_rb.IsChecked = False + self.closewindows_close_all_rb.IsChecked = True + def _setup_engines(self): """Sets up the list of available engines.""" attachment = user_config.get_current_attachment() @@ -846,6 +856,12 @@ def _save_core_options(self): user_config.load_beta = self.loadbetatools_cb.IsChecked + user_config.output_close_others = self.minimize_consoles_cb.IsChecked + if self.closewindows_current_rb.IsChecked: + user_config.output_close_mode_enum = PyRevit.OutputCloseMode.CurrentCommand + else: + user_config.output_close_mode_enum = PyRevit.OutputCloseMode.CloseAll + def _save_engines(self): # set active cpython engine engine_cfg = self.cpythonEngines.SelectedItem diff --git a/pyrevitlib/pyrevit/script.py b/pyrevitlib/pyrevit/script.py index 1f3bf9ca7..89f2fcc01 100644 --- a/pyrevitlib/pyrevit/script.py +++ b/pyrevitlib/pyrevit/script.py @@ -264,7 +264,7 @@ def get_data_file(file_id, file_ext, add_cmd_name=False): script.get_data_file('mydata', 'data', add_cmd_name=True) ``` '/pyRevit_2018_Command Name_mydata.data' - + Data files are not cleaned up at pyRevit startup. Script should manage cleaning up these files. @@ -547,7 +547,7 @@ def load_ui(ui_instance, ui_file='ui.xaml', handle_esc=True, set_owner=True): """Load xaml file into given window instance. If window instance defines a method named `setup` it - will be called after loading + will be called after loading Args: ui_instance (forms.WPFWindow): ui form instance @@ -679,29 +679,29 @@ def store_data(slot_name, data, this_project=True): ```python from pyrevit import revit from pyrevit import script - - + + class CustomData(object): def __init__(self, count, element_ids): self._count = count # serializes the Revit native objects self._elmnt_ids = [revit.serialize(x) for x in element_ids] - + @property def count(self): return self._count - + @property def element_ids(self): # de-serializes the Revit native objects return [x.deserialize() for x in self._elmnt_ids] - - + + mydata = CustomData( count=3, element_ids=[, , ] ) - + script.store_data("Selected Elements", mydata) ``` @@ -740,24 +740,24 @@ def load_data(slot_name, this_project=True): ```python from pyrevit import revit from pyrevit import script - - + + class CustomData(object): def __init__(self, count, element_ids): self._count = count # serializes the Revit native objects self._elmnt_ids = [revit.serialize(x) for x in element_ids] - + @property def count(self): return self._count - + @property def element_ids(self): # de-serializes the Revit native objects return [x.deserialize() for x in self._elmnt_ids] - - + + mydata = script.load_data("Selected Elements") mydata.element_ids ``` diff --git a/pyrevitlib/pyrevit/userconfig.py b/pyrevitlib/pyrevit/userconfig.py index 7af641dfa..8363a4610 100644 --- a/pyrevitlib/pyrevit/userconfig.py +++ b/pyrevitlib/pyrevit/userconfig.py @@ -50,8 +50,7 @@ from pyrevit.coreutils import configparser from pyrevit.coreutils import logger from pyrevit.versionmgr import upgrade - - +# pylint: disable=C0103,C0413,W0703 DEFAULT_CSV_SEPARATOR = ',' @@ -302,6 +301,52 @@ def load_beta(self, state): value=state ) + @property + def output_close_others(self): + """Whether to close other output windows.""" + return self.core.get_option( + CONSTS.ConfigsCloseOtherOutputsKey, + default_value=CONSTS.ConfigsCloseOtherOutputsDefault, + ) + + @output_close_others.setter + def output_close_others(self, state): + self.core.set_option( + CONSTS.ConfigsCloseOtherOutputsKey, + value=state + ) + + @property + def output_close_mode_enum(self): + """Output window closing mode as enum (CurrentCommand | CloseAll).""" + value = self.core.get_option( + CONSTS.ConfigsCloseOutputModeKey, + default_value=CONSTS.ConfigsCloseOutputModeDefault, + ) + if not value: + value = CONSTS.ConfigsCloseOutputModeDefault + + value_lc = str(value).lower() + + if value_lc == str(CONSTS.ConfigsCloseOutputModeCloseAll).lower(): + return PyRevit.OutputCloseMode.CloseAll + else: + return PyRevit.OutputCloseMode.CurrentCommand + + @output_close_mode_enum.setter + def output_close_mode_enum(self, mode): + """Store string in INI, mapped from enum.""" + if mode == PyRevit.OutputCloseMode.CloseAll: + self.core.set_option( + CONSTS.ConfigsCloseOutputModeKey, + value=CONSTS.ConfigsCloseOutputModeCloseAll + ) + else: + self.core.set_option( + CONSTS.ConfigsCloseOutputModeKey, + value=CONSTS.ConfigsCloseOutputModeCurrentCommand + ) + @property def cpython_engine_version(self): """CPython engine version to use."""