]> granicus.if.org Git - clang/commitdiff
clang-format-vsix: add command to format document
authorAntonio Maiorano <amaiorano@gmail.com>
Fri, 16 Dec 2016 01:51:43 +0000 (01:51 +0000)
committerAntonio Maiorano <amaiorano@gmail.com>
Fri, 16 Dec 2016 01:51:43 +0000 (01:51 +0000)
Bound to Ctrl+R, Ctrl+D by default. Also added section on how to debug the extension to the Readme.

Differential Revision: https://reviews.llvm.org/D27501

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289910 91177308-0d34-0410-b5e6-96231b3b80d8

tools/clang-format-vs/.gitignore
tools/clang-format-vs/ClangFormat/ClangFormat.vsct
tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
tools/clang-format-vs/ClangFormat/PkgCmdID.cs
tools/clang-format-vs/README.txt

index 6453dd8ecef2f3e9833b089e9cbb15258f62c7aa..c9d25d96c8ecdd1be9bc755f45998fd336106eef 100644 (file)
@@ -1,5 +1,6 @@
 # Visual Studio files
 .vs/
+*.user
 /packages/
 /ClangFormat/obj/
 /ClangFormat/bin/
index 3e3e22e67d42f5523f9a7cf140f12ebacb570080..798957740d548c1b354de197be691602e5c17a0b 100644 (file)
               <CommandFlag>DynamicVisibility</CommandFlag>\r
           If you do not want an image next to your command, remove the Icon node /> -->\r
 \r
-      <Button guid="guidClangFormatCmdSet" id="cmdidClangFormat" priority="0x0100" type="Button">\r
+      <Button guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" priority="0x0100" type="Button">\r
         <Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />\r
         <Icon guid="guidImages" id="bmpPic1" />\r
         <Strings>\r
-          <ButtonText>ClangFormat</ButtonText>\r
+          <ButtonText>Clang Format Selection</ButtonText>\r
         </Strings>\r
       </Button>\r
 \r
-\r
+      <Button guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" priority="0x0101" type="Button">\r
+        <Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />\r
+        <Icon guid="guidImages" id="bmpPic2" />\r
+        <Strings>\r
+          <ButtonText>Clang Format Document</ButtonText>\r
+        </Strings>\r
+      </Button>\r
 \r
     </Buttons>\r
    \r
@@ -88,7 +94,8 @@
 \r
 \r
   <KeyBindings>\r
-    <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormat" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>\r
+    <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>\r
+    <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" editor="guidTextEditor" key1="R" mod1="Control" key2="D" mod2="Control"/>\r
   </KeyBindings>\r
 \r
 \r
     <GuidSymbol name="guidClangFormatCmdSet" value="{e39cbab1-0f96-4022-a2bc-da5a9db7eb78}">\r
 \r
       <IDSymbol name="MyMenuGroup" value="0x1020" />\r
-      <IDSymbol name="cmdidClangFormat" value="0x0100" />\r
+      <IDSymbol name="cmdidClangFormatSelection" value="0x0100" />\r
+      <IDSymbol name="cmdidClangFormatDocument" value="0x0101" />\r
     </GuidSymbol>\r
 \r
     <GuidSymbol name="guidTextEditor" value="{8B382828-6202-11d1-8870-0000F87579D2}" />\r
index 6af2fd177f0fec361b1b6c2e4883e7f50f7167df..c7eac42211adaf3d20dc3fc3b37dbd910e5559ae 100644 (file)
@@ -180,14 +180,43 @@ namespace LLVM.ClangFormat
             var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;\r
             if (commandService != null)\r
             {\r
-                var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormat);\r
-                var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
-                commandService.AddCommand(menuItem);\r
+                {\r
+                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatSelection);\r
+                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
+                    commandService.AddCommand(menuItem);\r
+                }\r
+\r
+                {\r
+                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatDocument);\r
+                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
+                    commandService.AddCommand(menuItem);\r
+                }\r
             }\r
         }\r
         #endregion\r
 \r
         private void MenuItemCallback(object sender, EventArgs args)\r
+        {\r
+            var mc = sender as System.ComponentModel.Design.MenuCommand;\r
+            if (mc == null)\r
+                return;\r
+\r
+            switch (mc.CommandID.ID)\r
+            {\r
+                case (int)PkgCmdIDList.cmdidClangFormatSelection:\r
+                    FormatSelection();\r
+                    break;\r
+\r
+                case (int)PkgCmdIDList.cmdidClangFormatDocument:\r
+                    FormatDocument();\r
+                    break;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Runs clang-format on the current selection\r
+        /// </summary>\r
+        private void FormatSelection()\r
         {\r
             IWpfTextView view = GetCurrentView();\r
             if (view == null)\r
@@ -197,24 +226,40 @@ namespace LLVM.ClangFormat
             int start = view.Selection.Start.Position.GetContainingLine().Start.Position;\r
             int end = view.Selection.End.Position.GetContainingLine().End.Position;\r
             int length = end - start;\r
+            \r
             // clang-format doesn't support formatting a range that starts at the end\r
             // of the file.\r
             if (start >= text.Length && text.Length > 0)\r
                 start = text.Length - 1;\r
             string path = GetDocumentParent(view);\r
             string filePath = GetDocumentPath(view);\r
+\r
+            RunClangFormatAndApplyReplacements(text, start, length, path, filePath, view);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Runs clang-format on the current document\r
+        /// </summary>\r
+        private void FormatDocument()\r
+        {\r
+            IWpfTextView view = GetCurrentView();\r
+            if (view == null)\r
+                // We're not in a text view.\r
+                return;\r
+\r
+            string filePath = GetDocumentPath(view);\r
+            var path = Path.GetDirectoryName(filePath);\r
+            string text = view.TextBuffer.CurrentSnapshot.GetText();\r
+\r
+            RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, view);\r
+        }\r
+\r
+        private void RunClangFormatAndApplyReplacements(string text, int offset, int length, string path, string filePath, IWpfTextView view)\r
+        {\r
             try\r
             {\r
-                var root = XElement.Parse(RunClangFormat(text, start, length, path, filePath));\r
-                var edit = view.TextBuffer.CreateEdit();\r
-                foreach (XElement replacement in root.Descendants("replacement"))\r
-                {\r
-                    var span = new Span(\r
-                        int.Parse(replacement.Attribute("offset").Value),\r
-                        int.Parse(replacement.Attribute("length").Value));\r
-                    edit.Replace(span, replacement.Value);\r
-                }\r
-                edit.Apply();\r
+                string replacements = RunClangFormat(text, offset, length, path, filePath);\r
+                ApplyClangFormatReplacements(replacements, view);\r
             }\r
             catch (Exception e)\r
             {\r
@@ -304,6 +349,27 @@ namespace LLVM.ClangFormat
             return output;\r
         }\r
 \r
+        /// <summary>\r
+        /// Applies the clang-format replacements (xml) to the current view\r
+        /// </summary>\r
+        private void ApplyClangFormatReplacements(string replacements, IWpfTextView view)\r
+        {\r
+            // clang-format returns no replacements if input text is empty\r
+            if (replacements.Length == 0)\r
+                return;\r
+\r
+            var root = XElement.Parse(replacements);\r
+            var edit = view.TextBuffer.CreateEdit();\r
+            foreach (XElement replacement in root.Descendants("replacement"))\r
+            {\r
+                var span = new Span(\r
+                    int.Parse(replacement.Attribute("offset").Value),\r
+                    int.Parse(replacement.Attribute("length").Value));\r
+                edit.Replace(span, replacement.Value);\r
+            }\r
+            edit.Apply();\r
+        }\r
+\r
         /// <summary>\r
         /// Returns the currently active view if it is a IWpfTextView.\r
         /// </summary>\r
index bb6b4559a98ddb46be727f4ee68a699e188753bf..fcc31ee95b1e47ee02333c54c384cb550c1cd891 100644 (file)
@@ -2,6 +2,7 @@
 {\r
     static class PkgCmdIDList\r
     {\r
-        public const uint cmdidClangFormat = 0x100;\r
+        public const uint cmdidClangFormatSelection = 0x100;\r
+        public const uint cmdidClangFormatDocument = 0x101;\r
     };\r
 }
\ No newline at end of file
index edfffed774c1570d46da00f111b95582df1a1a66..84e0b451f018df7b4d36de5a923c2b824eb63218 100644 (file)
@@ -25,3 +25,27 @@ directory so they can be bundled with the plug-in, as well as creating
 ClangFormat/source.extension.vsixmanifest. Once the plug-in has been built with\r
 CMake once, it can be built manually from the ClangFormat.sln solution in Visual\r
 Studio.\r
+\r
+===========\r
+ Debugging\r
+===========\r
+\r
+Once you've built the clang_format_vsix project from LLVM.sln at least once,\r
+open ClangFormat.sln in Visual Studio, then:\r
+\r
+- Make sure the "Debug" target is selected\r
+- Open the ClangFormat project properties\r
+- Select the Debug tab\r
+- Set "Start external program:" to where your devenv.exe is installed. Typically\r
+  it's "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"\r
+- Set "Command line arguments" to: /rootsuffix Exp\r
+- You can now set breakpoints if you like\r
+- Press F5 to build and run with debugger\r
+\r
+If all goes well, a new instance of Visual Studio will be launched in a special\r
+mode where it uses the experimental hive instead of the normal configuration hive.\r
+By default, when you build a VSIX project in Visual Studio, it auto-registers the\r
+extension in the experimental hive, allowing you to test it. In the new Visual Studio\r
+instance, open or create a C++ solution, and you should now see the Clang Format\r
+entries in the Tool menu. You can test it out, and any breakpoints you set will be\r
+hit where you can debug as usual.\r