115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek//===-- ClangFormatPackages.cs - VSPackage for clang-format ------*- C# -*-===// 215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// 315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// The LLVM Compiler Infrastructure 415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// 515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// This file is distributed under the University of Illinois Open Source 615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// License. See LICENSE.TXT for details. 715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// 815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek//===----------------------------------------------------------------------===// 915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// 1015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// This class contains a VS extension package that runs clang-format over a 1115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// selection in a VS text editor. 1215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek// 1315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek//===----------------------------------------------------------------------===// 1415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 1515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.Editor; 1615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.Shell; 1715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.Shell.Interop; 1815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.Text; 1915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.Text.Editor; 2015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing Microsoft.VisualStudio.TextManager.Interop; 2115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System; 2215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System.ComponentModel; 2315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System.ComponentModel.Design; 2415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System.IO; 25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesusing System.Reflection; 2615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System.Runtime.InteropServices; 2715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimekusing System.Xml.Linq; 2815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 2915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimeknamespace LLVM.ClangFormat 3015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek{ 3115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [ClassInterface(ClassInterfaceType.AutoDual)] 3215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [CLSCompliant(false), ComVisible(true)] 3315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek public class OptionPageGrid : DialogPage 3415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 3515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private string style = "File"; 3615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 3715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [Category("LLVM/Clang")] 3815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [DisplayName("Style")] 3915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [Description("Coding style, currently supports:\n" + 4015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla').\n" + 419a7a50eef777765e4d20e3b1f3670b32582114fbHans Wennborg " - 'File' to search for a YAML .clang-format or _clang-format\n" + 429a7a50eef777765e4d20e3b1f3670b32582114fbHans Wennborg " configuration file.\n" + 4315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " - A YAML configuration snippet.\n\n" + 4415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek "'File':\n" + 459a7a50eef777765e4d20e3b1f3670b32582114fbHans Wennborg " Searches for a .clang-format or _clang-format configuration file\n" + 469a7a50eef777765e4d20e3b1f3670b32582114fbHans Wennborg " in the source file's directory and its parents.\n\n" + 4715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek "YAML configuration snippet:\n" + 4815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " The content of a .clang-format configuration file, as string.\n" + 4915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " Example: '{BasedOnStyle: \"LLVM\", IndentWidth: 8}'\n\n" + 5015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek "See also: http://clang.llvm.org/docs/ClangFormatStyleOptions.html.")] 5115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek public string Style 5215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 5315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek get { return style; } 5415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek set { style = value; } 5515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 5615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 5715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 5815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [PackageRegistration(UseManagedResourcesOnly = true)] 5915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] 6015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [ProvideMenuResource("Menus.ctmenu", 1)] 6115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [Guid(GuidList.guidClangFormatPkgString)] 6215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek [ProvideOptionPage(typeof(OptionPageGrid), "LLVM/Clang", "ClangFormat", 0, 0, true)] 6315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek public sealed class ClangFormatPackage : Package 6415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 6515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek #region Package Members 6615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek protected override void Initialize() 6715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 6815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek base.Initialize(); 6915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 7015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 7115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (commandService != null) 7215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 7315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormat); 7415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var menuItem = new MenuCommand(MenuItemCallback, menuCommandID); 7515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek commandService.AddCommand(menuItem); 7615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 7715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 7815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek #endregion 7915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 8015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private void MenuItemCallback(object sender, EventArgs args) 8115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 8215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek IWpfTextView view = GetCurrentView(); 8315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (view == null) 8415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // We're not in a text view. 8515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return; 8615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek string text = view.TextBuffer.CurrentSnapshot.GetText(); 8715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int start = view.Selection.Start.Position.GetContainingLine().Start.Position; 8815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int end = view.Selection.End.Position.GetContainingLine().End.Position; 8915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int length = end - start; 9015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // clang-format doesn't support formatting a range that starts at the end 9115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // of the file. 9215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (start >= text.Length && text.Length > 0) 9315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek start = text.Length - 1; 9415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek string path = GetDocumentParent(view); 9515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek try 9615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 9715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var root = XElement.Parse(RunClangFormat(text, start, length, path)); 9815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var edit = view.TextBuffer.CreateEdit(); 9915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek foreach (XElement replacement in root.Descendants("replacement")) 10015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 10115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var span = new Span( 10215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int.Parse(replacement.Attribute("offset").Value), 10315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int.Parse(replacement.Attribute("length").Value)); 10415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek edit.Replace(span, replacement.Value); 10515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 10615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek edit.Apply(); 10715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 10815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek catch (Exception e) 10915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 11015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); 11115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var id = Guid.Empty; 11215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek int result; 11315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek uiShell.ShowMessageBox( 11415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 0, ref id, 11515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek "Error while running clang-format:", 11615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek e.Message, 11715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek string.Empty, 0, 11815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek OLEMSGBUTTON.OLEMSGBUTTON_OK, 11915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, 12015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek OLEMSGICON.OLEMSGICON_INFO, 12115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 0, out result); 12215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 12315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 12415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 12515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// <summary> 12615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// Runs the given text through clang-format and returns the replacements as XML. 12715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// 12815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// Formats the text range starting at offset of the given length. 12915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// </summary> 13015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private string RunClangFormat(string text, int offset, int length, string path) 13115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines string vsixPath = Path.GetDirectoryName( 133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines typeof(ClangFormatPackage).Assembly.Location); 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 13515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek System.Diagnostics.Process process = new System.Diagnostics.Process(); 13615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.UseShellExecute = false; 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines process.StartInfo.FileName = vsixPath + "\\clang-format.exe"; 13815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // Poor man's escaping - this will not work when quotes are already escaped 13915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // in the input (but we don't need more). 14015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek string style = GetStyle().Replace("\"", "\\\""); 14115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.Arguments = " -offset " + offset + 14215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " -length " + length + 14315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " -output-replacements-xml " + 14415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek " -style \"" + style + "\""; 14515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.CreateNoWindow = true; 14615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.RedirectStandardInput = true; 14715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.RedirectStandardOutput = true; 14815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.RedirectStandardError = true; 14915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (path != null) 15015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StartInfo.WorkingDirectory = path; 15115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // We have to be careful when communicating via standard input / output, 15215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // as writes to the buffers will block until they are read from the other side. 15315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // Thus, we: 15415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // 1. Start the process - clang-format.exe will start to read the input from the 15515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // standard input. 15622d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek try 15722d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek { 15822d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek process.Start(); 15922d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek } 16022d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek catch (Exception e) 16122d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek { 16222d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek throw new Exception( 16322d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek "Cannot execute " + process.StartInfo.FileName + ".\n\"" + 16422d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek e.Message + "\".\nPlease make sure it is on the PATH."); 16522d58ddc9e3cb01ef2d736a27759cda39a336b95Manuel Klimek } 16615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // 2. We write everything to the standard output - this cannot block, as clang-format 16715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // reads the full standard input before analyzing it without writing anything to the 16815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // standard output. 16915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StandardInput.Write(text); 17015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // 3. We notify clang-format that the input is done - after this point clang-format 17115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // will start analyzing the input and eventually write the output. 17215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.StandardInput.Close(); 17315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // 4. We must read clang-format's output before waiting for it to exit; clang-format 17415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // will close the channel by exiting. 17515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek string output = process.StandardOutput.ReadToEnd(); 17615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // 5. clang-format is done, wait until it is fully shut down. 17715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek process.WaitForExit(); 17815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (process.ExitCode != 0) 17915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 18015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // FIXME: If clang-format writes enough to the standard error stream to block, 18115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // we will never reach this point; instead, read the standard error asynchronously. 18215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek throw new Exception(process.StandardError.ReadToEnd()); 18315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 18415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return output; 18515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 18615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 18715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// <summary> 18815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// Returns the currently active view if it is a IWpfTextView. 18915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek /// </summary> 19015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private IWpfTextView GetCurrentView() 19115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 19215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // The SVsTextManager is a service through which we can get the active view. 19315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager)); 19415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek IVsTextView textView; 19515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek textManager.GetActiveView(1, null, out textView); 19615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 19715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // Now we have the active view as IVsTextView, but the text interfaces we need 19815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek // are in the IWpfTextView. 19915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var userData = (IVsUserData)textView; 20015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (userData == null) 20115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return null; 20215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek Guid guidWpfViewHost = DefGuidList.guidIWpfTextViewHost; 20315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek object host; 20415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek userData.GetData(ref guidWpfViewHost, out host); 20515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return ((IWpfTextViewHost)host).TextView; 20615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 20715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 20815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private string GetStyle() 20915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 21015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 21115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return page.Style; 21215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 21315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek 21415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek private string GetDocumentParent(IWpfTextView view) 21515852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 21615852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek ITextDocument document; 21715852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek if (view.TextBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document)) 21815852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek { 21915852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return Directory.GetParent(document.FilePath).ToString(); 22015852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 22115852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek return null; 22215852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 22315852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek } 22415852fc162eb6f77c28b67c868fdeeffed8c57d4Manuel Klimek} 225