<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
\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
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
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
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
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