├── .gitignore ├── LICENSE.md ├── PsISEProjectExplorer.Tests ├── Properties │ └── AssemblyInfo.cs ├── PsISEProjectExplorer.Tests.csproj ├── UI │ └── ViewModel │ │ └── IconProviderTest.cs └── packages.config ├── PsISEProjectExplorer ├── Bootstrap.cs ├── Commands │ ├── AddNewTreeItemCommand.cs │ ├── ChangeWorkspaceCommand.cs │ ├── ClearSearchTextCommand.cs │ ├── ClearTreeViewCommand.cs │ ├── CloseAllButThisCommand.cs │ ├── CollapseAllCommand.cs │ ├── Command.cs │ ├── CommandExecutor.cs │ ├── DeleteItemCommand.cs │ ├── DotSourceCommand.cs │ ├── EndEditingTreeItemCommand.cs │ ├── ExcludeOrIncludeItemCommand.cs │ ├── FindAllOccurrencesCommand.cs │ ├── FindInFilesCommand.cs │ ├── GoToDefinitionCommand.cs │ ├── LocateFileInTreeCommand.cs │ ├── MoveItemCommand.cs │ ├── OpenBuiltinContextMenuCommand.cs │ ├── OpenExplorerContextMenuCommand.cs │ ├── OpenInExplorerCommand.cs │ ├── OpenItemCommand.cs │ ├── ParameterizedCommand.cs │ ├── ReindexSearchTreeCommand.cs │ ├── RenameItemCommand.cs │ ├── ResetWorkspaceDirectoryCommand.cs │ ├── RunSearchCommand.cs │ ├── SelectItemCommand.cs │ ├── SyncWithActiveDocumentCommand.cs │ └── UnsavedFileChecker.cs ├── Component.cs ├── Config │ ├── ApplicationConfig.cs │ ├── ConfigHandler.cs │ └── ConfigValues.cs ├── Contrib │ └── Regex │ │ ├── CSharpRegexCapabilities.cs │ │ ├── IRegexCapabilities.cs │ │ ├── IRegexQueryCapable.cs │ │ ├── RegexQuery.cs │ │ └── RegexTermEnum.cs ├── Debug_LoadToIse.bat ├── Debug_LoadToIse.ps1 ├── Enums │ ├── FullTextFieldType.cs │ ├── NodeType.cs │ └── PowershellItemType.cs ├── FullText │ ├── CustomAnalyzer.cs │ ├── CustomQueryParser.cs │ ├── CustomTokenizer.cs │ ├── DocumentFactory.cs │ ├── FullTextDirectory.cs │ └── TokenizeRules.cs ├── Install_to_PsGallery.ps1 ├── Install_to_UserModules.bat ├── Install_to_UserModules.ps1 ├── Model │ ├── ChangePoolEntry.cs │ ├── DocHierarchy │ │ ├── DocumentHierarchy.cs │ │ └── Nodes │ │ │ ├── AbstractNode.cs │ │ │ ├── DirectoryNode.cs │ │ │ ├── FileNode.cs │ │ │ ├── INode.cs │ │ │ ├── NodeComparerAlphabetical.cs │ │ │ ├── NodeComparerAsIs.cs │ │ │ ├── NodeComparerProvider.cs │ │ │ ├── PowershellItemNode.cs │ │ │ ├── RootNode.cs │ │ │ └── ViewNode.cs │ ├── EditorInfo.cs │ ├── FileSystemChangedInfo.cs │ ├── IndexingMode.cs │ ├── LineInfo.cs │ ├── PowershellItem.cs │ ├── PowershellParseResult.cs │ ├── PowershellRegion.cs │ ├── SearchOptions.cs │ ├── SearchResult.cs │ └── TokenPosition.cs ├── NLog.config ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── PsISEProjectExplorer.csproj ├── PsISEProjectExplorer.psd1 ├── PsISEProjectExplorer.psm1 ├── PsISEProjectExplorer.xaml ├── PsISEProjectExplorer.xaml.cs ├── Resources │ ├── add.png │ ├── cancel.png │ ├── cross.png │ ├── node_class.png │ ├── node_classconstructor.png │ ├── node_classproperty.png │ ├── node_configuration.png │ ├── node_directory.png │ ├── node_dslelement.png │ ├── node_file.png │ ├── node_function.png │ ├── node_overlay_excluded.png │ ├── node_overlay_invalid.png │ ├── node_region.png │ ├── textfield_dotsource.png │ ├── textfield_exclude.png │ ├── textfield_include.png │ ├── textfield_rename.png │ ├── toolbar_autoUpdateProjectDir.png │ ├── toolbar_index_all.png │ ├── toolbar_index_local.png │ ├── toolbar_refresh.png │ ├── toolbar_searchRegex.png │ ├── toolbar_showAllFiles.png │ ├── toolbar_sort.png │ ├── toolbar_sync.png │ ├── toolbar_toggle-expand.png │ └── toolbar_toggle_collapse.png ├── Services │ ├── DocumentHierarchyFactory.cs │ ├── DocumentHierarchyIndexer.cs │ ├── DocumentHierarchySearcher.cs │ ├── FileReader.cs │ ├── FileSystemChangeNotifier.cs │ ├── FileSystemChangeWatcher.cs │ ├── FileSystemOperationsService.cs │ ├── FilesPatternProvider.cs │ ├── IPowershellTokenizer.cs │ ├── Powershell5Tokenizer.cs │ ├── PowershellBaseTokenizer.cs │ ├── PowershellFileParser.cs │ ├── PowershellLegacyTokenVisitor.cs │ ├── PowershellLegacyTokenizer.cs │ ├── PowershellTokenizerProvider.cs │ ├── PowershellTreeRestructurer.cs │ ├── RootDirectoryProvider.cs │ └── TokenLocator.cs ├── UI │ ├── GongSolutions.Shell │ │ ├── Interop │ │ │ ├── BHID.cs │ │ │ ├── CoClass.cs │ │ │ ├── ComCtl32.cs │ │ │ ├── HResult.cs │ │ │ ├── ICommDlgBrowser.cs │ │ │ ├── IContextMenu.cs │ │ │ ├── IDropSource.cs │ │ │ ├── IDropTarget.cs │ │ │ ├── IEnumIDList.cs │ │ │ ├── IFileDialog.cs │ │ │ ├── IKnownFolder.cs │ │ │ ├── IKnownFolderManager.cs │ │ │ ├── IOleCommandTarget.cs │ │ │ ├── IQueryInfo.cs │ │ │ ├── IServiceProvider.cs │ │ │ ├── IShellBrowser.cs │ │ │ ├── IShellFolder.cs │ │ │ ├── IShellItem.cs │ │ │ ├── IShellItemArray.cs │ │ │ ├── IShellView.cs │ │ │ ├── Kernel32.cs │ │ │ ├── Ole32.cs │ │ │ ├── Shell32.cs │ │ │ ├── ShlWapi.cs │ │ │ ├── User32.cs │ │ │ └── VistaBridge │ │ │ │ └── ShellItemImpl.cs │ │ ├── KnownFolderManager.cs │ │ ├── Licence.md │ │ ├── ShellContextMenu.cs │ │ └── ShellItem.cs │ ├── Helpers │ │ ├── DragDropHandler.cs │ │ ├── EmptyListToVisibilityConverter.cs │ │ ├── FocusExtensions.cs │ │ ├── IndexingModeConverter.cs │ │ ├── LockedToolBar.cs │ │ ├── MessageBoxHelper.cs │ │ ├── StretchingTreeView.cs │ │ ├── TreeViewDropHighlighter.cs │ │ ├── TreeViewHelper.cs │ │ ├── TreeViewMouseHelper.cs │ │ └── TreeViewSpecialCharactersHandler.cs │ ├── IseIntegration │ │ ├── IseEventArgs.cs │ │ ├── IseFileReloader.cs │ │ ├── IseFileWatcher.cs │ │ └── IseIntegrator.cs │ ├── Ookii.Dialogs.Wpf │ │ ├── Interop │ │ │ ├── COMGuids.cs │ │ │ ├── ErrorHelper.cs │ │ │ ├── ShellComInterfaces.cs │ │ │ └── ShellWrapperDefinitions.cs │ │ ├── NativeMethods.cs │ │ ├── SafeHandles.cs │ │ ├── VistaFolderBrowserDialog.cs │ │ └── license.txt │ ├── ViewModel │ │ ├── BaseViewModel.cs │ │ ├── DefaultTreeViewEntryItemComparer.cs │ │ ├── IconProvider.cs │ │ ├── MainViewModel.cs │ │ ├── TreeViewEntryItemModel.cs │ │ ├── TreeViewEntryItemModelState.cs │ │ ├── TreeViewEntryItemObservableSet.cs │ │ ├── TreeViewModel.cs │ │ └── WorkspaceDirectoryModel.cs │ └── Workers │ │ ├── BackgroundIndexer.cs │ │ ├── BackgroundIndexerParams.cs │ │ ├── BackgroundSearcher.cs │ │ ├── BackgroundSearcherParams.cs │ │ ├── IndexerResult.cs │ │ └── SearcherResult.cs └── packages.config ├── PsISEProjectExplorerPS5 ├── Properties │ └── AssemblyInfo.cs ├── PsISEProjectExplorerPS5.csproj └── Services │ └── Powershell5TokenVisitor.cs ├── PsISEProjectExplorer_screen.png ├── PsISEProjectExplorer_screen_dsl.png ├── PsIseProjectExplorer.sln ├── PsIseProjectExplorer.sln.DotSettings └── README.md /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Marcin Grzywa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PsISEProjectExplorer.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PsISEProjectExplorer.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PsISEProjectExplorer.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016 Marcin Grzywa")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("80493b05-f311-47ad-b361-a2ccba29082a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PsISEProjectExplorer.Tests/UI/ViewModel/IconProviderTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using PsISEProjectExplorer.Enums; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Media; 11 | 12 | namespace PsISEProjectExplorer.Tests.UI.ViewModel 13 | { 14 | [TestFixture] 15 | public class IconProviderTest 16 | { 17 | 18 | private IconProvider iconProvider; 19 | 20 | private String testFileName; 21 | 22 | [OneTimeSetUp] 23 | public void Setup() 24 | { 25 | if (!UriParser.IsKnownScheme("pack")) 26 | new System.Windows.Application(); 27 | this.iconProvider = new IconProvider(); 28 | this.testFileName = Path.GetTempFileName(); 29 | File.Create(testFileName).Close(); 30 | } 31 | 32 | [OneTimeTearDown] 33 | public void Teardown() 34 | { 35 | File.Delete(testFileName); 36 | } 37 | 38 | [Test] 39 | public void GetImageSourceForFileSystemEntryShouldReturnShellIconWhenIsNotExcludedAndIsValid() 40 | { 41 | ImageSource result = iconProvider.GetImageSourceForFileSystemEntry(testFileName, false, true); 42 | Assert.That(result, Is.Not.Null); 43 | Assert.That(result, Is.Not.AssignableFrom()); 44 | Assert.That(result.Width, Is.GreaterThan(0)); 45 | } 46 | 47 | [Test] 48 | public void GetImageSourceForFileSystemEntryShouldReturnOverlayedIconWhenIsNotExcludedAndIsNotValid() 49 | { 50 | ImageSource result = iconProvider.GetImageSourceForFileSystemEntry(testFileName, false, false); 51 | Assert.That(result, Is.Not.Null); 52 | Assert.That(result, Is.AssignableFrom()); 53 | Assert.That(result.Width, Is.GreaterThan(0)); 54 | } 55 | 56 | [Test] 57 | public void GetImageSourceForFileSystemEntryShouldReturnOverlayedIconWhenIsExcludedAndIsNotValid() 58 | { 59 | ImageSource result = iconProvider.GetImageSourceForFileSystemEntry(testFileName, true, false); 60 | Assert.That(result, Is.Not.Null); 61 | Assert.That(result, Is.AssignableFrom()); 62 | Assert.That(result.Width, Is.GreaterThan(0)); 63 | } 64 | 65 | [Test] 66 | public void GetImageSourceForFileSystemEntryShouldReturnOverlayedIconWhenIsExcludedAndIsValid() 67 | { 68 | ImageSource result = iconProvider.GetImageSourceForFileSystemEntry(testFileName, true, true); 69 | Assert.That(result, Is.Not.Null); 70 | Assert.That(result, Is.AssignableFrom()); 71 | Assert.That(result.Width, Is.GreaterThan(0)); 72 | } 73 | 74 | [Test] 75 | public void GetImageSourceForPowershellItemEntryShouldReturnResourceIconWhenNodeTypeIsValid() 76 | { 77 | var namesToTest = Enum.GetNames(typeof(NodeType)).Where(name => "Intermediate" != name); 78 | foreach (var name in namesToTest) 79 | { 80 | Console.WriteLine("IconProvider " + name); 81 | ImageSource result = iconProvider.GetImageSourceBasingOnNodeType(name); 82 | Assert.That(result, Is.Not.Null); 83 | } 84 | } 85 | 86 | [Test] 87 | public void GetImageSourceForPowershellItemEntryShouldReturnNullWhenNodeTypeIsNotValid() 88 | { 89 | ImageSource result = iconProvider.GetImageSourceBasingOnNodeType("x"); 90 | Assert.That(result, Is.Null); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /PsISEProjectExplorer.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Bootstrap.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.PowerShell.Host.ISE; 2 | using NLog; 3 | using PsISEProjectExplorer.Model; 4 | using PsISEProjectExplorer.Services; 5 | using PsISEProjectExplorer.UI.IseIntegration; 6 | using PsISEProjectExplorer.UI.ViewModel; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.Linq; 11 | 12 | namespace PsISEProjectExplorer.Commands 13 | { 14 | [Component] 15 | public class Bootstrap 16 | { 17 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 18 | 19 | private readonly IseIntegrator iseIntegrator; 20 | 21 | private readonly IseFileReloader iseFileReloader; 22 | 23 | private readonly CommandExecutor commandExecutor; 24 | 25 | private readonly WorkspaceDirectoryModel workspaceDirectoryModel; 26 | 27 | private readonly DocumentHierarchyFactory documentHierarchyFactory; 28 | 29 | private readonly FileSystemChangeWatcher fileSystemChangeWatcher; 30 | 31 | public Bootstrap(IseIntegrator iseIntegrator, IseFileReloader iseFileReloader, CommandExecutor commandExecutor, 32 | WorkspaceDirectoryModel workspaceDirectoryModel, DocumentHierarchyFactory documentHierarchyFactory, FileSystemChangeWatcher fileSystemChangeWatcher) 33 | { 34 | this.iseIntegrator = iseIntegrator; 35 | this.iseFileReloader = iseFileReloader; 36 | this.commandExecutor = commandExecutor; 37 | this.workspaceDirectoryModel = workspaceDirectoryModel; 38 | this.documentHierarchyFactory = documentHierarchyFactory; 39 | this.fileSystemChangeWatcher = fileSystemChangeWatcher; 40 | } 41 | 42 | public void Start(ObjectModelRoot objectModelRoot) 43 | { 44 | this.iseIntegrator.setHostObject(objectModelRoot); 45 | this.workspaceDirectoryModel.PropertyChanged += this.RecreateSearchTreeOnWorkspaceDirectoryChanged; 46 | this.iseIntegrator.FileTabChanged += this.ResetWorkspaceOnFileTabChanged; 47 | this.fileSystemChangeWatcher.RegisterOnChangeCallback(this.ReindexOnFileSystemChanged); 48 | this.iseFileReloader.startWatching(); 49 | this.commandExecutor.ExecuteWithParam(true); 50 | } 51 | 52 | private void ResetWorkspaceOnFileTabChanged(object sender, IseEventArgs args) 53 | { 54 | this.commandExecutor.ExecuteWithParam(false); 55 | this.commandExecutor.ExecuteWithParam(true); 56 | } 57 | 58 | private void RecreateSearchTreeOnWorkspaceDirectoryChanged(object sender, PropertyChangedEventArgs e) 59 | { 60 | if (e.PropertyName == "CurrentWorkspaceDirectory") 61 | { 62 | this.commandExecutor.ExecuteWithParam>(null); 63 | } 64 | } 65 | 66 | private void ReindexOnFileSystemChanged(object sender, FileSystemChangedInfo changedInfo) 67 | { 68 | var workspaceDirectory = this.workspaceDirectoryModel.CurrentWorkspaceDirectory; 69 | var pathsChanged = changedInfo.PathsChanged.Where(p => p.RootPath == workspaceDirectory).Select(p => p.PathChanged).ToList(); 70 | if (!pathsChanged.Any()) 71 | { 72 | return; 73 | } 74 | if (pathsChanged.Contains(workspaceDirectory, StringComparer.InvariantCultureIgnoreCase)) 75 | { 76 | pathsChanged = null; 77 | } 78 | Logger.Debug("OnFileSystemChanged: " + (pathsChanged == null ? "root" : string.Join(",", pathsChanged))); 79 | this.commandExecutor.ExecuteWithParam>(pathsChanged); 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/AddNewTreeItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 3 | using PsISEProjectExplorer.Services; 4 | using PsISEProjectExplorer.UI.ViewModel; 5 | 6 | namespace PsISEProjectExplorer.Commands 7 | { 8 | [Component] 9 | public class AddNewTreeItemCommand : ParameterizedCommand 10 | { 11 | private readonly TreeViewModel treeViewModel; 12 | 13 | private readonly DocumentHierarchyFactory documentHierarchyFactory; 14 | 15 | public AddNewTreeItemCommand(TreeViewModel treeViewModel, DocumentHierarchyFactory documentHierarchyFactory) 16 | { 17 | this.treeViewModel = treeViewModel; 18 | this.documentHierarchyFactory = documentHierarchyFactory; 19 | } 20 | 21 | public void Execute(NodeType nodeType) 22 | { 23 | var parent = this.treeViewModel.SelectedItem; 24 | if (this.documentHierarchyFactory == null) 25 | { 26 | return; 27 | } 28 | if (parent == null) 29 | { 30 | parent = this.treeViewModel.RootTreeViewEntryItem; 31 | } 32 | parent.IsExpanded = true; 33 | INode newNode = this.documentHierarchyFactory.CreateTemporaryNode(parent.Node, nodeType); 34 | if (newNode == null) 35 | { 36 | return; 37 | } 38 | var newItem = this.treeViewModel.CreateTreeViewEntryItemModel(newNode, parent, true); 39 | newItem.IsBeingEdited = true; 40 | newItem.IsBeingAdded = true; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ChangeWorkspaceCommand.cs: -------------------------------------------------------------------------------- 1 | using Ookii.Dialogs.Wpf; 2 | using PsISEProjectExplorer.UI.Helpers; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | using System.IO; 5 | 6 | namespace PsISEProjectExplorer.Commands 7 | { 8 | [Component] 9 | public class ChangeWorkspaceCommand : Command 10 | { 11 | private readonly WorkspaceDirectoryModel workspaceDirectoryModel; 12 | 13 | private readonly MessageBoxHelper messageBoxHelper; 14 | 15 | public ChangeWorkspaceCommand(WorkspaceDirectoryModel workspaceDirectoryModel, MessageBoxHelper messageBoxHelper) 16 | { 17 | this.workspaceDirectoryModel = workspaceDirectoryModel; 18 | this.messageBoxHelper = messageBoxHelper; 19 | } 20 | 21 | public void Execute() 22 | { 23 | var dialog = new VistaFolderBrowserDialog 24 | { 25 | SelectedPath = this.workspaceDirectoryModel.CurrentWorkspaceDirectory, 26 | Description = "Please select the new workspace folder.", 27 | UseDescriptionForTitle = true 28 | }; 29 | 30 | bool? dialogResult = dialog.ShowDialog(); 31 | if (dialogResult != null && dialogResult.Value) 32 | { 33 | if (dialog.SelectedPath == Path.GetPathRoot(dialog.SelectedPath)) 34 | { 35 | this.messageBoxHelper.ShowError("Cannot use root directory ('" + dialog.SelectedPath + "'). Please select another path."); 36 | } 37 | else 38 | { 39 | this.workspaceDirectoryModel.SetWorkspaceDirectory(dialog.SelectedPath); 40 | this.workspaceDirectoryModel.AutoUpdateRootDirectory = false; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ClearSearchTextCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.ViewModel; 2 | 3 | namespace PsISEProjectExplorer.Commands 4 | { 5 | [Component] 6 | public class ClearSearchTextCommand : Command 7 | { 8 | private MainViewModel mainViewModel; 9 | 10 | public ClearSearchTextCommand(MainViewModel mainViewModel) 11 | { 12 | this.mainViewModel = mainViewModel; 13 | } 14 | 15 | public void Execute() 16 | { 17 | this.mainViewModel.SearchText = string.Empty; 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ClearTreeViewCommand.cs: -------------------------------------------------------------------------------- 1 |  2 | using PsISEProjectExplorer.Services; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | 5 | namespace PsISEProjectExplorer.Commands 6 | { 7 | [Component] 8 | public class ClearTreeViewCommand : Command 9 | { 10 | private readonly DocumentHierarchyFactory documentHierarchyFactory; 11 | 12 | private readonly TreeViewModel treeViewModel; 13 | 14 | private readonly FileSystemChangeWatcher fileSystemChangeWatcher; 15 | 16 | public ClearTreeViewCommand(DocumentHierarchyFactory documentHierarchyFactory, TreeViewModel treeViewModel, FileSystemChangeWatcher fileSystemChangeWatcher) 17 | { 18 | this.documentHierarchyFactory = documentHierarchyFactory; 19 | this.treeViewModel = treeViewModel; 20 | this.fileSystemChangeWatcher = fileSystemChangeWatcher; 21 | } 22 | 23 | public void Execute() 24 | { 25 | var documentHierarchy = this.documentHierarchyFactory.DocumentHierarchy; 26 | var rootNode = documentHierarchy == null ? null : documentHierarchy.RootNode; 27 | this.treeViewModel.ReRoot(rootNode); 28 | this.fileSystemChangeWatcher.StopWatching(); 29 | if (rootNode != null) 30 | { 31 | this.fileSystemChangeWatcher.Watch(rootNode.Path); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/CloseAllButThisCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.IseIntegration; 2 | 3 | namespace PsISEProjectExplorer.Commands 4 | { 5 | [Component] 6 | public class CloseAllButThisCommand : Command 7 | { 8 | private readonly IseIntegrator iseIntegrator; 9 | 10 | public CloseAllButThisCommand(IseIntegrator iseIntegrator) 11 | { 12 | this.iseIntegrator = iseIntegrator; 13 | } 14 | 15 | public void Execute() 16 | { 17 | this.iseIntegrator.CloseAllButThis(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/CollapseAllCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.Helpers; 2 | 3 | namespace PsISEProjectExplorer.Commands 4 | { 5 | [Component] 6 | public class CollapseAllCommand : Command 7 | { 8 | private readonly ProjectExplorerWindow projectExplorerWindow; 9 | 10 | public CollapseAllCommand(ProjectExplorerWindow projectExplorerWindow) 11 | { 12 | this.projectExplorerWindow = projectExplorerWindow; 13 | } 14 | 15 | public void Execute() 16 | { 17 | this.projectExplorerWindow.SearchResultsTreeView.CollapseAll(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/Command.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Commands 2 | { 3 | public interface Command 4 | { 5 | void Execute(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/CommandExecutor.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Config; 2 | using System.Windows; 3 | 4 | namespace PsISEProjectExplorer.Commands 5 | { 6 | [Component] 7 | public class CommandExecutor 8 | { 9 | 10 | private readonly ApplicationConfig bootstrapConfig; 11 | 12 | public CommandExecutor(ApplicationConfig bootstrapConfig) 13 | { 14 | this.bootstrapConfig = bootstrapConfig; 15 | } 16 | 17 | public void Execute() where T : class, Command 18 | { 19 | var command = this.bootstrapConfig.GetInstance(); 20 | Application.Current.Dispatcher.Invoke(() => command.Execute()); 21 | } 22 | 23 | public void ExecuteWithParam(P param) where T : class, ParameterizedCommand

24 | { 25 | var command = this.bootstrapConfig.GetInstance(); 26 | Application.Current.Dispatcher.Invoke(() => command.Execute(param)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/DeleteItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Services; 2 | using PsISEProjectExplorer.UI.Helpers; 3 | using PsISEProjectExplorer.UI.IseIntegration; 4 | using PsISEProjectExplorer.UI.ViewModel; 5 | using System; 6 | using System.IO; 7 | using System.Linq; 8 | 9 | namespace PsISEProjectExplorer.Commands 10 | { 11 | [Component] 12 | public class DeleteItemCommand : Command 13 | { 14 | private readonly TreeViewModel treeViewModel; 15 | 16 | private readonly MessageBoxHelper messageBoxHelper; 17 | 18 | private readonly IseIntegrator iseIntegrator; 19 | 20 | private readonly FilesPatternProvider filesPatternProvider; 21 | 22 | private readonly FileSystemOperationsService fileSystemOperationsService; 23 | 24 | private readonly UnsavedFileChecker unsavedFileChecker; 25 | 26 | public DeleteItemCommand(TreeViewModel treeViewModel, MessageBoxHelper messageBoxHelper, IseIntegrator iseIntegrator, 27 | FilesPatternProvider filesPatternProvider, FileSystemOperationsService fileSystemOperationsService, UnsavedFileChecker unsavedFileChecker) 28 | { 29 | this.treeViewModel = treeViewModel; 30 | this.messageBoxHelper = messageBoxHelper; 31 | this.iseIntegrator = iseIntegrator; 32 | this.filesPatternProvider = filesPatternProvider; 33 | this.fileSystemOperationsService = fileSystemOperationsService; 34 | this.unsavedFileChecker = unsavedFileChecker; 35 | } 36 | 37 | public void Execute() 38 | { 39 | var selectedItem = this.treeViewModel.SelectedItem; 40 | if (selectedItem == null) 41 | { 42 | return; 43 | } 44 | 45 | if (!this.unsavedFileChecker.EnsureCurrentlyOpenedFileIsSaved()) 46 | { 47 | return; 48 | } 49 | int numFilesInside = 0; 50 | try 51 | { 52 | numFilesInside = Directory.GetFileSystemEntries(selectedItem.Path).Count(); 53 | } 54 | catch (Exception) 55 | { 56 | // ignore - this only has impact on message 57 | } 58 | string message = numFilesInside == 0 ? 59 | String.Format("'{0}' will be deleted permanently.", selectedItem.Path) : 60 | String.Format("'{0}' will be deleted permanently (together with {1} items inside).", selectedItem.Path, numFilesInside); 61 | if (this.messageBoxHelper.ShowConfirmMessage(message)) 62 | { 63 | try 64 | { 65 | this.iseIntegrator.CloseFile(selectedItem.Path); 66 | this.filesPatternProvider.RemoveAdditionalPath(selectedItem.Path); 67 | fileSystemOperationsService.DeleteFileOrDirectory(selectedItem.Path); 68 | } 69 | catch (Exception e) 70 | { 71 | this.messageBoxHelper.ShowError("Failed to delete: " + e.Message); 72 | } 73 | } 74 | } 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/DotSourceCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 3 | using PsISEProjectExplorer.UI.Helpers; 4 | using PsISEProjectExplorer.UI.IseIntegration; 5 | using PsISEProjectExplorer.UI.ViewModel; 6 | using System; 7 | using System.Diagnostics; 8 | using System.IO; 9 | 10 | namespace PsISEProjectExplorer.Commands 11 | { 12 | [Component] 13 | public class DotSourceCommand : Command 14 | { 15 | private readonly TreeViewModel treeViewModel; 16 | 17 | private readonly IseIntegrator iseIntegrator; 18 | 19 | public DotSourceCommand(TreeViewModel TreeViewModel, IseIntegrator iseIntegrator) 20 | { 21 | this.treeViewModel = TreeViewModel; 22 | this.iseIntegrator = iseIntegrator; 23 | } 24 | 25 | public void Execute() 26 | { 27 | var selectedItem = this.treeViewModel.SelectedItem; 28 | if (selectedItem == null) 29 | { 30 | return; 31 | } 32 | var fileItem = GetParentFileItem(selectedItem); 33 | if (fileItem == null || fileItem.Path == null || iseIntegrator.SelectedFilePath == null) 34 | { 35 | return; 36 | } 37 | string dotSourcePath = GetDotSourcePath(iseIntegrator.SelectedFilePath, fileItem.Path); 38 | iseIntegrator.WriteTextWithNewLine(String.Format(". \"$PSScriptRoot\\{0}\"", dotSourcePath)); 39 | iseIntegrator.SetFocusOnCurrentTab(); 40 | } 41 | 42 | private string GetDotSourcePath(string srcPath, string dstPath) 43 | { 44 | Uri srcUri = new Uri(srcPath); 45 | Uri dstUri = new Uri(dstPath); 46 | Uri relativeUri = srcUri.MakeRelativeUri(dstUri); 47 | string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); 48 | if (dstUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase)) 49 | { 50 | relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); 51 | } 52 | return relativePath; 53 | } 54 | 55 | private TreeViewEntryItemModel GetParentFileItem(TreeViewEntryItemModel selectedItem) 56 | { 57 | var item = selectedItem; 58 | while (item.NodeType != NodeType.File && item.Parent != null) 59 | { 60 | item = item.Parent; 61 | } 62 | if (item.NodeType == NodeType.File) 63 | { 64 | return item; 65 | } 66 | return null; 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ExcludeOrIncludeItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Config; 2 | using PsISEProjectExplorer.Services; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | 5 | namespace PsISEProjectExplorer.Commands 6 | { 7 | [Component] 8 | public class ExcludeOrIncludeItemCommand : Command 9 | { 10 | private readonly MainViewModel mainViewModel; 11 | 12 | private readonly TreeViewModel treeViewModel; 13 | 14 | private readonly FilesPatternProvider filesPatternProvider; 15 | 16 | private readonly ConfigValues configValues; 17 | 18 | private readonly ReindexSearchTreeCommand reindexSearchTreeCommand; 19 | 20 | public ExcludeOrIncludeItemCommand(MainViewModel mainViewModel, TreeViewModel treeViewModel, FilesPatternProvider filesPatternProvider, ConfigValues configValues, 21 | ReindexSearchTreeCommand reindexSearchTreeCommand) 22 | { 23 | this.mainViewModel = mainViewModel; 24 | this.treeViewModel = treeViewModel; 25 | this.filesPatternProvider = filesPatternProvider; 26 | this.configValues = configValues; 27 | this.reindexSearchTreeCommand = reindexSearchTreeCommand; 28 | } 29 | 30 | public void Execute() 31 | { 32 | var selectedItem = this.treeViewModel.SelectedItem; 33 | if (selectedItem == null || selectedItem.IsBeingEdited) 34 | { 35 | return; 36 | } 37 | 38 | if (selectedItem.IsExcluded) 39 | { 40 | this.filesPatternProvider.ExcludePaths = this.configValues.RemoveExcludePath(selectedItem.Path); 41 | } 42 | else 43 | { 44 | this.filesPatternProvider.ExcludePaths = this.configValues.AddExcludePath(selectedItem.Path); 45 | } 46 | this.reindexSearchTreeCommand.Execute(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/FindAllOccurrencesCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using PsISEProjectExplorer.Model.DocHierarchy; 3 | using PsISEProjectExplorer.Services; 4 | using PsISEProjectExplorer.UI.IseIntegration; 5 | using PsISEProjectExplorer.UI.ViewModel; 6 | 7 | namespace PsISEProjectExplorer.Commands 8 | { 9 | [Component] 10 | public class FindAllOccurrencesCommand : Command 11 | { 12 | private readonly IseIntegrator iseIntegrator; 13 | 14 | private readonly PowershellTokenizerProvider powershellTokenizerProvider; 15 | 16 | private readonly MainViewModel mainViewModel; 17 | 18 | private readonly DocumentHierarchyFactory documentHierarchyFactory; 19 | 20 | public FindAllOccurrencesCommand(IseIntegrator iseIntegrator, PowershellTokenizerProvider powershellTokenizerProvider, MainViewModel mainViewModel, 21 | DocumentHierarchyFactory documentHierarchyFactory) 22 | { 23 | this.iseIntegrator = iseIntegrator; 24 | this.powershellTokenizerProvider = powershellTokenizerProvider; 25 | this.mainViewModel = mainViewModel; 26 | this.documentHierarchyFactory = documentHierarchyFactory; 27 | } 28 | 29 | public void Execute() 30 | { 31 | DocumentHierarchy documentHierarchy = this.documentHierarchyFactory.DocumentHierarchy; 32 | if (documentHierarchy == null) 33 | { 34 | return; 35 | } 36 | string funcName = this.GetFunctionNameAtCurrentPosition(); 37 | if (funcName == null) 38 | { 39 | return; 40 | } 41 | 42 | // TODO: this is hacky... 43 | this.mainViewModel.SearchOptions.SearchText = string.Empty; 44 | if (this.mainViewModel.IndexFilesMode == IndexingMode.NO_FILES) 45 | { 46 | this.mainViewModel.IndexFilesMode = IndexingMode.LOCAL_FILES; 47 | } 48 | this.mainViewModel.SearchText = funcName; 49 | } 50 | 51 | private string GetFunctionNameAtCurrentPosition() 52 | { 53 | EditorInfo editorInfo = this.iseIntegrator.GetCurrentLineWithColumnIndex(); 54 | if (editorInfo == null) 55 | { 56 | return null; 57 | } 58 | return this.powershellTokenizerProvider.PowershellTokenizer.GetTokenAtColumn(editorInfo.CurrentLine, editorInfo.CurrentColumn); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/FindInFilesCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.ViewModel; 2 | 3 | namespace PsISEProjectExplorer.Commands 4 | { 5 | [Component] 6 | public class FindInFilesCommand : Command 7 | { 8 | private readonly MainViewModel mainViewModel; 9 | 10 | private readonly ProjectExplorerWindow projectExplorerWindow; 11 | 12 | public FindInFilesCommand(MainViewModel mainViewModel, ProjectExplorerWindow projectExplorerWindow) 13 | { 14 | this.mainViewModel = mainViewModel; 15 | this.projectExplorerWindow = projectExplorerWindow; 16 | } 17 | 18 | public void Execute() 19 | { 20 | this.mainViewModel.SearchOptions.SearchText = string.Empty; 21 | if (this.mainViewModel.IndexFilesMode == Model.IndexingMode.NO_FILES) 22 | { 23 | this.mainViewModel.IndexFilesMode = Model.IndexingMode.LOCAL_FILES; 24 | } 25 | this.projectExplorerWindow.FocusOnTextBoxSearchText(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/GoToDefinitionCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using PsISEProjectExplorer.Model.DocHierarchy; 3 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 4 | using PsISEProjectExplorer.Services; 5 | using PsISEProjectExplorer.UI.IseIntegration; 6 | 7 | namespace PsISEProjectExplorer.Commands 8 | { 9 | [Component] 10 | public class GoToDefinitionCommand : Command 11 | { 12 | private readonly IseIntegrator iseIntegrator; 13 | 14 | private readonly PowershellTokenizerProvider powershellTokenizerProvider; 15 | 16 | private readonly DocumentHierarchyFactory documentHierarchyFactory; 17 | 18 | private readonly DocumentHierarchySearcher documentHierarchySearcher; 19 | 20 | public GoToDefinitionCommand(IseIntegrator iseIntegrator, PowershellTokenizerProvider powershellTokenizerProvider, 21 | DocumentHierarchyFactory documentHierarchyFactory, DocumentHierarchySearcher documentHierarchySearcher) 22 | { 23 | this.iseIntegrator = iseIntegrator; 24 | this.powershellTokenizerProvider = powershellTokenizerProvider; 25 | this.documentHierarchyFactory = documentHierarchyFactory; 26 | this.documentHierarchySearcher = documentHierarchySearcher; 27 | } 28 | 29 | public void Execute() 30 | { 31 | DocumentHierarchy documentHierarchy = this.documentHierarchyFactory.DocumentHierarchy; 32 | if (documentHierarchy == null) 33 | { 34 | return; 35 | } 36 | string funcName = this.GetFunctionNameAtCurrentPosition(); 37 | if (funcName == null) 38 | { 39 | return; 40 | } 41 | string selectedFilePath = iseIntegrator.SelectedFilePath; 42 | var node = (PowershellItemNode)this.documentHierarchySearcher.GetFunctionNodeByName(documentHierarchy, funcName, selectedFilePath); 43 | if (node == null) 44 | { 45 | return; 46 | } 47 | this.iseIntegrator.GoToFile(node.FilePath); 48 | this.iseIntegrator.SetCursor(node.PowershellItem.StartLine, node.PowershellItem.StartColumn); 49 | } 50 | 51 | private string GetFunctionNameAtCurrentPosition() 52 | { 53 | EditorInfo editorInfo = this.iseIntegrator.GetCurrentLineWithColumnIndex(); 54 | if (editorInfo == null) 55 | { 56 | return null; 57 | } 58 | return this.powershellTokenizerProvider.PowershellTokenizer.GetTokenAtColumn(editorInfo.CurrentLine, editorInfo.CurrentColumn); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/LocateFileInTreeCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.Helpers; 2 | using PsISEProjectExplorer.UI.IseIntegration; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | 5 | namespace PsISEProjectExplorer.Commands 6 | { 7 | [Component] 8 | public class LocateFileInTreeCommand : Command 9 | { 10 | private readonly ProjectExplorerWindow projectExplorerWindow; 11 | 12 | private readonly IseIntegrator iseIntegrator; 13 | 14 | private readonly TreeViewModel treeViewModel; 15 | 16 | public LocateFileInTreeCommand(ProjectExplorerWindow projectExplorerWindow, IseIntegrator iseIntegrator, TreeViewModel treeViewModel) 17 | { 18 | this.projectExplorerWindow = projectExplorerWindow; 19 | this.iseIntegrator = iseIntegrator; 20 | this.treeViewModel = treeViewModel; 21 | } 22 | 23 | public void Execute() 24 | { 25 | this.ExpandAndSelectCurrentlyOpenedItem(); 26 | } 27 | 28 | public bool ExpandAndSelectCurrentlyOpenedItem() 29 | { 30 | string path = this.iseIntegrator.SelectedFilePath; 31 | if (path == null) 32 | { 33 | return false; 34 | } 35 | 36 | var selectedItem = this.treeViewModel.SelectedItem; 37 | if (selectedItem != null && selectedItem.Path.StartsWith(path)) 38 | { 39 | return true; 40 | } 41 | 42 | TreeViewEntryItemModel item = this.treeViewModel.FindTreeViewEntryItemByPath(path); 43 | if (item == null) 44 | { 45 | return false; 46 | } 47 | 48 | this.projectExplorerWindow.SearchResultsTreeView.ExpandAndSelectItem(item); 49 | return true; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/OpenExplorerContextMenuCommand.cs: -------------------------------------------------------------------------------- 1 | using GongSolutions.Shell; 2 | using NLog; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | using System; 5 | using System.IO; 6 | 7 | namespace PsISEProjectExplorer.Commands 8 | { 9 | [Component] 10 | public class OpenExplorerContextMenuCommand : Command 11 | { 12 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 13 | 14 | private readonly TreeViewModel treeViewModel; 15 | 16 | private readonly WorkspaceDirectoryModel workspaceDirectoryModel; 17 | 18 | public OpenExplorerContextMenuCommand(TreeViewModel treeViewModel, WorkspaceDirectoryModel workspaceDirectoryModel) 19 | { 20 | this.treeViewModel = treeViewModel; 21 | this.workspaceDirectoryModel = workspaceDirectoryModel; 22 | } 23 | 24 | public void Execute() 25 | { 26 | string path; 27 | var selectedItem = this.treeViewModel.SelectedItem; 28 | if (selectedItem == null) 29 | { 30 | path = this.workspaceDirectoryModel.CurrentWorkspaceDirectory; 31 | } 32 | else 33 | { 34 | path = selectedItem.Path; 35 | } 36 | 37 | if (String.IsNullOrEmpty(path) || (!File.Exists(path) && !Directory.Exists(path))) 38 | { 39 | return; 40 | } 41 | 42 | var uri = new Uri(path); 43 | ShellItem shellItem = new ShellItem(uri); 44 | ShellContextMenu menu = new ShellContextMenu(shellItem); 45 | try 46 | { 47 | menu.ShowContextMenu(System.Windows.Forms.Control.MousePosition); 48 | } 49 | catch (Exception ex) 50 | { 51 | Logger.Error(ex, "Failed to show Windows Explorer Context Menu"); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/OpenInExplorerCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using PsISEProjectExplorer.UI.Helpers; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | using System; 5 | using System.Diagnostics; 6 | 7 | namespace PsISEProjectExplorer.Commands 8 | { 9 | [Component] 10 | public class OpenInExplorerCommand : Command 11 | { 12 | private readonly TreeViewModel treeViewModel; 13 | 14 | private readonly MessageBoxHelper messageBoxHelper; 15 | 16 | public OpenInExplorerCommand(TreeViewModel TreeViewModel, MessageBoxHelper messageBoxHelper) 17 | { 18 | this.treeViewModel = TreeViewModel; 19 | this.messageBoxHelper = messageBoxHelper; 20 | } 21 | 22 | public void Execute() 23 | { 24 | var item = this.treeViewModel.SelectedItem; 25 | if (item == null) 26 | { 27 | return; 28 | } 29 | 30 | try 31 | { 32 | switch (item.NodeType) 33 | { 34 | case NodeType.Directory: 35 | Process.Start(item.Path); 36 | break; 37 | case NodeType.File: 38 | Process.Start("explorer.exe", "/select, \"" + item.Path + "\""); 39 | break; 40 | } 41 | 42 | } 43 | catch (Exception ex) 44 | { 45 | this. messageBoxHelper.ShowError(string.Format("Cannot open path: '{0}' - {1}.", item.Path, ex.Message)); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/OpenItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using PsISEProjectExplorer.Model; 3 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 4 | using PsISEProjectExplorer.Services; 5 | using PsISEProjectExplorer.UI.IseIntegration; 6 | using PsISEProjectExplorer.UI.ViewModel; 7 | using System; 8 | 9 | namespace PsISEProjectExplorer.Commands 10 | { 11 | [Component] 12 | public class OpenItemCommand : Command 13 | { 14 | private readonly TreeViewModel treeViewModel; 15 | 16 | private readonly MainViewModel mainViewModel; 17 | 18 | private readonly IseIntegrator iseIntegrator; 19 | 20 | private readonly TokenLocator tokenLocator; 21 | 22 | public OpenItemCommand(TreeViewModel treeViewModel, MainViewModel mainViewModel, IseIntegrator iseIntegrator, TokenLocator tokenLocator) 23 | { 24 | this.treeViewModel = treeViewModel; 25 | this.mainViewModel = mainViewModel; 26 | this.iseIntegrator = iseIntegrator; 27 | this.tokenLocator = tokenLocator; 28 | } 29 | 30 | public void Execute() 31 | { 32 | var item = this.treeViewModel.SelectedItem; 33 | var searchOptions = this.mainViewModel.SearchOptions; 34 | if (item == null) 35 | { 36 | return; 37 | } 38 | 39 | if (item.Node.NodeType == NodeType.File) 40 | { 41 | bool wasOpen = (this.iseIntegrator.SelectedFilePath == item.Node.Path); 42 | if (!wasOpen) 43 | { 44 | this.iseIntegrator.GoToFile(item.Node.Path); 45 | } 46 | else 47 | { 48 | this.iseIntegrator.SetFocusOnCurrentTab(); 49 | } 50 | if (searchOptions.SearchText != null && searchOptions.SearchText.Length > 2) 51 | { 52 | EditorInfo editorInfo = (wasOpen ? this.iseIntegrator.GetCurrentLineWithColumnIndex() : null); 53 | TokenPosition tokenPos = this.tokenLocator.LocateNextToken(item.Node.Path, searchOptions, editorInfo); 54 | if (tokenPos.MatchLength > 2) 55 | { 56 | this.iseIntegrator.SelectText(tokenPos.Line, tokenPos.Column, tokenPos.MatchLength); 57 | } 58 | else if (string.IsNullOrEmpty(this.iseIntegrator.SelectedText)) 59 | { 60 | tokenPos = this.tokenLocator.LocateSubtoken(item.Node.Path, searchOptions); 61 | if (tokenPos.MatchLength > 2) 62 | { 63 | this.iseIntegrator.SelectText(tokenPos.Line, tokenPos.Column, tokenPos.MatchLength); 64 | } 65 | } 66 | } 67 | } 68 | else if (item.Node.NodeType == NodeType.Directory) 69 | { 70 | item.IsExpanded = !item.IsExpanded; 71 | } 72 | else if (item.Node.NodeType != NodeType.Intermediate) 73 | { 74 | var node = ((PowershellItemNode)item.Node); 75 | this.iseIntegrator.GoToFile(node.FilePath); 76 | this.iseIntegrator.SelectText(node.PowershellItem.StartLine, node.PowershellItem.StartColumn, node.PowershellItem.EndColumn - node.PowershellItem.StartColumn); 77 | } 78 | 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ParameterizedCommand.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Commands 2 | { 3 | public interface ParameterizedCommand 4 | { 5 | void Execute(T param); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/RenameItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.ViewModel; 2 | 3 | namespace PsISEProjectExplorer.Commands 4 | { 5 | [Component] 6 | public class RenameItemCommand : Command 7 | { 8 | private readonly TreeViewModel treeViewModel; 9 | 10 | private readonly UnsavedFileChecker unsavedFileChecker; 11 | 12 | public RenameItemCommand(TreeViewModel treeViewModel, UnsavedFileChecker unsavedFileChecker) 13 | { 14 | this.treeViewModel = treeViewModel; 15 | this.unsavedFileChecker = unsavedFileChecker; 16 | } 17 | 18 | public void Execute() 19 | { 20 | var item = this.treeViewModel.SelectedItem; 21 | if (item == null) 22 | { 23 | return; 24 | } 25 | 26 | if (!this.unsavedFileChecker.EnsureCurrentlyOpenedFileIsSaved()) 27 | { 28 | return; 29 | } 30 | item.IsBeingEdited = true; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/ResetWorkspaceDirectoryCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Services; 2 | using PsISEProjectExplorer.UI.IseIntegration; 3 | using PsISEProjectExplorer.UI.ViewModel; 4 | using System; 5 | using System.IO; 6 | using System.Windows; 7 | 8 | namespace PsISEProjectExplorer.Commands 9 | { 10 | [Component] 11 | public class ResetWorkspaceDirectoryCommand : ParameterizedCommand 12 | { 13 | private readonly IseIntegrator iseIntegrator; 14 | 15 | private readonly WorkspaceDirectoryModel workspaceDirectoryModel; 16 | 17 | private readonly RootDirectoryProvider rootDirectoryProvider; 18 | 19 | private readonly FileSystemOperationsService fileSystemOperationsService; 20 | 21 | public ResetWorkspaceDirectoryCommand(IseIntegrator iseIntegrator, WorkspaceDirectoryModel workspaceDirectoryModel, RootDirectoryProvider rootDirectoryProvider, 22 | FileSystemOperationsService fileSystemOperationsService) 23 | { 24 | this.iseIntegrator = iseIntegrator; 25 | this.workspaceDirectoryModel = workspaceDirectoryModel; 26 | this.rootDirectoryProvider = rootDirectoryProvider; 27 | this.fileSystemOperationsService = fileSystemOperationsService; 28 | } 29 | 30 | public void Execute(bool forceReindex) 31 | { 32 | bool changed = this.AutoChangeWorkspaceDirectory(); 33 | if (!changed && forceReindex) 34 | { 35 | this.workspaceDirectoryModel.TriggerWorkspaceDirectoryChange(); 36 | } 37 | } 38 | 39 | private bool AutoChangeWorkspaceDirectory() 40 | { 41 | var currentPath = this.iseIntegrator.SelectedFilePath; 42 | if (String.IsNullOrEmpty(currentPath) || currentPath == this.workspaceDirectoryModel.CurrentWorkspaceDirectory) 43 | { 44 | return false; 45 | } 46 | if (!this.workspaceDirectoryModel.AutoUpdateRootDirectory && this.workspaceDirectoryModel.CurrentWorkspaceDirectory != null) 47 | { 48 | return false; 49 | } 50 | string newRootDirectoryToSearch = this.rootDirectoryProvider.GetRootDirectoryToSearch(currentPath); 51 | if (newRootDirectoryToSearch == null || newRootDirectoryToSearch == this.workspaceDirectoryModel.CurrentWorkspaceDirectory || 52 | fileSystemOperationsService.IsSubdirectory(this.workspaceDirectoryModel.CurrentWorkspaceDirectory, newRootDirectoryToSearch) || 53 | !Directory.Exists(newRootDirectoryToSearch)) 54 | { 55 | return false; 56 | } 57 | this.workspaceDirectoryModel.SetWorkspaceDirectory(newRootDirectoryToSearch); 58 | return true; 59 | } 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/SelectItemCommand.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.UI.Helpers; 2 | using PsISEProjectExplorer.UI.ViewModel; 3 | using System.Windows; 4 | 5 | namespace PsISEProjectExplorer.Commands 6 | { 7 | [Component] 8 | public class SelectItemCommand : ParameterizedCommand 9 | { 10 | private readonly ProjectExplorerWindow projectExplorerWindow; 11 | 12 | public SelectItemCommand(ProjectExplorerWindow projectExplorerWindow) 13 | { 14 | this.projectExplorerWindow = projectExplorerWindow; 15 | } 16 | 17 | public void Execute(DependencyObject originalSource) 18 | { 19 | var treeView = this.projectExplorerWindow.SearchResultsTreeView; 20 | var item = treeView.FindItemFromSource(originalSource); 21 | if (item == null && treeView.SelectedItem != null) 22 | { 23 | ((TreeViewEntryItemModel)treeView.SelectedItem).IsSelected = false; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/SyncWithActiveDocumentCommand.cs: -------------------------------------------------------------------------------- 1 |  2 | using PsISEProjectExplorer.UI.ViewModel; 3 | 4 | namespace PsISEProjectExplorer.Commands 5 | { 6 | [Component] 7 | public class SyncWithActiveDocumentCommand : ParameterizedCommand 8 | { 9 | private MainViewModel mainViewModel; 10 | 11 | private TreeViewModel treeViewModel; 12 | 13 | private LocateFileInTreeCommand locateFileInTreeCommand; 14 | 15 | private bool itemFound; 16 | 17 | public SyncWithActiveDocumentCommand(MainViewModel mainViewModel, TreeViewModel treeViewModel, LocateFileInTreeCommand locateFileInTreeCommand) 18 | { 19 | this.mainViewModel = mainViewModel; 20 | this.treeViewModel = treeViewModel; 21 | this.locateFileInTreeCommand = locateFileInTreeCommand; 22 | } 23 | 24 | public void Execute(bool resetState) 25 | { 26 | if (resetState) 27 | { 28 | this.itemFound = false; 29 | } 30 | if (this.mainViewModel.SyncWithActiveDocument && !this.itemFound) 31 | { 32 | this.itemFound = this.locateFileInTreeCommand.ExpandAndSelectCurrentlyOpenedItem(); 33 | } 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Commands/UnsavedFileChecker.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using PsISEProjectExplorer.UI.Helpers; 3 | using PsISEProjectExplorer.UI.IseIntegration; 4 | using PsISEProjectExplorer.UI.ViewModel; 5 | using System.Linq; 6 | 7 | namespace PsISEProjectExplorer.Commands 8 | { 9 | [Component] 10 | public class UnsavedFileChecker 11 | { 12 | private readonly TreeViewModel treeViewModel; 13 | 14 | private readonly IseIntegrator iseIntegrator; 15 | 16 | private readonly MessageBoxHelper messageBoxHelper; 17 | 18 | public UnsavedFileChecker(TreeViewModel treeViewModel, IseIntegrator iseIntegrator, MessageBoxHelper messageBoxHelper) 19 | { 20 | this.treeViewModel = treeViewModel; 21 | this.iseIntegrator = iseIntegrator; 22 | this.messageBoxHelper = messageBoxHelper; 23 | } 24 | 25 | public bool EnsureCurrentlyOpenedFileIsSaved() 26 | { 27 | var selectedItem = this.treeViewModel.SelectedItem; 28 | if (selectedItem != null && selectedItem.NodeType == NodeType.File && this.iseIntegrator.OpenFiles.Contains(selectedItem.Path) && !this.iseIntegrator.IsFileSaved(selectedItem.Path)) 29 | { 30 | this.iseIntegrator.GoToFile(selectedItem.Path); 31 | this.messageBoxHelper.ShowInfo("Please save your changes or close the file first."); 32 | return false; 33 | } 34 | return true; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Component.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PsISEProjectExplorer 8 | { 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class Component : System.Attribute 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Config/ApplicationConfig.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.UI.ViewModel; 3 | using SimpleInjector; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Threading; 13 | 14 | namespace PsISEProjectExplorer.Config 15 | { 16 | public class ApplicationConfig 17 | { 18 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 19 | 20 | private Container container; 21 | 22 | public void ConfigureApplication(ProjectExplorerWindow mainWindow) 23 | { 24 | this.ConfigureLogging(); 25 | this.container = this.ConfigureDependencyInjection(mainWindow); 26 | Application.Current.Dispatcher.UnhandledException += DispatcherUnhandledExceptionHandler; 27 | } 28 | 29 | public T GetInstance() where T : class 30 | { 31 | return this.container.GetInstance(); 32 | } 33 | 34 | private void ConfigureLogging() 35 | { 36 | string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 37 | string logFileName = Path.Combine(assemblyFolder, "NLog.config"); 38 | var config = new NLog.Config.XmlLoggingConfiguration(logFileName); 39 | LogManager.Configuration = config; 40 | } 41 | 42 | private Container ConfigureDependencyInjection(ProjectExplorerWindow mainWindow) 43 | { 44 | Container container = new Container(); 45 | var components = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && Attribute.IsDefined(t, typeof(Component))); 46 | 47 | foreach (var component in components) 48 | { 49 | container.Register(component, component, Lifestyle.Singleton); 50 | } 51 | container.RegisterInstance(typeof(ProjectExplorerWindow), mainWindow); 52 | container.RegisterInstance(typeof(ApplicationConfig), this); 53 | return container; 54 | } 55 | 56 | private static void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args) 57 | { 58 | Exception e = args.Exception; 59 | Logger.Error(e, "Unhandled Dispatcher exception"); 60 | 61 | StringBuilder sources = new StringBuilder().Append("Sources: "); 62 | string firstSource = null; 63 | var innerException = e.InnerException; 64 | 65 | while (innerException != null) 66 | { 67 | if (firstSource == null) 68 | { 69 | firstSource = innerException.Source; 70 | } 71 | 72 | sources.Append(innerException.Source).Append(","); 73 | innerException = innerException.InnerException; 74 | } 75 | 76 | Logger.Error(sources.ToString()); 77 | args.Handled = true; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Contrib/Regex/IRegexCapabilities.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | namespace Contrib.Regex 19 | { 20 | ///

21 | /// Defines basic operations needed by for a regular expression implementation. 22 | /// 23 | /// http://www.java2s.com/Open-Source/Java-Document/Net/lucene-connector/org/apache/lucene/search/regex/RegexCapabilities.java.htm 24 | public interface IRegexCapabilities 25 | { 26 | /// 27 | /// Called by the constructor of allowing implementations to cache 28 | /// a compiled version of the regular expression pattern. 29 | /// 30 | /// regular expression pattern 31 | void Compile(string pattern); 32 | 33 | /// 34 | /// True on match. 35 | /// 36 | /// text to match 37 | /// true on match 38 | bool Match(string s); 39 | 40 | /// 41 | /// A wise prefix implementation can reduce the term enumeration (and thus performance) 42 | /// of RegexQuery dramatically. 43 | /// 44 | /// static non-regex prefix of the pattern last passed to . 45 | /// May return null 46 | string Prefix(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Contrib/Regex/IRegexQueryCapable.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | namespace Contrib.Regex 19 | { 20 | /// 21 | /// Defines methods for regular expression supporting queries to use. 22 | /// 23 | /// http://www.java2s.com/Open-Source/Java-Document/Net/lucene-connector/org/apache/lucene/search/regex/RegexQueryCapable.java.htm 24 | public interface IRegexQueryCapable 25 | { 26 | IRegexCapabilities RegexImplementation { set; get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Contrib/Regex/RegexQuery.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | using System; 19 | using System.Text; 20 | using Lucene.Net.Index; 21 | using Lucene.Net.Search; 22 | using Lucene.Net.Util; 23 | 24 | namespace Contrib.Regex 25 | { 26 | /// 27 | /// Regular expression based query. 28 | /// 29 | /// http://www.java2s.com/Open-Source/Java-Document/Net/lucene-connector/org/apache/lucene/search/regex/RegexQuery.java.htm 30 | public class RegexQuery : MultiTermQuery, IRegexQueryCapable, IEquatable 31 | { 32 | private IRegexCapabilities _regexImpl = new CSharpRegexCapabilities(); 33 | public Term Term { get; private set; } 34 | 35 | public RegexQuery(Term term) 36 | { 37 | Term = term; 38 | } 39 | 40 | /// Construct the enumeration to be used, expanding the pattern term. 41 | protected override FilteredTermEnum GetEnum(IndexReader reader) 42 | { 43 | return new RegexTermEnum(reader, Term, _regexImpl); 44 | } 45 | 46 | public IRegexCapabilities RegexImplementation 47 | { 48 | set { _regexImpl = value; } 49 | get { return _regexImpl; } 50 | } 51 | 52 | 53 | public override String ToString(String field) 54 | { 55 | StringBuilder buffer = new StringBuilder(); 56 | if (!Term.Field.Equals(field)) 57 | { 58 | buffer.Append(Term.Field); 59 | buffer.Append(":"); 60 | } 61 | buffer.Append(Term.Text); 62 | buffer.Append(ToStringUtils.Boost(Boost)); 63 | return buffer.ToString(); 64 | } 65 | 66 | /// 67 | /// Indicates whether the current object is equal to another object of the same type. 68 | /// 69 | /// 70 | /// true if the current object is equal to the parameter; otherwise, false. 71 | /// 72 | /// An object to compare with this object 73 | public bool Equals(RegexQuery other) 74 | { 75 | if (other == null) return false; 76 | if (this == other) return true; 77 | 78 | if (!base.Equals(other)) return false; 79 | return _regexImpl.Equals(other._regexImpl); 80 | } 81 | 82 | public override bool Equals(object obj) 83 | { 84 | if ((obj == null) || (obj as RegexQuery == null)) return false; 85 | if (this == obj) return true; 86 | 87 | return Equals((RegexQuery)obj); 88 | } 89 | 90 | public override int GetHashCode() 91 | { 92 | return 29 * base.GetHashCode() + _regexImpl.GetHashCode(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Contrib/Regex/RegexTermEnum.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | using Lucene.Net.Index; 19 | using Lucene.Net.Search; 20 | 21 | namespace Contrib.Regex 22 | { 23 | /// 24 | /// Subclass of FilteredTermEnum for enumerating all terms that match the 25 | /// specified regular expression term using the specified regular expression 26 | /// implementation. 27 | /// Term enumerations are always ordered by Term.compareTo(). Each term in 28 | /// the enumeration is greater than all that precede it. 29 | /// 30 | /// http://www.java2s.com/Open-Source/Java-Document/Net/lucene-connector/org/apache/lucene/search/regex/RegexTermEnum.java.htm 31 | public class RegexTermEnum : FilteredTermEnum 32 | { 33 | private string _sField = ""; 34 | private string _sPre = ""; 35 | private bool _bEndEnum; 36 | private readonly IRegexCapabilities _regexImpl; 37 | 38 | public RegexTermEnum(IndexReader reader, Term term, IRegexCapabilities regexImpl) 39 | { 40 | _sField = term.Field; 41 | string sText = term.Text; 42 | 43 | _regexImpl = regexImpl; 44 | 45 | _regexImpl.Compile(sText); 46 | 47 | _sPre = _regexImpl.Prefix() ?? ""; 48 | 49 | SetEnum(reader.Terms(new Term(term.Field, _sPre))); 50 | } 51 | 52 | /// Equality compare on the term 53 | protected override bool TermCompare(Term term) 54 | { 55 | if (_sField == term.Field) 56 | { 57 | string sSearchText = term.Text; 58 | if (sSearchText.StartsWith(_sPre)) return _regexImpl.Match(sSearchText); 59 | } //eif 60 | 61 | _bEndEnum = true; 62 | return false; 63 | } 64 | 65 | /// Equality measure on the term 66 | public override float Difference() 67 | { 68 | // TODO: adjust difference based on distance of searchTerm.text() and term().text() 69 | return 1.0F; 70 | } 71 | 72 | /// Indicates the end of the enumeration has been reached 73 | public override bool EndEnum() 74 | { 75 | return _bEndEnum; 76 | } 77 | 78 | //public override void Close() 79 | //{ 80 | // base.Close(); 81 | // _sField = null; 82 | //} 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Debug_LoadToIse.bat: -------------------------------------------------------------------------------- 1 | del %USERPROFILE%\Documents\WindowsPowerShell\Modules\PsISEProjectExplorer\* /Q 2 | powershell_ise.exe Debug_LoadToIse.ps1 -------------------------------------------------------------------------------- /PsISEProjectExplorer/Debug_LoadToIse.ps1: -------------------------------------------------------------------------------- 1 | $curDir = Split-Path -Parent $MyInvocation.MyCommand.Definition 2 | Import-Module "$curDir\bin\Debug\PsISEProjectExplorer\PsISEProjectExplorer.psd1" -Force 3 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Enums/FullTextFieldType.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PsISEProjectExplorer.Enums 3 | { 4 | public enum FullTextFieldType 5 | { 6 | CatchAll, 7 | Name, 8 | NameNotAnalyzed, 9 | Path 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Enums/NodeType.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PsISEProjectExplorer.Enums 3 | { 4 | public enum NodeType 5 | { 6 | // note: this enum values is used for ordering items in the tree view 7 | Directory = 1, 8 | File, 9 | Region, 10 | Class, 11 | ClassProperty, 12 | ClassConstructor, 13 | DslElement, 14 | Configuration, 15 | Function, 16 | Intermediate 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Enums/PowershellItemType.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Enums 2 | { 3 | public enum PowershellItemType 4 | { 5 | Root, 6 | Region, 7 | Function, 8 | Configuration, 9 | Class, 10 | ClassConstructor, 11 | ClassMethod, 12 | ClassProperty, 13 | DslElement 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/FullText/CustomAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using Lucene.Net.Analysis; 2 | 3 | namespace PsISEProjectExplorer.FullText 4 | { 5 | /// 6 | /// Custom Lucene Analyzer - like SimpleAnalyzer but treats numbers as text. 7 | /// 8 | public class CustomAnalyzer : Analyzer 9 | { 10 | 11 | public override TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) 12 | { 13 | return new CustomTokenizer(reader); 14 | } 15 | 16 | public override TokenStream ReusableTokenStream(System.String fieldName, System.IO.TextReader reader) 17 | { 18 | var tokenizer = (Tokenizer)PreviousTokenStream; 19 | if (tokenizer == null) 20 | { 21 | tokenizer = new CustomTokenizer(reader); 22 | PreviousTokenStream = tokenizer; 23 | } 24 | else 25 | tokenizer.Reset(reader); 26 | return tokenizer; 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/FullText/CustomTokenizer.cs: -------------------------------------------------------------------------------- 1 | using Lucene.Net.Analysis; 2 | 3 | namespace PsISEProjectExplorer.FullText 4 | { 5 | public class CustomTokenizer : CharTokenizer 6 | { 7 | 8 | private TokenizeRules TokenizeRules = new TokenizeRules(); 9 | 10 | /// Construct a new CustomTokenizer. 11 | public CustomTokenizer(System.IO.TextReader @in):base(@in) 12 | { 13 | } 14 | 15 | /// Collects only characters which satisfy 16 | /// . 17 | /// 18 | protected override bool IsTokenChar(char c) 19 | { 20 | return this.TokenizeRules.IsTokenChar(c); 21 | } 22 | 23 | /// Converts char to lower case 24 | /// . 25 | /// 26 | protected override char Normalize(char c) 27 | { 28 | return this.TokenizeRules.Normalize(c); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/FullText/DocumentFactory.cs: -------------------------------------------------------------------------------- 1 | using Lucene.Net.Documents; 2 | using Lucene.Net.Index; 3 | using PsISEProjectExplorer.Enums; 4 | 5 | namespace PsISEProjectExplorer.FullText 6 | { 7 | public class DocumentFactory 8 | { 9 | private readonly IndexWriter indexWriter; 10 | 11 | private readonly bool analyzeContents; 12 | 13 | public DocumentFactory(IndexWriter indexWriter, bool analyzeContents) 14 | { 15 | this.indexWriter = indexWriter; 16 | this.analyzeContents = analyzeContents; 17 | } 18 | 19 | public void AddDirectoryEntry(string path, string segment) 20 | { 21 | this.CreateDocument(path, segment, string.Empty); 22 | } 23 | 24 | public void AddFileEntry(string path, string fileName, string fileContents) 25 | { 26 | this.CreateDocument(path, fileName, fileContents); 27 | } 28 | 29 | public void AddPowershellItemEntry(string path, string name) 30 | { 31 | this.CreateDocument(path, name, string.Empty); 32 | } 33 | 34 | private void CreateDocument(string path, string name, string contents) 35 | { 36 | var doc = new Document(); 37 | var field = new Field(FullTextFieldType.Path.ToString(), path, Field.Store.YES, Field.Index.NOT_ANALYZED); 38 | doc.Add(field); 39 | field = new Field(FullTextFieldType.Name.ToString(), name, Field.Store.NO, Field.Index.ANALYZED) 40 | { 41 | OmitTermFreqAndPositions = true 42 | }; 43 | doc.Add(field); 44 | field = new Field(FullTextFieldType.NameNotAnalyzed.ToString(), name, Field.Store.NO, Field.Index.NOT_ANALYZED) 45 | { 46 | OmitTermFreqAndPositions = true 47 | }; 48 | doc.Add(field); 49 | field = new Field(FullTextFieldType.CatchAll.ToString(), name + " " + contents, Field.Store.NO, this.analyzeContents ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED); 50 | doc.Add(field); 51 | this.indexWriter.AddDocument(doc); 52 | this.indexWriter.Commit(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/FullText/FullTextDirectory.cs: -------------------------------------------------------------------------------- 1 | using Lucene.Net.Analysis; 2 | using Lucene.Net.Index; 3 | using Lucene.Net.Search; 4 | using Lucene.Net.Store; 5 | using PsISEProjectExplorer.Enums; 6 | using PsISEProjectExplorer.Model; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | namespace PsISEProjectExplorer.FullText 11 | { 12 | // note: one instance of this class can be used by many threads 13 | public class FullTextDirectory 14 | { 15 | private readonly Analyzer analyzer; 16 | 17 | private readonly Directory luceneDirectory; 18 | 19 | private readonly IndexWriter indexWriter; 20 | 21 | private IndexReader indexReader; 22 | 23 | private readonly CustomQueryParser customQueryParser; 24 | 25 | private readonly DocumentFactory documentFactory; 26 | 27 | public DocumentFactory DocumentFactory { get { return this.documentFactory; } } 28 | 29 | public FullTextDirectory(bool analyzeContents) 30 | { 31 | this.analyzer = new CustomAnalyzer(); 32 | this.luceneDirectory = new RAMDirectory(); 33 | this.indexWriter = new IndexWriter(this.luceneDirectory, this.analyzer, IndexWriter.MaxFieldLength.UNLIMITED); 34 | this.indexReader = this.indexWriter.GetReader(); 35 | this.customQueryParser = new CustomQueryParser(); 36 | this.documentFactory = new DocumentFactory(this.indexWriter, analyzeContents); 37 | } 38 | 39 | public IList SearchTerm(string searchTerm, FullTextFieldType field) 40 | { 41 | Query query = new TermQuery(new Term(field.ToString(), searchTerm)); 42 | return this.RunQuery(query); 43 | } 44 | 45 | public IList Search(SearchOptions searchOptions) 46 | { 47 | Query query = this.customQueryParser.Parse(searchOptions); 48 | return this.RunQuery(query); 49 | 50 | } 51 | 52 | public void DeleteDocument(string path) 53 | { 54 | this.indexWriter.DeleteDocuments(new Term(FullTextFieldType.Path.ToString(), path)); 55 | } 56 | 57 | private IList RunQuery(Query query) 58 | { 59 | // If two threads ran this method simultaneously, there would be issues with this.IndexReader. 60 | // Alternatively, there could be one RAMDirectory per filesystem directory. 61 | lock (this) 62 | { 63 | IndexReader newReader = this.indexReader.Reopen(); 64 | if (newReader != this.indexReader) 65 | { 66 | this.indexReader.Dispose(); 67 | this.indexReader = newReader; 68 | } 69 | 70 | IndexSearcher searcher; searcher = new IndexSearcher(newReader); 71 | if (query == null) 72 | { 73 | return new List(); 74 | } 75 | TopDocs hits = searcher.Search(query, 1000); 76 | 77 | return hits.ScoreDocs 78 | .Select(scoreDoc => searcher.Doc(scoreDoc.Doc).Get(FullTextFieldType.Path.ToString())) 79 | .Select(path => new SearchResult(path)) 80 | .ToList(); 81 | } 82 | } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/FullText/TokenizeRules.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace PsISEProjectExplorer.FullText 4 | { 5 | public class TokenizeRules 6 | { 7 | private static readonly char[] TokenSeparators = { '.', ',', ':', '(', ')', '[', ']', '{', '}', '\\', '/', '`', '\'', '"' }; 8 | 9 | // note this is used both in CustomQueryParser (for parsing user input) and CustomTokenizer (for parsing document) 10 | public bool IsTokenChar(char c) 11 | { 12 | return !System.Char.IsWhiteSpace(c) && !TokenSeparators.Contains(c); 13 | } 14 | 15 | public bool IsPhraseChar(char c) 16 | { 17 | return '"'.Equals(c); 18 | } 19 | 20 | public char Normalize(char c) 21 | { 22 | return System.Char.ToLower(c); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Install_to_PsGallery.ps1: -------------------------------------------------------------------------------- 1 | $Global:ErrorActionPreference = 'Stop' 2 | 3 | $publishParams = @{ 4 | Path = "$PSScriptRoot\.\bin\Release\PsISEProjectExplorer" 5 | NuGetApiKey = 'private' 6 | } 7 | 8 | Publish-Module @publishParams -------------------------------------------------------------------------------- /PsISEProjectExplorer/Install_to_UserModules.bat: -------------------------------------------------------------------------------- 1 | @pushd %~dp0 2 | @powershell -File Install_to_UserModules.ps1 3 | @pause 4 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Install_to_UserModules.ps1: -------------------------------------------------------------------------------- 1 | if ($PSVersionTable.PSVersion.Major -lt 3) { 2 | Write-Warning "PsISEProjectExplorer requires Powershell 3.0 or above" 3 | return 4 | } 5 | 6 | $Global:ErrorActionPreference = 'Stop' 7 | 8 | $currentDir = Split-Path -parent $MyInvocation.MyCommand.Path 9 | 10 | $docDir = [Environment]::getfolderpath("mydocuments") 11 | $moduleDir = "$docDir\WindowsPowerShell\Modules\PsISEProjectExplorer" 12 | $profileFile = "$docDir\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1" 13 | 14 | $copyToModules = Read-Host 'Install PsISEProjectExplorer to your Modules directory [y/n]?' 15 | if ($copyToModules -ieq 'y') { 16 | if (!(Test-Path $moduleDir)) { 17 | Write-Host "Creating directory '$moduleDir'..." -NoNewline 18 | New-Item -Path $moduleDir -ItemType Directory | Out-Null 19 | Write-Host "OK" 20 | } 21 | Write-Host "Unblocking PSISEProjectExplorer files..." -NoNewLine 22 | Get-ChildItem (Join-Path $currentDir "PsISEProjectExplorer") | Unblock-File 23 | Write-Host "OK" 24 | 25 | Write-Host "Copying PSISEProjectExplorer files to '$moduleDir'..." -NoNewline 26 | Copy-Item -Path (Join-Path $currentDir "PsISEProjectExplorer\*") -Destination $moduleDir -Recurse -Force 27 | Write-Host "OK" 28 | } else { 29 | return 30 | } 31 | 32 | Write-Host "" 33 | 34 | $installToProfile = Read-Host 'Install PsISEProjectExplorer to ISE Profile (will start when ISE starts) [y/n]?' 35 | 36 | if ($installToProfile -ieq 'y') { 37 | if (!(Test-Path $profileFile)) { 38 | Write-Host "Creating file '$profileFile'..." -NoNewline 39 | New-Item -Path $profileFile -ItemType file | Out-Null 40 | Write-Host "OK" 41 | $contents = "" 42 | } else { 43 | Write-Host "Reading file '$profileFile'..." -NoNewLine 44 | $contents = Get-Content -Path $profileFile | Out-String 45 | Write-Host "OK" 46 | } 47 | 48 | $importModule = "Import-Module PsISEProjectExplorer" 49 | 50 | if ($contents -inotmatch $importModule) { 51 | Write-Host "Adding '$importModule'..." -NoNewLine 52 | Add-Content -Path $profileFile -Value $importModule | Out-Null 53 | Write-Host "OK" 54 | } else { 55 | Write-Host "Import command for PSIseProjectExplorer already exists in profile file." 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/ChangePoolEntry.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Model 2 | { 3 | public class ChangePoolEntry 4 | { 5 | public string PathChanged { get; set; } 6 | 7 | public string PathAfterRename { get; set; } 8 | 9 | public string RootPath { get; set; } 10 | 11 | public ChangePoolEntry(string pathChanged, string rootPath, string pathAfterRename) 12 | { 13 | this.PathChanged = pathChanged; 14 | this.RootPath = rootPath; 15 | this.PathAfterRename = pathAfterRename; 16 | } 17 | 18 | public ChangePoolEntry(string pathChanged, string rootPath) 19 | : this(pathChanged, rootPath, null) 20 | { 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | if (!(obj is ChangePoolEntry)) 26 | { 27 | return false; 28 | } 29 | var other = (ChangePoolEntry)obj; 30 | return (other.PathChanged == this.PathChanged && other.RootPath == this.RootPath && other.PathAfterRename == this.PathAfterRename); 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | return ((this.PathChanged ?? "") + (this.RootPath ?? "") + (this.PathAfterRename ?? "")).GetHashCode(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/AbstractNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 6 | { 7 | public abstract class AbstractNode : INode 8 | { 9 | public abstract NodeType NodeType { get; } 10 | public virtual string Path { get; private set; } 11 | public virtual string Name { get; private set; } 12 | public virtual bool IsExcluded { get; protected set; } 13 | public virtual bool IsValid { get; protected set; } 14 | public virtual string Metadata { get; protected set; } 15 | public INode Parent { get; private set; } 16 | public ISet Children { get; private set; } 17 | public PowershellItem PowershellItem { get; private set; } 18 | 19 | protected AbstractNode(string path, string name, INode parent, PowershellItem powershellItem) 20 | : this(path, name, parent, powershellItem, false, true, null) 21 | { 22 | } 23 | 24 | protected AbstractNode(string path, string name, INode parent, PowershellItem powershellItem, bool isExcluded, bool isValid, string metadata) 25 | { 26 | if (path == null) { 27 | throw new ArgumentNullException("path"); 28 | } 29 | this.Path = path; 30 | this.Name = name; 31 | this.PowershellItem = powershellItem; 32 | this.IsExcluded = isExcluded; 33 | this.IsValid = isValid; 34 | this.Metadata = metadata; 35 | this.Parent = parent; 36 | this.Children = new SortedSet(NodeComparerProvider.NodeComparer); 37 | if (this.Parent != null) 38 | { 39 | if (!this.Parent.Children.Add(this)) 40 | { 41 | throw new InvalidOperationException(String.Format("Adding element '{0}' failed", path)); 42 | } 43 | } 44 | } 45 | 46 | public override bool Equals(object obj) 47 | { 48 | if (!(obj is INode)) 49 | { 50 | return false; 51 | } 52 | var node = (INode)obj; 53 | return (node.Path == this.Path); 54 | } 55 | 56 | public override int GetHashCode() 57 | { 58 | return this.Path.GetHashCode(); 59 | } 60 | 61 | public void Remove() 62 | { 63 | if (this.Parent != null) 64 | { 65 | this.Parent.Children.Remove(this); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/DirectoryNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 7 | { 8 | public class DirectoryNode : AbstractNode 9 | { 10 | public override NodeType NodeType { get { return NodeType.Directory; } } 11 | 12 | private ISet filesWithErrors = new HashSet(); 13 | 14 | private string metadata; 15 | 16 | public override string Metadata 17 | { 18 | get 19 | { 20 | var filesErrors = String.Join(Environment.NewLine, filesWithErrors.Select(file => "Error(s) in file " + file)); 21 | return (String.IsNullOrEmpty(this.metadata) ? String.Empty : this.metadata + Environment.NewLine) + filesErrors; 22 | } 23 | protected set 24 | { 25 | this.metadata = value; 26 | } 27 | } 28 | 29 | public DirectoryNode(string path, string name, INode parent, bool isExcluded, string errorMessage) 30 | : base(path, name, parent, null, isExcluded, errorMessage == null, errorMessage) 31 | { 32 | } 33 | 34 | public void AddFileError(string fileName) 35 | { 36 | this.IsValid = false; 37 | this.filesWithErrors.Add(fileName); 38 | } 39 | 40 | public void RemoveFileError(string fileName) 41 | { 42 | this.filesWithErrors.Remove(fileName); 43 | this.IsValid = !this.filesWithErrors.Any(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/FileNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System; 3 | 4 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 5 | { 6 | public class FileNode : AbstractNode 7 | { 8 | public override NodeType NodeType { get { return NodeType.File; } } 9 | 10 | public FileNode(string path, string name, INode parent, bool isExcluded, string errorMessage) 11 | : base(path, name, parent, null, isExcluded, errorMessage == null, errorMessage) 12 | { 13 | } 14 | 15 | public void MakeInvalid(string errorMessage) 16 | { 17 | this.IsValid = false; 18 | if (this.Metadata == null) 19 | { 20 | this.Metadata = errorMessage; 21 | } 22 | else 23 | { 24 | this.Metadata += Environment.NewLine + errorMessage; 25 | } 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/INode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System.Collections.Generic; 3 | 4 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 5 | { 6 | public interface INode 7 | { 8 | NodeType NodeType { get; } 9 | string Path { get; } 10 | string Name { get; } 11 | bool IsExcluded { get; } 12 | bool IsValid { get; } 13 | string Metadata { get; } 14 | INode Parent { get; } 15 | ISet Children { get; } 16 | 17 | void Remove(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/NodeComparerAlphabetical.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 5 | { 6 | public class NodeComparerAlphabetical : IComparer 7 | { 8 | public static readonly IComparer NodeComparer = new NodeComparerAlphabetical(); 9 | 10 | public int Compare(INode x, INode y) 11 | { 12 | if (x == null && y == null) 13 | { 14 | return 0; 15 | } 16 | if (x == null) 17 | { 18 | return -1; 19 | } 20 | if (y == null) 21 | { 22 | return 1; 23 | } 24 | if (x.NodeType != y.NodeType) 25 | { 26 | return x.NodeType.CompareTo(y.NodeType); 27 | } 28 | int nameCompare = string.Compare(x.Name, y.Name, StringComparison.InvariantCulture); 29 | if (nameCompare != 0) 30 | { 31 | return nameCompare; 32 | } 33 | return string.Compare(x.Path, y.Path, StringComparison.InvariantCulture); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/NodeComparerAsIs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 5 | { 6 | public class NodeComparerAsIs : IComparer 7 | { 8 | public static readonly IComparer NodeComparer = new NodeComparerAsIs(); 9 | 10 | public int Compare(INode x, INode y) 11 | { 12 | if (x == null && y == null) 13 | { 14 | return 0; 15 | } 16 | if (x == null) 17 | { 18 | return -1; 19 | } 20 | if (y == null) 21 | { 22 | return 1; 23 | } 24 | bool bothItemsArePowershellItemNode = x is PowershellItemNode && y is PowershellItemNode; 25 | if (x.NodeType != y.NodeType && !bothItemsArePowershellItemNode) 26 | { 27 | return x.NodeType.CompareTo(y.NodeType); 28 | } 29 | return bothItemsArePowershellItemNode ? CompareLines(x, y) : CompareNames(x, y); 30 | } 31 | 32 | private int CompareNames(INode x, INode y) 33 | { 34 | int nameCompare = string.Compare(x.Name, y.Name, StringComparison.InvariantCulture); 35 | if (nameCompare != 0) 36 | { 37 | return nameCompare; 38 | } 39 | return string.Compare(x.Path, y.Path, StringComparison.InvariantCulture); 40 | } 41 | 42 | private int CompareLines(INode x, INode y) 43 | { 44 | PowershellItemNode psNode1 = x as PowershellItemNode; 45 | PowershellItemNode psNode2 = y as PowershellItemNode; 46 | if (psNode1.PowershellItem == null && psNode2.PowershellItem == null) 47 | { 48 | return 0; 49 | } 50 | if (psNode1.PowershellItem == null) 51 | { 52 | return -1; 53 | } 54 | if (psNode2.PowershellItem == null) 55 | { 56 | return 1; 57 | } 58 | int lineNumberCompare = psNode1.PowershellItem.StartLine - psNode2.PowershellItem.StartLine; 59 | if (lineNumberCompare != 0) 60 | { 61 | return lineNumberCompare; 62 | } 63 | return psNode1.PowershellItem.StartColumn - psNode2.PowershellItem.StartColumn; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/NodeComparerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 4 | { 5 | public class NodeComparerProvider 6 | { 7 | public static bool SortFunctions { get; set; } 8 | 9 | public static IComparer NodeComparer 10 | { 11 | get 12 | { 13 | return SortFunctions ? NodeComparerAlphabetical.NodeComparer : NodeComparerAsIs.NodeComparer; 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/PowershellItemNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System; 3 | 4 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 5 | { 6 | public class PowershellItemNode : AbstractNode 7 | { 8 | public override NodeType NodeType { get 9 | { 10 | if (PowershellItem != null) 11 | { 12 | switch (PowershellItem.Type) 13 | { 14 | case PowershellItemType.Configuration: return NodeType.Configuration; 15 | case PowershellItemType.Class: return NodeType.Class; 16 | case PowershellItemType.ClassProperty: return NodeType.ClassProperty; 17 | case PowershellItemType.ClassConstructor: return NodeType.ClassConstructor; 18 | case PowershellItemType.DslElement: return NodeType.DslElement; 19 | case PowershellItemType.Region: return NodeType.Region; 20 | } 21 | } 22 | return NodeType.Function; 23 | } 24 | } 25 | 26 | public string FilePath { get; private set; } 27 | 28 | public PowershellItemNode(string filePath, PowershellItem item, INode parent) 29 | : base(GetNodePath(filePath, item, parent), item.Name, parent, item) 30 | { 31 | this.FilePath = filePath; 32 | } 33 | 34 | private static string GetNodePath(string filePath, PowershellItem item, INode parent) 35 | { 36 | if (filePath == null) 37 | { 38 | throw new ArgumentNullException("filePath"); 39 | } 40 | if (item == null) 41 | { 42 | throw new ArgumentNullException("item"); 43 | } 44 | 45 | string basePath = parent != null && parent is PowershellItemNode ? parent.Path : filePath; 46 | return System.IO.Path.Combine(basePath, item.StartLine.ToString() + "_" + item.StartColumn.ToString()); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/RootNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | 3 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 4 | { 5 | public class RootNode : AbstractNode 6 | { 7 | public override NodeType NodeType { get { return NodeType.Intermediate; } } 8 | 9 | public RootNode(string path) 10 | : base(path, string.Empty, null, null) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/DocHierarchy/Nodes/ViewNode.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace PsISEProjectExplorer.Model.DocHierarchy.Nodes 6 | { 7 | public class ViewNode : INode 8 | { 9 | public NodeType NodeType { get { return this.Node.NodeType; } } 10 | 11 | public INode Node { get; private set; } 12 | 13 | public string Path 14 | { 15 | get 16 | { 17 | return this.Node.Path; 18 | } 19 | } 20 | 21 | public string Name 22 | { 23 | get 24 | { 25 | return this.Node.Name; 26 | } 27 | } 28 | 29 | public bool IsValid 30 | { 31 | get 32 | { 33 | return this.Node.IsValid; 34 | } 35 | } 36 | 37 | public bool IsExcluded 38 | { 39 | get 40 | { 41 | return this.Node.IsExcluded; 42 | } 43 | } 44 | 45 | public string Metadata 46 | { 47 | get 48 | { 49 | return this.Node.Metadata; 50 | } 51 | } 52 | 53 | 54 | public INode Parent { get; private set; } 55 | 56 | public ISet Children { get; private set; } 57 | 58 | public ViewNode(INode viewedNode, INode parent) 59 | { 60 | if (viewedNode == null) 61 | { 62 | throw new ArgumentNullException("viewedNode"); 63 | } 64 | this.Node = viewedNode; 65 | this.Parent = parent; 66 | this.Children = new SortedSet(NodeComparerProvider.NodeComparer); 67 | if (this.Parent != null) 68 | { 69 | this.Parent.Children.Add(this); 70 | } 71 | } 72 | 73 | public override bool Equals(object obj) 74 | { 75 | if (!(obj is INode)) 76 | { 77 | return false; 78 | } 79 | var node = (INode)obj; 80 | return (node.Path == this.Path); 81 | } 82 | 83 | public override int GetHashCode() 84 | { 85 | return this.Path.GetHashCode(); 86 | } 87 | 88 | public void Remove() 89 | { 90 | if (this.Parent != null) 91 | { 92 | this.Parent.Children.Remove(this); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/EditorInfo.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Model 2 | { 3 | public class EditorInfo 4 | { 5 | public string CurrentLine { get; private set; } 6 | 7 | public int CurrentLineNum { get; private set; } 8 | 9 | public int CurrentColumn { get; private set; } 10 | 11 | public EditorInfo(string currentLine, int currentLineNum, int currentColumn) 12 | { 13 | this.CurrentLine = currentLine; 14 | this.CurrentLineNum = currentLineNum; 15 | this.CurrentColumn = currentColumn; 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/FileSystemChangedInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PsISEProjectExplorer.Model 4 | { 5 | public class FileSystemChangedInfo 6 | { 7 | private IEnumerable pathsChanged; 8 | 9 | public IEnumerable PathsChanged { get { return this.pathsChanged; } } 10 | 11 | public FileSystemChangedInfo(IEnumerable pathsChanged) 12 | { 13 | this.pathsChanged = pathsChanged; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/IndexingMode.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Model 2 | { 3 | public enum IndexingMode 4 | { 5 | LOCAL_FILES, 6 | ALL_FILES, 7 | NO_FILES 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/LineInfo.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PsISEProjectExplorer.Model 3 | { 4 | public class LineInfo 5 | { 6 | public string LineText { get; private set; } 7 | 8 | public int LineNumber { get; private set; } 9 | 10 | public LineInfo(string lineText, int lineNumber) 11 | { 12 | this.LineText = lineText; 13 | this.LineNumber = lineNumber; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/PowershellItem.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | using System.Collections.Generic; 3 | namespace PsISEProjectExplorer.Model 4 | { 5 | public class PowershellItem 6 | { 7 | public PowershellItemType Type { get; private set; } 8 | 9 | public string Name { get; private set; } 10 | 11 | public int StartLine { get; private set; } 12 | 13 | public int StartColumn { get; private set; } 14 | 15 | public int EndColumn { get; private set; } 16 | 17 | public int NestingLevel { get; private set; } 18 | 19 | public PowershellItem Parent { get; private set; } 20 | 21 | public string ParsingErrors { get; private set; } 22 | 23 | public IList Children { get; private set; } 24 | 25 | public PowershellItem(PowershellItemType type, string name, int startLine, int startColumn, int endColumn, int nestingLevel, PowershellItem parent, string parsingErrors) 26 | { 27 | this.Type = type; 28 | this.Name = name; 29 | this.StartLine = startLine; 30 | this.StartColumn = startColumn; 31 | this.EndColumn = endColumn; 32 | this.NestingLevel = nestingLevel; 33 | this.Parent = parent; 34 | this.ParsingErrors = parsingErrors; 35 | this.Children = new List(); 36 | if (parent != null) 37 | { 38 | this.Parent.Children.Add(this); 39 | } 40 | } 41 | 42 | public void Reparent(PowershellItem newParent) 43 | { 44 | if (Parent != null) 45 | { 46 | this.Parent.Children.Remove(this); 47 | } 48 | this.Parent = newParent; 49 | if (newParent != null) 50 | { 51 | newParent.Children.Add(this); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/PowershellParseResult.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace PsISEProjectExplorer.Model 4 | { 5 | public class PowershellParseResult 6 | { 7 | public PowershellItem RootPowershellItem { get; private set; } 8 | 9 | public string ErrorMessage { get; set; } 10 | 11 | public string Path { get; private set; } 12 | 13 | public string FileContents { get; private set; } 14 | 15 | public bool IsDirectory { get; private set; } 16 | 17 | public bool IsExcluded { get; private set; } 18 | 19 | public PowershellParseResult(PowershellItem rootPowershellItem, string errorMessage, string path, string fileContents, bool isDirectory, bool isExcluded) 20 | { 21 | this.RootPowershellItem = rootPowershellItem; 22 | if (rootPowershellItem != null) 23 | { 24 | this.ErrorMessage = this.RootPowershellItem.ParsingErrors; 25 | } 26 | else 27 | { 28 | this.ErrorMessage = errorMessage; 29 | } 30 | this.Path = path; 31 | this.FileContents = fileContents; 32 | this.IsDirectory = isDirectory; 33 | this.IsExcluded = isExcluded; 34 | } 35 | 36 | 37 | public string FileName 38 | { 39 | get 40 | { 41 | return Path.Split('\\').Last(); 42 | } 43 | } 44 | 45 | public bool IsValid 46 | { 47 | get 48 | { 49 | return ErrorMessage != null; 50 | } 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/PowershellRegion.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.Model 2 | { 3 | public class PowershellRegion 4 | { 5 | public string Name { get; set; } 6 | public int StartLine { get; set; } 7 | public int EndLine { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/SearchOptions.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Enums; 2 | 3 | namespace PsISEProjectExplorer.Model 4 | { 5 | public class SearchOptions 6 | { 7 | public FullTextFieldType SearchField { get; set; } 8 | 9 | public string SearchText { get; set; } 10 | 11 | public bool SearchRegex { get; set; } 12 | 13 | public SearchOptions(FullTextFieldType searchField, string searchText, bool searchRegex) 14 | { 15 | this.SearchField = searchField; 16 | this.SearchText = searchText == null ? string.Empty : searchText; 17 | this.SearchRegex = searchRegex; 18 | } 19 | 20 | public SearchOptions(SearchOptions searchOptions) : this(searchOptions.SearchField, searchOptions.SearchText, searchOptions.SearchRegex) 21 | { 22 | } 23 | 24 | public override bool Equals(object obj) 25 | { 26 | if (!(obj is SearchOptions)) 27 | { 28 | return false; 29 | } 30 | var other = (SearchOptions)obj; 31 | return (other.SearchField == this.SearchField && other.SearchText == this.SearchText && other.SearchRegex == this.SearchRegex); 32 | } 33 | 34 | public override int GetHashCode() 35 | { 36 | return (this.SearchField + (this.SearchText ?? "") + this.SearchRegex).GetHashCode(); 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/SearchResult.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 2 | 3 | namespace PsISEProjectExplorer.Model 4 | { 5 | public class SearchResult 6 | { 7 | public string Path { get; private set; } 8 | 9 | public INode Node { get; set; } 10 | 11 | public SearchResult(string path) 12 | { 13 | this.Path = path; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Model/TokenPosition.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PsISEProjectExplorer.Model 3 | { 4 | public class TokenPosition 5 | { 6 | public int MatchLength { get; private set; } 7 | 8 | public int Line { get; private set; } 9 | 10 | public int Column { get; private set; } 11 | 12 | public TokenPosition(int matchLength, int line, int column) 13 | { 14 | this.MatchLength = matchLength; 15 | this.Line = line; 16 | this.Column = column; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/NLog.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.InteropServices; 4 | using System.Windows; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("PsISEProjectExplorer")] 10 | [assembly: AssemblyDescription("Powershell ISE Project Explorer")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("PsISEProjectExplorer")] 14 | [assembly: AssemblyCopyright("Copyright © 2016 Marcin Grzywa")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | //In order to begin building localizable applications, set 24 | //CultureYouAreCodingWith in your .csproj file 25 | //inside a . For example, if you are using US english 26 | //in your source files, set the to en-US. Then uncomment 27 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 28 | //the line below to match the UICulture setting in the project file. 29 | 30 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 31 | 32 | 33 | [assembly:ThemeInfo( 34 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 35 | //(used if a resource is not found in the page, 36 | // or application resource dictionaries) 37 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 38 | //(used if a resource is not found in the page, 39 | // app, or any theme specific resource dictionaries) 40 | )] 41 | 42 | 43 | // Version information for an assembly consists of the following four values: 44 | // 45 | // Major Version 46 | // Minor Version 47 | // Build Number 48 | // Revision 49 | // 50 | // You can specify all the values or you can default the Build and Revision Numbers 51 | // by using the '*' as shown below: 52 | // [assembly: AssemblyVersion("1.0.*")] 53 | [assembly: AssemblyVersion("1.0.0.0")] 54 | [assembly: AssemblyFileVersion("1.0.0.0")] 55 | [assembly: NeutralResourcesLanguageAttribute("en-US")] 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PsISEProjectExplorer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PsISEProjectExplorer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PsISEProjectExplorer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/add.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/cancel.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/cross.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_class.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_classconstructor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_classconstructor.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_classproperty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_classproperty.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_configuration.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_directory.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_dslelement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_dslelement.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_file.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_function.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_overlay_excluded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_overlay_excluded.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_overlay_invalid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_overlay_invalid.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/node_region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/node_region.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/textfield_dotsource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/textfield_dotsource.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/textfield_exclude.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/textfield_exclude.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/textfield_include.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/textfield_include.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/textfield_rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/textfield_rename.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_autoUpdateProjectDir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_autoUpdateProjectDir.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_index_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_index_all.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_index_local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_index_local.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_refresh.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_searchRegex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_searchRegex.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_showAllFiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_showAllFiles.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_sort.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_sync.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_toggle-expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_toggle-expand.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Resources/toolbar_toggle_collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/Resources/toolbar_toggle_collapse.png -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/DocumentHierarchyIndexer.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using PsISEProjectExplorer.Model.DocHierarchy; 3 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace PsISEProjectExplorer.Services 9 | { 10 | [Component] 11 | public class DocumentHierarchyIndexer 12 | { 13 | 14 | public bool AddFileSystemNode(DocumentHierarchy documentHierarchy, PowershellParseResult parseResult) 15 | { 16 | if (documentHierarchy.GetNode(parseResult.Path) != null || parseResult.Path == documentHierarchy.RootNode.Path) 17 | { 18 | return false; 19 | } 20 | INode lastDirNode = this.FillHierarchyWithIntermediateDirectories(documentHierarchy, parseResult.Path, parseResult.IsDirectory, parseResult.IsExcluded, parseResult.ErrorMessage); 21 | if (!parseResult.IsDirectory) 22 | { 23 | FileNode fileNode = documentHierarchy.CreateNewFileNode(parseResult.Path, parseResult.FileContents, lastDirNode, parseResult.IsExcluded, parseResult.ErrorMessage); 24 | if (parseResult.RootPowershellItem != null) 25 | { 26 | documentHierarchy.CreateNewPowershellItemNode(parseResult.Path, parseResult.RootPowershellItem, fileNode); 27 | var parent = fileNode.Parent; 28 | while (parent != null && parent is DirectoryNode) 29 | { 30 | if (parseResult.RootPowershellItem.ParsingErrors != null) 31 | { 32 | ((DirectoryNode)parent).AddFileError(fileNode.Name); 33 | } 34 | else 35 | { 36 | ((DirectoryNode)parent).RemoveFileError(fileNode.Name); 37 | } 38 | parent = parent.Parent; 39 | } 40 | } 41 | } 42 | return true; 43 | } 44 | 45 | private INode FillHierarchyWithIntermediateDirectories(DocumentHierarchy documentHierarchy, string path, bool lastSegmentIsDirectory, bool isExcluded, string errorMessage) 46 | { 47 | IList segments = path.Replace(documentHierarchy.RootNode.Path + "\\", "").Split('\\').ToList(); 48 | var currentNode = documentHierarchy.RootNode; 49 | if (!lastSegmentIsDirectory) 50 | { 51 | if (segments.Count <= 1) 52 | { 53 | return currentNode; 54 | } 55 | segments.RemoveAt(segments.Count - 1); 56 | isExcluded = false; 57 | } 58 | var currentAbsolutePath = documentHierarchy.RootNode.Path; 59 | int lastIndex = segments.Count - 1; 60 | int i = 0; 61 | foreach (string segment in segments) 62 | { 63 | currentAbsolutePath = Path.Combine(currentAbsolutePath, segment); 64 | bool nodeIsExcluded = i == lastIndex ? isExcluded : false; 65 | currentNode = documentHierarchy.GetNode(currentAbsolutePath) ?? 66 | documentHierarchy.CreateNewDirectoryNode(currentAbsolutePath, currentNode, nodeIsExcluded, currentAbsolutePath == path ? errorMessage : null); 67 | i++; 68 | } 69 | return currentNode; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/FileReader.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | namespace PsISEProjectExplorer.Services 8 | { 9 | [Component] 10 | public class FileReader 11 | { 12 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 13 | 14 | // note: exceptions not handled 15 | public string ReadFileAsString(string path) 16 | { 17 | using (var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite)) 18 | { 19 | using (var bs = new BufferedStream(fs)) 20 | { 21 | using (var sr = new StreamReader(bs)) 22 | { 23 | return sr.ReadToEnd(); 24 | } 25 | } 26 | } 27 | } 28 | 29 | // note: exceptions handled and ignored (logged only) 30 | public IEnumerable ReadFileAsEnumerableWithWrap(string path, int startLine) 31 | { 32 | FileStream fs = null; 33 | BufferedStream bs = null; 34 | StreamReader sr = null; 35 | try 36 | { 37 | fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite); 38 | bs = new BufferedStream(fs); 39 | sr = new StreamReader(bs); 40 | } 41 | catch (IOException e) 42 | { 43 | Logger.Error(e, "Cannot open file '" + path + "'"); 44 | if (sr != null) 45 | sr.Dispose(); 46 | if (bs != null) 47 | bs.Dispose(); 48 | if (fs != null) 49 | fs.Dispose(); 50 | yield break; 51 | } 52 | 53 | string line; 54 | IList wrappedLines = new List(startLine - 1); 55 | int lineNum = 0; 56 | String startLineString = string.Empty; 57 | do 58 | { 59 | try 60 | { 61 | line = sr.ReadLine(); 62 | lineNum++; 63 | } 64 | catch (Exception e) 65 | { 66 | Logger.Error(e, "Cannot read from file '" + path + "'"); 67 | sr.Dispose(); 68 | bs.Dispose(); 69 | fs.Dispose(); 70 | yield break; 71 | } 72 | if (line != null) 73 | { 74 | if (lineNum >= startLine) 75 | { 76 | if (lineNum == startLine) 77 | { 78 | startLineString = line; 79 | } 80 | yield return new LineInfo(line, lineNum); 81 | } 82 | else 83 | { 84 | wrappedLines.Add(line); 85 | } 86 | } 87 | } 88 | while (line != null); 89 | sr.Dispose(); 90 | bs.Dispose(); 91 | fs.Dispose(); 92 | 93 | int i = 1; 94 | foreach (string wrappedLine in wrappedLines) 95 | { 96 | yield return new LineInfo(wrappedLine, i++); 97 | } 98 | yield return new LineInfo(startLineString, i); 99 | 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/FileSystemChangeNotifier.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using PsISEProjectExplorer.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using NLog; 8 | 9 | namespace PsISEProjectExplorer.Services 10 | { 11 | public class FileSystemChangeNotifier 12 | { 13 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 14 | 15 | public event EventHandler FileSystemChanged; 16 | 17 | private readonly ISet changePool = new HashSet(); 18 | 19 | private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); 20 | 21 | private readonly string Name; 22 | 23 | private readonly FileSystemOperationsService fileSystemOperationsService; 24 | 25 | public FileSystemChangeNotifier(string name, FileSystemOperationsService fileSystemOperationsService) 26 | { 27 | this.fileSystemOperationsService = fileSystemOperationsService; 28 | this.Name = name; 29 | Task.Factory.StartNew(ChangeNotifier); 30 | } 31 | 32 | public void AddChangePoolEntry(ChangePoolEntry changePoolEntry) 33 | { 34 | lock (this) 35 | { 36 | this.changePool.Add(changePoolEntry); 37 | } 38 | } 39 | 40 | public void ClearChangePool() 41 | { 42 | lock (this) 43 | { 44 | this.changePool.Clear(); 45 | } 46 | } 47 | 48 | // runs on a separate thread (created in constructor) 49 | private void ChangeNotifier() 50 | { 51 | if (Thread.CurrentThread.Name == null) 52 | { 53 | Thread.CurrentThread.Name = this.Name; 54 | } 55 | while (true) 56 | { 57 | Thread.Sleep(200); 58 | if (cancellationTokenSource.Token.IsCancellationRequested) 59 | { 60 | return; 61 | } 62 | FileSystemChangedInfo changedInfo = null; 63 | lock (this) 64 | { 65 | if (this.changePool.Any()) 66 | { 67 | IList pathsChanged = RemoveSubdirectories(changePool); 68 | changedInfo = new FileSystemChangedInfo(pathsChanged); 69 | this.changePool.Clear(); 70 | } 71 | } 72 | if (changedInfo != null && this.FileSystemChanged != null) 73 | { 74 | FileSystemChanged(this, changedInfo); 75 | } 76 | } 77 | } 78 | 79 | private IList RemoveSubdirectories(ISet dirList) 80 | { 81 | IList result = new List(); 82 | foreach (ChangePoolEntry entry in dirList) 83 | { 84 | string dir = entry.PathChanged; 85 | if (dirList.Select(d => d.PathChanged).Where(d => d != dir).All(d => !fileSystemOperationsService.IsSubdirectory(d, dir))) 86 | { 87 | result.Add(entry); 88 | } 89 | } 90 | return result; 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/FileSystemOperationsService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace PsISEProjectExplorer.Services 5 | { 6 | [Component] 7 | public class FileSystemOperationsService 8 | { 9 | public void RenameFileOrDirectory(string filePath, string newFilePath) 10 | { 11 | if (newFilePath == filePath) 12 | { 13 | return; 14 | } 15 | if (Directory.Exists(filePath)) 16 | { 17 | if (IsSubdirectory(filePath, newFilePath)) 18 | { 19 | throw new InvalidOperationException("Cannot move folder - the destination folder cannot be a subfolder of the source folder."); 20 | } 21 | Directory.Move(filePath, newFilePath); 22 | } 23 | else if (File.Exists(filePath)) 24 | { 25 | File.Move(filePath, newFilePath); 26 | } 27 | else 28 | { 29 | throw new InvalidOperationException(String.Format("Path '{0}' does not exist.", filePath)); 30 | } 31 | } 32 | 33 | public void DeleteFileOrDirectory(string filePath) 34 | { 35 | if (Directory.Exists(filePath)) 36 | { 37 | Directory.Delete(filePath, true); 38 | } 39 | else if (File.Exists(filePath)) 40 | { 41 | File.Delete(filePath); 42 | } 43 | else 44 | { 45 | throw new InvalidOperationException(String.Format("Path '{0}' does not exist.", filePath)); 46 | } 47 | } 48 | 49 | public void CreateFile(string filePath) 50 | { 51 | if (File.Exists(filePath)) 52 | { 53 | throw new InvalidOperationException("File already exists. You should be able to see it when you enable 'Show all files' option."); 54 | } 55 | File.Create(filePath).Dispose(); 56 | } 57 | 58 | public void CreateDirectory(string filePath) 59 | { 60 | if (Directory.Exists(filePath)) 61 | { 62 | throw new InvalidOperationException("Directory already exists. You should be able to see it when you enable 'Show all files' option."); 63 | } 64 | Directory.CreateDirectory(filePath); 65 | } 66 | 67 | public bool IsSubdirectory(string rootDir, string potentialSubDir) 68 | { 69 | if (String.IsNullOrEmpty(rootDir) || String.IsNullOrEmpty(potentialSubDir)) 70 | { 71 | return false; 72 | } 73 | 74 | DirectoryInfo root = new DirectoryInfo(rootDir); 75 | DirectoryInfo sub = new DirectoryInfo(potentialSubDir); 76 | while (sub.Parent != null) 77 | { 78 | if (sub.Parent.FullName == root.FullName) 79 | { 80 | return true; 81 | } 82 | sub = sub.Parent; 83 | } 84 | return false; 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/IPowershellTokenizer.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace PsISEProjectExplorer.Services 9 | { 10 | public interface IPowershellTokenizer 11 | { 12 | PowershellItem GetPowershellItems(string path, string contents); 13 | 14 | string GetTokenAtColumn(string line, int column); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/Powershell5Tokenizer.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.Config; 3 | using PsISEProjectExplorer.Enums; 4 | using PsISEProjectExplorer.Model; 5 | using System.Management.Automation.Language; 6 | 7 | namespace PsISEProjectExplorer.Services 8 | { 9 | public class Powershell5Tokenizer : PowershellBaseTokenizer 10 | { 11 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 12 | 13 | private Powershell5TokenVisitor tokenVisitor; 14 | 15 | public Powershell5Tokenizer(ConfigValues configValues) : base(configValues) 16 | { 17 | this.tokenVisitor = new Powershell5TokenVisitor(this.OnFunctionVisit, 18 | this.OnConfigurationVisit, 19 | this.OnClassVisit, 20 | this.OnClassPropertyVisit, 21 | this.OnClassConstructorVisit, 22 | this.OnClassMethodVisit, 23 | this.GetDslInstanceName, 24 | this.OnDslVisit 25 | ); 26 | } 27 | 28 | protected override void VisitTokens(Ast ast) 29 | { 30 | this.tokenVisitor.VisitTokens(ast); 31 | } 32 | 33 | private object OnClassVisit(string name, IScriptExtent extent, int nestingLevel, object parent) 34 | { 35 | return CreateNewPowershellItem(PowershellItemType.Class, name, extent, (PowershellItem)parent, nestingLevel); 36 | } 37 | 38 | private object OnClassPropertyVisit(string name, IScriptExtent extent, int nestingLevel, object parent) 39 | { 40 | return CreateNewPowershellItem(PowershellItemType.ClassProperty, name, extent, (PowershellItem)parent, nestingLevel); 41 | } 42 | 43 | private object OnClassConstructorVisit(string name, IScriptExtent extent, int nestingLevel, object parent) 44 | { 45 | return CreateNewPowershellItem(PowershellItemType.ClassConstructor, name, extent, (PowershellItem)parent, nestingLevel); 46 | } 47 | 48 | private object OnClassMethodVisit(string name, IScriptExtent extent, int nestingLevel, object parent) 49 | { 50 | return CreateNewPowershellItem(PowershellItemType.ClassMethod, name, extent, (PowershellItem)parent, nestingLevel); 51 | } 52 | 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/PowershellFileParser.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using System; 3 | 4 | namespace PsISEProjectExplorer.Services 5 | { 6 | [Component] 7 | public class PowershellFileParser 8 | { 9 | private readonly IPowershellTokenizer powershellTokenizer; 10 | 11 | private readonly FileReader fileReader; 12 | 13 | private readonly PowershellTreeRestructurer powershellTreeRestructurer; 14 | 15 | public PowershellFileParser(PowershellTokenizerProvider powershellTokenizerProvider, FileReader fileReader, PowershellTreeRestructurer powershellTreeRestructurer) 16 | { 17 | this.powershellTokenizer = powershellTokenizerProvider.PowershellTokenizer; 18 | this.fileReader = fileReader; 19 | this.powershellTreeRestructurer = powershellTreeRestructurer; 20 | } 21 | 22 | public PowershellParseResult ParseFile(string path, bool isDirectory, bool isExcluded, string errorMessage) 23 | { 24 | if (isExcluded || isDirectory || !FilesPatternProvider.IsPowershellFile(path)) 25 | { 26 | return new PowershellParseResult(null, errorMessage, path, null, isDirectory, isExcluded); 27 | } 28 | string fileContents; 29 | try 30 | { 31 | fileContents = fileReader.ReadFileAsString(path); 32 | } 33 | catch (Exception e) 34 | { 35 | return new PowershellParseResult(null, e.Message, path, null, isDirectory, isExcluded); 36 | } 37 | if (fileContents != null) 38 | { 39 | var rootPowershellItem = this.powershellTokenizer.GetPowershellItems(path, fileContents); 40 | rootPowershellItem = this.powershellTreeRestructurer.AddRegions(rootPowershellItem, fileContents); 41 | return new PowershellParseResult(rootPowershellItem, errorMessage, path, fileContents, isDirectory, isExcluded); 42 | } 43 | return new PowershellParseResult(null, errorMessage, path, fileContents, isDirectory, isExcluded); 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/PowershellLegacyTokenizer.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.Config; 3 | using System.Management.Automation.Language; 4 | 5 | namespace PsISEProjectExplorer.Services 6 | { 7 | public class PowershellLegacyTokenizer : PowershellBaseTokenizer 8 | { 9 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 10 | 11 | private PowershellLegacyTokenVisitor tokenVisitor; 12 | 13 | public PowershellLegacyTokenizer(ConfigValues configValues) : base(configValues) 14 | { 15 | this.tokenVisitor = new PowershellLegacyTokenVisitor( 16 | this.OnFunctionVisit, 17 | this.OnConfigurationVisit, 18 | this.GetDslInstanceName, 19 | this.OnDslVisit); 20 | } 21 | 22 | protected override void VisitTokens(Ast ast) 23 | { 24 | this.tokenVisitor.visitTokens(ast); 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/PowershellTokenizerProvider.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.Config; 3 | using System; 4 | 5 | namespace PsISEProjectExplorer.Services 6 | { 7 | [Component] 8 | public class PowershellTokenizerProvider 9 | { 10 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 11 | 12 | private IPowershellTokenizer powershellTokenizer; 13 | 14 | public IPowershellTokenizer PowershellTokenizer { get { return this.powershellTokenizer; } } 15 | 16 | public PowershellTokenizerProvider(ConfigValues configValues) { 17 | Type t = typeof(System.Management.Automation.Language.AstVisitor); 18 | string assemblyName = t.Assembly.FullName.ToString(); 19 | bool isPowershell5Available = Type.GetType("System.Management.Automation.Language.AstVisitor2," + assemblyName, false) != null; 20 | if (isPowershell5Available) 21 | { 22 | Logger.Info("Using Powershell5Tokenizer"); 23 | this.powershellTokenizer = new Powershell5Tokenizer(configValues); 24 | } 25 | else 26 | { 27 | Logger.Info("Using PowershellLegacyTokenizer"); 28 | this.powershellTokenizer = new PowershellLegacyTokenizer(configValues); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/Services/RootDirectoryProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace PsISEProjectExplorer.Services 7 | { 8 | [Component] 9 | public class RootDirectoryProvider 10 | { 11 | public string GetRootDirectoryToSearch(string filePath) 12 | { 13 | if (String.IsNullOrEmpty(filePath)) 14 | { 15 | return null; 16 | } 17 | string driveRoot = Path.GetPathRoot(filePath).ToLowerInvariant(); 18 | string rootDir = Path.GetDirectoryName(filePath); 19 | if (String.IsNullOrEmpty(rootDir)) 20 | { 21 | return null; 22 | } 23 | var filesPatternProvider = new FilesPatternProvider(); 24 | string currentDir = rootDir; 25 | while (true) 26 | { 27 | var currentDirInfo = Directory.GetParent(currentDir); 28 | if (currentDirInfo == null || currentDirInfo.FullName.ToLowerInvariant() == driveRoot) 29 | { 30 | // TODO: why root dir is disallowed? 31 | return (rootDir.ToLowerInvariant() == driveRoot ? null : rootDir); 32 | } 33 | currentDir = currentDirInfo.FullName; 34 | if (!filesPatternProvider.DoesDirectoryMatch(currentDir)) 35 | { 36 | continue; 37 | } 38 | IList allFilesInCurrentDir; 39 | try 40 | { 41 | allFilesInCurrentDir = Directory.GetFiles(currentDir).ToList(); 42 | } 43 | catch (IOException) 44 | { 45 | return null; 46 | } 47 | foreach (string file in allFilesInCurrentDir) 48 | { 49 | if (filesPatternProvider.DoesFileMatch(file)) 50 | { 51 | rootDir = currentDir; 52 | } 53 | if (filesPatternProvider.IsModuleFile(file)) 54 | { 55 | // TODO: why root dir is disallowed? 56 | return (rootDir.ToLowerInvariant() == driveRoot ? null : rootDir); 57 | } 58 | } 59 | 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/BHID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | public class BHID 10 | { 11 | public static Guid SFObject 12 | { 13 | get { return m_SFObject; } 14 | } 15 | 16 | public static Guid SFUIObject 17 | { 18 | get { return m_SFUIObject; } 19 | } 20 | 21 | static Guid m_SFObject = new Guid("3981e224-f559-11d3-8e3a-00c04f6837d5"); 22 | static Guid m_SFUIObject = new Guid("3981e225-f559-11d3-8e3a-00c04f6837d5"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/CoClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | public class CoClass 9 | { 10 | [ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] 11 | public class FileOpenDialog 12 | { 13 | } 14 | 15 | [ComImport, Guid("4df0c730-df9d-4ae3-9153-aa6b82e9795a")] 16 | public class KnownFolderManager 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/ComCtl32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | public enum ILD 10 | { 11 | NORMAL = 0x00000000, 12 | TRANSPARENT = 0x00000001, 13 | MASK = 0x00000010, 14 | IMAGE = 0x00000020, 15 | ROP = 0x00000040, 16 | BLEND25 = 0x00000002, 17 | BLEND50 = 0x00000004, 18 | OVERLAYMASK = 0x00000F00, 19 | PRESERVEALPHA = 0x00001000, 20 | } 21 | 22 | public class ComCtl32 23 | { 24 | [DllImport("comctl32")] 25 | public static extern bool ImageList_Draw(IntPtr himl, 26 | int i, IntPtr hdcDst, int x, int y, uint fStyle); 27 | 28 | [DllImport("comctl32")] 29 | public static extern bool ImageList_GetIconSize(IntPtr himl, out int cx, out int cy); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/HResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | public enum HResult 10 | { 11 | DRAGDROP_S_CANCEL = 0x00040101, 12 | DRAGDROP_S_DROP = 0x00040100, 13 | DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102, 14 | DATA_S_SAMEFORMATETC = 0x00040130, 15 | S_OK = 0, 16 | S_FALSE = 1, 17 | E_NOINTERFACE = unchecked((int)0x80004002), 18 | E_NOTIMPL = unchecked((int)0x80004001), 19 | OLE_E_ADVISENOTSUPPORTED = unchecked((int)80040003), 20 | MK_E_NOOBJECT = unchecked((int)0x800401E5), 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/ICommDlgBrowser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | public enum CDBOSC 9 | { 10 | CDBOSC_SETFOCUS, 11 | CDBOSC_KILLFOCUS, 12 | CDBOSC_SELCHANGE, 13 | CDBOSC_RENAME, 14 | CDBOSC_STATECHANGE, 15 | } 16 | 17 | [ComImport] 18 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 19 | [Guid("000214F1-0000-0000-C000-000000000046")] 20 | public interface ICommDlgBrowser 21 | { 22 | [PreserveSig] 23 | HResult OnDefaultCommand(IShellView ppshv); 24 | [PreserveSig] 25 | HResult OnStateChange(IShellView ppshv, CDBOSC uChange); 26 | [PreserveSig] 27 | HResult IncludeObject(IShellView ppshv, IntPtr pidl); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IDropSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [ComImport] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [Guid("00000121-0000-0000-C000-000000000046")] 11 | public interface IDropSource 12 | { 13 | [PreserveSig] 14 | HResult QueryContinueDrag(bool fEscapePressed, int grfKeyState); 15 | [PreserveSig] 16 | HResult GiveFeedback(int dwEffect); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IDropTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Runtime.InteropServices; 4 | using System.Runtime.InteropServices.ComTypes; 5 | 6 | #pragma warning disable 1591 7 | 8 | namespace GongSolutions.Shell.Interop 9 | { 10 | [ComImport] 11 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 12 | [Guid("00000122-0000-0000-C000-000000000046")] 13 | public interface IDropTarget 14 | { 15 | void DragEnter(IDataObject pDataObj, int grfKeyState, 16 | Point pt, ref int pdwEffect); 17 | void DragOver(int grfKeyState, Point pt, ref int pdwEffect); 18 | void DragLeave(); 19 | void Drop(IDataObject pDataObj, int grfKeyState, 20 | Point pt, ref int pdwEffect); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IEnumIDList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [ComImport] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [Guid("000214F2-0000-0000-C000-000000000046")] 11 | public interface IEnumIDList 12 | { 13 | [PreserveSig] 14 | HResult Next(uint celt, 15 | out IntPtr rgelt, 16 | out uint pceltFetched); 17 | 18 | [PreserveSig] 19 | HResult Skip(uint celt); 20 | 21 | [PreserveSig] 22 | HResult Reset(); 23 | 24 | IEnumIDList Clone(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IKnownFolder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | [ComImport] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | [Guid("3AA7AF7E-9B36-420c-A8E3-F77D4674A488")] 12 | public interface IKnownFolder 13 | { 14 | Guid GetId(); 15 | 16 | int GetCategory(); 17 | 18 | IShellItem GetShellItem( 19 | [In] ushort dwFlags, 20 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid); 21 | 22 | string GetPath(ushort dwFlags); 23 | 24 | void SetPath(ushort dwFlags, string pszPath); 25 | 26 | IntPtr GetIDList(ushort dwFlags); 27 | 28 | Guid GetFolderType(); 29 | 30 | uint GetRedirectionCapabilities(); 31 | 32 | KNOWNFOLDER_DEFINITION GetFolderDefinition(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IKnownFolderManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | [ComImport] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | [Guid("8BE2D872-86AA-4d47-B776-32CCA40C7018")] 12 | public interface IKnownFolderManager 13 | { 14 | Guid FolderIdFromCsidl(int nCsidl); 15 | 16 | CSIDL FolderIdToCsidl( 17 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid); 18 | 19 | void GetFolderIds( 20 | [Out] out IntPtr ppKFId, 21 | [Out] out uint pCount); 22 | 23 | IKnownFolder GetFolder( 24 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid); 25 | 26 | [PreserveSig] 27 | HResult GetFolderByName( 28 | [In] string pszCanonicalName, 29 | [Out] out IKnownFolder ppkf); 30 | 31 | void RegisterFolder( 32 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid, 33 | [In] IntPtr pKFD); 34 | 35 | void UnregisterFolder( 36 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid); 37 | 38 | [PreserveSig] 39 | HResult FindFolderFromPath( 40 | [In] string pszPath, 41 | [In] FFFP_MODE mode, 42 | [Out] out IKnownFolder ppkf); 43 | 44 | [PreserveSig] 45 | HResult FindFolderFromIDList( 46 | [In] IntPtr pidl, 47 | [Out] out IKnownFolder ppkf); 48 | 49 | string Redirect( 50 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid, 51 | [In] IntPtr hwnd, 52 | [In] int flags, 53 | [In] string pszTargetPath, 54 | [In] uint cFolders, 55 | [In] Guid[] pExclusion); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IOleCommandTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 9 | public struct OLECMDTEXT 10 | { 11 | public uint cmdtextf; 12 | public uint cwActual; 13 | public uint cwBuf; 14 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] 15 | public char rgwz; 16 | } 17 | 18 | [StructLayout(LayoutKind.Sequential)] 19 | public struct OLECMD 20 | { 21 | public uint cmdID; 22 | public uint cmdf; 23 | } 24 | 25 | [ComImport] 26 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 27 | [Guid("b722bccb-4e68-101b-a2bc-00aa00404770")] 28 | public interface IOleCommandTarget 29 | { 30 | void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds, 31 | [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] 32 | OLECMD[] prgCmds, 33 | ref OLECMDTEXT CmdText); 34 | void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, 35 | ref object pvaIn, ref object pvaOut); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IQueryInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [ComImport] 9 | [Guid("00021500-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IQueryInfo 12 | { 13 | [PreserveSig] 14 | void GetInfoTip(int dwFlags, out IntPtr ppwszTip); 15 | 16 | [PreserveSig] 17 | void GetInfoFlags(IntPtr pdwFlags); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [ComImport] 9 | [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | interface IServiceProvider 12 | { 13 | [PreserveSig] 14 | HResult QueryService(ref Guid guidService, ref Guid riid, 15 | out IntPtr ppvObject); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IShellBrowser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | public enum FCW 9 | { 10 | FCW_STATUS = 0x0001, 11 | FCW_TOOLBAR = 0x0002, 12 | FCW_TREE = 0x0003, 13 | FCW_INTERNETBAR = 0x0006, 14 | FCW_PROGRESS = 0x0008, 15 | } 16 | 17 | [Flags] 18 | public enum SBSP : uint 19 | { 20 | SBSP_DEFBROWSER = 0x0000, 21 | SBSP_SAMEBROWSER = 0x0001, 22 | SBSP_NEWBROWSER = 0x0002, 23 | SBSP_DEFMODE = 0x0000, 24 | SBSP_OPENMODE = 0x0010, 25 | SBSP_EXPLOREMODE = 0x0020, 26 | SBSP_HELPMODE = 0x0040, 27 | SBSP_NOTRANSFERHIST = 0x0080, 28 | SBSP_ABSOLUTE = 0x0000, 29 | SBSP_RELATIVE = 0x1000, 30 | SBSP_PARENT = 0x2000, 31 | SBSP_NAVIGATEBACK = 0x4000, 32 | SBSP_NAVIGATEFORWARD = 0x8000, 33 | SBSP_ALLOW_AUTONAVIGATE = 0x10000, 34 | SBSP_CALLERUNTRUSTED = 0x00800000, 35 | SBSP_TRUSTFIRSTDOWNLOAD = 0x01000000, 36 | SBSP_UNTRUSTEDFORDOWNLOAD = 0x02000000, 37 | SBSP_NOAUTOSELECT = 0x04000000, 38 | SBSP_WRITENOHISTORY = 0x08000000, 39 | SBSP_TRUSTEDFORACTIVEX = 0x10000000, 40 | SBSP_REDIRECT = 0x40000000, 41 | SBSP_INITIATEDBYHLINKFRAME = 0x80000000, 42 | } 43 | 44 | [ComImport] 45 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 46 | [Guid("000214E2-0000-0000-C000-000000000046")] 47 | public interface IShellBrowser 48 | { 49 | [PreserveSig] 50 | HResult GetWindow(out IntPtr phwnd); 51 | [PreserveSig] 52 | HResult ContextSensitiveHelp(bool fEnterMode); 53 | [PreserveSig] 54 | HResult InsertMenusSB(IntPtr IntPtrShared, IntPtr lpMenuWidths); 55 | [PreserveSig] 56 | HResult SetMenuSB(IntPtr IntPtrShared, IntPtr holemenuRes, 57 | IntPtr IntPtrActiveObject); 58 | [PreserveSig] 59 | HResult RemoveMenusSB(IntPtr IntPtrShared); 60 | [PreserveSig] 61 | HResult SetStatusTextSB(IntPtr pszStatusText); 62 | [PreserveSig] 63 | HResult EnableModelessSB(bool fEnable); 64 | [PreserveSig] 65 | HResult TranslateAcceleratorSB(IntPtr pmsg, ushort wID); 66 | 67 | [PreserveSig] 68 | HResult BrowseObject(IntPtr pidl, SBSP wFlags); 69 | [PreserveSig] 70 | HResult GetViewStateStream(uint grfMode, IntPtr ppStrm); 71 | [PreserveSig] 72 | HResult GetControlWindow(FCW id, out IntPtr lpIntPtr); 73 | [PreserveSig] 74 | HResult SendControlMsg(FCW id, MSG uMsg, uint wParam, uint lParam, IntPtr pret); 75 | [PreserveSig] 76 | HResult QueryActiveShellView(out IShellView ppshv); 77 | [PreserveSig] 78 | HResult OnViewWindowActive(IShellView ppshv); 79 | [PreserveSig] 80 | HResult SetToolbarItems(IntPtr lpButtons, uint nButtons, uint uFlags); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IShellFolder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | [ComImport] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [Guid("000214E6-0000-0000-C000-000000000046")] 11 | public interface IShellFolder 12 | { 13 | void ParseDisplayName( 14 | [In] IntPtr hwnd, 15 | [In] IntPtr pbc, 16 | [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, 17 | [Out] out uint pchEaten, 18 | [Out] out IntPtr ppidl, 19 | [In, Out] ref uint pdwAttributes); 20 | 21 | [PreserveSig] 22 | HResult EnumObjects( 23 | [In] IntPtr hwnd, 24 | [In] SHCONTF grfFlags, 25 | [Out] out IEnumIDList ppenumIDList); 26 | 27 | void BindToObject(IntPtr pidl, IntPtr pbc, 28 | [MarshalAs(UnmanagedType.LPStruct)] Guid riid, 29 | out IntPtr ppv); 30 | 31 | void BindToStorage(IntPtr pidl, IntPtr pbc, 32 | [MarshalAs(UnmanagedType.LPStruct)] Guid riid, 33 | out IntPtr ppv); 34 | 35 | [PreserveSig] 36 | short CompareIDs(SHCIDS lParam, IntPtr pidl1, IntPtr pidl2); 37 | 38 | IntPtr CreateViewObject(IntPtr hwndOwner, 39 | [MarshalAs(UnmanagedType.LPStruct)] Guid riid); 40 | 41 | void GetAttributesOf(UInt32 cidl, 42 | [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] 43 | IntPtr[] apidl, 44 | ref SFGAO rgfInOut); 45 | 46 | void GetUIObjectOf(IntPtr hwndOwner, UInt32 cidl, 47 | [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] 48 | IntPtr[] apidl, 49 | [MarshalAs(UnmanagedType.LPStruct)] Guid riid, 50 | UInt32 rgfReserved, 51 | out IntPtr ppv); 52 | 53 | void GetDisplayNameOf(IntPtr pidl, SHGNO uFlags, out STRRET pName); 54 | 55 | void SetNameOf(IntPtr hwnd, IntPtr pidl, string pszName, 56 | SHCONTF uFlags, out IntPtr ppidlOut); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IShellItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | [ComImport] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")] 12 | public interface IShellItem 13 | { 14 | IntPtr BindToHandler(IntPtr pbc, 15 | [MarshalAs(UnmanagedType.LPStruct)]Guid bhid, 16 | [MarshalAs(UnmanagedType.LPStruct)]Guid riid); 17 | 18 | [PreserveSig] 19 | HResult GetParent(out IShellItem ppsi); 20 | 21 | IntPtr GetDisplayName(SIGDN sigdnName); 22 | 23 | SFGAO GetAttributes(SFGAO sfgaoMask); 24 | 25 | int Compare(IShellItem psi, SICHINT hint); 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IShellItemArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | [ComImport] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | [Guid("b63ea76d-1f85-456f-a19c-48159efa858b")] 12 | public interface IShellItemArray 13 | { 14 | void BindToHandler( 15 | [In] IntPtr pbc, 16 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid, 17 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 18 | [Out] out IntPtr ppv); 19 | 20 | void GetPropertyStore( 21 | [In] int flags, 22 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 23 | [Out] out IntPtr ppv); 24 | 25 | void GetPropertyDescriptionList( 26 | [In] int keyType, 27 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 28 | [Out] out IntPtr ppv); 29 | 30 | void GetAttributes( 31 | [In] int dwAttribFlags, 32 | [In] int sfgaoMask, 33 | [Out] out int psfgaoAttribs); 34 | 35 | void GetCount( 36 | [Out] out ushort pdwNumItems); 37 | 38 | void GetItemAt( 39 | [In] ushort dwIndex, 40 | [Out, MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); 41 | 42 | void EnumItems( 43 | [Out] out IntPtr ppenumShellItems); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/IShellView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Runtime.InteropServices; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | public enum SVGIO : uint 10 | { 11 | SVGIO_BACKGROUND = 0, 12 | SVGIO_SELECTION = 0x1, 13 | SVGIO_ALLVIEW = 0x2, 14 | SVGIO_CHECKED = 0x3, 15 | SVGIO_TYPE_MASK = 0xf, 16 | SVGIO_FLAG_VIEWORDER = 0x80000000, 17 | } 18 | 19 | [ComImport] 20 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 21 | [Guid("000214E3-0000-0000-C000-000000000046")] 22 | public interface IShellView 23 | { 24 | void GetWindow(out IntPtr windowHandle); 25 | void ContextSensitiveHelp(bool fEnterMode); 26 | [PreserveSig] 27 | long TranslateAcceleratorA(IntPtr message); 28 | void EnableModeless(bool enable); 29 | void UIActivate(UInt32 activtionState); 30 | void Refresh(); 31 | void CreateViewWindow( 32 | IShellView previousShellView, 33 | ref FOLDERSETTINGS folderSetting, 34 | IShellBrowser shellBrowser, 35 | ref Rectangle bounds, 36 | out IntPtr handleOfCreatedWindow); 37 | void DestroyViewWindow(); 38 | void GetCurrentInfo(ref FOLDERSETTINGS pfs); 39 | void AddPropertySheetPages([In, MarshalAs(UnmanagedType.U4)] uint reserved, [In]ref IntPtr functionPointer, [In] IntPtr lparam); 40 | void SaveViewState(); 41 | void SelectItem(IntPtr pidlItem, [MarshalAs(UnmanagedType.U4)] SVSI flags); 42 | 43 | [PreserveSig] 44 | int GetItemObject( 45 | [In] SVGIO AspectOfView, 46 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, 47 | [Out] out IntPtr ppv); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/Kernel32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | #pragma warning disable 1591 5 | 6 | namespace GongSolutions.Shell.Interop 7 | { 8 | public class Kernel32 9 | { 10 | [DllImport("kernel32.dll")] 11 | public static extern IntPtr GlobalLock(IntPtr hMem); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/Ole32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows.Forms; 4 | using ComTypes = System.Runtime.InteropServices.ComTypes; 5 | 6 | #pragma warning disable 1591 7 | 8 | namespace GongSolutions.Shell.Interop 9 | { 10 | public class Ole32 11 | { 12 | [DllImport("ole32.dll")] 13 | public static extern void CoTaskMemFree(IntPtr pv); 14 | 15 | [DllImport("ole32.dll")] 16 | public static extern int DoDragDrop(ComTypes.IDataObject pDataObject, 17 | IDropSource pDropSource, DragDropEffects dwOKEffect, 18 | out DragDropEffects pdwEffect); 19 | 20 | [DllImport("ole32.dll")] 21 | public static extern int RegisterDragDrop(IntPtr hwnd, IDropTarget pDropTarget); 22 | 23 | [DllImport("ole32.dll")] 24 | public static extern int RevokeDragDrop(IntPtr hwnd); 25 | 26 | public static Guid IID_IDataObject 27 | { 28 | get { return new Guid("0000010e-0000-0000-C000-000000000046"); } 29 | } 30 | 31 | public static Guid IID_IDropTarget 32 | { 33 | get { return new Guid("00000122-0000-0000-C000-000000000046"); } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Interop/ShlWapi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | #pragma warning disable 1591 6 | 7 | namespace GongSolutions.Shell.Interop 8 | { 9 | public class ShlWapi 10 | { 11 | [DllImport("shlwapi.dll")] 12 | public static extern Int32 StrRetToBuf(ref STRRET pstr, IntPtr pidl, 13 | StringBuilder pszBuf, 14 | UInt32 cchBuf); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/GongSolutions.Shell/Licence.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Steven Kirk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/EmptyListToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | 8 | namespace PsISEProjectExplorer.UI.Helpers 9 | { 10 | [ValueConversion(typeof(IEnumerable), typeof(Visibility))] 11 | public class EmptyListToVisibilityConverter : IValueConverter 12 | { 13 | enum Parameters 14 | { 15 | VisibleOnEmpty, HiddenOnEmpty 16 | } 17 | 18 | public object Convert(object value, Type targetType, 19 | object parameter, CultureInfo culture) 20 | { 21 | var collection = (IEnumerable)value; 22 | Parameters direction = Parameters.HiddenOnEmpty; 23 | if (parameter != null) 24 | { 25 | direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter); 26 | } 27 | if (direction == Parameters.VisibleOnEmpty) 28 | { 29 | return collection.Any() ? Visibility.Collapsed : Visibility.Visible; 30 | } 31 | return collection.Any() ? Visibility.Visible : Visibility.Collapsed; 32 | } 33 | 34 | public object ConvertBack(object value, Type targetType, 35 | object parameter, CultureInfo culture) 36 | { 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/FocusExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace PsISEProjectExplorer.UI.Helpers 5 | { 6 | // http://stackoverflow.com/questions/5152324/transfer-focus-on-a-controls-sub-part-in-its-template-in-wpf 7 | public static class FocusExtensions 8 | { 9 | public static bool GetIsDefaultFocusElement(DependencyObject obj) 10 | { 11 | return (bool)obj.GetValue(IsDefaultFocusElementProperty); 12 | } 13 | 14 | public static void SetIsDefaultFocusElement(DependencyObject obj, bool value) 15 | { 16 | obj.SetValue(IsDefaultFocusElementProperty, value); 17 | } 18 | 19 | public static readonly DependencyProperty IsDefaultFocusElementProperty = 20 | DependencyProperty.RegisterAttached("IsDefaultFocusElement", typeof(bool), typeof(FocusExtensions), new UIPropertyMetadata(false, OnIsDefaultFocusElementChanged)); 21 | 22 | private static void OnIsDefaultFocusElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 23 | { 24 | var fe = (FrameworkElement)d; 25 | 26 | if (!(bool)e.NewValue) 27 | { 28 | return; 29 | } 30 | 31 | if (fe.IsLoaded) 32 | { 33 | SetFocus(fe); 34 | } 35 | else 36 | { 37 | fe.Loaded += OnDefaultFocusElementLoaded; 38 | } 39 | } 40 | 41 | private static void OnDefaultFocusElementLoaded(object sender, RoutedEventArgs e) 42 | { 43 | var fe = (FrameworkElement)sender; 44 | 45 | fe.Loaded -= OnDefaultFocusElementLoaded; 46 | 47 | SetFocus(fe); 48 | } 49 | 50 | private static void SetFocus(FrameworkElement element) 51 | { 52 | element.Focus(); 53 | var textboxElement = element as TextBox; 54 | if (textboxElement != null) 55 | { 56 | int selectionEnd = textboxElement.Text.LastIndexOf('.'); 57 | if (selectionEnd == -1) { 58 | selectionEnd = textboxElement.Text.Length; 59 | } 60 | textboxElement.Select(0, selectionEnd); 61 | } 62 | 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/IndexingModeConverter.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace PsISEProjectExplorer.UI.Helpers 7 | { 8 | [ValueConversion(typeof(IndexingMode), typeof(string))] 9 | public class IndexingModeConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | IndexingMode indexingMode = (IndexingMode)value; 14 | switch (indexingMode) 15 | { 16 | case IndexingMode.ALL_FILES: return true; 17 | case IndexingMode.NO_FILES: return false; 18 | default: return null; 19 | } 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | bool? nullableValue = value as bool?; 25 | if (!nullableValue.HasValue) 26 | { 27 | return IndexingMode.LOCAL_FILES; 28 | } 29 | return nullableValue.Value ? IndexingMode.ALL_FILES : IndexingMode.NO_FILES; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/LockedToolBar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | 9 | namespace PsISEProjectExplorer.UI.Helpers 10 | { 11 | public class LockedToolBar : ToolBar 12 | { 13 | public LockedToolBar() 14 | { 15 | Loaded += new RoutedEventHandler(LockedToolBar_Loaded); 16 | } 17 | 18 | private void LockedToolBar_Loaded(object sender, RoutedEventArgs e) 19 | { 20 | ToolBar toolBar = sender as ToolBar; 21 | var overflowGrid = toolBar.Template.FindName("OverflowGrid", toolBar) as FrameworkElement; 22 | if (overflowGrid != null) 23 | { 24 | overflowGrid.Visibility = Visibility.Collapsed; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/MessageBoxHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace PsISEProjectExplorer.UI.Helpers 4 | { 5 | [Component] 6 | public class MessageBoxHelper 7 | { 8 | public void ShowError(string message) 9 | { 10 | Application.Current.Dispatcher.Invoke(() => 11 | { 12 | MessageBox.Show(Application.Current.MainWindow, message, "PsISEProjectExplorer - error", MessageBoxButton.OK, MessageBoxImage.Error); 13 | }); 14 | } 15 | 16 | public void ShowInfo(string message) 17 | { 18 | Application.Current.Dispatcher.Invoke(() => 19 | { 20 | MessageBox.Show(Application.Current.MainWindow, message, "PsISEProjectExplorer - information", MessageBoxButton.OK, MessageBoxImage.Information); 21 | }); 22 | } 23 | 24 | public bool ShowConfirmMessage(string message) 25 | { 26 | return Application.Current.Dispatcher.Invoke(() => 27 | { 28 | var result = MessageBox.Show(Application.Current.MainWindow, message, "Please confirm your action", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); 29 | return result == MessageBoxResult.OK; 30 | }); 31 | } 32 | 33 | public bool ShowQuestion(string header, string message) 34 | { 35 | return Application.Current.Dispatcher.Invoke(() => 36 | { 37 | var result = MessageBox.Show(Application.Current.MainWindow, message, "PsISEProjectExplorer - " + header, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes); 38 | return result == MessageBoxResult.Yes; 39 | }); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/StretchingTreeView.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace PsISEProjectExplorer.UI.Helpers 5 | { 6 | // http://blogs.msdn.com/b/jpricket/archive/2008/08/05/wpf-a-stretching-treeview.aspx 7 | public class StretchingTreeView : TreeView 8 | { 9 | protected override DependencyObject GetContainerForItemOverride() 10 | { 11 | return new StretchingTreeViewItem(); 12 | } 13 | 14 | protected override bool IsItemItsOwnContainerOverride(object item) 15 | { 16 | return item is StretchingTreeViewItem; 17 | } 18 | } 19 | 20 | class StretchingTreeViewItem : TreeViewItem 21 | { 22 | public StretchingTreeViewItem() 23 | { 24 | this.Loaded += new RoutedEventHandler(StretchingTreeViewItem_Loaded); 25 | } 26 | 27 | private void StretchingTreeViewItem_Loaded(object sender, RoutedEventArgs e) 28 | { 29 | // The purpose of this code is to stretch the Header Content all the way accross the TreeView. 30 | if (this.VisualChildrenCount > 0) 31 | { 32 | Grid grid = this.GetVisualChild(0) as Grid; 33 | if (grid != null && grid.ColumnDefinitions.Count == 3) 34 | { 35 | // Remove the middle column which is set to Auto and let it get replaced with the 36 | // last column that is set to Star. 37 | grid.ColumnDefinitions.RemoveAt(1); 38 | } 39 | } 40 | } 41 | 42 | protected override DependencyObject GetContainerForItemOverride() 43 | { 44 | return new StretchingTreeViewItem(); 45 | } 46 | 47 | protected override bool IsItemItsOwnContainerOverride(object item) 48 | { 49 | return item is StretchingTreeViewItem; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Helpers/TreeViewSpecialCharactersHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | 4 | namespace PsISEProjectExplorer.UI.Helpers 5 | { 6 | public static class TreeViewSpecialCharactersHandler 7 | { 8 | public static void RouteSpecialCharacters(this TreeView treeView, object sender, KeyEventArgs e) 9 | { 10 | string keyText = null; 11 | switch (e.Key) 12 | { 13 | case Key.Subtract: keyText = "-"; break; 14 | case Key.Add: keyText = "+"; break; 15 | case Key.Multiply: keyText = "*"; break; 16 | } 17 | if (keyText == null) 18 | { 19 | return; 20 | } 21 | 22 | var target = Keyboard.FocusedElement; 23 | if (target == null) 24 | { 25 | return; 26 | } 27 | e.Handled = true; 28 | var routedEvent = TextCompositionManager.TextInputEvent; 29 | target.RaiseEvent( 30 | new TextCompositionEventArgs 31 | ( 32 | InputManager.Current.PrimaryKeyboardDevice, 33 | new TextComposition(InputManager.Current, target, keyText) 34 | ) 35 | { 36 | RoutedEvent = routedEvent 37 | }); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/IseIntegration/IseEventArgs.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PsISEProjectExplorer.UI.IseIntegration 3 | { 4 | public class IseEventArgs 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/IseIntegration/IseFileWatcher.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.PowerShell.Host.ISE; 2 | using NLog; 3 | using PsISEProjectExplorer.Model; 4 | using PsISEProjectExplorer.Services; 5 | using System; 6 | using System.IO; 7 | 8 | namespace PsISEProjectExplorer.UI.IseIntegration 9 | { 10 | public class IseFileWatcher 11 | { 12 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 13 | 14 | private readonly FileSystemChangeNotifier fileSystemChangeNotifier; 15 | 16 | private readonly FileSystemWatcher watcher; 17 | 18 | private ISEFile iseFile; 19 | 20 | public IseFileWatcher(FileSystemChangeNotifier fileSystemChangeNotifier, string path, ISEFile iseFile) 21 | { 22 | this.iseFile = iseFile; 23 | this.fileSystemChangeNotifier = fileSystemChangeNotifier; 24 | this.watcher = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path)); 25 | this.watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.Security; 26 | this.watcher.Changed += OnFileChanged; 27 | this.watcher.Deleted += OnFileChanged; 28 | this.watcher.Renamed += OnFileRenamed; 29 | this.watcher.EnableRaisingEvents = true; 30 | } 31 | 32 | public void StopWatching() 33 | { 34 | this.watcher.EnableRaisingEvents = false; 35 | this.iseFile = null; 36 | } 37 | 38 | private void OnFileChanged(object source, FileSystemEventArgs e) 39 | { 40 | Logger.Debug("File changed: " + e.FullPath); 41 | this.fileSystemChangeNotifier.AddChangePoolEntry(new ChangePoolEntry(e.FullPath, String.Empty)); 42 | } 43 | 44 | private void OnFileRenamed(object source, RenamedEventArgs e) 45 | { 46 | Logger.Debug("File renamed: " + e.OldFullPath + " to " + e.FullPath); 47 | this.fileSystemChangeNotifier.AddChangePoolEntry(new ChangePoolEntry(e.OldFullPath, String.Empty, e.FullPath)); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/Interop/COMGuids.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Ookii.Dialogs.Wpf.Interop 3 | { 4 | internal static class IIDGuid 5 | { 6 | internal const string IModalWindow = "b4db1657-70d7-485e-8e3e-6fcb5a5c1802"; 7 | internal const string IFileDialog = "42f85136-db7e-439c-85f1-e4075d135fc8"; 8 | internal const string IFileOpenDialog = "d57c7288-d4ad-4768-be02-9d969532d960"; 9 | internal const string IFileSaveDialog = "84bccd23-5fde-4cdb-aea4-af64b83d78ab"; 10 | internal const string IFileDialogEvents = "973510DB-7D7F-452B-8975-74A85828D354"; 11 | internal const string IFileDialogControlEvents = "36116642-D713-4b97-9B83-7484A9D00433"; 12 | internal const string IFileDialogCustomize = "e6fdd21a-163f-4975-9c8c-a69f1ba37034"; 13 | internal const string IShellItem = "43826D1E-E718-42EE-BC55-A1E261C37BFE"; 14 | internal const string IShellItemArray = "B63EA76D-1F85-456F-A19C-48159EFA858B"; 15 | internal const string IKnownFolder = "38521333-6A87-46A7-AE10-0F16706816C3"; 16 | internal const string IKnownFolderManager = "44BEAAEC-24F4-4E90-B3F0-23D258FBB146"; 17 | internal const string IPropertyStore = "886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"; 18 | internal const string IProgressDialog = "EBBC7C04-315E-11d2-B62F-006097DF5BD4"; 19 | } 20 | 21 | internal static class CLSIDGuid 22 | { 23 | internal const string FileOpenDialog = "DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7"; 24 | internal const string FileSaveDialog = "C0B4E2F3-BA21-4773-8DBA-335EC946EB8B"; 25 | internal const string KnownFolderManager = "4df0c730-df9d-4ae3-9153-aa6b82e9795a"; 26 | internal const string ProgressDialog = "F8383852-FCD3-11d1-A6B9-006097DF5BD4"; 27 | } 28 | 29 | internal static class KFIDGuid 30 | { 31 | internal const string ComputerFolder = "0AC0837C-BBF8-452A-850D-79D08E667CA7"; 32 | internal const string Favorites = "1777F761-68AD-4D8A-87BD-30B759FA33DD"; 33 | internal const string Documents = "FDD39AD0-238F-46AF-ADB4-6C85480369C7"; 34 | internal const string Profile = "5E6C858F-0E22-4760-9AFE-EA3317B67173"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/Interop/ErrorHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Ookii.Dialogs.Wpf.Interop 2 | { 3 | internal enum HRESULT : long 4 | { 5 | S_FALSE = 0x0001, 6 | S_OK = 0x0000, 7 | E_INVALIDARG = 0x80070057, 8 | E_OUTOFMEMORY = 0x8007000E, 9 | ERROR_CANCELLED = 0x800704C7 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/Interop/ShellWrapperDefinitions.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Ookii.Dialogs.Wpf.Interop 4 | { 5 | // Dummy base interface for CommonFileDialog coclasses 6 | internal interface NativeCommonFileDialog 7 | { } 8 | 9 | // --------------------------------------------------------- 10 | // Coclass interfaces - designed to "look like" the object 11 | // in the API, so that the 'new' operator can be used in a 12 | // straightforward way. Behind the scenes, the C# compiler 13 | // morphs all 'new CoClass()' calls to 'new CoClassWrapper()' 14 | [ComImport, 15 | Guid(IIDGuid.IFileOpenDialog), 16 | CoClass(typeof(FileOpenDialogRCW))] 17 | internal interface NativeFileOpenDialog : IFileOpenDialog 18 | { 19 | } 20 | 21 | [ComImport, 22 | Guid(IIDGuid.IFileSaveDialog), 23 | CoClass(typeof(FileSaveDialogRCW))] 24 | internal interface NativeFileSaveDialog : IFileSaveDialog 25 | { 26 | } 27 | 28 | [ComImport, 29 | Guid(IIDGuid.IKnownFolderManager), 30 | CoClass(typeof(KnownFolderManagerRCW))] 31 | internal interface KnownFolderManager : IKnownFolderManager 32 | { 33 | } 34 | 35 | // --------------------------------------------------- 36 | // .NET classes representing runtime callable wrappers 37 | [ComImport, 38 | ClassInterface(ClassInterfaceType.None), 39 | TypeLibType(TypeLibTypeFlags.FCanCreate), 40 | Guid(CLSIDGuid.FileOpenDialog)] 41 | internal class FileOpenDialogRCW 42 | { 43 | } 44 | 45 | [ComImport, 46 | ClassInterface(ClassInterfaceType.None), 47 | TypeLibType(TypeLibTypeFlags.FCanCreate), 48 | Guid(CLSIDGuid.FileSaveDialog)] 49 | internal class FileSaveDialogRCW 50 | { 51 | } 52 | 53 | [ComImport, 54 | ClassInterface(ClassInterfaceType.None), 55 | TypeLibType(TypeLibTypeFlags.FCanCreate), 56 | Guid(CLSIDGuid.KnownFolderManager)] 57 | internal class KnownFolderManagerRCW 58 | { 59 | } 60 | 61 | 62 | // TODO: make these available (we'll need them when passing in 63 | // shell items to the CFD API 64 | //[ComImport, 65 | //Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"), 66 | //CoClass(typeof(ShellItemClass))] 67 | //internal interface ShellItem : IShellItem 68 | //{ 69 | //} 70 | 71 | //// NOTE: This GUID is for CLSID_ShellItem, which 72 | //// actually implements IShellItem2, which has lots of 73 | //// stuff we don't need 74 | //[ComImport, 75 | //ClassInterface(ClassInterfaceType.None), 76 | //TypeLibType(TypeLibTypeFlags.FCanCreate)] 77 | //internal class ShellItemClass 78 | //{ 79 | //} 80 | } 81 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/SafeHandles.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/SafeHandles.cs -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/VistaFolderBrowserDialog.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/VistaFolderBrowserDialog.cs -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer/UI/Ookii.Dialogs.Wpf/license.txt -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/ViewModel/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace PsISEProjectExplorer.UI.ViewModel 5 | { 6 | public abstract class BaseViewModel : INotifyPropertyChanged 7 | { 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | protected void OnPropertyChanged([CallerMemberName]string propName = null) 11 | { 12 | if (PropertyChanged != null) 13 | PropertyChanged(this, new PropertyChangedEventArgs(propName)); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/ViewModel/DefaultTreeViewEntryItemComparer.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 2 | using System.Collections.Generic; 3 | 4 | namespace PsISEProjectExplorer.UI.ViewModel 5 | { 6 | public class DefaultTreeViewEntryItemComparer : IComparer 7 | { 8 | public static readonly IComparer TreeViewEntryItemComparer = new DefaultTreeViewEntryItemComparer(); 9 | 10 | public int Compare(TreeViewEntryItemModel x, TreeViewEntryItemModel y) 11 | { 12 | if (x == null && y == null) 13 | { 14 | return 0; 15 | } 16 | if (x == null) 17 | { 18 | return -1; 19 | } 20 | if (y == null) 21 | { 22 | return 1; 23 | } 24 | return NodeComparerProvider.NodeComparer.Compare(x.Node, y.Node); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/ViewModel/TreeViewEntryItemModelState.cs: -------------------------------------------------------------------------------- 1 | namespace PsISEProjectExplorer.UI.ViewModel 2 | { 3 | public class TreeViewEntryItemModelState 4 | { 5 | public bool IsExpanded { get; set; } 6 | 7 | public bool IsSelected { get; set; } 8 | 9 | public TreeViewEntryItemModelState(bool isExpanded, bool isSelected) 10 | { 11 | this.IsExpanded = isExpanded; 12 | this.IsSelected = isSelected; 13 | } 14 | 15 | public override bool Equals(object obj) 16 | { 17 | if (obj == null || this.GetType() != obj.GetType()) 18 | { 19 | return false; 20 | } 21 | var item = (TreeViewEntryItemModelState)obj; 22 | return (this.IsExpanded == item.IsExpanded && this.IsSelected == item.IsSelected); 23 | } 24 | 25 | public override int GetHashCode() 26 | { 27 | return this.IsExpanded.GetHashCode() + this.IsSelected.GetHashCode(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/ViewModel/TreeViewEntryItemObservableSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | 5 | namespace PsISEProjectExplorer.UI.ViewModel 6 | { 7 | public class TreeViewEntryItemObservableSet : INotifyCollectionChanged, IEnumerable 8 | { 9 | public event NotifyCollectionChangedEventHandler CollectionChanged; 10 | 11 | private readonly List items; 12 | 13 | public TreeViewEntryItemObservableSet() 14 | { 15 | this.items = new List(); 16 | } 17 | 18 | public bool Add(TreeViewEntryItemModel item) 19 | { 20 | int indexOfAddedItem = this.AddItem(item); 21 | if (indexOfAddedItem < 0) 22 | { 23 | return false; 24 | } 25 | this.RaiseOnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, indexOfAddedItem)); 26 | return true; 27 | } 28 | 29 | public void Clear() 30 | { 31 | this.items.Clear(); 32 | this.RaiseOnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 33 | } 34 | 35 | public bool Remove(TreeViewEntryItemModel item) 36 | { 37 | int index = this.items.BinarySearch(item, DefaultTreeViewEntryItemComparer.TreeViewEntryItemComparer); 38 | if (index < 0) 39 | { 40 | // not in list; 41 | return false; 42 | } 43 | this.items.RemoveAt(index); 44 | this.RaiseOnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); 45 | return true; 46 | } 47 | 48 | public IEnumerator GetEnumerator() 49 | { 50 | return this.items.GetEnumerator(); 51 | } 52 | 53 | IEnumerator IEnumerable.GetEnumerator() 54 | { 55 | return this.items.GetEnumerator(); 56 | } 57 | 58 | private void RaiseOnCollectionChanged(NotifyCollectionChangedEventArgs e) 59 | { 60 | if (this.CollectionChanged != null) 61 | this.CollectionChanged(this, e); 62 | } 63 | 64 | private int AddItem(TreeViewEntryItemModel item) 65 | { 66 | int result = this.items.BinarySearch(item, DefaultTreeViewEntryItemComparer.TreeViewEntryItemComparer); 67 | if (result >= 0) 68 | { 69 | // already on list 70 | return -1; 71 | } 72 | int index = ~result; 73 | this.items.Insert(index, item); 74 | return index; 75 | } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/BackgroundIndexer.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Threading; 6 | 7 | namespace PsISEProjectExplorer.UI.Workers 8 | { 9 | public class BackgroundIndexer : BackgroundWorker 10 | { 11 | private static object BackgroundIndexerLock = new Object(); 12 | 13 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 14 | 15 | public DateTime StartTimestamp { get; private set; } 16 | 17 | public BackgroundIndexer() 18 | { 19 | this.StartTimestamp = DateTime.Now; 20 | this.DoWork += RunIndexing; 21 | this.WorkerReportsProgress = true; 22 | this.WorkerSupportsCancellation = true; 23 | } 24 | 25 | // running in Indexing thread 26 | private void RunIndexing(object sender, DoWorkEventArgs e) 27 | { 28 | if (Thread.CurrentThread.Name == null) 29 | { 30 | Thread.CurrentThread.Name = "PsISEPE-Indexer"; 31 | } 32 | var indexerParams = (BackgroundIndexerParams)e.Argument; 33 | Logger.Info("Indexing started, rootDir: " + indexerParams.RootDirectory + ", pathsChanged: " + (indexerParams.PathsChanged == null ? "null" : String.Join(", ", indexerParams.PathsChanged))); 34 | lock (BackgroundIndexerLock) 35 | { 36 | if (this.CancellationPending) 37 | { 38 | e.Cancel = true; 39 | return; 40 | } 41 | try 42 | { 43 | IEnumerable paths; 44 | if (indexerParams.PathsChanged == null) 45 | { 46 | paths = new List { indexerParams.RootDirectory }; 47 | } 48 | else 49 | { 50 | paths = indexerParams.PathsChanged; 51 | } 52 | var isChanged = indexerParams.DocumentHierarchyFactory.UpdateDocumentHierarchy(paths, indexerParams.FilesPatternProvider, this); 53 | e.Result = new IndexerResult(this.StartTimestamp, isChanged); 54 | } 55 | catch (OperationCanceledException) 56 | { 57 | e.Cancel = true; 58 | } 59 | } 60 | } 61 | 62 | // running in Indexing thread 63 | public void ReportProgressInCurrentThread(string path) 64 | { 65 | this.OnProgressChanged(new ProgressChangedEventArgs(0, path)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/BackgroundIndexerParams.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Services; 2 | using System.Collections.Generic; 3 | 4 | namespace PsISEProjectExplorer.UI.Workers 5 | { 6 | public class BackgroundIndexerParams 7 | { 8 | public DocumentHierarchyFactory DocumentHierarchyFactory { get; private set; } 9 | public string RootDirectory { get; private set; } 10 | public IEnumerable PathsChanged { get; private set; } 11 | public FilesPatternProvider FilesPatternProvider { get; private set; } 12 | 13 | public BackgroundIndexerParams(DocumentHierarchyFactory documentHierarchyFactory, string rootDirectory, IEnumerable pathsChanged, FilesPatternProvider filesPatternProvider) 14 | { 15 | this.DocumentHierarchyFactory = documentHierarchyFactory; 16 | this.RootDirectory = rootDirectory; 17 | this.PathsChanged = pathsChanged; 18 | this.FilesPatternProvider = filesPatternProvider; 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/BackgroundSearcher.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 3 | using PsISEProjectExplorer.Services; 4 | using System; 5 | using System.ComponentModel; 6 | using System.Threading; 7 | 8 | namespace PsISEProjectExplorer.UI.Workers 9 | { 10 | public class BackgroundSearcher : BackgroundWorker 11 | { 12 | private static object BackgroundSearcherLock = new Object(); 13 | 14 | private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 15 | 16 | public DateTime StartTimestamp { get; private set; } 17 | 18 | private DocumentHierarchySearcher DocumentHierarchySearcher { get; set; } 19 | 20 | public BackgroundSearcher(DocumentHierarchySearcher documentHierarchySearcher) 21 | { 22 | this.DocumentHierarchySearcher = documentHierarchySearcher; 23 | this.StartTimestamp = DateTime.Now; 24 | this.DoWork += RunSearching; 25 | this.WorkerSupportsCancellation = true; 26 | } 27 | 28 | public void RunWorkerSync(BackgroundSearcherParams argument) 29 | { 30 | var args = new DoWorkEventArgs(argument); 31 | this.RunSearching(this, args); 32 | this.OnRunWorkerCompleted(new RunWorkerCompletedEventArgs(args.Result, null, args.Cancel)); 33 | } 34 | 35 | private void RunSearching(object sender, DoWorkEventArgs e) 36 | { 37 | if (Thread.CurrentThread.Name == null) 38 | { 39 | Thread.CurrentThread.Name = "PsISEPE-Searcher"; 40 | } 41 | var searcherParams = (BackgroundSearcherParams)e.Argument; 42 | if (searcherParams.DocumentHierarchy == null) 43 | { 44 | e.Result = null; 45 | return; 46 | } 47 | if (searcherParams.Path == null) 48 | { 49 | // lock is only for full (non-incremental) searches 50 | lock (BackgroundSearcherLock) 51 | { 52 | RunActualSearch(searcherParams, e); 53 | } 54 | } 55 | else 56 | { 57 | RunActualSearch(searcherParams, e); 58 | } 59 | } 60 | 61 | private void RunActualSearch(BackgroundSearcherParams searcherParams, DoWorkEventArgs e) 62 | { 63 | if (this.CancellationPending) 64 | { 65 | e.Cancel = true; 66 | return; 67 | } 68 | Logger.Info(string.Format("Searching started, path: {0}, text: {1} ", searcherParams.Path ?? "null", searcherParams.SearchOptions.SearchText)); 69 | try 70 | { 71 | INode result = this.DocumentHierarchySearcher.GetDocumentHierarchyViewNodeProjection(searcherParams.DocumentHierarchy, searcherParams.Path, searcherParams.SearchOptions, this); 72 | e.Result = new SearcherResult(this.StartTimestamp, result, searcherParams.Path, searcherParams.SearchOptions); 73 | } 74 | catch (OperationCanceledException) 75 | { 76 | e.Cancel = true; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/BackgroundSearcherParams.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using PsISEProjectExplorer.Model.DocHierarchy; 3 | using PsISEProjectExplorer.Services; 4 | 5 | namespace PsISEProjectExplorer.UI.Workers 6 | { 7 | public class BackgroundSearcherParams 8 | { 9 | public DocumentHierarchy DocumentHierarchy { get; private set; } 10 | public SearchOptions SearchOptions { get; private set; } 11 | public string Path { get; private set; } 12 | 13 | public BackgroundSearcherParams(DocumentHierarchy documentHierarchy, SearchOptions searchOptions, string path) 14 | { 15 | this.DocumentHierarchy = documentHierarchy; 16 | this.SearchOptions = new SearchOptions(searchOptions); 17 | this.Path = path; 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/IndexerResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PsISEProjectExplorer.UI.Workers 4 | { 5 | public class IndexerResult 6 | { 7 | public DateTime StartTimestamp { get; private set; } 8 | 9 | public bool IsChanged { get; private set; } 10 | 11 | public IndexerResult(DateTime startTimestamp, bool isChanged) 12 | { 13 | this.StartTimestamp = startTimestamp; 14 | this.IsChanged = isChanged; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/UI/Workers/SearcherResult.cs: -------------------------------------------------------------------------------- 1 | using PsISEProjectExplorer.Model; 2 | using PsISEProjectExplorer.Model.DocHierarchy.Nodes; 3 | using System; 4 | 5 | namespace PsISEProjectExplorer.UI.Workers 6 | { 7 | public class SearcherResult 8 | { 9 | public DateTime StartTimestamp { get; private set; } 10 | 11 | public INode ResultNode { get; private set; } 12 | 13 | public string Path { get; private set; } 14 | 15 | public SearchOptions SearchOptions { get; private set; } 16 | 17 | public SearcherResult(DateTime startTimeStamp, INode resultNode, string path, SearchOptions searchOptions) 18 | { 19 | this.StartTimestamp = startTimeStamp; 20 | this.ResultNode = resultNode; 21 | this.Path = path; 22 | this.SearchOptions = searchOptions; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PsISEProjectExplorer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PsISEProjectExplorerPS5/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PsISEProjectExplorerPS5")] 9 | [assembly: AssemblyDescription("Powershell5 extensions for Powershell ISE Project Explorer")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PsISEProjectExplorerPS5")] 13 | [assembly: AssemblyCopyright("Copyright © 2016 Marcin Grzywa")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0c425642-ded0-41e2-a393-9cfd6b2af181")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PsISEProjectExplorerPS5/PsISEProjectExplorerPS5.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0C425642-DED0-41E2-A393-9CFD6B2AF181} 8 | Library 9 | Properties 10 | PsISEProjectExplorerPS5 11 | PsISEProjectExplorerPS5 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /PsISEProjectExplorer_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer_screen.png -------------------------------------------------------------------------------- /PsISEProjectExplorer_screen_dsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgr32/PsISEProjectExplorer/de5dda7916713eeadd191411415ff70ac83c80a4/PsISEProjectExplorer_screen_dsl.png -------------------------------------------------------------------------------- /PsIseProjectExplorer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PsISEProjectExplorer", "PsISEProjectExplorer\PsISEProjectExplorer.csproj", "{FCE0F6FA-5377-4D9A-8FB7-561F97AD2ABA}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PsISEProjectExplorerPS5", "PsISEProjectExplorerPS5\PsISEProjectExplorerPS5.csproj", "{0C425642-DED0-41E2-A393-9CFD6B2AF181}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PsISEProjectExplorer.Tests", "PsISEProjectExplorer.Tests\PsISEProjectExplorer.Tests.csproj", "{80493B05-F311-47AD-B361-A2CCBA29082A}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {FCE0F6FA-5377-4D9A-8FB7-561F97AD2ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {FCE0F6FA-5377-4D9A-8FB7-561F97AD2ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {FCE0F6FA-5377-4D9A-8FB7-561F97AD2ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {FCE0F6FA-5377-4D9A-8FB7-561F97AD2ABA}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {0C425642-DED0-41E2-A393-9CFD6B2AF181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {0C425642-DED0-41E2-A393-9CFD6B2AF181}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {0C425642-DED0-41E2-A393-9CFD6B2AF181}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {0C425642-DED0-41E2-A393-9CFD6B2AF181}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {80493B05-F311-47AD-B361-A2CCBA29082A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {80493B05-F311-47AD-B361-A2CCBA29082A}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {80493B05-F311-47AD-B361-A2CCBA29082A}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {80493B05-F311-47AD-B361-A2CCBA29082A}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /PsIseProjectExplorer.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | DO_NOT_SHOW 3 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> 4 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Powershell ISE Addon - Project Explorer 1.5.0 2 | 3 | [PsGallery](https://www.powershellgallery.com/packages/PsISEProjectExplorer) or [direct download](https://github.com/mgr32/PsISEProjectExplorer/releases/latest) 4 | 5 | [What's new](https://github.com/mgr32/PsISEProjectExplorer/wiki) 6 | 7 | [![Build status](https://ci.appveyor.com/api/projects/status/u2erfvsojuedn1sl/branch/master?svg=true)](https://ci.appveyor.com/project/mgr32/psiseprojectexplorer/branch/master) 8 | 9 | #### Project status 10 | 11 | Project is in maintenance mode - it was created to support work on large Powershell projects, but now it has been mostly superseded by Visual Studio Code. Therefore, please don't expect any new major features, but still if there's a bug you need fixed or an improvement you need implemented please let me know by adding a new issue. 12 | 13 | #### Description 14 | 15 | Provides a tree view that enables to index and explore whole directory structure containing Powershell scripts. It has following features: 16 | 17 | * Visualize directory structure (also files not loaded to ISE yet) in a tree view. 18 | * Show functions, classes and DSL nodes (e.g. Pester / psake / custom) in leaves of the tree view and jump to the function definition (F12). 19 | * Search the tree view (file names, function names, optionally file contents) - using full-text search or regex. 20 | * Show parse errors in tree view. 21 | * File operations in tree view (context menu - add / rename / delete, exclude, drag&drop). 22 | * Find all occurrences of the text under the cursor (SHIFT+F12). 23 | * Locate current file in the tree view (ALT+SHIFT+L). 24 | * Close All But This tab (CTRL+ALT+W). 25 | * Automatic reindex on file system change. 26 | * Ask user to reload files on file system change (editor functionality missing in ISE). 27 | 28 | Requires Powershell 3.0 or above. 29 | 30 | #### Screenshots 31 | ![ScreenShot](./PsISEProjectExplorer_screen.png?raw=true) 32 | ![ScreenShot](./PsISEProjectExplorer_screen_dsl.png?raw=true) 33 | 34 | #### Installation 35 | 36 | If you have Powershell 5 or PowerShellGet, run following commands in Powershell ISE: 37 | ``` 38 | Install-Module PsISEProjectExplorer 39 | Import-Module PsISEProjectExplorer 40 | Add-PsISEProjectExplorerToIseProfile 41 | ``` 42 | 43 | If you don't have PsGet, [download latest package](https://github.com/mgr32/PsISEProjectExplorer/releases/latest) and either: 44 | * Install it automatically - by running `Install_to_UserModules.bat`, or 45 | * Install it manually: 46 | * Ensure all the files are unblocked (properties of the file / General) 47 | * Copy PSISEProjectExplorer to `$env:USERPROFILE\Documents\WindowsPowerShell\Modules`. 48 | * Launch PowerShell ISE. 49 | * Run `Import-Module PsISEProjectExplorer`. 50 | * If you want it to be loaded automatically when ISE starts, add the line above to your ISE profile (see `$profile`). 51 | 52 | #### Usage 53 | 54 | When you open a Powershell file in ISE, Project Explorer will automatically set its project root directory to the last parent directory of the opened file where any .ps*1 file resides. 55 | 56 | You can also select the root directory manually (by clicking 'Change' button), which will prevent automatic root directory changes (you can enable it again by enabling 'Auto-update root dir'). 57 | 58 | #### Documentation 59 | 60 | Please see [wiki](https://github.com/mgr32/PsISEProjectExplorer/wiki). 61 | --------------------------------------------------------------------------------