Skip to content

Commit d379368

Browse files
tommckjesperbjensen
authored andcommitted
Adding Format On Save Option (#6) (#24)
1 parent 933b58d commit d379368

File tree

7 files changed

+133
-6
lines changed

7 files changed

+133
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ download in the
1515
These are the changes to each version that has been released
1616
on the official Visual Studio extension gallery.
1717

18+
## 2.1
19+
- [x] Ability to use a locally installed prettier version before using internal version
20+
- [x] New "Format On Save" option in Tools->Options->Prettier
21+
1822
## 2.0
1923
- [x] Updated to prettier@1.12.1
2024
- [x] Ability to read and use the [prettier configuration](https://prettier.io/docs/en/configuration.html) specified in your project

src/Commands/CommandRegistration.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public void VsTextViewCreated(IVsTextView textViewAdapter)
3434
ITextBufferUndoManager undoManager = UndoProvider.GetTextBufferUndoManager(view.TextBuffer);
3535
NodeProcess node = view.Properties.GetOrCreateSingletonProperty(() => new NodeProcess());
3636

37-
AddCommandFilter(textViewAdapter, new PrettierCommand(view, undoManager, node, doc.Encoding, doc.FilePath));
37+
var cmd = new PrettierCommand(view, undoManager, node, doc.Encoding, doc.FilePath);
38+
view.Properties.AddProperty("prettierCommand", cmd);
39+
40+
AddCommandFilter(textViewAdapter, cmd);
3841

3942
if (!node.IsReadyToExecute())
4043
{

src/Commands/PrettierCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public override int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt,
4848
return Next.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
4949
}
5050

51-
private async Task<bool> MakePrettierAsync()
51+
public async Task<bool> MakePrettierAsync()
5252
{
5353
string input = _view.TextBuffer.CurrentSnapshot.GetText();
5454
string output = await _node.ExecuteProcessAsync(input, _encoding, _filePath);

src/JavaScriptPrettier.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<StartArguments>/rootsuffix Exp</StartArguments>
1111
<NuGetPackageImportStamp>
1212
</NuGetPackageImportStamp>
13+
<TargetFrameworkProfile />
1314
</PropertyGroup>
1415
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1516
<PropertyGroup>
@@ -22,7 +23,7 @@
2223
<AppDesignerFolder>Properties</AppDesignerFolder>
2324
<RootNamespace>JavaScriptPrettier</RootNamespace>
2425
<AssemblyName>JavaScriptPrettier</AssemblyName>
25-
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
26+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
2627
<GeneratePkgDefFile>true</GeneratePkgDefFile>
2728
<IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>
2829
<IncludeDebugSymbolsInVSIXContainer>true</IncludeDebugSymbolsInVSIXContainer>
@@ -38,6 +39,7 @@
3839
<DefineConstants>DEBUG;TRACE</DefineConstants>
3940
<ErrorReport>prompt</ErrorReport>
4041
<WarningLevel>4</WarningLevel>
42+
<LangVersion>7.2</LangVersion>
4143
</PropertyGroup>
4244
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
4345
<DebugType>pdbonly</DebugType>
@@ -46,6 +48,7 @@
4648
<DefineConstants>TRACE</DefineConstants>
4749
<ErrorReport>prompt</ErrorReport>
4850
<WarningLevel>4</WarningLevel>
51+
<LangVersion>7.2</LangVersion>
4952
</PropertyGroup>
5053
<ItemGroup>
5154
<Compile Include="Commands\BaseCommand.cs" />
@@ -55,6 +58,7 @@
5558
<Compile Include="NodeProcess.cs" />
5659
<Compile Include="PrettierPackage.cs" />
5760
<Compile Include="Properties\AssemblyInfo.cs" />
61+
<Compile Include="RunningDocTableEventsHandler.cs" />
5862
<Compile Include="source.extension.cs">
5963
<DependentUpon>source.extension.vsixmanifest</DependentUpon>
6064
</Compile>
@@ -99,6 +103,7 @@
99103
<EmbedInteropTypes>False</EmbedInteropTypes>
100104
<Private>False</Private>
101105
</Reference>
106+
<Reference Include="Microsoft.VisualStudio.ComponentModelHost, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
102107
<Reference Include="Microsoft.VisualStudio.CoreUtility, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
103108
<HintPath>..\packages\Microsoft.VisualStudio.CoreUtility.14.3.25407\lib\net45\Microsoft.VisualStudio.CoreUtility.dll</HintPath>
104109
<Private>False</Private>

src/PrettierPackage.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
1-
using Microsoft.VisualStudio.Shell;
1+
using EnvDTE80;
2+
using Microsoft.VisualStudio;
3+
using Microsoft.VisualStudio.Shell;
4+
using Microsoft.VisualStudio.Threading;
25
using System;
6+
using System.ComponentModel;
37
using System.Runtime.InteropServices;
8+
using System.Threading;
9+
using IServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
410

511
namespace JavaScriptPrettier
612
{
713
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
814
[InstalledProductRegistration("#110", "#112", Vsix.Version, IconResourceID = 400)]
915
[Guid(PackageGuids.guidPrettierPackageString)]
1016
[ProvideMenuResource("Menus.ctmenu", 1)]
17+
[ProvideOptionPage(typeof(OptionPageGrid), "Prettier", "General", 0, 0, true)]
18+
[ProvideAutoLoad(cmdUiContextGuid: VSConstants.UICONTEXT.NotBuildingAndNotDebugging_string, flags: PackageAutoLoadFlags.BackgroundLoad)]
1119
public sealed class PrettierPackage : AsyncPackage
1220
{
21+
internal DTE2 _dte;
22+
internal RunningDocumentTable _runningDocTable;
23+
internal OptionPageGrid optionPage;
24+
internal ServiceProvider _serviceProvider;
1325

26+
protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
27+
{
28+
await JoinableTaskFactory.SwitchToMainThreadAsync();
29+
30+
_dte = ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE.DTE)) as DTE2;
31+
_serviceProvider = new ServiceProvider((IServiceProvider)_dte);
32+
_runningDocTable = new RunningDocumentTable(_serviceProvider);
33+
_runningDocTable.Advise(new RunningDocTableEventsHandler(this));
34+
35+
optionPage = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
36+
37+
await base.InitializeAsync(cancellationToken, progress);
38+
}
39+
}
40+
41+
public class OptionPageGrid : DialogPage
42+
{
43+
[Category("Prettier")]
44+
[DisplayName("Format On Save")]
45+
[Description("Run Pretter whenever a file is saved")]
46+
public bool FormatOnSave { get; set; }
1447
}
1548
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.Linq;
3+
using EnvDTE;
4+
using Microsoft.VisualStudio;
5+
using Microsoft.VisualStudio.Shell;
6+
using Microsoft.VisualStudio.Shell.Interop;
7+
using Microsoft.VisualStudio.Text.Editor;
8+
using Microsoft.VisualStudio.TextManager.Interop;
9+
10+
namespace JavaScriptPrettier
11+
{
12+
internal sealed class RunningDocTableEventsHandler : IVsRunningDocTableEvents3
13+
{
14+
private readonly PrettierPackage _package;
15+
16+
public RunningDocTableEventsHandler(PrettierPackage package)
17+
{
18+
_package = package;
19+
}
20+
21+
public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => VSConstants.S_OK;
22+
public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => VSConstants.S_OK;
23+
public int OnAfterSave(uint docCookie) => VSConstants.S_OK;
24+
public int OnAfterAttributeChange(uint docCookie, uint grfAttribs) => VSConstants.S_OK;
25+
public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame) => VSConstants.S_OK;
26+
public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame) => VSConstants.S_OK;
27+
public int OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew) => VSConstants.S_OK;
28+
29+
public int OnBeforeSave(uint docCookie)
30+
{
31+
if (_package.optionPage.FormatOnSave)
32+
{
33+
RunningDocumentInfo docInfo = _package._runningDocTable.GetDocumentInfo(docCookie);
34+
Document doc = _package._dte.Documents.OfType<Document>().SingleOrDefault(x => x.FullName == docInfo.Moniker);
35+
36+
if (doc != null)
37+
{
38+
IVsTextView vsTextView = GetIVsTextView(doc.FullName);
39+
if (vsTextView == null)
40+
{
41+
return VSConstants.S_OK;
42+
}
43+
44+
IWpfTextView wpfTextView = GetWpfTextView(vsTextView);
45+
if (wpfTextView == null)
46+
{
47+
return VSConstants.S_OK;
48+
}
49+
50+
PrettierCommand cmd = wpfTextView.Properties.GetProperty<PrettierCommand>("prettierCommand");
51+
if (cmd != null)
52+
{
53+
ThreadHelper.JoinableTaskFactory.Run(() => cmd.MakePrettierAsync());
54+
}
55+
}
56+
}
57+
return VSConstants.S_OK;
58+
}
59+
60+
private IVsTextView GetIVsTextView(string filePath)
61+
{
62+
return VsShellUtilities.IsDocumentOpen(_package._serviceProvider, filePath, Guid.Empty, out var uiHierarchy, out uint itemId, out var windowFrame)
63+
? VsShellUtilities.GetTextView(windowFrame) : null;
64+
}
65+
66+
private static IWpfTextView GetWpfTextView(IVsTextView vTextView)
67+
{
68+
IWpfTextView view = null;
69+
IVsUserData userData = (IVsUserData)vTextView;
70+
71+
if (userData != null)
72+
{
73+
Guid guidViewHost = Microsoft.VisualStudio.Editor.DefGuidList.guidIWpfTextViewHost;
74+
userData.GetData(ref guidViewHost, out var holder);
75+
IWpfTextViewHost viewHost = (IWpfTextViewHost)holder;
76+
view = viewHost.TextView;
77+
}
78+
79+
return view;
80+
}
81+
}
82+
}

src/source.extension.vsixmanifest

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
33
<Metadata>
4-
<Identity Id="J1da7ad9e-85b3-4a0c-8e45-b2ae59a575a7" Version="2.0" Language="en-US" Publisher="Mads Kristensen" />
4+
<Identity Id="J1da7ad9e-85b3-4a0c-8e45-b2ae59a575a7" Version="2.1" Language="en-US" Publisher="Mads Kristensen" />
55
<DisplayName>JavaScript Prettier</DisplayName>
66
<Description xml:space="preserve">Prettier is an opinionated JavaScript formatter inspired by refmt with advanced support for language features from ES2017, JSX, and Flow. It removes all original styling and ensures that all outputted JavaScript conforms to a consistent style.</Description>
77
<MoreInfo>https://github.com/madskristensen/JavaScriptPrettier</MoreInfo>
88
<License>Resources\LICENSE</License>
99
<ReleaseNotes>https://github.com/madskristensen/JavaScriptPrettier/blob/master/CHANGELOG.md</ReleaseNotes>
1010
<Icon>Resources\Icon.png</Icon>
1111
<PreviewImage>Resources\Icon.png</PreviewImage>
12-
<Tags>JavaScript, JSX, EcmaScript, formatting</Tags>
12+
<Tags>JavaScript, JSX, TypeScript, TSX, EcmaScript, formatting</Tags>
1313
</Metadata>
1414
<Installation>
1515
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[14.0,17.0)" />

0 commit comments

Comments
 (0)