├── EditAdvancedMenu.png ├── HotCommands ├── Packaging │ ├── ReleaseNotes.txt │ └── License.rtf ├── Resources │ ├── HotCommandsIcon.png │ ├── HotCommandsPreview.png │ └── HotCommandsIcon_v2_128x.png ├── Commands │ ├── JoinLines.cs │ ├── MoveMemberDown.cs │ ├── FormatCode.cs │ ├── Command.cs │ ├── MoveMemberUp.cs │ ├── ToggleComment.cs │ ├── GoToLastEditLocation.cs │ ├── DuplicateSelection.cs │ ├── ExpandSelection.cs │ ├── MoveCursorToAdjacentMember.cs │ └── EditorExtensions.cs ├── Constants.cs ├── Properties │ └── AssemblyInfo.cs ├── Listeners │ ├── HotCommandsTextViewCreationListener.cs │ └── LastEditTextViewCreationListener.cs ├── source.extension.vsixmanifest ├── Hot Commands Shortcuts.vssettings ├── app.config ├── HotCommandsPackage.cs ├── Util │ └── KeyBindingUtil.cs ├── VSPackage.resx ├── HotCommandsCommandFilter.cs ├── HotCommands.csproj └── HotCommandsPackage.vsct ├── renovate.json ├── HotCommands.sln ├── README.md └── .gitignore /EditAdvancedMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcla/HotCommands/HEAD/EditAdvancedMenu.png -------------------------------------------------------------------------------- /HotCommands/Packaging/ReleaseNotes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcla/HotCommands/HEAD/HotCommands/Packaging/ReleaseNotes.txt -------------------------------------------------------------------------------- /HotCommands/Resources/HotCommandsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcla/HotCommands/HEAD/HotCommands/Resources/HotCommandsIcon.png -------------------------------------------------------------------------------- /HotCommands/Resources/HotCommandsPreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcla/HotCommands/HEAD/HotCommands/Resources/HotCommandsPreview.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /HotCommands/Resources/HotCommandsIcon_v2_128x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcla/HotCommands/HEAD/HotCommands/Resources/HotCommandsIcon_v2_128x.png -------------------------------------------------------------------------------- /HotCommands/Commands/JoinLines.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio; 2 | using Microsoft.VisualStudio.Text.Classification; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.Text.Operations; 5 | using OleInterop = Microsoft.VisualStudio.OLE.Interop; 6 | 7 | namespace HotCommands 8 | { 9 | /// 10 | /// Command handler for JoinLines 11 | /// 12 | internal sealed class JoinLines 13 | { 14 | public static int HandleCommand(IWpfTextView textView, IClassifier classifier, OleInterop.IOleCommandTarget commandTarget, IEditorOperations editorOperations) 15 | { 16 | // TODO: Handle UNDO management. This should occur as a single undo-able transaction in the Undo history 17 | editorOperations.MoveToEndOfLine(false); 18 | editorOperations.Delete(); 19 | editorOperations.DeleteHorizontalWhiteSpace(); 20 | 21 | return VSConstants.S_OK; 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /HotCommands/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace HotCommands 4 | { 5 | public class Constants 6 | { 7 | public static readonly Guid HotCommandsGuid = new Guid("1023dc3d-550c-46b8-a3ec-c6b03431642c"); 8 | public const uint DuplicateLinesUpCmdId = 0x1017; 9 | public const uint DuplicateLinesDownCmdId = 0x1018; 10 | public const uint DuplicateSelectionCmdId = 0x1019; 11 | public const uint DuplicateSelectionReverseCmdId = 0x1020; 12 | public const uint ToggleCommentCmdId = 0x1021; 13 | public const uint ExpandSelectionCmdId = 0x1022; 14 | public const uint ShrinkSelectionCmdId = 0x1023; 15 | public const uint FormatCodeCmdId = 0x1027; 16 | public const uint MoveMemberUpCmdId = 0x1031; 17 | public const uint MoveMemberDownCmdId = 0x1032; 18 | public const uint GoToPreviousMemberCmdId = 0x1033; 19 | public const uint GoToNextMemberCmdId = 0x1034; 20 | public const uint JoinLinesCmdId = 0x1040; 21 | public const uint GoToLastEditLocationCmdId = 0x1050; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /HotCommands.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.25907.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotCommands", "HotCommands\HotCommands.csproj", "{F0DDF909-9D14-44EC-8F0C-3D8858865CF0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F0DDF909-9D14-44EC-8F0C-3D8858865CF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F0DDF909-9D14-44EC-8F0C-3D8858865CF0}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F0DDF909-9D14-44EC-8F0C-3D8858865CF0}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F0DDF909-9D14-44EC-8F0C-3D8858865CF0}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A7BA05F2-4B3F-410E-A9B3-3AB8E097654C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /HotCommands/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("HotCommands")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("HotCommands")] 12 | [assembly: AssemblyCopyright("")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | // You can specify all the values or you can default the Build and Revision Numbers 29 | // by using the '*' as shown below: 30 | // [assembly: AssemblyVersion("1.0.*")] 31 | [assembly: AssemblyVersion("1.0.0.0")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | -------------------------------------------------------------------------------- /HotCommands/Commands/MoveMemberDown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.Shell; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.Text.Operations; 5 | using OleInterop = Microsoft.VisualStudio.OLE.Interop; 6 | 7 | namespace HotCommands 8 | { 9 | /// 10 | /// Command handler for MoveMemberDown 11 | /// 12 | internal sealed class MoveMemberDown 13 | { 14 | private readonly Package package; 15 | 16 | private MoveMemberDown(Package package) 17 | { 18 | if (package == null) 19 | { 20 | throw new ArgumentNullException("package"); 21 | } 22 | 23 | this.package = package; 24 | } 25 | 26 | public static MoveMemberDown Instance 27 | { 28 | get; 29 | private set; 30 | } 31 | 32 | private IServiceProvider ServiceProvider 33 | { 34 | get 35 | { 36 | return this.package; 37 | } 38 | } 39 | 40 | public static void Initialize(Package package) 41 | { 42 | Instance = new MoveMemberDown(package); 43 | } 44 | 45 | public int HandleCommand(IWpfTextView textView, OleInterop.IOleCommandTarget commandTarget, IEditorOperations editorOperations) 46 | { 47 | return textView.MoveMemberDown(commandTarget, editorOperations); 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /HotCommands/Commands/FormatCode.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Copyright (c) Company. All rights reserved. 4 | // 5 | //------------------------------------------------------------------------------ 6 | 7 | using System; 8 | using Microsoft.VisualStudio; 9 | using Microsoft.VisualStudio.Text.Editor; 10 | using OleInterop = Microsoft.VisualStudio.OLE.Interop; 11 | 12 | namespace HotCommands 13 | { 14 | /// 15 | /// Command handler for FormatCode 16 | /// 17 | internal sealed class FormatCode : Command 18 | { 19 | public int HandleCommand(IWpfTextView textView, OleInterop.IOleCommandTarget commandTarget) 20 | { 21 | Guid cmdGroup = VSConstants.VSStd2K; 22 | 23 | // Execute FormatSelection or FormatDocument depending on current state of selected code 24 | uint cmdID = IsCursorOnly(textView) ? (uint)VSConstants.VSStd2KCmdID.FORMATDOCUMENT : (uint)VSConstants.VSStd2KCmdID.FORMATSELECTION; 25 | commandTarget.Exec(ref cmdGroup, cmdID, (uint)OleInterop.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, IntPtr.Zero, IntPtr.Zero); 26 | 27 | return VSConstants.S_OK; 28 | } 29 | 30 | private bool IsCursorOnly(IWpfTextView textView) 31 | { 32 | if (textView.Selection.SelectedSpans.Count > 1) return false; 33 | // Only one selection. Check if there is any selected content. 34 | return textView.Selection.SelectedSpans[0].Length == 0; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /HotCommands/Commands/Command.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Copyright (c) Company. All rights reserved. 4 | // 5 | //------------------------------------------------------------------------------ 6 | 7 | using System; 8 | using Microsoft.VisualStudio.Shell; 9 | using Microsoft.VisualStudio; 10 | using Microsoft.VisualStudio.Text.Editor; 11 | 12 | namespace HotCommands 13 | { 14 | class Command where T : Command , new() 15 | { 16 | /// 17 | /// VS Package that provides this command, not null. 18 | /// 19 | public Package package; 20 | 21 | /// 22 | /// Gets the instance of the command. 23 | /// 24 | public static T Instance 25 | { 26 | get; 27 | private set; 28 | } 29 | 30 | /// 31 | /// Gets the service provider from the owner package. 32 | /// 33 | protected IServiceProvider ServiceProvider 34 | { 35 | get 36 | { 37 | return this.package; 38 | } 39 | } 40 | 41 | /// 42 | /// Initializes the singleton instance of the command. 43 | /// 44 | /// Owner package, not null. 45 | public static void Initialize(Package package) 46 | { 47 | Instance = new T { package = package }; 48 | } 49 | 50 | public virtual int HandleCommand(IWpfTextView textView) 51 | { 52 | return VSConstants.S_OK; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /HotCommands/Listeners/HotCommandsTextViewCreationListener.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Editor; 2 | using Microsoft.VisualStudio.OLE.Interop; 3 | using Microsoft.VisualStudio.TextManager.Interop; 4 | using Microsoft.VisualStudio.Text.Editor; 5 | using Microsoft.VisualStudio.Utilities; 6 | using System.ComponentModel.Composition; 7 | using Microsoft.VisualStudio.Text.Classification; 8 | using Microsoft.VisualStudio.Shell; 9 | using Microsoft.VisualStudio.Text.Operations; 10 | #pragma warning disable 0649 11 | 12 | namespace HotCommands 13 | { 14 | [Export(typeof(IVsTextViewCreationListener))] 15 | [ContentType("text")] 16 | [TextViewRole(PredefinedTextViewRoles.Editable)] 17 | internal sealed class HotCommandsTextViewCreationListener : IVsTextViewCreationListener 18 | { 19 | [Import] 20 | private IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } 21 | 22 | [Import] 23 | private IClassifierAggregatorService _aggregatorFactory; 24 | 25 | [Import] 26 | private SVsServiceProvider _globalServiceProvider; 27 | 28 | [Import(typeof(IEditorOperationsFactoryService))] 29 | private IEditorOperationsFactoryService _editorOperationsFactory; 30 | 31 | [Import] 32 | private ITextBufferUndoManagerProvider _undoProvider; 33 | 34 | public void VsTextViewCreated(IVsTextView textViewAdapter) 35 | { 36 | IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); 37 | 38 | HotCommandsCommandFilter commandFilter = new HotCommandsCommandFilter(textView, _aggregatorFactory, _globalServiceProvider, _editorOperationsFactory, _undoProvider); 39 | IOleCommandTarget next; 40 | textViewAdapter.AddCommandFilter(commandFilter, out next); 41 | 42 | commandFilter.Next = next; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /HotCommands/Commands/MoveMemberUp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.Shell; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.Text.Operations; 5 | using OleInterop = Microsoft.VisualStudio.OLE.Interop; 6 | 7 | namespace HotCommands 8 | { 9 | /// 10 | /// Command handler for ToggleComment 11 | /// 12 | internal sealed class MoveMemberUp 13 | { 14 | /// 15 | /// VS Package that provides this command, not null. 16 | /// 17 | private readonly Package package; 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// Owner package, not null. 23 | private MoveMemberUp(Package package) 24 | { 25 | if (package == null) 26 | { 27 | throw new ArgumentNullException("package"); 28 | } 29 | 30 | this.package = package; 31 | } 32 | 33 | /// 34 | /// Gets the instance of the command. 35 | /// 36 | public static MoveMemberUp Instance 37 | { 38 | get; 39 | private set; 40 | } 41 | 42 | /// 43 | /// Gets the service provider from the owner package. 44 | /// 45 | private IServiceProvider ServiceProvider 46 | { 47 | get 48 | { 49 | return this.package; 50 | } 51 | } 52 | 53 | /// 54 | /// Initializes the singleton instance of the command. 55 | /// 56 | /// Owner package, not null. 57 | public static void Initialize(Package package) 58 | { 59 | Instance = new MoveMemberUp(package); 60 | } 61 | 62 | public int HandleCommand(IWpfTextView textView, OleInterop.IOleCommandTarget commandTarget, IEditorOperations editorOperations) 63 | { 64 | return textView.MoveMemberUp(commandTarget,editorOperations); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /HotCommands/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hot Commands 6 | A collection of commands and shortcuts for enhanced productivity in Visual Studio IDE. VS2022+ 7 | https://marketplace.visualstudio.com/items?itemName=JustinClareburtMSFT.HotCommandsforVisualStudio 8 | Packaging\License.rtf 9 | https://github.com/justcla/HotCommands 10 | https://github.com/justcla/HotCommands/blob/master/HotCommands/Packaging/ReleaseNotes.txt 11 | Resources\HotCommandsIcon_v2_128x.png 12 | Resources\HotCommandsPreview.png 13 | HotCommands;Hot;Commands;Productivity;Keyboard;Shortcuts;Toggle comment;Duplicate code;Format code 14 | 15 | 16 | 17 | amd64 18 | 19 | 20 | arm64 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /HotCommands/Hot Commands Shortcuts.vssettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15.0.0.0 9 | 10 | 11 | 12 | 13 | 14 | 15 | Ctrl+/ 16 | Ctrl+Shift+J 17 | Ctrl+Alt+F 18 | Ctrl+Shift+Bkspce 19 | 20 | Ctrl+D 21 | Ctrl+Shift+U 22 | Ctrl+Shift+D 23 | Ctrl+D 24 | 25 | 26 | Ctrl+W 27 | Ctrl+Shift+W 28 | 29 | Ctrl+Alt+Up Arrow 30 | Ctrl+Alt+Down Arrow 31 | Ctrl+Shift+Alt+Up Arrow 32 | Ctrl+Shift+Alt+Down Arrow 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /HotCommands/Listeners/LastEditTextViewCreationListener.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Editor; 2 | using Microsoft.VisualStudio.Text; 3 | using Microsoft.VisualStudio.Text.Editor; 4 | using Microsoft.VisualStudio.TextManager.Interop; 5 | using Microsoft.VisualStudio.Utilities; 6 | using System; 7 | using System.ComponentModel.Composition; 8 | #pragma warning disable 0649 9 | 10 | namespace HotCommands 11 | { 12 | [Export(typeof(IVsTextViewCreationListener))] 13 | [ContentType("text")] 14 | [TextViewRole(PredefinedTextViewRoles.Editable)] 15 | internal sealed class LastEditTextViewCreationListener : IVsTextViewCreationListener 16 | { 17 | [Import] 18 | private IVsEditorAdaptersFactoryService _editorAdaptersFactoryService { get; set; } 19 | 20 | [Import] 21 | private ITextDocumentFactoryService _textDocumentFactoryService; 22 | 23 | public void VsTextViewCreated(IVsTextView textViewAdapter) 24 | { 25 | var textView = _editorAdaptersFactoryService.GetWpfTextView(textViewAdapter); 26 | LastEditHandler lastEditHandler = new LastEditHandler(textView, _textDocumentFactoryService); 27 | textView.TextDataModel.DocumentBuffer.PostChanged += lastEditHandler.RecordLastEdit; 28 | } 29 | } 30 | 31 | public class LastEditHandler { 32 | 33 | private IWpfTextView _textView; 34 | private ITextDocumentFactoryService _textDocumentFactoryService; 35 | 36 | public LastEditHandler(IWpfTextView textView, ITextDocumentFactoryService textDocumentFactoryService) 37 | { 38 | _textView = textView; 39 | _textDocumentFactoryService = textDocumentFactoryService; 40 | } 41 | 42 | public void RecordLastEdit(object sender, EventArgs e) 43 | { 44 | // An edit has been made. Record the caret file and position. 45 | string filepath = GetCurrentFilePath(); 46 | int position = GetCurrentCaretPosition(); 47 | LastEdit.SetLastEdit(filepath, position); 48 | } 49 | 50 | private string GetCurrentFilePath() 51 | { 52 | ITextBuffer textBuffer = _textView.TextDataModel.DocumentBuffer; 53 | ITextDocument textDocument; 54 | _textDocumentFactoryService.TryGetTextDocument(textBuffer, out textDocument); 55 | return textDocument.FilePath; 56 | } 57 | 58 | private int GetCurrentCaretPosition() 59 | { 60 | return _textView.Caret.Position.BufferPosition; 61 | } 62 | 63 | } 64 | 65 | public class LastEdit 66 | { 67 | public static string LastEditFile { get; private set; } 68 | public static int LastEditPosn { get; private set; } 69 | 70 | internal static void SetLastEdit(string filepath, int position) 71 | { 72 | LastEditFile = filepath; 73 | LastEditPosn = position; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HotCommands 2 | 3 | Project for creating new commands and shortcuts for Visual Studio. 4 | 5 |

Hot Commands for Visual Studio provides the follow features:

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 87 | 88 | 89 |
FeatureNotesShortcut
Toggle CommentComments or Uncomments selected text or lines,
or if no selection, Comments/Uncomments the current line then moves cursor down one line.
Ctrl+/
Duplicate SelectionDuplicates the currently selected text, or the current line if no selection.Ctrl+D
Duplicate LinesDuplicates the entire line(s) of the current selection, or the current line if no selection.Ctrl+Shift+D
Edit.JoinLinesJoins the current line with the next line and removes redundant whitespace.Ctrl+Shift+J
Format CodeFormats the selected text, or the whole document if no selection.Ctrl+Alt+F
Increase SelectionExpands the current text selection by one level (ie. next largest code block level) 42 |

Ctrl+{, Ctrl+}
(Same as Ctrl+Shift+[, Ctrl+Shift+[)

43 |
Decrease SelectionShrinks the current text selection by one level (ie. next smallest code block level) 49 |

Ctrl+{, Ctrl+}
(Same as Ctrl+Shift+[, Ctrl+Shift+[)

50 |
Go To Previous Member /
Go To Next Member
Navigates to the previous/next member (ie. Method, Class, Field, Property)Ctrl+Alt+UpArrow /
Ctrl+Alt+DownArrow
Move Member Up /
Move Member Down
Moves the current member above(/below) the previous(/next) member 61 |

Ctrl+Shift+Alt+UpArrow /
Ctrl+Shift+Alt+DownArrow 

62 |
Refactoring Suggestions/Helpers
Initialize Field From ConstructorInserts variable as parameter to constructor and initializes it 71 |

Lightbulb action
(Roslyn Analyzer)

72 |
Extract Class or NamespaceExtracts the selected class (or namespace) into a separate file 78 |

Lightbulb action
(Roslyn Analyzer)

79 |
Change class modifierChange class modifier to public, protected, internal, private, or protected internal 85 |

Lightbulb action
(Roslyn Analyzer)

86 |
90 |
91 | 92 |
93 | -------------------------------------------------------------------------------- /HotCommands/Commands/ToggleComment.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Copyright (c) Company. All rights reserved. 4 | // 5 | //------------------------------------------------------------------------------ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using Microsoft.VisualStudio; 10 | using Microsoft.VisualStudio.Text.Classification; 11 | using Microsoft.VisualStudio.Text.Editor; 12 | using Microsoft.VisualStudio.Text; 13 | using Microsoft.VisualStudio.Language.StandardClassification; 14 | using Microsoft.VisualStudio.Text.Operations; 15 | using OleInterop = Microsoft.VisualStudio.OLE.Interop; 16 | 17 | namespace HotCommands 18 | { 19 | /// 20 | /// Command handler for ToggleComment 21 | /// 22 | internal sealed class ToggleComment : Command 23 | { 24 | public int HandleCommand(IWpfTextView textView, IClassifier classifier, OleInterop.IOleCommandTarget commandTarget, IEditorOperations editorOperations) 25 | { 26 | Guid cmdGroup = VSConstants.VSStd2K; 27 | 28 | // Is anything selected? (Or just a cursor) 29 | bool cursorOnly = IsCursorOnly(textView); 30 | 31 | // Execute Comment or Uncomment depending on current state of selected code 32 | uint cmdID = IsAllCommented(textView, classifier) ? (uint) VSConstants.VSStd2KCmdID.UNCOMMENT_BLOCK : (uint) VSConstants.VSStd2KCmdID.COMMENT_BLOCK; 33 | int hr = commandTarget.Exec(ref cmdGroup, cmdID, (uint)OleInterop.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, IntPtr.Zero, IntPtr.Zero); 34 | 35 | if (cursorOnly) 36 | { 37 | // Move caret down one line 38 | editorOperations.MoveLineDown(extendSelection:false); 39 | } 40 | 41 | return VSConstants.S_OK; 42 | } 43 | 44 | private bool IsCursorOnly(IWpfTextView textView) 45 | { 46 | if (textView.Selection.SelectedSpans.Count > 1) return false; 47 | // Only one selection. Check if there is any selected content. 48 | return textView.Selection.SelectedSpans[0].Length == 0; 49 | } 50 | 51 | private bool IsAllCommented(IWpfTextView textView, IClassifier classifier) 52 | { 53 | foreach (SnapshotSpan snapshotSpan in textView.Selection.SelectedSpans) 54 | { 55 | SnapshotSpan spanToCheck = snapshotSpan.Length == 0 ? 56 | new SnapshotSpan(textView.TextSnapshot, textView.Caret.ContainingTextViewLine.Extent.Span) : 57 | snapshotSpan; 58 | IList classificationSpans = classifier.GetClassificationSpans(spanToCheck); 59 | foreach (var classification in classificationSpans) 60 | { 61 | var name = classification.ClassificationType.Classification.ToLower(); 62 | if (!name.Contains(PredefinedClassificationTypeNames.Comment)) 63 | { 64 | return false; 65 | } 66 | } 67 | } 68 | 69 | return true; 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /HotCommands/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /HotCommands/HotCommandsPackage.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Copyright (c) Company. All rights reserved. 4 | // 5 | //------------------------------------------------------------------------------ 6 | 7 | using System.Diagnostics.CodeAnalysis; 8 | using System.Runtime.InteropServices; 9 | using HotCommands.Commands; 10 | using Microsoft.VisualStudio.Shell; 11 | using Microsoft.VisualStudio; 12 | using System; 13 | using System.Threading; 14 | 15 | namespace HotCommands 16 | { 17 | /// 18 | /// This is the class that implements the package exposed by this assembly. 19 | /// 20 | /// 21 | /// 22 | /// The minimum requirement for a class to be considered a valid package for Visual Studio 23 | /// is to implement the IVsPackage interface and register itself with the shell. 24 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF) 25 | /// to do it: it derives from the Package class that provides the implementation of the 26 | /// IVsPackage interface and uses the registration attributes defined in the framework to 27 | /// register itself and its components with the shell. These attributes tell the pkgdef creation 28 | /// utility what data to put into .pkgdef file. 29 | /// 30 | /// 31 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. 32 | /// 33 | /// 34 | [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] 35 | [InstalledProductRegistration("#1110", "#1112", "1.0", IconResourceID = 1400)] // Info on this package for Help/About 36 | [ProvideMenuResource("Menus.ctmenu", 1)] 37 | [Guid(HotCommandsPackage.PackageGuidString)] 38 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] 39 | [ProvideAutoLoad(VSConstants.VsEditorFactoryGuid.TextEditor_string, PackageAutoLoadFlags.BackgroundLoad)] 40 | public sealed class HotCommandsPackage : AsyncPackage 41 | { 42 | /// 43 | /// HotCommandsPackage GUID string. 44 | /// 45 | public const string PackageGuidString = "dec6a640-ee9b-4753-821b-e24d75523940"; 46 | 47 | /// 48 | /// Initializes a new instance of the class. 49 | /// 50 | public HotCommandsPackage() 51 | { 52 | // Inside this method you can place any initialization code that does not require 53 | // any Visual Studio service because at this point the package object is created but 54 | // not sited yet inside Visual Studio environment. The place to do all the other 55 | // initialization is the Initialize method. 56 | } 57 | 58 | #region Package Members 59 | 60 | /// 61 | /// Initialization of the package; this method is called right after the package is sited, so this is the place 62 | /// where you can put all the initialization code that rely on services provided by VisualStudio. 63 | /// 64 | protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) 65 | { 66 | await base.InitializeAsync(cancellationToken, progress); 67 | ToggleComment.Initialize(this); 68 | ExpandSelection.Initialize(this); 69 | FormatCode.Initialize(this); 70 | DuplicateSelection.Initialize(this); 71 | MoveMemberUp.Initialize(this); 72 | MoveMemberDown.Initialize(this); 73 | await GoToLastEditLocation.Initialize(this); 74 | } 75 | 76 | #endregion 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | *.ncrunchsolution 116 | *.ncrunchproject 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | 145 | # TODO: Un-comment the next line if you do not want to checkin 146 | # your web deploy settings because they may include unencrypted 147 | # passwords 148 | #*.pubxml 149 | *.publishproj 150 | 151 | # NuGet Packages 152 | *.nupkg 153 | # The packages folder can be ignored because of Package Restore 154 | **/packages/* 155 | # except build/, which is used as an MSBuild target. 156 | !**/packages/build/ 157 | # Uncomment if necessary however generally it will be regenerated when needed 158 | #!**/packages/repositories.config 159 | # NuGet v3's project.json files produces more ignoreable files 160 | *.nuget.props 161 | *.nuget.targets 162 | 163 | # Microsoft Azure Build Output 164 | csx/ 165 | *.build.csdef 166 | 167 | # Microsoft Azure Emulator 168 | ecf/ 169 | rcf/ 170 | 171 | # Microsoft Azure ApplicationInsights config file 172 | ApplicationInsights.config 173 | 174 | # Windows Store app package directory 175 | AppPackages/ 176 | BundleArtifacts/ 177 | 178 | # Visual Studio cache files 179 | # files ending in .cache can be ignored 180 | *.[Cc]ache 181 | # but keep track of directories ending in .cache 182 | !*.[Cc]ache/ 183 | 184 | # Others 185 | ClientBin/ 186 | [Ss]tyle[Cc]op.* 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # RIA/Silverlight projects 197 | Generated_Code/ 198 | 199 | # Backup & report files from converting an old project file 200 | # to a newer Visual Studio version. Backup files are not needed, 201 | # because we have git ;-) 202 | _UpgradeReport_Files/ 203 | Backup*/ 204 | UpgradeLog*.XML 205 | UpgradeLog*.htm 206 | 207 | # SQL Server files 208 | *.mdf 209 | *.ldf 210 | 211 | # Business Intelligence projects 212 | *.rdl.data 213 | *.bim.layout 214 | *.bim_*.settings 215 | 216 | # Microsoft Fakes 217 | FakesAssemblies/ 218 | 219 | # GhostDoc plugin setting file 220 | *.GhostDoc.xml 221 | 222 | # Node.js Tools for Visual Studio 223 | .ntvs_analysis.dat 224 | 225 | # Visual Studio 6 build log 226 | *.plg 227 | 228 | # Visual Studio 6 workspace options file 229 | *.opt 230 | 231 | # Visual Studio LightSwitch build output 232 | **/*.HTMLClient/GeneratedArtifacts 233 | **/*.DesktopClient/GeneratedArtifacts 234 | **/*.DesktopClient/ModelManifest.xml 235 | **/*.Server/GeneratedArtifacts 236 | **/*.Server/ModelManifest.xml 237 | _Pvt_Extensions 238 | 239 | # LightSwitch generated files 240 | GeneratedArtifacts/ 241 | ModelManifest.xml 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | 246 | # FAKE - F# Make 247 | .fake/ 248 | 249 | #JetBrains project files 250 | .idea/ 251 | *.iml -------------------------------------------------------------------------------- /HotCommands/Commands/GoToLastEditLocation.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio; 2 | using Microsoft.VisualStudio.ComponentModelHost; 3 | using Microsoft.VisualStudio.Editor; 4 | using Microsoft.VisualStudio.Shell; 5 | using Microsoft.VisualStudio.Shell.Interop; 6 | using Microsoft.VisualStudio.Text; 7 | using Microsoft.VisualStudio.Text.Editor; 8 | using Microsoft.VisualStudio.TextManager.Interop; 9 | using System; 10 | using System.ComponentModel.Design; 11 | 12 | namespace HotCommands 13 | { 14 | /// 15 | /// Command handler for GoToLastEditLocation 16 | /// 17 | internal sealed class GoToLastEditLocation 18 | { 19 | /// 20 | /// VS Package that provides this command, not null. 21 | /// 22 | private readonly AsyncPackage package; 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// Adds our command handlers for menu (commands must exist in the command table file) 27 | /// 28 | /// Owner package, not null. 29 | private GoToLastEditLocation(AsyncPackage package) 30 | { 31 | this.package = package ?? throw new ArgumentNullException("package"); 32 | } 33 | 34 | public async System.Threading.Tasks.Task Initialize() 35 | { 36 | if (await this.AsyncServiceProvider.GetServiceAsync(typeof(IMenuCommandService)) is OleMenuCommandService globalCommandService) 37 | { 38 | var menuCommandID = new CommandID(Constants.HotCommandsGuid, (int)Constants.GoToLastEditLocationCmdId); 39 | var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 40 | // Switch to main thread before calling AddCommand because it calls GetService 41 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); 42 | globalCommandService.AddCommand(menuItem); 43 | } 44 | } 45 | 46 | public static GoToLastEditLocation Instance 47 | { 48 | get; 49 | private set; 50 | } 51 | 52 | private Microsoft.VisualStudio.Shell.IAsyncServiceProvider AsyncServiceProvider 53 | { 54 | get 55 | { 56 | return this.package; 57 | } 58 | } 59 | 60 | private IServiceProvider ServiceProvider 61 | { 62 | get 63 | { 64 | return this.package; 65 | } 66 | } 67 | 68 | /// 69 | /// Initializes the singleton instance of the command. 70 | /// 71 | /// Owner package, not null. 72 | public static async System.Threading.Tasks.Task Initialize(AsyncPackage package) 73 | { 74 | Instance = new GoToLastEditLocation(package); 75 | await Instance.Initialize(); 76 | } 77 | 78 | private void MenuItemCallback(object sender, EventArgs e) 79 | { 80 | NavigateToLastEditPosition(); 81 | } 82 | 83 | private void NavigateToLastEditPosition() 84 | { 85 | System.Diagnostics.Debug.WriteLine("Navigate to last edit position."); 86 | 87 | // Open the file last editted 88 | string lastEditFilePath = LastEdit.LastEditFile; 89 | IWpfTextView textView = OpenLastEdittedFile(lastEditFilePath); 90 | if (textView == null) 91 | { 92 | // Unable to open the file. Do No-Op. 93 | System.Diagnostics.Debug.WriteLine($"Unable to open last editted file: {lastEditFilePath}"); 94 | return; 95 | } 96 | 97 | // Navigate to the last edit caret position 98 | int lastEditPosn = LastEdit.LastEditPosn; 99 | SetCaretAtGivenPosition(textView, lastEditPosn); 100 | } 101 | 102 | private IWpfTextView OpenLastEdittedFile(string lastEditFilePath) 103 | { 104 | try 105 | { 106 | VsShellUtilities.OpenDocument(this.ServiceProvider, lastEditFilePath, VSConstants.LOGVIEWID_TextView, 107 | out IVsUIHierarchy hierarchy, out uint itemId, 108 | out IVsWindowFrame windowFrame, out IVsTextView vsTextView); 109 | return GetEditorAdaptorsFactoryService().GetWpfTextView(vsTextView); 110 | } 111 | catch (Exception e) 112 | { 113 | System.Diagnostics.Debug.WriteLine("Exception occurred trying to navigate set open file last editted.", e); 114 | return null; 115 | } 116 | } 117 | 118 | private static void SetCaretAtGivenPosition(IWpfTextView textView, int lastEditPosn) 119 | { 120 | try 121 | { 122 | // TODO: Check if position exists in file. 123 | textView.Caret.MoveTo(new SnapshotPoint(textView.TextSnapshot, lastEditPosn)); 124 | textView.ViewScroller.EnsureSpanVisible(new SnapshotSpan(textView.TextSnapshot, lastEditPosn, 0), EnsureSpanVisibleOptions.None); 125 | } 126 | catch (Exception e) 127 | { 128 | System.Diagnostics.Debug.WriteLine("Exception occurred trying to set caret poistion to last edit location.", e); 129 | } 130 | } 131 | 132 | private static IVsEditorAdaptersFactoryService GetEditorAdaptorsFactoryService() 133 | { 134 | IComponentModel componentService = (IComponentModel)(Package.GetGlobalService(typeof(SComponentModel))); 135 | IVsEditorAdaptersFactoryService editorAdaptersFactoryService = componentService.GetService(); 136 | return editorAdaptersFactoryService; 137 | } 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /HotCommands/Util/KeyBindingUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.Shell; 4 | using EnvDTE; 5 | 6 | namespace HotCommands 7 | { 8 | class KeyBindingUtil 9 | { 10 | /// 11 | /// VS Package that provides this command, not null. 12 | /// 13 | private static Package package; 14 | 15 | /// 16 | /// Initializes the singleton instance of the command. 17 | /// 18 | /// Owner package, not null. 19 | public static void Initialize(Package thePackage) 20 | { 21 | if (thePackage == null) 22 | { 23 | throw new ArgumentNullException("thePackage"); 24 | } 25 | 26 | package = thePackage; 27 | } 28 | 29 | /// 30 | /// Gets the service provider from the owner package. 31 | /// 32 | private IServiceProvider ServiceProvider 33 | { 34 | get 35 | { 36 | return package; 37 | } 38 | } 39 | 40 | /// 41 | /// Adds (appends) a binding for the given shortcut 42 | /// 43 | /// 44 | /// 45 | public static void BindShortcut(string commandName, string shortcutDef) 46 | { 47 | // Make sure we're not using the Default keyboard mapping scheme 48 | DTE dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE)); 49 | EnvDTE.Commands cmds = dte.Commands; 50 | Command cmd = cmds.Item(commandName); 51 | object[] newBindings = AppendKeyboardBinding(cmd, shortcutDef); 52 | cmd.Bindings = newBindings; 53 | } 54 | 55 | internal static bool BindingExists(string commandName, string shortcutDef) 56 | { 57 | DTE dte = (DTE)((IServiceProvider)package).GetService(typeof(DTE)); 58 | EnvDTE.Commands cmds = dte.Commands; 59 | // Find command 60 | Command cmd = cmds.Item(commandName); 61 | if (cmd == null) return false; 62 | // Check if the binding is attached to it 63 | object[] existingBindings = (object[])cmd.Bindings; 64 | if (existingBindings == null) return false; 65 | // Check if the keyboard binding is already there 66 | return existingBindings.Contains(shortcutDef); 67 | } 68 | 69 | /// 70 | /// Note: Calling this is redundant if the original KeyBinding works in the vsct file. 71 | /// However, sometimes there is another command bound to the desired keybinding. 72 | /// In those cases, explicitly defining the key binding here is usually more effective. 73 | /// 74 | internal void UpdateKeyBindings() 75 | { 76 | // Make sure we're not using the Default keyboard mapping scheme 77 | DTE dte = (DTE)ServiceProvider.GetService(typeof(DTE)); 78 | Properties props = dte.Properties["Environment", "Keyboard"]; 79 | Property prop = props.Item("SchemeName"); 80 | prop.Value = "MyBindings.vsk"; 81 | 82 | EnvDTE.Commands cmds = dte.Commands; 83 | 84 | // Add a binding for ExpandSelection(TextEditor) 85 | { 86 | Command cmdToggleComment = cmds.Item("Edit.ToggleComment"); 87 | const string toggleCommentKeyBinding = "Text Editor::Ctrl+/"; 88 | cmdToggleComment.Bindings = (object)AppendKeyboardBinding(cmdToggleComment, toggleCommentKeyBinding); // Note: This overrides any key bindings already assigned to this command 89 | } 90 | 91 | // Add a binding for ExpandSelection(TextEditor) 92 | { 93 | Command cmdExpandSelection = cmds.Item("1023dc3d-550c-46b8-a3ec-c6b03431642c", 0x1022); // Edit.ExpandSelection 94 | const string expandSelectionKeyBinding = "Text Editor::Ctrl+W"; 95 | object[] newBindings = SingleKeyboardBinding(expandSelectionKeyBinding); 96 | cmdExpandSelection.Bindings = (object)newBindings; 97 | } 98 | 99 | { 100 | Command cmdToggleComment = cmds.Item("Edit.DuplicateSelection"); 101 | const string toggleCommentKeyBinding = "Text Editor::Ctrl+D"; 102 | cmdToggleComment.Bindings = AppendKeyboardBinding(cmdToggleComment, toggleCommentKeyBinding); 103 | 104 | cmdToggleComment = cmds.Item("Edit.DuplicateAndSelectOriginal"); 105 | const string toggleCommentKeyReverseBinding = "Text Editor::Ctrl+Shift+D"; 106 | cmdToggleComment.Bindings = AppendKeyboardBinding(cmdToggleComment, toggleCommentKeyReverseBinding); 107 | } 108 | 109 | // Add a binding for MoveMemberUp(TextEditor) 110 | { 111 | Command cmdMoveMemberUP = cmds.Item("Edit.MoveMemberUp", 0x1031); 112 | const string moveMemberUPKeyBinding = "Text Editor::Ctrl+Num 8"; 113 | cmdMoveMemberUP.Bindings = (object)AppendKeyboardBinding(cmdMoveMemberUP, moveMemberUPKeyBinding); 114 | } 115 | 116 | // Add a binding for MoveMemberDown(TextEditor) 117 | { 118 | Command cmdMoveMemberDown = cmds.Item("Edit.MoveMemberDown", 0x1032); 119 | const string moveMemberDownKeyBinding = "Text Editor::Ctrl+Num 2"; 120 | cmdMoveMemberDown.Bindings = (object)AppendKeyboardBinding(cmdMoveMemberDown, moveMemberDownKeyBinding); 121 | } 122 | 123 | } 124 | 125 | private static object[] SingleKeyboardBinding(string keyboardBindingDefn) 126 | { 127 | return new object[] { keyboardBindingDefn }; 128 | } 129 | 130 | private static object[] AppendKeyboardBinding(Command command, string keyboardBindingDefn) 131 | { 132 | object[] oldBindings = (object[])command.Bindings; 133 | 134 | // Check that keyboard binding is not already there 135 | for (int i = 0; i < oldBindings.Length; i++) 136 | { 137 | if (keyboardBindingDefn.Equals(oldBindings[i])) 138 | { 139 | // Exit early and return the existing bindings array if new keyboard binding is already there 140 | return oldBindings; 141 | } 142 | } 143 | 144 | // Build new array with all the old bindings, plus the new one. 145 | object[] newBindings = new object[oldBindings.Length + 1]; 146 | Array.Copy(oldBindings, newBindings, oldBindings.Length); 147 | newBindings[newBindings.Length - 1] = keyboardBindingDefn; 148 | return newBindings; 149 | } 150 | 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /HotCommands/VSPackage.resx: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | text/microsoft-resx 120 | 121 | 122 | 2.0 123 | 124 | 125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | 132 | ToggleComment Extension 133 | 134 | 135 | ToggleComment Visual Studio Extension Detailed Info 136 | 137 | 138 | HotCommands Extension 139 | 140 | 141 | HotCommands Visual Stuido Extension Detailed Info 142 | 143 | -------------------------------------------------------------------------------- /HotCommands/Commands/DuplicateSelection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.VisualStudio; 5 | using Microsoft.VisualStudio.OLE.Interop; 6 | using Microsoft.VisualStudio.Shell; 7 | using Microsoft.VisualStudio.Text; 8 | using Microsoft.VisualStudio.Text.Classification; 9 | using Microsoft.VisualStudio.Text.Editor; 10 | using Microsoft.VisualStudio.Text.Operations; 11 | using IServiceProvider = System.IServiceProvider; 12 | 13 | namespace HotCommands.Commands 14 | { 15 | internal sealed class DuplicateSelection 16 | { 17 | private readonly Package _package; 18 | 19 | public static DuplicateSelection Instance { get; private set; } 20 | 21 | private IServiceProvider ServiceProvider => _package; 22 | 23 | private ITextBufferUndoManagerProvider UndoProvider; 24 | 25 | 26 | public static void Initialize(Package package) 27 | { 28 | Instance = new DuplicateSelection(package); 29 | } 30 | 31 | private DuplicateSelection(Package package) 32 | { 33 | if (package == null) 34 | throw new ArgumentNullException(nameof(package)); 35 | _package = package; 36 | } 37 | 38 | public static int HandleCommand(IWpfTextView textView, IClassifier classifier, 39 | IOleCommandTarget commandTarget, IEditorOperations editorOperations, 40 | ITextBufferUndoManagerProvider undoManagerProvider, bool isDuplicateLines = false, bool isReversed = false) 41 | { 42 | // Use cases: 43 | // Single or Multiple carets 44 | // For each caret/selection (in SelectedSpans): 45 | // - No-text selection 46 | // - Single-line selection 47 | // - Multi-line selection 48 | // - Selection that ends on the first char of the line 49 | 50 | // Create a single transaction so the user can Undo all operations in one go. 51 | ITextBufferUndoManager undoManager = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer); 52 | ITextUndoTransaction transaction = undoManager.TextBufferUndoHistory.CreateTransaction("Duplicate Selection"); 53 | 54 | // This bool is to handle an annoying edge case where the selection would be expanded 55 | // by the inserted text because the insertion happens at the end of the selection. 56 | bool isEdgeCase_InsertExpandsSelection = false; 57 | 58 | IMultiSelectionBroker selectionBroker = textView.GetMultiSelectionBroker(); 59 | IReadOnlyList selections = selectionBroker.AllSelections; 60 | Selection primarySelection = selectionBroker.PrimarySelection; 61 | ITextSnapshot afterEditSnapshot; 62 | using (ITextEdit edit = textView.TextBuffer.CreateEdit()) // Perform compound operation. 63 | { 64 | foreach (Selection selection in selections) 65 | { 66 | SnapshotSpan selectionSpan = selection.Extent.SnapshotSpan; 67 | bool isDuplicateLinesForThisSelection = isDuplicateLines || selectionSpan.Length == 0; // When selection length is zero we treat it as duplicate lines command (or should we not?). 68 | 69 | SnapshotSpan duplicationSpan; 70 | bool isMissingNewLine; // Should only be true when duplicating the last line in the document. 71 | if (isDuplicateLinesForThisSelection) 72 | { 73 | duplicationSpan = GetContainingLines(selectionSpan); 74 | isMissingNewLine = duplicationSpan.End == edit.Snapshot.Length 75 | && edit.Snapshot.GetLineFromLineNumber(edit.Snapshot.LineCount - 1).Length > 0; 76 | } 77 | else 78 | { 79 | duplicationSpan = selectionSpan; 80 | isMissingNewLine = false; 81 | } 82 | 83 | string textToInsert = duplicationSpan.GetText(); 84 | 85 | SnapshotPoint insertPos; 86 | if (isReversed) 87 | { 88 | insertPos = duplicationSpan.End; 89 | 90 | isEdgeCase_InsertExpandsSelection |= selectionSpan.End == insertPos; 91 | 92 | if (isMissingNewLine) textToInsert = Environment.NewLine + textToInsert; 93 | } 94 | else 95 | { 96 | insertPos = duplicationSpan.Start; 97 | 98 | if (isMissingNewLine) textToInsert = textToInsert + Environment.NewLine; 99 | } 100 | 101 | edit.Insert(insertPos, textToInsert); 102 | } 103 | 104 | afterEditSnapshot = edit.Apply(); 105 | } 106 | 107 | if (isEdgeCase_InsertExpandsSelection) 108 | { 109 | // Translate selections to newest snapshot with negative tracking mode for the 110 | // end point so that they are not expanded due to the recent insertions. 111 | var newSelections = new Selection[selections.Count]; 112 | int primarySelectionIndex = 0; 113 | for (int i = 0; i < newSelections.Length; i++) 114 | { 115 | Selection selection = selections[i]; 116 | if (primarySelection.Equals(selection)) primarySelectionIndex = i; 117 | newSelections[i] = TranslateTo( 118 | selection, afterEditSnapshot, 119 | GetPointTrackingMode(selection.InsertionPoint), 120 | GetPointTrackingMode(selection.AnchorPoint), 121 | GetPointTrackingMode(selection.ActivePoint) 122 | ); 123 | 124 | PointTrackingMode GetPointTrackingMode(VirtualSnapshotPoint point) 125 | { 126 | if (point.Position == point.Position.Snapshot.Length) return PointTrackingMode.Negative; 127 | return point <= selection.Extent.Start ? PointTrackingMode.Positive : PointTrackingMode.Negative; 128 | } 129 | } 130 | 131 | selectionBroker.SetSelectionRange(newSelections, newSelections[primarySelectionIndex]); 132 | } 133 | 134 | // Complete the transaction 135 | transaction.Complete(); 136 | 137 | return VSConstants.S_OK; 138 | } 139 | 140 | /// 141 | /// Transforms a selection to a target snapshot using the provided tracking rules. 142 | /// TODO: Move to utility class and make into extension? 143 | /// 144 | public static Selection TranslateTo(Selection selection, ITextSnapshot targetSnapshot, PointTrackingMode insertionPointTracking, PointTrackingMode anchorPointTracking, PointTrackingMode activePointTracking) 145 | { 146 | return new Selection 147 | ( 148 | selection.InsertionPoint.TranslateTo(targetSnapshot, insertionPointTracking), 149 | selection.AnchorPoint.TranslateTo(targetSnapshot, anchorPointTracking), 150 | selection.ActivePoint.TranslateTo(targetSnapshot, activePointTracking), 151 | selection.InsertionPointAffinity 152 | ); 153 | } 154 | 155 | /// 156 | /// Expands span to include all lines it touches. 157 | /// Spans ending on first char of a new line does not count as touching that line. 158 | /// Includes any trailing new-line chars (CR/LF). 159 | /// TODO: Move to utility class and make into extension? 160 | /// 161 | /// The lines that contains this span. 162 | public static SnapshotSpan GetContainingLines(SnapshotSpan span) 163 | { 164 | var firstLine = span.Start.GetContainingLine(); 165 | SnapshotPoint linesStart = firstLine.Start; 166 | SnapshotPoint linesEnd; 167 | if (span.Length == 0) 168 | { 169 | linesEnd = firstLine.EndIncludingLineBreak; 170 | } 171 | else 172 | { 173 | var lastLine = span.End.GetContainingLine(); 174 | linesEnd = span.End == lastLine.Start ? 175 | lastLine.Start 176 | : 177 | lastLine.EndIncludingLineBreak; 178 | } 179 | return new SnapshotSpan(linesStart, linesEnd); 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /HotCommands/HotCommandsCommandFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.OLE.Interop; 2 | using Microsoft.VisualStudio.Text.Editor; 3 | using OLEConstants = Microsoft.VisualStudio.OLE.Interop.Constants; 4 | using System; 5 | using HotCommands.Commands; 6 | using Microsoft.VisualStudio; 7 | using Microsoft.VisualStudio.Text.Classification; 8 | using Microsoft.VisualStudio.Shell; 9 | using Microsoft.VisualStudio.Shell.Interop; 10 | using Microsoft.VisualStudio.Text.Operations; 11 | 12 | namespace HotCommands 13 | { 14 | internal sealed class HotCommandsCommandFilter : IOleCommandTarget 15 | { 16 | private readonly IWpfTextView textView; 17 | private readonly IClassifier classifier; 18 | private readonly SVsServiceProvider globalServiceProvider; 19 | private IEditorOperations editorOperations; 20 | private readonly ITextBufferUndoManagerProvider undoManagerProvider; 21 | private IVsStatusbar statusBarService; 22 | internal IVsStatusbar StatusBarService => this.statusBarService 23 | ?? (this.statusBarService = globalServiceProvider.GetService(typeof(SVsStatusbar)) as IVsStatusbar); 24 | 25 | public HotCommandsCommandFilter(IWpfTextView textView, IClassifierAggregatorService aggregatorFactory, 26 | SVsServiceProvider globalServiceProvider, IEditorOperationsFactoryService editorOperationsFactory, 27 | ITextBufferUndoManagerProvider undoProvider) 28 | { 29 | this.textView = textView; 30 | classifier = aggregatorFactory.GetClassifier(textView.TextBuffer); 31 | this.globalServiceProvider = globalServiceProvider; 32 | editorOperations = editorOperationsFactory.GetEditorOperations(textView); 33 | this.undoManagerProvider = undoProvider; 34 | } 35 | 36 | public IOleCommandTarget Next { get; internal set; } 37 | 38 | public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) 39 | { 40 | // Command handling 41 | if (pguidCmdGroup == Constants.HotCommandsGuid) 42 | { 43 | // Due to Async initialization, some Instances might be uninitialized and will return null. 44 | // Safely catch the NullReferenceException and report a message to the status bar 45 | try 46 | { 47 | // Dispatch to the correct command handler 48 | switch (nCmdID) 49 | { 50 | case Constants.ToggleCommentCmdId: 51 | return ToggleComment.Instance.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations); 52 | case Constants.ExpandSelectionCmdId: 53 | return ExpandSelection.Instance.HandleCommand(textView, true); 54 | case Constants.ShrinkSelectionCmdId: 55 | return ExpandSelection.Instance.HandleCommand(textView, false); 56 | case Constants.FormatCodeCmdId: 57 | return FormatCode.Instance.HandleCommand(textView, GetShellCommandDispatcher()); 58 | case Constants.DuplicateSelectionCmdId: 59 | return DuplicateSelection.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations, undoManagerProvider, isDuplicateLines: false, isReversed: false); 60 | case Constants.DuplicateSelectionReverseCmdId: 61 | return DuplicateSelection.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations, undoManagerProvider, isDuplicateLines: false, isReversed: true); 62 | case Constants.DuplicateLinesDownCmdId: 63 | return DuplicateSelection.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations, undoManagerProvider, isDuplicateLines: true, isReversed: false); 64 | case Constants.DuplicateLinesUpCmdId: 65 | return DuplicateSelection.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations, undoManagerProvider, isDuplicateLines: true, isReversed: true); 66 | case Constants.JoinLinesCmdId: 67 | return JoinLines.HandleCommand(textView, classifier, GetShellCommandDispatcher(), editorOperations); 68 | case Constants.MoveMemberUpCmdId: 69 | return MoveMemberUp.Instance.HandleCommand(textView,GetShellCommandDispatcher(), editorOperations); 70 | case Constants.MoveMemberDownCmdId: 71 | return MoveMemberDown.Instance.HandleCommand(textView,GetShellCommandDispatcher(), editorOperations); 72 | case Constants.GoToPreviousMemberCmdId: 73 | return MoveCursorToAdjacentMember.MoveToPreviousMember(textView, editorOperations); 74 | case Constants.GoToNextMemberCmdId: 75 | return MoveCursorToAdjacentMember.MoveToNextMember(textView, editorOperations); 76 | } 77 | // Clear the Status Bar text 78 | StatusBarService.Clear(); 79 | } 80 | catch (NullReferenceException) 81 | { 82 | // Most likely exception: System.NullReferenceException: 'Object reference not set to an instance of an object.' 83 | // Resulting from the command being called before Async loading has taken place. 84 | // Swallow the exception and hope it works the next time the user tries it. 85 | // Print a message to the StatusBar 86 | StatusBarService.SetText("HotCommands is still loading. Please try again soon."); 87 | } 88 | } 89 | 90 | // No commands called. Pass to next command handler. 91 | if (Next != null) 92 | { 93 | return Next.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); 94 | } 95 | return (int)OLEConstants.OLECMDERR_E_UNKNOWNGROUP; 96 | } 97 | 98 | public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) 99 | { 100 | // Command handling registration 101 | if (pguidCmdGroup == Constants.HotCommandsGuid && cCmds == 1) 102 | { 103 | const uint supportedAndEnabledStatus = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); 104 | 105 | var contentType = textView.TextBuffer.ContentType; 106 | 107 | uint commandStatus = default; 108 | switch (prgCmds[0].cmdID) 109 | { 110 | // 'Any' content commands 111 | case Constants.DuplicateLinesUpCmdId: 112 | case Constants.DuplicateLinesDownCmdId: 113 | case Constants.DuplicateSelectionCmdId: 114 | case Constants.DuplicateSelectionReverseCmdId: 115 | commandStatus = supportedAndEnabledStatus; 116 | break; 117 | 118 | // 'Code' content commands 119 | case Constants.ToggleCommentCmdId: 120 | commandStatus = contentType.IsOfType("Code") ? supportedAndEnabledStatus : default; 121 | break; 122 | 123 | // 'CSharp' content commands 124 | case Constants.ExpandSelectionCmdId: 125 | case Constants.FormatCodeCmdId: 126 | case Constants.MoveMemberUpCmdId: 127 | case Constants.MoveMemberDownCmdId: 128 | case Constants.GoToPreviousMemberCmdId: 129 | case Constants.GoToNextMemberCmdId: 130 | commandStatus = contentType.IsOfType("CSharp") ? supportedAndEnabledStatus : default; 131 | break; 132 | } 133 | 134 | prgCmds[0].cmdf |= commandStatus; 135 | return VSConstants.S_OK; 136 | } 137 | 138 | if (Next != null) 139 | { 140 | return Next.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); 141 | } 142 | return (int)OLEConstants.OLECMDERR_E_UNKNOWNGROUP; 143 | } 144 | 145 | /// 146 | /// Get the SUIHostCommandDispatcher from the global service provider. 147 | /// 148 | private IOleCommandTarget GetShellCommandDispatcher() 149 | { 150 | return globalServiceProvider.GetService(typeof(SUIHostCommandDispatcher)) as IOleCommandTarget; 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /HotCommands/HotCommands.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(VisualStudioVersion) 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | true 9 | 10 | 11 | 12 | true 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Debug 21 | AnyCPU 22 | 2.0 23 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 24 | {F0DDF909-9D14-44EC-8F0C-3D8858865CF0} 25 | Library 26 | Properties 27 | HotCommands 28 | HotCommands 29 | v4.7.2 30 | true 31 | true 32 | true 33 | true 34 | true 35 | false 36 | 37 | 38 | Program 39 | $(DevEnvDir)\devenv.exe 40 | /rootsuffix Exp 41 | 42 | 43 | true 44 | full 45 | false 46 | bin\Debug\ 47 | DEBUG;TRACE 48 | prompt 49 | 4 50 | 51 | 52 | pdbonly 53 | true 54 | bin\Release\ 55 | TRACE 56 | prompt 57 | 4 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | true 82 | Designer 83 | 84 | 85 | true 86 | Always 87 | 88 | 89 | Designer 90 | 91 | 92 | true 93 | Always 94 | 95 | 96 | Designer 97 | 98 | 99 | 100 | 101 | true 102 | VSPackage 103 | Designer 104 | 105 | 106 | 107 | 108 | Menus.ctmenu 109 | Designer 110 | 111 | 112 | 113 | 114 | Always 115 | 116 | 117 | Always 118 | true 119 | 120 | 121 | true 122 | Always 123 | 124 | 125 | 126 | 127 | 128 | 129 | 4.4.0 130 | 131 | 132 | 4.4.0 133 | 134 | 135 | 4.4.0 136 | 137 | 138 | 17.4.255 139 | 140 | 141 | 17.4.255 142 | 143 | 144 | 17.4.255 145 | 146 | 147 | 17.4.33103.184 148 | 149 | 150 | 17.4.33103.184 151 | 152 | 153 | 17.4.255 154 | 155 | 156 | 157 | 17.4.255 158 | 159 | 160 | 17.4.255 161 | 162 | 163 | 17.4.255 164 | 165 | 166 | 17.4.255 167 | 168 | 169 | 17.4.33 170 | 171 | 172 | 17.4.33103.184 173 | 174 | 175 | 17.0.65 176 | 177 | 178 | runtime; build; native; contentfiles; analyzers; buildtransitive 179 | all 180 | 181 | 182 | 183 | 4.3.0 184 | 185 | 186 | 4.3.0 187 | 188 | 189 | 4.3.0 190 | 191 | 192 | 4.3.1 193 | 194 | 195 | 4.3.0 196 | 197 | 198 | 4.3.0 199 | 200 | 201 | 4.3.2 202 | 203 | 204 | 4.3.0 205 | 206 | 207 | 4.3.0 208 | 209 | 210 | 4.3.0 211 | 212 | 213 | 4.3.0 214 | 215 | 216 | 223 | -------------------------------------------------------------------------------- /HotCommands/Commands/ExpandSelection.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Copyright (c) Company. All rights reserved. 4 | // 5 | //------------------------------------------------------------------------------ 6 | 7 | using Microsoft.VisualStudio.Shell; 8 | using Microsoft.VisualStudio; 9 | using Microsoft.VisualStudio.Text.Editor; 10 | using Microsoft.CodeAnalysis.Text; 11 | using System.Linq; 12 | using Microsoft.CodeAnalysis; 13 | using Microsoft.VisualStudio.Text; 14 | using System.Threading.Tasks; 15 | using System.Collections.Generic; 16 | 17 | namespace HotCommands 18 | { 19 | /// 20 | /// Command handler 21 | /// 22 | internal sealed class ExpandSelection : Command 23 | { 24 | public new static void Initialize(Package package) 25 | { 26 | Command.Initialize(package); 27 | //ForceKeyboardBindings(package); 28 | } 29 | 30 | private static void ForceKeyboardBindings(Package package) 31 | { 32 | KeyBindingUtil.Initialize(package); 33 | // We only want to force this keyboard binding if it is currently set to the default VS shortcut 34 | // ie. Ctrl+W bound to Edit.SelectCurrentWord 35 | //if (KeyBindingUtil.BindingExists("Edit.SelectCurrentWord", "Text Editor::Ctrl+W")) 36 | //{ 37 | KeyBindingUtil.BindShortcut("Edit.IncreaseSelection", "Text Editor::Ctrl+W"); 38 | //} 39 | } 40 | 41 | public int HandleCommand(IWpfTextView textView, bool expand) 42 | { 43 | if (expand) 44 | { 45 | return HandleCommandExpandTask(textView).Result; 46 | } 47 | else 48 | { 49 | return HandleCommandShrinkTask(textView).Result; 50 | } 51 | } 52 | 53 | private async Task HandleCommandShrinkTask(IWpfTextView textView) 54 | { 55 | var syntaxRoot = await textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges().GetSyntaxRootAsync(); 56 | if (syntaxRoot == null) 57 | { 58 | return VSConstants.S_FALSE; 59 | } 60 | 61 | var caretPos = textView.Caret.Position.BufferPosition; 62 | 63 | var startPosition = textView.Selection.Start.Position; 64 | var endPosition = textView.Selection.End.Position; 65 | var length = endPosition.Position - startPosition.Position; 66 | var selectionSpan = new TextSpan(startPosition.Position, length); 67 | 68 | List spans = new List(); 69 | var trivia = syntaxRoot.FindTrivia(caretPos); 70 | var token = syntaxRoot.FindToken(caretPos); 71 | var node = syntaxRoot.FindNode(new TextSpan(caretPos.Position, 0)); 72 | TextSpan currSelect = GetSyntaxSpan(trivia, token, node, new TextSpan(caretPos, 0)); 73 | while(!IsOverlap(currSelect, startPosition.Position, endPosition.Position)) 74 | { 75 | if (currSelect.Start == startPosition.Position && currSelect.End == endPosition.Position) 76 | { 77 | break; 78 | } 79 | spans.Add(currSelect); 80 | trivia = syntaxRoot.FindTrivia(currSelect.Start); 81 | token = syntaxRoot.FindToken(currSelect.Start); 82 | node = syntaxRoot.FindNode(currSelect); 83 | currSelect = GetSyntaxSpan(trivia, token, node, currSelect); 84 | } 85 | 86 | if (spans.Count > 0) 87 | { 88 | TextSpan finalSpan = spans.Last(); 89 | SetSelection(textView, finalSpan); 90 | } 91 | 92 | return VSConstants.S_OK; 93 | } 94 | 95 | private async Task HandleCommandExpandTask(IWpfTextView textView) 96 | { 97 | var syntaxRoot = await textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges().GetSyntaxRootAsync(); 98 | if (syntaxRoot == null) 99 | { 100 | return VSConstants.S_FALSE; 101 | } 102 | 103 | var startPosition = textView.Selection.Start.Position; 104 | var endPosition = textView.Selection.End.Position; 105 | var length = endPosition.Position - startPosition.Position; 106 | var selectionSpan = new TextSpan(startPosition.Position, length); 107 | 108 | var trivia = syntaxRoot.FindTrivia(startPosition.Position); 109 | var token = syntaxRoot.FindToken(startPosition.Position); 110 | var node = syntaxRoot.FindNode(selectionSpan); 111 | 112 | TextSpan finalSpan = GetSyntaxSpan(trivia, token, node, selectionSpan); 113 | 114 | SetSelection(textView, finalSpan); 115 | return VSConstants.S_OK; 116 | } 117 | 118 | private static TextSpan GetSyntaxSpan(SyntaxTrivia trivia, SyntaxToken token, SyntaxNode node, TextSpan selection) 119 | { 120 | TextSpan finalSpan; 121 | int start = selection.Start; 122 | int end = selection.End; 123 | if (trivia.RawKind != 0) // in trivia 124 | { 125 | if (IsOverlap(trivia.Span, start, end) && (trivia.RawKind == 8542 || trivia.RawKind == 8541)) // in comment so grab comment 126 | { 127 | finalSpan = trivia.Span; 128 | } 129 | else // not a comment or already selecting comment so get selection of next open/close bracket 130 | { 131 | TextSpan innerBracketSpan = GetInnerBracketSpan(node); 132 | while ((innerBracketSpan.Equals(node.Span) && node.Parent != null) || !IsOverlap(innerBracketSpan, start, end)) 133 | { 134 | node = node.Parent; 135 | innerBracketSpan = GetInnerBracketSpan(node); 136 | } 137 | // check that we are not selecting same area as current selection 138 | finalSpan = (innerBracketSpan.Equals(selection)) ? node.Span : innerBracketSpan; 139 | } 140 | } 141 | else if (IsOverlap(token.Span, start, end)) // in token. 142 | { 143 | finalSpan = token.Span; 144 | } 145 | else // in node 146 | { 147 | node = (IsOverlap(node, start, end) || node.Parent == null) ? node : node.Parent; 148 | TextSpan innerBracketSpan = GetInnerBracketSpan(node); 149 | while ((innerBracketSpan.Equals(node.Span) && node.Parent != null) || !IsOverlap(innerBracketSpan, start, end)) 150 | { 151 | if (IsOverlap(node.Parent.Span, start, end) && GetInnerBracketSpan(node.Parent).Equals(node.Parent.Span)) 152 | { 153 | return node.Span; 154 | } 155 | node = node.Parent; 156 | innerBracketSpan = GetInnerBracketSpan(node); 157 | } 158 | if (IsOverlap(innerBracketSpan, start, end)) 159 | { 160 | finalSpan = innerBracketSpan; 161 | } 162 | else 163 | { 164 | finalSpan = node.Span; 165 | } 166 | } 167 | return finalSpan; 168 | } 169 | 170 | 171 | private static TextSpan GetInnerBracketSpan(SyntaxNode node) 172 | { 173 | if (node == null || node.RawKind == 0) 174 | { 175 | return new TextSpan(0, 0); 176 | } 177 | var children = node.ChildNodesAndTokens(); 178 | // node itself not fully selected, select it first 179 | var firstBracket = children.FirstOrDefault(x => x.RawKind == 8205); 180 | var lastBracket = children.LastOrDefault(x => x.RawKind == 8206); 181 | if (firstBracket.RawKind != 0 || lastBracket.RawKind != 0) 182 | { 183 | // We found an open and close brackets. Check and see if we need to only select the insides of the brackets 184 | int start = firstBracket.Span.End; 185 | int end; 186 | SyntaxTrivia lastEOL = lastBracket.GetLeadingTrivia().LastOrDefault(x => x.RawKind == 8539); 187 | if (lastEOL.RawKind == 8539) 188 | { 189 | end = lastEOL.Span.Start; 190 | } else 191 | { 192 | var nodeOrToken = lastBracket.GetPreviousSibling(); 193 | if(nodeOrToken.IsNode) 194 | { 195 | end = nodeOrToken.AsNode().Span.End; 196 | } 197 | else if (nodeOrToken.IsToken) 198 | { 199 | end = nodeOrToken.Span.End; 200 | } else 201 | { 202 | return new TextSpan(0, 0); 203 | } 204 | } 205 | return new TextSpan(start, end - start); 206 | } 207 | return node.Span; 208 | } 209 | 210 | private static void SetSelection(IWpfTextView textView, TextSpan span) 211 | { 212 | if (span == null) 213 | { 214 | return; 215 | } 216 | 217 | var snapshot = textView.TextSnapshot; 218 | 219 | textView.Selection.Select(new SnapshotSpan(snapshot, span.Start, span.Length), false); 220 | //textView.Caret.MoveTo(new SnapshotPoint(snapshot, node.Span.End)); 221 | } 222 | 223 | private static bool IsOverlap(TextSpan span, int startPosition, int endPosition) 224 | { 225 | return span.Start < startPosition && span.End > endPosition || 226 | (span.Start == startPosition && span.End > endPosition) || 227 | (span.Start < startPosition && span.End == endPosition); 228 | } 229 | 230 | private static bool IsOverlap(SyntaxNode node, int startPosition, int endPosition) 231 | { 232 | return node.SpanStart < startPosition && node.Span.End > endPosition || 233 | (node.SpanStart == startPosition && node.Span.End > endPosition) || 234 | (node.SpanStart < startPosition && node.Span.End == endPosition); 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /HotCommands/Commands/MoveCursorToAdjacentMember.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio; 2 | using Microsoft.VisualStudio.Text.Editor; 3 | using Microsoft.CodeAnalysis.Text; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using Microsoft.VisualStudio.Text; 6 | using Microsoft.CodeAnalysis; 7 | using System.Linq; 8 | using Microsoft.VisualStudio.Text.Operations; 9 | 10 | namespace HotCommands 11 | { 12 | class MoveCursorToAdjacentMember : Command 13 | { 14 | public static int MoveToNextMember(IWpfTextView textView, IEditorOperations editorOperations) 15 | { 16 | return MoveToAdjacentMember(textView, editorOperations, up: false); 17 | } 18 | public static int MoveToPreviousMember(IWpfTextView textView, IEditorOperations editorOperations) 19 | { 20 | return MoveToAdjacentMember(textView, editorOperations, up: true); 21 | } 22 | 23 | public static int MoveToAdjacentMember( 24 | IWpfTextView textView, 25 | IEditorOperations editorOperations, 26 | bool up) 27 | { 28 | var syntaxRoot = textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges().GetSyntaxRootAsync().Result; 29 | var position = textView.Caret.Position.BufferPosition.Position; 30 | var currMember = FindDeclarationAt(syntaxRoot, position); 31 | // Check if outside of all namespaces and classes 32 | if (currMember == null) 33 | { 34 | var children = syntaxRoot.ChildNodes().OfType(); 35 | if (children.Count() < 1) 36 | { 37 | return VSConstants.S_OK; 38 | } 39 | if (up) 40 | { 41 | var last = children.Last(); 42 | if (position > last.SpanStart) 43 | { 44 | var node = last.DescendantNodesAndSelf().OfType().LastOrDefault(); 45 | MoveCursor(textView, node, editorOperations); 46 | return VSConstants.S_OK; 47 | } 48 | } 49 | else 50 | { 51 | var first = children.First(); 52 | if (position < first.SpanStart) 53 | { 54 | MoveCursor(textView, first, editorOperations); 55 | return VSConstants.S_OK; 56 | } 57 | } 58 | return VSConstants.S_OK; 59 | } 60 | // Check if inside a method 61 | // Includes all annotations and comments (trivia??) 62 | if ((position < GetCorrectPosition(currMember) && !up) || 63 | (position > GetCorrectPosition(currMember) && up)) 64 | { 65 | MoveCursor(textView, currMember, editorOperations); 66 | return VSConstants.S_OK; 67 | } 68 | MemberDeclarationSyntax MoveToNode = null; 69 | // Check if inside Namespace or class 70 | if (isContainer(currMember)) 71 | { 72 | int posInContainer = getPosInContainer(currMember, position); 73 | // The current member is a container. We need to deal with one of four (ish) possibilities: 74 | // 1. We are at the top (or it is empty) and moving up 75 | if (posInContainer <= 0 && up) 76 | { 77 | MoveToNode = getPrevious(currMember); 78 | } 79 | // 2. We are at the bottom (or it is empty) and moving down 80 | if (posInContainer >= 0 && !up) 81 | { 82 | var node = getNext(currMember); 83 | if (node != currMember) 84 | { 85 | MoveCursor(textView, node, editorOperations); 86 | } 87 | return VSConstants.S_OK; 88 | } 89 | // 3. We are at the top and moving down 90 | if (posInContainer == -1 && !up) 91 | { 92 | // go to first child member declaration 93 | MoveToNode = currMember.DescendantNodes().OfType().FirstOrDefault(); 94 | } 95 | // 4. WE are at the bottom and moving up 96 | else if (posInContainer == 1 && up) 97 | { 98 | // go to the last member 99 | MoveToNode = currMember.DescendantNodes().OfType().LastOrDefault(); 100 | } 101 | } 102 | // Else we are not in a container 103 | else 104 | { 105 | if (up) 106 | { 107 | MoveToNode = getPrevious(currMember); 108 | } 109 | else // down 110 | { 111 | var node = getNext(currMember); 112 | if (node != currMember) 113 | { 114 | MoveCursor(textView, node, editorOperations); 115 | } 116 | return VSConstants.S_OK; 117 | } 118 | } 119 | MoveCursor(textView, MoveToNode, editorOperations); 120 | return VSConstants.S_OK; 121 | } 122 | 123 | public static MemberDeclarationSyntax getNext(SyntaxNode current) 124 | { 125 | // First, go to the parent 126 | SyntaxNode Parent = current.Parent; 127 | if (Parent == null) 128 | { 129 | // We have reached the root node, there can be no siblings, and therefore there is no next 130 | return null; 131 | } 132 | bool foundSelf = false; 133 | // Iterate through parent children 134 | foreach (MemberDeclarationSyntax node in Parent.ChildNodes().OfType()) 135 | { 136 | if (!foundSelf) 137 | { 138 | // mark when we come accross our own node so that on the next one we can return it 139 | foundSelf = node.Equals(current); 140 | } 141 | else 142 | { 143 | // return the next node after we find ourselves 144 | return node; 145 | } 146 | } 147 | 148 | // If we get here, the current node was the last declaration in the parent 149 | return getNext(Parent); 150 | } 151 | 152 | public static MemberDeclarationSyntax getPrevious(SyntaxNode current) 153 | { 154 | SyntaxNode parent = current.Parent; 155 | MemberDeclarationSyntax previous = null; 156 | foreach (MemberDeclarationSyntax node in parent.ChildNodes().OfType()) 157 | { 158 | if (node.Equals(current)) 159 | { 160 | if (previous == null) 161 | { 162 | return parent.Parent != null ? (MemberDeclarationSyntax)parent : null; 163 | } 164 | if (isContainer(previous)) 165 | { 166 | return previous.DescendantNodesAndSelf().OfType().LastOrDefault(); 167 | } 168 | return previous; 169 | } 170 | previous = node; 171 | } 172 | // this should never happen. By definition the node will be found within its own parent's children 173 | return null; 174 | } 175 | 176 | public static void MoveCursor(IWpfTextView textView, MemberDeclarationSyntax node, IEditorOperations editorOperations) 177 | { 178 | if (node != null) 179 | { 180 | // move the cursor to the previous member 181 | int newCaretPosn = GetCorrectPosition(node); 182 | textView.Caret.MoveTo(new SnapshotPoint(textView.TextSnapshot, newCaretPosn)); 183 | EditorExtensions.MakeCaretVisible(textView, newCaretPosn); 184 | } 185 | } 186 | 187 | private static bool CursorInView(IWpfTextView textView) 188 | { 189 | var caretPos = textView.Caret.Position.BufferPosition.Position; 190 | return caretPos < textView.ViewportBottom && caretPos > textView.ViewportTop; 191 | } 192 | 193 | private static int GetCorrectPosition(MemberDeclarationSyntax node) 194 | { 195 | var children = node.ChildNodesAndTokens().Where(x => x.RawKind != (int)Microsoft.CodeAnalysis.CSharp.SyntaxKind.AttributeList); 196 | return children.First().SpanStart; 197 | } 198 | 199 | private static bool isContainer(MemberDeclarationSyntax currMember) 200 | { 201 | return (currMember.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.ClassDeclaration) 202 | || currMember.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.NamespaceDeclaration) 203 | && currMember.DescendantNodes().OfType().Count() > 0); 204 | } 205 | 206 | /// 207 | /// Determines if we are before or after the members of this container (or if there are none) 208 | /// 209 | /// The namespace or class SyntxNode 210 | /// The position in the text 211 | /// -1 if position is before all members, 0 if there are none, 1 if it is after all members 212 | private static int getPosInContainer(MemberDeclarationSyntax currMember, int position) 213 | { 214 | var lastMember = currMember.DescendantNodes().OfType().LastOrDefault(); 215 | if (lastMember == null) 216 | { 217 | return 0; 218 | } 219 | else if (position > lastMember.FullSpan.End) 220 | { 221 | return 1; 222 | } 223 | else 224 | { 225 | return -1; 226 | } 227 | } 228 | 229 | internal static MemberDeclarationSyntax FindDeclarationAt(SyntaxNode root, int position) 230 | { 231 | if (position > root.FullSpan.End || position < root.FullSpan.Start) 232 | { 233 | return null; 234 | } 235 | var token = root.FindToken(position, false); 236 | var member = token.Parent.AncestorsAndSelf().OfType().FirstOrDefault(); 237 | return member; 238 | } 239 | } 240 | } -------------------------------------------------------------------------------- /HotCommands/Commands/EditorExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using Microsoft.CodeAnalysis.Text; 5 | using Microsoft.VisualStudio; 6 | using Microsoft.VisualStudio.OLE.Interop; 7 | using Microsoft.VisualStudio.Text; 8 | using Microsoft.VisualStudio.Text.Editor; 9 | using Microsoft.VisualStudio.Text.Operations; 10 | using System; 11 | using System.Linq; 12 | 13 | namespace HotCommands 14 | { 15 | static class EditorExtensions 16 | { 17 | internal static int MoveMemberUp(this IWpfTextView textView, IOleCommandTarget commandTarget, IEditorOperations editorOperations) 18 | { 19 | var position = textView.Caret.Position.BufferPosition.Position; 20 | var syntaxRoot = textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges().GetSyntaxRootAsync().Result; 21 | MovePosition movePsoition = MovePosition.Top; 22 | 23 | // Find the Current member, and exit if it is outside the container 24 | var currMember = syntaxRoot.FindMemberDeclarationAt(position); 25 | if (!currMember.ContainsPosition(position)) 26 | { 27 | currMember = currMember?.Parent.AncestorsAndSelf().OfType().FirstOrDefault(); 28 | } 29 | if (currMember == null || currMember.Parent == null) return VSConstants.S_OK; 30 | 31 | //Find Previous member 32 | var prevMember = syntaxRoot.FindMemberDeclarationAt(currMember.FullSpan.Start - 1); 33 | if (prevMember.IsContainerType()) 34 | { 35 | if (prevMember.Equals(currMember.Parent)) 36 | { 37 | //Move Methods/Properties/Enum/Constructor/.. 38 | if (!currMember.IsContainerType()) 39 | { 40 | while (prevMember.IsRootNodeof(currMember) || prevMember.IsKind(SyntaxKind.NamespaceDeclaration)) //untill valid 41 | { 42 | prevMember = syntaxRoot.FindMemberDeclarationAt(prevMember.FullSpan.Start - 1); 43 | prevMember = prevMember.IsRootNodeof(currMember) ? prevMember : prevMember.GetNextChildMember(true); 44 | if (prevMember == null) return VSConstants.S_OK; 45 | } 46 | movePsoition = prevMember.IsContainerType() ? MovePosition.MiddlefromBottom : MovePosition.Bottom; 47 | } 48 | } 49 | else //prev member is Sibling 50 | { 51 | prevMember.GetNextChildMember(true); 52 | movePsoition = prevMember.IsContainerType() ? MovePosition.MiddlefromBottom : MovePosition.Bottom; 53 | } 54 | } 55 | 56 | int newCaretPosn = textView.SwapMembers(currMember, prevMember, movePsoition, MoveDirection.Up, commandTarget, editorOperations); 57 | MakeCaretVisible(textView, newCaretPosn); 58 | return VSConstants.S_OK; 59 | } 60 | 61 | internal static int MoveMemberDown(this IWpfTextView textView, IOleCommandTarget commandTarget, IEditorOperations editorOperations) 62 | { 63 | var position = textView.Caret.Position.BufferPosition.Position; 64 | var syntaxRoot = textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges().GetSyntaxRootAsync().Result; 65 | MovePosition movePsoition = MovePosition.Bottom; 66 | 67 | // Find the Current member, and exit if it is outside the container 68 | var currMember = syntaxRoot.FindMemberDeclarationAt(position); 69 | if (!currMember.ContainsPosition(position)) 70 | { 71 | currMember = currMember?.Parent.AncestorsAndSelf().OfType().FirstOrDefault(); 72 | } 73 | if (currMember == null || currMember.Parent == null) return VSConstants.S_OK; 74 | 75 | //Find next member 76 | var nextMember = syntaxRoot.FindMemberDeclarationAt(currMember.FullSpan.End + 1); 77 | if (nextMember.IsContainerType()) 78 | { 79 | if (nextMember.Equals(currMember.Parent)) 80 | { 81 | //if Moving Methods,Properties,Enum,Constructor,.. (excludes class, interface, struct,..) 82 | if (!currMember.IsContainerType()) 83 | { 84 | while (nextMember.IsRootNodeof(currMember) || nextMember.IsKind(SyntaxKind.NamespaceDeclaration)) //untill valid 85 | { 86 | nextMember = syntaxRoot.FindMemberDeclarationAt(nextMember.FullSpan.End + 1); 87 | nextMember = nextMember.IsRootNodeof(currMember) ? nextMember : nextMember.GetNextChildMember(false); 88 | if (nextMember == null) return VSConstants.S_OK; 89 | } 90 | movePsoition = nextMember.IsContainerType() ? MovePosition.MiddlefromTop : MovePosition.Top; 91 | } 92 | } 93 | else //Next member is Sibling 94 | { 95 | nextMember.GetNextChildMember(false); 96 | movePsoition = nextMember.IsContainerType() ? MovePosition.MiddlefromTop : MovePosition.Top; 97 | } 98 | } 99 | 100 | int newCaretPosn = textView.SwapMembers(currMember, nextMember, movePsoition, MoveDirection.Down, commandTarget, editorOperations); 101 | MakeCaretVisible(textView, newCaretPosn); 102 | return VSConstants.S_OK; 103 | } 104 | 105 | public static void MakeCaretVisible(IWpfTextView textView, int newCaretPosn) 106 | { 107 | if (newCaretPosn < 0) return; 108 | SnapshotSpan spanToMakeVisible = new SnapshotSpan(textView.TextSnapshot, newCaretPosn, 1); 109 | textView.ViewScroller.EnsureSpanVisible(spanToMakeVisible, EnsureSpanVisibleOptions.None); 110 | } 111 | 112 | private static void FormatDocument(IOleCommandTarget commandTarget) 113 | { 114 | Guid cmdGroup = VSConstants.VSStd2K; 115 | uint cmdID = (uint)VSConstants.VSStd2KCmdID.FORMATDOCUMENT; 116 | int hr = commandTarget.Exec(ref cmdGroup, cmdID, (uint)OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, IntPtr.Zero, IntPtr.Zero); 117 | } 118 | 119 | private static int SwapMembers(this IWpfTextView textView, SyntaxNode member1, SyntaxNode member2, MovePosition position, MoveDirection direction, IOleCommandTarget commandTarget, IEditorOperations editorOperations) 120 | { 121 | if (member1 == null || member2 == null) return -1; 122 | int caretIndent = textView.Caret.Position.BufferPosition.Position - member1.FullSpan.Start; 123 | int movePosition = 0; 124 | string moveText = member1.GetText().ToString(); 125 | 126 | //Find the position to Move the Current method (i.e. member1) 127 | if (position == MovePosition.Top) 128 | { 129 | movePosition = member2.FullSpan.Start; 130 | } 131 | else if (position == MovePosition.Bottom) 132 | { 133 | movePosition = member2.FullSpan.End; 134 | } 135 | else if (position == MovePosition.MiddlefromBottom) 136 | { 137 | movePosition = member2.ChildTokens().FirstOrDefault(t => t.IsKind(SyntaxKind.CloseBraceToken)).SpanStart - 1; 138 | } 139 | else if (position == MovePosition.MiddlefromTop) 140 | { 141 | movePosition = member2.ChildTokens().FirstOrDefault(t => t.IsKind(SyntaxKind.OpenBraceToken)).SpanStart + 1; 142 | } 143 | 144 | var editor = textView.TextSnapshot.TextBuffer.CreateEdit(); 145 | editor.Delete(member1.FullSpan.Start, member1.FullSpan.Length); 146 | editor.Insert(movePosition, moveText); 147 | editor.Apply(); 148 | 149 | int newCaretPosition = direction == MoveDirection.Up ? (movePosition + caretIndent) : (movePosition + caretIndent - moveText.Length); 150 | textView.Caret.MoveTo(new SnapshotPoint(textView.TextSnapshot, newCaretPosition)); 151 | textView.Selection.Select(new SnapshotSpan(textView.TextSnapshot, (direction == MoveDirection.Up) ? movePosition : movePosition - moveText.Length, moveText.Length), false); 152 | FormatDocument(commandTarget); 153 | textView.Selection.Clear(); 154 | 155 | return newCaretPosition; 156 | } 157 | 158 | private static MemberDeclarationSyntax GetNextChildMember(this MemberDeclarationSyntax member, bool moveFromBottom) 159 | { 160 | var childMembers = member?.ChildNodes().OfType(); 161 | while (childMembers?.Count() > 0 && !member.IsKind(SyntaxKind.EnumDeclaration)) 162 | { 163 | member = moveFromBottom ? childMembers.Last() : childMembers.First(); 164 | childMembers = member.ChildNodes().OfType(); 165 | } 166 | return member; 167 | } 168 | 169 | private static MemberDeclarationSyntax FindMemberDeclarationAt(this SyntaxNode root, int position) 170 | { 171 | if (position > root.FullSpan.End || position < root.FullSpan.Start) return null; 172 | var token = root.FindToken(position, false); 173 | var member = token.Parent.AncestorsAndSelf().OfType().FirstOrDefault(); 174 | 175 | //If the caret is at EnumDeclaration, entire EnumMemberDeclaration as a Member declaration 176 | member = member.IsKind(SyntaxKind.EnumMemberDeclaration) ? member.Parent.AncestorsAndSelf().OfType().FirstOrDefault() : member; 177 | return member; 178 | } 179 | 180 | private static bool ContainsPosition(this MemberDeclarationSyntax currMember, int caretPosition) 181 | { 182 | var trivia = currMember?.GetFirstToken().LeadingTrivia; 183 | foreach (var t in trivia) 184 | { 185 | if (t.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) || t.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia) || t.IsKind(SyntaxKind.SingleLineCommentTrivia) || t.IsKind(SyntaxKind.MultiLineCommentTrivia)) 186 | { 187 | break; 188 | } 189 | if (t.IsKind(SyntaxKind.EndOfLineTrivia) && t.Span.Start <= caretPosition && t.Span.End >= caretPosition) 190 | { 191 | return false; 192 | } 193 | } 194 | return true; 195 | } 196 | 197 | private static bool IsRootNodeof(this SyntaxNode member, SyntaxNode currentMember) 198 | { 199 | while (currentMember.Parent != null) 200 | { 201 | if (currentMember.Parent.Equals(member)) 202 | { 203 | return true; 204 | } 205 | currentMember = currentMember.Parent; 206 | } 207 | return false; 208 | } 209 | 210 | private static bool IsContainerType(this SyntaxNode node) 211 | { 212 | return node.IsKind(SyntaxKind.ClassDeclaration) || node.IsKind(SyntaxKind.StructDeclaration) || node.IsKind(SyntaxKind.InterfaceDeclaration) || node.IsKind(SyntaxKind.NamespaceDeclaration); 213 | } 214 | 215 | private enum MovePosition 216 | { 217 | Top, 218 | Bottom, 219 | MiddlefromBottom, 220 | MiddlefromTop 221 | } 222 | 223 | private enum MoveDirection 224 | { 225 | Up, 226 | Down 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /HotCommands/HotCommandsPackage.vsct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 53 | 54 | 61 | 62 | 71 | 72 | 81 | 90 | 99 | 108 | 109 | 118 | 119 | 127 | 135 | 136 | 143 | 144 | 151 | 158 | 159 | 166 | 173 | 174 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /HotCommands/Packaging/License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 2 | {\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f40\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Segoe UI;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 3 | {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} 4 | {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 5 | {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} 6 | {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f42\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 7 | {\f44\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f45\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f46\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f47\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 8 | {\f48\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f49\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f41\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f42\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 9 | {\f44\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f45\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f46\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f47\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 10 | {\f48\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f49\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f431\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f432\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} 11 | {\f434\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f435\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f436\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f437\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);} 12 | {\f438\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f439\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f441\fbidi \fswiss\fcharset238\fprq2 Segoe UI CE;}{\f442\fbidi \fswiss\fcharset204\fprq2 Segoe UI Cyr;} 13 | {\f444\fbidi \fswiss\fcharset161\fprq2 Segoe UI Greek;}{\f445\fbidi \fswiss\fcharset162\fprq2 Segoe UI Tur;}{\f446\fbidi \fswiss\fcharset177\fprq2 Segoe UI (Hebrew);}{\f447\fbidi \fswiss\fcharset178\fprq2 Segoe UI (Arabic);} 14 | {\f448\fbidi \fswiss\fcharset186\fprq2 Segoe UI Baltic;}{\f449\fbidi \fswiss\fcharset163\fprq2 Segoe UI (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 15 | {\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 16 | {\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 17 | {\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 18 | {\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 19 | {\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 20 | {\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;} 21 | {\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);} 22 | {\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 23 | {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 24 | {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 25 | {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 26 | {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 27 | {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 28 | {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} 29 | {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 30 | {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} 31 | {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} 32 | {\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} 33 | {\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 34 | {\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 35 | {\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} 36 | {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; 37 | \red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f31506\fs22 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1 38 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 39 | \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* 40 | \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 41 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}} 42 | {\*\rsidtbl \rsid538951\rsid612962\rsid1639629\rsid2229665\rsid3373281\rsid4148663\rsid8420212\rsid10361784}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info 43 | {\author Justin Clareburt}{\operator Justin Clareburt}{\creatim\yr2016\mo5\dy20\hr19\min18}{\revtim\yr2016\mo11\dy14\hr22\min9}{\version6}{\edmins4}{\nofpages1}{\nofwords20}{\nofchars116}{\nofcharsws135}{\vern11}}{\*\xmlnstbl {\xmlns1 http://schemas.micro 44 | soft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect 45 | \widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen 46 | \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1 47 | \jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct 48 | \asianbrkrule\rsidroot10361784\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0 49 | {\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sectrsid4148663\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}} 50 | {\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (} 51 | {\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar 52 | \ql \li0\ri0\widctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid612962 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af40\afs18 \ltrch\fcs0 53 | \b\f40\fs18\cf1\insrsid1639629\charrsid1639629 Hot }{\rtlch\fcs1 \af40\afs18 \ltrch\fcs0 \b\f40\fs18\cf1\insrsid8420212 Commands for Visual Studio}{\rtlch\fcs1 \af40\afs18 \ltrch\fcs0 \b\f40\fs18\cf1\insrsid1639629 54 | \par }{\rtlch\fcs1 \af40\afs18 \ltrch\fcs0 \f40\fs18\cf1\insrsid8420212 55 | \par }{\rtlch\fcs1 \af40\afs18 \ltrch\fcs0 \f40\fs18\cf1\insrsid612962 \'a9 2016 Justin Clareburt 56 | \par }{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f40\fs18\cf1\insrsid1639629 57 | \par }{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f40\fs18\cf1\insrsid612962 This extension is provided "as is" with no warranties, and confers no rights. 58 | \par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid612962 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2229665\charrsid612962 59 | \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 60 | 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 61 | 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 62 | b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 63 | 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 64 | a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f 65 | c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 66 | 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 67 | a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 68 | 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b 69 | 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b 70 | 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210007b740aaca0600008f1a0000160000007468656d652f7468656d652f 71 | 7468656d65312e786d6cec595b8bdb46147e2ff43f08bd3bbe49be2cf1065bb69336bb49889d943cceda636bb2238dd18c776342a0244f7d2914d2d28706fad6 72 | 87521a68a0a12ffd310b1bdaf447f4cc489667ec71f6420aa1640d8b34face996fce39face48ba7aed51449d239c70c2e2965bbe52721d1c8fd898c4d3967b6f 73 | d82f345c870b148f1165316eb90bccdd6bbb9f7e7215ed881047d801fb98efa0961b0a31db2916f9088611bfc26638866b13964448c069322d8e13740c7e235a 74 | ac944ab5628448ec3a318ac0ededc9848cb033942edddda5f31e85d358703930a2c940bac68685c28e0fcb12c1173ca089738468cb8579c6ec78881f09d7a188 75 | 0bb8d0724beacf2dee5e2da29dcc888a2db69a5d5ffd657699c1f8b0a2e64ca607f9a49ee77bb576ee5f01a8d8c4f5eabd5aaf96fb5300341ac14a532eba4fbf 76 | d3ec74fd0cab81d2438bef6ebd5b2d1b78cd7f758373db973f03af40a97f6f03dfef07104503af4029dedfc07b5ebd1278065e81527c6d035f2fb5bb5eddc02b 77 | 5048497cb8812ef9b56ab05c6d0e99307ac30a6ffa5ebf5ec99caf50500d7975c929262c16db6a2d420f59d2078004522448ec88c50c4fd008aa3840941c24c4 78 | d923d3100a6f8662c661b85429f54b55f82f7f9e3a5211413b1869d6921730e11b43928fc34709998996fb39787535c8e9ebd7274f5f9d3cfdfde4d9b393a7bf 79 | 66732b5786dd0d144f75bbb73f7df3cf8b2f9dbf7ffbf1edf36fd3a9d7f15cc7bff9e5ab377ffcf92ef7b0e255284ebf7bf9e6d5cbd3efbffeebe7e716efed04 80 | 1de8f0218930776ee163e72e8b608116fef820b998c5304444b768c7538e622467b1f8ef89d040df5a208a2cb80e36e3783f01a9b101afcf1f1a8407613217c4 81 | e2f1661819c07dc6688725d628dc947369611ecee3a97df264aee3ee2274649b3b40b191e5de7c061a4b6c2e83101b34ef50140b34c531168ebcc60e31b6acee 82 | 0121465cf7c928619c4d84f380381d44ac21199203a39a56463748047959d80842be8dd8ecdf773a8cda56ddc5472612ee0d442de487981a61bc8ee602453697 83 | 4314513de07b48843692834532d2713d2e20d3534c99d31b63ce6d36b71358af96f49b2033f6b4efd345642213410e6d3ef710633ab2cb0e831045331b7640e2 84 | 50c77ec60fa144917387091b7c9f9977883c873ca0786bbaef136ca4fb6c35b8070aab535a1588bc324f2cb9bc8e9951bf83059d20aca4061a80a1eb1189cf14 85 | f93579f7ff3b7907113dfde1856545ef47d2ed8e8d7c5c50ccdb09b1de4d37d6247c1b6e5db803968cc987afdb5d348fef60b855369bd747d9fe28dbeeff5eb6 86 | b7ddcfef5fac57fa0cd22db7ade9765d6ddea3ad7bf709a174201614ef71b57de7d095c67d189476eab915e7cf72b3100ee59d0c1318b86982948d9330f10511 87 | e1204433d8e3975de964ca33d753eecc1887adbf1ab6fa96783a8ff6d9387d642d97e5e3692a1e1c89d578c9cfc7e17143a4e85a7df51896bb576ca7ea717949 88 | 40da5e8484369949a26a21515f0eca20a98773089a85845ad97b61d1b4b06848f7cb546db0006a795660dbe4c066abe5fa1e9880113c55218ac7324f69aa97d9 89 | 55c97c9f99de164ca302600fb1ac8055a69b92ebd6e5c9d5a5a5768e4c1b24b4723349a8c8a81ec64334c65975cad1f3d0b868ae9bab941af46428d47c505a2b 90 | 1af5c6bb585c36d760b7ae0d34d69582c6ce71cbad557d2899119ab5dc093cfac3613483dae172bb8be814de9f8d4492def097519659c24517f1300db8129d54 91 | 0d222270e25012b55cb9fc3c0d34561aa2b8952b20081f2cb926c8ca87460e926e26194f267824f4b46b2332d2e929287caa15d6abcafcf26069c9e690ee4138 92 | 3e760ee83cb98ba0c4fc7a5906704c38bc012aa7d11c1378a5990bd9aafed61a5326bbfa3b455543e938a2b310651d4517f314aea43ca7a3cef2186867d99a21 93 | a05a48b2467830950d560faad14df3ae9172d8da75cf369291d34473d5330d55915dd3ae62c60ccb36b016cbcb35798dd532c4a0697a874fa57b5d729b4bad5b 94 | db27e45d02029ec7cfd275cfd110346aabc90c6a92f1a60c4bcdce46cddeb15ce019d4ced32434d5af2dddaec52def11d6e960f0529d1fecd6ab168626cb7da5 95 | 8ab4faf6a17f9e60070f413cbaf022784e0557a9848f0f09820dd140ed4952d9805be491c86e0d3872e60969b98f4b7edb0b2a7e502835fc5ec1ab7aa542c36f 96 | 570b6ddfaf967b7eb9d4ed549e4063116154f6d3ef2e7d780d4517d9d71735bef105265abe69bb32625191a92f2c45455c7d812957b67f81710888cee35aa5df 97 | ac363bb542b3daee17bc6ea7516806b54ea15b0beadd7e37f01bcdfe13d7395260af5d0dbc5aaf51a89583a0e0d54a927ea359a87b954adbabb71b3daffd24db 98 | c6c0ca53f9c86201e155bc76ff050000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72 99 | 656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c08 100 | 2e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd0 101 | 8a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa 102 | 4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f 103 | 6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72 104 | 656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f746865 105 | 6d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210007b740aaca0600008f1a00001600000000000000000000000000d60200 106 | 007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000000000000000000000 107 | 00d40900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cf0a00000000} 108 | {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 109 | 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 110 | 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 111 | 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} 112 | {\*\latentstyles\lsdstimax372\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; 113 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; 114 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; 115 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; 116 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; 117 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; 118 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; 119 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; 120 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; 121 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; 122 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; 123 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; 124 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; 125 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; 126 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; 127 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; 128 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; 129 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; 130 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; 131 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; 132 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; 133 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; 134 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; 135 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; 136 | \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; 137 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; 138 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; 139 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; 140 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; 141 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; 142 | \lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; 143 | \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; 144 | \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; 145 | \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; 146 | \lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; 147 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; 148 | \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; 149 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; 150 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; 151 | \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; 152 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; 153 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; 154 | \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; 155 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; 156 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; 157 | \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; 158 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; 159 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; 160 | \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; 161 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; 162 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; 163 | \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; 164 | \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; 165 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; 166 | \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; 167 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; 168 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; 169 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; 170 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; 171 | \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; 172 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; 173 | \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; 174 | \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; 175 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; 176 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; 177 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; 178 | \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; 179 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; 180 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; 181 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; 182 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; 183 | \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; 184 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; 185 | \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; 186 | \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; 187 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; 188 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; 189 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention;}}{\*\datastore 0105000002000000 190 | 180000004d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 191 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 192 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 193 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 194 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 195 | fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 196 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 197 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 198 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 199 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000f0f3 200 | a8d1063fd201feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 201 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 202 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 203 | 0000000000000000000000000000000000000000000000000105000000000000}} --------------------------------------------------------------------------------